Skip to content

Commit e6d6cfc

Browse files
refactor: Remove ClientInfo and ServerInfo models, update client configuration to use name and version directly
1 parent 84c1ed6 commit e6d6cfc

24 files changed

+155
-976
lines changed

README.md

Lines changed: 29 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
[![Tests](https://img.shields.io/github/actions/workflow/status/php-mcp/client/tests.yml?branch=main&style=flat-square)](https://github.com/php-mcp/client/actions/workflows/tests.yml)
66
[![License](https://img.shields.io/packagist/l/php-mcp/client.svg?style=flat-square)](LICENSE)
77

8-
**`php-mcp/client` is a PHP library for interacting with servers that implement the Model Context Protocol (MCP).**
8+
** PHP MCP Client is a PHP library for interacting with servers that implement the Model Context Protocol (MCP).**
99

1010
It provides a developer-friendly interface to connect to individual MCP servers using different transports (`stdio`, `http+sse`), manage the connection lifecycle, discover server capabilities (Tools, Resources, Prompts), and execute requests like calling tools or reading resources.
1111

1212
While utilizing asynchronous I/O internally via ReactPHP for robustness and handling features like server-sent events, the library offers **both** a straightforward **synchronous (blocking) API** for common use cases and an **asynchronous (Promise-based) API** for advanced control and concurrency.
1313

14-
This library aligns with the MCP specification's model where one client instance manages a stateful connection to one server, and acts as the counterpart to the [`php-mcp/server`](https://github.com/php-mcp/server) package.
14+
This library aligns with the MCP specification's model where one client instance manages a stateful connection to one server.
1515

1616
## Introduction to MCP
1717

@@ -30,7 +30,6 @@ This client library allows your PHP application (acting as the "Host" in MCP ter
3030
* `stdio`: Communicating with server processes via Standard Input/Output.
3131
* `http`: Communicating with servers via HTTP POST and Server-Sent Events (SSE).
3232
* **Explicit Connection Lifecycle:** Requires `->initialize()` or `->initializeAsync()` to connect and perform the handshake before making requests. Provides `disconnect()` / `disconnectAsync()`.
33-
* **Capability Discovery:** Automatically performs the MCP handshake via `initialize()` to determine server capabilities.
3433
* **Tool/Resource/Prompt Interaction:** Provides comprehensive methods (sync & async) to list available elements and execute requests like `tools/call`, `resources/read`, `prompts/get`.
3534
* **PSR Compliance:** Integrates with standard PHP interfaces:
3635
* `PSR-3` (LoggerInterface): Integrate your application's logger.
@@ -43,7 +42,6 @@ This client library allows your PHP application (acting as the "Host" in MCP ter
4342

4443
* PHP >= 8.1
4544
* Composer
46-
* `react/event-loop` (and other ReactPHP components installed as dependencies)
4745
* *(For Stdio Transport)*: Ability to execute the server command.
4846
* *(For Http Transport)*: Network access to the MCP server URL.
4947

@@ -68,66 +66,44 @@ require 'vendor/autoload.php';
6866

6967
use PhpMcp\Client\Client;
7068
use PhpMcp\Client\Enum\TransportType;
71-
use PhpMcp\Client\Model\ClientInfo;
7269
use PhpMcp\Client\Model\Capabilities as ClientCapabilities;
7370
use PhpMcp\Client\ServerConfig;
7471
use PhpMcp\Client\Exception\McpClientException;
7572

76-
// 1. Client Info & Capabilities
77-
$clientInfo = new ClientInfo('MyFileSystemApp', '1.0');
7873
$clientCapabilities = ClientCapabilities::forClient(); // Default client caps
7974

80-
// 2. Server Configuration (Filesystem Server Example)
81-
$userHome = $_SERVER['HOME'] ?? $_SERVER['USERPROFILE'] ?? getcwd(); // Get user's home reliably
75+
$userHome = $_SERVER['HOME'] ?? $_SERVER['USERPROFILE'] ?? getcwd();
8276
$fsServerConfig = new ServerConfig(
83-
name: 'local_filesystem', // A name for this config
77+
name: 'local_filesystem',
8478
transport: TransportType::Stdio,
8579
timeout: 15,
86-
command: 'npx', // The command executable
87-
args: [ // Arguments array
88-
'-y', // Argument for npx
89-
'@modelcontextprotocol/server-filesystem', // The server package
90-
$userHome . '/Documents', // Example directory server can access
91-
// Add more allowed paths if needed
80+
command: 'npx',
81+
args: [
82+
'-y',
83+
'@modelcontextprotocol/server-filesystem',
84+
$userHome . '/Documents',
9285
],
93-
workingDir: $userHome // Where to run npx from
86+
workingDir: $userHome
9487
);
9588

96-
// 3. Build the Client instance for this specific server
9789
$fsClient = Client::make()
98-
->withClientInfo($clientInfo)
90+
->withName('MyFileSystemApp')
91+
->withVersion('1.0')
9992
->withCapabilities($clientCapabilities)
10093
// ->withLogger(new MyPsrLogger()) // Optional
10194
->withServerConfig($fsServerConfig)
10295
->build();
10396

10497
try {
105-
// 4. Initialize Connection (BLOCKING)
106-
echo "Initializing connection to '{$fsServerConfig->name}'...\n";
98+
// Initialize Connection (BLOCKING)
10799
$fsClient->initialize();
108-
echo "Connection Ready! Server: {$fsClient->getServerInfo()?->name}\n";
109100

110-
// 5. Interact (Synchronously)
111-
echo "Listing tools...\n";
101+
// Interact (Synchronously)
112102
$tools = $fsClient->listTools(); // Blocking call
113103
foreach ($tools as $tool) {
114104
echo "- Tool: {$tool->name}\n";
115105
}
116106

117-
echo "\nReading a resource (e.g., a file in allowed dir)...\n";
118-
$readmePath = $userHome . '/Documents/README.md'; // Example file path
119-
if (file_exists($readmePath)) {
120-
$resourceUri = 'file://' . realpath($readmePath);
121-
echo "Reading: {$resourceUri}\n";
122-
$readResult = $fsClient->readResource($resourceUri); // Blocking call
123-
$content = $readResult->contents[0] ?? null;
124-
if ($content) {
125-
echo "Content (first 100 chars): " . substr($content->text ?? '', 0, 100) . "...\n";
126-
}
127-
} else {
128-
echo "Skipping readResource: {$readmePath} not found.\n";
129-
}
130-
131107
// ... Call other methods like $fsClient->callTool(...) ...
132108

133109
} catch (McpClientException $e) {
@@ -136,11 +112,9 @@ try {
136112
} catch (\Throwable $e) {
137113
echo "[UNEXPECTED ERROR] " . $e->getMessage() . "\n";
138114
} finally {
139-
// 6. Disconnect (BLOCKING)
115+
// Disconnect (BLOCKING)
140116
if (isset($fsClient)) {
141-
echo "Disconnecting from '{$fsServerConfig->name}'...\n";
142117
$fsClient->disconnect();
143-
echo "Disconnected.\n";
144118
}
145119
}
146120
```
@@ -149,25 +123,11 @@ try {
149123

150124
Configuration involves setting up:
151125

152-
1. **Client Identity:** Your application's details using `ClientInfo`.
126+
1. **Client Identity:** Your application's name and version, passed directly to the builder.
153127
2. **Client Capabilities:** Features your client supports using `ClientCapabilities`.
154128
3. **Server Connection:** Details for the *single server* this client instance will connect to, using `ServerConfig`.
155129
4. **(Optional) Dependencies:** Logger, Cache, Event Dispatcher, Event Loop.
156130

157-
### `ClientInfo`
158-
159-
A simple value object for identifying your client application to the server.
160-
161-
```php
162-
use PhpMcp\Client\Model\ClientInfo;
163-
164-
$clientInfo = new ClientInfo(
165-
name: 'MyAwesomePHPApp',
166-
version: '2.5.0'
167-
// Optional: supportedLocales: ['en-US', 'en-GB']
168-
);
169-
```
170-
171131
### `ClientCapabilities`
172132

173133
Declares features your client supports. Use the static factory method.
@@ -267,14 +227,15 @@ use PhpMcp\Client\Client;
267227
// ... other use statements for Config, Logger etc...
268228

269229
$client = Client::make()
270-
->withClientInfo($clientInfo) // Required
271-
->withCapabilities($clientCapabilities) // Optional (defaults provided)
272-
->withServerConfig($stdioConfig) // Required: Config for THE server
273-
->withLogger($myLogger) // Optional
274-
->withCache($myCache, 3600) // Optional (cache + TTL)
275-
->withEventDispatcher($myDispatcher) // Optional
276-
->withIdGenerator($myIdGenerator) // Optional
277-
->withLoop($myEventLoop) // Optional (defaults to Loop::get())
230+
->withName($clientName) // Required
231+
->withVersion($clientVersion) // Required
232+
->withCapabilities($clientCapabilities) // Optional (defaults provided)
233+
->withServerConfig($stdioConfig) // Required: Config for THE server
234+
->withLogger($myLogger) // Optional
235+
->withCache($myCache, 3600) // Optional (cache + TTL)
236+
->withEventDispatcher($myDispatcher) // Optional
237+
->withIdGenerator($myIdGenerator) // Optional
238+
->withLoop($myEventLoop) // Optional (defaults to Loop::get())
278239
->build();
279240
```
280241

@@ -377,8 +338,10 @@ The `Client` class provides methods for interacting with the connected MCP serve
377338
Returns the current connection status enum (`Disconnected`, `Connecting`, `Handshaking`, `Ready`, `Closing`, `Closed`, `Error`).
378339
* `isReady(): bool`
379340
Helper method, returns `true` if status is `Ready`.
380-
* `getServerInfo(): ?ServerInfo`
381-
Returns information about the connected server (available after successful initialization).
341+
* `getServerName(): ?string`
342+
Returns the name of the server (available after successful initialization).
343+
* `getServerVersion(): ?string`
344+
Returns the version of the server (available after successful initialization).
382345
* `getNegotiatedCapabilities(): ?Capabilities`
383346
Returns the capabilities negotiated with the server (available after successful initialization).
384347
* `getNegotiatedProtocolVersion(): ?string`

examples/01-simple-stdio-sync.php

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,14 @@
1212
use PhpMcp\Client\Exception\McpClientException;
1313
use PhpMcp\Client\Exception\RequestException;
1414
use PhpMcp\Client\Model\Capabilities as ClientCapabilities;
15-
use PhpMcp\Client\Model\ClientInfo;
1615
use PhpMcp\Client\Model\Content\EmbeddedResource;
1716
use PhpMcp\Client\Model\Content\TextContent;
1817
use PhpMcp\Client\ServerConfig;
1918
use PhpMcp\Client\StreamLogger;
2019

2120
// --- Configuration ---
22-
$clientInfo = new ClientInfo(
23-
name: 'MySimplePHPClient',
24-
version: '0.1.0'
25-
);
21+
$clientName = 'MySimplePHPClient';
22+
$clientVersion = '0.1.0';
2623
$clientCapabilities = ClientCapabilities::forClient(supportsSampling: false);
2724
$logger = new StreamLogger(__DIR__.'/client_stdio.log');
2825

@@ -37,7 +34,8 @@
3734
);
3835

3936
$stdioClient = Client::make()
40-
->withClientInfo($clientInfo)
37+
->withName($clientName)
38+
->withVersion($clientVersion)
4139
->withCapabilities($clientCapabilities)
4240
->withLogger($logger)
4341
->withServerConfig($stdioServerConfig)
@@ -49,7 +47,7 @@
4947
$stdioClient->initialize();
5048

5149
echo "Connection to {$stdioServerConfig->name} initialized successfully!\n";
52-
echo "Server: {$stdioClient->getServerInfo()?->name} v{$stdioClient->getServerInfo()?->version}, Protocol: {$stdioClient->getNegotiatedProtocolVersion()}\n";
50+
echo "Server: {$stdioClient->getServerName()} v{$stdioClient->getServerVersion()}, Protocol: {$stdioClient->getNegotiatedProtocolVersion()}\n";
5351

5452
// 1. List Tools
5553
echo "\n[1] Listing Tools...\n";

examples/02-simple-http-sync.php

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,14 @@
1212
use PhpMcp\Client\Exception\McpClientException;
1313
use PhpMcp\Client\Exception\RequestException;
1414
use PhpMcp\Client\Model\Capabilities as ClientCapabilities;
15-
use PhpMcp\Client\Model\ClientInfo;
1615
use PhpMcp\Client\Model\Content\EmbeddedResource;
1716
use PhpMcp\Client\ServerConfig;
1817
use PhpMcp\Client\StreamLogger;
1918

2019
// --- Configuration ---
2120

22-
$clientInfo = new ClientInfo(
23-
name: 'MySimplePHPHttpClient',
24-
version: '0.1.1'
25-
);
21+
$clientName = 'MySimplePHPHttpClient';
22+
$clientVersion = '0.1.1';
2623
$clientCapabilities = ClientCapabilities::forClient(supportsSampling: false);
2724
$logger = new StreamLogger(__DIR__.'/client_http.log');
2825

@@ -34,7 +31,8 @@
3431
);
3532

3633
$httpClient = Client::make()
37-
->withClientInfo($clientInfo)
34+
->withName($clientName)
35+
->withVersion($clientVersion)
3836
->withCapabilities($clientCapabilities)
3937
->withLogger($logger)
4038
->withServerConfig($httpServerConfig)
@@ -47,7 +45,7 @@
4745
$httpClient->initialize();
4846

4947
echo "Connection to {$httpServerConfig->name} initialized successfully!\n";
50-
echo "Server: {$httpClient->getServerInfo()?->name} v{$httpClient->getServerInfo()?->version}, Protocol: {$httpClient->getNegotiatedProtocolVersion()}\n";
48+
echo "Server: {$httpClient->getServerName()} v{$httpClient->getServerVersion()}, Protocol: {$httpClient->getNegotiatedProtocolVersion()}\n";
5149

5250
// 1. List Tools
5351
echo "\n[1] Listing Tools...\n";

examples/03-multiple-servers-sync.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,14 @@
1111
use PhpMcp\Client\Enum\TransportType;
1212
use PhpMcp\Client\Exception\McpClientException;
1313
use PhpMcp\Client\Model\Capabilities as ClientCapabilities;
14-
use PhpMcp\Client\Model\ClientInfo;
1514
use PhpMcp\Client\Model\Content\TextContent;
1615
use PhpMcp\Client\ServerConfig;
1716
use PhpMcp\Client\StreamLogger;
1817

1918
// --- Configuration ---
2019

21-
$clientInfo = new ClientInfo(
22-
name: 'MultiServerClientDemo',
23-
version: '0.2.0'
24-
);
20+
$clientName = 'MultiServerClientDemo';
21+
$clientVersion = '0.2.0';
2522
$clientCapabilities = ClientCapabilities::forClient(supportsSampling: false);
2623
$logger = new StreamLogger(__DIR__.'/client_multi.log');
2724

@@ -42,14 +39,16 @@
4239

4340
// --- Instantiate Clients ---
4441
$stdioClient = Client::make()
45-
->withClientInfo($clientInfo)
42+
->withName($clientName)
43+
->withVersion($clientVersion)
4644
->withCapabilities($clientCapabilities)
4745
->withLogger($logger)
4846
->withServerConfig($stdioServerConfig)
4947
->build();
5048

5149
$httpClient = Client::make()
52-
->withClientInfo($clientInfo)
50+
->withName($clientName)
51+
->withVersion($clientVersion)
5352
->withCapabilities($clientCapabilities)
5453
->withLogger($logger)
5554
->withServerConfig($httpServerConfig)

examples/04-multiple-servers-async.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
use PhpMcp\Client\Enum\ConnectionStatus;
1313
use PhpMcp\Client\Enum\TransportType;
1414
use PhpMcp\Client\Model\Capabilities as ClientCapabilities;
15-
use PhpMcp\Client\Model\ClientInfo;
1615
use PhpMcp\Client\Model\Content\EmbeddedResource;
1716
use PhpMcp\Client\Model\Content\TextContent;
1817
use PhpMcp\Client\ServerConfig;
@@ -21,10 +20,8 @@
2120

2221
use function React\Promise\all;
2322

24-
$clientInfo = new ClientInfo(
25-
name: 'MultiServerAsyncClient',
26-
version: '0.3.0'
27-
);
23+
$clientName = 'MultiServerAsyncClient';
24+
$clientVersion = '0.3.0';
2825
$clientCapabilities = ClientCapabilities::forClient(supportsSampling: false);
2926
$logger = new StreamLogger(__DIR__.'/client_multi_async.log');
3027
$loop = Loop::get();
@@ -47,15 +44,17 @@
4744

4845
// --- Build Clients ---
4946
$stdioClient = Client::make()
50-
->withClientInfo($clientInfo)
47+
->withName($clientName)
48+
->withVersion($clientVersion)
5149
->withCapabilities($clientCapabilities)
5250
->withLogger($logger)
5351
->withLoop($loop)
5452
->withServerConfig($stdioServerConfig)
5553
->build();
5654

5755
$httpClient = Client::make()
58-
->withClientInfo($clientInfo)
56+
->withName($clientName)
57+
->withVersion($clientVersion)
5958
->withCapabilities($clientCapabilities)
6059
->withLogger($logger)
6160
->withLoop($loop)

examples/05-openai-php-integration-sync/client.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
use PhpMcp\Client\Exception\McpClientException;
1313
use PhpMcp\Client\Exception\RequestException;
1414
use PhpMcp\Client\Model\Capabilities as ClientCapabilities;
15-
use PhpMcp\Client\Model\ClientInfo;
1615
use PhpMcp\Client\Model\Content\TextContent;
1716
use PhpMcp\Client\ServerConfig;
1817
use PhpMcp\Client\StreamLogger;
@@ -29,7 +28,8 @@
2928

3029
$logger = new StreamLogger(__DIR__.'/openai_client.log');
3130

32-
$clientInfo = new ClientInfo('OpenAI-MCP-Demo', '1.0');
31+
$clientName = 'OpenAI-MCP-Demo';
32+
$clientVersion = '1.0';
3333
$clientCapabilities = ClientCapabilities::forClient();
3434

3535
$pathToStdioServerScript = __DIR__.'/../../../server/samples/php_stdio/server.php';
@@ -39,7 +39,8 @@
3939
name: 'local_stdio',
4040
transport: TransportType::Stdio,
4141
timeout: 15,
42-
command: ['php', $pathToStdioServerScript]
42+
command: 'php',
43+
args: [$pathToStdioServerScript]
4344
);
4445

4546
$httpServerConfig = new ServerConfig(
@@ -53,8 +54,8 @@
5354
name: 'firecrawl',
5455
transport: TransportType::Stdio,
5556
timeout: 45,
56-
command: [
57-
'env',
57+
command: 'env',
58+
args: [
5859
'FIRECRAWL_API_KEY=fc-f6bc6f23c9554cecb64a3feecc802d26',
5960
'npx',
6061
'-y',
@@ -75,7 +76,8 @@
7576
foreach ($serversToConfigure as $serverName => $serverConfig) {
7677
try {
7778
$mcpClients[$serverName] = Client::make()
78-
->withClientInfo($clientInfo)
79+
->withName($clientName)
80+
->withVersion($clientVersion)
7981
->withCapabilities($clientCapabilities)
8082
->withLogger($logger)
8183
->withServerConfig($serverConfig)

0 commit comments

Comments
 (0)