# Elysia Mcp

> ElysiaJS plugin for Model Context Protocol with HTTP transport

- **Type:** MCP server
- **Install:** `agentstack add mcp-kerlos-elysia-mcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [kerlos](https://agentstack.voostack.com/s/kerlos)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [kerlos](https://github.com/kerlos)
- **Source:** https://github.com/kerlos/elysia-mcp

## Install

```sh
agentstack add mcp-kerlos-elysia-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Elysia MCP Plugin 

A comprehensive ElysiaJS plugin for implementing
[Model Context Protocol (MCP)](https://modelcontextprotocol.io/) 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

## Installation

```bash
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:

```bash
# 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](https://github.com/kerlos/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

```typescript
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:**

```bash
# Run the basic example server (port 3000)
bun run example

# Or with development mode (auto-restart)
bun run dev
```

**Multiple Servers Example:**

```bash
# 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:

   ```bash
   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](#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:

```typescript
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:

```typescript
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

```typescript
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

```typescript
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`:

```typescript
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:

```typescript
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:

```typescript
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:

```typescript
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:

```typescript
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:

```bash
bun test
```

## License

MIT - see [LICENSE](./LICENSE) file for details.

## Contributing

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

## Related

- [Model Context Protocol](https://modelcontextprotocol.io/)
- [ElysiaJS](https://elysiajs.com/)
- [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)

## Plugin Configuration

### Plugin Options

```typescript
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;

  /**
   * Setup function to configure the MCP server with tools, resources, and prompts
   */
  setupServer?: (server: McpServer) => void | Promise;

  /**
   * Enable stateless mode (no session management)
   */
  stateless?: boolean;

  /**
   * Provide a custom MCP server instance
   */
  mcpServer?: McpServer;

  /**
   * Event store for resumability support
   */
  eventStore?: EventStore;
}
```

## Architecture

```mermaid
flowchart LR
    A["HTTP Client"] --> B["Elysia HTTP Handler"]
    B --> C["MCP Plugin"]
    C --> D["McpServer(Singleton)"]
```

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [kerlos](https://github.com/kerlos)
- **Source:** [kerlos/elysia-mcp](https://github.com/kerlos/elysia-mcp)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-kerlos-elysia-mcp
- Seller: https://agentstack.voostack.com/s/kerlos
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
