Build production-grade Model Context Protocol (MCP) servers with a powerful, type-safe, and extensible foundation.
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.
Developing a reliable server for AI agents requires a thoughtful approach to architecture, error handling, and security. This template provides a starting point to help you:
- Focus on Innovation: Move past the setup and boilerplate. Spend your time building the unique logic for your tools.
- Build with Confidence: Start with a foundation that includes logging, error handling, security features, and a testing framework.
- Write Maintainable Code: The modular architecture is designed to be easy to understand, maintain, and extend as your project grows.
- Create for AI: With detailed schemas and developer resources (like
.clinerules
), the template is set up for building tools that LLM agents can easily understand and use.
Note on src/mcp-client & src/agent: The MCP client & Agent components have been enhanced and moved to the (coming soon)atlas-mcp-agent repository. This template now focuses exclusively on providing a best-in-class server implementation and framework.
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. |
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 (JsonRpcErrorCode ), 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 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/ |
πΎ Storage Service | A flexible, provider-based storage layer for persisting data. Supports in-memory, filesystem, and Supabase backends out-of-the-box. | src/storage/ |
π§© Services | Reusable modules for LLM (OpenRouter) integration. | src/services/ |
π§ͺ 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 |
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, using theMcpServer
class directly from the SDK. - Transports (
src/mcp-server/transports/
): The transport layer connects the core server to the outside world. It supports bothstdio
for direct process communication and a streamable Hono-basedhttp
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 structuredMcpError
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.
- Core Logic (
- 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.
Clone the repository and install dependencies:
git clone https://github.com/cyanheads/mcp-ts-template.git
cd mcp-ts-template
npm install
npm run build
# Or use 'npm run rebuild' for a clean install
- Via Stdio (Default):
npm run start:server
- Via Streamable HTTP:
npm run start:server:http
This template uses Vitest for testing, with a strong emphasis on integration testing to ensure all components work together correctly.
- Run all tests once:
npm test
- Run tests in watch mode:
npm run test:watch
- Run tests and generate a coverage report:
npm run test:coverage
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) |
STORAGE_PROVIDER_TYPE |
The storage backend to use: in-memory , filesystem , or supabase . |
filesystem |
STORAGE_FILESYSTEM_PATH |
Required for filesystem mode. The local path for storing data. |
./.storage |
SUPABASE_URL |
Required for supabase mode. The URL of your Supabase project. |
(none) |
SUPABASE_SERVICE_ROLE_KEY |
Required for supabase mode. The service role key for your Supabase project. |
(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) |
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 (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 or generate it dynamically:
npm run tree
The template enforces a strict, modular pattern for adding new tools and resources, as mandated by the Architectural Standard. The echoTool
(src/mcp-server/tools/echoTool/
) serves as the canonical example.
This is the cornerstone of the architecture:
-
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.
-
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 theErrorHandler
, and formatted into a standardized error response.
- It imports the schemas and logic function from
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.
Looking for more examples, guides, and pre-built MCP servers? Check out the companion repository:
β‘οΈ cyanheads/model-context-protocol-resources
This project is licensed under the Apache License 2.0. See the LICENSE file for details.