Skip to content

Latest commit

 

History

History
97 lines (77 loc) · 8.24 KB

File metadata and controls

97 lines (77 loc) · 8.24 KB

Examples

Every example lives in examples/ and runs against the dependencies installed in the repository root. Each server example is a server.php whose bootstrap picks the transport from the SAPI it runs under:

# STDIO transport
php examples/server/discovery-calculator/server.php

# Streamable HTTP transport
php -S 127.0.0.1:8000 examples/server/discovery-userprofile/server.php

# Interactive testing with the MCP Inspector
npx @modelcontextprotocol/inspector php examples/server/discovery-calculator/server.php

Server examples

Example What it shows Docs
discovery-calculator Attribute discovery of tools, resources and prompts; ResourceLink content Tools
discovery-userprofile Resource templates with completion providers; FileSessionStore Resource templates, Completions
explicit-registration Manual addTool()/addResource()/addResourceTemplate()/addPrompt() without discovery Registering elements
combined-registration Discovery and manual registration combined, and which wins on conflict Registering elements
cached-discovery Caching the discovery scan in a PSR-16 cache Server builder
custom-dependencies Handlers pulling services from a PSR-11 container Server builder
complex-tool-schema Rich input schemas from typed parameters, PHP enums and defaults Schema generation
schema-showcase #[Schema] constraint attributes: formats, patterns, ranges Schema generation
env-variables Configuring a server through environment variables Server builder
client-communication Sampling, roots, progress and log messages from inside a handler Talking back to the client
client-logging Structured log notifications through the ClientLogger Logging
elicitation Asking the user for input mid-call with ClientGateway::elicit() and typed elicitation schemas, on either protocol era Asking for input
custom-method-handlers Registering handlers for custom JSON-RPC methods Custom message handlers
mcp-apps The MCP Apps extension: a tool that ships an interactive HTML view Protocol extensions
stateless-lifecycle Revision 2026-07-28: cache policy, request state, notification bus Serving both eras, Caching, Subscriptions
oauth-keycloak OAuth authorization against a Keycloak instance (own README) Authorization
oauth-microsoft OAuth authorization against Microsoft Entra ID (own README) Authorization

Client examples

Example What it shows Docs
stdio_discovery_calculator.php Connecting over STDIO, listing and calling tools, reading resources Connecting to a server
http_discovery_calculator.php The same conversation over the Streamable HTTP transport Transports
stdio_client_communication.php Answering server-initiated sampling, log and progress messages Server-initiated requests
http_client_communication.php The same handlers over HTTP — see the note on PHP's built-in server below Server-initiated requests
stdio_elicitation.php Answering elicitation requests from an interactive prompt Server-initiated requests
stdio_roots.php Exposing workspace roots and signalling roots/list_changed Server-initiated requests
stateless_lifecycle_client.php A client pinned to revision 2026-07-28 — see Modern-era client Connecting to a server

Client examples run directly:

php examples/client/stdio_discovery_calculator.php

Note: PHP's built-in development server handles one request at a time, so the sampling round-trip in http_client_communication.php will not complete under a plain php -S. Start it with worker processes instead: PHP_CLI_SERVER_WORKERS=2 php -S 127.0.0.1:8000 ….

The 2026-07-28 lifecycle

stateless-lifecycle/server.php answers both eras on the same URL. On revision 2026-07-28 every request carries its own protocol version and client capabilities, so a call is a single POST with no handshake before it:

php -S 127.0.0.1:8000 examples/server/stateless-lifecycle/server.php
curl -sS http://127.0.0.1:8000/ \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2026-07-28' \
  -H 'Mcp-Method: server/discover' \
  -d '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{
        "io.modelcontextprotocol/protocolVersion":"2026-07-28",
        "io.modelcontextprotocol/clientCapabilities":{}}}}'

The example's header comments document the equivalent handshake-era conversation against the same endpoint. Serving both eras explains how the routing works.

Modern-era client

stateless_lifecycle_client.php drives the server above from PHP: it pins ProtocolVersion::V2026_07_28, skips the handshake, discovers the server through server/discover and calls a tool — one process, no session:

php -S 127.0.0.1:8000 examples/server/stateless-lifecycle/server.php &
php examples/client/stateless_lifecycle_client.php

See Clients on the modern revision for the API it uses.