Skip to main content
Glama

Elysia MCP Plugin

⚠️ Under Development

A comprehensive ElysiaJS plugin for implementing Model Context Protocol (MCP) servers with HTTP transport support.

Features

  • HTTP Transport: Full HTTP-based MCP transport with Streamable HTTP

  • Session Management: Stateful session handling via headers

  • Type-Safe: Built with TypeScript and Zod validation

  • Easy Integration: Simple plugin architecture for Elysia apps

  • Comprehensive Support: Tools, Resources, Prompts, and Logging

  • Custom Logger Support: Use any logger (pino, winston, bunyan, etc.)

  • Error Handling: Proper JSON-RPC 2.0 error responses

  • Testing: Full unit test coverage with Bun test runner

Related MCP server: MCP Framework

Installation

bun add elysia-mcp # or npm install elysia-mcp

Starter Template

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:

  • Pre-configured Elysia setup with MCP plugin

  • TypeScript configuration

  • Development scripts

  • Basic project structure

  • Example MCP server implementation

Quick Start

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);

Usage

Running the Examples

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 numbers

    • multiply - Multiply two numbers

    • power - Calculate base to the power of exponent

  • Text Utilities Plugin (/text) - Text processing tools:

    • uppercase - Convert text to uppercase

    • word_count - Count words in text

    • reverse - Reverse text characters

    • replace - Replace text with global matching

Testing with MCP Inspector

  1. Install MCP Inspector:

    npx @modelcontextprotocol/inspector
  2. Connect to your server:

    • Basic Example: http://localhost:3000/mcp

    • Multiple Servers Example:

      • Math Plugin: http://localhost:3000/math

      • Text Plugin: http://localhost:3000/text

Configuration Options

  • serverInfo: Server information

  • capabilities: MCP capabilities to advertise

  • logger: Custom logger instance (pino, winston, etc.) - see Custom Logger section

  • setupServer: Callback to register tools, resources, and prompts

  • basePath: Base path for MCP endpoints (default: '/mcp')

  • enableJsonResponse: Enable JSON response mode instead of SSE streaming

  • stateless: Enable stateless mode (no session management)

  • authentication: Authentication handler for protected routes

  • eventStore: Event store for resumability support

Session Management

The plugin automatically handles session management via the Mcp-Session-Id header. Each session maintains its own state and can be terminated cleanly.

Modular Handler Architecture

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 */ }) );

Custom Logger

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; }

Using Pino Logger

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);

Using Winston Logger

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);

Default Console Logger

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);

Custom Logger Implementation

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);

API Reference

Tools

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' }], }; } );

Resources

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', }, ], }; } );

Prompts

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}`, }, }, ], }; } );

Testing

Run the comprehensive test suite:

bun test

License

MIT - see LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Related

Plugin Configuration

Plugin Options

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; }

Architecture

flowchart LR A["HTTP Client"] --> B["Elysia HTTP Handler"] B --> C["MCP Plugin"] C --> D["McpServer<br/>(Singleton)"]
-
security - not tested
A
license - permissive license
-
quality - not tested

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kerlos/elysia-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server