loading…
Search for a command to run...
loading…
ElysiaJS plugin for Model Context Protocol with HTTP transport and stateful sessions
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)"]
Добавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"elysia-mcp": {
"command": "npx",
"args": [
"-y",
"elysia-mcp"
]
}
}
}PRs, issues, code search, CI status
Database, auth and storage
Reference / test server with prompts, resources, and tools.
Secure file operations with configurable access controls.