Skip to main content
Glama

mcp-proxy

一个加固型 MCP 代理,位于一个或多个上游 MCP 服务器之前,只暴露给定配置文件允许查看和调用的工具。

一个配置文件描述你的真实服务器(GitHub、filesystem、Slack 等)以及配置文件(reviewer、implementer、ci-bot 等)。每个代理使用 --profile <name> 启动自己的代理副本——或者,在 serve 模式下,一个共享的 HTTP 服务器通过认证将每个连接映射到配置文件——并获得这些服务器的过滤后强制执行的视图,从而节省上下文令牌并从构造上防止危险的工具调用。


为什么使用 mcp-proxy?

官方 MCP 服务器将所有工具暴露给每个代理。客户端获取 tools/list 并将每个工具的模式注入到提示中,在每一轮都如此,消耗上下文令牌。而且,可见的工具就是可调用的工具——没有硬性边界。

mcp-proxy 一次性解决这两个问题:

  • 令牌节省 —— 配置文件只宣传你明确允许的工具,因此只有这些模式会进入代理的上下文。

  • 硬性护栏 —— 不允许的工具既不会被列出,也不会被调用:即使是幻觉调用也会在执行时被拒绝,而不仅仅是从菜单中隐藏。


Related MCP server: Mavryn

优势

优势

帮助方式

🔒 故障关闭护栏

block 优先;未知工具默认拒绝。可见性和可调用性保持同步。

📉 令牌节省

过滤后的 tools/list 意味着更小的提示和更便宜、更专注的会话。

👥 一个配置,多个代理

Reviewer、implementer 和 CI bot 共享相同的 servers 块,但通过 --profile 获得不同的配置文件。

🧩 多服务器聚合

在单个 MCP 端点后面合并多个上游(stdio + HTTP)。

🔐 密钥不进入仓库

${VAR} 占位符 + .env;加载器在缺少变量时快速失败。

♻️ 弹性

自动重连,指数退避;实时 tools/list_changed 更新被重新过滤并传播到下游。

🛡️ 参数验证

tools/call 参数在转发前根据上游 inputSchema 进行验证。

📊 可观测性

--verbose 输出结构化 JSON 行日志,带有每个请求的相关性 ID;共享服务器还暴露 Prometheus /metrics

🌐 共享服务器模式

serve 运行一个 Streamable HTTP 服务器供多个代理使用;每个连接的认证将令牌/头映射到配置文件。

🏷️ 冲突安全

跨服务器共享名称的工具自动加前缀(github__read_file),其他工具保留裸名称。


工作原理

架构

flowchart TB
    subgraph agents["🤖 Agents (MCP clients)"]
        direction LR
        A1["reviewer agent<br/><code>--profile reviewer</code>"]
        A2["implementer agent<br/><code>--profile implementer</code>"]
    end

    subgraph proxy["mcp-proxy — one stdio process per agent"]
        direction TB
        D1["stdio transport"]
        D2["tool filter<br/>(allow/block · globs + regex)"]
        D3["call-time guardrail<br/>+ argument validation"]
        D4["upstream registry<br/>(discovery · reconnect · list_changed)"]
    end

    subgraph up["Upstream MCP servers"]
        direction LR
        U1["filesystem<br/>(stdio)"]
        U2["github<br/>(HTTP)"]
        U3["slack<br/>(HTTP)"]
    end

    A1 -->|"stdin/stdout"| D1
    A2 -->|"stdin/stdout"| D1
    D1 --> D2 --> D3 --> D4
    D4 -->|"spawn"| U1
    D4 -->|"connect"| U2
    D4 -->|"connect"| U3

每个代理将代理作为子进程通过 stdio 生成。代理连接到所选配置文件中列出的每个上游,获取每个 tools/list,应用配置文件的允许/阻止规则,并仅重新暴露存活的工具。

请求流程

sequenceDiagram
    autonumber
    participant A as Agent
    participant P as mcp-proxy
    participant U as Upstream MCP server

    A->>P: tools/list
    P->>U: tools/list (every upstream in profile)
    U-->>P: full tool set
    P->>P: filter + collision resolve
    P-->>A: allowed tools only

    A->>P: tools/call (allowed tool)
    P->>P: guardrail re-check<br/>+ schema validation
    P->>U: forward call
    U-->>P: result
    P-->>A: result

    A->>P: tools/call (blocked tool)
    P-->>A: ❌ rejected with error

    U-->>P: notifications/tools/list_changed
    P->>U: re-fetch tools/list
    P->>P: re-filter
    P-->>A: notifications/tools/list_changed

过滤决策

只有当工具通过以下优先级链时,它才被允许:

flowchart LR
    T["tool name"] --> B{"matches a<br/><code>block</code> pattern?"}
    B -- "yes" --> DENY["🔒 DENY"]
    B -- "no" --> A{"matches an<br/><code>allow</code> pattern?"}
    A -- "yes" --> OK["✅ ALLOW"]
    A -- "no" --> D["fallback:<br/>server <code>default</code><br/>→ profile <code>default</code><br/>→ <code>block</code>"]
    D --> F{"fallback is <code>allow</code>?"}
    F -- "yes" --> OK
    F -- "no" --> DENY

block 始终优先。模式是通配符(read_*{get,list}_*)或正则表达式(/.*delete.*/i)。配置文件中省略的服务器不会暴露其任何工具。


示例:三个配置文件,实时测量

同一个代理通过三个配置文件驱动,针对真实的 @modelcontextprotocol/server-filesystem 上游(14 个工具)运行。第二个 filesystem 实例代替 HTTP GitHub 服务器,因此演示不需要令牌——每个服务器的过滤行为对任何上游都是相同的。

# mcp-proxy.yaml (demo)
version: 1
servers:
  filesystem:
    type: stdio
    command: npx
    args: ["-y", "@modelcontextprotocol/server-filesystem", "C:/data"]
  github:                     # HTTP in real life; filesystem stand-in in this demo
    type: http
    url: https://api.github.com/mcp
    headers: { Authorization: "${GITHUB_TOKEN}" }

profiles:
  reviewer:
    default: block
    servers:
      filesystem:
        allow: ["read_file", "list_directory", "search_files", "directory_tree", "get_file_info"]
      github:
        block: ["**"]          # GitHub fully disabled for this agent

  implementer:
    default: allow
    servers:
      filesystem:
        block: ["/.*delete.*/i", "remove_*", "edit_file", "write_file"]
      github: {}               # all GitHub tools allowed

  noTools:
    default: block
    servers:
      filesystem: { block: ["**"] }
      github: { block: ["**"] }

在实时 tools/list 握手中测量:

配置文件

暴露的工具

tools/list 负载

~令牌

reviewer

5

2,926 字符

~732

implementer

26

15,762 字符

~3,941

noTools

0

2 字符

~1

令牌使用 ~4 字符/令牌的启发式方法;真正的节省是代理每轮重新加载到上下文中的模式表面。

每个配置文件实际收到的工具:

  • reviewer(只读,GitHub 被阻止): read_filelist_directorydirectory_treesearch_filesget_file_info

  • implementer(拒绝列表,GitHub 允许): filesystem__read_filegithub__read_filefilesystem__read_text_filegithub__read_text_filefilesystem__read_media_filegithub__read_media_filefilesystem__read_multiple_filesgithub__read_multiple_filesfilesystem__create_directorygithub__create_directoryfilesystem__list_directorygithub__list_directoryfilesystem__list_directory_with_sizesgithub__list_directory_with_sizesfilesystem__directory_treegithub__directory_treefilesystem__move_filegithub__move_filefilesystem__search_filesgithub__search_filesfilesystem__get_file_infogithub__get_file_infofilesystem__list_allowed_directoriesgithub__list_allowed_directorieswrite_fileedit_file

  • noTools(所有内容被阻止):(无)

两个值得注意的细节:

  • 冲突自动加前缀 —— read_file 存在于两个服务器上,因此它变成 filesystem__read_filegithub__read_file。但 write_file/edit_file 保留其裸名称,因为它们在 filesystem 上被阻止,留下 github 作为唯一来源。

  • 空配置文件视图是有效的 —— noTools(或任何带有 block: ["**"] 的配置文件,或省略的服务器)暴露个工具;代理仍然连接,只是没有可调用的内容。


快速开始

1. 安装并构建

npm install
npm run build          # compiles TypeScript to dist/

2. 将密钥放入 .env(切勿放入配置中)

cp .env.example .env   # then fill in your tokens

3. 编写 mcp-proxy.yaml

version: 1

servers:
  filesystem:
    type: stdio
    command: npx
    args: ["-y", "@modelcontextprotocol/server-filesystem", "C:/repo"]
    env:
      ROOT: "C:/repo"

  github:
    type: http
    url: https://api.github.com/mcp
    headers:
      Authorization: "${GITHUB_TOKEN}"   # env-var reference, not a literal secret

profiles:
  reviewer:                 # read-only, fail-closed
    description: "Read-only agent"
    default: block
    servers:
      filesystem:
        allow: ["read_file", "list_directory", "directory_tree", "get_file_info"]
      github:
        allow: ["get_*", "list_*", "search_*"]

  implementer:              # deny-list, fail-open minus dangerous ops
    description: "Full access minus destructive ops"
    default: allow
    servers:
      filesystem:
        block: ["/.*delete.*/i", "edit_file", "write_file"]
      github:
        block: ["merge_pull_request", "delete_*"]

defaultProfile: reviewer

4. 运行

node dist/cli/index.js --profile reviewer
# add --verbose for structured debug logging
node dist/cli/index.js --profile reviewer --verbose

配置文件优先级:--profile > MCP_PROFILE > defaultProfile


配置参考

servers —— 上游 MCP 服务器

stdio(作为子进程生成):

filesystem:
  type: stdio
  command: npx
  args: ["-y", "@modelcontextprotocol/server-filesystem", "C:/repo"]
  env: { ROOT: "C:/repo" }
  prefix: fs__          # optional: override collision-prefix namespace

http(Streamable HTTP):

github:
  type: http
  url: https://api.github.com/mcp
  headers:
    Authorization: "${GITHUB_TOKEN}"
  prefix: gh__          # optional

profiles —— 命名工具视图

profiles:
  my-profile:
    description: "..."           # optional
    default: allow               # allow | block (fallback when no rule matches)
    servers:
      github:
        allow: ["get_*"]         # optional allow-list
        block: ["delete_*"]      # optional block-list (always wins)
        default: block           # optional per-server fallback override
      # filesystem omitted → none of its tools are exposed

http —— Streamable HTTP 下游(serve 模式)

可选的顶级块,将代理变成共享 HTTP 服务器,从一个进程服务多个代理。请参阅 共享服务器(HTTP)

http:
  host: 0.0.0.0             # default 127.0.0.1
  port: 3000                # default 3000
  path: /mcp                # MCP endpoint (default /mcp)
  metricsPath: /metrics     # Prometheus metrics (default /metrics)
  healthPath: /health       # liveness (default /health)
  readyPath: /ready         # readiness (default /ready)
  auth:
    header: authorization   # selector header (default authorization)
    scheme: Bearer          # optional prefix to strip
    tokens:                 # token -> profile map (values may use ${VAR})
      tok-reviewer: reviewer
      tok-impl: implementer
    defaultProfile: reviewer # optional fallback (fail-closed without it)

当设置了 tokens 时,去除方案后的头值在映射中查找。没有 tokens 时,去除方案后的头值直接用作配置文件名称。缺失/未知的选择器回退到 defaultProfile,如果没有适用则被拒绝(401/403)。

密钥

${VAR} 占位符在加载时从环境(或 .env)解析。YAML 只保存变量名称,因此提交是安全的。缺少变量会使加载器快速失败——不会出现静默空头。


连接到你的代理

代理就是一个通过 stdio 的 MCP 服务器。将你的代理指向代理入口点,而不是真实服务器,并传递配置文件标志。

// .mcp.json — reviewer agent
{
  "mcpServers": {
    "proxy": {
      "command": "node",
      "args": ["C:/Dev/mcp-proxy/dist/cli/index.js", "--profile", "reviewer"]
    }
  }
}
// .mcp.json — implementer agent (same proxy, different profile)
{
  "mcpServers": {
    "proxy": {
      "command": "node",
      "args": ["C:/Dev/mcp-proxy/dist/cli/index.js", "--profile", "implementer"]
    }
  }
}

每个代理都有自己的 stdio 进程,因此配置文件在每个代理之间完全隔离,凭据永远不会跨进程边界。

共享服务器(HTTP)

对于集中部署,运行 serve 以暴露一个 Streamable HTTP 服务器,供多个代理共享。每个连接根据其认证头映射到配置文件:

node dist/cli/index.js serve --config mcp-proxy.yaml
# options: --host, --port (override http.host/http.port)

端点:

路径

用途

/mcp

Streamable HTTP MCP 端点(每个连接一个会话)

/health

存活——进程启动后始终 200

/ready

就绪——仅当每个配置文件的上游都连接时返回 200

/metrics

Prometheus 文本指标(列出的/调用的/阻止的工具、延迟、上游状态)

每个连接的配置文件解析是故障关闭的:没有可用选择器的连接被拒绝(401),除非设置了 http.auth.defaultProfile,并且映射到未知配置文件的选择器被拒绝(403)。

共享部署的客户端配置(任何支持 Streamable-HTTP 的客户端):

// .mcp.json — reviewer agent (token maps to the `reviewer` profile)
{
  "mcpServers": {
    "proxy": {
      "type": "http",
      "url": "https://proxy.example.com/mcp",
      "headers": { "Authorization": "Bearer ${PROXY_TOKEN}" }
    }
  }
}
// .mcp.json — implementer agent (same server, different token/profile)
{
  "mcpServers": {
    "proxy": {
      "type": "http",
      "url": "https://proxy.example.com/mcp",
      "headers": { "Authorization": "Bearer ${PROXY_TOKEN_IMPL}" }
    }
  }
}

Copilot 编码代理读取仓库的 .mcp.json;对于其他代理,使用其原生 MCP 服务器字段(请参阅 context/AGENT-SETUP.mdcontext/VENDOR-AGENTS.md)。


可观测性

使用 --verbose 运行以向 stderr 输出结构化 JSON 行日志(保持 MCP stdio 通道在 stdout 上干净):

{"timestamp":"2026-08-23T17:22:26.976Z","level":"info","message":"connected to upstream","server":"filesystem","tools":14}
{"timestamp":"2026-08-23T17:22:26.980Z","level":"debug","message":"tools/call","correlationId":"42","tool":"read_file","server":"filesystem"}

每个 tools/listtools/call 条目都携带 MCP 请求的 correlationId,因此可以在代理及其上游之间跟踪单个请求。

要查看配置文件的上下文成本,请比较不同配置文件之间的工具数量和 tools/list 负载大小(请参阅上面的测量示例):宣传的工具越少,意味着每轮注入到提示中的模式越少。

serve 模式下,抓取 /metrics 获取 Prometheus 计数器、仪表和直方图:mcp_proxy_tools_listed_totalmcp_proxy_tools_called_totalmcp_proxy_tools_blocked_totalmcp_proxy_tool_call_duration_secondsmcp_proxy_upstream_connections(全部按 profile/server/tool 标记)。


弹性

  • 自动重连 —— 如果上游(尤其是生成的 stdio 进程)死亡,代理以指数退避重连(500ms → 15s 上限,无限重试)。

  • 实时工具更新 —— 当上游发出 notifications/tools/list_changed 时,代理重新获取、重新过滤并将更改转发到下游,因此代理始终看到准确的工具列表。

  • 参数验证 —— tools/call 参数在转发前根据上游的 inputSchema 进行检查;无效调用在本地被拒绝。


开发

npm run typecheck    # tsc --noEmit
npm test             # vitest (unit + integration + filesystem smoke)
npm run build        # tsc → dist/

更多

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Self-hosted MCP proxy and aggregation platform. Register multiple upstream MCP servers and expose them through a single unified endpoint with namespace routing, multi-transport support (HTTP/SSE, stdio, OpenAPI→MCP), per-tool overrides, and a web admin UI.
    16
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Centralized MCP control plane that proxies multiple upstream MCP servers with tool namespacing, filtering, policy enforcement, audit logging, and health checks.
    16
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    An authorizing reverse proxy for MCP servers that enforces per-call policy rules on tool arguments with audit logging, dry-run, and rate limiting.
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables serving multiple MCP toolkits behind one server with capability-based access control, so different callers see and can call only the tools they are authorized for, over stdio or streamable HTTP with bearer-token auth.
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/DawidNowak/mcp-proxy'

If you have feedback or need assistance with the MCP directory API, please join our Discord server