mcp-doorman

mcp-doorman

A drop-in proxy that guards MCP servers with policy enforcement, secret redaction, prompt-injection screening, rug-pull detection, rate limiting, and audit logging.

Category
访问服务器

README

mcp-doorman

The security gateway for MCP servers — every tool call gets checked at the door.

CI npm License: Apache-2.0 PRs welcome

mcp-doorman is a drop-in proxy that sits between your AI agent (Claude Desktop, Claude Code, Cursor, VS Code, any MCP client) and the MCP servers it uses. One command, zero infrastructure, and every tools/list and tools/call passes through a guard pipeline:

  • 🛂 Policy engine — allow / deny / require-approval rules per tool, glob-matched
  • 🕵️ Secret redaction — AWS keys, GitHub/Slack/Stripe/OpenAI/Anthropic tokens, private keys, JWTs, cards (Luhn-checked)… scrubbed from tool results before they reach the model
  • 💉 Prompt-injection screening — flags or blocks tool results (and tool descriptions — tool poisoning) that try to instruct the model
  • 📌 Rug-pull detection — tool definitions are hash-pinned on first use; if a server silently swaps a description, the tool is blocked until a human re-pins it
  • 🚦 Rate limiting — per-tool token buckets cap the blast radius of a runaway agent loop
  • 🙋 Human approval gates — sensitive tools trigger an interactive approval prompt via MCP elicitation, right in your client
  • 🧾 Audit log — every call, denial, redaction, and flag lands in an append-only JSONL file

Why this exists

Everyone is one npx some-random-mcp-server away from handing an unvetted process their API keys and a direct line into their model's context window. The documented attack classes are real, not hypothetical:

Attack How it works
Tool poisoning Malicious instructions hidden in a tool's description, invisible in most client UIs
Rug pull Server presents innocent tools on day 1, swaps the definitions after you've approved them
Indirect prompt injection A webpage/issue/email fetched by a legitimate tool carries instructions aimed at the model
Secret exfiltration A leaked credential in one tool result + one injected instruction = your key on someone else's server
Runaway loops A confused or hijacked agent mass-deletes, mass-mails, mass-scrapes

Enterprise MCP gateways exist for platform teams with Kubernetes clusters. Nothing lightweight guards the individual developer's laptop — the place where 99% of MCP servers actually run. That's the gap this project fills.

Quickstart (60 seconds)

# 1. Create a config
npx -y mcp-doorman init

# 2. Edit doorman.config.json — put your real servers in it

# 3. Pin the current tool definitions (trust on first use)
npx -y mcp-doorman pin --config doorman.config.json

Then point your client at the gateway instead of your servers. Claude Desktop / Claude Code / Cursor:

// BEFORE — every server talks straight to the model
{
  "mcpServers": {
    "github":     { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"] },
    "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/repos"] }
  }
}

// AFTER — one doorman guards them all
{
  "mcpServers": {
    "doorman": {
      "command": "npx",
      "args": ["-y", "mcp-doorman", "run", "--config", "/absolute/path/to/doorman.config.json"]
    }
  }
}

Tools show up namespaced as github__create_issue, filesystem__read_file, etc., plus two built-ins: doorman__status and doorman__recent_events (ask your agent "what did doorman block recently?").

Windows note: if a server entry uses npx directly, spawn it through cmd: "command": "cmd", "args": ["/c", "npx", "-y", "..."].

See it work

git clone https://github.com/Sushank05/mcp-doorman && cd mcp-doorman
npm install
npm run demo

The demo wires the gateway to a deliberately misbehaving server (examples/demo-server.mjs) that leaks fake credentials, serves a prompt-injection payload, and offers a destructive tool — and shows each guard catching it.

How it works

flowchart LR
    A["MCP client\n(Claude Desktop, Cursor, ...)"] -- stdio --> D
    subgraph D [mcp-doorman]
        direction TB
        P[policy] --> R[rate limit] --> AP[approval] --> RD[redaction] --> I[injection scan] --> AU[(audit log)]
    end
    D -- stdio --> S1[github server]
    D -- stdio --> S2[filesystem server]
    D -- streamable HTTP --> S3[remote server]

The gateway is an MCP server toward your client and an MCP client toward every upstream (stdio child processes or streamable-HTTP endpoints), aggregating them behind one connection. It is built on the official TypeScript SDK.

Configuration

Everything lives in one JSON file. Full example with every option:

{
  "servers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" }   // ${VAR} = read from gateway env
    },
    "remote": { "url": "https://mcp.example.com/mcp", "headers": { "Authorization": "Bearer ${MCP_TOKEN}" } }
  },

  "policy": {
    "defaultAction": "allow",                    // "allow" | "deny" | "approve"
    "rules": [                                   // first match wins, evaluated top-down
      { "match": "*__delete*",  "action": "deny",    "reason": "no destructive tools" },
      { "match": ["github__create_*", "*__send_*"], "action": "approve" },
      { "match": "filesystem__*", "action": "allow" }
    ]
  },

  "redaction": {
    "enabled": true,
    "disable": [],                               // built-in rule names to turn off
    "enableOptIn": ["email"],                    // opt-ins: "email", "us-ssn", "ipv4"
    "custom": [{ "name": "acme-id", "pattern": "ACME-[0-9]{6}" }],
    "redactArguments": false                     // also scrub model-supplied arguments
  },

  "injection": {
    "action": "flag",                            // "flag" (warn the model) | "block" | "off"
    "scanToolDescriptions": true,                // tool-poisoning check on tools/list
    "custom": []
  },

  "pinning": {
    "enabled": true,
    "onNewTool": "pin",                          // "pin" (TOFU) | "block" (until `mcp-doorman pin`)
    "onChangedTool": "block"                     // "block" | "warn"
  },

  "rateLimit": { "perMinute": 120, "perTool": { "*__send_*": 5 } },

  "approval": { "fallback": "deny", "timeoutMs": 120000 },  // fallback when client lacks elicitation

  "audit": { "enabled": true, "includeArguments": true, "includeResults": false },

  "logLevel": "info"
}

Pin state and the audit log default to <config-name>.pins.json / <config-name>.audit.jsonl next to the config file.

CLI

Command What it does
mcp-doorman run --config <path> Start the gateway over stdio (default command)
mcp-doorman pin --config <path> Connect to all upstreams and pin (trust) their current tool definitions
mcp-doorman init Write a starter config with sensible defaults

Honest limitations

Security tooling that oversells is worse than none. Read this part.

  • Heuristics are bypassable. The injection patterns catch documented, common attack shapes. A motivated attacker can phrase around any regex. Use deny/approve policies as the hard boundary; screening is defense-in-depth.
  • Redaction is best-effort. Known token formats are caught reliably; a random hex secret with no context is not. Don't point agents at credential stores.
  • This is not a sandbox. Upstream servers still run as child processes with your user's privileges. Doorman guards the protocol; pair it with containers (ToolHive-style) to guard the process.
  • TOFU trusts first sight. Pinning detects changes, not tools that were malicious from day one — that's what the description scanner and your own review are for.
  • Approval gates need elicitation. Clients without elicitation support fall back to approval.fallback (deny by default).

Roadmap — help wanted 🙌

  • [ ] resources/* and prompts/* proxying (currently tools-only)
  • [ ] Pass-through for sampling and roots
  • [ ] Community rule packs (doorman-rules-finance, doorman-rules-healthcare…)
  • [ ] Learning mode: observe for a week, propose a least-privilege policy
  • [ ] OPA / Cedar policy backends
  • [ ] mcp-doorman audit subcommand: pretty-print and query the JSONL log
  • [ ] Web dashboard for audit visualization
  • [ ] Entropy-based generic secret detection

Grab anything above, or start with a [good first issue](https://github.com/YOUR_GITHUB_USERNAME/mcp-doorman/labels/good%20first%20issue). New detection rules are the easiest contribution: one regex + two tests. See CONTRIBUTING.md and docs/detection-rules.md.

Development

npm install
npm test          # 69 tests: unit + full stdio e2e
npm run build
npm run demo      # watch the guards fire live

License

Apache-2.0 — free for any use, with an explicit patent grant.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选