返回市场
服务器

服务器

作者:php-mcp774 星标更新:2025-08-10

项目介绍

PHP MCP Server SDK

最新版本 总下载量 测试 许可证

一个全面的PHP SDK,用于构建模型上下文协议(MCP)服务器。使用现代架构、广泛的测试和灵活的传输选项,在PHP中创建生产就绪的MCP服务器。

此SDK使您能够将PHP应用程序的功能作为标准化的MCP 工具资源提示公开,允许AI助手(如Anthropic的Claude、Cursor IDE、OpenAI的ChatGPT等)使用MCP标准与您的后端进行交互。

🚀 主要功能

  • 🏗️ 现代架构:使用PHP 8.1+特性、PSR标准和模块化设计
  • 📡 多种传输方式:支持stdiohttp+sse以及新的可恢复的流式HTTP
  • 🎯 基于属性的定义:使用PHP 8 属性(如#[McpTool]#[McpResource]等)进行零配置元素注册
  • 🔧 灵活的处理器:支持闭包、类方法、静态方法和可调用类
  • 📝 智能模式生成:从方法签名自动生成JSON模式,并可通过#[Schema]属性进行增强
  • ⚡ 会话管理:具有多个存储后端的高级会话处理
  • 🔄 事件驱动:基于ReactPHP,实现高并发和非阻塞操作
  • 📊 批处理:完全支持JSON-RPC批请求
  • 💾 智能缓存:智能缓存发现的元素,并优先手动覆盖
  • 🧪 完成提供者:内置支持工具和提示中的参数完成
  • 🔌 依赖注入:完整的PSR-11容器支持和自动装配
  • 📋 全面测试:包含所有传输的广泛测试套件

该包支持2025-03-26版本的模型上下文协议,并具有向后兼容性。

📋 要求

  • PHP >= 8.1
  • Composer
  • 对于HTTP传输:需要事件驱动的PHP环境(推荐使用CLI)
  • 扩展jsonmbstringpcre(通常默认启用)

📦 安装

composer require php-mcp/server

💡 Laravel用户:考虑使用php-mcp/laravel,以获得增强的框架集成、配置管理和Artisan命令。

⚡ 快速开始:带有发现功能的Stdio服务器

此示例演示了最常见的使用模式——使用属性发现的stdio服务器。

1. 定义您的MCP元素

创建src/CalculatorElements.php

<?php

namespace App;

use PhpMcp\Server\Attributes\McpTool;
use PhpMcp\Server\Attributes\Schema;

class CalculatorElements
{
    /**
     * 将两个数字相加。
     *
     * @param int $a 第一个数字
     * @param int $b 第二个数字
     * @return int 两个数字之和
     */
    #[McpTool(name: 'add_numbers')]
    public function add(int $a, int $b): int
    {
        return $a + $b;
    }

    /**
     * 带有验证的幂计算。
     */
    #[McpTool(name: 'calculate_power')]
    public function power(
        #[Schema(type: 'number', minimum: 2, maximum: 1000)]
        float $base,

        #[Schema(type: 'integer', minimum: 0, maximum: 10)]
        int $exponent
    ): float {
        return pow($base, $exponent);
    }
}

2. 创建服务器脚本

创建mcp-server.php

#!/usr/bin/env php
<?php

declare(strict_types=1);

require_once __DIR__ . '/vendor/autoload.php';

use PhpMcp\Server\Server;
use PhpMcp\Server\Transports\StdioServerTransport;

try {
    // 构建服务器配置
    $server = Server::make()
        ->withServerInfo('PHP计算器服务器', '1.0.0')
        ->build();

    // 通过属性发现MCP元素
    $server->discover(
        basePath: __DIR__,
        scanDirs: ['src']
    );

    // 通过stdio传输开始监听
    $transport = new StdioServerTransport();
    $server->listen($transport);

} catch (\Throwable $e) {
    fwrite(STDERR, "[严重错误] " . $e->getMessage() . "\n");
    exit(1);
}

3. 配置您的MCP客户端

添加到您的客户端配置(例如,.cursor/mcp.json):

{
    "mcpServers": {
        "php-calculator": {
            "command": "php",
            "args": ["/绝对路径到你的/mcp-server.php"]
        }
    }
}

4. 测试服务器

您的AI助手现在可以调用:

  • add_numbers - 将两个整数相加
  • calculate_power - 带有验证约束的幂计算

🏗️ 架构概述

PHP MCP服务器使用现代、解耦的架构:

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│   MCP客户端    │◄──►│   传输层      │◄──►│   协议层      │
│  (Claude等)   │    │ (Stdio/HTTP/SSE) │    │   (JSON-RPC)    │
└─────────────────┘    └──────────────────┘    └─────────────────┘
                                                         │
                       ┌─────────────────┐               │
                       │ 会话管理器   │◄──────────────┤
                       │ (多后端)   │               │
                       └─────────────────┘               │
                                                         │
┌─────────────────┐    ┌──────────────────┐              │
│   分发器    │◄───│   服务器核心    │◄─────────────┤
│ (方法路由)  │    │   配置层    │              │
└─────────────────┘    └──────────────────┘              │
         │                                               │
         ▼                                               │
┌─────────────────┐    ┌──────────────────┐              │
│    注册表     │    │   元素层       │◄─────────────┘
│  (元素存储)  │◄──►│ (工具/资源/提示等) │
└─────────────────┘    └──────────────────┘

核心组件

  • ServerBuilder:流畅的配置接口(Server::make()->...->build()
  • Server:包含所有已配置组件的中央协调器
  • Protocol:JSON-RPC 2.0处理器,连接传输和核心逻辑
  • SessionManager:多后端会话存储(数组、缓存、自定义)
  • Dispatcher:方法路由和请求处理
  • Registry:元素存储,带智能缓存和优先规则
  • Elements:注册的MCP组件(工具、资源、提示、模板)

传输选项

  1. StdioServerTransport:标准I/O,用于直接客户端启动
  2. HttpServerTransport:HTTP + 服务发送事件,用于Web集成
  3. StreamableHttpServerTransport:增强的HTTP,具有可恢复性和事件源

⚙️ 服务器配置

基础配置

use PhpMcp\Server\Server;
use PhpMcp\Schema\ServerCapabilities;

$server = Server::make()
    ->withServerInfo('我的应用服务器', '2.1.0')
    ->withCapabilities(ServerCapabilities::make(
        resources: true,
        resourcesSubscribe: true,
        prompts: true,
        tools: true
    ))
    ->withPaginationLimit(100)
    ->build();

高级配置与依赖项

use Psr\Log\Logger;
use Psr\SimpleCache\CacheInterface;
use Psr\Container\ContainerInterface;

$server = Server::make()
    ->withServerInfo('生产服务器', '1.0.0')
    ->withLogger($myPsrLogger)                    // PSR-3日志
    ->withCache($myPsrCache)                      // PSR-16缓存
    ->withContainer($myPsrContainer)              // PSR-11容器
    ->withSession('cache', 7200)                  // 缓存后端会话,2小时TTL
    ->withPaginationLimit(50)                     // 限制列表响应
    ->build();

会话管理选项

// 内存会话(默认,不持久)
->withSession('array', 3600)

// 缓存后端会话(重启时持久)
->withSession('cache', 7200)

// 自定义会话处理器(实现SessionHandlerInterface)
->withSessionHandler(new MyCustomSessionHandler(), 1800)

🎯 定义MCP元素

服务器提供了两种强大的方式来定义MCP元素:基于属性的发现(推荐)和手动注册。两者可以结合使用,手动注册优先。

元素类型

  • 🔧 工具:可执行函数/动作(例如,calculatesend_emailquery_database
  • 📄 资源:静态内容/数据(例如,config://settingsfile://readme.txt
  • 📋 资源模板:带有URI模式的动态资源(例如,user://{id}/profile
  • 💬 提示:对话开始/模板(例如,summarizetranslate

1. 🏷️ 基于属性的发现(推荐)

使用PHP 8属性标记方法或可调用类作为MCP元素。服务器将通过文件系统扫描发现它们。

use PhpMcp\Server\Attributes\{McpTool, McpResource, McpResourceTemplate, McpPrompt};

class UserManager
{
    /**
     * 创建一个新的用户账户。
     */
    #[McpTool(name: 'create_user')]
    public function createUser(string $email, string $password, string $role = 'user'): array
    {
        // 创建用户的逻辑
        return ['id' => 123, 'email' => $email, 'role' => $role];
    }

    /**
     * 获取用户配置。
     */
    #[McpResource(
        uri: 'config://user/settings',
        mimeType: 'application/json'
    )]
    public function getUserConfig(): array
    {
        return ['theme' => 'dark', 'notifications' => true];
    }

    /**
     * 根据ID获取用户资料。
     */
    #[McpResourceTemplate(
        uriTemplate: 'user://{userId}/profile',
        mimeType: 'application/json'
    )]
    public function getUserProfile(string $userId): array
    {
        return ['id' => $userId, 'name' => 'John Doe'];
    }

    /**
     * 生成欢迎消息提示。
     */
    #[McpPrompt(name: 'welcome_user')]
    public function welcomeUserPrompt(string $username, string $role): array
    {
        return [
            ['role' => 'user', 'content' => "为{$username}生成一条角色为{$role}的欢迎消息"]
        ];
    }
}

发现过程:

// 首先构建服务器
$server = Server::make()
    ->withServerInfo('我的应用服务器', '1.0.0')
    ->build();

// 然后发现元素
$server->discover(
    basePath: __DIR__,
    scanDirs: ['src/Handlers', 'src/Services'],  // 要扫描的目录
    excludeDirs: ['src/Tests'],                  // 要跳过的目录
    saveToCache: true                            // 缓存结果(默认:true)
);

可用属性:

  • #[McpTool]:可执行动作
  • #[McpResource]:可通过URI访问的静态内容
  • #[McpResourceTemplate]:带有URI模板的动态资源
  • #[McpPrompt]:对话模板和提示生成器

2. 🔧 手动注册

在调用build()之前使用ServerBuilder程序化地注册元素。适用于动态注册、闭包或希望显式控制的情况。

use App\Handlers\{EmailHandler, ConfigHandler, UserHandler, PromptHandler};
use PhpMcp\Schema\{ToolAnnotations, Annotations};

$server = Server::make()
    ->withServerInfo('手动注册服务器', '1.0.0')

    // 使用处理器方法注册工具
    ->withTool(
        [EmailHandler::class, 'sendEmail'],     // 处理器:[类名,方法名]
        name: 'send_email',                     // 工具名称(可选)
        description: '给用户发送邮件',          // 描述(可选)
        annotations: ToolAnnotations::make(     // 注释(可选)
            title: '发送邮件工具'
        )
    )

    // 注册可调用类作为工具
    ->withTool(UserHandler::class)             // 处理器:可调用类

    // 使用闭包注册工具
    ->withTool(
        function(int $a, int $b): int {         // 处理器:闭包
            return $a + $b;
        },
        name: 'add_numbers',
        description: '将两个数字相加'
    )

    // 使用闭包注册资源
    ->withResource(
        function(): array {                     // 处理器:闭包
            return ['timestamp' => time(), 'server' => 'php-mcp'];
        },
        uri: 'config://runtime/status',         // URI(必需)
        mimeType: 'application/json'           // MIME类型(可选)
    )

    // 注册资源模板
    ->withResourceTemplate(
        [UserHandler::class, 'getUserProfile'],
        uriTemplate: 'user://{userId}/profile'  // URI模板(必需)
    )

    // 使用闭包注册提示
    ->withPrompt(
        function(string $topic, string $tone = 'professional'): array {
            return [
                ['role' => 'user', 'content' => "写关于{$topic}的文章,使用{$tone}的语气"]
            ];
        },
        name: 'writing_prompt'                  // 提示名称(可选)
    )

    ->build();

服务器支持三种灵活的处理器格式:[ClassName::class, 'methodName']用于类方法处理器,InvokableClass::class用于可调用类处理器(具有__invoke方法的类),以及任何PHP可调用对象,包括闭包、静态方法如[SomeClass::class, 'staticMethod']或函数名。基于类的处理器通过配置的PSR-11容器进行依赖注入。手动注册永远不会被缓存,并且优先于具有相同标识符的发现元素。

[!重要] 当使用闭包作为处理器时,服务器仅根据PHP类型提示生成最小的JSON模式,因为没有docblocks或类上下文可用。为了更详细的模式,包括验证约束、描述和格式,您有两个选择:

  • 使用#[Schema]属性(参见#-模式生成和验证)进行增强模式生成
  • 在使用->withTool()注册工具时提供自定义$inputSchema参数

🏆 元素优先级及发现

优先规则:

  • 手动注册始终覆盖具有相同标识符的发现/缓存元素
  • 发现的元素为性能而缓存(可配置)
  • 新鲜发现运行会自动失效缓存

发现过程:

$server->discover(
    basePath: __DIR__,
    scanDirs: ['src/Handlers', 'src/Services'],  // 扫描这些目录
    excludeDirs: ['tests', 'vendor'],            // 跳过这些目录
    force: false,                                // 强制重新扫描(默认:false)
    saveToCache: true                            // 保存到缓存(默认:true)
);

缓存行为:

  • 只有发现的元素会被缓存(从不手动注册)
  • 如果可用,构建时自动加载缓存
  • 新鲜的discover()调用清除并重建缓存
  • 使用force: true绕过已经运行的检查

🚀 运行服务器(传输)

服务器核心是传输无关的。根据您的部署需求选择传输:

1. 📟 Stdio传输

最佳用途:直接客户端执行、命令行工具、简单部署

use PhpMcp\Server\Transports\StdioServerTransport;

$server = Server::make()
    ->withServerInfo('Stdio服务器', '1.0.0')
    ->build();

$server->discover(__DIR__, ['src']);

// 创建stdio传输(默认使用STDIN/STDOUT)
$transport = new StdioServerTransport();

// 开始监听(阻塞调用)
$server->listen($transport);

客户端配置:

{
    "mcpServers": {
        "my-php-server": {
            "command": "php",
            "args": ["/绝对路径到/server.php"]
        }
    }
}