mcp-ts-template

mcp-ts-template

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.

Stars: 69

Visit
 screenshot

The MCP TypeScript Server Template is a production-grade framework for building powerful and scalable Model Context Protocol servers with TypeScript. It features built-in observability, declarative tooling, robust error handling, and a modular, DI-driven architecture. The template is designed to be AI-agent-friendly, providing detailed rules and guidance for developers to adhere to best practices. It enforces architectural principles like 'Logic Throws, Handler Catches' pattern, full-stack observability, declarative components, and dependency injection for decoupling. The project structure includes directories for configuration, container setup, server resources, services, storage, utilities, tests, and more. Configuration is done via environment variables, and key scripts are available for development, testing, and publishing to the MCP Registry.

README:


MCP Logo

Model Context Protocol (MCP) TypeScript Server Template

The definitive, production-grade template for building powerful and scalable Model Context Protocol servers with TypeScript, featuring built-in observability (OpenTelemetry), declarative tooling, robust error handling, and a modular, DI-driven architecture.

Version MCP Spec License Status TypeScript Bun Code Coverage


mcp-ts-template is more than just a template; it's a feature-rich, production-ready framework for building robust, observable, and secure MCP servers, providing a solid architectural foundation so you can focus entirely on creating powerful tools and resources for AI agents.

This project is designed to be AI-agent-friendly, providing an LLM-optimized AGENTS.md and detailed rules in .clinerules/clinerules.md to ensure your coding agents adhere to best practices from the start.

โœจ Core Features

This template is packed with production-grade features designed for high-performance, secure, and maintainable MCP servers.

Feature Description
Declarative Tooling Define tools in a single, self-contained file (*.tool.ts). The framework handles registration, validation, error handling, and performance metrics automatically.
Full Observability Zero-configuration OpenTelemetry integration. Get distributed traces and metrics out-of-the-box for all your tools and underlying dependencies (HTTP, DNS).
Pluggable Auth Built-in authentication middleware supporting JWT and OAuth 2.1. Easily toggle auth modes or extend with new strategies via the AuthStrategy interface.
Stateful & Stateless Transports Choose between stdio or HTTP transports. The HTTP transport supports both persistent, stateful sessions and ephemeral, stateless requests intelligently.
Robust Error Handling A centralized ErrorHandler maps all exceptions to standardized JsonRpcErrorCodes and automatically correlates them with OpenTelemetry traces for easy debugging.
Type-Safe & Validated Zod is used everywhere for rigorous schema validation of configuration, tool inputs/outputs, and API boundaries, preventing invalid data at the source.
Abstracted Storage Layer A flexible, provider-based storage service (IStorageProvider) with ready-to-use backends for In-Memory, Filesystem, and Supabase.
Comprehensive Utilities A rich set of internal utilities for logging (Winston), rate-limiting, security sanitization, ID generation, cron scheduling, and network requests.
Integration-First Testing Pre-configured with Vitest and msw for writing meaningful integration tests that reflect real-world usage, ensuring reliability from end to end.
Agent-Ready Design Includes detailed guidance in AGENTS.md and .clinerules/ to direct developer LLM agents, ensuring they adhere to the project's architectural standards.

๐Ÿš€ Getting Started

Prerequisites

  • Bun (v1.2.0 or higher)

Installation

  1. Clone the Repository

    git clone https://github.com/cyanheads/mcp-ts-template.git
    cd mcp-ts-template
  2. Install Dependencies

    bun install
  3. Build the Project

    bun build # or bun rebuild

๐Ÿƒ Running the Server

You can run the server in several modes for development and production.

Standard Transports

  • STDIO Transport: Ideal for local development or when the server is a child process.
    bun run start:stdio
  • HTTP Transport: For network-accessible deployments.
    bun run start:http
    # Server now running at http://127.0.0.1:3010

๐Ÿ—๏ธ Architectural Principles

This template enforces a set of non-negotiable architectural principles to ensure every server built from it is robust, maintainable, and debuggable.

1. The "Logic Throws, Handler Catches" Pattern

This is the cornerstone of control flow and error handling. It creates a complete separation between pure business logic and the surrounding infrastructure concerns.

  • Core Logic (logic): Defined within your ToolDefinition, this is a pure, stateless async function. It contains only the business logic for the tool. If an operational or validation error occurs, it must terminate by throwing a structured McpError. It never contains a try...catch block.
  • Handler (Auto-Generated): The toolHandlerFactory automatically wraps your logic function in a robust try...catch block at runtime. This factory-generated handler is responsible for creating the RequestContext, measuring performance with OpenTelemetry, invoking your logic, and catching any thrown errors. It is the only place where errors are caught and formatted into a final CallToolResult.

This pattern allows you to write clean, focused business logic while the framework guarantees it's executed within a fully instrumented, safe, and observable context.

2. Full-Stack Observability by Default

Every operation is traceable from end to end without any manual setup.

  • OpenTelemetry SDK: Initialized in src/utils/telemetry/instrumentation.ts before any other module, it automatically instruments supported I/O operations (HTTP, DNS, etc.).
  • Trace-Aware Context: The requestContextService automatically injects the active traceId and spanId into every RequestContext.
  • Error-Trace Correlation: The central ErrorHandler records every handled exception on the active OTel span and sets its status to ERROR, ensuring every failure is visible and searchable in your tracing backend.
  • Performance Spans: The measureToolExecution utility wraps every tool call in a dedicated span, capturing duration, status, and input/output sizes as attributes.

3. Declarative, Self-Contained Components

Tools and resources are defined declaratively in single, self-contained files. This makes the system highly modular and easy to reason about.

4. Dependency Injection for Maximum Decoupling

The entire architecture is built around a Dependency Injection (DI) container (tsyringe).

  • Centralized Container: All services, providers, and managers are registered in a central DI container, configured in src/container/.
  • Inversion of Control: Components never create their own dependencies. Instead, they receive them via constructor injection, making them highly testable and decoupled.
  • Auto-Registration: Tool and resource definitions are automatically discovered and registered with the container from barrel exports, eliminating manual wiring.

๐Ÿ“ Project Structure

.
โ”œโ”€โ”€ .clinerules/         # --> Rules and mandates for LLM-based development agents.
โ”œโ”€โ”€ .github/             # --> GitHub Actions workflows (e.g., CI/CD).
โ”œโ”€โ”€ scripts/             # --> Helper scripts for development (cleaning, docs, etc.).
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ config/          # --> Application configuration (Zod schemas, loader).
โ”‚   โ”œโ”€โ”€ container/       # --> Dependency Injection container setup and registrations.
โ”‚   โ”œโ”€โ”€ mcp-server/
โ”‚   โ”‚   โ”œโ”€โ”€ resources/   # --> Declarative resource definitions (*.resource.ts).
โ”‚   โ”‚   โ”œโ”€โ”€ tools/       # --> Declarative tool definitions (*.tool.ts).
โ”‚   โ”‚   โ”œโ”€โ”€ transports/  # --> HTTP and STDIO transport layers, including auth.
โ”‚   โ”‚   โ””โ”€โ”€ server.ts    # --> Core McpServer setup (resolves components from DI).
โ”‚   โ”œโ”€โ”€ services/        # --> Clients for external services (e.g., LLM providers).
โ”‚   โ”œโ”€โ”€ storage/         # --> Abstracted storage layer and providers.
โ”‚   โ”œโ”€โ”€ types-global/    # --> Global TypeScript types (e.g., McpError).
โ”‚   โ””โ”€โ”€ utils/           # --> Core utilities (logger, error handler, security).
โ”œโ”€โ”€ tests/               # --> Vitest integration and unit tests.
โ”œโ”€โ”€ .env.example         # --> Example environment variables.
โ”œโ”€โ”€ AGENTS.md            # --> Detailed architectural guide for LLM agents.
โ””โ”€โ”€ Dockerfile           # --> For building and running the server in a container.

๐Ÿ”ง Extending the Template

Adding a New Tool

  1. Create the Definition: Create a new file at src/mcp-server/tools/definitions/my-new-tool.tool.ts. Use an existing tool as a template.
  2. Define the Tool: Export a single const of type ToolDefinition containing the name, Zod schemas, and pure business logic.
  3. Register via Barrel Export: Open src/mcp-server/tools/definitions/index.ts and add your new tool definition to the allToolDefinitions array.
// src/mcp-server/tools/definitions/index.ts
import { myNewTool } from './my-new-tool.tool.js';
// ... other imports
export const allToolDefinitions = [
  // ... other tools
  myNewTool,
];

That's it. The DI container automatically discovers and registers all tools from this array at startup.

Adding a New Storage Provider

  1. Create Provider: Create a new class under src/storage/providers/ that implements the IStorageProvider interface.
  2. Add to Factory: Open src/storage/core/storageFactory.ts. Add a case to the switch statement to instantiate your new provider based on the STORAGE_PROVIDER_TYPE from the config.
  3. Update Config Schema: Add your new provider's name to the StorageProviderType enum in src/config/index.ts.
  4. Set Environment Variable: In your .env file, set STORAGE_PROVIDER_TYPE to your new provider's name.

โš™๏ธ Configuration

The server is configured via environment variables, loaded and validated by src/config/index.ts. Copy .env.example to .env and fill in the required values.

Variable Description Default
MCP_TRANSPORT_TYPE Transport to use: stdio or http. http
MCP_SESSION_MODE HTTP session mode: stateless, stateful, or auto. auto
MCP_AUTH_MODE Authentication mode: none, jwt, or oauth. none
MCP_LOG_LEVEL Minimum log level: debug, info, warning, error, etc. debug
LOGS_DIR Directory for log files. logs/
STORAGE_PROVIDER_TYPE Storage backend: in-memory, filesystem, supabase. filesystem
STORAGE_FILESYSTEM_PATH Path for the filesystem storage provider. ./.storage
OPENROUTER_API_KEY API key for the OpenRouter LLM service.
OTEL_ENABLED Set to true to enable OpenTelemetry. false
MCP_AUTH_SECRET_KEY Secret key for signing JWTs (required for jwt auth mode).
SUPABASE_URL URL for your Supabase project.
SUPABASE_SERVICE_ROLE_KEY Service role key for Supabase admin tasks.

Refer to .env.example for a complete list of configurable options.

๐Ÿ“œ Available Scripts

Key scripts available in package.json:

Script Description
bun run devdocs Generates a comprehensive development documentation prompt for AI analysis.
bun run rebuild Clears logs, cache, and compiles the TypeScript source code to JavaScript in dist/.
bun run start:http Starts the compiled server using the HTTP transport.
bun run start:stdio Starts the compiled server using the STDIO transport.
bun run test Runs all unit and integration tests with Vitest.
bun run test:coverage Runs all tests and generates a code coverage report.
bun run devcheck A comprehensive script that runs linting, type-checking, and formatting.
bun run publish-mcp (Recommended) An all-in-one script to sync, validate, commit, and publish your server to the MCP Registry.

You can find these scripts in the scripts/ directory.


๐Ÿ“ฆ Publishing to the MCP Registry

This template is configured for easy publishing to the public MCP Registry, making your server discoverable by any MCP-compatible client. The recommended method is to use the all-in-one publishing script.

For a complete walkthrough, including alternative methods and CI/CD automation, please refer to the detailed guide:

โžก๏ธ How to Publish Your MCP Server

The Easy Way: All-in-One Publish Script

This template includes a powerful script that automates the entire publishing workflowโ€”from syncing versions and validating schemas to committing changes and publishing.

  1. Ensure you are on the main branch with no uncommitted changes.
  2. Run the script:
    bun run publish-mcp

The script will guide you through the process, including pausing for you to complete the GitHub browser login.

Script Flags for More Control

The script also supports flags for more granular control:

  • --validate-only: Syncs metadata, validates server.json, then stops.
  • --no-commit: Skips the automatic Git commit step.
  • --publish-only: Skips local file changes and proceeds directly to publishing.

Example:

bun run publish-mcp --validate-only

This template also includes a GitHub Actions workflow (.github/workflows/publish-mcp.yml) that can be configured to automate this process whenever you push a new Git tag.

๐Ÿค Contributing

This is an open-source project. Contributions, issues, and feature requests are welcome. Please feel free to fork the repository, make changes, and open a pull request.

๐Ÿ“„ License

This project is licensed under the Apache 2.0 License. See the LICENSE file for details.

For Tasks:

Click tags to check more tools for each tasks

For Jobs:

Alternative AI tools for mcp-ts-template

Similar Open Source Tools

For similar tasks

For similar jobs