Skip to main content
Glama
bhargavlukka

SecureAgentServer

by bhargavlukka

基于 MCP 的安全智能体系统

一个用于客服工单与客户账户的 MCP 服务器和客户端,整个链路均实现了安全构建:签名令牌认证、两道分别防范提示注入和工具投毒的独立护栏、一份文档化的威胁模型,以及针对唯一那个破坏性工具调用的人工批准门控。本系统为“Secure an MCP-Based Agent System”实验室而构建。

架构

flowchart TD
    HOST["Host application"] --> CLIENT["client.py\n(fastmcp.Client + elicitation_handler)"]
    CLIENT <-->|"Streamable HTTP\nAuthorization: Bearer <signed JWT>"| SERVER

    subgraph Server["server.py — FastMCP('SecureAgentServer')"]
        AUTH["JWTVerifier (HS256)\nissuer + audience + signature checked"]
        G1["Guardrail 1: sanitize_untrusted_text()\napplied to ticket body/subject"]
        G2["Guardrail 2: verify_tool_manifest()\nchecked at startup, refuses to start on mismatch"]
        TOOLS["Tools: search_tickets, lookup_customer_account,\nclose_ticket (elicitation-gated)"]
        AUTH --> TOOLS
        TOOLS --> G1
    end
    G2 -.->|startup check| SERVER

    TOOLS --> TICKETS[("data/tickets.json\n(untrusted customer text)")]
    TOOLS --> CUSTOMERS[("data/customers.json\n('internal API')")]

Related MCP server: enterprise-agent-lab

设置

pip install -r requirements.txt

# 1. Set the JWT signing secret (never commit the real value; see .env.example)
export MCP_JWT_SECRET="a-long-random-secret-at-least-32-characters"

# 2. Generate the pinned tool-integrity manifest (a deliberate, manual step —
#    see docs/threat-model.md Risk #2)
python generate_manifest.py

# 3. Run the server
python server.py

# 4. In another terminal (same MCP_JWT_SECRET exported)
python client.py --auto-confirm   # non-interactive demo
python client.py                  # interactive: real yes/no confirmation prompts

复现安全控制

控制项

验证方式

签名 JWT 认证

client.py 最后的两个演示:只读作用域令牌会被 close_ticket 拒绝;伪造/未签名的令牌会在任何工具运行之前就被 401 拒绝。两者都记录在 demo/session_log.txt 中。

护栏 1:提示注入净化

运行客户端,并查看 search_tickets 输出中的 TICKET-2002(其正文包含一个预置的“IGNORE ALL PREVIOUS INSTRUCTIONS...” payload)——返回文本会被包裹起来,且触发短语会被隐去。服务器自身在触发时也会在 stdout 记录一行 [SECURITY] 日志。

护栏 2:工具投毒检测

python demo/verify_tampering_detection.py ——在内存中篡改 close_ticket 的描述,并显示 verify_tool_manifest() 捕获到的不匹配;可参阅 demo/tampering_detection_log.txt 查看已捕获的运行结果

破坏性动作的人中回路

close_ticket 在 demo 日志中只有出现 [ELICITATION] ... -> accepting 后才完成;运行 client.py 时不加 --auto-confirm 即可看到真实交互式确认提示。

最小权限范围

add_ticket_note/close_ticket 通过 get_access_token()(server.py::_require_scope)显式检查 write:tickets,而不仅是连接级的限制——上面只读令牌拒绝已体现。

威胁模型

完整论述,包括通过缓解措施和残余风险说明明确阐述、未回避的5项风险:docs/threat-model.md。

明确说明范围内之外的内容

  • mint_token.py 只是真实 OAuth 2.1 身份提供者的替代品——生产环境需要真正的令牌签发/轮换/吊销,而不是本地铸造脚本。

  • 没有速率限制或网络层加固(TLS 终止、WAF)——这是应用层安全演示,不是完整的部署加固指南。

  • GuardRail 1 的正则版本部分明确是次要的、best-effort 缓解层——请参阅 docs/threat-model.md 的 Risk #1 了解为何实际依赖的是分隔符包裹控制。

不提交任何机密

从环境变量中读取 MCP_JWT_SECRET(参见 .env.example),从不硬编码或提交。tool_manifest.json 是刻意提交的——它就像 lockfile 一样是一个组合列表,并不是机密。

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables controlled AI-agent access to enterprise-shaped tools with a deny-by-default gated write path, human approval, dry-run execution, and append-only audit logging.
    1
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enforces authenticated identity on every tool call and SSE frame, rotates vaulted credentials in place, and restricts tools via allowlists.
    71 npm
    MIT