|
2 | 2 |
|
3 | 3 | namespace PhpMcp\Server\Tests\Unit; |
4 | 4 |
|
| 5 | +use Grpc\Call; |
5 | 6 | use Mockery; |
6 | 7 | use Mockery\MockInterface; |
7 | 8 | use PhpMcp\Schema\ClientCapabilities; |
| 9 | +use PhpMcp\Server\CallContext; |
8 | 10 | use PhpMcp\Server\Configuration; |
9 | 11 | use PhpMcp\Server\Contracts\CompletionProviderInterface; |
10 | 12 | use PhpMcp\Server\Contracts\SessionInterface; |
|
104 | 106 | $this->session->shouldReceive('set')->with('client_info', Mockery::on(fn($value) => $value['name'] === 'client' && $value['version'] === '1.0'))->once(); |
105 | 107 | $this->session->shouldReceive('set')->with('protocol_version', Protocol::LATEST_PROTOCOL_VERSION)->once(); |
106 | 108 |
|
107 | | - $result = $this->dispatcher->handleRequest($request, $this->session); |
| 109 | + $result = $this->dispatcher->handleRequest($request, $this->session, new CallContext()); |
108 | 110 | expect($result)->toBeInstanceOf(InitializeResult::class); |
109 | 111 | expect($result->protocolVersion)->toBe(Protocol::LATEST_PROTOCOL_VERSION); |
110 | 112 | expect($result->serverInfo->name)->toBe('DispatcherTestServer'); |
111 | 113 | }); |
112 | 114 |
|
113 | 115 | it('routes to handlePing for ping request', function () { |
114 | 116 | $request = new JsonRpcRequest('2.0', 'id1', 'ping', []); |
115 | | - $result = $this->dispatcher->handleRequest($request, $this->session); |
| 117 | + $result = $this->dispatcher->handleRequest($request, $this->session, new CallContext()); |
116 | 118 | expect($result)->toBeInstanceOf(EmptyResult::class); |
117 | 119 | }); |
118 | 120 |
|
119 | 121 | it('throws MethodNotFound for unknown request method', function () { |
120 | 122 | $rawRequest = new JsonRpcRequest('2.0', 'id1', 'unknown/method', []); |
121 | | - $this->dispatcher->handleRequest($rawRequest, $this->session); |
| 123 | + $this->dispatcher->handleRequest($rawRequest, $this->session, new CallContext()); |
122 | 124 | })->throws(McpServerException::class, "Method 'unknown/method' not found."); |
123 | 125 |
|
124 | 126 | it('routes to handleNotificationInitialized for initialized notification', function () { |
|
200 | 202 | $args = ['a' => 10, 'b' => 5]; |
201 | 203 | $toolSchema = ToolSchema::make($toolName, ['type' => 'object', 'properties' => ['a' => ['type' => 'integer'], 'b' => ['type' => 'integer']]]); |
202 | 204 | $registeredToolMock = Mockery::mock(RegisteredTool::class, [$toolSchema, 'MyToolHandler', 'handleTool', false]); |
| 205 | + $callContext = new CallContext(); |
203 | 206 |
|
204 | 207 | $this->registry->shouldReceive('getTool')->with($toolName)->andReturn($registeredToolMock); |
205 | 208 | $this->schemaValidator->shouldReceive('validateAgainstJsonSchema')->with($args, $toolSchema->inputSchema)->andReturn([]); // No validation errors |
206 | | - $registeredToolMock->shouldReceive('call')->with($this->container, $args)->andReturn([TextContent::make("Result: 15")]); |
| 209 | + $registeredToolMock->shouldReceive('call')->with($this->container, $args, $callContext)->andReturn([TextContent::make("Result: 15")]); |
207 | 210 |
|
208 | 211 | $request = CallToolRequest::make(1, $toolName, $args); |
209 | | - $result = $this->dispatcher->handleToolCall($request); |
| 212 | + $result = $this->dispatcher->handleToolCall($request, $callContext); |
210 | 213 |
|
211 | 214 | expect($result)->toBeInstanceOf(CallToolResult::class); |
212 | 215 | expect($result->content[0]->text)->toBe("Result: 15"); |
|
216 | 219 | it('can handle tool call request and throw exception if tool not found', function () { |
217 | 220 | $this->registry->shouldReceive('getTool')->with('unknown-tool')->andReturn(null); |
218 | 221 | $request = CallToolRequest::make(1, 'unknown-tool', []); |
219 | | - $this->dispatcher->handleToolCall($request); |
| 222 | + $this->dispatcher->handleToolCall($request, new CallContext()); |
220 | 223 | })->throws(McpServerException::class, "Tool 'unknown-tool' not found."); |
221 | 224 |
|
222 | 225 | it('can handle tool call request and throw exception if argument validation fails', function () { |
|
231 | 234 |
|
232 | 235 | $request = CallToolRequest::make(1, $toolName, $args); |
233 | 236 | try { |
234 | | - $this->dispatcher->handleToolCall($request); |
| 237 | + $this->dispatcher->handleToolCall($request, new CallContext()); |
235 | 238 | } catch (McpServerException $e) { |
236 | 239 | expect($e->getMessage())->toContain("Invalid parameters for tool 'strict-tool'"); |
237 | 240 | expect($e->getData()['validation_errors'])->toBeArray(); |
|
248 | 251 | $registeredToolMock->shouldReceive('call')->andThrow(new \RuntimeException("Tool crashed!")); |
249 | 252 |
|
250 | 253 | $request = CallToolRequest::make(1, $toolName, []); |
251 | | - $result = $this->dispatcher->handleToolCall($request); |
| 254 | + $result = $this->dispatcher->handleToolCall($request, new CallContext()); |
252 | 255 |
|
253 | 256 | expect($result->isError)->toBeTrue(); |
254 | 257 | expect($result->content[0]->text)->toBe("Tool execution failed: Tool crashed!"); |
|
265 | 268 |
|
266 | 269 |
|
267 | 270 | $request = CallToolRequest::make(1, $toolName, []); |
268 | | - $result = $this->dispatcher->handleToolCall($request); |
| 271 | + $result = $this->dispatcher->handleToolCall($request, new CallContext()); |
269 | 272 |
|
270 | 273 | expect($result->isError)->toBeTrue(); |
271 | 274 | expect($result->content[0]->text)->toBe("Failed to serialize tool result: Unencodable."); |
|
0 commit comments