php-sdk/examples/server
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Christopher Hertel 7fe88677ad
[Docs][Examples][CI] Document and gate the 2026-07-28 lifecycle (#457)
docs/stateless-lifecycle.md walks the revision end to end - per-request
_meta, server/discover, multi round-trip requests, caching and subscriptions
- and a runnable example on each side shows what that looks like in code.

CI matrixes both conformance roles over both revisions. --spec-version is
cumulative across the dated revisions, so 2025-11-25 covers the two before
it; 2026-07-28 is not cumulative with them and needs its own run against its
own baseline. The runner is pinned so a PR only goes red for reasons in the
PR, and conformance-weekly tracks the moving target instead - on both
revisions, since the draft scenarios ship only on the alpha dist-tag.

The Inspector cannot reach a modern-lifecycle server (it opens with
initialize), so the example is covered by integration tests instead: one
drives it with hand-built HTTP the way a conforming client would, one drives
it with this SDK's client, and one drives the single endpoint from both eras.
2026-08-19 03:24:17 +02:00
..
cached-discovery CS update after release of v3.95 (#282) 2026-04-26 12:39:27 +02:00
client-communication [Client] Speak the 2026-07-28 lifecycle (#456) 2026-08-19 02:41:02 +02:00
client-logging Move examples to server directory (#198) 2025-12-27 15:39:05 +01:00
combined-registration [Examples] Demo pre-built instance handlers + inspector coverage (#390) 2026-07-15 00:23:20 +02:00
complex-tool-schema Use SchemaValidator to validate tool input (#203) 2026-01-11 21:46:53 +01:00
custom-dependencies Update codestyle based on updated Symfony rules (#229) 2026-02-01 11:54:31 +01:00
custom-method-handlers [Schema][Server] Add top-level title to Tool (#288) 2026-04-26 15:37:40 +02:00
discovery-calculator Move examples to server directory (#198) 2025-12-27 15:39:05 +01:00
discovery-userprofile [Schema] Add resource_link content block (#400) 2026-08-14 23:20:56 +02:00
elicitation [Client] Speak the 2026-07-28 lifecycle (#456) 2026-08-19 02:41:02 +02:00
env-variables Update codestyle based on updated Symfony rules (#229) 2026-02-01 11:54:31 +01:00
explicit-registration Move examples to server directory (#198) 2025-12-27 15:39:05 +01:00
mcp-apps [Examples][Tests] Make the MCP Apps example work over HTTP, and pin it (#439) 2026-08-18 14:51:34 +02:00
oauth-keycloak [Server] Compose StreamableHttpTransport security middleware via defaultMiddleware() factory (#307) 2026-05-25 13:49:43 +02:00
oauth-microsoft [Server] Compose StreamableHttpTransport security middleware via defaultMiddleware() factory (#307) 2026-05-25 13:49:43 +02:00
schema-showcase Update codestyle based on updated Symfony rules (#229) 2026-02-01 11:54:31 +01:00
stateless-lifecycle [Docs][Examples][CI] Document and gate the 2026-07-28 lifecycle (#457) 2026-08-19 03:24:17 +02:00
bootstrap.php [Server] Serve both protocol eras from one endpoint (#455) 2026-08-19 01:36:56 +02:00
README.md [Docs][Examples][CI] Document and gate the 2026-07-28 lifecycle (#457) 2026-08-19 03:24:17 +02:00

MCP SDK Examples

This directory contains various examples of how to use the PHP MCP SDK.

You can run the examples with the dependencies already installed in the root directory of the SDK. The bootstrapping of the example will choose the used transport based on the SAPI you use.

For running an example, you execute the server.php like this:

# For using the STDIO transport:
php examples/server/discovery-calculator/server.php

# For using the Streamable HTTP transport:
php -S localhost:8000 examples/server/discovery-userprofile/server.php

You will see debug outputs to help you understand what is happening.

Run with Inspector:

npx @modelcontextprotocol/inspector php examples/server/discovery-calculator/server.php

The 2026-07-28 lifecycle

stateless-lifecycle/server.php speaks protocol revision 2026-07-28, which removed the initialize handshake and protocol-level sessions. It is HTTP-only and cannot be driven by the Inspector, which opens with initialize:

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

Every request carries its own protocol version and client capabilities, so a call is a single POST with no handshake before it:

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":{}}}}'

tests/Integration/StatelessLifecycleTest.php drives this example end to end — discovery, a tool call, the multi round-trip flow, and the response stream carrying progress and log notifications.

Debugging

You can enable debug output by setting the DEBUG environment variable to 1, and additionally log to a file by setting the FILE_LOG environment variable to 1 as well. A dev.log file gets written within the example's directory.

With the Inspector you can set the environment variables like this:

npx @modelcontextprotocol/inspector -e DEBUG=1 -e FILE_LOG=1 php examples/server/discovery-calculator/server.php