Hono MCP Server-Sent Events Transport

raw JSON →
0.0.7 verified Thu Apr 23 auth: no javascript

This package provides a Server-Sent Events (SSE) transport layer specifically designed for Hono applications to interface with a Model Context Protocol (MCP) server. As of version `0.0.7`, it offers a working solution to a known incompatibility: the official `@modelcontextprotocol/sdk` is primarily built for Express.js, leading to issues with Hono's response handling for SSE. This library acts as an interim solution, enabling developers to integrate MCP servers with Hono by correctly managing SSE connections and message routing. Releases are currently rapid patch/minor versions, indicating active development in its early stages. Its primary differentiator is bridging this specific framework gap, ensuring proper header and stream management for Hono-based MCP server implementations, including robust handling of multiple simultaneous connections via session IDs.

error No transport found for sessionId
cause The `sessionId` provided in a POST request did not match any active `SSETransport` in the server's `transports` lookup object.
fix
Verify that the client is sending the correct sessionId that corresponds to an established SSE connection. Ensure the server-side transports object correctly tracks and cleans up connections.
error TypeError: Cannot find module '@modelcontextprotocol/sdk'
cause The `@modelcontextprotocol/sdk` package is being imported incorrectly, likely missing the deep import path or the `.js` extension for ESM.
fix
Use the correct deep import path: import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
error TypeError: streamSSE is not a function
cause The `streamSSE` utility from Hono is imported from the main `hono` package instead of its specific submodule.
fix
Import streamSSE from the correct Hono submodule: import { streamSSE } from 'hono/streaming';
error ReferenceError: SSETransport is not defined
cause The `SSETransport` class was not imported correctly, likely due to using CommonJS `require` syntax in an ESM environment or a typo in the import.
fix
Ensure you are using import { SSETransport } from 'hono-mcp-server-sse-transport'; at the top of your TypeScript/ESM file.
gotcha This package is an interim solution designed to bridge an incompatibility between Hono and the official `@modelcontextprotocol/sdk`. It may become deprecated or obsolete once official Hono support is integrated into the SDK.
fix Monitor the `@modelcontextprotocol/sdk` repository for official Hono integration. Be prepared to migrate if official support is released.
breaking Version `0.0.5` introduced a fix for 'export destinations'. If you were relying on previously incorrect or internal module paths, this change might break your imports or module resolution.
fix Ensure all imports for `hono-mcp-server-sse-transport` use the direct, top-level named exports as shown in the documentation and examples (e.g., `import { SSETransport } from 'hono-mcp-server-sse-transport';`).
gotcha The management of `sessionId` and the `transports` object is manual in the quickstart example. Incorrect handling of session IDs or failure to clean up abandoned transports can lead to memory leaks or messages being routed to the wrong client.
fix Implement robust session management, including proper `onAbort` handlers to remove disconnected clients from the `transports` lookup, and consider strategies for handling stale or unclosed connections.
gotcha As of v0.0.7, a 'ping event' is sent before the 'endpoint event'. This changes the event order in the SSE stream, which could potentially affect clients expecting a different sequence of initial events.
fix Ensure your SSE client-side logic is resilient to the order of initial events or specifically handles a 'ping' event before other setup events.
npm install hono-mcp-server-sse-transport
yarn add hono-mcp-server-sse-transport
pnpm add hono-mcp-server-sse-transport

Demonstrates setting up a Hono server that acts as an MCP server, using SSE for client communication. It includes session management for multiple concurrent connections.

import { Hono } from 'hono';
import { serve } from '@hono/node-server';
import { streamSSE } from 'hono/streaming';
import { SSETransport } from 'hono-mcp-server-sse-transport';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';

const mcpServer = new McpServer(
  {
    name: 'your-mcp-server-name',
    version: '1.0.0'
  },
  {
    capabilities: {
      tools: {}
    }
  }
);

// here you add your tools
// ...

const app = new Hono();

// to support multiple simultaneous connections we have a lookup object from
// sessionId to transport
const transports: { [sessionId: string]: SSETransport } = {};

app.get('/sse', (c) => {
  return streamSSE(c, async (stream) => {
    const transport = new SSETransport('/messages', stream);

    transports[transport.sessionId] = transport;

    stream.onAbort(() => {
      delete transports[transport.sessionId];
    });

    await mcpServer.connect(transport);

    while (true) {
      // This will keep the connection alive
      // You can also await for a promise that never resolves
      await stream.sleep(60_000);
    }
  });
});

app.post('/messages', async (c) => {
  const sessionId = c.req.query('sessionId');
  const transport = transports[sessionId];

  if (transport == null) {
    return c.text('No transport found for sessionId', 400);
  }

  return await transport.handlePostMessage(c);
});

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