最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

PHP MCP 服务器 v1.0.0 发布!

网站源码admin3浏览0评论

PHP MCP 服务器 v1.0.0 发布!

简介

PHP MCP Server:Model Context Protocol(MCP)服务器的核心PHP实现。

Model Context Protocol(MCP)是一种开放标准,最初由Anthropic开发,旨在规范AI助手和工具连接外部数据源、API及其他系统的方式。可以将其想象为AI领域的USB-C接口,是一种统一、一致的提供上下文的方式。

php-mcp/server是一个PHP库,使用它能够轻松构建符合MCP标准的服务器。其核心目标是让你能够通过最少的工作,主要利用PHP 8的属性,将现有PHP应用程序的特定方法,作为MCP工具、资源或提示公开。

该软件包目前支持2024年11月5日版本的Model Context Protocol,并且与各种符合该协议版本的MCP客户端兼容,如Claude Desktop、Cursor、Windsurf等。

关键特性

  1. 基于属性的定义:使用简单的PHP 8属性(#[McpTool]#[McpResource]#[McpPrompt]#[McpResourceTemplate]#[McpTemplate])定义MCP元素(工具、资源、提示、模板)。
  2. 自动元数据推断:利用方法名称、参数名称、PHP类型提示(用于架构)和文档块(用于架构和描述)自动生成MCP定义,最大限度减少样板代码。
  3. 符合PSR标准:与标准PHP接口无缝集成:
    • PSR-3(LoggerInterface):可使用自己的日志记录器(例如Monolog)。
    • PSR-11(ContainerInterface):使用自己喜欢的依赖注入容器(例如Laravel、Symfony、PHP-DI),在调用MCP元素时解析应用程序类及其依赖项。
    • PSR-16(SimpleCacheInterface):提供缓存实现(例如Symfony Cache、Laravel Cache),用于缓存发现的元素和传输状态。
  4. 灵活的配置:以合理的默认设置开始,但允许为日志记录、缓存、依赖注入容器和详细的MCP配置(ConfigurationRepositoryInterface)提供自己的实现。
  5. 多种传输方式:支持stdio(用于命令行客户端),并包含开箱即用的构建http+sse(HTTP + Server-Sent Events)传输的组件(需要与HTTP服务器集成)。
  6. 自动发现:扫描项目内指定的目录,查找使用MCP属性注释的类和方法。
  7. 框架无关:设计为在普通PHP项目中或集成到任何PHP框架中都能同样良好地工作。

要求

  • PHP >= 8.1
  • Composer

安装

可以通过Composer安装该软件包:

代码语言:javascript代码运行次数:0运行复制
composer require php-mcp/server

注意:对于Laravel应用程序,建议使用专门的php-mcp/laravel-server软件包。它基于这个核心库构建,提供了针对Laravel框架的有用集成、配置选项和Artisan命令。

一个简单的stdio服务器

以下是一个最小示例,展示如何使用stdio传输将一个简单的PHP类方法作为MCP工具公开。

  1. 创建MCP元素类:创建一个文件,例如src/MyMcpStuff.php
代码语言:javascript代码运行次数:0运行复制
<?php

namespaceApp;

usePhpMcp\Server\Attributes\McpTool;

class MyMcpStuff
{
    /**
     * 一个用于将两个数字相加的简单工具。
     *
     * @param int $a 第一个数字。
     * @param int $b 第二个数字。
     * @return int 两个数字的和。
     */
    #[McpTool(name: 'adder')]
    publicfunction addNumbers(int $a, int $b): int
    {
        return $a + $b;
    }
}
  1. 创建服务器脚本:在项目根目录中创建一个脚本,例如mcp-server.php
代码语言:javascript代码运行次数:0运行复制
<?php

declare(strict_types=1);

usePhpMcp\Server\Server;

// 确保包含项目的自动加载器
require_once__DIR__ . '/vendor/autoload.php';
// 如果MCP元素在特定命名空间中,确保该命名空间也被自动加载(例如通过composer.json)

// 可选:配置日志记录(默认记录到STDERR)
// $logger = new MyPsrLoggerImplementation(...);

$server = Server::make()
    // 可选:->withLogger($logger)
    // 可选:->withCache(new MyPsrCacheImplementation(...))
    // 可选:->withContainer(new MyPsrContainerImplementation(...))
    ->withBasePath(__DIR__) // 开始扫描属性的目录
    ->withScanDirectories(['src']) // 要扫描的特定子目录(相对于basePath)
    ->discover(); // 查找所有#[Mcp*]属性

// 使用stdio传输运行服务器
$exitCode = $server->run('stdio');

exit($exitCode);
  1. 配置MCP客户端:配置MCP客户端(如Cursor、Claude Desktop等)以使用stdio传输进行连接。这通常涉及指定运行服务器脚本的命令。例如,在Cursor的.cursor/mcp.json中:
代码语言:javascript代码运行次数:0运行复制
{
    "mcpServers": {
        "my-php-server": {
            "command": "php",
            "args": [
                "/path/to/your/project/mcp-server.php"
            ]
        }
    }
}

/path/to/your/project/mcp-server.php替换为脚本的实际绝对路径。现在,当连接客户端时,它应该能够发现adder工具。

核心概念

通过php-mcp/server公开功能的主要方式是使用特定属性装饰PHP方法。服务器会自动发现这些属性,并将它们转换为相应的MCP定义。

  1. #[McpTool] :将一个方法标记为MCP工具。工具代表客户端可以调用的操作或函数,通常带有参数。该属性接受以下参数:
    • name(可选):暴露给客户端的工具名称。默认为方法名称(例如,addNumbers变为addNumbers)。
    • description(可选):工具的描述。默认为方法的文档块摘要。
    • 方法的参数(包括名称、类型提示和默认值)定义了工具的输入架构。方法的返回类型提示定义了输出架构。文档块中的@param@return描述用于参数/输出描述。
  2. 返回值格式化 :方法返回的值决定了发送回客户端的内容。该库会自动格式化常见类型:
    • null:返回空内容(如果返回类型提示为void)或带有(null)TextContent
    • stringintfloatbool:自动包装在PhpMcp\Server\JsonRpc\Contents\TextContent中。
    • arrayobject:自动JSON编码(漂亮打印)并包装在TextContent中。
    • PhpMcp\Server\JsonRpc\Contents\Content对象:如果返回Content(例如TextContentImageContentAudioContentResourceContent)的实例或Content对象数组,它们将直接使用。这使你可以完全控制输出格式。例如:return TextContent::code('echo \'Hello\';', 'php');
    • 异常:如果方法抛出异常,将返回一个包含错误消息和类型的TextContent。方法的返回类型提示(文档块中的@return标签)用于生成工具的输出架构,但实际格式化取决于运行时返回的值。
  3. #[McpResource] :将一个方法标记为代表特定的、静态的MCP资源实例。资源代表由URI标识的内容或数据片段。当客户端对指定的URI执行resources/read时,通常会调用此方法。该属性接受以下参数:
    • uri(必需):此资源实例的唯一URI(例如,config://app/settingsfile:///data/status.txt)。必须符合RFC 3986。
    • name(可选):人类可读的名称。默认值从方法名称推断。
    • description(可选):描述。默认值为文档块摘要。
    • mimeType(可选):资源的MIME类型(例如,text/plainapplication/json)。
    • size(可选):资源大小(以字节为单位),如果已知且固定。
    • annotations(可选):MCP注释数组(例如,['audience' => ['user']])。方法应返回资源的内容。
  4. #[McpResourceTemplate] :将一个方法标记为可以基于模板URI生成资源实例的方法。这对于URI包含可变部分(如用户ID或文档ID)的资源很有用。当客户端执行与模板匹配的resources/read时,将调用此方法。该属性接受以下参数:
    • uriTemplate(必需):URI模板字符串,符合RFC 6570(例如,user://{userId}/profiledocument://{docId}?format={fmt})。
    • namedescriptionmimeTypeannotations(可选):与#[McpResource]类似,但用于描述模板本身。方法参数必须与uriTemplate中定义的变量匹配。方法应返回解析后的资源实例的内容。
  5. #[McpPrompt] :将一个方法标记为MCP提示生成器。提示是预定义的模板或函数,可根据输入参数生成对话消息(如用户或助手的回复)。该属性接受以下参数:
    • name(可选):提示名称。默认值为方法名称。
    • description(可选):描述。默认值为文档块摘要。方法参数定义了提示的输入参数。方法应返回提示内容,通常是符合MCP消息结构的数组。

Server流接口

PhpMcp\Server\Server类是配置和运行MCP服务器的主要入口点。它提供了一个流畅接口(方法链式调用)来设置依赖项和参数。

  1. Server::make(): self:静态工厂方法,用于创建一个新的服务器实例。
  2. ->withLogger(LoggerInterface $logger): self:提供一个符合PSR-3标准的日志记录器实现。默认情况下,使用一个基本的StreamLogger,将日志写入STDERR,日志级别为LogLevel::INFO
  3. ->withCache(CacheInterface $cache): self:提供一个符合PSR-16标准的缓存实现。用于缓存发现的MCP元素以及可能的传输状态。默认情况下,使用一个简单的内存ArrayCache
  4. ->withContainer(ContainerInterface $container): self:提供一个符合PSR-11标准的依赖注入容器。当需要调用包含#[Mcp*]属性的方法时,这个容器将用于实例化相应的类。默认情况下,使用一个非常基本的BasicContainer,它只能解析显式设置的服务。
  5. ->withConfig(ConfigurationRepositoryInterface $config): self:提供一个自定义配置存储库。这允许覆盖所有默认设置,包括启用的功能、协议版本、缓存键/生存时间等。默认情况下,使用ArrayConfigurationRepository,并带有预定义的默认值。
  6. ->withBasePath(string $path): self:设置发现过程中目录扫描的绝对基本路径。默认值为当前工作目录(getcwd())。
  7. ->withScanDirectories(array $dirs): self:指定一个相对于basePath的目录路径数组,服务器将在这些目录中查找注释方法。默认值为['.'](即基本路径本身)。
  8. ->discover(bool
  9. ->run(?string $transport = null): int:使用指定的传输启动服务器的主处理循环。
    • 如果$transport'stdio'(或在CLI中运行时为null),它将使用StdioTransportHandler通过标准输入/输出进行通信。
    • 如果$transport'http',它将抛出一个异常,因为HTTP传输需要集成到现有的HTTP服务器循环中(请参阅传输部分)。返回退出代码(与stdio相关)。

发现

当调用->discover()时,服务器会在->withScanDirectories()指定的目录(相对于->withBasePath())中查找所有文件。对于每个文件,它会尝试解析类定义,反射该类的公共非静态方法,并检查这些方法是否有#[McpTool]#[McpResource]#[McpPrompt]#[McpResourceTemplate]属性。

如果找到一个属性,它会从属性实例、方法签名(名称、参数、类型提示)和方法的文档块中提取元数据。然后,它会创建一个相应的Definition对象(例如,ToolDefinitionResourceDefinition),并将它们注册到注册表中。最后,收集到的定义会被序列化并存储在通过->withCache()提供的缓存中(使用配置的缓存键和生存时间),以加快后续服务器启动的速度。

依赖注入

当MCP客户端调用一个工具或读取一个映射到你带有属性的方法的资源/提示时:

  1. ProcessorRegistry中识别目标类和方法。
  2. 它使用通过->withContainer()提供的PSR-11容器来检索目标类的实例(例如,$container->get(MyMcpStuff::class))。这意味着你的类构造函数可以注入在容器中配置的任何依赖项(数据库连接、服务等)。
  3. 处理器然后根据客户端请求和方法签名准备参数。
  4. 最后,它在检索到的类实例上调用目标方法。

使用默认的BasicContainer仅适用于非常简单的情况,即你带有属性的方法所在的类没有构造函数依赖项。对于任何实际应用程序,你都应该提供自己的PSR-11容器实例,例如->withContainer(MyFrameworkContainer::getInstance())

配置

服务器的行为可以通过实现PhpMcp\Server\Contracts\ConfigurationRepositoryInterface的配置存储库进行自定义。你可以使用->withConfig()来提供这个存储库。如果没有提供,则使用默认的PhpMcp\Server\Defaults\ArrayConfigurationRepository

关键配置值(使用点表示法)包括:

  1. mcp.server.name:(字符串)用于握手的服务器名称。
  2. mcp.server.version:(字符串)用于握手的服务器版本。
  3. mcp.protocol_versions:(数组)支持的协议版本(例如,['2024-11-05'])。
  4. mcp.pagination_limit:(整数)列出元素的默认限制。
  5. mcp.capabilities.tools.enabled:(布尔值)启用/禁用工具功能。
  6. mcp.capabilities.resources.enabled:(布尔值)启用/禁用资源功能。
  7. mcp.capabilities.resources.subscribe:(布尔值)启用/禁用资源订阅。
  8. mcp.capabilities.prompts.enabled:(布尔值)启用/禁用提示功能。
  9. mcp.capabilities.logging.enabled:(布尔值)启用/禁用logging/setLevel方法。
  10. mcp.cache.ttl:(整数)缓存生存时间(以秒为单位)。
  11. mcp.cache.prefix:(字符串)与MCP相关的缓存前缀。
  12. mcp.discovery.base_path:(字符串)发现的基本路径(会被withBasePath覆盖)。
  13. mcp.discovery.directories:(数组)要扫描的目录(会被withScanDirectories覆盖)。
  14. mcp.runtime.log_level:(字符串)默认日志级别(由默认日志记录器使用)。

你可以创建自己的接口实现,或者将填充了覆盖值的ArrayConfiguration

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2025-05-04,如有侵权请联系 cloudcommunity@tencent 删除php服务器工具配置MCP

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论