Loading [MathJax]/jax/output/CommonHTML/fonts/TeX/AMS-Regular.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >PHP MCP 客户端 v1.0.0 发布!

PHP MCP 客户端 v1.0.0 发布!

作者头像
Tinywan
发布于 2025-05-08 08:02:21
发布于 2025-05-08 08:02:21
11900
代码可运行
举报
文章被收录于专栏:开源技术小栈开源技术小栈
运行总次数:0
代码可运行

简介

PHP MCP Client是一个PHP库,用于与实现Model Context Protocol (MCP)的服务器进行交互。它为开发者提供了友好的接口,可通过不同的传输方式(stdiohttp+sse)连接到单个MCP服务器,管理连接生命周期,发现服务器功能(工具、资源、提示),并执行诸如调用工具或读取资源等请求。

该库内部通过ReactPHP利用异步I/O来确保健壮性并处理服务器发送事件等功能,同时提供了简单的同步(阻塞)API用于常见用例,以及异步(基于Promise)API用于高级控制和并发操作。它遵循MCP规范模型,即一个客户端实例管理与一个服务器的有状态连接。

MCP介绍

Model Context Protocol (MCP)是一个开放标准,旨在规范AI助手和应用程序连接到外部数据源、API和工具(如代码库、数据库、网页浏览器)的方式。它作为一个通信层,使AI模型(如Claude,或通过OpenAI等框架集成的模型)能够安全地访问不同服务器提供的上下文并与之交互。这个客户端库允许你的PHP应用程序(在MCP术语中称为“主机”)使用一个或多个MCP服务器提供的功能。

特性

  • 客户端-服务器一对一模型:每个Client实例管理与单个配置好的MCP服务器的有状态连接,符合MCP规范。
  • 流畅的配置方式:使用Client::make()->with...()构建器模式轻松设置每个客户端实例。
  • 双API设计
    • 同步门面API:使用简单的阻塞方法(如
    • 异步API:访问底层基于Promise的方法(如
  • 多种传输方式支持
    • stdio:通过标准输入/输出与服务器进程通信。
    • http:通过HTTP POST和服务器发送事件(SSE)与服务器通信。
  • 明确的连接生命周期管理:需要调用->initialize()->initializeAsync()连接并执行握手操作后才能发出请求。提供disconnect() / disconnectAsync()方法断开连接。
  • 工具/资源/提示交互功能:提供全面的同步和异步方法,用于列出可用元素并执行tools/callresources/readprompts/get等请求。
  • 符合PSR标准:与标准PHP接口集成
    • PSR-3(LoggerInterface):集成应用程序的日志记录器。
    • PSR-16(SimpleCacheInterface):可选的服务器定义缓存。
    • PSR-14(EventDispatcherInterface):通过事件(需要异步处理)可选地处理服务器发送的通知。
  • 强大的错误处理机制:针对不同的失败模式提供特定的异常。
  • 异步核心:内部使用ReactPHP实现非阻塞I/O。

要求

  • PHP >= 8.1
  • Composer
  • (对于Stdio传输)能够执行服务器命令。
  • (对于Http传输)能够访问MCP服务器URL的网络权限。

安装

通过Composer安装该包:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
composer require php-mcp/client

必要的ReactPHP依赖(event-looppromisestreamchild-processhttp)会自动安装。

快速上手:简单同步使用(Stdio)

这个示例展示了如何连接到通过npx运行的本地文件系统服务器。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php 
require'vendor/autoload.php';

usePhpMcp\Client\Client;
usePhpMcp\Client\Enum\TransportType;
usePhpMcp\Client\Model\CapabilitiesasClientCapabilities;
usePhpMcp\Client\ServerConfig;
usePhpMcp\Client\Exception\McpClientException;

$clientCapabilities = ClientCapabilities::forClient(); // 默认客户端功能
$userHome = $_SERVER['HOME'] ?? $_SERVER['USERPROFILE'] ?? getcwd();
$fsServerConfig = new ServerConfig(
    name: 'local_filesystem',
    transport: TransportType::Stdio,
    timeout: 15,
    command: 'npx',
    args: [
        '-y',
        '@modelcontextprotocol/server-filesystem',
        $userHome . '/Documents',
    ],
    workingDir: $userHome
);

$fsClient = Client::make()
    ->withClientInfo('MyFileSystemApp', '1.0')
    ->withCapabilities($clientCapabilities)
    // ->withLogger(new MyPsrLogger()) // 可选
    ->withServerConfig($fsServerConfig)
    ->build();

try {
    // 初始化连接(阻塞)
    $fsClient->initialize();

    // 同步交互
    $tools = $fsClient->listTools(); // 阻塞调用
    foreach ($tools as $tool) {
        echo"- Tool: {$tool->name}\n";
    }

    //... 调用其他方法,如 $fsClient->callTool(...)...

} catch (McpClientException $e) {
    echo"[MCP ERROR] ". get_class($e). ": ". $e->getMessage(). "\n";
    // 检查 $e->getPrevious() 获取底层传输/进程错误
} catch (\Throwable $e) {
    echo"[UNEXPECTED ERROR] ". $e->getMessage(). "\n";
} finally {
    // 断开连接(阻塞)
    if (isset($fsClient)) {
        $fsClient->disconnect();
    }
}

配置

配置包括以下几个方面:

  • 客户端标识:应用程序的名称和版本,直接传递给构建器。
  • 客户端功能:使用ClientCapabilities声明客户端支持的功能。
  • 服务器连接:使用ServerConfig配置客户端实例要连接的单个服务器的详细信息。
  • (可选)依赖项:日志记录器、缓存、事件分发器、事件循环。

ClientCapabilities

用于声明客户端支持的功能,使用静态工厂方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use PhpMcp\Client\Model\Capabilities as ClientCapabilities;

// 客户端支持从服务器采样请求
$clientCapabilities = ClientCapabilities::forClient(supportsSampling: true);

// 客户端不支持从服务器采样请求
$clientCapabilities = ClientCapabilities::forClient(supportsSampling: false);

// 待办事项:如果需要,添加对声明“roots”功能的支持

ServerConfig

定义如何连接到单个MCP服务器。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use PhpMcp\Client\Enum\TransportType;
usePhpMcp\Client\ServerConfig;

// 示例:Stdio服务器
$stdioConfig = new ServerConfig(
    name: 'local_file_server',       // 必需:此配置的唯一ID
    transport: TransportType::Stdio, // 必需:传输类型
    timeout: 15.0,                   // 可选:请求超时时间(秒)
    command: 'npx',                  // Stdio必需:可执行文件
    args: [                          // Stdio可选:参数数组
        '-y',
        '@modelcontextprotocol/server-filesystem',
        '/path/to/project'
    ],
    workingDir: '/path/to/project',  // Stdio可选:工作目录
    env: ['DEBUG' =>'mcp*']         // Stdio可选:环境变量
);

// 示例:HTTP服务器
$httpConfig = new ServerConfig(
    name:'remote_web_agent',        // 必需:唯一ID
    transport: TransportType::Http,  // 必需:传输类型
    timeout: 45.0,                   // 可选:请求超时时间
    url: 'http://localhost:8080/sse',// Http必需:SSE URL
    headers: [                       // Http可选:认证/自定义头
        'Authorization' => 'Bearer xyz789'
    ],
);

从数组/JSON加载配置

可以轻松解析存储在数组中的配置(例如从JSON文件或框架配置中获取)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use PhpMcp\Client\ServerConfig;
usePhpMcp\Client\Exception\ConfigurationException;

$jsonConfig = '{
    "mcpServers": {
        "stdio_files": {
            "command": "php",
            "args": ["/app/mcp/file_server.php"],
            "timeout": 10
        },
        "http_api": {
            "url": "https://api.example.com/mcp/sse",
            "transport": "http",
            "headers": {"X-API-Key": "secret"}
        }
    }
}';

$decodedConfig = json_decode($jsonConfig, true)['mcpServers']?? [];

$serverConfigs = [];
foreach ($decodedConfig as $name => $data) {
    try {
        $serverConfigs[$name] = ServerConfig::fromArray($name, $data);
    } catch (ConfigurationException $e) {
        echo"Error parsing config for '{$name}': {$e->getMessage()}\n";
    }
}

// 现在 $serverConfigs['stdio_files'] 和 $serverConfigs['http_api'] 包含ServerConfig对象。

ClientBuilder

使用构建器组装Client实例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use PhpMcp\Client\Client;
//... 其他用于Config、Logger等的use语句...
$client = Client::make()
    ->withClientInfo($clientName, $clientVersion) // 必需
    ->withCapabilities($clientCapabilities)       // 可选(提供默认值)
    ->withServerConfig($stdioConfig)              // 必需:服务器配置
    ->withLogger($myLogger)                       // 可选
    ->withCache($myCache, 3600)                   // 可选(缓存 + 生存时间)
    ->withEventDispatcher($myDispatcher)          // 可选
    ->withIdGenerator($myIdGenerator)             // 可选
    ->withLoop($myEventLoop)                      // 可选(默认为Loop::get())
    ->build();

使用方法

一旦为特定服务器配置好了Client实例:

1. 初始化连接

在发出请求之前,必须调用initialize()initializeAsync()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 同步(阻塞)
try {
    $client->initialize(); // 连接、执行握手操作,等待直到准备就绪
    echo"Connection Ready!";
} catch (Throwable $e) {
    echo"Initialization failed: ". $e->getMessage();
    // 处理错误... 客户端可能处于错误状态
}

// 异步(基于Promise)
$client->initializeAsync()->then(
    function(Client $readyClient) { /* 准备就绪 */ },
    function(Throwable $error) { /* 处理初始化失败 */ }
);
// 需要运行事件循环 ($client->getLoop()->run())

2. 发出请求

使用客户端方法,这些方法基于initialize()建立的单个连接进行操作。

  • 同步API(推荐用于简单脚本/框架):像listTools()callTool()readResource()等方法会阻塞执行,直到收到响应或超时。它们返回解析后的结果对象(如array<ToolDefinition>CallToolResult),或者抛出异常(TimeoutExceptionRequestExceptionConnectionException等)。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
try {
    if ($client->isReady()) { // 检查状态
        $tools = $client->listTools();
        $result = $client->callTool('myTool', ['param' => 'value']);
    }
} catch (Throwable $e) { /* 处理错误 */ }
  • 异步API(用于异步应用或并发请求):像listToolsAsync()callToolAsync()readResourceAsync()等方法返回一个React\Promise\PromiseInterface。需要使用Promise方法(thencatchfinally)或React\Async\await(在Fiber上下文中)来处理结果。并且需要运行事件循环。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use functionReact\Promise\all;

if ($client->isReady()) {
    $p1 = $client->listToolsAsync();
    $p2 = $client->readResourceAsync('config://settings');

    all([$p1, $p2])->then(
        function(array $results) {
            [$tools, $readResult] = $results;
            // 处理异步结果...
        },
        function(Throwable $error) {
            // 处理异步错误...
        }
    );
    // $client->getLoop()->run(); // 需要运行循环
}

3. 断开连接

与服务器交互完成后,始终要断开连接以释放资源(特别是对于stdio传输)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 同步
$client->disconnect(); // 阻塞直到连接关闭或超时

// 异步
$client->disconnectAsync()->then(function() { echo "Disconnected async"; });
// $loop->run();

可用的客户端方法

Client类提供了与连接的MCP服务器交互的方法。大多数方法都有同步(阻塞)和异步(返回Promise)两种变体。

连接与生命周期

  • (同步)initialize(): self:连接到服务器并执行MCP握手操作。阻塞直到准备就绪或抛出异常。返回客户端实例。
  • (异步)initializeAsync(): PromiseInterface<Client>:异步启动连接和握手操作。返回一个Promise,在连接准备就绪时解析为客户端实例,失败时拒绝。
  • (同步)disconnect(): void:优雅地关闭连接。阻塞直到断开连接完成或超时。
  • (异步)disconnectAsync(): PromiseInterface<void>:异步启动优雅断开连接操作。返回一个Promise,在断开连接完成时解析。
  • getStatus(): ConnectionStatus:返回当前连接状态枚举(DisconnectedConnectingHandshakingReadyClosingClosedError)。
  • isReady(): bool:辅助方法,如果状态为Ready则返回true
  • getServerName():?string:返回服务器名称(成功初始化后可用)。
  • getServerVersion():?string:返回服务器版本(成功初始化后可用)。
  • getNegotiatedCapabilities():?Capabilities:返回与服务器协商的功能(成功初始化后可用)。
  • getNegotiatedProtocolVersion():?string:返回与服务器商定的协议版本(成功初始化后可用)。

MCP操作(同步)

(这些方法要求客户端先初始化,并且会阻塞)

  • ping(): void
  • listTools(bool $useCache = true): array<ToolDefinition>
  • listResources(bool $useCache = true): array<ResourceDefinition>
  • listPrompts(bool $useCache = true): array<PromptDefinition>
  • listResourceTemplates(bool $useCache = true): array<ResourceTemplateDefinition>
  • callTool(string arguments = []): CallToolResult
  • readResource(string $uri): ReadResourceResult
  • getPrompt(string arguments = []): GetPromptResult
  • subscribeResource(string $uri): void
  • unsubscribeResource(string $uri): void
  • setLogLevel(string $level): void

MCP操作(异步)

(这些方法要求客户端先初始化,并返回React\Promise\PromiseInterface

  • pingAsync(): PromiseInterface<void>
  • listToolsAsync(): PromiseInterface<array<ToolDefinition>>
  • listResourcesAsync(): PromiseInterface<array<ResourceDefinition>>
  • listPromptsAsync(): PromiseInterface<array<PromptDefinition>>
  • listResourceTemplatesAsync(): PromiseInterface<array<ResourceTemplateDefinition>>
  • callToolAsync(string arguments = []): PromiseInterface<CallToolResult>
  • readResourceAsync(string $uri): PromiseInterface<ReadResourceResult>
  • getPromptAsync(string arguments = []): PromiseInterface<GetPromptResult>
  • subscribeResourceAsync(string $uri): PromiseInterface<void>
  • unsubscribeResourceAsync(string $uri): PromiseInterface<void>
  • setLogLevelAsync(string $level): PromiseInterface<void>
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-05-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开源技术小栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
PHP MCP 服务器 v1.0.0 发布!
PHP MCP Server:Model Context Protocol(MCP)服务器的核心PHP实现。
Tinywan
2025/05/05
2740
PHP MCP 服务器 v1.0.0 发布!
用 Go 语言轻松构建 MCP 客户端
](https://cloud.tencent.com/developer/article/2509998)。
陈明勇
2025/04/03
1.3K2
用 Go 语言轻松构建 MCP 客户端
PHP开发玩转MCP〡腾讯地图SSE接入Cursor客户端应用
2024 年 11 月,Anthropic 公司搞了个挺有意思的新玩意 - Model Context Protocol(模型上下文协议)简称为 MCP 协议。简单来说,它就是给 AI 和各类工具数据之间搭了个标准化的”桥梁”,让开发者不用再为对接问题头疼了。
Tinywan
2025/05/06
2240
PHP开发玩转MCP〡腾讯地图SSE接入Cursor客户端应用
适用于PHP的MCP模型上下文协议SDK
在 AI 大模型迅猛发展的当下,其影响力已广泛渗透至生活的方方面面。无论是智能客服的高效交互、内容创作的灵感激发,还是图像生成的创意呈现、数据分析的精准洞察,AI 大模型都展现出了令人瞩目的强大能力。然而,繁荣背后,AI 大模型正面临着一个棘手难题 —— 数据孤岛问题。这些模型如同被困孤岛的巨人,虽潜力无限,却因难以获取多元数据,致使应用严重受限。
Tinywan
2025/03/27
5660
适用于PHP的MCP模型上下文协议SDK
【Swoole系列2.3】TCP、UDP服务客户端
上一节,我们学习了如何搭起简单的 Http、TCP 以及 UDP 服务。是不是发现在 Swoole 中搭建这三种服务非常地简单方便。对于 Http 客户端来说,我们可以直接使用浏览器来进行测试,或者普通的 Curl、Guzzle 也可以方便地从代码中进行 Http 的测试。因此,我们也就不会过多地说 Http 客户端的问题。等到进阶相关的文章时,我们会再看看在 协程 中的 Http 客户端如何使用。
硬核项目经理
2023/03/03
1.7K0
【Swoole系列2.3】TCP、UDP服务客户端
【Swoole系列4.7】协程服务客户端
协程的学习依然还在继续,要知道,Swoole 现在最核心的就是协程,或者说,整个软件开发语言中,协程都是热门的内容。对于协程的理论以及一些基础的操作我们都已经了解过了,接下来,我们再看看 Swoole 中提供的一些协程客户端功能。在协程之前,异步客户端是 Swoole 的主流应用,但是,现在已经不推荐了,所以我们就直接拿协程来讲这些客户端相关的内容。
硬核项目经理
2023/03/03
5760
【Swoole系列4.7】协程服务客户端
PHP网络请求插件Guzzle使用
在写后台代码时,避免不了需要与其他第三方接口交互,如向服务号下发模板消息,有时可能需要下发超过 10 万条。这时不得不考虑使用异步和「多线程」的网络请求。
超级小可爱
2024/01/20
4600
PHP网络请求插件Guzzle使用
必看!SpringAI轻松构建MCP Client-Server架构
MCP 这个概念相信大家已经听了无数次了,但不同人会有不同的解释,你可能也是听得云里雾里的。
磊哥
2025/03/30
6781
必看!SpringAI轻松构建MCP Client-Server架构
理解MCP 通信机制
MCP核心遵循客户端-服务器架构,其中主机应用程序(MCP client)可以连接到多个服务器(MCP Server):
windealli
2025/04/21
3520
理解MCP 通信机制
一文掌握 MCP 上下文协议:从理论到实践
应用能够安全、灵活地访问和操作本地及远程数据资源,提升模型的功能性和可扩展性。 ​
陈明勇
2025/04/02
2.7K8
一文掌握 MCP 上下文协议:从理论到实践
快速上手:实现你的第一个 MCP Client
在 MCP Server 开发实战:无缝对接 LLM 和 Elasticsearch 一文中,我们详细介绍了如何利用 MCP Python SDK 编写一个 Elasticsearch MCP 服务器,并通过 Claude Desktop 作为 MCP 客户端进行交互。本文将进一步介绍如何使用 MCP Python SDK 编写一个 MCP 客户端,以便更加灵活地与 MCP 服务器进行通信和集成。本文的完整代码可以在 Github 上找到:https://github.com/cr7258/hands-on-lab/tree/main/ai/claude/mcp/client/elasticsearch-mcp-client-example
Se7en258
2025/05/21
820
快速上手:实现你的第一个 MCP Client
在浏览器使用 MCP,纯边缘函数实现 MCP Client & Server
下面是一个在线示例:https://mcp-on-edge.edgeone.site/?from=eo
EdgeOne 小助手
2025/05/09
2680
MCP协议从原理到开发:一文读懂大模型交互的标准化革命!
本文系统介绍了MCP协议在大模型交互标准化中的创新应用,通过技术解析+实践案例的方式,阐述了MCP协议的架构设计、开发实现原理及实际应用效果。重点探讨了MCP如何解决AI工具调用碎片化问题,并通过企业微信机器人开发实例展示MCP服务端/客户端开发全流程,干货满满点赞收藏!
腾讯云开发者
2025/04/18
2.2K1
MCP协议从原理到开发:一文读懂大模型交互的标准化革命!
swoole入门 server 跟 client
###那么什么是server呢 ? 顾名思义就是服务端。up 平时接触比较多的无非就是 nginx 和 apache。作为 webServer,二者都是通过监听某端口对外提供服务,swoole 的 server 也不例外同样需要绑定端口,同时能够提供给客户端相关的服务。
风清醉
2019/12/18
8060
swoole深入学习 2. tcp Server和tcp Client
这节来学习Swoole最基础的Server和Client。会通过创建一个tcp Server来讲解。
sunsky
2020/08/20
5150
Swoole入门到实战(一):PHP7&Swoole源码安装、玩转网络通信引擎、异步非堵塞IO场景
source FileName 作用:在当前bash环境下读取并执行FileName中的命令。 用于重新执行刚修改的初始化文档,如 .bash_profile 和 .profile 等等 注:该命令通常用命令“.”来替代 如:source /etc/profile 与 . /etc/profile是等效的
唐成勇
2019/05/26
1.7K0
Buzz库:PHP图像处理中的异步图像下载和保存
在互联网技术飞速发展的今天,图像处理成为了一个不可忽视的领域。无论是社交媒体、电子商务还是内容分享平台,图像的快速下载和保存都是提升用户体验的关键。Buzz库作为一个强大的PHP HTTP客户端库,提供了同步和异步请求的功能,使得图像处理变得更加高效。本文将详细介绍如何使用Buzz库在PHP中实现异步图像下载和保存,并在代码中加入代理信息以适应特定的网络环境。
小白学大数据
2024/12/09
3160
php与swoole实现异步任务队列
假如要发100封邮件,for循环100遍,用户直接揭竿而起,什么破网站! 但实际上,我们很可能有超过1万的邮件。怎么处理这个延迟的问题? 答案就是用异步。把“发邮件”这个操作封装,然后后台异步地执行1万遍。这样的话,用户提交网页后,他所等待的时间只是“把发邮件任务请求推送进队列里”的时间。而我们的后台服务将在用户看不见的地方跑。 在实现“异步队列”这点上,有人采用MySQL表或者redis来存放待发送的邮件,然后,每分钟定时读取待发送列表,然后处理。这便是定时异步任务队列。但当前提交的任务要一分钟后才能执行,在某些实时性要求高的应用场景里还是不快,比如发送短信的场景,只要一提交任务,便要马上执行,用户不需要等待返回结果。 以下将探讨用php扩展swoole实现实时异步任务队列发送短信的方案。
友儿
2022/09/11
1K0
simps/mqtt:适用于 PHP 的 MQTT 协议解析和协程客户端
Swoole 也给 PHP 提供了开发物联网项目的能力,只需要设置一个 open_mqtt_protocol[1] 选项,启用后就会解析 MQTT 包头,在 Worker 进程的 onReceive 事件每次都会返回一个完整的 MQTT 数据包
沈唁
2020/12/25
3.3K1
Swoole-2.0.1-Alpha 已发布,提供PHP原生协程支持
Swoole-2.0 提供了PHP原生协程调度器,PHP代码可以按照同步方式编写,底层引擎使用异步IO,调度器会在IO完成后自动切换PHP函数调用栈。 内置协程不依赖PHP的Yield/Generator语法,实现了真正的同步代码,异步IO。Swoole-2.0兼容Swoole-1.0所有现存特性,同时支持同步阻塞、异步非阻塞回调、协程 3 种 IO 模型。 协程可以理解为用户态线程,通过协作而不是抢占来进行切换。相对于操作系统进程或者线程,协程所有的操作都可以在用户态完成,创建和切换的消耗更低。Swool
CSDN技术头条
2018/02/12
9570
推荐阅读
相关推荐
PHP MCP 服务器 v1.0.0 发布!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档