ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

php使用Laravel创建MCP服务:TaoToken统一Key接入与本地调试

php使用Laravel创建MCP服务:TaoToken统一Key接入与本地调试 1. 为什么要在 Laravel 里手搓一个 MCP 服务MCP 服务说白了就是给 AI 客户端准备的一套“工具插座”。你写好的 PHP 函数通过 MCP 协议暴露出去Cursor、Claude Desktop 这类客户端就能像调用本地函数一样调用它。对 PHP 开发者来说Laravel 本身就是干这个的天然好手路由、中间件、服务容器、配置管理全都现成不用再自己搭一套 HTTP 框架。我这次要做的场景很具体用 Laravel 12 从零搭一个 MCP 服务里面放一个加法工具laravel_adder然后把这个服务的模型调用通道统一走 TaoToken 的 Key 和 API 地址。这样做的价值在于你本地调试 MCP 工具时不用在代码里散落一堆不同厂商的 Key一个统一入口就能切换模型、看调用量、排查问题。适合谁看如果你会一点 PHP用过 Composer知道 Laravel 的artisan命令怎么跑那这篇就能直接跟做。如果你完全没碰过 Laravel建议先花半小时把官方文档的“路由”和“中间件”两节过一遍不然配置片段里的路径你会对不上。先说清楚 MCP 服务在 Laravel 里的定位。它不是一个普通的 Web 页面而是一个遵循 MCP 协议的端点。客户端通过 STDIO 或 SSE/Streamable HTTP 两种传输方式跟它通信。STDIO 适合本地进程直连SSE 适合走 HTTP 端口。我在 Windows 环境下试过 STDIO一直连不上换成 SSE 就通了所以后面配置我会以 SSE 为主STDIO 作为备选写出来。整个链路是这样的AI 客户端 → MCP 端点Laravel 路由→ 工具方法CalculatorService::add→ 如果需要模型能力再通过 TaoToken 的统一 API 通道去请求模型。工具本身是纯 PHP 计算不依赖模型但一旦你的工具要调用大模型做总结、翻译、代码生成统一 Key 的价值就出来了。所以这篇的结构是先把 Laravel MCP 服务跑起来能返回结果再把 TaoToken 的 Key 和 Base URL 接进去最后用 curl 验证端点把常见报错一个个排掉。每一步都有可复制的代码你照着敲就行。2. 用 TaoToken 统一 Key 接入前的环境准备与依赖安装在写任何业务代码之前先把地基打好。Laravel 12 对 PHP 版本有要求MCP 的 SDK 也有自己的依赖。我实测下来PHP 8.1 是底线8.2/8.3 更稳。你需要确认这几个扩展开着json、mbstring、pcre。这三个基本是 Laravel 的标配但有些精简版 PHP 镜像会缺pcre跑composer时会报错。先建项目。如果你已经有 Laravel 12 项目跳过这步composer create-project laravel/laravel laravel-mcp-demo 12.* cd laravel-mcp-demo然后装 MCP 的 Laravel SDK。这里用的是php-mcp/laravel版本锁^3.0composer require php-mcp/laravel:^3.0 -W-W参数是允许更新依赖树里的其他包避免版本冲突卡住。装完之后发布配置文件和迁移文件php artisan vendor:publish --providerPhpMcp\Laravel\McpServiceProvider --tagmcp-config php artisan vendor:publish --providerPhpMcp\Laravel\McpServiceProvider --tagmcp-migrations php artisan migrate第一条命令会在config/mcp.php生成配置文件第二条生成数据库迁移第三条执行迁移。MCP 服务需要存一些工具注册信息和调用记录所以有迁移这一步。接下来是 TaoToken 的接入准备。TaoToken 提供统一的 API 通道你只需要一个 Key 和一个 Base URL就能在代码里请求不同模型。先去控制台拿 Key打开 https://taotoken.net/console 创建 API Key然后在 https://taotoken.net/api-keys 管理你的 Key 列表。Base URL 统一用 https://taotoken.net/api。拿到 Key 之后不要硬编码在代码里写进.envTAOTOKEN_API_KEYsk-你的实际Key TAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_MODELclaude-sonnet-4-5然后在config/services.php里加一段映射让 Laravel 能读到taotoken [ key env(TAOTOKEN_API_KEY), base_url env(TAOTOKEN_BASE_URL, https://taotoken.net/api), model env(TAOTOKEN_MODEL, claude-sonnet-4-5), ],这样你在任何地方用config(services.taotoken.key)就能取到 Key不用满项目找。环境变量改完记得清缓存php artisan config:clear php artisan cache:clear到这里Laravel 项目、MCP SDK、TaoToken 的 Key 三样都齐了。下一步开始写路由和工具逻辑。3. 可复制的 Laravel MCP 路由、控制器与 TaoToken 配置片段这一节是核心所有代码都能直接复制。先建路由文件。在routes目录下新建mcp.php?php use App\Services\CalculatorService; use PhpMcp\Laravel\Facades\Mcp; Mcp::tool([CalculatorService::class, add]) -name(laravel_adder) -description(Add two numbers together);这段代码把CalculatorService的add方法注册成一个 MCP 工具名字叫laravel_adder。客户端看到的就是这个名字和描述。然后写工具逻辑。新建app/Services/CalculatorService.php?php namespace App\Services; use PhpMcp\Server\Attributes\McpTool; class CalculatorService { /** * Adds two numbers using a tool. * * param int $a The first number. * param int $b The second number. * return int The sum. */ #[McpTool(name: laravel_adder)] public function add(int $a, int $b): int { $sum $a $b 10000; return $sum; } }注意这里我故意加了 10000方便你验证调用确实走到了这个方法而不是被缓存或别的东西拦截。真实项目里你换成自己的业务逻辑就行。MCP 支持四种元素类型这里列个对照表你按需选类型用途示例Tools执行函数调用计算、发邮件、查数据库Resources通过 URI 访问的静态内容config://settings、file://readme.txtResource Templates带 URI 模式的动态资源user://{id}/profilePrompts对话开场白或模板summarize、translate服务发现默认是开的config/mcp.php里auto_discover为true。你也可以手动跑php artisan mcp:discover php artisan mcp:discover --force php artisan mcp:discover --no-cache第一条是发现并缓存第二条强制重新发现忽略缓存第三条只发现不写缓存。改完工具代码后跑一次--force最保险。接下来把 TaoToken 的配置接进 MCP 服务。如果你希望工具内部调用模型可以在CalculatorService里注入一个 HTTP 客户端走 TaoToken 的 Base URL。这里给一个可复制的配置片段放在config/mcp.php的server段附近server [ name laravel-mcp-demo, version 1.0.0, transport env(MCP_TRANSPORT, sse), taotoken [ base_url env(TAOTOKEN_BASE_URL, https://taotoken.net/api), key env(TAOTOKEN_API_KEY), model env(TAOTOKEN_MODEL, claude-sonnet-4-5), ], ],然后在.env里补上传输方式MCP_TRANSPORTsseSSE 模式下MCP 端点默认挂在/mcp。你可以在routes/mcp.php里确认路由注册或者用php artisan route:list看php artisan route:list | grep mcp应该能看到mcp:serve相关的路由。如果没看到检查bootstrap/app.php里有没有加载routes/mcp.php。Laravel 12 默认只加载web.php和console.php你需要手动加-withRouting( web: __DIR__./../routes/web.php, commands: __DIR__./../routes/console.php, then: function () { Route::middleware(api) -group(base_path(routes/mcp.php)); }, )这段加在bootstrap/app.php的withRouting里。加完之后再跑route:list就能看到 MCP 路由了。4. 启动服务并用 curl 验证 MCP 端点返回结果配置写完启动 Laravel 开发服务器php artisan serve --host127.0.0.1 --port8000服务起来后MCP 端点在http://127.0.0.1:8000/mcp。先用 curl 探一下 SSE 握手curl -N -H Accept: text/event-stream http://127.0.0.1:8000/mcp-N是禁用缓冲让你实时看到 SSE 流。正常的话你会看到类似event: endpoint和data: /mcp/message的输出。如果卡住不动说明路由没通或者中间件拦了。接下来发一个真正的工具调用请求。MCP 的 JSON-RPC 格式长这样curl -X POST http://127.0.0.1:8000/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d { jsonrpc: 2.0, id: 1, method: tools/call, params: { name: laravel_adder, arguments: { a: 3, b: 4 } } }预期返回里result.content会包含10007因为3 4 10000 10007。如果你看到这个数字说明整条链路通了路由 → 工具注册 → 方法执行 → 结果返回。再验证一下工具列表curl -X POST http://127.0.0.1:8000/mcp \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 2, method: tools/list }返回里应该能看到laravel_adder的名字和描述。这一步能帮你确认服务发现有没有生效。如果你要在 Cursor 或 Claude Desktop 里接SSE 方式的配置是{ mcpServers: { laravel_adder: { url: http://127.0.0.1:8000/mcp } } }STDIO 方式我也写出来但 Windows 下我实测连不上你可以试试{ mcpServers: { laravel_adder: { command: php, args: [ artisan所在的绝对路径, mcp:serve, --transportstdio ] } } }注意artisan所在的绝对路径要换成你项目里artisan文件的完整路径比如D:/code/laravel-mcp-demo/artisan。Windows 路径用正斜杠或双反斜杠都行。验证模型通道是否走 TaoToken可以加一个调用模型的工具然后在日志里看请求地址。简单做法是在CalculatorService里加一个方法用 Laravel 的 HTTP 客户端请求 TaoTokenuse Illuminate\Support\Facades\Http; public function askModel(string $prompt): string { $response Http::withToken(config(services.taotoken.key)) -post(config(services.taotoken.base_url) . /v1/messages, [ model config(services.taotoken.model), max_tokens 256, messages [ [role user, content $prompt], ], ]); return $response-json(content.0.text, ); }这段代码把请求打到 TaoToken 的 Base URLKey 从配置读。你可以在storage/logs/laravel.log里看到实际请求确认没有走错地址。5. 本篇常见报错排查401、local proxy failed、reading choices、OAuth这一节把我踩过的坑列出来你对照报错直接定位。401 Unauthorized。最常见的原因是 Key 没读到或者格式不对。先确认.env里TAOTOKEN_API_KEY没有多余空格然后跑php artisan config:clear。如果还报 401检查config/services.php里的键名是不是taotoken代码里取的是config(services.taotoken.key)。另外确认请求头是Authorization: Bearer sk-xxx不是x-api-key。local proxy failed。这个报错通常出现在客户端连 MCP 端点时。原因一般是端点地址写错或者 Laravel 服务没起来。先curl http://127.0.0.1:8000/mcp看有没有响应。如果 curl 通但客户端不通检查客户端配置里的 URL 是不是http://127.0.0.1:8000/mcp不要写成localhost有些客户端解析localhost会走 IPv6 导致连不上。reading choices 相关报错。这个一般出现在你调用模型接口时返回体不是预期的 JSON 结构。比如你请求 TaoToken 的/v1/messages但返回的是错误页。先看storage/logs/laravel.log里的原始响应确认base_url拼对了。https://taotoken.net/api后面接/v1/messages不要重复加/api。OAuth 报错。MCP 客户端有些版本会尝试 OAuth 流程如果你的服务没配 OAuth就会报错。解决办法是在客户端配置里显式指定不需要认证或者用 SSE 方式直连。如果你在 Cursor 里看到 OAuth 相关提示检查 MCP 配置里有没有多余的auth字段删掉再试。再补一个 Windows 下 STDIO 连不上的排查。我试过把artisan路径写成相对路径客户端找不到写成绝对路径后还是连不上换 SSE 就通了。如果你非要用 STDIO确认php命令在系统 PATH 里用where php能查到。查不到就把command换成php的绝对路径。还有一个容易忽略的点MCP 服务发现缓存。你改了工具代码但客户端看到的还是旧描述跑php artisan mcp:discover --force强制刷新。如果还不行删掉bootstrap/cache下的缓存文件再试。最后如果你在工具里调 TaoToken 的模型接口报model not found检查TAOTOKEN_MODEL的值是不是 TaoToken 支持的模型 ID。去 https://taotoken.net/doc 看模型列表别自己编名字。6. 把 MCP 服务接进日常开发流的几个实用动作服务跑通之后别让它停在 demo 状态。我平时会做三件事让它真正进开发流。第一件把 MCP 端点加到项目的 README 或者团队文档里写清楚启动命令和客户端配置。这样换台机器或者同事接手不用重新踩一遍坑。配置片段直接贴 SSE 那段 JSON改个端口就能用。第二件给工具加日志。MCP 调用出问题时光看客户端报错很难定位。在CalculatorService的方法里加一行Log::info(laravel_adder called, [a $a, b $b]);然后tail -f storage/logs/laravel.log调用有没有进来一目了然。第三件把模型调用统一收口到 TaoToken。你可以在config/services.php里只留一份 Key所有需要模型的地方都走config(services.taotoken)。这样换模型、查用量、排故障都只在一个地方操作。需要看调用记录就去 https://taotoken.net/console需要管 Key 就去 https://taotoken.net/api-keys。如果你要长期跑编码类 Agent或者 MCP 工具里频繁调模型可以看看 Coding Planhttps://taotoken.net/coding-plan 。它适合那种每天都要跟模型打交道的场景比按次调用省心。模型对话调试用这个入口https://taotoken.net/models 可以直接在页面上试模型返回确认 Key 和模型 ID 没问题再写进代码。接入文档在 https://taotoken.net/doc 里面有完整的 API 说明和示例。遇到不确定的参数先翻文档再改代码比瞎试快。最后留一个我常用的验证顺序先curl通 MCP 端点再在客户端里tools/list看到工具最后调一次tools/call拿到结果。三步都过说明服务没问题。哪一步卡住就回到对应小节查报错。这套流程我跑过十几遍基本能覆盖九成以上的连接问题。
返回列表