首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Webman MCP Server 实战:让 Agent 真正调用你的 PHP 方法

Webman MCP Server 实战:让 Agent 真正调用你的 PHP 方法

作者头像
Tinywan
发布于 2026-09-15 14:30:14
发布于 2026-09-15 14:30:14
1670
举报
文章被收录于专栏:开源技术小栈开源技术小栈

概述

不用手写协议实现,tinywan/webman-mcp 开箱即用,原生对齐 MCP 2026-07-28 标准协议,无缝对接 Neuron AI / Codex 等智能体。

本文就基于这个扩展,从零到一搭建订单查询 MCP 服务,并完成与 Neuron AI 智能体的全链路对接。

环境要求

  • PHP >= 8.2
  • Webman >= 2.1
  • Composer 2.x
  • 支持工具调用的大模型 API Key(DeepSeek / OpenAI / 通义千问等)

快速搭建 MCP 服务端

1. 安装扩展

在你的 Webman 项目根目录执行:

代码语言:javascript
复制
composer require tinywan/webman-mcp

安装后扩展会自动发布配置文件到 config/plugin/tinywan/webman-mcp/ 目录,无需手动初始化。

2. 生成服务与工具脚手架

扩展提供了内置的生成命令,一键创建服务定义和工具类骨架。

我们以「订单查询 MCP 服务」为例,执行两条命令:

代码语言:javascript
复制
# 生成 MCP 服务定义类
php webman make:mcp-server Order

# 生成工具类
php webman make:mcp-tool OrderQuery

执行后会在 app/mcp/ 目录下生成两个核心文件:

  • OrderServer.php:服务定义,负责注册工具、配置认证授权、绑定路由路径
  • OrderQueryTool.php:具体的工具实现,包含工具元数据定义和业务调用逻辑

3. 实现业务工具类

打开 app/mcp/OrderQueryTool.php,实现订单查询的业务逻辑。 工具类必须实现 ToolInterface 接口,核心是两个方法:

  • definition():定义工具名称、描述、参数 Schema、返回值 Schema(扩展自动做入参出参校验)
  • call():工具实际执行的业务逻辑
代码语言:javascript
复制
<?php
declare(strict_types=1);

namespace app\mcp;

use Tinywan\Mcp\Contracts\ToolInterface;
use Tinywan\Mcp\Runtime\ExecutionContext;
use Tinywan\Mcp\Tool\Content\TextContent;
use Tinywan\Mcp\Tool\ToolCall;
use Tinywan\Mcp\Tool\ToolDefinition;
use Tinywan\Mcp\Tool\ToolResult;

final class OrderQueryTool implements ToolInterface
{
    public function definition(): ToolDefinition
    {
        return new ToolDefinition(
            name: 'query_order_snapshot',
            description: '根据订单号查询订单状态、物流进度、售后政策和处理建议,仅支持只读查询',
            inputSchema: [
                'type' => 'object',
                'properties' => [
                    'order_no' => [
                        'type' => 'string',
                        'description' => '订单号,格式示例:ORDER-20260621-1001'
                    ]
                ],
                'required' => ['order_no'],
                'additionalProperties' => false,
            ],
            outputSchema: [
                'type' => 'object',
                'properties' => [
                    'order_no' => ['type' => 'string', 'description' => '订单号'],
                    'status' => ['type' => 'string', 'description' => '订单状态:PAID已支付/SHIPPED已发货/NOT_FOUND不存在'],
                    'ship_company' => ['type' => 'string', 'description' => '快递公司'],
                    'tracking_no' => ['type' => 'string', 'description' => '快递单号'],
                    'latest_tracking' => ['type' => 'string', 'description' => '最新物流信息'],
                    'after_sales_policy' => ['type' => 'string', 'description' => '售后政策说明'],
                    'suggestion' => ['type' => 'string', 'description' => '客服处理建议'],
                ],
                'required' => ['order_no', 'status', 'suggestion'],
            ],
        );
    }

    public function call(ToolCall $call, ExecutionContext $context): ToolResult
    {
        // 1. 获取入参(扩展已自动做 Schema 校验,无需手动判空和格式校验)
        $orderNo = $call->arguments['order_no'];

        // 2. 执行业务查询(演示用模拟数据,生产可替换为数据库查询、RPC调用、内部接口)
        $orderData = $this->getOrderData($orderNo);

        // 3. 返回结构化结果
        return ToolResult::success(
            content: [new TextContent(json_encode($orderData, JSON_UNESCAPED_UNICODE))],
            structuredContent: $orderData,
        );
    }

    /**
     * 模拟订单数据查询
     */
    private function getOrderData(string $orderNo): array
    {
        $demoData = [
            'ORDER-20260621-1001' => [
                'order_no' => $orderNo,
                'status' => 'SHIPPED',
                'ship_company' => '顺丰速运',
                'tracking_no' => 'SF1234567890',
                'latest_tracking' => '已到达上海浦东集散中心,预计明天上午派送',
                'after_sales_policy' => '支持7天无理由退换,发货后可申请改地址',
                'suggestion' => '订单已在运输途中,可帮用户催促网点优先派送',
            ],
            'ORDER-20260621-1002' => [
                'order_no' => $orderNo,
                'status' => 'PAID',
                'ship_company' => '',
                'tracking_no' => '',
                'latest_tracking' => '支付成功,仓库正在拣货备货',
                'after_sales_policy' => '支付后48小时内发货,可申请取消订单',
                'suggestion' => '订单尚未发货,可帮用户备注优先发货',
            ],
        ];

        return $demoData[$orderNo] ?? [
            'order_no' => $orderNo,
            'status' => 'NOT_FOUND',
            'ship_company' => '',
            'tracking_no' => '',
            'latest_tracking' => '',
            'after_sales_policy' => '',
            'suggestion' => '未查询到对应订单,请核对订单号或提供手机号后四位查询',
        ];
    }
}

💡 核心优势:扩展会自动根据 inputSchema 校验入参格式,不符合规范的调用直接返回标准错误,不用手写参数校验逻辑;structuredContent 返回结构化数据,既方便大模型解析,也方便下游程序处理。

4. 注册 MCP 服务

打开 app/mcp/OrderServer.php,把刚才的工具注册到服务中,同时配置认证授权规则:

代码语言:javascript
复制
<?php
declare(strict_types=1);

namespace app\mcp;

use Tinywan\Mcp\Registry\RegisteredTool;
use Tinywan\Mcp\Registry\ServerDefinition;
use Tinywan\Mcp\Registry\ServerIdentity;
use Tinywan\Mcp\Security\AllowAllAuthorizer;
use Tinywan\Mcp\Security\AllowAnonymousAuthenticator;

final class OrderServer
{
    public static function definition(): ServerDefinition
    {
        return new ServerDefinition(
            // 服务唯一标识
            id: 'order-service',
            // 服务路由路径,最终访问地址为 /mcp/order
            path: '/mcp/order',
            // 服务身份信息
            identity: new ServerIdentity('订单查询MCP服务', '1.0.0'),
            // 注册的工具列表,支持批量注册多个工具
            tools: [
                new RegisteredTool(
                    (new OrderQueryTool())->definition(),
                    OrderQueryTool::class
                ),
            ],
            // 认证方式:演示用匿名访问,生产环境建议用 Bearer Token
            authenticator: new AllowAnonymousAuthenticator(),
            // 授权方式:演示全部放行,生产可自定义权限逻辑
            authorizer: new AllowAllAuthorizer(),
        );
    }
}

5. 配置服务注册

打开配置文件 config/plugin/tinywan/webman-mcp/servers.php,把我们的服务加入全局配置:

代码语言:javascript
复制
<?php
declare(strict_types=1);

use app\mcp\OrderServer;

return [
    'servers' => [
        OrderServer::definition(),
    ],
];

6. 配置校验与启动服务

先执行校验命令,检查配置与 Schema 是否合法
代码语言:javascript
复制
php webman mcp:inspect

正常会输出:所有服务配置合法,Schema 校验通过。

查看已注册的服务和工具清单
代码语言:javascript
复制
php webman mcp:list

可以看到 order-service 服务和 query_order_snapshot 工具已成功注册。

启动 Webman 服务
代码语言:javascript
复制
php start.php start

启动成功后,MCP 服务端点为:http://127.0.0.1:8787/mcp/order

7. 手动测试工具调用

用 curl 直接调用工具,验证服务是否正常运行:

代码语言:javascript
复制
curl -X POST http://127.0.0.1:8787/mcp/order \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/call" \
  -H "Mcp-Name: query_order_snapshot" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "query_order_snapshot",
      "arguments": {"order_no": "ORDER-20260621-1001"}
    }
  }'

正常返回结果示例:

代码语言:javascript
复制
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{...结构化订单数据...}"
      }
    ],
    "structuredContent": {
      "order_no": "ORDER-20260621-1001",
      "status": "SHIPPED",
      "ship_company": "顺丰速运",
      "tracking_no": "SF1234567890",
      "latest_tracking": "已到达上海浦东集散中心,预计明天上午派送"
    },
    "isError": false
  }
}

对接 Neuron AI 智能体客户端

MCP 服务端跑通之后,我们用 Neuron AI 原生的 McpConnector 连接服务,让大模型可以自动发现、自主调用订单查询工具。

1. 客户端环境准备

新建一个 Webman 项目作为 Agent 客户端,安装 Neuron AI 核心依赖:

代码语言:javascript
复制
composer require neuron-core/neuron-ai

2. 封装订单客服 Agent 服务

新建 app/Service/OrderAgentService.php:

代码语言:javascript
复制
<?php
namespace app\Service;

use NeuronAI\Agent\Agent;
use NeuronAI\MCP\McpConnector;
use NeuronAI\Chat\Messages\UserMessage;
use NeuronAI\Providers\Deepseek\Deepseek;

class OrderAgentService
{
    public function ask(string $question): string
    {
        // 1. 连接远端 MCP Server,自动发现并拉取所有可用工具
        $mcpConnector = McpConnector::make([
            // 使用 HTTP 传输方式,对应 webman-mcp 的无状态 HTTP 协议
            'type' => 'http',
            'url' => 'http://127.0.0.1:8787/mcp/order',
            // 协议版本与服务端对齐
            'protocol_version' => '2026-07-28',
            // 如果服务端配置了 Bearer 认证,在这里加上请求头
            // 'headers' => ['Authorization' => 'Bearer your-secure-token']
        ]);
        
        $tools = $mcpConnector->tools();

        // 2. 构建电商客服 Agent
        $agent = new class($tools) extends Agent {
            private array $mcpTools;
            
            public function __construct(array $tools)
            {
                $this->mcpTools = $tools;
                parent::__construct();
            }
            
            protected function provider(): \NeuronAI\Providers\AIProviderInterface
            {
                return new Deepseek(
                    key: getenv('DEEPSEEK_API_KEY'),
                    model: 'deepseek-chat',
                );
            }
            
            protected function instructions(): string
            {
                return <<<PROMPT
                你是专业的电商客服助手。
                必须遵守的规则:
                1. 涉及订单、物流、售后的问题,必须先调用 query_order_snapshot 工具查询真实数据,严禁编造订单、物流信息。
                2. 用自然友好的客服语气回复用户,不要暴露你调用了工具。
                3. 查询不到订单时,引导用户核对订单号或提供手机号后四位查询。
                PROMPT;
            }
            
            protected function tools(): array
            {
                return $this->mcpTools;
            }
        };

        // 3. 发起对话,Neuron AI 自动处理工具调用全流程(判断是否调用→执行工具→返回结果→生成最终回答)
        $response = $agent->chat(new UserMessage($question));
        
        return $response->getContent();
    }
}

3. 对外提供 HTTP 问答接口

新建控制器和路由,方便前端或业务系统调用:

代码语言:javascript
复制
// app/Controller/AskController.php
namespace app\Controller;

use support\Request;
use support\Response;
use app\Service\OrderAgentService;

class AskController
{
    public function index(Request $request): Response
    {
        $question = $request->input('question', '');
        if (!$question) {
            return json(['code' => 400, 'message' => '问题不能为空']);
        }
        
        try {
            $answer = (new OrderAgentService())->ask($question);
            return json(['code' => 0, 'answer' => $answer]);
        } catch (\Throwable $e) {
            return json(['code' => 500, 'message' => $e->getMessage()]);
        }
    }
}
代码语言:javascript
复制
// config/route.php
use Webman\Route;
use app\Controller\AskController;

Route::post('/ask', [AskController::class, 'index']);

4. 全链路效果测试

启动客户端服务后,调用接口测试:

代码语言:javascript
复制
curl -X POST http://127.0.0.1:8788/ask \
  -H "Content-Type: application/json" \
  -d '{"question":"我的订单ORDER-20260621-1001发货了吗?什么时候能到?"}'

预期返回效果:

您好呀~ 您的订单 ORDER-20260621-1001 已经发货了,快递公司是顺丰速运,单号 SF1234567890。目前快件已经到达上海浦东集散中心,预计明天上午就会为您派送哦。如果您比较着急的话,我也可以帮您催促网点优先派送~

同时你可以在 MCP 服务端日志中看到工具调用记录,说明大模型确实触发了 MCP 工具调用,基于真实业务数据生成了回答。

MCP 工具设计最佳实践

  1. 单一职责原则:一个工具只做一件事,比如拆成「查订单」「查物流」「创建催单」,而不是一个 handle_order 包揽所有功能,工具越单一,大模型调用准确率越高。
  2. 优先结构化返回:优先使用 structuredContent 返回结构化数据,不要只返回自然语言文本,既方便大模型解析,也方便下游程序做逻辑处理。
  3. 错误标准化:业务异常用 ToolResult::error() 返回标准化错误码和友好提示,不要抛出 PHP 异常栈,避免泄露内部系统信息。
  4. 只读工具优先开放:优先开放只读查询工具,写操作工具必须加强权限校验、人工确认机制,避免 AI 误操作导致业务事故。
  5. 描述精准清晰:工具和参数的 description 一定要写清楚业务含义,这直接决定了大模型会不会正确调用工具,描述越精准,幻觉越少。

方案总结

  • 服务端:基于 tinywan/webman-mcp 扩展,不用手写 MCP 协议细节,专注业务逻辑即可,自带 Schema 校验、安全认证、多服务管理,完全符合最新标准协议。
  • 客户端:Neuron AI 原生支持 MCP 连接器,几行代码就能把远端工具注入 Agent,自动处理工具调用的完整循环。
  • 生态兼容:标准 MCP 协议,一套服务可以同时给 Neuron AI、Codex CLI、Claude Code 等多种智能体使用。
  • 生产就绪:支持权限控制、多服务拆分、结构化校验,满足企业级落地要求。

如果你需要更复杂的场景,比如结合 RAG 知识库、多 Agent 协作、工作流编排,都可以在这个基础上基于 Neuron AI 的能力继续扩展。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-07-31,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 概述
  • 环境要求
    • 快速搭建 MCP 服务端
  • 1. 安装扩展
  • 2. 生成服务与工具脚手架
  • 3. 实现业务工具类
  • 4. 注册 MCP 服务
  • 5. 配置服务注册
  • 6. 配置校验与启动服务
    • 先执行校验命令,检查配置与 Schema 是否合法
    • 查看已注册的服务和工具清单
    • 启动 Webman 服务
  • 7. 手动测试工具调用
    • 对接 Neuron AI 智能体客户端
  • 1. 客户端环境准备
  • 2. 封装订单客服 Agent 服务
  • 3. 对外提供 HTTP 问答接口
  • 4. 全链路效果测试
  • MCP 工具设计最佳实践
  • 方案总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档