
Security News
RubyGems Adds Cooldown Feature to Bundler for Newly Published Gems
RubyGems and Bundler 4.0.13 introduced an opt-in cooldown feature that delays newly published gems during dependency resolution.
elysia-mcp
Advanced tools
ElysiaJS plugin for Model Context Protocol with HTTP transport and stateful sessions
A comprehensive ElysiaJS plugin for implementing Model Context Protocol (MCP) servers with HTTP transport support.
bun add elysia-mcp
# or
npm install elysia-mcp
To quickly get started with a pre-configured Elysia MCP project, you can use our starter template:
# Create a new project from the starter template
bun create https://github.com/kerlos/elysia-mcp-starter my-mcp-project
# Navigate to the project
cd my-mcp-project
# Install dependencies
bun install
# Start development server
bun run dev
The elysia-mcp-starter template includes:
import { Elysia } from 'elysia';
import { mcp } from 'elysia-mcp';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
const app = new Elysia()
.use(
mcp({
serverInfo: {
name: 'my-mcp-server',
version: '1.0.0',
},
capabilities: {
tools: {},
resources: {},
prompts: {},
logging: {},
},
setupServer: async (server: McpServer) => {
// Register your MCP tools, resources, and prompts here
server.registerTool(
'echo',
{
description: 'Echoes back the provided text',
inputSchema: {
text: z.string().describe('Text to echo back'),
},
},
async (args) => {
return {
content: [{ type: 'text', text: `Echo: ${args.text}` }],
};
}
);
},
})
)
.listen(3000);
Basic Example:
# Run the basic example server (port 3000)
bun run example
# Or with development mode (auto-restart)
bun run dev
Multiple Servers Example:
# Run the multiple MCP servers example (port 3000)
bun example:multi
This example demonstrates how to create multiple MCP plugins in a single Elysia application:
Math Operations Plugin (/math) - Basic arithmetic tools:
add - Add two numbersmultiply - Multiply two numberspower - Calculate base to the power of exponentText Utilities Plugin (/text) - Text processing tools:
uppercase - Convert text to uppercaseword_count - Count words in textreverse - Reverse text charactersreplace - Replace text with global matchingInstall MCP Inspector:
npx @modelcontextprotocol/inspector
Connect to your server:
http://localhost:3000/mcphttp://localhost:3000/mathhttp://localhost:3000/textserverInfo: Server informationcapabilities: MCP capabilities to advertiselogger: Custom logger instance (pino, winston, etc.) - see Custom Logger sectionsetupServer: Callback to register tools, resources, and promptsbasePath: Base path for MCP endpoints (default: '/mcp')enableJsonResponse: Enable JSON response mode instead of SSE streamingstateless: Enable stateless mode (no session management)authentication: Authentication handler for protected routeseventStore: Event store for resumability supportThe plugin automatically handles session management via the Mcp-Session-Id
header. Each session maintains its own state and can be terminated cleanly.
The plugin supports a modular handler architecture that allows you to create specialized endpoints for different MCP capabilities:
import {
mcp,
ToolsHandler,
ResourcesHandler,
PromptsHandler,
} from 'elysia-mcp';
const app = new Elysia().use(
mcp({
/* config */
})
);
The plugin supports custom logger instances, allowing you to use any logging library that conforms to the ILogger interface:
interface ILogger {
info(message: string, ...args: unknown[]): void;
error(message: string, ...args: unknown[]): void;
warn(message: string, ...args: unknown[]): void;
debug(message: string, ...args: unknown[]): void;
}
import { Elysia } from 'elysia';
import { mcp } from 'elysia-mcp';
import pino from 'pino';
const logger = pino({ level: 'debug' });
const app = new Elysia()
.use(
mcp({
logger, // Pass your custom logger
serverInfo: {
name: 'my-mcp-server',
version: '1.0.0',
},
// ... other options
})
)
.listen(3000);
import winston from 'winston';
const logger = winston.createLogger({
level: 'debug',
format: winston.format.json(),
transports: [new winston.transports.Console()],
});
const app = new Elysia()
.use(
mcp({
logger, // Pass your winston logger
// ... other options
})
)
.listen(3000);
If you don't provide a custom logger, the plugin will use a default console logger when enableLogging is set to true:
const app = new Elysia()
.use(
mcp({
enableLogging: true, // Uses default console logger with colors
// ... other options
})
)
.listen(3000);
You can also implement your own logger:
import type { ILogger } from 'elysia-mcp';
class MyCustomLogger implements ILogger {
info(message: string, ...args: unknown[]): void {
// Your custom implementation
}
error(message: string, ...args: unknown[]): void {
// Your custom implementation
}
warn(message: string, ...args: unknown[]): void {
// Your custom implementation
}
debug(message: string, ...args: unknown[]): void {
// Your custom implementation
}
}
const logger = new MyCustomLogger();
const app = new Elysia()
.use(
mcp({
logger,
// ... other options
})
)
.listen(3000);
Register tools using the MCP Server instance:
server.registerTool(
'tool-name',
{
description: 'Tool description',
inputSchema: {
param: z.string().describe('Parameter description'),
},
},
async (args) => {
// Tool implementation
return {
content: [{ type: 'text', text: 'Tool result' }],
};
}
);
Register resources for file or data access:
server.registerResource(
'resource-name',
'resource://uri',
{
title: 'Resource Name',
description: 'Resource description',
},
async () => {
return {
contents: [
{
uri: 'resource://uri',
mimeType: 'text/plain',
text: 'Resource content',
},
],
};
}
);
Register reusable prompt templates following MCP best practices:
server.registerPrompt(
'prompt-name',
{
title: 'Prompt Title',
description: 'Prompt description',
argsSchema: {
param: z.string().describe('Parameter description'),
},
},
async (args) => {
return {
description: 'Generated prompt',
messages: [
{
role: 'user',
content: {
type: 'text',
text: `Generated prompt with ${args.param}`,
},
},
],
};
}
);
Run the comprehensive test suite:
bun test
MIT - see LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
interface MCPPluginOptions {
/**
* Base path for MCP endpoints (default: '/mcp')
*/
basePath?: string;
/**
* Server information
*/
serverInfo?: {
name: string;
version: string;
};
/**
* MCP server capabilities
*/
capabilities?: ServerCapabilities;
/**
* @deprecated Use logger option instead
* Enable or disable logging
*/
enableLogging?: boolean;
/**
* Custom logger instance (pino, winston, etc.)
* If not provided and enableLogging is true, will use default console logger
*/
logger?: ILogger;
/**
* Enable JSON response mode instead of SSE streaming
*/
enableJsonResponse?: boolean;
/**
* Authentication handler
*/
authentication?: (
context: McpContext
) => Promise<{ authInfo?: AuthInfo; response?: unknown }>;
/**
* Setup function to configure the MCP server with tools, resources, and prompts
*/
setupServer?: (server: McpServer) => void | Promise<void>;
/**
* Enable stateless mode (no session management)
*/
stateless?: boolean;
/**
* Provide a custom MCP server instance
*/
mcpServer?: McpServer;
/**
* Event store for resumability support
*/
eventStore?: EventStore;
}
flowchart LR
A["HTTP Client"] --> B["Elysia HTTP Handler"]
B --> C["MCP Plugin"]
C --> D["McpServer<br/>(Singleton)"]
FAQs
ElysiaJS plugin for Model Context Protocol with HTTP transport and stateful sessions
We found that elysia-mcp demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
RubyGems and Bundler 4.0.13 introduced an opt-in cooldown feature that delays newly published gems during dependency resolution.

Security News
pnpm 11.5 now recognizes npm staged publish approvals in release metadata, preventing those releases from being mistaken for lower-trust package publishes.

Security News
Federal audit finds NIST lacked a plan to clear the NVD backlog, wasted funds on duplicate work, and delayed use of CISA data.