diff --git a/tests/Inspector/Http/HttpClientCommunicationTest.php b/tests/Inspector/Http/HttpClientCommunicationTest.php new file mode 100644 index 00000000..0b396e2e --- /dev/null +++ b/tests/Inspector/Http/HttpClientCommunicationTest.php @@ -0,0 +1,64 @@ +markTestSkipped('Test skipped: SDK cannot handle logging/setLevel requests required by logging capability, and built-in PHP server does not support sampling.'); + } + + public static function provideMethods(): array + { + return [ + ...parent::provideMethods(), + 'Prepare Project Briefing (Simple)' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'prepare_project_briefing', + 'toolArgs' => [ + 'projectName' => 'Website Redesign', + 'milestones' => ['Discovery', 'Design', 'Development', 'Testing'], + ], + ], + 'testName' => 'prepare_project_briefing_simple', + ], + 'Prepare Project Briefing (Complex)' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'prepare_project_briefing', + 'toolArgs' => [ + 'projectName' => 'Mobile App Launch', + 'milestones' => ['Market Research', 'UI/UX Design', 'MVP Development', 'Beta Testing', 'Marketing Campaign', 'Public Launch'], + ], + ], + 'testName' => 'prepare_project_briefing_complex', + ], + 'Run Service Maintenance' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'run_service_maintenance', + 'toolArgs' => [ + 'serviceName' => 'Payment Gateway API', + ], + ], + 'testName' => 'run_service_maintenance', + ], + ]; + } + + protected function getServerScript(): string + { + return \dirname(__DIR__, 3).'/examples/http-client-communication/server.php'; + } +} diff --git a/tests/Inspector/Http/HttpCombinedRegistrationTest.php b/tests/Inspector/Http/HttpCombinedRegistrationTest.php new file mode 100644 index 00000000..932c200b --- /dev/null +++ b/tests/Inspector/Http/HttpCombinedRegistrationTest.php @@ -0,0 +1,50 @@ + [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'manualGreeter', + 'toolArgs' => ['user' => 'HTTP Test User'], + ], + 'testName' => 'manual_greeter', + ], + 'Discovered Status Check Tool' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'discovered_status_check', + 'toolArgs' => [], + ], + 'testName' => 'discovered_status_check', + ], + 'Read Priority Config (Manual Override)' => [ + 'method' => 'resources/read', + 'options' => [ + 'uri' => 'config://priority', + ], + 'testName' => 'config_priority', + ], + ]; + } + + protected function getServerScript(): string + { + return \dirname(__DIR__, 3).'/examples/http-combined-registration/server.php'; + } +} diff --git a/tests/Inspector/Http/HttpComplexToolSchemaTest.php b/tests/Inspector/Http/HttpComplexToolSchemaTest.php new file mode 100644 index 00000000..93f3ca30 --- /dev/null +++ b/tests/Inspector/Http/HttpComplexToolSchemaTest.php @@ -0,0 +1,87 @@ + [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'schedule_event', + 'toolArgs' => [ + 'title' => 'Team Standup', + 'date' => '2024-12-01', + 'type' => 'meeting', + 'time' => '09:00', + 'priority' => 'normal', + 'attendees' => ['alice@example.com', 'bob@example.com'], + 'sendInvites' => true, + ], + ], + 'testName' => 'schedule_event_meeting_with_time', + ], + 'Schedule Event (All Day Reminder)' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'schedule_event', + 'toolArgs' => [ + 'title' => 'Project Deadline', + 'date' => '2024-12-15', + 'type' => 'reminder', + 'priority' => 'high', + ], + ], + 'testName' => 'schedule_event_all_day_reminder', + ], + 'Schedule Event (Call with High Priority)' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'schedule_event', + 'toolArgs' => [ + 'title' => 'Client Call', + 'date' => '2024-12-02', + 'type' => 'call', + 'time' => '14:30', + 'priority' => 'high', + 'attendees' => ['client@example.com'], + 'sendInvites' => false, + ], + ], + 'testName' => 'schedule_event_high_priority', + ], + 'Schedule Event (Other Event with Low Priority)' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'schedule_event', + 'toolArgs' => [ + 'title' => 'Office Party', + 'date' => '2024-12-20', + 'type' => 'other', + 'time' => '18:00', + 'priority' => 'low', + 'attendees' => ['team@company.com'], + ], + ], + 'testName' => 'schedule_event_low_priority', + ], + ]; + } + + protected function getServerScript(): string + { + return \dirname(__DIR__, 3).'/examples/http-complex-tool-schema/server.php'; + } +} diff --git a/tests/Inspector/Http/HttpDiscoveryUserProfileTest.php b/tests/Inspector/Http/HttpDiscoveryUserProfileTest.php new file mode 100644 index 00000000..abffbacd --- /dev/null +++ b/tests/Inspector/Http/HttpDiscoveryUserProfileTest.php @@ -0,0 +1,72 @@ + [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'send_welcome', + 'toolArgs' => ['userId' => '101', 'customMessage' => 'Welcome to our platform!'], + ], + 'testName' => 'send_welcome', + ], + 'Test Tool Without Params' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'test_tool_without_params', + 'toolArgs' => [], + ], + 'testName' => 'test_tool_without_params', + ], + 'Read User Profile 101' => [ + 'method' => 'resources/read', + 'options' => [ + 'uri' => 'user://101/profile', + ], + 'testName' => 'read_user_profile_101', + ], + 'Read User Profile 102' => [ + 'method' => 'resources/read', + 'options' => [ + 'uri' => 'user://102/profile', + ], + 'testName' => 'read_user_profile_102', + ], + 'Read User ID List' => [ + 'method' => 'resources/read', + 'options' => [ + 'uri' => 'user://list/ids', + ], + 'testName' => 'read_user_id_list', + ], + 'Generate Bio Prompt (Formal)' => [ + 'method' => 'prompts/get', + 'options' => [ + 'promptName' => 'generate_bio_prompt', + 'promptArgs' => ['userId' => '101', 'tone' => 'formal'], + ], + 'testName' => 'generate_bio_prompt', + ], + ]; + } + + protected function getServerScript(): string + { + return \dirname(__DIR__, 3).'/examples/http-discovery-userprofile/server.php'; + } +} diff --git a/tests/Inspector/Http/HttpInspectorSnapshotTestCase.php b/tests/Inspector/Http/HttpInspectorSnapshotTestCase.php new file mode 100644 index 00000000..41f224a9 --- /dev/null +++ b/tests/Inspector/Http/HttpInspectorSnapshotTestCase.php @@ -0,0 +1,102 @@ +startServer(); + } + + protected function tearDown(): void + { + $this->stopServer(); + parent::tearDown(); + } + + abstract protected function getServerScript(): string; + + protected function getServerConnectionArgs(): array + { + return [\sprintf('http://127.0.0.1:%d', $this->serverPort)]; + } + + protected function getTransport(): string + { + return 'http'; + } + + private function startServer(): void + { + $this->serverPort = 8000 + (getmypid() % 1000); + + $this->serverProcess = new Process([ + 'php', + '-S', + \sprintf('127.0.0.1:%d', $this->serverPort), + $this->getServerScript(), + ]); + + $this->serverProcess->start(); + + $timeout = 5; // seconds + $startTime = time(); + + while (time() - $startTime < $timeout) { + if ($this->serverProcess->isRunning() && $this->isServerReady()) { + return; + } + usleep(100000); // 100ms + } + + $this->fail(\sprintf('Server failed to start on port %d within %d seconds', $this->serverPort, $timeout)); + } + + private function stopServer(): void + { + if (isset($this->serverProcess)) { + $this->serverProcess->stop(1, \SIGTERM); + } + } + + private function isServerReady(): bool + { + $context = stream_context_create([ + 'http' => [ + 'timeout' => 1, + 'method' => 'GET', + ], + ]); + + // Try a simple health check - this will likely fail with MCP but should respond + $response = @file_get_contents(\sprintf('http://127.0.0.1:%d', $this->serverPort), false, $context); + + // We don't care about the response content, just that the server is accepting connections + return false !== $response || false === str_contains(error_get_last()['message'] ?? '', 'Connection refused'); + } + + protected function getSnapshotFilePath(string $method, ?string $testName = null): string + { + $className = substr(static::class, strrpos(static::class, '\\') + 1); + $suffix = $testName ? '-'.preg_replace('/[^a-zA-Z0-9_]/', '_', $testName) : ''; + + return __DIR__.'/snapshots/'.$className.'-'.str_replace('/', '_', $method).$suffix.'.json'; + } +} diff --git a/tests/Inspector/Http/HttpSchemaShowcaseTest.php b/tests/Inspector/Http/HttpSchemaShowcaseTest.php new file mode 100644 index 00000000..e4b137da --- /dev/null +++ b/tests/Inspector/Http/HttpSchemaShowcaseTest.php @@ -0,0 +1,116 @@ + [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'format_text', + 'toolArgs' => ['text' => 'Hello World Test', 'format' => 'uppercase'], + ], + 'testName' => 'format_text', + ], + 'Calculate Range Tool' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'calculate_range', + 'toolArgs' => ['first' => 10, 'second' => 5, 'operation' => 'multiply', 'precision' => 2], + ], + 'testName' => 'calculate_range', + ], + 'Validate Profile Tool' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'validate_profile', + 'toolArgs' => [ + 'profile' => ['name' => 'John Doe', 'email' => 'john@example.com', 'age' => 30, 'role' => 'user'], + ], + ], + 'testName' => 'validate_profile', + ], + 'Manage List Tool' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'manage_list', + 'toolArgs' => [ + 'items' => ['apple', 'banana', 'cherry', 'date'], + 'action' => 'sort', + ], + ], + 'testName' => 'manage_list', + ], + 'Generate Config Tool' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'generate_config', + 'toolArgs' => [ + 'appName' => 'TestApp', + 'baseUrl' => 'https://example.com', + 'environment' => 'development', + 'debug' => true, + 'port' => 8080, + ], + ], + 'testName' => 'generate_config', + ], + 'Schedule Event Tool' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'schedule_event', + 'toolArgs' => [ + 'title' => 'Team Meeting', + 'startTime' => '2024-12-01T14:30:00Z', + 'durationHours' => 1.5, + 'priority' => 'high', + 'attendees' => ['alice@example.com', 'bob@example.com'], + ], + ], + 'testName' => 'schedule_event', + ], + ]; + } + + protected function getServerScript(): string + { + return \dirname(__DIR__, 3).'/examples/http-schema-showcase/server.php'; + } + + protected function normalizeTestOutput(string $output, ?string $testName = null): string + { + return match ($testName) { + 'validate_profile' => preg_replace( + '/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', + '2025-01-01 00:00:00', + $output + ), + 'generate_config' => preg_replace( + '/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}/', + '2025-01-01T00:00:00+00:00', + $output + ), + 'schedule_event' => preg_replace([ + '/event_[a-f0-9]{13,}/', + '/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}/', + ], [ + 'event_test123456789', + '2025-01-01T00:00:00+00:00', + ], $output), + default => $output, + }; + } +} diff --git a/tests/Inspector/snapshots/StdioCachedDiscoveryTest-prompts_list.json b/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-prompts_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioCachedDiscoveryTest-prompts_list.json rename to tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-prompts_list.json diff --git a/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-resources_list.json b/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-resources_list.json new file mode 100644 index 00000000..2d0c6ce2 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-resources_list.json @@ -0,0 +1,9 @@ +{ + "resources": [ + { + "name": "priority_config_discovered", + "uri": "config://priority", + "description": "A resource discovered via attributes." + } + ] +} diff --git a/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-resources_read-config_priority.json b/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-resources_read-config_priority.json new file mode 100644 index 00000000..053dcceb --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-resources_read-config_priority.json @@ -0,0 +1,9 @@ +{ + "contents": [ + { + "uri": "config://priority", + "mimeType": "text/plain", + "text": "Discovered Priority Config: Low" + } + ] +} diff --git a/tests/Inspector/snapshots/StdioCachedDiscoveryTest-resources_templates_list.json b/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-resources_templates_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioCachedDiscoveryTest-resources_templates_list.json rename to tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-resources_templates_list.json diff --git a/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-tools_call-discovered_status_check.json b/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-tools_call-discovered_status_check.json new file mode 100644 index 00000000..d849f400 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-tools_call-discovered_status_check.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "System status: OK (discovered)" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-tools_call-manual_greeter.json b/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-tools_call-manual_greeter.json new file mode 100644 index 00000000..4d8cf0da --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-tools_call-manual_greeter.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "Hello HTTP Test User, from manual registration!" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-tools_list.json b/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-tools_list.json new file mode 100644 index 00000000..04d8ea1c --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpCombinedRegistrationTest-tools_list.json @@ -0,0 +1,28 @@ +{ + "tools": [ + { + "name": "manualGreeter", + "description": "A manually registered tool.", + "inputSchema": { + "type": "object", + "properties": { + "user": { + "type": "string", + "description": "the user to greet" + } + }, + "required": [ + "user" + ] + } + }, + { + "name": "discovered_status_check", + "description": "A tool discovered via attributes.", + "inputSchema": { + "type": "object", + "properties": {} + } + } + ] +} diff --git a/tests/Inspector/snapshots/StdioCustomDependenciesTest-prompts_list.json b/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-prompts_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioCustomDependenciesTest-prompts_list.json rename to tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-prompts_list.json diff --git a/tests/Inspector/snapshots/StdioCachedDiscoveryTest-resources_list.json b/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-resources_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioCachedDiscoveryTest-resources_list.json rename to tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-resources_list.json diff --git a/tests/Inspector/snapshots/StdioCustomDependenciesTest-resources_templates_list.json b/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-resources_templates_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioCustomDependenciesTest-resources_templates_list.json rename to tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-resources_templates_list.json diff --git a/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_call-schedule_event_all_day_reminder.json b/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_call-schedule_event_all_day_reminder.json new file mode 100644 index 00000000..1e7667fa --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_call-schedule_event_all_day_reminder.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"success\": true,\n \"message\": \"Event \\\"Project Deadline\\\" scheduled successfully for \\\"2024-12-15\\\".\",\n \"event_details\": {\n \"title\": \"Project Deadline\",\n \"date\": \"2024-12-15\",\n \"type\": \"reminder\",\n \"time\": \"All day\",\n \"priority\": \"Normal\",\n \"attendees\": [],\n \"invites_will_be_sent\": false\n }\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_call-schedule_event_high_priority.json b/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_call-schedule_event_high_priority.json new file mode 100644 index 00000000..5309d2e9 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_call-schedule_event_high_priority.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"success\": true,\n \"message\": \"Event \\\"Client Call\\\" scheduled successfully for \\\"2024-12-02\\\".\",\n \"event_details\": {\n \"title\": \"Client Call\",\n \"date\": \"2024-12-02\",\n \"type\": \"call\",\n \"time\": \"14:30\",\n \"priority\": \"Normal\",\n \"attendees\": [\n \"client@example.com\"\n ],\n \"invites_will_be_sent\": false\n }\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_call-schedule_event_low_priority.json b/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_call-schedule_event_low_priority.json new file mode 100644 index 00000000..a9f4d35f --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_call-schedule_event_low_priority.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"success\": true,\n \"message\": \"Event \\\"Office Party\\\" scheduled successfully for \\\"2024-12-20\\\".\",\n \"event_details\": {\n \"title\": \"Office Party\",\n \"date\": \"2024-12-20\",\n \"type\": \"other\",\n \"time\": \"18:00\",\n \"priority\": \"Normal\",\n \"attendees\": [\n \"team@company.com\"\n ],\n \"invites_will_be_sent\": true\n }\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_call-schedule_event_meeting_with_time.json b/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_call-schedule_event_meeting_with_time.json new file mode 100644 index 00000000..68c6f014 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_call-schedule_event_meeting_with_time.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"success\": true,\n \"message\": \"Event \\\"Team Standup\\\" scheduled successfully for \\\"2024-12-01\\\".\",\n \"event_details\": {\n \"title\": \"Team Standup\",\n \"date\": \"2024-12-01\",\n \"type\": \"meeting\",\n \"time\": \"09:00\",\n \"priority\": \"Normal\",\n \"attendees\": [\n \"alice@example.com\",\n \"bob@example.com\"\n ],\n \"invites_will_be_sent\": true\n }\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_list.json b/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_list.json new file mode 100644 index 00000000..5f47adca --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpComplexToolSchemaTest-tools_list.json @@ -0,0 +1,67 @@ +{ + "tools": [ + { + "name": "schedule_event", + "description": "Schedules a new event.", + "inputSchema": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "the title of the event" + }, + "date": { + "type": "string", + "description": "the date of the event (YYYY-MM-DD)" + }, + "type": { + "type": "string", + "description": "the type of event", + "enum": [ + "meeting", + "reminder", + "call", + "other" + ] + }, + "time": { + "type": [ + "null", + "string" + ], + "description": "the time of the event (HH:MM), optional", + "default": null + }, + "priority": { + "type": "integer", + "description": "The priority of the event. Defaults to Normal.", + "default": 1, + "enum": [ + 0, + 1, + 2 + ] + }, + "attendees": { + "type": [ + "array", + "null" + ], + "description": "an optional list of attendee email addresses", + "default": null + }, + "sendInvites": { + "type": "boolean", + "description": "send calendar invites to attendees? Defaults to true if attendees are provided", + "default": true + } + }, + "required": [ + "title", + "date", + "type" + ] + } + } + ] +} diff --git a/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-prompts_get-generate_bio_prompt.json b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-prompts_get-generate_bio_prompt.json new file mode 100644 index 00000000..74dff36e --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-prompts_get-generate_bio_prompt.json @@ -0,0 +1,11 @@ +{ + "messages": [ + { + "role": "user", + "content": { + "type": "text", + "text": "Write a short, formal biography for Alice (Role: admin, Email: alice@example.com). Highlight their role within the system." + } + } + ] +} diff --git a/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-prompts_list.json b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-prompts_list.json new file mode 100644 index 00000000..3b140f83 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-prompts_list.json @@ -0,0 +1,20 @@ +{ + "prompts": [ + { + "name": "generate_bio_prompt", + "description": "Generates a prompt to write a bio for a user.", + "arguments": [ + { + "name": "userId", + "description": "the user ID to generate the bio for", + "required": true + }, + { + "name": "tone", + "description": "Desired tone (e.g., 'formal', 'casual').", + "required": false + } + ] + } + ] +} diff --git a/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_list.json b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_list.json new file mode 100644 index 00000000..a9d91a86 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_list.json @@ -0,0 +1,16 @@ +{ + "resources": [ + { + "name": "system_status", + "uri": "system://status", + "description": "Current system status and runtime information", + "mimeType": "application/json" + }, + { + "name": "user_id_list", + "uri": "user://list/ids", + "description": "Provides a list of all available user IDs.", + "mimeType": "application/json" + } + ] +} diff --git a/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_read-read_user_id_list.json b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_read-read_user_id_list.json new file mode 100644 index 00000000..04c7ae82 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_read-read_user_id_list.json @@ -0,0 +1,9 @@ +{ + "contents": [ + { + "uri": "user://list/ids", + "mimeType": "application/json", + "text": "[\n 101,\n 102,\n 103\n]" + } + ] +} diff --git a/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_read-read_user_profile_101.json b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_read-read_user_profile_101.json new file mode 100644 index 00000000..39931e8c --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_read-read_user_profile_101.json @@ -0,0 +1,9 @@ +{ + "contents": [ + { + "uri": "user://101/profile", + "mimeType": "application/json", + "text": "{\n \"name\": \"Alice\",\n \"email\": \"alice@example.com\",\n \"role\": \"admin\"\n}" + } + ] +} diff --git a/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_read-read_user_profile_102.json b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_read-read_user_profile_102.json new file mode 100644 index 00000000..c3e1dcf8 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_read-read_user_profile_102.json @@ -0,0 +1,9 @@ +{ + "contents": [ + { + "uri": "user://102/profile", + "mimeType": "application/json", + "text": "{\n \"name\": \"Bob\",\n \"email\": \"bob@example.com\",\n \"role\": \"user\"\n}" + } + ] +} diff --git a/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_templates_list.json b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_templates_list.json new file mode 100644 index 00000000..c92be4ad --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-resources_templates_list.json @@ -0,0 +1,10 @@ +{ + "resourceTemplates": [ + { + "name": "user_profile", + "uriTemplate": "user://{userId}/profile", + "description": "Get profile information for a specific user ID.", + "mimeType": "application/json" + } + ] +} diff --git a/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-tools_call-send_welcome.json b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-tools_call-send_welcome.json new file mode 100644 index 00000000..95ed1898 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-tools_call-send_welcome.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"success\": true,\n \"message_sent\": \"Welcome, Alice! Welcome to our platform!\"\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-tools_call-test_tool_without_params.json b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-tools_call-test_tool_without_params.json new file mode 100644 index 00000000..cac9850a --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-tools_call-test_tool_without_params.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"success\": true,\n \"message\": \"Test tool without params\"\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-tools_list.json b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-tools_list.json new file mode 100644 index 00000000..f515430e --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpDiscoveryUserProfileTest-tools_list.json @@ -0,0 +1,58 @@ +{ + "tools": [ + { + "name": "calculator", + "description": "Perform basic math operations (add, subtract, multiply, divide)", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "number" + }, + "b": { + "type": "number" + }, + "operation": { + "type": "string", + "default": "add" + } + }, + "required": [ + "a", + "b" + ] + } + }, + { + "name": "send_welcome", + "description": "Sends a welcome message to a user.", + "inputSchema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "the ID of the user to message" + }, + "customMessage": { + "type": [ + "null", + "string" + ], + "description": "an optional custom message part", + "default": null + } + }, + "required": [ + "userId" + ] + } + }, + { + "name": "test_tool_without_params", + "inputSchema": { + "type": "object", + "properties": {} + } + } + ] +} diff --git a/tests/Inspector/snapshots/StdioDiscoveryCalculatorTest-prompts_list.json b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-prompts_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioDiscoveryCalculatorTest-prompts_list.json rename to tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-prompts_list.json diff --git a/tests/Inspector/snapshots/StdioEnvVariablesTest-resources_list.json b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-resources_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioEnvVariablesTest-resources_list.json rename to tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-resources_list.json diff --git a/tests/Inspector/snapshots/StdioDiscoveryCalculatorTest-resources_templates_list.json b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-resources_templates_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioDiscoveryCalculatorTest-resources_templates_list.json rename to tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-resources_templates_list.json diff --git a/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-calculate_range.json b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-calculate_range.json new file mode 100644 index 00000000..817d33d9 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-calculate_range.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"result\": 50,\n \"operation\": \"10 multiply 5\",\n \"precision\": 2,\n \"within_bounds\": true\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-format_text.json b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-format_text.json new file mode 100644 index 00000000..eb9d89de --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-format_text.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"original\": \"Hello World Test\",\n \"formatted\": \"HELLO WORLD TEST\",\n \"length\": 16,\n \"format_applied\": \"uppercase\"\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-generate_config.json b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-generate_config.json new file mode 100644 index 00000000..e193e9fb --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-generate_config.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"success\": true,\n \"config\": {\n \"app\": {\n \"name\": \"TestApp\",\n \"env\": \"development\",\n \"debug\": true,\n \"url\": \"https://example.com\",\n \"port\": 8080\n },\n \"generated_at\": \"2025-01-01T00:00:00+00:00\",\n \"version\": \"1.0.0\",\n \"features\": {\n \"logging\": true,\n \"caching\": false,\n \"analytics\": false,\n \"rate_limiting\": false\n }\n },\n \"validation\": {\n \"app_name_valid\": true,\n \"url_valid\": true,\n \"port_in_range\": true\n }\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-manage_list.json b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-manage_list.json new file mode 100644 index 00000000..25623f28 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-manage_list.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"original_count\": 4,\n \"processed_count\": 4,\n \"action\": \"sort\",\n \"original\": [\n \"apple\",\n \"banana\",\n \"cherry\",\n \"date\"\n ],\n \"processed\": [\n \"apple\",\n \"banana\",\n \"cherry\",\n \"date\"\n ],\n \"stats\": {\n \"average_length\": 5.25,\n \"shortest\": 4,\n \"longest\": 6\n }\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-schedule_event.json b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-schedule_event.json new file mode 100644 index 00000000..924527dc --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-schedule_event.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"success\": true,\n \"event\": {\n \"id\": \"event_test123456789\",\n \"title\": \"Team Meeting\",\n \"start_time\": \"2025-01-01T00:00:00+00:00\",\n \"end_time\": \"2025-01-01T00:00:00+00:00\",\n \"duration_hours\": 1.5,\n \"priority\": \"high\",\n \"attendees\": [\n \"alice@example.com\",\n \"bob@example.com\"\n ],\n \"created_at\": \"2025-01-01T00:00:00+00:00\"\n },\n \"info\": {\n \"attendee_count\": 2,\n \"is_all_day\": false,\n \"is_future\": false,\n \"timezone_note\": \"Times are in UTC\"\n }\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-validate_profile.json b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-validate_profile.json new file mode 100644 index 00000000..9fe2fa53 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_call-validate_profile.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"valid\": true,\n \"profile\": {\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\",\n \"age\": 30,\n \"role\": \"user\"\n },\n \"errors\": [],\n \"warnings\": [],\n \"processed_at\": \"2025-01-01 00:00:00\"\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_list.json b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_list.json new file mode 100644 index 00000000..9b9b90e7 --- /dev/null +++ b/tests/Inspector/Http/snapshots/HttpSchemaShowcaseTest-tools_list.json @@ -0,0 +1,284 @@ +{ + "tools": [ + { + "name": "format_text", + "description": "Formats text with validation constraints. Text must be 5-100 characters and contain only letters, numbers, spaces, and basic punctuation.", + "inputSchema": { + "type": "object", + "properties": { + "text": { + "type": "string", + "description": "The text to format", + "minLength": 5, + "maxLength": 100, + "pattern": "^[a-zA-Z0-9\\s\\.,!?\\-]+$" + }, + "format": { + "type": "string", + "default": "sentence", + "description": "Format style", + "enum": [ + "uppercase", + "lowercase", + "title", + "sentence" + ] + } + }, + "required": [ + "text" + ] + } + }, + { + "name": "calculate_range", + "description": "Performs mathematical operations with numeric constraints.", + "inputSchema": { + "type": "object", + "properties": { + "first": { + "type": "number", + "description": "First number (must be between 0 and 1000)", + "minimum": 0, + "maximum": 1000 + }, + "second": { + "type": "number", + "description": "Second number (must be between 0 and 1000)", + "minimum": 0, + "maximum": 1000 + }, + "operation": { + "type": "string", + "description": "Operation to perform", + "enum": [ + "add", + "subtract", + "multiply", + "divide", + "power" + ] + }, + "precision": { + "type": "integer", + "default": 2, + "description": "Decimal precision (must be multiple of 2, between 0-10)", + "minimum": 0, + "maximum": 10, + "multipleOf": 2 + } + }, + "required": [ + "first", + "second", + "operation" + ] + } + }, + { + "name": "validate_profile", + "description": "Validates and processes user profile data with strict schema requirements.", + "inputSchema": { + "type": "object", + "properties": { + "profile": { + "type": "object", + "description": "User profile information", + "properties": { + "name": { + "type": "string", + "minLength": 2, + "maxLength": 50, + "description": "Full name" + }, + "email": { + "type": "string", + "format": "email", + "description": "Valid email address" + }, + "age": { + "type": "integer", + "minimum": 13, + "maximum": 120, + "description": "Age in years" + }, + "role": { + "type": "string", + "enum": [ + "user", + "admin", + "moderator", + "guest" + ], + "description": "User role" + }, + "preferences": { + "type": "object", + "properties": { + "notifications": { + "type": "boolean" + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark", + "auto" + ] + } + }, + "additionalProperties": false + } + }, + "required": [ + "name", + "email", + "age" + ], + "additionalProperties": true + } + }, + "required": [ + "profile" + ] + } + }, + { + "name": "manage_list", + "description": "Manages a list of items with size and uniqueness constraints.", + "inputSchema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "string", + "minLength": 1, + "maxLength": 30 + }, + "description": "List of items to manage (2-10 unique strings)", + "minItems": 2, + "maxItems": 10, + "uniqueItems": true + }, + "action": { + "type": "string", + "default": "sort", + "description": "Action to perform on the list", + "enum": [ + "sort", + "reverse", + "shuffle", + "deduplicate", + "filter_short", + "filter_long" + ] + } + }, + "required": [ + "items" + ] + } + }, + { + "name": "generate_config", + "description": "Generates configuration with format-validated inputs.", + "inputSchema": { + "type": "object", + "properties": { + "appName": { + "type": "string", + "description": "Application name (alphanumeric with hyphens)", + "minLength": 3, + "maxLength": 20, + "pattern": "^[a-zA-Z0-9\\-]+$" + }, + "baseUrl": { + "type": "string", + "description": "Valid URL for the application", + "format": "uri" + }, + "environment": { + "type": "string", + "default": "development", + "description": "Environment type", + "enum": [ + "development", + "staging", + "production" + ] + }, + "debug": { + "type": "boolean", + "default": true, + "description": "Enable debug mode" + }, + "port": { + "type": "integer", + "default": 8080, + "description": "Port number (1024-65535)", + "minimum": 1024, + "maximum": 65535 + } + }, + "required": [ + "appName", + "baseUrl" + ] + } + }, + { + "name": "schedule_event", + "description": "Schedules an event with time validation and constraints.", + "inputSchema": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "Event title (3-50 characters)", + "minLength": 3, + "maxLength": 50 + }, + "startTime": { + "type": "string", + "description": "Event start time in ISO 8601 format", + "format": "date-time" + }, + "durationHours": { + "type": "number", + "description": "Duration in hours (minimum 0.5, maximum 24)", + "minimum": 0.5, + "maximum": 24, + "multipleOf": 0.5 + }, + "priority": { + "type": "string", + "default": "medium", + "description": "Event priority level", + "enum": [ + "low", + "medium", + "high", + "urgent" + ] + }, + "attendees": { + "type": "array", + "default": [], + "items": { + "type": "string", + "format": "email" + }, + "description": "List of attendee email addresses", + "maxItems": 20 + } + }, + "required": [ + "title", + "startTime", + "durationHours" + ] + } + } + ] +} diff --git a/tests/Inspector/InspectorSnapshotTestCase.php b/tests/Inspector/InspectorSnapshotTestCase.php index 8fe3d96a..c8335308 100644 --- a/tests/Inspector/InspectorSnapshotTestCase.php +++ b/tests/Inspector/InspectorSnapshotTestCase.php @@ -11,6 +11,7 @@ namespace Mcp\Tests\Inspector; +use Mcp\Schema\Enum\LoggingLevel; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Process\Process; @@ -19,67 +20,105 @@ abstract class InspectorSnapshotTestCase extends TestCase { private const INSPECTOR_VERSION = '0.16.8'; - /** - * @param array $toolArgs - */ + /** @param array $options */ #[DataProvider('provideMethods')] - public function testMethodOutputMatchesSnapshot( + public function testOutputMatchesSnapshot( string $method, - ?string $toolName = null, - array $toolArgs = [], - ?string $uri = null, + array $options = [], + ?string $testName = null, ): void { $inspector = \sprintf('@modelcontextprotocol/inspector@%s', self::INSPECTOR_VERSION); + $args = [ - 'npx', $inspector, '--cli', 'php', $this->getServerScript(), '--method', $method, + 'npx', + $inspector, + '--cli', + ...$this->getServerConnectionArgs(), + '--transport', + $this->getTransport(), + '--method', + $method, ]; // Options for tools/call - if (null !== $toolName) { + if (isset($options['toolName'])) { $args[] = '--tool-name'; - $args[] = $toolName; + $args[] = $options['toolName']; - foreach ($toolArgs as $key => $value) { + foreach ($options['toolArgs'] ?? [] as $key => $value) { $args[] = '--tool-arg'; - $args[] = \sprintf('%s=%s', $key, $value); + if (\is_array($value)) { + $args[] = \sprintf('%s=%s', $key, json_encode($value)); + } elseif (\is_bool($value)) { + $args[] = \sprintf('%s=%s', $key, $value ? '1' : '0'); + } else { + $args[] = \sprintf('%s=%s', $key, $value); + } } } // Options for resources/read - if (null !== $uri) { + if (isset($options['uri'])) { $args[] = '--uri'; - $args[] = $uri; + $args[] = $options['uri']; + } + + // Options for prompts/get + if (isset($options['promptName'])) { + $args[] = '--prompt-name'; + $args[] = $options['promptName']; + + foreach ($options['promptArgs'] ?? [] as $key => $value) { + $args[] = '--prompt-args'; + if (\is_array($value)) { + $args[] = \sprintf('%s=%s', $key, json_encode($value)); + } elseif (\is_bool($value)) { + $args[] = \sprintf('%s=%s', $key, $value ? '1' : '0'); + } else { + $args[] = \sprintf('%s=%s', $key, $value); + } + } + } + + // Options for logging/setLevel + if (isset($options['logLevel'])) { + $args[] = '--log-level'; + $args[] = $options['logLevel'] instanceof LoggingLevel ? $options['logLevel']->value : $options['logLevel']; + } + + // Options for env variables + if (isset($options['envVars'])) { + foreach ($options['envVars'] as $key => $value) { + $args[] = '-e'; + $args[] = \sprintf('%s=%s', $key, $value); + } } - $output = (new Process($args)) + $output = (new Process(command: $args)) ->mustRun() ->getOutput(); - $snapshotFile = $this->getSnapshotFilePath($method); + $snapshotFile = $this->getSnapshotFilePath($method, $testName); + + $normalizedOutput = $this->normalizeTestOutput($output, $testName); if (!file_exists($snapshotFile)) { - file_put_contents($snapshotFile, $output.\PHP_EOL); + file_put_contents($snapshotFile, $normalizedOutput.\PHP_EOL); $this->markTestIncomplete("Snapshot created at $snapshotFile, please re-run tests."); } $expected = file_get_contents($snapshotFile); - $this->assertJsonStringEqualsJsonString($expected, $output); + $this->assertJsonStringEqualsJsonString($expected, $normalizedOutput); } - /** - * List of methods to test. - * - * @return array - */ - abstract public static function provideMethods(): array; - - abstract protected function getServerScript(): string; + protected function normalizeTestOutput(string $output, ?string $testName = null): string + { + return $output; + } - /** - * @return array - */ - protected static function provideListMethods(): array + /** @return array> */ + public static function provideMethods(): array { return [ 'Prompt Listing' => ['method' => 'prompts/list'], @@ -89,10 +128,10 @@ protected static function provideListMethods(): array ]; } - private function getSnapshotFilePath(string $method): string - { - $className = substr(static::class, strrpos(static::class, '\\') + 1); + abstract protected function getSnapshotFilePath(string $method, ?string $testName = null): string; - return __DIR__.'/snapshots/'.$className.'-'.str_replace('/', '_', $method).'.json'; - } + /** @return array */ + abstract protected function getServerConnectionArgs(): array; + + abstract protected function getTransport(): string; } diff --git a/tests/Inspector/Stdio/StdioCachedDiscoveryTest.php b/tests/Inspector/Stdio/StdioCachedDiscoveryTest.php new file mode 100644 index 00000000..ede61ed3 --- /dev/null +++ b/tests/Inspector/Stdio/StdioCachedDiscoveryTest.php @@ -0,0 +1,93 @@ + [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'add_numbers', + 'toolArgs' => ['a' => 5, 'b' => 3], + ], + 'testName' => 'add_numbers', + ], + 'Add Numbers (Negative)' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'add_numbers', + 'toolArgs' => ['a' => -10, 'b' => 7], + ], + 'testName' => 'add_numbers_negative', + ], + 'Multiply Numbers Tool' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'multiply_numbers', + 'toolArgs' => ['a' => 4, 'b' => 6], + ], + 'testName' => 'multiply_numbers', + ], + 'Multiply Numbers (Zero)' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'multiply_numbers', + 'toolArgs' => ['a' => 15, 'b' => 0], + ], + 'testName' => 'multiply_numbers_zero', + ], + 'Divide Numbers Tool' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'divide_numbers', + 'toolArgs' => ['a' => 20, 'b' => 4], + ], + 'testName' => 'divide_numbers', + ], + 'Divide Numbers (Decimal Result)' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'divide_numbers', + 'toolArgs' => ['a' => 7, 'b' => 2], + ], + 'testName' => 'divide_numbers_decimal', + ], + 'Power Tool' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'power', + 'toolArgs' => ['base' => 2, 'exponent' => 8], + ], + 'testName' => 'power', + ], + 'Power Tool (Zero Exponent)' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'power', + 'toolArgs' => ['base' => 5, 'exponent' => 0], + ], + 'testName' => 'power_zero_exponent', + ], + ]; + } + + protected function getServerScript(): string + { + return \dirname(__DIR__, 3).'/examples/stdio-cached-discovery/server.php'; + } +} diff --git a/tests/Inspector/Stdio/StdioCustomDependenciesTest.php b/tests/Inspector/Stdio/StdioCustomDependenciesTest.php new file mode 100644 index 00000000..e4285e27 --- /dev/null +++ b/tests/Inspector/Stdio/StdioCustomDependenciesTest.php @@ -0,0 +1,77 @@ + [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'add_task', + 'toolArgs' => ['userId' => 'alice', 'description' => 'Complete the project documentation'], + ], + 'testName' => 'add_task', + ], + 'List User Tasks' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'list_user_tasks', + 'toolArgs' => ['userId' => 'alice'], + ], + 'testName' => 'list_user_tasks', + ], + 'Complete Task' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'complete_task', + 'toolArgs' => ['taskId' => 1], + ], + 'testName' => 'complete_task', + ], + 'Read System Statistics Resource' => [ + 'method' => 'resources/read', + 'options' => [ + 'uri' => 'stats://system/overview', + ], + 'testName' => 'read_system_stats', + ], + ]; + } + + protected function getServerScript(): string + { + return \dirname(__DIR__, 3).'/examples/stdio-custom-dependencies/server.php'; + } + + protected function normalizeTestOutput(string $output, ?string $testName = null): string + { + return match ($testName) { + 'add_task' => preg_replace( + '/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}/', + '2025-01-01T00:00:00+00:00', + $output + ), + 'read_system_stats' => preg_replace( + '/\\\\"server_uptime_seconds\\\\": -?\d+\.?\d*/', + '\\"server_uptime_seconds\\": 12345', + $output + ), + default => $output, + }; + } +} diff --git a/tests/Inspector/Stdio/StdioDiscoveryCalculatorTest.php b/tests/Inspector/Stdio/StdioDiscoveryCalculatorTest.php new file mode 100644 index 00000000..8a62b2c6 --- /dev/null +++ b/tests/Inspector/Stdio/StdioDiscoveryCalculatorTest.php @@ -0,0 +1,50 @@ + [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'calculate', + 'toolArgs' => ['a' => 12.5, 'b' => 7.3, 'operation' => 'add'], + ], + 'testName' => 'calculate_sum', + ], + 'Update Setting' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'update_setting', + 'toolArgs' => ['setting' => 'precision', 'value' => 3], + ], + 'testName' => 'update_setting', + ], + 'Read Config' => [ + 'method' => 'resources/read', + 'options' => [ + 'uri' => 'config://calculator/settings', + ], + 'testName' => 'read_config', + ], + ]; + } + + protected function getServerScript(): string + { + return \dirname(__DIR__, 3).'/examples/stdio-discovery-calculator/server.php'; + } +} diff --git a/tests/Inspector/Stdio/StdioEnvVariablesTest.php b/tests/Inspector/Stdio/StdioEnvVariablesTest.php new file mode 100644 index 00000000..97601d1a --- /dev/null +++ b/tests/Inspector/Stdio/StdioEnvVariablesTest.php @@ -0,0 +1,55 @@ + [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'process_data_by_mode', + 'toolArgs' => ['input' => 'test data'], + ], + 'testName' => 'process_data_default', + ], + 'Process Data (Debug Mode)' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'process_data_by_mode', + 'toolArgs' => ['input' => 'debug test'], + 'envVars' => ['APP_MODE' => 'debug'], + ], + 'testName' => 'process_data_debug', + ], + 'Process Data (Production Mode)' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'process_data_by_mode', + 'toolArgs' => ['input' => 'production data'], + 'envVars' => ['APP_MODE' => 'production'], + ], + 'testName' => 'process_data_production', + ], + ]; + } + + protected function getServerScript(): string + { + return \dirname(__DIR__, 3).'/examples/stdio-env-variables/server.php'; + } +} diff --git a/tests/Inspector/Stdio/StdioExplicitRegistrationTest.php b/tests/Inspector/Stdio/StdioExplicitRegistrationTest.php new file mode 100644 index 00000000..103d3e67 --- /dev/null +++ b/tests/Inspector/Stdio/StdioExplicitRegistrationTest.php @@ -0,0 +1,82 @@ + [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'echo_text', + 'toolArgs' => ['text' => 'Hello World!'], + ], + 'testName' => 'echo_text', + ], + 'Echo Tool with Special Characters' => [ + 'method' => 'tools/call', + 'options' => [ + 'toolName' => 'echo_text', + 'toolArgs' => ['text' => 'Test with emoji 🎉 and symbols @#$%'], + ], + 'testName' => 'echo_text_special_chars', + ], + 'Read App Version Resource' => [ + 'method' => 'resources/read', + 'options' => [ + 'uri' => 'app://version', + ], + 'testName' => 'read_app_version', + ], + 'Read Item Details (123)' => [ + 'method' => 'resources/read', + 'options' => [ + 'uri' => 'item://123/details', + ], + 'testName' => 'read_item_123_details', + ], + 'Read Item Details (ABC)' => [ + 'method' => 'resources/read', + 'options' => [ + 'uri' => 'item://ABC/details', + ], + 'testName' => 'read_item_ABC_details', + ], + 'Personalized Greeting Prompt (Alice)' => [ + 'method' => 'prompts/get', + 'options' => [ + 'promptName' => 'personalized_greeting', + 'promptArgs' => ['userName' => 'Alice'], + ], + 'testName' => 'personalized_greeting_alice', + ], + 'Personalized Greeting Prompt (Bob)' => [ + 'method' => 'prompts/get', + 'options' => [ + 'promptName' => 'personalized_greeting', + 'promptArgs' => ['userName' => 'Bob'], + ], + 'testName' => 'personalized_greeting_bob', + ], + ]; + } + + protected function getServerScript(): string + { + return \dirname(__DIR__, 3).'/examples/stdio-explicit-registration/server.php'; + } +} diff --git a/tests/Inspector/Stdio/StdioInspectorSnapshotTestCase.php b/tests/Inspector/Stdio/StdioInspectorSnapshotTestCase.php new file mode 100644 index 00000000..a88896c3 --- /dev/null +++ b/tests/Inspector/Stdio/StdioInspectorSnapshotTestCase.php @@ -0,0 +1,37 @@ +getServerScript()]; + } + + protected function getTransport(): string + { + return 'stdio'; + } + + protected function getSnapshotFilePath(string $method, ?string $testName = null): string + { + $className = substr(static::class, strrpos(static::class, '\\') + 1); + $suffix = $testName ? '-'.preg_replace('/[^a-zA-Z0-9_]/', '_', $testName) : ''; + + return __DIR__.'/snapshots/'.$className.'-'.str_replace('/', '_', $method).$suffix.'.json'; + } +} diff --git a/tests/Inspector/snapshots/StdioEnvVariablesTest-prompts_list.json b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-prompts_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioEnvVariablesTest-prompts_list.json rename to tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-prompts_list.json diff --git a/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-resources_list.json b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-resources_list.json new file mode 100644 index 00000000..d02ef58d --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-resources_list.json @@ -0,0 +1,3 @@ +{ + "resources": [] +} diff --git a/tests/Inspector/snapshots/StdioEnvVariablesTest-resources_templates_list.json b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-resources_templates_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioEnvVariablesTest-resources_templates_list.json rename to tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-resources_templates_list.json diff --git a/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-add_numbers.json b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-add_numbers.json new file mode 100644 index 00000000..3bb28b3d --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-add_numbers.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "8" + } + ], + "isError": false +} diff --git a/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-add_numbers_negative.json b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-add_numbers_negative.json new file mode 100644 index 00000000..2a25b87b --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-add_numbers_negative.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "-3" + } + ], + "isError": false +} diff --git a/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-divide_numbers.json b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-divide_numbers.json new file mode 100644 index 00000000..957d6df4 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-divide_numbers.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "5" + } + ], + "isError": false +} diff --git a/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-divide_numbers_decimal.json b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-divide_numbers_decimal.json new file mode 100644 index 00000000..1ae0005d --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-divide_numbers_decimal.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "3.5" + } + ], + "isError": false +} diff --git a/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-multiply_numbers.json b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-multiply_numbers.json new file mode 100644 index 00000000..b391c653 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-multiply_numbers.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "24" + } + ], + "isError": false +} diff --git a/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-multiply_numbers_zero.json b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-multiply_numbers_zero.json new file mode 100644 index 00000000..04988535 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-multiply_numbers_zero.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "0" + } + ], + "isError": false +} diff --git a/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-power.json b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-power.json new file mode 100644 index 00000000..d4289e41 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-power.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "256" + } + ], + "isError": false +} diff --git a/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-power_zero_exponent.json b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-power_zero_exponent.json new file mode 100644 index 00000000..5088e95f --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_call-power_zero_exponent.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "1" + } + ], + "isError": false +} diff --git a/tests/Inspector/snapshots/StdioCachedDiscoveryTest-tools_list.json b/tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioCachedDiscoveryTest-tools_list.json rename to tests/Inspector/Stdio/snapshots/StdioCachedDiscoveryTest-tools_list.json diff --git a/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-prompts_list.json b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-prompts_list.json new file mode 100644 index 00000000..7292222c --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-prompts_list.json @@ -0,0 +1,3 @@ +{ + "prompts": [] +} diff --git a/tests/Inspector/snapshots/StdioCustomDependenciesTest-resources_list.json b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-resources_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioCustomDependenciesTest-resources_list.json rename to tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-resources_list.json diff --git a/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-resources_read-read_system_stats.json b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-resources_read-read_system_stats.json new file mode 100644 index 00000000..bdea849a --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-resources_read-read_system_stats.json @@ -0,0 +1,9 @@ +{ + "contents": [ + { + "uri": "stats://system/overview", + "mimeType": "application/json", + "text": "{\n \"total_tasks\": 3,\n \"completed_tasks\": 0,\n \"pending_tasks\": 3,\n \"server_uptime_seconds\": 12345\n}" + } + ] +} diff --git a/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-resources_templates_list.json b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-resources_templates_list.json new file mode 100644 index 00000000..e867d9d2 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-resources_templates_list.json @@ -0,0 +1,3 @@ +{ + "resourceTemplates": [] +} diff --git a/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-tools_call-add_task.json b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-tools_call-add_task.json new file mode 100644 index 00000000..9ded3d2a --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-tools_call-add_task.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"id\": 4,\n \"userId\": \"alice\",\n \"description\": \"Complete the project documentation\",\n \"completed\": false,\n \"createdAt\": \"2025-01-01T00:00:00+00:00\"\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-tools_call-complete_task.json b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-tools_call-complete_task.json new file mode 100644 index 00000000..3d852eda --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-tools_call-complete_task.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"success\": true,\n \"message\": \"Task 1 completed.\"\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-tools_call-list_user_tasks.json b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-tools_call-list_user_tasks.json new file mode 100644 index 00000000..6fac3026 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-tools_call-list_user_tasks.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "[]" + } + ], + "isError": false +} diff --git a/tests/Inspector/snapshots/StdioCustomDependenciesTest-tools_list.json b/tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-tools_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioCustomDependenciesTest-tools_list.json rename to tests/Inspector/Stdio/snapshots/StdioCustomDependenciesTest-tools_list.json diff --git a/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-prompts_list.json b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-prompts_list.json new file mode 100644 index 00000000..7292222c --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-prompts_list.json @@ -0,0 +1,3 @@ +{ + "prompts": [] +} diff --git a/tests/Inspector/snapshots/StdioDiscoveryCalculatorTest-resources_list.json b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-resources_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioDiscoveryCalculatorTest-resources_list.json rename to tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-resources_list.json diff --git a/tests/Inspector/snapshots/StdioDiscoveryCalculatorTest-resources_read.json b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-resources_read-read_config.json similarity index 100% rename from tests/Inspector/snapshots/StdioDiscoveryCalculatorTest-resources_read.json rename to tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-resources_read-read_config.json diff --git a/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-resources_read.json b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-resources_read.json new file mode 100644 index 00000000..c15d9a8e --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-resources_read.json @@ -0,0 +1,9 @@ +{ + "contents": [ + { + "uri": "config://calculator/settings", + "mimeType": "application/json", + "text": "{\n \"precision\": 2,\n \"allow_negative\": true\n}" + } + ] +} diff --git a/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-resources_templates_list.json b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-resources_templates_list.json new file mode 100644 index 00000000..e867d9d2 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-resources_templates_list.json @@ -0,0 +1,3 @@ +{ + "resourceTemplates": [] +} diff --git a/tests/Inspector/snapshots/StdioDiscoveryCalculatorTest-tools_call.json b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-tools_call-calculate_sum.json similarity index 100% rename from tests/Inspector/snapshots/StdioDiscoveryCalculatorTest-tools_call.json rename to tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-tools_call-calculate_sum.json diff --git a/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-tools_call-update_setting.json b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-tools_call-update_setting.json new file mode 100644 index 00000000..37b42155 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-tools_call-update_setting.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"success\": true,\n \"message\": \"Precision updated to 3.\"\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-tools_call.json b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-tools_call.json new file mode 100644 index 00000000..a73c8b94 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-tools_call.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "19.8" + } + ], + "isError": false +} diff --git a/tests/Inspector/snapshots/StdioDiscoveryCalculatorTest-tools_list.json b/tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-tools_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioDiscoveryCalculatorTest-tools_list.json rename to tests/Inspector/Stdio/snapshots/StdioDiscoveryCalculatorTest-tools_list.json diff --git a/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-prompts_list.json b/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-prompts_list.json new file mode 100644 index 00000000..7292222c --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-prompts_list.json @@ -0,0 +1,3 @@ +{ + "prompts": [] +} diff --git a/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-resources_list.json b/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-resources_list.json new file mode 100644 index 00000000..d02ef58d --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-resources_list.json @@ -0,0 +1,3 @@ +{ + "resources": [] +} diff --git a/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-resources_templates_list.json b/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-resources_templates_list.json new file mode 100644 index 00000000..e867d9d2 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-resources_templates_list.json @@ -0,0 +1,3 @@ +{ + "resourceTemplates": [] +} diff --git a/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-tools_call-process_data_debug.json b/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-tools_call-process_data_debug.json new file mode 100644 index 00000000..3b11d407 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-tools_call-process_data_debug.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"mode\": \"debug\",\n \"processed_input\": \"DEBUG TEST\",\n \"message\": \"Processed in DEBUG mode.\"\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-tools_call-process_data_default.json b/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-tools_call-process_data_default.json new file mode 100644 index 00000000..fde189ee --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-tools_call-process_data_default.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"mode\": \"default\",\n \"original_input\": \"test data\",\n \"message\": \"Processed in default mode (APP_MODE not recognized or not set).\"\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-tools_call-process_data_production.json b/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-tools_call-process_data_production.json new file mode 100644 index 00000000..dd4cd9dc --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-tools_call-process_data_production.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "{\n \"mode\": \"production\",\n \"processed_input_length\": 15,\n \"message\": \"Processed in PRODUCTION mode (summary only).\"\n}" + } + ], + "isError": false +} diff --git a/tests/Inspector/snapshots/StdioEnvVariablesTest-tools_list.json b/tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-tools_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioEnvVariablesTest-tools_list.json rename to tests/Inspector/Stdio/snapshots/StdioEnvVariablesTest-tools_list.json diff --git a/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-prompts_get-personalized_greeting_alice.json b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-prompts_get-personalized_greeting_alice.json new file mode 100644 index 00000000..b5777fa4 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-prompts_get-personalized_greeting_alice.json @@ -0,0 +1,11 @@ +{ + "messages": [ + { + "role": "user", + "content": { + "type": "text", + "text": "Craft a personalized greeting for Alice." + } + } + ] +} diff --git a/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-prompts_get-personalized_greeting_bob.json b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-prompts_get-personalized_greeting_bob.json new file mode 100644 index 00000000..e432a6f4 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-prompts_get-personalized_greeting_bob.json @@ -0,0 +1,11 @@ +{ + "messages": [ + { + "role": "user", + "content": { + "type": "text", + "text": "Craft a personalized greeting for Bob." + } + } + ] +} diff --git a/tests/Inspector/snapshots/StdioExplicitRegistrationTest-prompts_list.json b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-prompts_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioExplicitRegistrationTest-prompts_list.json rename to tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-prompts_list.json diff --git a/tests/Inspector/snapshots/StdioExplicitRegistrationTest-resources_list.json b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-resources_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioExplicitRegistrationTest-resources_list.json rename to tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-resources_list.json diff --git a/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-resources_read-read_app_version.json b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-resources_read-read_app_version.json new file mode 100644 index 00000000..1547bdaa --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-resources_read-read_app_version.json @@ -0,0 +1,9 @@ +{ + "contents": [ + { + "uri": "app://version", + "mimeType": "text/plain", + "text": "1.0-manual" + } + ] +} diff --git a/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-resources_read-read_item_123_details.json b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-resources_read-read_item_123_details.json new file mode 100644 index 00000000..d3eca519 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-resources_read-read_item_123_details.json @@ -0,0 +1,9 @@ +{ + "contents": [ + { + "uri": "item://123/details", + "mimeType": "application/json", + "text": "{\n \"id\": \"123\",\n \"name\": \"Item 123\",\n \"description\": \"Details for item 123 from manual template.\"\n}" + } + ] +} diff --git a/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-resources_read-read_item_ABC_details.json b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-resources_read-read_item_ABC_details.json new file mode 100644 index 00000000..6a2dd65f --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-resources_read-read_item_ABC_details.json @@ -0,0 +1,9 @@ +{ + "contents": [ + { + "uri": "item://ABC/details", + "mimeType": "application/json", + "text": "{\n \"id\": \"ABC\",\n \"name\": \"Item ABC\",\n \"description\": \"Details for item ABC from manual template.\"\n}" + } + ] +} diff --git a/tests/Inspector/snapshots/StdioExplicitRegistrationTest-resources_templates_list.json b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-resources_templates_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioExplicitRegistrationTest-resources_templates_list.json rename to tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-resources_templates_list.json diff --git a/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-tools_call-echo_text.json b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-tools_call-echo_text.json new file mode 100644 index 00000000..9bad1e77 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-tools_call-echo_text.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "Echo: Hello World!" + } + ], + "isError": false +} diff --git a/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-tools_call-echo_text_special_chars.json b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-tools_call-echo_text_special_chars.json new file mode 100644 index 00000000..bf4fc3c7 --- /dev/null +++ b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-tools_call-echo_text_special_chars.json @@ -0,0 +1,9 @@ +{ + "content": [ + { + "type": "text", + "text": "Echo: Test with emoji 🎉 and symbols @#$%" + } + ], + "isError": false +} diff --git a/tests/Inspector/snapshots/StdioExplicitRegistrationTest-tools_list.json b/tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-tools_list.json similarity index 100% rename from tests/Inspector/snapshots/StdioExplicitRegistrationTest-tools_list.json rename to tests/Inspector/Stdio/snapshots/StdioExplicitRegistrationTest-tools_list.json diff --git a/tests/Inspector/StdioCachedDiscoveryTest.php b/tests/Inspector/StdioCachedDiscoveryTest.php deleted file mode 100644 index dfc8acec..00000000 --- a/tests/Inspector/StdioCachedDiscoveryTest.php +++ /dev/null @@ -1,29 +0,0 @@ - [ - 'method' => 'tools/call', - 'toolName' => 'calculate', - 'toolArgs' => ['a' => 12.5, 'b' => 7.3, 'operation' => 'add'], - ], - 'Read Config' => [ - 'method' => 'resources/read', - 'toolName' => null, // can be removed with newer PHPUnit versions - 'toolArgs' => [], // can be removed with newer PHPUnit versions - 'uri' => 'config://calculator/settings', - ], - ]; - } - - protected function getServerScript(): string - { - return \dirname(__DIR__, 2).'/examples/stdio-discovery-calculator/server.php'; - } -} diff --git a/tests/Inspector/StdioEnvVariablesTest.php b/tests/Inspector/StdioEnvVariablesTest.php deleted file mode 100644 index d347cd69..00000000 --- a/tests/Inspector/StdioEnvVariablesTest.php +++ /dev/null @@ -1,29 +0,0 @@ -