The Hono for MCP
Ship MCP Servers That Actually Scale
Stop reinventing auth, rate limiting, and middleware for every MCP server. One framework, composable by default, production-ready from day one.
12 Built-in features
137 Tests passing
v0.7 Latest
Batteries Included
Everything between the request and your handler -- handled.
- Dual Transport STDIO + Streamable HTTP. Same code.
- Middleware Pipeline Composable onion model, like Koa.
- OAuth2 Auth JWT/Bearer + RFC 9728 metadata.
- OIDC Presets GitHub, Google, Auth0 -- one line.
- YAML + Env Config File config, env overrides at deploy.
- Concurrency Backpressure: sleep, queue, or reject.
- Rate Limiting Sliding window, per-client isolation.
- Schema Validation JSON Schema via ajv at registration.
- Observability OTel spans + Prometheus /metrics.
- MCP Apps Serve interactive UIs via ui:// scheme.
SDK vs Framework
The official SDK gives you the protocol. This gives you the production stack.
| Official SDK | @casys/mcp-server | |
|---|---|---|
| MCP protocol | ✓ | ✓ |
| Middleware pipeline | — | ✓ |
| OAuth2 / JWT auth | — | ✓ |
| Rate limiting | — | ✓ |
| Schema validation | — | ✓ |
| Streamable HTTP + SSE | Manual | Built-in |
| Concurrency control | — | ✓ |
| OpenTelemetry tracing | — | ✓ |
| Prometheus metrics | — | ✓ |
| MCP Apps (UI resources) | Manual | Built-in |
5 Lines to Production
No boilerplate. No config ceremony. Register a tool, call start(), ship it.
import { ConcurrentMCPServer } from "@casys/mcp-server";
const server = new ConcurrentMCPServer({
name: "my-server",
version: "1.0.0",
});
server.registerTool(
{ name: "greet", description: "Greet a user",
inputSchema: { type: "object",
properties: { name: { type: "string" } },
required: ["name"] } },
({ name }) => \`Hello, \${name}!\`,
);
await server.start(); import { ConcurrentMCPServer, createGoogleAuthProvider } from "@casys/mcp-server";
const server = new ConcurrentMCPServer({
name: "my-api", version: "1.0.0",
auth: {
provider: createGoogleAuthProvider({
audience: "https://my-mcp.example.com",
resource: "https://my-mcp.example.com",
}),
},
});
server.registerTool(
{ name: "query", description: "Query the database",
inputSchema: { type: "object",
properties: { sql: { type: "string" } } },
requiredScopes: ["db:read"] },
async ({ sql }) => ({ rows: [] }),
);
await server.startHttp({ port: 3000 }); # mcp-server.yaml
auth:
provider: auth0
audience: https://my-mcp.example.com
resource: https://my-mcp.example.com
domain: my-tenant.auth0.com
scopesSupported: [read, write, admin] # Override with env vars in production
MCP_AUTH_AUDIENCE=https://prod.example.com ./my-server --http --port 3000 Your Server, Your Rules
Every request flows through a composable middleware chain. Need auth? Drop it in. Rate limiting? One line. Custom logic? Slot it anywhere.
arrow_forward Request
timer Rate Limit
shield Auth
tune Custom
verified_user Scopes
check_circle Validation
speed Backpressure
play_arrow Handler
Ready When You Are
One command. Works with Deno and Node.js. Published on JSR, the modern JavaScript registry.
Deno
deno add jsr:@casys/mcp-server npm
npx jsr add @casys/mcp-server