MCP SDK for PHP

July 4, 2026 · View on GitHub

Working examples for building MCP servers and clients with logiscape/mcp-sdk-php v2. Every example targets the 2026-07-28 MCP specification revision by default while remaining interoperable with legacy clients and servers (2024-11-052025-11-25) through the SDK's automatic dual-era negotiation.

Unless a command says otherwise, run the examples from the repository (or your project) root so vendor/autoload.php resolves.

Getting started

ExampleDemonstrates
simple_server.phpThe minimal McpServer: one tool, run() auto-selects stdio (CLI) or HTTP (web SAPI)
simple_server_stdio.phpSame server forced onto the stdio transport with runStdio()
simple_server_http.phpSame server forced onto the HTTP transport with runHttp()
# stdio (for MCP hosts that spawn a local process)
php examples/simple_server.php

# HTTP (development server; on real hosting just upload the script)
php -S localhost:8000 examples/simple_server_http.php

# inspect either with MCP Inspector
npx @modelcontextprotocol/inspector

The 2026-07-28 stateless revision

ExampleDemonstrates
stateless_server.phpA minimal stateless server: tools (including structured output), resources, a resource template, and a prompt served per-request with no handshake and no session — the model that fits shared PHP hosting
client_negotiation.phpDual-era negotiation from the client side: server/discover probing, legacy fallback, and the protocolMode override (auto / modern / legacy)
# stdio, auto-negotiates the modern era
php examples/client_negotiation.php examples/stateless_server.php

# force the legacy initialize handshake for comparison
php examples/client_negotiation.php examples/stateless_server.php --mode=legacy

# or over HTTP
php -S localhost:8000 examples/stateless_server.php &
php examples/client_negotiation.php http://localhost:8000

Interactive tools (elicitation / multi-round-trip input)

ExampleDemonstrates
elicitation_server.phpA tool that asks the user for structured input mid-execution via an injected ElicitationContext — carried as SEP-2322 InputRequiredResult exchanges on the modern path, as server-initiated requests on the legacy path
elicitation_client.phpRegistering an onElicit handler; the SDK services the multi-round-trip exchange transparently inside callTool()
php examples/elicitation_client.php   # spawns elicitation_server.php over stdio

Tasks extension (SEP-2663, io.modelcontextprotocol/tasks)

ExampleDemonstrates
tasks_server.phpenableTasks() plus per-tool taskSupport: opt-in (OPTIONAL and REQUIRED), including a task that gathers in-task input
tasks_client.phpDeclaring the extension, receiving a CreateTaskResult task handle from callTool(), polling tasks/get, and answering input_required via tasks/update
php examples/tasks_client.php   # spawns tasks_server.php over stdio

MCP Apps extension (SEP-1865, io.modelcontextprotocol/ui)

ExampleDemonstrates
apps_server/Linking a tool to an interactive ui:// HTML template with McpServer::ui(), rendered by Apps-capable hosts in a sandboxed iframe

HTTP clients and OAuth

ExampleDemonstrates
client_http.phpA command-line HTTP client: connect options (headers, TLS, timeouts), capability inspection, and listing tools/prompts/resources
server_auth/An OAuth 2.1-protected HTTP server (McpServer::withAuth()) with JWT validation and the RFC 9728 protected-resource metadata endpoint, deployable on cPanel/Apache