elysiajs-mcp
An MCP server plugin for the Elysia web framework, enabling AI clients to connect via Streamable HTTP transport with stateful or stateless sessions and authentication.
README
elysiajs-mcp
Model Context Protocol (MCP) server transport and plugin for the Elysia web framework (Bun).
Connect AI clients to your Elysia app over the MCP Streamable HTTP transport. Built on the official @modelcontextprotocol/sdk web-standard transport, with an idiomatic Elysia plugin that handles session lifecycle for you.
Features
mcp()plugin — mount a full MCP server in one line, with automatic stateful (per-session) and stateless modes.StreamableHTTPTransport— a low-level transport you can wire up manually (mirrors the@hono/mcpAPI).- Permissive
Acceptheader handling by default — works out of the box with Gemini CLI, the Java MCP SDK, Open WebUI, andcurl. Toggle strict mode if you prefer. MemoryEventStore— in-memory event store enabling SSE resumability.- Auth helpers —
bearerAuth()for token validation andmcpAuthMetadata()for the/.well-knownOAuth discovery endpoints. - Runs on any web-standard runtime (Bun, Node, Deno, Workers).
Install
bun add elysiajs-mcp @modelcontextprotocol/sdk elysia
Quick start
import { Elysia } from "elysia";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { mcp } from "elysiajs-mcp";
new Elysia()
.use(
mcp({
server: () => {
const server = new McpServer({ name: "my-server", version: "1.0.0" });
server.registerTool(
"greet",
{
description: "Greet someone by name",
inputSchema: { name: z.string().default("world") },
},
async ({ name }) => ({
content: [{ type: "text", text: `Hello, ${name}!` }],
}),
);
return server;
},
}),
)
.listen(3000);
Connect any MCP client (e.g. the MCP Inspector) to http://localhost:3000/mcp.
How it works
mcp() mounts a single .all('/mcp') route. A server() factory is invoked for every new session (stateful mode) or every request (stateless mode), so each session gets isolated tools, prompts, and resources.
| Option | Default | Description |
|---|---|---|
server |
(required) | Factory returning an MCP Server / McpServer. |
path |
'/mcp' |
Endpoint path. |
sessionIdGenerator |
() => crypto.randomUUID() |
Pass undefined for stateless mode. |
strictAcceptHeader |
false |
Strictly enforce the MCP Accept header spec. |
enableJsonResponse |
false |
Return JSON instead of SSE for POST requests. |
eventStore |
none | Provide a MemoryEventStore (or your own) for resumability. |
auth |
none | (request) => AuthInfo | Response | undefined hook. |
onsessioninitialized |
none | Called when a session is created. |
onsessionclosed |
none | Called when a session is closed via DELETE. |
Stateful vs. stateless
// Stateful (default): one server + transport kept alive per session.
mcp({ server: () => new McpServer({ name: "s", version: "1" }) });
// Stateless: a fresh server + transport per request, torn down after.
mcp({ server: () => new McpServer({ name: "s", version: "1" }), sessionIdGenerator: undefined });
Resumability (event store)
Pass an eventStore so clients that disconnect can resume missed messages via Last-Event-ID.
import { mcp, MemoryEventStore } from 'elysiajs-mcp'
mcp({ server: () => …, eventStore: new MemoryEventStore() })
MemoryEventStore keeps the last 100 streams × 100 events by default (both configurable).
Auth
Bearer tokens
import { mcp, bearerAuth } from 'elysiajs-mcp'
new Elysia().use(
mcp({
server: () => …,
auth: bearerAuth({
require: true,
verify: async (token) => {
const user = await verifyToken(token)
return user ? { token, clientId: user.id, scopes: user.scopes } : undefined
},
}),
})
)
OAuth discovery endpoints
Advertise where clients should authenticate (RFC 8414 / RFC 9728):
import { mcpAuthMetadata } from "elysiajs-mcp";
new Elysia().use(
mcpAuthMetadata({
issuerUrl: "https://auth.example.com",
resourceServerUrl: new URL("http://localhost:3000/mcp"),
}),
);
This serves /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource.
Low-level transport
If you need full control (mirrors @hono/mcp's API):
import { Elysia } from "elysia";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPTransport } from "elysiajs-mcp";
const server = new McpServer({ name: "low-level", version: "1.0.0" });
const transport = new StreamableHTTPTransport({ sessionIdGenerator: () => crypto.randomUUID() });
new Elysia().all("/mcp", async ({ request }) => {
if (!server.isConnected()) await server.connect(transport);
return transport.handleRequest(request);
});
StreamableHTTPTransport accepts the same options as the SDK's transport, plus strictAcceptHeader.
API
mcp(options): Elysia
Mount an MCP Streamable HTTP server.
StreamableHTTPTransport
Extends WebStandardStreamableHTTPServerTransport. Adds strictAcceptHeader (default false).
MemoryEventStore
In-memory EventStore implementation with bounded ring buffers.
bearerAuth(options) / unauthorizedResponse(request, url?)
Bearer-token auth extractor (401 challenge helper).
mcpAuthMetadata(options) / createOAuthMetadata(options)
Elysia plugin + helper serving OAuth discovery metadata.
Scripts
bun run lint # oxlint
bun run lint:fix # oxlint --fix
bun run format # oxfmt (write)
bun run format:check # oxfmt --check
bun run typecheck # tsc --noEmit
bun run check # lint + format:check + typecheck
bun test # run the test suite
bun run dev # run the example server (example/server.ts)
bun run build # bundle to dist/
Credits & license
Inspired by @hono/mcp by Aditya Mathur.
License
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.