wmcp

wmcp

Provides transport/wiring layer for running Model Context Protocol servers, supporting stdio, Streamable HTTP, and legacy SSE, with example and optional personas server for prompts.

Category
Visit Server

README

wmcp

MCP exposure infrastructure — how to run Model Context Protocol servers so Cursor, Claude Desktop, and Claude Code can reach them from WSL, Windows, or macOS.

This repo is the transport/wiring layer, plus an optional personas server (compose / list_prompts). It also ships a tiny example server (echo / ping) so you can verify the plumbing. Bring your own tools and prompt packs.

Requires Node.js ≥ 18.

What an MCP server is (short version)

An MCP server is a process that speaks Model Context Protocol — JSON-RPC messages describing tools, prompts, and/or resources. Clients (Cursor, Claude) call those tools during a chat.

The interesting part is not the tools themselves. It is how the client connects:

Transport Who speaks it How it runs
stdio Cursor (local), Claude Desktop Client spawns node dist/….js and talks over stdin/stdout
Streamable HTTP Cursor, Claude Desktop (URL mode) One long-lived Node HTTP server; client POSTs to http://host:port/<name>
Legacy SSE Claude Code CLI Same HTTP server; GET /<name>/sse + POST /<name>/message

wmcp implements all three from one codebase.

┌─────────────────┐     stdio      ┌──────────────────┐
│ Cursor / Claude │ ◄────────────► │ example-server   │  (per-process)
│   (local spawn) │                │ or stdio-bridge  │
└─────────────────┘                └──────────────────┘

┌─────────────────┐   HTTP/SSE     ┌──────────────────┐
│ Cursor / Claude │ ◄────────────► │   http-server    │──► example
│   (URL mode)    │                │   :8820          │──► personas (opt)
└─────────────────┘                └──────────────────┘

Typical setup when the real Node runtime lives in WSL:

  1. Run http-server inside WSL (systemd user unit or npm start).
  2. Point Windows/mac Cursor at http://localhost:8820/example (WSL localhost forwarding).
  3. Or, for stdio-only clients on Windows: wsl.exe … node dist/example-server.js.

On macOS / native Linux, skip the wsl.exe path — run Node locally and point Cursor at http://localhost:8820/<server> or a direct node dist/….js stdio command.

Quick start

git clone https://github.com/mwhobrey/wmcp.git
cd wmcp
npm install
npm run build
npm start                    # HTTP front door on :8820
curl http://localhost:8820/health

stdio smoke test (separate terminal):

node dist/example-server.js
# or: node dist/stdio-bridge.js example

Wire Cursor

If transport is "sse" (the default in the example config), start the HTTP server first (npm start) and leave it running. Cursor connects to URLs; nothing is listening otherwise.

Option A — paste a minimal entry (safest; does not touch other MCP servers):

{
  "mcpServers": {
    "example": {
      "url": "http://localhost:8820/example"
    }
  }
}

Add that under your existing mcpServers in Cursor's MCP config, then reload MCP and call ping on example.

For stdio instead of HTTP:

{
  "mcpServers": {
    "example": {
      "command": "node",
      "args": ["/absolute/path/to/wmcp/dist/example-server.js"]
    }
  }
}

Option B — generate configs from this repo (WSL + Windows):

Warning: npm run sync:mcp overwrites ~/.cursor/mcp.json and, when /mnt/c is present, C:\Users\<windowsUser>\.cursor\mcp.json. Back up first if you already have other servers configured.

  1. Copy and edit config:

    cp config/mcp-servers.example.json config/mcp-servers.json
    # set projectRoot, nodePath, wslUser, windowsUser
    
  2. With the HTTP server running (for "transport": "sse"):

    npm run sync:mcp
    
  3. Reload MCP in Cursor. Call the ping tool on the example server.

transport in mcp-servers.json:

  • "sse" (default) → Cursor entries are { "url": "http://localhost:8820/example" }http-server must be up
  • "stdio" → Cursor spawns Node (or wsl.exe on Windows) — no shared HTTP process needed

Optional: personas server

Markdown prompt packs with hot reload. Tools:

Tool Purpose
compose Merge layers into one system prompt (see order below)
list_prompts List loaded prompts by category

Also exposes MCP prompts (list / get) for clients that use that capability.

Compose merge order (each layer optional except when base is left on):

  1. base (personas/base) — omitted if base: false
  2. team — repo/org policy card
  3. persona — role
  4. skill — mode
  5. script — playbook

Sections are joined with ---. Template args apply to every included layer.

Enable on the HTTP front door:

cp env.example .env   # then set WMCP_ENABLE_PERSONAS=1
# PERSONAS_DIR=/absolute/path/to/prompts   # optional; default ./prompts

npm start
# → http://localhost:8820/personas

Cursor URL entry:

{
  "mcpServers": {
    "personas": {
      "url": "http://localhost:8820/personas"
    }
  }
}

Or run stdio directly (no WMCP_ENABLE_PERSONAS required):

npm run start:personas
# or: node dist/stdio-bridge.js personas

Sample prompts ship under prompts/ (personas/, skills/, scripts/, teams/). Replace them with your own — edits hot-reload; no restart needed.

Frontmatter shape:

---
name: engineer
description: Short description for list_prompts
category: persona
args:
  - name: stack
    description: Primary tech stack
    required: false
---

# Role: Engineer

{{stack}}Primary stack: {{stack}}.{{/stack}}

Template syntax: {{var}}, {{var|default}}, and {{var}}…{{/var}} (block omitted when unset).

Adding your own MCP server

  1. Create src/my-server.ts — construct an MCP Server, register tools, expose getServer().
  2. Register a factory in src/registry.ts.
  3. Add a servers.my entry in config/mcp-servers.json with "script": "my-server.js".
  4. npm run build && npm run sync:mcp (and restart http-server if using URL mode).

The HTTP and stdio layers stay unchanged. They only need a name → () => Server factory.

Layout

src/
  example-server.ts   # reference MCP tools (echo, ping)
  personas-server.ts  # optional compose / list_prompts
  registry.ts         # name → factory map (+ env toggles)
  http-server.ts      # Streamable HTTP + legacy SSE multiplexer
  stdio-bridge.ts     # named stdio launcher
  env-flags.ts
  is-main-module.ts
prompts/              # sample prompt pack (swap for yours)
config/
  mcp-servers.example.json
scripts/
  sync-mcp-config.mjs
  fix-permissions.mjs
systemd/
  wmcp.service

Environment

Variable Default Purpose
MCP_PORT 8820 HTTP listen port
MCP_SSE_PING_MS 30000 SSE keep-alive comment interval (0 disables)
WMCP_ENABLE_PERSONAS off Register personas on the HTTP front door (1/true/yes/on)
PERSONAS_DIR ./prompts Markdown prompt root (personas/, skills/, scripts/, teams/)

See env.example. Load via .env in the project root (dotenv) or export in the shell / systemd unit.

systemd (optional)

# edit User / paths in systemd/wmcp.service first
mkdir -p ~/.config/systemd/user
cp systemd/wmcp.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now wmcp
systemctl --user status wmcp

To enable personas under systemd, set WMCP_ENABLE_PERSONAS=1 in .env (or Environment= in the unit).

Design notes

  • One HTTP process, many logical servers — routes by path prefix; each request gets a fresh MCP Server instance for Streamable HTTP (stateless).
  • Fail per server at boot — a broken factory is skipped; others still serve.
  • Personas are optional — off by default so the public repo stays a transport template; flip the env when you want compose/list_prompts on HTTP. Direct npm run start:personas always works.
  • Private prompt packs stay private — point PERSONAS_DIR at an external directory, or replace prompts/ locally and don't commit company content.

License

MIT

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured