一个全面的PHP SDK,用于构建模型上下文协议(MCP)服务器。使用现代架构、广泛的测试和灵活的传输选项,在PHP中创建生产就绪的MCP服务器。
此SDK使您能够将PHP应用程序的功能作为标准化的MCP 工具、资源和提示公开,允许AI助手(如Anthropic的Claude、Cursor IDE、OpenAI的ChatGPT等)使用MCP标准与您的后端进行交互。
stdio、http+sse以及新的可恢复的流式HTTP#[McpTool]、#[McpResource]等)进行零配置元素注册#[Schema]属性进行增强该包支持2025-03-26版本的模型上下文协议,并具有向后兼容性。
json、mbstring、pcre(通常默认启用)composer require php-mcp/server
💡 Laravel用户:考虑使用
php-mcp/laravel,以获得增强的框架集成、配置管理和Artisan命令。
此示例演示了最常见的使用模式——使用属性发现的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组件(工具、资源、提示、模板)StdioServerTransport:标准I/O,用于直接客户端启动HttpServerTransport:HTTP + 服务发送事件,用于Web集成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元素:基于属性的发现(推荐)和手动注册。两者可以结合使用,手动注册优先。
calculate、send_email、query_database)config://settings、file://readme.txt)user://{id}/profile)summarize、translate)使用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]:对话模板和提示生成器在调用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绕过已经运行的检查服务器核心是传输无关的。根据您的部署需求选择传输:
最佳用途:直接客户端执行、命令行工具、简单部署
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"]
}
}
}