Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Reverse

FreeMaintained

Reverse transports for MCP (Model Context Protocol) — SSE engine. Allows internal MCP servers behind NAT/firewall to connect out to public MCP clients.

GitHubEmbed

About

Reverse transports for MCP (Model Context Protocol) — SSE engine. Allows internal MCP servers behind NAT/firewall to connect out to public MCP clients.

README

Reverse transports for MCP — SSE engine.
Let internal MCP servers behind NAT/firewall connect OUT to your public client.

The Problem

Standard MCP transports are client-initiated: the Client must reach the Server's address.

Client (public) ───connect───> Server (public)   ✅ works
Client (public) ───connect───X Server (NAT)       ❌ unreachable

mcp-reverse flips the direction at the transport layer. The internal MCP Server initiates the connection; the public MCP Client accepts it. The MCP protocol then runs normally over the established channel.

Public Client (chat-ai) <───incoming──── Internal Server (behind NAT)       ✅ works

Features

Feature Support
NAT traversal
Authentication (token + custom handler)
Keepalive / heartbeat ✅ SSE comments
Auto-reconnect (exponential backoff + jitter)
TLS / HTTPS
Tools / Resources / Prompts
Notifications (both directions)
Next.js / Vercel / serverless

Install

npm install mcp-reverse

Requires @modelcontextprotocol/sdk as peer dependency.


Quick Start — SSE

Public Side (chat-ai / Next.js App Router)

import { SSEAcceptor } from 'mcp-reverse';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';

const acceptor = new SSEAcceptor({
  authTokens: { 'office-server': 'secret123' },
});

acceptor.onConnection(async ({ transport, metadata }) => {
  console.log(`Server connected: ${metadata.serverName}`);

  const client = new Client(
    { name: 'chat-ai', version: '1.0.0' },
    { capabilities: {} }
  );
  await client.connect(transport);

  // Use client normally
  const tools = await client.listTools();
  const result = await client.callTool({ name: 'exec', arguments: { cmd: 'ls' } });
});

acceptor.onDisconnection((serverName) => console.log(`Disconnected: ${serverName}`));

// ─── Next.js App Router integration ───
export async function GET(req: NextRequest) {
  return acceptor.handleSSE(req);
}
export async function POST(req: NextRequest) {
  return acceptor.handleMessage(req);
}

Or run standalone (creates its own HTTP server):

const acceptor = new SSEAcceptor({ port: 3400, authTokens: { ... } });
await acceptor.start();  // listens on http://0.0.0.0:3400/mcp-reverse

Internal Side (behind NAT)

import { SSEReverseClientTransport } from 'mcp-reverse';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';

const transport = new SSEReverseClientTransport({
  url: 'https://public-chatai.example.com:3000/mcp-reverse',
  serverName: 'office-server',
  authToken: 'secret123',
  reconnect: { enabled: true },
});

const server = new McpServer({ name: 'office-server', version: '1.0.0' });
server.tool('greet', 'Greet someone', { name: z.string() },
  async ({ name }) => ({ content: [{ type: 'text', text: `Hello, ${name}!` }] })
);

await server.connect(transport);

High-Level Client (recommended)

import { ReverseMCPClient } from 'mcp-reverse/connector';

const client = await ReverseMCPClient.createSSE(server, {
  url: 'https://public-host.example.com:3000/mcp-reverse',
  serverName: 'office-server',
  authToken: 'secret123',
  reconnect: { enabled: true, maxDelay: 30000 },
});

client.on('connected', () => console.log('Connected'));
client.on('disconnected', () => console.log('Disconnected'));
client.on('reconnecting', (attempt) => console.log(`Reconnecting (${attempt})`));

API Reference

SSEAcceptor (Public Side)

new SSEAcceptor(options: SSEAcceptorOptions | SSEAcceptorStandaloneOptions)
Option Type Default Notes
authTokens Record<string, string> serverName → token map
authHandler async (meta) => boolean Custom auth logic
heartbeat SSEHeartbeatOptions {enabled:true} Keepalive
maxMessageSize number 4MB POST body limit
sessionTimeout number 60000 Inactivity timeout (ms)
pathPrefix string /mcp-reverse URL prefix
port number Standalone only: listen port

SSEReverseClientTransport (Internal Side)

new SSEReverseClientTransport(options: SSEReverseClientTransportOptions)
Option Type Default Notes
url string required Base URL
serverName string required Server identifier
authToken string Bearer token
reconnect ReconnectOptions {enabled:true} Auto-reconnect
heartbeat SSEHeartbeatOptions {enabled:true} Keepalive
headers Record<string, string> Extra headers
insecureTls boolean false Skip TLS verify
queryParams Record<string, string> Extra query params

Reconnect Options

{
  enabled?: boolean;       // default: true
  initialDelay?: number;   // default: 1000ms
  maxDelay?: number;       // default: 30000ms
  multiplier?: number;     // default: 2
  jitter?: boolean;        // default: true
  maxRetries?: number;     // default: 0 (infinite)
}

Project Structure

src/
├── protocol/                # Protocol-level abstractions
│   ├── types.ts             # All type definitions
│   └── reconnect.ts         # Exponential backoff reconnection
├── acceptor/
│   └── sse-acceptor.ts      # SSEAcceptor (public side)
├── connector/
│   ├── mcp-connector.ts     # ReverseMCPClient (high-level)
│   └── sse-connector.ts     # SSEReverseClientTransport (internal side)
├── transport/
│   ├── sse-transport.ts     # SSEConnectionTransport
│   └── sse-util.ts          # SSE parsing/formatting utilities
├── proxy/
│   └── reverse-proxy.ts     # ReverseProxy / gateway
└── index.ts                 # Main entry point

Sub-path exports

Export path Description
mcp-reverse Main entry — all types
mcp-reverse/connector High-level ReverseMCPClient
mcp-reverse/acceptor SSEAcceptor
mcp-reverse/sse Backward compat — all SSE types
mcp-reverse/transport SSEConnectionTransport, SSE utilities
mcp-reverse/proxy ReverseProxy

Testing

npm test                   # All 43 tests (unit + integration)
npm run build              # TypeScript compilation

License

MIT

from github.com/ChineseAStar/mcp-reverse

Install Reverse in Claude Desktop, Claude Code & Cursor

Recommended · one command, every IDE
unyly install reverse

Installs into Claude Desktop, Claude Code, Cursor & VS Code — handles npx, uvx and build-from-source repos for you.

First time? Get the CLI: curl -fsSL https://unyly.org/install | sh

Or configure manually

Run in your terminal:

claude mcp add reverse -- npx -y mcp-reverse

FAQ

Is Reverse MCP free?

Yes, Reverse MCP is free — one-click install via Unyly at no cost.

Does Reverse need an API key?

No, Reverse runs without API keys or environment variables.

Is Reverse hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Reverse in Claude Desktop, Claude Code or Cursor?

Open Reverse on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Reverse with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All development MCPs