elysia-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@elysia-mcplist the MCP tools exposed by my Elysia API"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
@8monkey/elysia-mcp
Turn your existing Elysia routes into MCP tools. No manual registration, no schema duplication, no handler rewrites.
Why?
The Model Context Protocol lets AI agents discover and call tools over a standard JSON-RPC interface. If you already have an Elysia API with typed schemas and handlers, you shouldn't have to rewrite all of that as MCP tool definitions.
@8monkey/elysia-mcp bridges the gap: add .use(mcp()) and every endpoint becomes a callable MCP tool, with its name, description, and input schema derived from what you already wrote.
Related MCP server: hono-mcp-server
Key highlights
🔄 Zero duplication — tool names, descriptions, and input schemas are derived from your existing route definitions. OpenAPI metadata such as
detail.operationIdanddetail.summaryalso drive MCP tool discovery. Write once, serve both humans and AI agents.🔌 Any schema library — works with TypeBox, Zod, Valibot, or any validation library supported by Elysia via Standard Schema.
⚡ Full lifecycle — MCP tool calls go through
app.handle(), so derive, resolve, beforeHandle, afterHandle, error hooks, and all plugins run exactly as they do for normal HTTP requests.📋 Schema flattening — params, query, and body schemas are merged into a single flat MCP input schema with property origins tracked for correct unflattening
🏷️ Smart naming —
GET /usersbecomeslist_users,GET /users/:idbecomesget_user,POST /usersbecomescreate_user, and nested paths likeGET /users/:uid/postsbecomelist_user_posts
How it differs from existing solutions
Compared to kerlos/elysia-mcp and keithagroves/Elysia-mcp, which require manual tool registration with separate Zod schemas and standalone handlers:
Auto-discovery — routes become tools automatically; no registration callbacks
Schema reuse — uses your existing Elysia schema definitions (TypeBox, Zod, Valibot, or any Standard Schema provider) instead of duplicating separately
Full lifecycle execution — tool calls run through
app.handle(), not standalone functions, so all middleware appliesStreamable HTTP — full GET/POST/DELETE support over the MCP Streamable HTTP transport, including SSE streams for clients that open them via GET
Install
bun add @8monkey/elysia-mcpPeer dependency: elysia >= 1.4.0
Basic usage
Add .use(mcp()) and all routes become MCP tools:
import { Elysia } from "elysia";
import { mcp } from "@8monkey/elysia-mcp";
const app = new Elysia()
.use(mcp())
.get("/users", () => db.users.findAll())
.get("/users/:id", ({ params }) => db.users.find(params.id))
.post("/users", ({ body }) => db.users.create(body))
.listen(3000);This exposes a /mcp endpoint that speaks the MCP Streamable HTTP transport — POST for JSON-RPC requests, GET (with Accept: text/event-stream) for SSE streams, and DELETE for session termination. An MCP client calling tools/list will see list_users, get_user, and create_user.
Descriptions matter — for agents and docs
Good descriptions are critical for AI agents to understand when and how to call your tools. The plugin uses Elysia's standard detail.summary as the MCP tool description, and TypeBox description on each property as the parameter description. These are the same fields that Elysia uses for OpenAPI/Swagger documentation, meaning there's zero duplication. Write them once and they serve both your API docs and your MCP tools.
The plugin warns at startup if any property is missing a description, since agents rely on these to choose the right tool and pass the correct arguments.
Route-level: detail.summary
Use detail.summary to describe what the tool does. This becomes the MCP tool description and the OpenAPI operation summary:
.get("/users", () => db.users.findAll(), {
detail: {
operationId: "list_users",
summary: "List all users in the system",
mcp: true,
},
})If operationId is omitted, the plugin falls back to generated names like list_users or get_user.
Property-level: schema description
Add description to each schema property. These become the MCP parameter descriptions and the OpenAPI property descriptions — the same metadata, no duplication:
import { t } from "elysia";
.get("/users/:id", ({ params }) => db.users.find(params.id), {
params: t.Object({
id: t.String({ description: "The user's unique ID" }),
}),
detail: { summary: "Get user by ID" },
})MCP tools accept a single flat input object. The plugin merges params, query, and body into one schema:
Route: PATCH /users/:id (params: { id }, query: { fields }, body: { name, email })
↓
MCP Tool Input: { id: string, fields?: string, name: string, email: string }Property descriptions are preserved. The plugin warns at startup if properties collide across buckets or lack descriptions.
Opting routes out
By default, all routes are exposed. Opt out individual routes with mcp: false:
.get("/health", () => ({ status: "ok" }), {
detail: { mcp: false },
})Or flip the default — set allRoutes: false to require explicit opt-in:
.use(mcp({ allRoutes: false }))
.get("/users", () => db.users.findAll(), {
detail: { mcp: true }, // only this route becomes a tool
})
.get("/health", () => "ok") // not exposedOverriding tool names and descriptions
Auto-generated names follow a {verb}_{resource} convention. If you want an explicit tool name, set detail.operationId:
.get("/items", handler, {
detail: {
operationId: "search_items",
summary: "Full-text search across all items",
mcp: true,
},
})Naming conventions
Method + Path | Generated Name |
|
|
|
|
|
|
|
|
|
|
|
|
Configuration
mcp({
name: "my-api", // MCP server name (default: "elysia-mcp")
version: "1.0.0", // MCP server version (default: "1.0.0")
path: "/mcp", // Endpoint path (default: "/mcp")
allRoutes: true, // Expose all routes by default (default: true)
});How tool calls work
When an MCP client calls a tool:
The flat args are unflattened back into
params,query, andbodyA synthetic HTTP request is built with the correct method, path, query string, body, and headers from the original MCP request
app.handle(request)runs the full Elysia lifecycle — derive, resolve, beforeHandle, the handler, afterHandle, and error hooksThe response body is parsed and returned as MCP text content
This means your auth middleware, rate limiting, validation, and every other plugin work exactly the same for MCP calls as they do for REST calls.
Connecting an MCP client
Point any MCP-compatible client at your /mcp endpoint. For example, with the MCP Inspector:
npx @modelcontextprotocol/inspector --transport http http://localhost:3000/mcpOr configure it in Claude Desktop, Cursor, or any other MCP-enabled tool as an HTTP MCP server at http://localhost:3000/mcp.
Important notes
Tools only (v1): This plugin exposes MCP tools. Resources and prompts are not supported yet.
Stateless transport: Each request gets its own transport instance — no session tracking. POST returns JSON-RPC responses inline; GET with
Accept: text/event-streamopens a server-initiated SSE stream; DELETE is accepted as a no-op terminator.
This server cannot be deployed
Maintenance
Related MCP Connectors
Give any MCP-compatible AI assistant a builder for live, hosted web tools and workflows.
The OpenRouter for tools. One MCP connection gives any AI agent 254 hosted tools, pay per call.
Host your MCP tool over streamable HTTP in one command.
Build, validate, deploy — HTTP APIs, cron jobs, webhooks and MCP tools — from your AI client.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceExposes Hono API endpoints as Model Context Protocol tools, allowing LLMs to interact with your API routes through a dedicated MCP endpoint. It provides helpers to describe routes and includes a codemode for dynamic API interaction via search and execute tools.25 npm86MIT
- AlicenseNot gradedqualityCmaintenanceEasily expose your Hono API endpoints as MCP tools with minimal configuration, supporting type-safe input handling and tool registration.25 npm2MIT
- AlicenseNot gradedqualityBmaintenanceExposes FastAPI routes as MCP tools with auto-discovery, Pydantic schema extraction, and built-in observability.Apache 2.0
- AlicenseNot gradedqualityBmaintenanceExposes Elysia HTTP routes and MCP-native primitives through a single Model Context Protocol endpoint, preserving Elysia's request lifecycle.17 npmMIT