PHP官方MCP SDK实战:把老项目变成AI工具箱
发布时间:2026/9/30 11:48:01来源:尧图网络
PHP 在 AI 这件事上憋了太久。这几年每次聊到大模型应用脚本语言这边的存在感基本都被 Python 和 Node.js 包圆了PHP 社区能拿得出手的大多是零散的民间封装。直到 PHP 官方 MCP SDK 正式发布的消息落地我第一时间就去仓库把代码拉下来跑了一遍——上手之后最大的感受是PHP 终于不是 AI 生态里的旁观者了。这篇文章我不打算照念官方文档就按我自己从安装、写 Server、接到大模型客户端、再实际调用的全过程把 PHP 官方 MCP SDK 是什么、为什么重要、怎么用、有哪些坑一次讲透。先给还没关注过这块的同学交代一句背景MCP 是 Model Context Protocol 的缩写即模型上下文协议是 2024 年底由 Anthropic 提出的开放标准目标是把大模型和外部数据、工具之间的连接方式统一起来。而 PHP 官方 MCP SDK就是 PHP 官方组织发布的、用于在 PHP 项目里实现 MCP Server 和 MCP Client 的正式开发工具包。如果你的目标是给 PHP 老项目接上 AI 能力或者想让 AI Agent 能安全地调用 PHP 写的内部服务这篇文章正好适合你。下面按理解概念 → 拆解设计 → 实操上手 → 进阶玩法 → 踩坑排查的顺序来讲基础偏弱的同学也能跟着跑通。1. MCP 到底是什么PHP 官方这次是在补哪块短板1.1 把 MCP 理解成 AI 世界的 USB-C要理解 PHP 官方为什么专门发一个 MCP SDK先得明白 MCP 解决的是什么问题。你把大模型想象成一台只给了一两个 USB-C 口的电脑这台电脑能力很强但它看不到你硬盘里的数据也控制不了你外接的打印机。AI 行业早期就是这样每个模型厂商有自己的一套连接方式你想让模型读数据库、查订单、调内部接口就得为每个模型写一套定制代码换个模型等于重写接入层。MCP 做的事情是定义了一个统一的接口规范。它把大模型需要的外部能力抽象成三种基本东西工具Tools、资源Resources和提示词模板Prompts。工具是模型可以主动调用的函数比如查询库存资源是模型可以读取的数据比如一份订单列表或者配置文件提示词模板是预先编排好的工作流比如生成周报的固定套路。三者都通过 JSON-RPC 2.0 协议进行消息交互传输方式可以是本地进程间的 stdio也可以是走网络的 HTTP 长连接。这就是为什么有人把 MCP 比作 AI 世界的 USB-C它不关心你背后是 PHP、Python 还是 Java只要实现同一个协议任何模型客户端都能对话。对于 PHP 开发者来说MCP 意味着我们不需要把自己现有的业务逻辑翻译成大模型厂商私有的格式只需要包一层标准接口模型就能用了。1.2 PHP 生态此前的尴尬处境MCP 标准刚出来那阵子官方提供的 SDK 只有 Python 和 TypeScript 两套。Python 生态有大模型原生优势TypeScript 有 Anthropic 自家客户端和 Node 社区撑着两边都有官方实现、完整测试和持续维护。而 PHP 这边只有几个社区个人维护的库功能覆盖不完整有的只实现了 Server 端有的传输层只支持老旧的 SSE遇到协议升级基本就断了维护。更尴尬的是PHP 在存量业务里其实非常庞大。电商、OA、ERP、后台管理系统大量核心业务逻辑都跑在 PHP 进程里。这些系统恰恰是最需要 AI 能力的让客服机器人查订单、让运营助手读报表、让告警机器人查日志。但因为没有官方 SDKPHP 项目接 AI 的路径非常曲折要么用 Python 写一个中间服务把 PHP 数据导出过去架构复杂不说还多了一层出问题的概率要么等社区库更新但生产环境谁敢把核心业务压在一个个人维护的库上PHP 官方这次发布 MCP SDK等于是把标准实现、测试覆盖、后续维护这摊责任接了过来。对于大量 PHP 存量系统来说这是一条可以走稳的路Composer 装一个官方包写几十行代码就能把老系统里的接口暴露给大模型。1.3 官方 SDK 里到底装了什么我拉下代码看了一圈这个 SDK 的服务范围很清晰主要包含这几块MCP Server 端能力用于把 PHP 代码封装成 MCP 服务供 Claude Desktop、Cursor 这类支持 MCP 的客户端连接也支持自定义工具、资源、提示词模板的注册和管理。MCP Client 端能力用于在 PHP 程序里作为客户端去连接外部已经部署好的 MCP Server相当于让我们自己的 PHP 服务也能调用别人家的 AI 工具。传输层实现覆盖 stdio 和基于 HTTP 的 Streamable HTTP 两种主流传输方式分别对应本地开发和远程服务两种部署形态。协议消息处理包括初始化握手、能力协商、工具列表拉取、工具调用、错误上报等完整流程这些细节如果自己实现非常容易踩坑。一句话总结这个 SDK 的目标不是给你一个调大模型 API 的封装而是给你一套完整的AI 工具互联基础设施。调模型你仍然可以用各种 LLM 客户端库但连接模型与业务系统之间的这层协议官方帮你做好了。2. 官方 MCP SDK 的技术拆解架构、传输层与设计取舍2.1 核心组件Server、Client 和三种协议原语我实际翻代码时发现SDK 的设计并不复杂核心就两个大角色McpServer 和 McpClient。这两个类分别对应协议的两端而它们之间流动的消息全部围绕工具、资源、提示词模板这三类原语展开。Server 端的工作方式很直观。你先创建一个 Server 实例告诉它服务名和版本号然后通过链式方法注册工具。每个工具需要有名字、描述、输入参数定义和处理函数。协议层面的连接管理、消息编解码、错误处理都在 Server 内部完成你只需要专注于业务逻辑。Client 端则反过来连接到一个远程或本地的 Server 地址可以列出对方有哪些工具然后按需调用。这个设计的好处是边界清晰。对于大多数 PHP 业务系统来说绝大多数场景只需要 Server 端把现有的订单查询函数、库存扣减逻辑、文案生成接口包成工具让大模型来调用。而 Client 端更适合做AI 网关类的项目PHP 作为中枢程序统一对接多个外部 MCP 服务把不同来源的 AI 能力编排成一个整体。2.2 stdio 与 Streamable HTTP两种传输怎么选传输层是 MCP 协议里最容易被忽略、但直接影响稳定性的部分。官方 SDK 提供了两种主流传输方式我强烈建议你在动手前先把这两者的区别想清楚。stdio 传输的意思是MCP Server 以子进程的方式被客户端拉起两者通过标准输入输出通信。Claude Desktop 配置一个本地 MCP 服务本质就是让 Claude 帮你执行一条命令比如php /path/to/server.php然后父子进程之间用 JSON-RPC 消息对话。stdio 的优点是零网络配置、安全性高、进程生命周期由客户端管理非常适合本地开发和单机工具。缺点也很明显Server 和客户端必须在一台机器上没法跨网络部署。Streamable HTTP 则解决了远程访问的问题。Server 以 HTTP 接口的形式运行客户端通过 HTTP 请求来初始化会话、发送消息、接收响应。这种传输适合部署在服务器上的业务系统让远程的 AI 客户端或团队内部的其他服务来调用。我自己的经验是开发调试阶段用 stdio 最省事一旦要部署到生产环境、要让多个客户端共享服务就必须上 Streamable HTTP同时配好身份认证和访问控制。2.3 为什么 Tool 的参数要用 JSON Schema 定义这是官方 SDK 里最值得细看的一个设计点。注册工具的时候除了名字和描述还必须提供一个输入参数定义格式是 JSON Schema。很多第一次接触的同学会问不就是参数吗直接在代码里声明不行吗原因在于调用工具的不是人而是大模型。模型需要根据你给的描述和参数定义自己判断什么时候该调用这个工具、参数该怎么填。JSON Schema 在这里就是给模型看的说明书properties 里写了参数名、类型、说明required 里标了哪些必填模型会照着这个 schema 生成一次标准化的调用请求。你在 schema 里把参数描述写得越清楚模型调用成功的概率就越高。举个我们后面实操会遇到的例子一个温度换算工具如果只写celsius: number模型可能不确定传摄氏还是华氏但如果 description 里写明请输入摄氏温度值模型就会很自然地传对。写 PHP 的 MCP 工具本质上是在跟一个聪明的陌生人协作你需要把话说清楚而不是像写内部函数那样默认别人都懂上下文。2.4 官方实现里值得注意的几个细节SDK 里有些细节是我研究源码时发现的对实际使用影响很大。一是消息处理是同步的但对于耗时较长的工具调用协议层面支持进度上报。这意味着如果你有一个查询要跑好几秒不能傻等应该在处理函数里主动上报进度否则客户端那边容易超时误判。二是 SDK 对输入做了严格的类型校验。PHP 是弱类型语言但 MCP 协议要求严格按 schema 来传错类型会直接抛异常。这个设计初看有点烦生产环境里其实是保护伞避免脏数据一路传到业务逻辑层。三是官方实现了完整的initialize握手和协议版本协商。MCP 协议还在快速演进客户端和 Server 可能是不同版本SDK 会自动协商到一个双方都支持的版本避免因为版本不匹配直接崩掉。这一点在社区老库里是普遍缺失的。3. 实操从零搭一个 PHP MCP Server 并接到 Claude Desktop3.1 环境准备PHP 8.2 与 Composer先说环境要求。官方 SDK 要求 PHP 8.2 及以上版本需要启用常用的 JSON、PCNTL 等扩展。PCNTL 在 Windows 下不可用所以如果你用的是 Windows 开发环境建议装个 WSL 或者直接用 Docker 跑 PHP 容器后面处理信号和长驻进程都会省心很多。Composer 是必须的装包全靠它。检查完环境后建议先用php -v确认版本用php -m看看扩展列表。我自己的开发机是 PHP 8.3 Linux整个流程非常顺如果你还在用 PHP 7.4 或者更老的版本建议先把项目升级一下再来碰 MCP老版本的类型系统和协程支持都撑不住这套东西。3.2 安装 SDK安装就一条命令composer require php/mcp-sdk装完可以在vendor/php/mcp-sdk目录下看到源码和示例。官方包里带了几个 example 文件我建议先跑一下官方示例确认环境没问题再开始写自己的 Server。这里多说一句不同小版本的 API 命名可能会有细微差别网上教程如果出现了和本地不一样的类名或方法名以你装到的版本源码为准不要盲目复制粘贴。3.3 写一个温度换算工具 Server我习惯用最简单的例子验证整条链路所以先写一个摄氏度和华氏度互转的工具。代码如下?php declare(strict_types1); use PhpMcp\McpServer; use PhpMcp\Transport\StdioTransport; require __DIR__ . /vendor/autoload.php; $server new McpServer(php-demo-server, 1.0.0); $server-tool(celsius_to_fahrenheit) -description(将摄氏温度转换为华氏温度) -inputSchema([ type object, properties [ celsius [ type number, description 摄氏温度值例如 25 表示 25 摄氏度, ], ], required [celsius], ]) -handle(function (array $args): array { $celsius (float) $args[celsius]; $fahrenheit $celsius * 9 / 5 32; return [ result [ celsius $celsius, fahrenheit $fahrenheit, ], ]; }); $server-run(new StdioTransport());这里有几个关键点。description不只是给人看的更是给模型看的调用提示务必写清楚单位、示例和边界。inputSchema严格定义了输入结构模型会基于这个结构生成参数。handle闭包接收到的$args已经是经过校验的关联数组你可以放心使用。返回值直接返回数组即可SDK 会帮你包装成协议要求的格式。注意这里我先实现了一个工具。如果你想注册多个工具就在同一个 Server 实例上继续链式调用$server-tool(...)即可完全没问题。3.4 用 MCP Inspector 做冒烟测试写完之后别急着配客户端先用官方调试工具 MCP Inspector 验证一下协议是否正常。启动方式很简单npx modelcontextprotocol/inspector php server.phpInspector 会启动一个本地调试界面帮你以图形化方式连接你的 Server。进去之后能看到三块工具列表、资源列表、提示词列表。如果 Tools 下面出现了celsius_to_fahrenheit点击 Call 按钮、填上参数能正确返回结果说明你的 Server 已经从协议层面跑通了。这一步非常推荐因为实际和大模型客户端对接时问题出在哪边往往很难判断。用 Inspector 先把 Server 独立验证一遍后面出问题就知道锅不在 Server。3.5 配置 Claude Desktop 连接Server 验证通了接下来把它接到真正的 AI 客户端里。以 Claude Desktop 为例配置方法是在客户端的配置文件里加一段 MCP Server 注册。macOS 的配置文件在~/Library/Application Support/Claude/claude_desktop_config.jsonWindows 在%APPDATA%\Claude\claude_desktop_config.json。配置内容{ mcpServers: { php-demo: { command: php, args: [/absolute/path/to/server.php] } } }注意command要写 PHP 可执行文件的绝对路径或者确保php在 PATH 里args里的路径也必须是绝对路径。改完配置重启客户端在对话里问一句25 摄氏度等于多少华氏度如果模型调用了你的工具并返回 77就说明整条链路已经打通。我自己第一次测试时还故意用了一个模糊的问法25 度是多少华氏模型居然也能正确调用这就是描述写得清楚的功劳。你要是发现模型总是拒绝调用或者调用时参数填错大概率是 description 写得不够明确。4. 进阶玩法把 PHP 业务系统改造成 AI 工具箱4.1 用 Resource 暴露订单数据工具适合动作资源适合数据。假设你有一个电商系统想让 AI 助手能读取订单信息工具思路是写一个query_order函数让模型调用但更 MCP 的做法是注册一个资源。资源通过 URI 标识支持路径参数客户端可以直接读取。$server-resource(orders://{date}) -uriTemplate(orders://{date}) -description(获取指定日期的订单数据日期格式 YYYY-MM-DD) -load(function (array $variables): array { $date $variables[date]; $rows $orderRepository-findByDate($date); return [ content [ [ type text, text json_encode($rows, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), ], ], ]; });这样注册之后模型看到的数据引用就是orders://2025-06-18这样的地址。资源的好处是可复用、可缓存、语义清晰适合展示类数据而需要模型主动做动作的场景比如扣库存、发短信仍然应该用工具。实际项目里通常是资源和工具配合使用模型先读资源了解数据再调用工具执行操作。4.2 用 Prompt 固化业务流程第三个原语是 Prompt它适合把固定套路沉淀下来。比如你希望 AI 每次处理客户投诉时都先查订单、再判断是否超时、最后生成回复模板这些步骤如果让它自由发挥每次结果都不一样。用 Prompt 模板可以约束行为$server-prompt(handle_complaint) -description(处理客户投诉的标准流程) -arguments([ orderId [type string, description 订单号], ]) -messages(function (array $args): array { return [ [ role user, content [ type text, text 请按以下流程处理订单 . $args[orderId] . 的投诉 . 1. 查询订单状态2. 判断是否超时发货 . 3. 生成给客户的道歉与补偿方案。, ], ], ]; });这种能力非常适合内部知识库、运营后台或者客服系统。把业务专家的处理经验固化成 PromptAI 就能按同一套标准执行减少人为差异。注意 Prompt 本身不执行逻辑它只是生成一段结构化的提示词真正调用工具还是靠模型自己判断。4.3 反向操作PHP 当 Client 消费远程 MCP前面都在讲 Server 端其实 Client 端同样好用而且我认为这是 PHP 未来在 AI 架构里的一个重要角色。举个实际场景你的 PHP 后台系统想集成一个外部的 AI 能力服务对方已经用 MCP 协议发布了接口这时候不需要你去调对方的私有 API直接用官方的 Client 端连接即可。?php declare(strict_types1); use PhpMcp\McpClient; use PhpMcp\Transport\StreamableHttpTransport; require __DIR__ . /vendor/autoload.php; $transport new StreamableHttpTransport(https://mcp.example.com/mcp); $client new McpClient($transport); $client-connect(); $tools $client-listTools(); foreach ($tools as $tool) { echo $tool[name] . PHP_EOL; } $result $client-callTool(celsius_to_fahrenheit, [celsius 30]); print_r($result); $client-disconnect();这个模式意味着 PHP 不再是只会被调用的后端它可以作为编排中枢主动去调用分布式的 AI 工具服务。团队里不同语言的系统可以基于 MCP 互联而 PHP 通过官方 SDK拥有了完整的发言权。4.4 两个真实场景场景一ERP 系统的 AI 助手。传统 ERP 是 PHP 写的查询逻辑都在数据库存储过程和服务层里。用官方 SDK 包一层 MCP Server注册查库存查订单生成对账单三个工具前端聊天框接上大模型员工用自然语言就能查数不用再教他们操作复杂菜单。场景二运维告警机器人。PHP 写的监控系统检测到线上异常时不再只是往群里丢一条告警而是通过 Client 端调用一个诊断用 MCP Server让 AI 分析日志、定位根因、给出处置建议再回填到工单系统。整个过程都是 PHP 自己在编排。这两个场景的共同点是业务逻辑复杂、历史包袱重、原始数据在 PHP 这边而 MCP SDK 正好把复杂逻辑和AI 理解之间的鸿沟填上了。5. 这些坑我替你先踩了常见问题与排查思路5.1 最经典的坑stdout 被日志污染如果问我这套东西最容易出的问题是什么我一定会说是这个。stdio 模式下的 MCP Server所有信息和客户端交互都是通过标准输出进行的所以你的代码里绝对不能有echo、print_r、var_dump这类直接往标准输出写内容的操作包括调试用的日志函数一旦输出了一行非协议内容整个连接就会失败而且错误信息往往很奇怪。排查思路也很简单先用php server.php手动跑一下看控制台有没有多出不该有的输出如果有把日志改用文件存储或者error_log写到 stderr。我在第一次测试时就是因为在处理函数里加了个var_dump调试结果客户端直接报连接中断排查了半天才发现是这行输出的锅。5.2 工具描述写不好模型就是不用第二个高频问题模型不调用你的工具或者调用了但参数总是错。我在项目里见过太多人只给工具写一句查询库存模型根本不知道什么时候该用它。工具描述应该包含什么情况下调用、参数的单位和含义、返回结果的形式。描述写得像写给同事的接口文档而不是写给编译器看的注释。Command 方式还有一个常见问题有些业务逻辑比较重的工具需要十几秒才能返回客户端可能已经超时。这种工具要么拆分减小粒度要么使用协议里的进度上报机制不要在没有任何反馈的情况下让客户端干等。5.3 长驻进程的信号处理用 Streamable HTTP 方式部署时Server 是一个常驻的 PHP 进程需要考虑优雅退出。如果直接kill掉进程正在处理中的请求会丢失客户端拿到一个莫名的连接错误。官方 SDK 里借助 PCNTL 扩展做了信号处理但我还是建议你在自己的代码里主动考虑平滑退出收到 SIGTERM 时停止接收新请求等待正在执行的任务完成后再退出。另外部署 HTTP 传输时不要忘了安全。MCP Server 暴露在网络上意味着任何人都可能让你的 PHP 服务执行工具如果没有认证等于裸奔。建议在 Server 前加 API Key 校验或网关层鉴权工具内部还要再做一层权限控制尤其是那些涉及写操作的业务工具。这个安全意识怎么强调都不过分。5.4 版本与扩展兼容性第三类问题集中在环境层面。官方 SDK 要求 PHP 8.2我见过有同学在 8.1 环境上报各种莫名的语法错误还有依赖的 JSON、PCNTL 扩展没装一启动就报未定义函数。建议动手前先跑一遍composer check-platform-reqs把环境问题一次性暴露出来不要等代码写完才发现装不了。5.5 问题速查表现象大概率原因解决办法客户端提示连接中断stdout 被日志或调试输出污染清理 echo/var_dump日志写文件或 stderr工具列表为空Server 未启动或协议版本不兼容用 MCP Inspector 单独测试 Server模型不调用工具description 不明确、缺少触发条件重写描述说明何时用、参数含义调用参数总出错JSON Schema 定义不完整补全 properties、required、类型和描述HTTP 模式连不上未配置认证、端口被防火墙拦截检查鉴权配置确认网络策略与 CORS进程被杀后客户端报错缺少优雅退出处理使用 PCNTL 信号处理等待任务完成再退出这张表基本覆盖了我实操中遇到的大部分问题。如果你遇到的不在里面我的建议是先用 Inspector 把 Server 独立验证再逐层排查客户端配置和网络这类问题八成能定位。最后再分享一个小技巧初期做技术验证时不要一上来就接复杂的业务系统。像我一样先用一个温度换算、字符串处理这类无状态工具把链路打通再慢慢往里面加真实业务。链路通了之后再出问题排查范围就小得多。这套 SDK 的定位本来就是基础设施基础设施稳了上面跑什么业务都踏实。我对 PHP 在 AI 生态里的前景反而比前两年乐观了不少——毕竟存量业务和成熟的工程体系本来就是 PHP 最大的本钱。
网站建设高端定制企业官网