MCP Hub
Back to servers

mcp-honojs

A lightweight Hono.js middleware for building Model Context Protocol servers using a simple, fluent API and supporting both SSE and HTTP transports. It enables developers to create type-safe, edge-ready MCP-compatible APIs with built-in session management.

glama
Updated
Mar 18, 2026

mcp-honojs

Hono.js middleware for building Model Context Protocol (MCP) servers. Create MCP-compatible APIs with a simple, fluent interface — no decorators required.

Features

  • Simple fluent APIserver.tool(), server.resource(), server.prompt()
  • Multiple transports — SSE and HTTP (JSON-RPC 2.0)
  • Session management — Built-in session handling with automatic cleanup
  • Type-safe — Full TypeScript support with comprehensive types
  • Zero dependencies — Only peer dependency is Hono
  • Lightweight — Minimal footprint, perfect for edge deployments

Installation

npm install mcp-honojs hono

Quick Start

import { Hono } from 'hono';
import { McpServer } from 'mcp-honojs';

// Create MCP server
const mcp = new McpServer({
  name: 'my-mcp-server',
  version: '1.0.0',
});

// Register a tool
mcp.tool(
  {
    name: 'greet',
    description: 'Greet someone by name',
    inputSchema: {
      type: 'object',
      properties: {
        name: { type: 'string', description: 'Name to greet' },
      },
      required: ['name'],
    },
  },
  async (args) => {
    return {
      content: [{ type: 'text', text: `Hello, ${args.name}!` }],
    };
  }
);

// Create Hono app and attach MCP
const app = new Hono();
mcp.attach(app);

export default app;

Visit your endpoints:

  • SSE: GET /sse
  • HTTP: POST /mcp

API Reference

McpServer

Constructor

const mcp = new McpServer(options: McpServerOptions);

Options:

interface McpServerOptions {
  name: string;              // Server name
  version: string;           // Server version
  session?: {
    timeout?: number;        // Session timeout in ms (default: 30min)
    cleanupInterval?: number; // Cleanup interval in ms (default: 5min)
    maxSessions?: number;     // Max concurrent sessions (default: 1000)
  };
}

Methods

tool(options, handler) — Register a tool

mcp.tool(
  {
    name: 'add',
    description: 'Add two numbers',
    inputSchema: {
      type: 'object',
      properties: {
        a: { type: 'number' },
        b: { type: 'number' },
      },
      required: ['a', 'b'],
    },
  },
  async (args, context) => {
    return {
      content: [
        { type: 'text', text: `Result: ${args.a + args.b}` }
      ],
    };
  }
);

resource(options, handler) — Register a resource

mcp.resource(
  {
    uri: 'example://data',
    name: 'example-data',
    description: 'Example data resource',
    mimeType: 'application/json',
  },
  async (uri, context) => {
    return {
      contents: [
        {
          uri,
          mimeType: 'application/json',
          text: JSON.stringify({ data: 'example' }),
        },
      ],
    };
  }
);

prompt(options, handler) — Register a prompt

mcp.prompt(
  {
    name: 'welcome',
    description: 'Welcome prompt',
    arguments: [
      { name: 'username', description: 'User name', required: true }
    ],
  },
  async (args, context) => {
    return {
      messages: [
        {
          role: 'user',
          content: {
            type: 'text',
            text: `Welcome, ${args.username}!`,
          },
        },
      ],
    };
  }
);

attach(app, transportOptions?) — Attach transports to Hono app

mcp.attach(app, {
  ssePath: '/sse',    // SSE endpoint (default: /sse)
  httpPath: '/mcp',   // HTTP endpoint (default: /mcp)
});

sseMiddleware(path?) — Get SSE middleware

app.use(mcp.sseMiddleware('/custom-sse'));

httpMiddleware(path?) — Get HTTP middleware

app.use(mcp.httpMiddleware('/custom-mcp'));

Context

Both tool and resource handlers receive a McpContext object:

interface McpContext {
  sessionId?: string;        // Current session ID
  honoContext?: Context;     // Hono request context
  metadata?: Record<string, any>; // Custom metadata
}

Access the Hono context for request details:

mcp.tool({ /* ... */ }, async (args, context) => {
  const userAgent = context.honoContext?.req.header('user-agent');
  // ...
});

Type Definitions

Tool Types

interface ToolResult {
  content: ToolResultContent[];
  isError?: boolean;
}

interface ToolResultContent {
  type: 'text' | 'image' | 'resource';
  text?: string;
  data?: string;          // Base64 for images
  mimeType?: string;
  uri?: string;           // For resource references
}

Resource Types

interface ResourceResult {
  contents: ResourceContent[];
}

interface ResourceContent {
  uri: string;
  mimeType?: string;
  text?: string;
  blob?: string;          // Base64 encoded binary
}

Prompt Types

interface PromptResult {
  description?: string;
  messages: PromptMessage[];
}

interface PromptMessage {
  role: 'user' | 'assistant';
  content: PromptMessageContent;
}

JSON-RPC Protocol

The server implements MCP's JSON-RPC 2.0 protocol.

Supported Methods

  • initialize — Initialize connection
  • tools/list — List available tools
  • tools/call — Execute a tool
  • resources/list — List resources
  • resources/templates/list — List resource templates
  • resources/read — Read a resource
  • prompts/list — List prompts
  • prompts/get — Get a prompt
  • ping — Health check

Example Requests

Initialize:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize"
}

Call a tool:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "greet",
    "arguments": { "name": "Alice" }
  }
}

Session Management

Sessions are automatically managed:

  • Created on first request
  • Returned in x-session-id header (HTTP) or endpoint event (SSE)
  • Auto-expire after timeout (default: 30 minutes)
  • Cleaned up periodically (default: every 5 minutes)

HTTP: Pass session ID in x-session-id header SSE: Session is bound to the connection

Examples

See the examples/ directory for complete examples:

  • basic.ts — Simple calculator and greeting tools
  • More examples coming soon!

Run examples:

cd examples
npm install
npm run dev

Comparison with mcp-nestjs

Featuremcp-honojsmcp-nestjs
FrameworkHono.jsNestJS
API StyleFluent/functionalDecorator-based
DI Container❌ (not needed)✅ (NestJS)
Auto-discovery
Edge-readyDepends
Bundle sizeTinyLarger
Use caseAPIs, edge, serverlessEnterprise apps

Deployment

Node.js

import { serve } from '@hono/node-server';
import app from './app';

serve({ fetch: app.fetch, port: 3000 });

Cloudflare Workers

export default app;

Deno

import { serve } from 'https://deno.land/std/http/server.ts';
serve(app.fetch);

Bun

export default {
  fetch: app.fetch,
  port: 3000,
};

Contributing

Contributions welcome! Please open an issue or PR.

License

MIT © zahidhasanaunto

Resources

Reviews

No reviews yet

Sign in to write a review