Offers storage backend integration with Cloudflare KV and R2 services for key-value storage and object storage capabilities
Includes text-to-speech service integration for converting text content into audio using ElevenLabs' voice synthesis API
Provides storage backend integration allowing data persistence and retrieval through Supabase's database and storage services
✨ Features
Declarative Tools & Resources: Define capabilities in single, self-contained files. The framework handles registration and execution.
Elicitation Support: Tools can interactively prompt the user for missing parameters during execution, streamlining user workflows.
Robust Error Handling: A unified
McpError
system ensures consistent, structured error responses across the server.Pluggable Authentication: Secure your server with zero-fuss support for
none
,jwt
, oroauth
modes.Abstracted Storage: Swap storage backends (
in-memory
,filesystem
,Supabase
,Cloudflare KV/R2
) without changing business logic.Full-Stack Observability: Get deep insights with structured logging (Pino) and optional, auto-instrumented OpenTelemetry for traces and metrics.
Dependency Injection: Built with
tsyringe
for a clean, decoupled, and testable architecture.Service Integrations: Pluggable services for external APIs, including LLM providers (OpenRouter) and text-to-speech (ElevenLabs).
Rich Built-in Utility Suite: Helpers for parsing (PDF, YAML, CSV), scheduling, security, and more.
Edge-Ready: Write code once and run it seamlessly on your local machine or at the edge on Cloudflare Workers.
🚀 Getting Started
MCP Client Settings/Configuration
Add the following to your MCP Client configuration file (e.g., cline_mcp_settings.json
).
Prerequisites
Bun v1.2.0 or higher.
Installation
Clone the repository:
Navigate into the directory:
Install dependencies:
🛠️ Understanding the Template: Tools & Resources
This template includes working examples of tools and resources.
1. Example Tool: template_echo_message
This tool echoes back a message with optional formatting. You can find the full source at src/mcp-server/tools/definitions/template-echo-message.tool.ts
.
The echoTool
is registered in src/mcp-server/tools/definitions/index.ts
, making it available to the server on startup. For an example of how to use the new elicitation feature, see template_madlibs_elicitation.tool.ts
.
2. Example Resource: echo-resource
This resource provides a simple echo response via a URI. The source is located at src/mcp-server/resources/definitions/echo.resource.ts
.
Like the tool, echoResourceDefinition
is registered in src/mcp-server/resources/definitions/index.ts
.
⚙️ Core Concepts
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 |
| The transport to use:
or
. |
|
| The port for the HTTP server. |
|
| Authentication mode:
,
, or
. |
|
| Storage backend:
,
,
,
,
. |
|
| Set to
to enable OpenTelemetry. |
|
| The minimum level for logging. |
|
Authentication & Authorization
Modes:
none
(default),jwt
(requiresMCP_AUTH_SECRET_KEY
), oroauth
(requiresOAUTH_ISSUER_URL
andOAUTH_AUDIENCE
).Enforcement: Wrap your tool/resource
logic
functions withwithToolAuth([...])
orwithResourceAuth([...])
to enforce scope checks. Scope checks are bypassed for developer convenience when auth mode isnone
.
Storage
Service: A DI-managed
StorageService
provides a consistent API for persistence. Never accessProviders: The default is
in-memory
. Node-only providers includefilesystem
. Edge-compatible providers includesupabase
,cloudflare-kv
, andcloudflare-r2
.Multi-Tenancy: The
StorageService
requirescontext.tenantId
. This is automatically propagated from thetid
claim in a JWT when auth is enabled.
Observability
Structured Logging: Pino is integrated out-of-the-box. All logs are JSON and include the
RequestContext
.OpenTelemetry: Disabled by default. Enable with
OTEL_ENABLED=true
and configure OTLP endpoints. Traces, metrics (duration, payload sizes), and errors are automatically captured for every tool call.
▶️ Running the Server
Local Development
Build and run the production version:
# One-time build bun rebuild # Run the built server bun start:http # or bun start:stdioRun checks and tests:
bun devcheck # Lints, formats, type-checks, and more bun test # Runs the test suite
Cloudflare Workers
Build the Worker bundle:
Run locally with Wrangler:
Deploy to Cloudflare:
sh bun deploy:prod
> Note: Thewrangler.toml
file is pre-configured to enablenodejs_compat
for best results.
📂 Project Structure
Directory | Purpose & Contents |
| Your tool definitions (
). This is where you add new capabilities. |
| Your resource definitions (
). This is where you add new data sources. |
| Implementations for HTTP and STDIO transports, including auth middleware. |
| The
abstraction and all storage provider implementations. |
| Integrations with external services (e.g., the default OpenRouter LLM provider). |
| Dependency injection container registrations and tokens. |
| Core utilities for logging, error handling, performance, security, and telemetry. |
| Environment variable parsing and validation with Zod. |
| Unit and integration tests, mirroring the
directory structure. |
🧑💻 Agent Development Guide
For a strict set of rules when using this template with an AI agent, please refer to AGENTS.md
. Key principles include:
Logic Throws, Handlers Catch: Never use
try/catch
in your tool/resourcelogic
. Throw anMcpError
instead.Use Elicitation for Missing Input: If a tool requires user input that wasn't provided, use the
elicitInput
function from theSdkContext
to ask the user for it.Pass the Context: Always pass the
RequestContext
object through your call stack.Use the Barrel Exports: Register new tools and resources only in the
index.ts
barrel files.
❓ FAQ
Does this work with both STDIO and Streamable HTTP?
Yes. Both transports are first-class citizens. Use
bun run dev:stdio
orbun run dev:http
.
Can I deploy this to the edge?
Yes. The template is designed for Cloudflare Workers. Run
bun run build:worker
and deploy with Wrangler.
Do I have to use OpenTelemetry?
No, it is disabled by default. Enable it by setting
OTEL_ENABLED=true
in your.env
file.
How do I publish my server to the MCP Registry?
Follow the step-by-step guide in
docs/publishing-mcp-server-registry.md
.
🤝 Contributing
Issues and pull requests are welcome! If you plan to contribute, please run the local checks and tests before submitting your PR.
📜 License
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
This server cannot be installed
hybrid server
The server is able to function both locally and remotely, depending on the configuration or use case.
A production-grade TypeScript template for building Model Context Protocol (MCP) servers with declarative tools/resources, authentication, storage abstraction, and support for both local and edge deployment. Provides example echo tools and resources to demonstrate MCP server development patterns.