npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ebowwa/mcp-transport

v0.2.0

Published

Unified MCP server transport - switch between stdio, HTTP, CLI, WebSocket, and Webhook at runtime

Readme

@ebowwa/mcp-transport

Unified MCP server transport - switch between stdio, HTTP, CLI, REST, WebSocket, and Webhook at runtime.

Why?

Every MCP server currently hardcodes its transport mode. This package provides a unified API so you can:

  1. Develop with HTTP - Test your MCP server in a browser or with curl
  2. Deploy with stdio - Run in production with Claude Desktop
  3. Test with CLI - Invoke tools directly from command line
  4. Expose as REST - Provide pure REST API with OpenAPI spec
  5. Real-time with WebSocket - Full-duplex communication
  6. Notify with Webhook - Push events to external systems
  7. Switch with env vars - No code changes needed

Installation

bun add @ebowwa/mcp-transport

Quick Start

import { createAndStartServer } from '@ebowwa/mcp-transport';

// Define your tools
const tools = [
  {
    name: 'echo',
    description: 'Echo a message back',
    inputSchema: {
      type: 'object',
      properties: {
        message: { type: 'string', description: 'Message to echo' },
      },
      required: ['message'],
    },
    handler: async ({ message }) => {
      return { content: [{ type: 'text', text: message }] };
    },
  },
];

// Start server - transport mode determined by env vars
const running = await createAndStartServer({
  config: { name: 'my-server' },
  tools,
});

// Graceful shutdown
process.on('SIGINT', async () => {
  await running.shutdown();
});

Transport Modes

| Mode | Use Case | Command | |------|----------|---------| | stdio | Claude Desktop, IDEs (default) | bun run server.ts | | http | Web clients, SSE streaming | MCP_TRANSPORT=http bun run server.ts | | cli | Direct tool invocation, testing | mcp-transport --module ./server.js --invoke echo | | rest | REST API consumers | MCP_TRANSPORT=rest bun run server.ts | | websocket | Real-time apps, low-latency | MCP_TRANSPORT=websocket bun run server.ts | | webhook | Event notifications, integrations | MCP_TRANSPORT=webhook bun run server.ts |

Environment Variables

Core Variables

| Variable | Default | Description | |----------|---------|-------------| | MCP_TRANSPORT | stdio | Transport mode: stdio, http, sse, cli, rest, websocket, webhook | | MCP_PORT | 3000 | HTTP/WebSocket port | | MCP_HOST | localhost | Server host | | MCP_SERVER_NAME | mcp-server | Server name for handshake | | MCP_SERVER_VERSION | 1.0.0 | Server version |

REST Mode Variables

| Variable | Default | Description | |----------|---------|-------------| | MCP_REST_BASE_PATH | /api | REST API base path | | MCP_REST_AUTH_TYPE | none | Auth type: bearer, basic, api-key, oauth2 | | MCP_REST_API_KEY | - | API key value | | MCP_REST_BEARER_TOKEN | - | Bearer token | | MCP_REST_RATE_LIMIT | false | Enable rate limiting | | MCP_REST_RATE_LIMIT_MAX | 100 | Max requests per window | | MCP_REST_OPENAPI | true | Generate OpenAPI spec |

WebSocket Mode Variables

| Variable | Default | Description | |----------|---------|-------------| | MCP_WS_PATH | /ws | WebSocket endpoint path | | MCP_WS_HEARTBEAT | 30000 | Heartbeat interval (ms) | | MCP_WS_MAX_MESSAGE_SIZE | 1048576 | Max message size (bytes) | | MCP_WS_COMPRESSION | false | Enable compression |

Webhook Mode Variables

| Variable | Default | Description | |----------|---------|-------------| | MCP_WEBHOOK_SECRET | - | HMAC-SHA256 signing secret | | MCP_WEBHOOK_OUTBOUND_URL | - | Webhook destination URL | | MCP_WEBHOOK_RETRY_ENABLED | true | Enable retry mechanism | | MCP_WEBHOOK_RETRY_MAX | 3 | Max retry attempts | | MCP_WEBHOOK_EVENTS | tool.called,tool.completed,tool.failed | Events to emit |

Usage Examples

Stdio Mode (Default)

# Run in stdio mode
bun run server.ts

# Claude Desktop config
{
  "mcpServers": {
    "my-server": {
      "command": "bun",
      "args": ["run", "server.ts"]
    }
  }
}

HTTP Mode

# Run in HTTP mode
MCP_TRANSPORT=http MCP_PORT=3000 bun run server.ts

# Test with curl
curl http://localhost:3000/health
# {"status":"ok","sessions":0,"transport":"http-sse"}

CLI Mode

Direct tool invocation without running a server:

# List available tools
mcp-transport --module ./dist/server.js --list-tools

# Output:
# Available tools:
#   echo
#     Echo a message back

# Invoke a tool directly
mcp-transport --module ./dist/server.js --invoke echo --input '{"message":"hello"}'

# Output (JSON):
# {"content":[{"type":"text","text":"hello"}]}

# Interactive REPL mode
mcp-transport --module ./dist/server.js --interactive

# mcp> list
# mcp> invoke echo {"message":"test"}
# mcp> exit

REST Mode

Pure REST API with OpenAPI specification:

# Start REST server
MCP_TRANSPORT=rest MCP_PORT=3000 bun run server.ts

# List all tools
curl http://localhost:3000/api/tools

# Get tool schema
curl http://localhost:3000/api/tools/echo

# Invoke tool
curl -X POST http://localhost:3000/api/tools/echo/invoke \
  -H "Content-Type: application/json" \
  -d '{"message":"hello"}'

# Get OpenAPI specification
curl http://localhost:3000/api/openapi.json

# Health check
curl http://localhost:3000/api/health

REST Endpoints

| Method | Path | Description | |--------|------|-------------| | GET | /api/tools | List all tools | | GET | /api/tools/:name | Get tool schema | | POST | /api/tools/:name/invoke | Invoke a tool | | GET | /api/resources | List resources | | GET | /api/resources/* | Read resource | | GET | /api/prompts | List prompts | | POST | /api/prompts/:name/render | Render prompt | | GET | /api/health | Health check | | GET | /api/openapi.json | OpenAPI specification |

WebSocket Mode

Full-duplex communication with NDJSON protocol:

# Start WebSocket server
MCP_TRANSPORT=websocket MCP_PORT=3000 bun run server.ts

# Connect with wscat
wscat -c ws://localhost:3000/ws

NDJSON Protocol

Messages are newline-delimited JSON:

// Request (requires response)
{"id": "req-1", "type": "request", "method": "tools/call", "params": {"name": "echo", "arguments": {"message": "hi"}}}

// Response
{"id": "req-1", "type": "response", "result": {"content": [{"type": "text", "text": "hi"}]}}

// Notification (no response)
{"type": "notification", "method": "notifications/message", "params": {"level": "info", "data": "Hello"}}

Webhook Mode

Push notifications to external URLs:

# Start webhook transport
MCP_TRANSPORT=webhook \
  MCP_WEBHOOK_SECRET=whsec_xxx \
  MCP_WEBHOOK_OUTBOUND_URL=https://example.com/webhook \
  bun run server.ts

Webhook Events

| Event | Description | |-------|-------------| | tool.called | Tool invocation started | | tool.completed | Tool finished successfully | | tool.failed | Tool failed with error | | resource.updated | Resource changed |

Webhook Payload

{
  "type": "tool.completed",
  "timestamp": "2026-02-24T21:30:00.000Z",
  "sessionId": "sess-abc123",
  "eventId": "evt_xyz123",
  "data": {
    "toolName": "echo",
    "result": {"content": [{"type": "text", "text": "hello"}]},
    "durationMs": 15
  }
}

Signature Verification

import { verifySignature } from '@ebowwa/mcp-transport/webhook';

const payload = JSON.stringify(webhookBody);
const signature = req.headers['x-webhook-signature'];

if (verifySignature(payload, signature, 'whsec_xxx')) {
  // Valid webhook
}

Using Zod Schemas

import { createAndStartServer } from '@ebowwa/mcp-transport';
import { z } from 'zod';

await createAndStartServer({
  tools: [{
    name: 'add',
    description: 'Add two numbers',
    inputSchema: z.object({
      a: z.number().describe('First number'),
      b: z.number().describe('Second number'),
    }),
    handler: async ({ a, b }) => ({ result: a + b }),
  }],
});

Custom Express Integration

import express from 'express';
import { createMCPExpressApp, createMCPServer } from '@ebowwa/mcp-transport';

const app = express();

// Your existing routes
app.get('/api/data', (req, res) => res.json({ data: 'hello' }));

// Add MCP routes to existing app
const serverFactory = () => createMCPServer({
  tools: [...],
});

const { app: mcpApp, sessions } = createMCPExpressApp(serverFactory, {
  expressApp: app,
  sseEndpoint: '/mcp/sse',
  messagesEndpoint: '/mcp/messages',
});

app.listen(3000);

Resources and Prompts

import { createAndStartServer } from '@ebowwa/mcp-transport';

await createAndStartServer({
  config: { name: 'resource-server' },
  tools: [...],
  resources: [
    {
      uriTemplate: 'file://config/{path}',
      name: 'config',
      description: 'Access config files',
      mimeType: 'application/json',
      handler: async (uri, params) => ({
        contents: [{
          uri: uri.href,
          text: JSON.stringify({ setting: params.path }),
        }],
      }),
    },
  ],
  prompts: [
    {
      name: 'greeting',
      description: 'Generate a greeting',
      arguments: [
        { name: 'name', description: 'Person to greet', required: true },
      ],
      handler: async ({ name }) => ({
        messages: [{
          role: 'user',
          content: { type: 'text', text: `Hello, ${name}!` },
        }],
      }),
    },
  ],
});

API Reference

createAndStartServer(definition)

Create and start an MCP server with automatic transport selection.

interface MCPServerDefinition {
  config?: MCPTransportConfig;
  tools?: MCPToolDefinition[];
  resources?: MCPResourceDefinition[];
  prompts?: MCPPromptDefinition[];
  setup?: (server: McpServer) => void | Promise<void>;
}

createMCPServer(definition)

Create an MCP server instance without starting transport.

Transport Functions

| Function | Description | |----------|-------------| | startStdioTransport(server, config) | Start with stdio transport | | startHttpTransport(serverFactory, config) | Start with HTTP/SSE transport | | startCLITransport(serverFactory, config) | Start with CLI transport | | startRESTTransport(serverFactory, config) | Start with REST transport | | startWebSocketTransport(serverFactory, config) | Start with WebSocket transport | | startWebhookTransport(serverFactory, config) | Start with Webhook transport | | createMCPExpressApp(serverFactory, config) | Create Express app with MCP routes |

CLI Commands

mcp-transport --module <path> [options]

Options:
  --module, -m <path>   Path to server module
  --name, -n <name>     Server name
  --list-tools, -l      List available tools
  --invoke, -i <name>   Invoke a tool
  --input <json>        JSON input for tool
  --interactive, -I     Start interactive REPL
  --json, -j            Output as JSON
  --mode <transport>    Transport mode
  --help, -h            Show help

License

MIT