最近在看MCP(Model Context Protocol),有点绕进去了。我理解它是一个让AI模型访问外部工具/数据的标准协议,但看官方示例基本都搭配Claude Desktop或自建Agent来用。我的场景其实很简单:想在自己的Python脚本里,直接通过MCP调用一个远程的数据库查询服务,不想引入LangChain或者搞一个复杂的Agent循环。我试了直接发JSON-RPC请求到MCP server的endpoint,但好像还需要处理初始化、能力协商这些步骤,有点懵。想问问各位,MCP本质上是不是要求客户端必须实现完整的Agent生命周期管理?有没有轻量级的方法,比如只做一次“工具发现”然后直接调用,忽略掉那些会话状态?或者说,我是不是理解偏了,MCP压根就不是给这种“单次调用”场景设计的?求指点。
MCP服务器是不是必须配一个Agent框架才能用?直接调用不行吗?
全部回复
共 8 条其实不用一上来就上全套Agent,MCP的核心是那套JSON-RPC握手流程,你只要按规范把initialize和tools/list走一遍,就能拿到工具列表然后直接调了。我之前在FastAPI里就是这么干的,自己写个几十行的客户端类就够了,根本不用LangChain。主要是官方示例太爱绑Claude Desktop,搞得大家以为必须配Agent框架,实际上协议本身是轻量的,你只需要把状态管理(比如session id)自己存一下就行。不过如果你要调的远程服务是别人部署的,最好确认下它支不支持无状态调用,有些server实现会强制要求带上下文,那就得自己维护会话了。
其实你不需要完整的Agent框架,MCP的协议层和Agent逻辑是分开的。官方SDK里有个叫MCPClient的低级类,你只要手动走一遍initialize和tools/list,拿到工具描述后自己构造JSON-RPC调用就行,大概十几行代码的事。我之前在FastAPI里就这么干过,直接封装成一个函数给业务逻辑调,完全没碰LangChain。不过要注意,如果服务端有资源订阅或者采样回调,那确实得自己处理那些通知,但纯工具调用场景真没你想的那么复杂。
其实不用想得那么复杂,MCP的核心就是客户端和服务端之间先握手、再干活,你直接发JSON-RPC当然能通,但初始化那几步绕不开。我试过用官方的Python SDK,几十行就能搞定,不需要LangChain,本质就是创建session然后调listTools。
另外你想做“只发现工具不跑Agent”的话,完全可以,MCP协议里listTools和callTool是分开的,你只调前者拿schema,再自己写逻辑发callTool就行。我自己的一个脚本就这么干的,数据库查询服务暴露成MCP,我这边就是个普通requests循环,没啥Agent味儿。
其实你抓到的点挺准的,MCP底层就是JSON-RPC那套,但初始化协商那步绕不开,官方SDK帮你封装了这层逻辑。我自己试过用Python的mcp库直接建个client会话,不走Agent框架,只调工具发现和调用,代码量很小,完全可行。你那个场景其实不需要管什么生命周期,只要把session建起来,拿工具列表然后call就行,别被那些Agent示例带偏了。
MCP本身不绑定Agent框架,它就是个协议,客户端只要按规范走完initialize、能力协商、tools/list、tools/call这套流程就行。你直接发JSON-RPC其实方向没错,只是initialize那步不能省,服务端要靠它确认版本和capabilities。我之前写过一个几十行的Python客户端,不依赖任何框架,就手动维护session和request id,跑得挺稳。所以不用被那些示例吓到,Agent只是帮你封装了循环,不是必需品。
MCP本身不绑定Agent,你手写JSON-RPC把initialize和tools/call走通就行,就是得自己管会话状态。
不需要Agent框架,MCP本身只是个协议,你完全可以在Python里用httpx或requests手动实现JSON-RPC的initialize、tools/list、tools/call这几步。我之前也以为必须配Claude Desktop,后来发现官方Python SDK里的ClientSession就能直接连,不用带任何Agent逻辑。你说的初始化那步其实就一次握手,把protocolVersion和capabilities发过去就行,之后直接调工具。唯一的坑是stdio和SSE两种传输方式写法不同,远程的话一般走SSE,记得先GET一下拿session id。
不用Agent框架也能跑,MCP的客户端部分其实就是一个JSON-RPC的封装,你完全可以自己手写。关键是要走完initialize握手拿到session,之后tools/list和tools/call就是普通请求了,没那么玄乎。我之前用几十行Python直接怼过,省掉LangChain那一堆依赖,清爽很多。官方SDK里也有client的实现,扒出来改改比从头写快。