mcp-ts-template
Version:
A production-grade TypeScript template for building robust Model Context Protocol (MCP) servers, featuring built-in observability with OpenTelemetry, advanced error handling, comprehensive utilities, and a modular architecture.
172 lines (126 loc) โข 13.4 kB
Markdown
<div align="center">
# mcp-ts-template
**Build production-grade Model Context Protocol (MCP) servers with a powerful, type-safe, and extensible foundation.**
[](https://www.typescriptlang.org/)
[](https://github.com/modelcontextprotocol/typescript-sdk)
[](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-06-18/changelog.mdx)
[](./CHANGELOG.md)
[](./vitest.config.ts)
[](https://opensource.org/licenses/Apache-2.0)
[](https://github.com/cyanheads/mcp-ts-template/issues)
[](https://github.com/cyanheads/mcp-ts-template)
</div>
This template provides a comprehensive foundation for building rich Model Context Protocol servers, adhering to the **MCP 2025-06-18 specification** and modern best practices. It includes a fully-featured server, production-ready utilities, and clear documentation to get you up and running quickly.
## ๐ค Why Use This Template?
Building a robust server for AI agents is more than just writing code. It requires a solid architecture, consistent error handling, and secure, type-safe practices from the ground up. This template solves these challenges by providing:
- **Accelerated Development**: Skip the boilerplate and focus on your tool's core logic.
- **Production-Ready Foundation**: Built-in logging, error handling, security, and testing.
- **Best Practices by Default**: Enforces a clean, modular architecture that's easy to maintain and extend.
- **AI-Ready**: Designed with LLM agents in mind, including detailed schemas and rich LLM developer-friendly resources (e.g. .clinerules).
> **Note on src/mcp-client & src/agent:** The MCP client & Agent components have been enhanced and moved to the [**atlas-mcp-agent**](https://github.com/cyanheads/atlas-mcp-agent) repository. This template now focuses exclusively on providing a best-in-class server implementation and framework.
## โจ Key Features
| Feature Area | Description | Key Components / Location |
| :-------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------- |
| **๐ MCP Server** | A functional server with example tools and resources. Supports `stdio` and a **Streamable HTTP** transport built with [**Hono**](https://hono.dev/). | `src/mcp-server/`, `src/mcp-server/transports/` |
| **๐ญ Observability** | Built-in **OpenTelemetry** for distributed tracing and metrics. Auto-instrumentation for core modules and custom tracing for all tool executions. | `src/utils/telemetry/` |
| **๐ Production Utilities** | Logging, Error Handling, ID Generation, Rate Limiting, Request Context tracking, Input Sanitization. | `src/utils/` |
| **๐ Type Safety/Security** | Strong type checking via TypeScript & Zod validation. Built-in security utilities (sanitization, auth middleware for HTTP). | Throughout, `src/utils/security/`, `src/mcp-server/transports/auth/` |
| **โ๏ธ Error Handling** | Consistent error categorization (`BaseErrorCode`), detailed logging, centralized handling (`ErrorHandler`). | `src/utils/internal/errorHandler.ts`, `src/types-global/` |
| **๐ Documentation** | Comprehensive `README.md`, structured JSDoc comments, API references. | `README.md`, Codebase, `tsdoc.json`, `docs/api-references/` |
| **๐ต๏ธ Interaction Logging** | Captures raw requests and responses for all external LLM provider interactions to a dedicated `interactions.log` file for full traceability. | `src/utils/internal/logger.ts` |
| **๐ค Agent Ready** | Includes a [.clinerules](./.clinerules/clinerules.md) developer cheatsheet tailored for LLM coding agents. | `.clinerules/` |
| **๐ ๏ธ Utility Scripts** | Scripts for cleaning builds, setting executable permissions, generating directory trees, and fetching OpenAPI specs. | `scripts/` |
| **๐งฉ Services** | Reusable modules for LLM (OpenRouter) and data storage (DuckDB) integration, with examples. | `src/services/`, `src/storage/duckdbExample.ts` |
| **๐งช Integration Testing** | Integrated with Vitest for fast and reliable integration testing. Includes example tests for core logic and a coverage reporter. | `vitest.config.ts`, `tests/` |
| **โฑ๏ธ Performance Metrics** | Built-in utility to automatically measure and log the execution time and payload size of every tool call. | `src/utils/internal/performance.ts` |
## Architecture Overview
This template is built on a set of architectural principles to ensure modularity, testability, and operational clarity.
- **Core Server (`src/mcp-server/server.ts`)**: The central point where tools and resources are registered. It uses a `ManagedMcpServer` wrapper to provide enhanced introspection capabilities. It acts the same way as the native McpServer, but with additional features like introspection and enhanced error handling.
- **Transports (`src/mcp-server/transports/`)**: The transport layer connects the core server to the outside world. It supports both `stdio` for direct process communication and a streamable **Hono**-based `http` server.
- **"Logic Throws, Handler Catches"**: This is the immutable cornerstone of our error-handling strategy.
- **Core Logic (`logic.ts`)**: This layer is responsible for pure, self-contained business logic. It **throws** a structured `McpError` on any failure.
- **Handlers (`registration.ts`)**: This layer interfaces with the server, invokes the core logic, and **catches** any errors. It is the exclusive location where errors are processed and formatted into a final response.
- **Structured, Traceable Operations**: Every operation is traced from initiation to completion via a `RequestContext` that is passed through the entire call stack, ensuring comprehensive and structured logging.
## Quick Start
### 1. Installation
Clone the repository and install dependencies:
```bash
git clone https://github.com/cyanheads/mcp-ts-template.git
cd mcp-ts-template
npm install
```
### 2. Build the Project
```bash
npm run build
# Or use 'npm run rebuild' for a clean install
```
### 3. Running the Server
- **Via Stdio (Default):**
```bash
npm run start:server
```
- **Via Streamable HTTP:**
```bash
npm run start:server:http
```
### 4. Running Tests
This template uses [Vitest](https://vitest.dev/) for testing, with a strong emphasis on **integration testing** to ensure all components work together correctly.
- **Run all tests once:**
```bash
npm test
```
- **Run tests in watch mode:**
```bash
npm run test:watch
```
- **Run tests and generate a coverage report:**
```bash
npm run test:coverage
```
## โ๏ธ Configuration
Configure the server using these environment variables (or a `.env` file):
| Variable | Description | Default |
| :-------------------- | :---------------------------------------------------------------------------------------- | :------------------------------------- |
| `MCP_TRANSPORT_TYPE` | Server transport: `stdio` or `http`. | `stdio` |
| `MCP_SESSION_MODE` | Session mode for HTTP: `stateless`, `stateful`, or `auto`. | `auto` |
| `MCP_HTTP_PORT` | Port for the HTTP server. | `3010` |
| `MCP_HTTP_HOST` | Host address for the HTTP server. | `127.0.0.1` |
| `MCP_ALLOWED_ORIGINS` | Comma-separated allowed origins for CORS. | (none) |
| `MCP_AUTH_MODE` | Authentication mode for HTTP: `jwt`, `oauth`, or `none`. | `none` |
| `MCP_AUTH_SECRET_KEY` | **Required for `jwt` mode.** Secret key (min 32 chars) for signing/verifying auth tokens. | (none - **MUST be set in production**) |
| `OAUTH_ISSUER_URL` | **Required for `oauth` mode.** The issuer URL of your authorization server. | (none) |
| `OAUTH_AUDIENCE` | **Required for `oauth` mode.** The audience identifier for this MCP server. | (none) |
| `OPENROUTER_API_KEY` | API key for OpenRouter.ai service. | (none) |
| `OTEL_ENABLED` | Set to `true` to enable OpenTelemetry instrumentation. | `false` |
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | The OTLP endpoint for exporting traces (e.g., `http://localhost:4318/v1/traces`). | (none; logs to file) |
| `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | The OTLP endpoint for exporting metrics (e.g., `http://localhost:4318/v1/metrics`). | (none) |
## ๐๏ธ Project Structure
- **`src/mcp-server/`**: Contains the core MCP server, tools, resources, and transport handlers.
- **`src/config/`**: Handles loading and validation of environment variables.
- **`src/services/`**: Reusable modules for integrating with external services (DuckDB, OpenRouter).
- **`src/types-global/`**: Defines shared TypeScript interfaces and type definitions.
- **`src/utils/`**: Core utilities (logging, error handling, security, etc.).
- **`src/index.ts`**: The main entry point that initializes and starts the server.
**Explore the full structure yourself:**
See the current file tree in [docs/tree.md](docs/tree.md) or generate it dynamically:
```bash
npm run tree
```
## ๐งฉ Extending the System
The template enforces a strict, modular pattern for adding new tools and resources, as mandated by the [Architectural Standard](./.clinerules/clinerules.md). The `echoTool` (`src/mcp-server/tools/echoTool/`) serves as the canonical example.
### The "Logic Throws, Handler Catches" Pattern
This is the cornerstone of the architecture:
1. **`logic.ts`**: This file contains the pure business logic.
- It defines the Zod schemas for input and output, which serve as the single source of truth for the tool's data contract.
- The core logic function is pure: it takes validated parameters and a request context, and either returns a result or **throws** a structured `McpError`.
- It **never** contains `try...catch` blocks for formatting a final response.
2. **`registration.ts`**: This file is the "handler" that connects the logic to the MCP server.
- It imports the schemas and logic function from `logic.ts`.
- It calls `server.registerTool()`, providing the tool's metadata and the runtime handler.
- The runtime handler **always** wraps the call to the logic function in a `try...catch` block. This is the **only** place where errors are caught, processed by the `ErrorHandler`, and formatted into a standardized error response.
This pattern ensures that core logic remains decoupled, pure, and easily testable, while the registration layer handles all transport-level concerns, side effects, and response formatting.
## ๐ Explore More MCP Resources
Looking for more examples, guides, and pre-built MCP servers? Check out the companion repository:
โก๏ธ **[cyanheads/model-context-protocol-resources](https://github.com/cyanheads/model-context-protocol-resources)**
## ๐ License
This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for details.