From 0751a836587a7b1f6e18aaaa8027a01fdc61c40e Mon Sep 17 00:00:00 2001 From: Christopher Hertel Date: Tue, 18 Aug 2026 14:51:34 +0200 Subject: [PATCH] [Examples][Tests] Make the MCP Apps example work over HTTP, and pin it (#439) * [Examples][Tests] Make the MCP Apps example work over HTTP, and pin it It was the only example without a session store, so every request under `php -S` or php-fpm - each its own process - was answered "Session not found or has expired". It now uses a FileSessionStore like the others. Inspector snapshots pin what the extension actually puts on the wire: the ui:// resource's `text/html;profile=mcp-app` MIME type and `ui` marker, and the `_meta.ui` on the tool that links the two. * Apply suggestion from @chr-hertel * Apply suggestion from @chr-hertel --- examples/server/mcp-apps/server.php | 2 + tests/Inspector/Http/HttpMcpAppsTest.php | 50 +++++++++++++++++++ .../HttpMcpAppsTest-prompts_list.json | 3 ++ .../HttpMcpAppsTest-resources_list.json | 13 +++++ ...cpAppsTest-resources_read-weather_app.json | 22 ++++++++ ...pMcpAppsTest-resources_templates_list.json | 3 ++ ...ttpMcpAppsTest-tools_call-get_weather.json | 9 ++++ .../snapshots/HttpMcpAppsTest-tools_list.json | 28 +++++++++++ 8 files changed, 130 insertions(+) create mode 100644 tests/Inspector/Http/HttpMcpAppsTest.php create mode 100644 tests/Inspector/Http/snapshots/HttpMcpAppsTest-prompts_list.json create mode 100644 tests/Inspector/Http/snapshots/HttpMcpAppsTest-resources_list.json create mode 100644 tests/Inspector/Http/snapshots/HttpMcpAppsTest-resources_read-weather_app.json create mode 100644 tests/Inspector/Http/snapshots/HttpMcpAppsTest-resources_templates_list.json create mode 100644 tests/Inspector/Http/snapshots/HttpMcpAppsTest-tools_call-get_weather.json create mode 100644 tests/Inspector/Http/snapshots/HttpMcpAppsTest-tools_list.json diff --git a/examples/server/mcp-apps/server.php b/examples/server/mcp-apps/server.php index d8ca259..d61c15a 100644 --- a/examples/server/mcp-apps/server.php +++ b/examples/server/mcp-apps/server.php @@ -18,12 +18,14 @@ use Mcp\Schema\Extension\Apps\McpApps; use Mcp\Schema\Extension\Apps\ToolVisibility; use Mcp\Schema\Extension\Apps\UiToolMeta; use Mcp\Server; +use Mcp\Server\Session\FileSessionStore; logger()->info('Starting MCP Apps Example Server...'); $server = Server::builder() ->setServerInfo('MCP Apps Weather Example', '1.0.0') ->setLogger(logger()) + ->setSession(new FileSessionStore(__DIR__.'/sessions')) ->enableExtension(new McpApps()) ->addResource( [WeatherApp::class, 'getWeatherApp'], diff --git a/tests/Inspector/Http/HttpMcpAppsTest.php b/tests/Inspector/Http/HttpMcpAppsTest.php new file mode 100644 index 0000000..76866f6 --- /dev/null +++ b/tests/Inspector/Http/HttpMcpAppsTest.php @@ -0,0 +1,50 @@ + [ + 'method' => 'resources/read', + 'options' => ['uri' => 'ui://weather-app'], + 'testName' => 'weather_app', + ], + 'Call the linked tool' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'get_weather', + 'toolArgs' => ['city' => 'london'], + ], + 'testName' => 'get_weather', + ], + ]; + } + + protected function getServerScript(): string + { + return \dirname(__DIR__, 3).'/examples/server/mcp-apps/server.php'; + } +} diff --git a/tests/Inspector/Http/snapshots/HttpMcpAppsTest-prompts_list.json b/tests/Inspector/Http/snapshots/HttpMcpAppsTest-prompts_list.json new file mode 100644 index 0000000..7292222 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpMcpAppsTest-prompts_list.json @@ -0,0 +1,3 @@ +{ + "prompts": [] +} diff --git a/tests/Inspector/Http/snapshots/HttpMcpAppsTest-resources_list.json b/tests/Inspector/Http/snapshots/HttpMcpAppsTest-resources_list.json new file mode 100644 index 0000000..2ff24ba --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpMcpAppsTest-resources_list.json @@ -0,0 +1,13 @@ +{ + "resources": [ + { + "name": "weather-app", + "uri": "ui://weather-app", + "description": "Interactive weather dashboard", + "mimeType": "text/html;profile=mcp-app", + "_meta": { + "ui": {} + } + } + ] +} diff --git a/tests/Inspector/Http/snapshots/HttpMcpAppsTest-resources_read-weather_app.json b/tests/Inspector/Http/snapshots/HttpMcpAppsTest-resources_read-weather_app.json new file mode 100644 index 0000000..84e1751 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpMcpAppsTest-resources_read-weather_app.json @@ -0,0 +1,22 @@ +{ + "contents": [ + { + "uri": "ui://weather-app", + "mimeType": "text/html;profile=mcp-app", + "_meta": { + "ui": { + "csp": { + "connectDomains": [ + "https://api.weather.example.com" + ] + }, + "permissions": { + "geolocation": {} + }, + "prefersBorder": true + } + }, + "text": "\n\n\n \n \n Weather Dashboard\n \n\n\n
\n \n \n
\n
\n
\n
\n
—
\n
—
\n
\n
🌤️
\n
\n
—
\n
\n Humidity —\n
\n
\n
\n \n\n\n" + } + ] +} diff --git a/tests/Inspector/Http/snapshots/HttpMcpAppsTest-resources_templates_list.json b/tests/Inspector/Http/snapshots/HttpMcpAppsTest-resources_templates_list.json new file mode 100644 index 0000000..e867d9d --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpMcpAppsTest-resources_templates_list.json @@ -0,0 +1,3 @@ +{ + "resourceTemplates": [] +} diff --git a/tests/Inspector/Http/snapshots/HttpMcpAppsTest-tools_call-get_weather.json b/tests/Inspector/Http/snapshots/HttpMcpAppsTest-tools_call-get_weather.json new file mode 100644 index 0000000..8d42069 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpMcpAppsTest-tools_call-get_weather.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "Weather in london: 15°C, Cloudy, Humidity: 78%" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpMcpAppsTest-tools_list.json b/tests/Inspector/Http/snapshots/HttpMcpAppsTest-tools_list.json new file mode 100644 index 0000000..dcb064a --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpMcpAppsTest-tools_list.json @@ -0,0 +1,28 @@ +{ + "tools": [ + { + "name": "get_weather", + "description": "Get current weather for a city", + "inputSchema": { + "type": "object", + "properties": { + "city": { + "type": "string" + } + }, + "required": [ + "city" + ] + }, + "_meta": { + "ui": { + "resourceUri": "ui://weather-app", + "visibility": [ + "model", + "app" + ] + } + } + } + ] +}