ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

不会还有人以为接上 MCP 就等于安全了吧?协议≠授权 | MCP 入门选型

不会还有人以为接上 MCP 就等于安全了吧?协议≠授权 | MCP 入门选型

上一篇:不会还有人拿单次工具调用撑多步骤业务吧?没有编排就没有纪律 | 意图流水线 Worker

不会还有人以为接上 MCP 就等于安全了吧?协议≠授权 | MCP 入门选型

系列:《从 Rule 到落地:AI 工程化实践》第 12 篇
标签:MCP · Tool · stdio · HTTP
专栏:从小白到AI落地大师

序言

编排有了骨架,童鞋们要让助手真正调到外部能力。于是 MCP 出场。别被英文唬住,也别神话它。本篇入门:它解决什么问题、工具与资源怎么分、stdio 与 HTTP 怎么选。完整服务器实现留给第 13 篇,上线加固留给第 14 篇。

说句自嘲的:我第一次接上协议时有短暂的「终于工程化了」幻觉。直到有人问鉴权在哪——我才发现自己只是换了个更标准的裸奔姿势。协议不等于授权。这句话值得贴在显示器边上。

记住一句话:协议只回答「能不能调用」,不回答「该不该调用」——后者写在 danger level、凭证隔离与网关策略里,一个都不能省。

概念

MCP,标准化工具与资源暴露方式,降低每个 IDE 一套插件的碎片成本。Tool,可调用动作,通常带参数与副作用边界。Resource,可读上下文材料,偏只读。stdio,本地子进程标准输入输出传输,适合 IDE 拉起。HTTP,远程或共享传输,需补鉴权与网络安全。

可以理解为:MCP 是领料窗口的标准尺寸;Tool 是能领走的动作,Resource 是能查阅的图纸。窗口标准化了,不等于谁都能进库房——钥匙还是 AuthZ 的事。

问题在哪

没有标准协议时,每个助手一套私有插件,权限模型各玩各的,发现成本高,审计更难。有了协议却停在「能调」:密钥粘配置、无风险分级、无超时熔断——只是把碎片化换成标准化风险。

工具与资源若混用,只读查询和写操作同一权限桶,事故半径被放大。传输方式选错也疼:把该本地的做成裸 HTTP,或把该共享的死撑 stdio 多机硬刚,都会在运维周会上留作业。

举例

工具描述要自描述:名字、参数 schema、危险级别。示意:

{"name":"list_fixtures","description":"列出适配引擎回归样例","inputSchema":{"type":"object","properties":{"engine":{"type":"string"}}}}

选型清单可以很直白:选 stdio——本地 IDE 插件、无多租户。选 HTTP——团队共享的 ops-gate-mcp、需审计网关。混合——本地 stdio 调远程 HTTP,注意密钥不落盘明文。与 Rule 的关系记牢:协议负责能调用,Rule 负责该不该调用。两者缺一,要么叫不动,要么乱叫。

「该不该调用」不能停在口号上。把它写成一份能跑的体检,对着自己仓库的工具清单扫一遍,就四步:

步骤总览

  1. 收一份 manifest:每个工具记 name / kind(read 还是 write)/ transport / risk / 参数 schema / 凭证桶;
  2. 逐条体检四件事:有没有声明危险级别、有没有参数 schema、读写是否共用同一凭证、HTTP 是否裸奔无鉴权;
  3. 按工具聚合报警——注意 apply_adapt 一个工具会同时撞中三条,这不是巧合,是「写操作最该被管」的照妖镜;
  4. 出结论:过审之前别谈上线,先补分级、拆凭证。

把上面那段「领料窗口不等于仓库大门」的直觉,落成mcp_review.py:

# mcp_review.py —— MCP 选型审查:把「协议≠授权」变成能跑的体检# 纯标准库,复制即跑。用法:python mcp_review.py## 审查一份 MCP 工具清单(manifest),只看四件事:# 1) 危险级别有没有声明(缺分级 = 网关没法判断该不该放行)# 2) 参数 schema 有没有(缺 schema = 助手只能靠猜,猜就会野)# 3) 读写是否共用同一凭证桶(共用 = 误调用一次,事故半径覆盖只读到写)# 4) HTTP 传输是否裸奔无鉴权(协议标准化 ≠ 大门敞开)TOOLS=[{"name":"health","kind":"read","transport":"stdio","risk":None,"schema":True,"credential":"ops-shared","desc":"服务是否存活"},{"name":"list_fixtures","kind":"read","transport":"stdio","risk":"low","schema":True,"credential":"ops-shared","desc":"列出适配引擎回归样例"},{"name":"apply_adapt","kind":"write","transport":"http","risk":None,"schema":False,"credential":"ops-shared","desc":"执行适配补丁(会改工作区文件)"},{"name":"fetch_log","kind":"read","transport":"http","risk":"medium","schema":True,"credential":"log-readonly","desc":"读生产日志","publicNoToken":True},]defreview(tools):findings=[]# 凭证桶:同一 credential 里既含 read 又含 write -> 读写同凭证bucket={}fortintools:bucket.setdefault(t["credential"],set()).add(t["kind"])fortintools:name=t["name"]ift["risk"]isNone:findings.append((name,"缺分级","未声明 danger level,网关无从判断该走哪档闸门"))ifnott["schema"]:findings.append((name,"缺参数schema","没有 inputSchema,助手只能猜参数,猜即野调用"))iflen(bucket[t["credential"]])>1:findings.append((name,"读写同凭证",f"凭证桶{t['credential']}同时握着 read/write,""误调用一次就把只读面一起点燃"))ift["transport"]=="http"andt.get("publicNoToken"):findings.append((name,"裸HTTP无鉴权","远程 HTTP 未挂 token/mTLS,等于把接口裸开在局域网"))returnfindingsdefmain():print("== MCP 工具清单体检(协议负责能调用,以下四项负责该不该调用)==\n")print(f"{'工具':<14}{'传输':<8}{'危险级别'}")print(" "+"-"*30)fortinTOOLS:risk=t["risk"]or"未声明"print(f"{t['name']:<14}{t['transport']:<8}{risk}")findings=review(TOOLS)print("\n== 检出问题 ==")by_tool={}forname,tag,whyinfindings:by_tool.setdefault(name,[]).append((tag,why))fornamein[t["name"]fortinTOOLSift["name"]inby_tool]:print(f" [{name}]")fortag,whyinby_tool[name]:print(f" ✗{tag:10}{why}")n=len({tfort,*_infindings})print(f"\n== 结论 ==")print(f" 4 个工具里{n}个不过审 -> 先补分级/拆凭证再谈上线。")print(" apply_adapt 是写操作:第 14 篇会用 ops-gate 给它套 T1-T4 闸门;")print(" 在此之前,它连『该不该被调用』都还没回答,只回答了『能不能调用』。")print("\n一句话:MCP 是插座,插座不负责判断该不该通电——那是 Rule 与网关的事。")if__name__=="__main__":main()

跑起来长这样:

== MCP 工具清单体检(协议负责能调用,以下四项负责该不该调用)== 工具 传输 危险级别 ------------------------------ health stdio 未声明 list_fixtures stdio low apply_adapt http 未声明 fetch_log http medium == 检出问题 == [health] ✗ 缺分级 未声明 danger level,网关无从判断该走哪档闸门 ✗ 读写同凭证 凭证桶 ops-shared 同时握着 read/write,误调用一次就把只读面一起点燃 [list_fixtures] ✗ 读写同凭证 凭证桶 ops-shared 同时握着 read/write,误调用一次就把只读面一起点燃 [apply_adapt] ✗ 缺分级 未声明 danger level,网关无从判断该走哪档闸门 ✗ 缺参数schema 没有 inputSchema,助手只能猜参数,猜即野调用 ✗ 读写同凭证 凭证桶 ops-shared 同时握着 read/write,误调用一次就把只读面一起点燃 [fetch_log] ✗ 裸HTTP无鉴权 远程 HTTP 未挂 token/mTLS,等于把接口裸开在局域网 == 结论 == 4 个工具里 4 个不过审 -> 先补分级/拆凭证再谈上线。 apply_adapt 是写操作:第 14 篇会用 ops-gate 给它套 T1-T4 闸门; 在此之前,它连『该不该被调用』都还没回答,只回答了『能不能调用』。 一句话:MCP 是插座,插座不负责判断该不该通电——那是 Rule 与网关的事。

输出你看什么

  1. 顶部表格只是「登记」,未声明三处就是裸奔名单——health 和 apply_adapt 连危险级别都没填,网关拿到它们只能二选一:全放或全拦,两个都错;
  2. ops-shared这个凭证桶同时握着 health、list_fixtures(read)和 apply_adapt(write),所以三个工具被同一条「读写同凭证」点名——这就是前面说的「误调用一次就把只读面一起点燃」,事故半径不是假设;
  3. apply_adapt 一个人撞中三条(缺分级 + 缺参数 schema + 读写同凭证):写操作本就最该被管,清单越糊,它爆得越狠——第 14 篇的 T1-T4 闸门就是冲着它来的;
  4. fetch_log 只有「裸 HTTP 无鉴权」一条,但它是唯一独立凭证桶(log-readonly)——说明拆凭证这件事你们其实会做,只是还没对 apply_adapt 下手。补上分级、把 ops-shared 拆成读写两桶,这份清单才配谈上线。

自检

# MCP 入门自检 - [ ] 能否向同事讲清 MCP 与随手写个 HTTP API 的差别? - [ ] 工具与资源是否分工明确? - [ ] stdio / HTTP 选型理由是否写得出来? - [ ] 是否仍清楚「协议≠授权」? - [ ] 工具描述是否含参数 schema 与危险级别?

两问。第一,今天接上的能力,鉴权在协议外的哪一层?答不上来,就是裸奔。第二,只读列表与写操作是否同一凭证?是的话,准备拆分——别等误调用替你拆。

向老板解释 MCP 时,别从缩写展开,从痛苦展开:以前每个助手一套插件,现在发现与权限可以收敛。痛苦清楚了,缩写才有意义。

资源(Resource)被低估得厉害。很多团队只会做 Tool,结果把只读上下文也做成动作,徒增副作用面。能只读就只读。

MCP 入门选型别被「协议很新」带跑。先问三句:工具是本地 stdio 还是远程 HTTP?有没有鉴权挂钩子?失败时返回结构化错误还是一段散文?散文错误会逼助手猜,猜就会野。

生活类比:MCP 像领料窗口的传票格式——格式统一不代表仓库大门敞开。能递传票,和有没有出门证,是两件事。

传输方式怎么选:本地仓库、私有日志、密钥材料,优先 stdio 本机进程;跨机共享、需统一鉴权的,再上 HTTP,并且默认 mTLS 或至少 token。不要因为 demo 方便就把生产日志接口裸开在局域网。

资源(resources)与工具(tools)也要分清:资源偏只读上下文,工具是动作。把「写生产」伪装成资源拉取,是协议层常见偷渡。

读到这里,不妨立刻做一个五分钟动作:打开你们仓库,找到与本篇对应的那个目录(没有就新建),把文中最小示意落成真实文件名。文件在,讨论才有坐标;文件不在,下周还会从「我们觉得」开始。第 12 篇的验收不是「读完」,是「仓库里多了一份可指出的东西」。

举例加长:选型对照(周末讨论用)

场景更合适别踩的坑
读本机日志stdio把日志目录挂成世界可读
公司内网工具HTTP + 鉴权demo 用的无 token 直上生产
需要前端同页调用HTTP把写操作做成 resource

开会时把这表投上去,比空谈「我们要上 MCP」快。协议是插座,插座不负责判断该不该通电。

童鞋们可以用一张名片向同事解释:

问题答法
MCP 是啥助手发现与调用工具的标准说法
等于安全吗不等于;授权在协议外
先选啥传输本地 stdio / 团队 HTTP
先警惕啥密钥粘配置、读写同一凭证

讲得清这四行,再谈字段细节不迟。

思考

小结三句。MCP 提供统一的工具与资源暴露方式,降低接入碎片。本地优先 stdio,共享与远程再上 HTTP 并补安全。协议不等于授权;授权交给 Rule 与网关策略。

可以理解为:先选对窗口和图纸柜,再往里放三件能演示的工具。下篇动手:health、list、run_safe_task,默认 dry-run,足够演示闭环。


下篇预告:《不会还有人一上来就做二十个工具吧?三个工具够演示闭环 | 最小 MCP 实战》——一上来二十个工具,通常一个都观不透。

觉得有用的话,欢迎点赞、留言聊聊你选型 stdio 还是 HTTP 的理由;有「接上就等于安全了」的幻觉瞬间,也欢迎自嘲区见。

专栏:从小白到AI落地大师|《从 Rule 到落地:AI 工程化实践》

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进