☰
php使用Laravel创建MCP服务:TaoToken统一Key接入与本地调试
2026/10/2 6:25:15 网站建设 项目流程

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.0:

composer require php-mcp/laravel:^3.0 -W

-W参数是允许更新依赖树里的其他包,避免版本冲突卡住。装完之后发布配置文件和迁移文件:

php artisan vendor:publish --provider="PhpMcp\Laravel\McpServiceProvider" --tag="mcp-config" php artisan vendor:publish --provider="PhpMcp\Laravel\McpServiceProvider" --tag="mcp-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 之后,不要硬编码在代码里,写进.env:

TAOTOKEN_API_KEY=sk-你的实际Key TAOTOKEN_BASE_URL=https://taotoken.net/api TAOTOKEN_MODEL=claude-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.txt
Resource Templates带 URI 模式的动态资源user://{id}/profile
Prompts对话开场白或模板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_TRANSPORT=sse

SSE 模式下,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 --host=127.0.0.1 --port=8000

服务起来后,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", "--transport=stdio" ] } } }

注意artisan所在的绝对路径要换成你项目里artisan文件的完整路径,比如D:/code/laravel-mcp-demo/artisan。Windows 路径用正斜杠或双反斜杠都行。

验证模型通道是否走 TaoToken,可以加一个调用模型的工具,然后在日志里看请求地址。简单做法是在CalculatorService里加一个方法,用 Laravel 的 HTTP 客户端请求 TaoToken:

use 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 URL,Key 从配置读。你可以在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 Plan:https://taotoken.net/coding-plan 。它适合那种每天都要跟模型打交道的场景,比按次调用省心。

模型对话调试用这个入口:https://taotoken.net/models ,可以直接在页面上试模型返回,确认 Key 和模型 ID 没问题再写进代码。

接入文档在 https://taotoken.net/doc ,里面有完整的 API 说明和示例。遇到不确定的参数,先翻文档再改代码,比瞎试快。

最后留一个我常用的验证顺序:先curl通 MCP 端点,再在客户端里tools/list看到工具,最后调一次tools/call拿到结果。三步都过,说明服务没问题。哪一步卡住,就回到对应小节查报错。这套流程我跑过十几遍,基本能覆盖九成以上的连接问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询