by cyanheads
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.
# Add to your Claude Code skills
git clone https://github.com/cyanheads/mcp-ts-templateTry 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.
McpError system for consistent, structured error responses.none, jwt, or oauth. Wrap logic with /.No comments yet. Be the first to share your thoughts!
withToolAuthwithResourceAuthin-memory, filesystem, Supabase, Cloudflare D1/KV/R2) without changing tool logic. Includes cursor pagination, batch ops, and input validation.Token<T> phantom branding. No external deps.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:
This template includes working examples to get you started.
| 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). |
| 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). |
| Prompt | Description |
| :---------------- | :--------------------------------------------------------------- |
| code-review | A structured prompt for guiding an LLM to perform a code review. |
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"
}
}
}
git clone https://github.com/cyanheads/mcp-ts-template.git
cd mcp-ts-template
bun install
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) |