谈谈mcp协议的实现

概述

大概是24年开始听说,mcp 协议。刚开始听说时不太感兴趣。主要的原因是太过自然了。往大了说,虽然 mcp 和 rag 的实现细节差距很大,本质上都是从模型外部获取信息和计算能力。这篇blog记录我从mcp server helloworld 到学习其实现的过程。

hello world

使用cursor。通过下面的提示词,生成了一个能计算加减乘除的 mcp server,并直接在 cursor 中使用。

  1. 写一个 mcp server,提供简单的 加减乘除 计算功能,用python3 实现。

  2. 给出cursor 使用这个mcp server 的配置示例。

    配置比较短,就这这里贴一下:

    复制代码
    {
    >   "mcpServers": {
     "calculator": {
       "command": "python",
       "args": ["D:/work/code/mcp_hello_world/server.py"],
       "env": {},
       "autoApprove": ["add", "subtract", "multiply", "divide"],
       "disabled": false
     }
      }
    }

    通过代码的变更,故意加上一个magic number,验证了 mcp server 是生效的。

    如何实现?

    在协议设计方面,对程序员来说太熟悉了。比较感兴趣的是,如何粘合llm和mcp server,llm的输入输出是文字,mcp server的输入输出是rpc调用,个人直觉是通过提示词工程做的,结果果真如此。

    注意,下面的文本绘图是我个人的理解,未全部通过看代码&调试证实,因segfragment的mermaid代码版本过低,渲染顺序不是自上而下。

    Backend 层

    MCP Protocol 协议层

    GUI/Text UI 层

    1. 输入需求

    2. 查询能力

    3. 返回能力

    4. 传入参数

    5. 输出参数

    6. 调用服务

    7. 返回结果

    8. 反馈结果

    LLM Model

    MCP Client

    MCP Server

    用户

    我先从 modelcontextprotocol 中寻找对应提示词,在cursor 输入指令,没有找到相关代码:

    分析这个工程。
    给出 "Client 先向 LLM 发送包含 MCP 调用规则的提示词,强制 LLM 输出符合 MCP 规范的 JSON 格式(而非自然语言),示例提示词" 相关的文件。

不在protocol中定义提示词,那只能是client中了。于是从sdk代码中找到了一个例子。

commit_hash:a9cc822a1051b1bd2b6b9b57e9e4136406983b61

python-sdk\examples\clients\simple-chatbot\main.py:331

复制代码
    async def start(self) -> None:
        """Main chat session handler."""
        try:
            for server in self.servers:
                try:
                    await server.initialize()
                except Exception as e:
                    logging.error(f"Failed to initialize server: {e}")
                    await self.cleanup_servers()
                    return

            all_tools = []
            for server in self.servers:
                tools = await server.list_tools()
                all_tools.extend(tools)

            tools_description = "\n".join([tool.format_for_llm() for tool in all_tools])

            system_message = (
                "You are a helpful assistant with access to these tools:\n\n"
                f"{tools_description}\n"
                "Choose the appropriate tool based on the user's question. "
                "If no tool is needed, reply directly.\n\n"
                "IMPORTANT: When you need to use a tool, you must ONLY respond with "
                "the exact JSON object format below, nothing else:\n"
                "{\n"
                '    "tool": "tool-name",\n'
                '    "arguments": {\n'
                '        "argument-name": "value"\n'
                "    }\n"
                "}\n\n"
                "After receiving a tool's response:\n"
                "1. Transform the raw data into a natural, conversational response\n"
                "2. Keep responses concise but informative\n"
                "3. Focus on the most relevant information\n"
                "4. Use appropriate context from the user's question\n"
                "5. Avoid simply repeating the raw data\n\n"
                "Please use only the tools that are explicitly defined above."
            )

上述代码只是example,无法证明实际的实现也是如此。我找了google python-genai的代码,发现llm 的api已经将 tools封装了。openai 家的也是如此:
openai function-calling。

只阅读了 google python-genai 的代码,tools参数在sdk层只是通过 json rpc 将参数传递给 llm server 服务。提示词拼装(如果有)的部分很可能在闭源的 llm server 服务中。

总结

  1. cursor 等 ai 编码工具对 快速生成demo,寻找xx实现,总结代码等细分场景效果很好。
  2. 鉴于llm的输入是token, 即自然语言,mcp-server 和 llm-server 的胶水层大概率是 隐藏在 llm-server 服务的提示词工程。

行业拓展

分享一个面向研发人群使用的前后端分离的低代码软件------JNPF。

基于 Java Boot/.Net Core双引擎,它适配国产化,支持主流数据库和操作系统,提供五十几种高频预制组件,内置了常用的后台管理系统使用场景和实用模版,通过简单的拖拉拽操作,开发者能够高效完成软件开发,提高开发效率,减少代码编写工作。

JNPF基于SpringBoot+Vue.js,提供了一个适合所有水平用户的低代码学习平台,无论是有经验的开发者还是编程新手,都可以在这里找到适合自己的学习路径。

此外,JNPF支持全源码交付,完全支持根据公司、项目需求、业务需求进行二次改造开发或内网部署,具备多角色门户、登录认证、组织管理、角色授权、表单设计、流程设计、页面配置、报表设计、门户配置、代码生成工具等开箱即用的在线服务。

相关推荐
夏幻灵1 小时前
JavaScript this 面试:五种绑定规则、优先级与常见面试陷阱
开发语言·javascript·面试
程序猿编码1 小时前
榨干 RTX5090 算力!Qwen3 专用单卡推理引擎,手写C++/CUDA 算子实现 MTP 推测解码
开发语言·c++·大模型推理·qwen3·多模态推理
西飘客2 小时前
vs 怎么根据dll 生成lib文件
c++·qt
bkspiderx3 小时前
Qt 插件机制:动态扩展应用功能的核心框架
开发语言·qt·元数据·qt 插件·qpluginloader
程序员老陆3 小时前
深入理解 C++ thread_local:线程私有存储的正确打开方式
开发语言·c++·程序设计
沐晓时光3 小时前
C语言入门,深入理解指针(3)
c语言·开发语言
码云数智-园园4 小时前
unique_ptr 还是 shared_ptr?C++ 智能指针选型与内存泄漏实战分析
java·开发语言
禾小西4 小时前
07丨Redis 哨兵机制:主库故障后,如何恢复服务?
java·开发语言·redis
我不是阵雨4 小时前
JDK 21虚拟线程Pinning陷阱:一文拔钉解困
java·开发语言
徐小黑ACG5 小时前
Golang 基础05 结构体struct
开发语言·算法·golang