{"_id":"@8monkey/elysia-mcp","_rev":"4-6604ac9b1044595b750b73900b06053c","name":"@8monkey/elysia-mcp","dist-tags":{"latest":"0.2.0","rc":"0.2.0-rc0"},"versions":{"0.1.0-rc0":{"name":"@8monkey/elysia-mcp","version":"0.1.0-rc0","keywords":["ai","elysia","mcp","tools"],"license":"MIT","_id":"@8monkey/elysia-mcp@0.1.0-rc0","maintainers":[{"name":"heiwen","email":"h@8monkey.ai"},{"name":"turisanapo","email":"selvaggiodavide@hotmail.it"}],"homepage":"https://hebo.ai","bugs":{"url":"https://github.com/8monkey-ai/elysia-mcp/issues"},"dist":{"shasum":"d016fb24dea22a33570641a3f3f3ad55e1ead122","tarball":"https://registry.npmjs.org/@8monkey/elysia-mcp/-/elysia-mcp-0.1.0-rc0.tgz","fileCount":13,"integrity":"sha512-Ei4o/ak56Nld4/qTr8whDVS0QNFanq7xMcxRdB1OnQFhGfRX2UUFKTbinap4kUQX9OFUnBvqI66rrvogmgY4QQ==","signatures":[{"sig":"MEUCIQDKB6zZ0GJYbfMo7TFZJkhc83t+KOZY+TPl74b5TOUFCgIgem8bryHgsoktPXfcQ3WtGlBPZmH/61hsfmvYEGuXq8w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":41119},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"0fcf47bb90d3b8b229c387f338b485db074b57b4","scripts":{"fix":"bun lint:staged && bun format:staged","lint":"oxlint","test":"bun test","build":"tsc -p tsconfig.build.json","check":"bun lint && bun typecheck","clean":"git clean -fdx -e '.env*' .","format":"oxfmt .","typecheck":"oxlint --type-check","lint:staged":"oxlint --fix","format:staged":"oxfmt --no-error-on-unmatched-pattern"},"_npmUser":{"name":"heiwen","email":"h@8monkey.ai"},"repository":{"url":"git+https://github.com/8monkey-ai/elysia-mcp.git","type":"git"},"_npmVersion":"11.10.1","description":"Turn Elysia routes into MCP tools using existing schemas, handlers, and metadata.","directories":{},"sideEffects":false,"_nodeVersion":"25.7.0","dependencies":{"@modelcontextprotocol/sdk":"^1.29.0"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^4.3.6","oxfmt":"^0.43.0","oxlint":"^1.58.0","@types/bun":"^1.2.18","typescript":"^6.0.2","@elysiajs/cors":"^1.4.1","oxlint-tsgolint":"^0.19.0","@sinclair/typebox":"^0.34.49"},"peerDependencies":{"elysia":"^1.4.0"},"peerDependenciesMeta":{},"_npmOperationalInternal":{"tmp":"tmp/elysia-mcp_0.1.0-rc0_1775542798259_0.5164446127347404","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@8monkey/elysia-mcp","version":"0.1.0","keywords":["ai","elysia","mcp","tools"],"license":"MIT","_id":"@8monkey/elysia-mcp@0.1.0","maintainers":[{"name":"heiwen","email":"h@8monkey.ai"},{"name":"turisanapo","email":"selvaggiodavide@hotmail.it"}],"homepage":"https://hebo.ai","bugs":{"url":"https://github.com/8monkey-ai/elysia-mcp/issues"},"dist":{"shasum":"a66c8963705b90e09f6b691ab7b18dfb9118d458","tarball":"https://registry.npmjs.org/@8monkey/elysia-mcp/-/elysia-mcp-0.1.0.tgz","fileCount":13,"integrity":"sha512-pW2dGrHiHh7cz7/VrfngTBKIrNWAM+3Frv7fchd8a7/hehIWmdZko9CBNZrpHX1VJff1pKnY39++mW/7J6HVzQ==","signatures":[{"sig":"MEYCIQCsuHa/TVmzqdbHapc5ej8FnBQJlPBC0HczWsDUuiDs4gIhALCAxOZ7nN8qcm1t4zlMGCqsUja/rOHhe/ZIrk8xeAuE","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":41115},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"0fcf47bb90d3b8b229c387f338b485db074b57b4","scripts":{"fix":"bun lint:staged && bun format:staged","lint":"oxlint","test":"bun test","build":"tsc -p tsconfig.build.json","check":"bun lint && bun typecheck","clean":"git clean -fdx -e '.env*' .","format":"oxfmt .","typecheck":"oxlint --type-check","lint:staged":"oxlint --fix","format:staged":"oxfmt --no-error-on-unmatched-pattern"},"_npmUser":{"name":"heiwen","email":"h@8monkey.ai"},"repository":{"url":"git+https://github.com/8monkey-ai/elysia-mcp.git","type":"git"},"_npmVersion":"11.10.1","description":"Turn Elysia routes into MCP tools using existing schemas, handlers, and metadata.","directories":{},"sideEffects":false,"_nodeVersion":"25.7.0","dependencies":{"@modelcontextprotocol/sdk":"^1.29.0"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^4.3.6","oxfmt":"^0.43.0","oxlint":"^1.58.0","@types/bun":"^1.2.18","typescript":"^6.0.2","@elysiajs/cors":"^1.4.1","oxlint-tsgolint":"^0.19.0","@sinclair/typebox":"^0.34.49"},"peerDependencies":{"elysia":"^1.4.0"},"peerDependenciesMeta":{},"_npmOperationalInternal":{"tmp":"tmp/elysia-mcp_0.1.0_1775566684433_0.08878835432927645","host":"s3://npm-registry-packages-npm-production"}},"0.2.0-rc0":{"name":"@8monkey/elysia-mcp","version":"0.2.0-rc0","keywords":["ai","elysia","mcp","tools"],"license":"MIT","_id":"@8monkey/elysia-mcp@0.2.0-rc0","maintainers":[{"name":"heiwen","email":"h@8monkey.ai"},{"name":"turisanapo","email":"selvaggiodavide@hotmail.it"}],"homepage":"https://hebo.ai","bugs":{"url":"https://github.com/8monkey-ai/elysia-mcp/issues"},"dist":{"shasum":"710da836a76100c7104cc22b8d351a320460b2a7","tarball":"https://registry.npmjs.org/@8monkey/elysia-mcp/-/elysia-mcp-0.2.0-rc0.tgz","fileCount":13,"integrity":"sha512-0rQkJ5qXh4gLFs7dBDORCI84EGyX2sHwnKU0K8SI+57XWS2/Jjdy71KblgQwMrTj7o+T3Pz7cQmOXysyCiIsTQ==","signatures":[{"sig":"MEYCIQCjPdKtP9DiusZtStjOvzQFucUkGOgICQHeHbSRoLnMfwIhAOt+ETkkuO3fujqqicU27sVBlgTir3vrLv1KgVdN5pm/","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":42493},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"40c05801c572b40ecd8f10b00073ec6956eb1b9b","scripts":{"fix":"bun lint:staged && bun format:staged","lint":"oxlint","test":"bun test","build":"tsc -p tsconfig.build.json","check":"bun lint && bun typecheck","clean":"git clean -fdx -e '.env*' .","format":"oxfmt .","typecheck":"oxlint --type-check","lint:staged":"oxlint --fix","format:staged":"oxfmt --no-error-on-unmatched-pattern"},"_npmUser":{"name":"heiwen","email":"h@8monkey.ai"},"repository":{"url":"git+https://github.com/8monkey-ai/elysia-mcp.git","type":"git"},"_npmVersion":"11.17.0","description":"Turn Elysia routes into MCP tools using existing schemas, handlers, and metadata.","directories":{},"sideEffects":false,"_nodeVersion":"26.4.0","dependencies":{"@modelcontextprotocol/sdk":"^1.29.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"zod":"^4.3.6","oxfmt":"^0.44.0","oxlint":"^1.59.0","@types/bun":"^1.2.18","typescript":"^6.0.2","@elysiajs/cors":"^1.4.1","oxlint-tsgolint":"^0.20.0","@sinclair/typebox":"^0.34.49"},"peerDependencies":{"elysia":"^1.4.0"},"peerDependenciesMeta":{},"_npmOperationalInternal":{"tmp":"tmp/elysia-mcp_0.2.0-rc0_1782815222873_0.6460274746517698","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@8monkey/elysia-mcp","version":"0.2.0","description":"Turn Elysia routes into MCP tools using existing schemas, handlers, and metadata.","keywords":["ai","elysia","mcp","tools"],"homepage":"https://hebo.ai","bugs":{"url":"https://github.com/8monkey-ai/elysia-mcp/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/8monkey-ai/elysia-mcp.git"},"type":"module","sideEffects":false,"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsc -p tsconfig.build.json","clean":"git clean -fdx -e '.env*' .","format":"oxfmt .","format:staged":"oxfmt --no-error-on-unmatched-pattern","lint":"oxlint","lint:staged":"oxlint --fix","typecheck":"oxlint --type-check","test":"bun test","check":"bun lint && bun typecheck","fix":"bun lint:staged && bun format:staged"},"dependencies":{"@modelcontextprotocol/sdk":"^1.29.0"},"devDependencies":{"@elysiajs/cors":"^1.4.2","@sinclair/typebox":"^0.34.50","@types/bun":"^1.3.14","oxfmt":"^0.44.0","oxlint":"^1.59.0","oxlint-tsgolint":"^0.20.0","typescript":"^6.0.2","zod":"^4.4.3"},"peerDependencies":{"elysia":"^1.4.0"},"peerDependenciesMeta":{},"gitHead":"d8adc6818b5d4503dccab40edb2c153428c967de","_id":"@8monkey/elysia-mcp@0.2.0","_nodeVersion":"26.4.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-9YaJPWOZwMP4JJp/8mEeWpTHCLJGYLd/+RHEkfRePt9qYA2gvrY4WkGxVatACayV8ixWTN3fbjXFEHQI/ynT2A==","shasum":"0dc7000092c574484b4146a80c96f06dd93b32e6","tarball":"https://registry.npmjs.org/@8monkey/elysia-mcp/-/elysia-mcp-0.2.0.tgz","fileCount":13,"unpackedSize":42489,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDYg/qLZiJKig8MfWXaGv9E4IRe+pOeppxqo7HZ6hKNXgIhAMMHXAQChuXyLgu/74rrj6O/A4yy66aejeMkBfjdZs38"}]},"_npmUser":{"name":"heiwen","email":"h@8monkey.ai"},"directories":{},"maintainers":[{"name":"heiwen","email":"h@8monkey.ai"},{"name":"turisanapo","email":"selvaggiodavide@hotmail.it"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/elysia-mcp_0.2.0_1783596745755_0.5691844445763459"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-07T06:19:58.124Z","modified":"2026-07-09T11:32:26.034Z","0.1.0-rc0":"2026-04-07T06:19:58.406Z","0.1.0":"2026-04-07T12:58:04.575Z","0.2.0-rc0":"2026-06-30T10:27:03.021Z","0.2.0":"2026-07-09T11:32:25.926Z"},"bugs":{"url":"https://github.com/8monkey-ai/elysia-mcp/issues"},"license":"MIT","homepage":"https://hebo.ai","keywords":["ai","elysia","mcp","tools"],"repository":{"type":"git","url":"git+https://github.com/8monkey-ai/elysia-mcp.git"},"description":"Turn Elysia routes into MCP tools using existing schemas, handlers, and metadata.","maintainers":[{"name":"heiwen","email":"h@8monkey.ai"},{"name":"turisanapo","email":"selvaggiodavide@hotmail.it"}],"readme":"# @8monkey/elysia-mcp\n\nTurn your existing Elysia routes into MCP tools. No manual registration, no schema duplication, no handler rewrites.\n\n## Why?\n\nThe [Model Context Protocol](https://modelcontextprotocol.io/) 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.\n\n`@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.\n\n## Key highlights\n\n- 🔄 **Zero duplication** — tool names, descriptions, and input schemas are derived from your existing route definitions. OpenAPI metadata such as `detail.operationId` and `detail.summary` also drive MCP tool discovery. Write once, serve both humans and AI agents.\n- 🔌 **Any schema library** — works with TypeBox, Zod, Valibot, or any validation library supported by Elysia via [Standard Schema](https://github.com/standard-schema/standard-schema).\n- ⚡ **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.\n- 📋 **Schema flattening** — params, query, and body schemas are merged into a single flat MCP input schema with property origins tracked for correct unflattening\n- 🏷️ **Smart naming** — `GET /users` becomes `list_users`, `GET /users/:id` becomes `get_user`, `POST /users` becomes `create_user`, and nested paths like `GET /users/:uid/posts` become `list_user_posts`\n\n## How it differs from existing solutions\n\nCompared to [kerlos/elysia-mcp](https://github.com/kerlos/elysia-mcp) and [keithagroves/Elysia-mcp](https://github.com/keithagroves/Elysia-mcp), which require manual tool registration with separate Zod schemas and standalone handlers:\n\n- **Auto-discovery** — routes become tools automatically; no registration callbacks\n- **Schema reuse** — uses your existing Elysia schema definitions (TypeBox, Zod, Valibot, or any [Standard Schema](https://github.com/standard-schema/standard-schema) provider) instead of duplicating separately\n- **Full lifecycle execution** — tool calls run through `app.handle()`, not standalone functions, so all middleware applies\n- **Streamable HTTP** — full GET/POST/DELETE support over the MCP Streamable HTTP transport, including SSE streams for clients that open them via GET\n\n## Install\n\n```bash\nbun add @8monkey/elysia-mcp\n```\n\nPeer dependency: `elysia >= 1.4.0`\n\n## Basic usage\n\nAdd `.use(mcp())` and all routes become MCP tools:\n\n```typescript\nimport { Elysia } from \"elysia\";\nimport { mcp } from \"@8monkey/elysia-mcp\";\n\nconst app = new Elysia()\n  .use(mcp())\n  .get(\"/users\", () => db.users.findAll())\n  .get(\"/users/:id\", ({ params }) => db.users.find(params.id))\n  .post(\"/users\", ({ body }) => db.users.create(body))\n  .listen(3000);\n```\n\nThis 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`.\n\n## Descriptions matter — for agents and docs\n\nGood 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.\n\nThe 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.\n\n### Route-level: `detail.summary`\n\nUse `detail.summary` to describe what the tool does. This becomes the MCP tool description **and** the OpenAPI operation summary:\n\n```typescript\n.get(\"/users\", () => db.users.findAll(), {\n  detail: {\n    operationId: \"list_users\",\n    summary: \"List all users in the system\",\n    mcp: true,\n  },\n})\n```\n\nIf `operationId` is omitted, the plugin falls back to generated names like `list_users` or `get_user`.\n\n### Property-level: schema `description`\n\nAdd `description` to each schema property. These become the MCP parameter descriptions **and** the OpenAPI property descriptions — the same metadata, no duplication:\n\n```typescript\nimport { t } from \"elysia\";\n\n.get(\"/users/:id\", ({ params }) => db.users.find(params.id), {\n  params: t.Object({\n    id: t.String({ description: \"The user's unique ID\" }),\n  }),\n  detail: { summary: \"Get user by ID\" },\n})\n```\n\nMCP tools accept a single flat input object. The plugin merges `params`, `query`, and `body` into one schema:\n\n```text\nRoute: PATCH /users/:id  (params: { id }, query: { fields }, body: { name, email })\n  ↓\nMCP Tool Input: { id: string, fields?: string, name: string, email: string }\n```\n\nProperty descriptions are preserved. The plugin warns at startup if properties collide across buckets or lack descriptions.\n\n## Opting routes out\n\nBy default, all routes are exposed. Opt out individual routes with `mcp: false`:\n\n```typescript\n.get(\"/health\", () => ({ status: \"ok\" }), {\n  detail: { mcp: false },\n})\n```\n\nOr flip the default — set `allRoutes: false` to require explicit opt-in:\n\n```typescript\n.use(mcp({ allRoutes: false }))\n.get(\"/users\", () => db.users.findAll(), {\n  detail: { mcp: true },  // only this route becomes a tool\n})\n.get(\"/health\", () => \"ok\")  // not exposed\n```\n\n## Overriding tool names and descriptions\n\nAuto-generated names follow a `{verb}_{resource}` convention. If you want an explicit tool name, set `detail.operationId`:\n\n```typescript\n.get(\"/items\", handler, {\n  detail: {\n    operationId: \"search_items\",\n    summary: \"Full-text search across all items\",\n    mcp: true,\n  },\n})\n```\n\n### Naming conventions\n\n| Method + Path           | Generated Name    |\n| ----------------------- | ----------------- |\n| `GET /users`            | `list_users`      |\n| `GET /users/:id`        | `get_user`        |\n| `POST /users`           | `create_user`     |\n| `PATCH /users/:id`      | `update_user`     |\n| `DELETE /users/:id`     | `delete_user`     |\n| `GET /users/:uid/posts` | `list_user_posts` |\n\n## Configuration\n\n```typescript\nmcp({\n  name: \"my-api\", // MCP server name (default: \"elysia-mcp\")\n  version: \"1.0.0\", // MCP server version (default: \"1.0.0\")\n  path: \"/mcp\", // Endpoint path (default: \"/mcp\")\n  allRoutes: true, // Expose all routes by default (default: true)\n});\n```\n\n## How tool calls work\n\nWhen an MCP client calls a tool:\n\n1. The flat args are unflattened back into `params`, `query`, and `body`\n2. A synthetic HTTP request is built with the correct method, path, query string, body, and headers from the original MCP request\n3. `app.handle(request)` runs the full Elysia lifecycle — derive, resolve, beforeHandle, the handler, afterHandle, and error hooks\n4. The response body is parsed and returned as MCP text content\n\nThis means your auth middleware, rate limiting, validation, and every other plugin work exactly the same for MCP calls as they do for REST calls.\n\n## Connecting an MCP client\n\nPoint any MCP-compatible client at your `/mcp` endpoint. For example, with the [MCP Inspector](https://github.com/modelcontextprotocol/inspector):\n\n```bash\nnpx @modelcontextprotocol/inspector --transport http http://localhost:3000/mcp\n```\n\nOr configure it in Claude Desktop, Cursor, or any other MCP-enabled tool as an HTTP MCP server at `http://localhost:3000/mcp`.\n\n## Important notes\n\n- **Tools only (v1)**: This plugin exposes MCP tools. Resources and prompts are not supported yet.\n- **Stateless transport**: Each request gets its own transport instance — no session tracking. POST returns JSON-RPC responses inline; GET with `Accept: text/event-stream` opens a server-initiated SSE stream; DELETE is accepted as a no-op terminator.\n","readmeFilename":"README.md"}