# webman-mcp

![Packagist Version](https://img.shields.io/packagist/v/luoyue/webman-mcp) ![Packagist License](https://img.shields.io/packagist/l/luoyue/webman-mcp) ![PHP Version](https://img.shields.io/packagist/dependency-v/luoyue/webman-mcp/php) ![SDK Version](https://img.shields.io/packagist/dependency-v/luoyue/webman-mcp/mcp%2Fsdk?label=sdk) [![MCP](https://img.shields.io/badge/MCP-Model%20Context%20Protocol-purple)](https://modelcontextprotocol.io/) [![codecov](https://codecov.io/gh/luoyue712/webman-mcp/graph/badge.svg?token=7FLMVF3O00)](https://codecov.io/gh/luoyue712/webman-mcp) ![Packagist Downloads](https://img.shields.io/packagist/dt/luoyue/webman-mcp) ![Packagist Stars](https://img.shields.io/packagist/stars/luoyue/webman-mcp)

这是一个Webman框架与官方MCP PHP SDK深度集成的插件，并在SDK基础上进行了扩展，可快速创建MCP服务器。

> 此插件依赖于官方的[MCP PHP SDK](https://github.com/modelcontextprotocol/php-sdk)，以下文档仅展示插件与sdk的差异。

## 特性

- 一键启动，安装后即可启动，同时支持配置复杂的功能。
- 一个项目支持多个MCP服务器，并按服务器名称隔离配置。
- 与Webman框架深度集成，HTTP支持路由模式和自定义进程模式。
- 支持 STDIO、Streamable HTTP 高性能传输。
- 支持协程与非协程，从而提高了在sse场景下高性能传输。
- 内置18个MCP开发工具，提升开发效率。

## 安装

```bash
composer require luoyue/webman-mcp
```

### 环境要求

- PHP >= 8.1
- webman ^2.1

### 可选依赖

- webman/cache（session持久化存储）
- webman/redis（Redis开发工具）
- webman/event（MCP生命周期钩子与列表变更通知）
- Swoole/Swow/Fiber协程（提升SSE传输性能）
- monolog/monolog（记录服务器日志）

## 注解

|        注解名称         | 描述                                |
|:-------------------:|:----------------------------------|
|       McpTool       | 标记一个PHP方法为MCP工具，使其可以被AI调用执行特定功能   |
|      McpPrompt      | 标记一个PHP方法为MCP提示生成器，用于生成对话提示消息     |
|     McpResource     | 标记一个PHP方法为MCP资源处理器，用于处理特定资源URI的请求 |
| McpResourceTemplate | 标记一个PHP方法为MCP资源模板，用于定义资源URI模板     |
| CompletionProvider  | 为参数提供自动完成功能，指定可能的值或提供者类           |
|       Schema        | 定义方法或参数的JSON Schema，用于参数验证和类型检查   |

## 启动方式

```shell
# 启动 MCP STDIO 服务器, mcp为服务器名称，配置文件中定义
php webman mcp:server mcp

# 启动 MCP HTTP 服务器(分为两种，一种是嵌入到路由中，另一种是自定义进程)
php webman start
```

## 快速开始

### 1. 使用命令行工具创建模板代码（也可直接使用插件自带的配置）

```bash
# 创建文件后可根据模板代码实现逻辑
php webman mcp:make template
```

实际上并不太需要此命令创建代码，因为使用方法已足够简单，只需在方法中声明注解即可。

### 2. 测试您的服务器

```bash
# 使用 MCP Inspector 测试（需要Node.js，使用npx或bunx）
php webman mcp:inspector mcp
```

## 内置工具

### 命令行工具

| 工具            |   参数    |         描述          |
|:--------------|:-------:|:-------------------:|
| mcp:server    | service |      启动MCP服务器       |
| mcp:list      |         |       MCP服务列表       |
| mcp:make      |  type   |    生成MCP配置或模板代码     |
| mcp:inspector | service | 启动MCP Inspector调试工具 |
| mcp:tools     | service | 列出服务的工具/资源/提示及Schema |
| mcp:tools:call | service, tool-name, [json-input] | 通过JSON参数执行服务中的工具 |
| mcp:resources:read | service, uri | 读取服务中的资源（支持资源模板URI） |

示例：

```shell
## 查看定义的mcp服务列表以及配置信息
php webman mcp:list

## 列出服务的工具/资源/提示及Schema
php webman mcp:tools conformance

## 执行服务中的工具（默认pretty输出，--format=json输出JSON）
php webman mcp:tools:call conformance test_simple_text
php webman mcp:tools:call conformance test_simple_text --format=json

## 读取服务中的资源（支持静态资源与资源模板URI）
php webman mcp:resources:read conformance test://static-text
php webman mcp:resources:read conformance test://template/abc123/data --format=json
```

> 注意：需要与客户端交互的工具（如 sampling、elicitation）无法通过 `mcp:tools:call` 执行，
> 这类工具依赖真实 MCP 客户端会话，请在 HTTP/STDIO 传输下运行。

### MCP开发工具

|  类别  |          名称           |          描述          |
|:----:|:---------------------:|:--------------------:|
| tool |      system_info      |       获取系统环境信息       |
| tool |     system_config     |       获取应用配置值        |
| tool |      system_env       |        获取环境变量        |
| tool |    system_php_ini     |      获取PHP配置信息       |
| tool |  system_dependencies  |   获取项目Composer依赖列表   |
| tool |   system_extensions   |    获取已加载的PHP扩展及函数    |
| tool |     system_routes     |        获取路由列表        |
| tool |  system_match_routes  |      匹配URL对应的路由      |
| tool |     system_events     |        获取事件列表        |
| tool |   system_eval_code    | 执行PHP代码（有安全风险，请谨慎使用） |
| tool |   system_build_phar   |     将项目打包为PHAR文件     |
| tool |   system_build_bin    |   将项目打包为Linux二进制文件   |
| tool | database_connections  |      获取数据库连接配置       |
| tool | database_execute_sql  |  执行原始SQL语句（支持参数绑定）   |
| tool |   redis_connections   |     获取Redis连接配置      |
| tool |   redis_execute_raw   |     执行原始Redis命令      |
| tool |   redis_execute_lua   |    执行Redis Lua脚本     |
| tool | redis_execute_lua_sha | 通过SHA1执行Redis Lua脚本  |

## 日志记录

### 发送客户端日志

> 注意：`2026-07-28`规范已废弃客户端日志（client logging），但1年内依然可用。

请参考[官方文档](https://github.com/modelcontextprotocol/php-sdk/blob/main/docs/client-communication.md)

### 记录服务器错误日志

根据`2025-11-25`规范，STDIO传输允许将任何日志记录到stderr中且客户端可以捕获stderr并视为非致命错误，stdout则必须用于传输json-rpc消息。

|  日志模式  | STDIO传输 | Streamable HTTP传输 |
|:------:|:-------:|:-----------------:|
|  file  |    ✅    |         ✅         |
| stdout |    ❌    |         ✅         |
| stderr |    ✅    |         ✅         |

从以上表格中看出：

- 在开发环境中使用stderr很方便的将日志输出到控制台中且不影响运行。
- 在生产环境中使用file记录日志可以将日志保存在磁盘中，方便后续维护。

配置monolog日志通道（插件配置目录 `config/plugin/luoyue/webman-mcp/log.php`）：

```php
<?php

return [
    //文件日志记录
    'mcp_file_log' => [
        'handlers' => [
            [
                'class' => Monolog\Handler\RotatingFileHandler::class,
                'constructor' => [
                    runtime_path() . '/logs/mcp.log',
                    7, //$maxFiles
                    Monolog\Logger::NOTICE,
                ],
                'formatter' => [
                    'class' => Monolog\Formatter\LineFormatter::class,
                    'constructor' => [null, 'Y-m-d H:i:s', true],
                ],
            ]
        ]
    ],
    // stderr日志记录
    'mcp_error_stderr' => [
        'handlers' => [
            [
                'class' => Monolog\Handler\StreamHandler::class,
                'constructor' => [
                    STDERR, // stderr流
                    Monolog\Logger::NOTICE, // 设置NOTICE可减少不必要的调试信息
                ],
                'formatter' => [
                    'class' => Monolog\Formatter\LineFormatter::class,
                    'constructor' => [null, 'Y-m-d H:i:s', true],
                ],
            ]
        ]
    ]
];
```

然后在`mcp.php`的`configure`闭包中为服务器设置日志通道。`setLogger`支持任意monolog channel：

```php
'configure' => function (\Mcp\Server\Builder $server) {
    // ...
    // 直接使用应用任意已配置的channel
    $server->setLogger(\support\Log::channel('default'));
}
```

如果使用插件自带的channel，通道名需要加上`plugin.luoyue.webman-mcp.`前缀，例如根据debug模式在stderr与文件日志之间切换：

```php
'configure' => function (\Mcp\Server\Builder $server) {
    // ...
    $server->setLogger(\support\Log::channel(
        \Luoyue\WebmanMcp\McpServerManager::PLUGIN_REWFIX .
        (config('app.debug', true) ? 'mcp_error_stderr' : 'mcp_file_log')
    ));
}
```

## 与webman的兼容问题

### McpTool注解如何将Controller结合使用

由于webman控制器和mcp消息处理机制差异，无法完美兼容，需要稍加改动即可适配。具体代码如下：

```php
<?php

use Mcp\Server\RequestContext;
use Luoyue\WebmanMcp\McpHelper;
use Workerman\Protocols\Http\Response;

class McpController
{

    /**
     * tool示例代码
     *
     * @param RequestContext|null $context MCP请求上下文，设置为可选适配controller
     * @return array 返回包含会话ID的状态信息
     */
    #[McpTool(name: 'example_tool')]
    public function exampleTool(?RequestContext $context): Response|array
    {
        $result = [
            'status' => 'ok',
            'params' => request()->all(),
        ];
        // controller将自动忽略此行代码
        $context?->getClientLogger()->info('example_tool', $result);
        return McpHelper::is_mcp_server_request() ? $result : response($result);
    }
}
```

### STDIO传输的限制

- 在linux/macos系统中此功能可能不受影响，在windows系统中，由于平台限制，无法将其设置为非阻塞。
- 根据上面的问题，在webman中无法使用依赖workerman环境中的函数：定时器、定时任务、协程、http-client等。

相关讨论：[Discussions #3](https://github.com/lvluoyue/webman-mcp/discussions/3)

## 参考文档

**学习资料：**

- [MCP 元素](https://github.com/modelcontextprotocol/php-sdk/blob/main/docs/mcp-elements.md) - 创建工具、资源和提示
- [示例](https://github.com/modelcontextprotocol/php-sdk/blob/main/docs/examples.md) - 全面的示例演练

**外部资源：**

- [模型上下文协议文档](https://modelcontextprotocol.io)
- [模型上下文协议规范](https://modelcontextprotocol.io/specification/2025-11-25)
- [MCP服务器列表](https://github.com/modelcontextprotocol/servers)
- [MCP PHP SDK](https://github.com/modelcontextprotocol/php-sdk)

## 许可证

本项目对于新贡献采用 Apache Apache 2.0 许可证，而现有代码采用 MIT 许可证 - 详情请见 [LICENSE](LICENSE) 文件。
