A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/php-mcp/client below:

php-mcp/client: Core PHP implementation for the Model Context Protocol (MCP) Client

PHP MCP Client is a PHP library for interacting with servers that implement the Model Context Protocol (MCP).

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.

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.

This library aligns with the MCP specification's model where one client instance manages a stateful connection to one server.

The Model Context Protocol (MCP) is an open standard designed to standardize how AI assistants and applications connect to external data sources, APIs, and tools (like codebases, databases, web browsers). It acts as a communication layer, enabling AI models (like Claude, or models integrated via frameworks like OpenAI's) to securely access and interact with context provided by different servers.

This client library allows your PHP application (acting as the "Host" in MCP terminology) to consume capabilities offered by one or more MCP servers.

Install the package via Composer:

composer require php-mcp/client

The necessary ReactPHP dependencies (event-loop, promise, stream, child-process, http) should be installed automatically.

Quick Start: Simple Synchronous Usage (Stdio)

This example connects to a local filesystem server running via npx.

<?php

require 'vendor/autoload.php';

use PhpMcp\Client\Client;
use PhpMcp\Client\Enum\TransportType;
use PhpMcp\Client\Model\Capabilities as ClientCapabilities;
use PhpMcp\Client\ServerConfig;
use PhpMcp\Client\Exception\McpClientException;

$clientCapabilities = ClientCapabilities::forClient(); // Default client caps

$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()) // Optional
    ->withServerConfig($fsServerConfig)
    ->build();

try {
    // Initialize Connection (BLOCKING)
    $fsClient->initialize();

    // Interact (Synchronously)
    $tools = $fsClient->listTools(); // Blocking call
    foreach ($tools as $tool) {
        echo "- Tool: {$tool->name}\n";
    }

    // ... Call other methods like $fsClient->callTool(...) ...

} catch (McpClientException $e) {
    echo "[MCP ERROR] " . get_class($e) . ": " . $e->getMessage() . "\n";
    // Check $e->getPrevious() for underlying transport/process errors
} catch (\Throwable $e) {
    echo "[UNEXPECTED ERROR] " . $e->getMessage() . "\n";
} finally {
    // Disconnect (BLOCKING)
    if (isset($fsClient)) {
        $fsClient->disconnect();
    }
}

Configuration involves setting up:

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

Declares features your client supports. Use the static factory method.

use PhpMcp\Client\Model\Capabilities as ClientCapabilities;

// Client supports sampling requests from the server
$clientCapabilities = ClientCapabilities::forClient(supportsSampling: true);

// Client does NOT support sampling
$clientCapabilities = ClientCapabilities::forClient(supportsSampling: false);

// TODO: Add support for declaring 'roots' capability if needed

Defines how to connect to a single MCP server.

use PhpMcp\Client\Enum\TransportType;
use PhpMcp\Client\ServerConfig;

// Example: Stdio Server
$stdioConfig = new ServerConfig(
    name: 'local_file_server',       // Required: Unique ID for this config
    transport: TransportType::Stdio, // Required: Transport type
    timeout: 15.0,                   // Optional: Request timeout (seconds)
    command: 'npx',                  // Required for Stdio: Executable
    args: [                          // Optional for Stdio: Arguments array
        '-y',
        '@modelcontextprotocol/server-filesystem',
        '/path/to/project'
    ],
    workingDir: '/path/to/project',  // Optional for Stdio: Working directory
    env: ['DEBUG' => 'mcp*']         // Optional for Stdio: Environment variables
);

// Example: HTTP Server
$httpConfig = new ServerConfig(
    name: 'remote_web_agent',        // Required: Unique ID
    transport: TransportType::Http,  // Required: Transport type
    timeout: 45.0,                   // Optional: Request timeout
    url: 'http://localhost:8080/sse',// Required for Http: SSE URL
    headers: [                       // Optional for Http: Auth/Custom headers
        'Authorization' => 'Bearer xyz789'
    ],
);
Loading Config from Array/JSON

You can easily parse configurations stored in arrays (e.g., from JSON files or framework config).

use PhpMcp\Client\ServerConfig;
use PhpMcp\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";
    }
}

// Now $serverConfigs['stdio_files'] and $serverConfigs['http_api']
// contain ServerConfig objects.

Use the builder to assemble the Client instance:

use PhpMcp\Client\Client;
// ... other use statements for Config, Logger etc...

$client = Client::make()
    ->withClientInfo($clientName, $clientVersion) // Required
    ->withCapabilities($clientCapabilities)       // Optional (defaults provided)
    ->withServerConfig($stdioConfig)              // Required: Config for THE server
    ->withLogger($myLogger)                       // Optional
    ->withCache($myCache, 3600)                   // Optional (cache + TTL)
    ->withEventDispatcher($myDispatcher)          // Optional
    ->withIdGenerator($myIdGenerator)             // Optional
    ->withLoop($myEventLoop)                      // Optional (defaults to Loop::get())
    ->build();

Once you have a configured Client instance for a specific server:

1. Initialize the Connection:

You must call initialize() or initializeAsync() before making requests.

// Synchronous (Blocking)
try {
    $client->initialize(); // Connects, performs handshake, waits until ready
    echo "Connection Ready!";
} catch (Throwable $e) {
    echo "Initialization failed: " . $e->getMessage();
    // Handle error... client is likely in Error state
}

// Asynchronous (Promise-based)
$client->initializeAsync()->then(
    function(Client $readyClient) { /* Ready */ },
    function(Throwable $error) { /* Handle init failure */ }
);
// Requires running the event loop ($client->getLoop()->run())

2. Making Requests:

Use the client methods. They operate on the single connection established by initialize().

3. Disconnecting:

Always disconnect when you are finished interacting with a server to release resources (especially for stdio transports).

// Synchronous
$client->disconnect(); // Blocks until closed or timeout

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

The Client class provides methods for interacting with the connected MCP server. Most methods have both a synchronous (blocking) and an asynchronous (Promise-returning) variant.

Connection & Lifecycle:

MCP Operations (Sync):

(These methods require the client to be initialized first and will block)

MCP Operations (Async):

(These methods require the client to be initialized first and return React\Promise\PromiseInterface)

Advanced:

Handling Server Notifications (Asynchronous Only)

MCP servers can send notifications (e.g., resources/didChange). To receive these:

  1. Configure the client with a PSR-14 EventDispatcherInterface using ->withEventDispatcher(...).
  2. Add listeners to your dispatcher for events like PhpMcp\Client\Event\ResourceChanged.
  3. Use the asynchronous API (initializeAsync, potentially other *Async methods).
  4. Run the event loop continuously ($client->getLoop()->run()). Notifications arrive via the underlying transport (usually SSE) only while the loop is active.

See examples/04-handling-notifications.php for a conceptual guide.

The client uses specific exceptions inheriting from PhpMcp\Client\Exception\McpClientException. Catching these allows for targeted error handling:

Always wrap client interactions in try...catch blocks to handle these potential failures gracefully.

See the examples/ directory for working code:

composer install --dev

composer test

Contributions are welcome! Please see CONTRIBUTING.md or open an issue/pull request.

The MIT License (MIT). See LICENSE.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4