mcpField
M
mcp-gatehouse

mcp-gatehouse

本地服务
nickgeorgeai.com安全26 天前更新

关于 mcp-gatehouse

mcp-gatehouse 是一个 Python 库,可在 MCP 服务内部添加权限、审批和审计日志。服务开发者可按风险划分工具、要求审批、隐藏敏感参数,并屏蔽指定工具,无需外部策略服务。

主要功能

  1. 01READ、WRITE 和 DESTRUCTIVE 权限层级
  2. 02默认拒绝的审批门控
  3. 03仅追加的 JSONL 审计记录
  4. 04敏感参数脱敏
  5. 05工具拒绝列表
  6. 06审批超时设置

适用场景

  1. 01在破坏性工具调用前要求审批
  2. 02记录允许、拒绝、失败和取消的调用
  3. 03隐藏日志及审批请求中的机密信息
  4. 04不论权限层级都屏蔽指定工具

MCP 相关

它包装使用官方 Python MCP SDK 构建的服务中的工具注册流程。在工具边界实施权限控制,同时保留原有模式和传输方式。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"nickgeorgeseo-gatehouse": {
"command": "uvx",
"args": [
"mcp-gatehouse"
]
}
}
}
启动命令uvx mcp-gatehouse

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypimcp-gatehouse0.4.0

工具

4

收录的工具列表 · 更新于 1 周前

此工具无需参数。

详细介绍

mcp-gatehouse

项目主页与文档: nickgeorgeai.com/open-source/mcp-gatehouse · PyPI

CI PyPI Python License: MIT mcp-gatehouse MCP server

Gatehouse MCP server

为 MCP 服务提供权限等级、审批关卡和审计日志。 该服务是把关者:由你决定 AI 可以读取什么、可以写入什么,以及哪些内容禁止访问;每项操作都会被记录。

大多数 MCP 服务会把所有工具都以完整权限交给模型,却不记录它做了什么。这对演示来说没问题。但如果某个 Agent 获得了 CRM、账簿或订单系统的写入权限,那就不行了。mcp-gatehouse 补上了缺失的关卡,并在服务内部强制执行——无需代理、外部策略服务,也不需要官方 mcp SDK 以外的依赖。

pip install mcp-gatehouse

你将获得

权限等级每个工具都声明为 READ、WRITE 或 DESTRUCTIVE;等级还会生成符合规范的 ToolAnnotations(readOnlyHint / destructiveHint),包装器不会允许你覆盖这些标注来伪装权限。
审批关卡你指定的等级需要在工具运行前获得批准。审批者可以是任何可调用对象——终端提示、Slack 消息或工单。**默认拒绝:**未配置审批者的受控工具将被拒绝,而不会放行。
审计日志仅追加的 JSONL,每次调用占一行——无论是允许、拒绝、失败还是取消——均记录 UTC 时间戳和耗时。六个月后,你仍能回答“AI 实际做了什么?”
脱敏你指定的参数键(默认包括 api_key、password、token、client_secret 等)在写入日志或发送给审批者之前都会被屏蔽,无论键的拼写方式如何:apiKey、API-Key 和 api_key 都视为同一个键。
拒绝列表无论工具属于哪个等级,都可以直接禁止它。

快速入门

from mcp.server.mcpserver import MCPServer
from mcp_gatehouse import AccessTier, AuditLog, Gatehouse, Policy, terminal_approver

mcp = MCPServer("order-desk")
gatehouse = Gatehouse(
    mcp,
    policy=Policy(approver=terminal_approver),
    audit=AuditLog(path="~/order-desk/audit.jsonl"),
)

@gatehouse.tool(tier=AccessTier.READ)
def lookup_order(order_id: str) -> str:
    """Look up an order's status."""
    ...

@gatehouse.tool(tier=AccessTier.DESTRUCTIVE)
def cancel_order(order_id: str) -> str:
    """Cancel an order. Runs only if the approver says yes."""
    ...

mcp.run()

集成就这么简单:按照 SDK 文档中的方式构建 MCPServer,但通过 gatehouse 注册工具。Schema 生成(包括 Annotated[..., Field(description=...)] 参数文档)、传输方式及其他一切都保持不变——守卫会保留函数的签名。同步工具仍在工作线程中运行,与在裸 MCPServer 上运行时完全一样。

terminal_approver 会在控制终端(/dev/tty)上询问,绝不会使用 stdin——通过 stdio 通信时,stdin 就是 协议管道,因此普通的 input() 审批器会破坏它。审批器可以是任意同步或异步可调用对象,接收一个 ApprovalRequest,并返回 True 表示允许;同步审批器会在专用线程池中的工作线程里运行,因此人工审批耗时不会阻塞其他调用,积压的审批请求也不会占用同步工具所需的线程。如果审批器抛出异常(Slack 不可用、工单 API 超时),调用将被拒绝,并记录失败。

为审批设置截止时间,避免无人批准的请求一直挂起:

Policy(approver=terminal_approver, approval_timeout=120)

超过截止时间后,调用将被拒绝,并记录为 approval timed out。审批器可以通过 request.deadline(time.monotonic() 值)查看截止时间,terminal_approver 会在截止时间到达时撤回提示。忽略截止时间的同步审批器会在后台继续运行,其答复会被丢弃。未设置超时时间时,守卫会一直等待审批器完成。

默认策略要求对 DESTRUCTIVE 操作进行审批,并审计所有操作。只需一行即可让守卫也写入日志:

Policy(require_approval=frozenset({AccessTier.WRITE, AccessTier.DESTRUCTIVE}), ...)

添加包含敏感信息的自定义键,同时保留默认配置:

from mcp_gatehouse import DEFAULT_REDACT
Policy(redact=DEFAULT_REDACT | {"card_pin"}, ...)

审计记录如下:

{"ts": "2026-07-16T14:02:11+00:00", "tool": "lookup_order", "tier": "read", "outcome": "ok", "arguments": {"order_id": "4417"}, "duration_ms": 0.42}
{"ts": "2026-07-16T14:02:38+00:00", "tool": "add_note", "tier": "write", "outcome": "ok", "arguments": {"order_id": "4417", "note": "call back", "api_key": "«redacted»"}, "duration_ms": 1.08}
{"ts": "2026-07-16T14:03:05+00:00", "tool": "cancel_order", "tier": "destructive", "outcome": "denied", "reason": "approver refused", "arguments": {"order_id": "4417"}}
{"ts": "2026-07-16T14:05:40+00:00", "tool": "cancel_order", "tier": "destructive", "outcome": "cancelled", "reason": "awaiting approval", "arguments": {"order_id": "4418"}}

outcome 的值为 ok、denied(reason 说明原因)、error(工具抛出了异常;reason 是异常类型)或 cancelled:客户端在调用完成前放弃了请求,或服务器已关闭。reason 说明具体情况。awaiting approval 表示工具尚未运行。tool running 会附带 duration_ms,工具可能已经完成了部分工作。同步工具无法中途停止:其工作线程会一直运行到结束,记录行仍会照常显示 ok 或 error。守卫只负责写入记录;取消操作仍按原本的方式继续进行。

试用演示

软件包附带一个可运行的订单台服务器,已接入全部三个等级,并配有终端提示审批器。将其添加到任何支持 stdio 的 MCP 客户端中——对于 Claude Desktop,可在 claude_desktop_config.json 中添加:

{
  "mcpServers": {
    "gatehouse-demo": {
      "command": "uvx",
      "args": ["mcp-gatehouse", "--audit-log", "/tmp/gatehouse-audit.jsonl"]
    }
  }
}

或者在运行 pip install mcp-gatehouse 后自行运行 mcp-gatehouse-demo。让模型列出订单并取消其中一个,然后观察审计日志中相应的审批结果。审计日志写入 --audit-log 指定的位置,否则使用 $MCP_GATEHOUSE_AUDIT_LOG,再否则使用 ./audit.jsonl——当工作目录不可写时(桌面客户端通常会从 / 启动服务器),则回退到 ~/.mcp-gatehouse/audit.jsonl。服务器会将选定的路径打印到 stderr。

审批提示需要独立的终端:在后台启动服务器的客户端没有终端,而使用全屏终端 UI 的客户端正在占用其终端,因此这两种情况下 cancel_order 都会被拒绝——守卫会按设计采用默认拒绝策略。若要交互式批准,请从未运行全屏程序的普通终端会话中启动客户端。两分钟后仍未响应的提示将被拒绝。examples/orders_server.py 是同一服务器,可作为模板复制使用。

设计说明

  • 在服务内部、工具边界处执行管控。 代理无法理解工具的语义,而策略服务又是一个需要部署的组件。一个有 40 人的工厂没有平台团队;这只需要几个小型类和一个 JSONL 文件。
  • 默认拒绝。 默默放行的安全默认设置还不如没有。脱敏也一样:清理器无法拆解的参数值(任意对象、字节)会被替换为不透明占位符,而不会直接传递;异常消息不会写入日志——只记录异常类型,因为错误文本很容易包含刚刚脱敏的值。
  • 审计日志会记录拒绝、错误和取消,而不只是成功——那些没有发生的调用也是重要信息的一半,而中途被终止的调用可能已经产生了影响。
  • 阻塞式终端审批器与 stdio 传输不能混用——stdout/stdin 是协议管道。terminal_approver 正是因此在 /dev/tty 上提示,并会在没有终端或全屏程序将其设为原始模式时拒绝审批。 实际部署应通过带外方式审批:Slack、工单或队列。
  • 本工具不提供: 身份验证、传输加密或沙箱。它是服务内部的关卡,而不是外围防护。请参阅 SECURITY.md。

兼容性

面向官方 mcp Python SDK v2.x(mcp>=2,<3)和 Python 3.10–3.14。附带类型信息 (py.typed)。版本说明:CHANGELOG.md。

mcp-gatehouseSDK服务类
0.4.xmcp>=2,<3MCPServer
0.3.xmcp>=2,<3MCPServer
0.2.xmcp>=2,<3MCPServer
0.1.xmcp>=1.27,<2FastMCP

正如承诺的那样,公开 API(Gatehouse、Policy、AuditLog、AccessTier)在整个版本系列中保持不变。将 v1 服务移植过来只需修改两处导入——FastMCP 已改为 MCPServer,并移至 mcp.server.mcpserver;请参阅 SDK 的 迁移指南。

继续使用 SDK v1 无需任何操作:0.1.x 固定使用 mcp<2,因此 pip 会继续解析到该版本。该版本系列不再添加新功能,但仍会获得安全修复。

开发者

Nick George — 我为一家中型逆向物流科技公司设计并运营生产环境中的 MCP 服务,也通过 nickgeorgeai.com 为企业构建 MCP 服务。这个库提取自这些项目中的权限与审计规范。 我为什么构建它,以及它如何运作的通俗说明,请参阅项目页面。

如果你是企业主或运营者,想了解 MCP 到底是什么,请从这篇通俗指南开始:什么是 MCP 服务?

许可证

MIT

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。