Skip to content

cyanheads/mcp-ts-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

809 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mcp-ts-template

TypeScript template for building Model Context Protocol (MCP) servers. Ships with declarative tools/resources, pluggable auth, multi-backend storage, OpenTelemetry observability, and support for both local and edge (Cloudflare Workers) runtimes.

7 Tools • 2 Resources • 1 Prompt

Version MCP Spec MCP SDK License

Status TypeScript Bun Code Coverage


Try it live — A public demo instance is running at https://mcp-ts-template.caseyjhand.com/mcp. Connect any MCP client to test the template's tools and resources without installing anything.

Features

  • Define tools and resources in single, self-contained files. The framework handles registration.
  • Tools can prompt users for missing parameters mid-execution via elicitation.
  • Unified McpError system for consistent, structured error responses.
  • Auth modes: none, jwt, or oauth. Wrap logic with withToolAuth/withResourceAuth.
  • Swap storage backends (in-memory, filesystem, Supabase, Cloudflare D1/KV/R2) without changing tool logic. Includes cursor pagination, batch ops, and input validation.
  • Structured logging (Pino) with optional OpenTelemetry for tracing and metrics.
  • Custom typed DI container with Token<T> phantom branding. No external deps.
  • Pluggable service integrations: LLM (OpenRouter), TTS (ElevenLabs).
  • Parsing helpers (PDF, YAML, CSV, frontmatter), formatting (diffs, tables, trees, markdown), scheduling, security.
  • Runs on local (stdio/HTTP) and edge (Cloudflare Workers) with the same code.

Architecture

Modular, domain-driven layout with clear separation of concerns:

┌─────────────────────────────────────────────────────────┐
│              MCP Client (Claude Code, ChatGPT, etc.)    │
└────────────────────┬────────────────────────────────────┘
                     │ JSON-RPC 2.0
                     ▼
┌─────────────────────────────────────────────────────────┐
│           MCP Server (Tools, Resources)                 │
│              [MCP Server Guide](src/mcp-server/)         │
└────────────────────┬────────────────────────────────────┘
                     │ Dependency Injection
                     ▼
┌─────────────────────────────────────────────────────────┐
│          Dependency Injection Container                 │
│              [Container Guide](src/container/)           │
└────────────────────┬────────────────────────────────────┘
                     │
        ┌────────────┼────────────┐
        ▼            ▼            ▼
 ┌──────────┐   ┌──────────┐   ┌──────────┐
 │ Services │   │ Storage  │   │ Utilities│
 │    [→]   │   │    [→]   │   │    [→]   │
 └──────────┘   └──────────┘   └──────────┘

[→]: src/services/    [→]: src/storage/    [→]: src/utils/

Key modules:

  • MCP Server — Tools, resources, prompts, and transport layer
  • Container — Typed DI container, no external deps
  • Services — External integrations (LLM, Speech, Graph) with pluggable providers
  • Storage — Persistence layer with multiple backend support
  • Utilities — Logging, security, parsing, telemetry

Included capabilities

This template includes working examples to get you started.

Tools

Tool Description
template_echo_message Echoes a message back with optional formatting and repetition.
template_cat_fact Fetches a random cat fact from an external API.
template_madlibs_elicitation Demonstrates elicitation by asking for words to complete a story.
template_code_review_sampling Uses the LLM service to perform a simulated code review.
template_image_test Returns a test image as a base64-encoded data URI.
template_async_countdown Demonstrates MCP Tasks API with an async countdown timer (experimental).
template_data_explorer Generates sample sales data with an interactive explorer UI (MCP Apps).

Resources

Resource URI Description
echo echo://{message} A simple resource that echoes back a message.
data-explorer-ui ui://template-data-explorer/app.html Interactive HTML app for the data explorer tool (MCP Apps).

Prompts

Prompt Description
code-review A structured prompt for guiding an LLM to perform a code review.

Getting started

MCP client configuration

Add the following to your MCP client configuration file.

{
  "mcpServers": {
    "mcp-ts-template": {
      "type": "stdio",
      "command": "bunx",
      "args": ["mcp-ts-template@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info",
        "STORAGE_PROVIDER_TYPE": "filesystem",
        "STORAGE_FILESYSTEM_PATH": "/path/to/your/storage"
      }
    }
  }
}

Or connect to the public demo server over HTTP — no installation required:

{
  "mcpServers": {
    "mcp-ts-template": {
      "type": "streamable-http",
      "url": "https://mcp-ts-template.caseyjhand.com/mcp"
    }
  }
}

Prerequisites

Installation

  1. Clone the repository:
git clone https://github.com/cyanheads/mcp-ts-template.git
  1. Navigate into the directory:
cd mcp-ts-template
  1. Install dependencies:
bun install

Configuration

All configuration is centralized and validated at startup in src/config/index.ts. Key environment variables in your .env file include:

Variable Description Default
MCP_TRANSPORT_TYPE The transport to use: stdio or http. stdio
MCP_HTTP_PORT The port for the HTTP server. 3010
MCP_HTTP_HOST The hostname for the HTTP server. 127.0.0.1
MCP_LOG_LEVEL Logging level (debug, info, notice, warning, error, crit, alert, emerg). debug
MCP_AUTH_MODE Authentication mode: none, jwt, or oauth. none
MCP_AUTH_SECRET_KEY Required for jwt auth mode. A 32+ character secret. (none)
DEV_MCP_AUTH_BYPASS Set to true to bypass JWT auth in development (requires no secret key). false
OAUTH_ISSUER_URL Required for oauth auth mode. URL of the OIDC provider. (none)
OAUTH_AUDIENCE Required for oauth auth mode. Expected audience claim in the JWT. (none)
STORAGE_PROVIDER_TYPE Storage backend: in-memory, filesystem, supabase, cloudflare-d1, cloudflare-kv, cloudflare-r2. in-memory
STORAGE_FILESYSTEM_PATH Path to the storage directory (for filesystem provider). ./.storage
SUPABASE_URL Required for supabase storage. Your Supabase project URL. (none)
SUPABASE_ANON_KEY Required for supabase storage. Your Supabase anon key. (none)
OTEL_ENABLED Set to true to enable OpenTelemetry. false
OPENROUTER_API_KEY API key for OpenRouter LLM service. (none)

Authentication and authorization

  • Modes: none (default), jwt (requires MCP_AUTH_SECRET_KEY), or oauth (requires OAUTH_ISSUER_URL and OAUTH_AUDIENCE).
  • In development, set DEV_MCP_AUTH_BYPASS=true to skip JWT validation without a secret key. Rejected in production.
  • Wrap tool/resource logic with withToolAuth([...]) or withResourceAuth([...]) for scope checks. Checks are bypassed when auth mode is none.

Storage

  • DI-managed StorageService provides a consistent API for persistence. Never access fs or storage SDKs directly from tool logic.
  • Default provider is in-memory. Node-only: filesystem. Edge-compatible: supabase, cloudflare-kv, cloudflare-r2.
  • StorageService requires context.tenantId, auto-propagated from the JWT tid claim when auth is enabled.
  • Opaque cursor pagination with tenant binding, parallel batch ops (getMany/setMany/deleteMany), TTL support, centralized input validation.

Observability

  • Pino for structured JSON logging. All logs include RequestContext.
  • OpenTelemetry disabled by default. Enable with OTEL_ENABLED=true. HTTP spans via @hono/otel (works on Bun). Tool-call metrics (duration, payload sizes, errors) captured automatically. Pino logs correlate to traces via trace_id/span_id.

Running the server

Local development

  • Build and run the production version:

    # One-time build
    bun run rebuild
    
    # Run the built server
    bun run start:http
    # or
    bun run start:stdio
  • Run checks and tests:

    bun run devcheck # Lints, formats, type-checks, and more
    bun run test # Runs the test suite (Do not use 'bun test' directly as it may not work correctly)

Cloudflare workers

  1. Build the Worker bundle:
bun run build:worker
  1. Run locally with Wrangler:
bun run deploy:dev
  1. Deploy to Cloudflare:
bun run deploy:prod

Note: The wrangler.toml file is pre-configured to enable nodejs_compat for best results.

Project structure

Directory Purpose & Contents Guide
src/mcp-server/tools/definitions Tool definitions (*.tool.ts). Add new capabilities here. MCP Guide
src/mcp-server/resources/definitions Resource definitions (*.resource.ts). Add new data sources here. MCP Guide
src/mcp-server/prompts/definitions Prompt definitions (*.prompt.ts). Add new prompt templates here. MCP Guide
src/mcp-server/tasks Async task infrastructure (MCP Tasks API, experimental). MCP Guide
src/mcp-server/transports HTTP and STDIO transports, including auth middleware. MCP Guide
src/storage StorageService abstraction and provider implementations. Storage Guide
src/services External service integrations (LLM, Speech, Graph) with pluggable providers. Services Guide
src/container DI container registrations and tokens. Container Guide
src/utils Core utilities for logging, error handling, performance, security, and telemetry.
src/config Environment variable parsing and validation with Zod.
tests/ Unit and integration tests, mirroring the src/ directory structure.

Documentation

Each module directory has its own README with architecture details and examples.

Core modules

  • MCP Server Guide — Building tools, resources, auth, transports, SDK context, response formatting
  • Container Guide — DI tokens, registration, service lifetimes, testing with mocks
  • Services Guide — LLM (OpenRouter), Speech (ElevenLabs, Whisper), Graph, custom providers
  • Storage Guide — Provider implementations, multi-tenancy, pagination, batch ops, TTL

Other references

Agent development guide

See AGENTS.md for the full rules when using this template with an AI agent. Key principles:

  • Never use try/catch in tool/resource logic. Throw McpError instead — handlers catch.
  • Use elicitInput from SdkContext to ask for missing user input.
  • Pass RequestContext through the call stack.
  • Import from the defining file, not barrel index.ts. Register new tools/resources in definitions/index.ts.

FAQ

  • Does this work with both STDIO and Streamable HTTP? Yes. Use bun run dev:stdio or bun run dev:http.
  • Can I deploy this to the edge? Yes. Run bun run build:worker and deploy with Wrangler.
  • Do I have to use OpenTelemetry? No, disabled by default. Set OTEL_ENABLED=true to enable.
  • How do I publish my server to the MCP Registry? See docs/publishing-mcp-server-registry.md.

Contributing

Issues and pull requests are welcome. Run checks and tests before submitting:

bun run devcheck
bun run test

License

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


About

TypeScript template for building Model Context Protocol (MCP) servers. Ships with declarative tools/resources, pluggable auth, multi-backend storage, OpenTelemetry observability, and first-class support for both local and edge (Cloudflare Workers) runtimes.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

  •  

Packages

 
 
 

Contributors