- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
224 lines
6.3 KiB
PHP
224 lines
6.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Framework\DI\Container;
|
|
use App\Framework\Mcp\McpResourceRegistry;
|
|
use App\Framework\Mcp\McpServer;
|
|
use App\Framework\Mcp\McpToolRegistry;
|
|
|
|
beforeEach(function () {
|
|
$this->container = Mockery::mock(Container::class);
|
|
$this->toolRegistry = Mockery::mock(McpToolRegistry::class);
|
|
$this->resourceRegistry = Mockery::mock(McpResourceRegistry::class);
|
|
|
|
$this->mcpServer = new McpServer(
|
|
$this->container,
|
|
$this->toolRegistry,
|
|
$this->resourceRegistry
|
|
);
|
|
});
|
|
|
|
afterEach(function () {
|
|
Mockery::close();
|
|
});
|
|
|
|
test('initialize returns correct protocol response', function () {
|
|
$request = json_encode([
|
|
'jsonrpc' => '2.0',
|
|
'method' => 'initialize',
|
|
'params' => [],
|
|
'id' => 1,
|
|
]);
|
|
|
|
$response = $this->mcpServer->handleRequest($request);
|
|
$decoded = json_decode($response, true);
|
|
|
|
expect($decoded)->toHaveKey('jsonrpc', '2.0')
|
|
->and($decoded)->toHaveKey('id', 1)
|
|
->and($decoded['result'])->toHaveKey('protocolVersion')
|
|
->and($decoded['result'])->toHaveKey('capabilities')
|
|
->and($decoded['result'])->toHaveKey('serverInfo')
|
|
->and($decoded['result']['serverInfo']['name'])->toBe('Custom PHP Framework MCP Server');
|
|
});
|
|
|
|
test('tools list returns registered tools', function () {
|
|
$mockTools = [
|
|
[
|
|
'name' => 'test_tool',
|
|
'description' => 'A test tool',
|
|
'parameters' => [],
|
|
'inputSchema' => null,
|
|
],
|
|
];
|
|
|
|
$this->toolRegistry
|
|
->shouldReceive('getAllTools')
|
|
->andReturn($mockTools);
|
|
|
|
$request = json_encode([
|
|
'jsonrpc' => '2.0',
|
|
'method' => 'tools/list',
|
|
'id' => 1,
|
|
]);
|
|
|
|
$response = $this->mcpServer->handleRequest($request);
|
|
$decoded = json_decode($response, true);
|
|
|
|
expect($decoded)->toHaveKey('result')
|
|
->and($decoded['result'])->toHaveKey('tools')
|
|
->and($decoded['result']['tools'])->toHaveCount(1)
|
|
->and($decoded['result']['tools'][0]['name'])->toBe('test_tool');
|
|
});
|
|
|
|
test('resources list returns registered resources', function () {
|
|
$mockResources = [
|
|
[
|
|
'uri' => 'framework://test',
|
|
'name' => 'Test Resource',
|
|
'description' => 'A test resource',
|
|
'mimeType' => 'application/json',
|
|
],
|
|
];
|
|
|
|
$this->resourceRegistry
|
|
->shouldReceive('getAllResources')
|
|
->andReturn($mockResources);
|
|
|
|
$request = json_encode([
|
|
'jsonrpc' => '2.0',
|
|
'method' => 'resources/list',
|
|
'id' => 1,
|
|
]);
|
|
|
|
$response = $this->mcpServer->handleRequest($request);
|
|
$decoded = json_decode($response, true);
|
|
|
|
expect($decoded)->toHaveKey('result')
|
|
->and($decoded['result'])->toHaveKey('resources')
|
|
->and($decoded['result']['resources'])->toHaveCount(1)
|
|
->and($decoded['result']['resources'][0]['uri'])->toBe('framework://test');
|
|
});
|
|
|
|
test('invalid json request returns error', function () {
|
|
$invalidJson = '{"invalid": json}';
|
|
|
|
$response = $this->mcpServer->handleRequest($invalidJson);
|
|
$decoded = json_decode($response, true);
|
|
|
|
expect($decoded)->toHaveKey('error')
|
|
->and($decoded['error']['message'])->toContain('Invalid JSON');
|
|
});
|
|
|
|
test('missing method returns error', function () {
|
|
$request = json_encode([
|
|
'jsonrpc' => '2.0',
|
|
'id' => 1,
|
|
// Missing 'method' field
|
|
]);
|
|
|
|
$response = $this->mcpServer->handleRequest($request);
|
|
$decoded = json_decode($response, true);
|
|
|
|
expect($decoded)->toHaveKey('error')
|
|
->and($decoded['error']['message'])->toContain('method missing');
|
|
});
|
|
|
|
test('unknown method returns error', function () {
|
|
$request = json_encode([
|
|
'jsonrpc' => '2.0',
|
|
'method' => 'unknown/method',
|
|
'id' => 1,
|
|
]);
|
|
|
|
$response = $this->mcpServer->handleRequest($request);
|
|
$decoded = json_decode($response, true);
|
|
|
|
expect($decoded)->toHaveKey('error')
|
|
->and($decoded['error']['message'])->toContain('Unknown method');
|
|
});
|
|
|
|
test('tool call executes registered tool', function () {
|
|
$mockTool = [
|
|
'name' => 'test_tool',
|
|
'class' => 'TestToolClass',
|
|
'method' => 'execute',
|
|
'parameters' => [],
|
|
];
|
|
|
|
$mockToolInstance = new class () {
|
|
public function execute(array $params): array
|
|
{
|
|
return ['result' => 'success', 'data' => $params];
|
|
}
|
|
};
|
|
|
|
$this->toolRegistry
|
|
->shouldReceive('getTool')
|
|
->with('test_tool')
|
|
->andReturn($mockTool);
|
|
|
|
$this->container
|
|
->shouldReceive('get')
|
|
->with('TestToolClass')
|
|
->andReturn($mockToolInstance);
|
|
|
|
$request = json_encode([
|
|
'jsonrpc' => '2.0',
|
|
'method' => 'tools/call',
|
|
'params' => [
|
|
'name' => 'test_tool',
|
|
'arguments' => ['param1' => 'value1'],
|
|
],
|
|
'id' => 1,
|
|
]);
|
|
|
|
$response = $this->mcpServer->handleRequest($request);
|
|
$decoded = json_decode($response, true);
|
|
|
|
expect($decoded)->toHaveKey('result')
|
|
->and($decoded['result']['content'])->toHaveCount(1)
|
|
->and($decoded['result']['content'][0]['type'])->toBe('text');
|
|
});
|
|
|
|
test('resource read returns resource content', function () {
|
|
$mockResource = [
|
|
'uri' => 'framework://test',
|
|
'class' => 'TestResourceClass',
|
|
'method' => 'read',
|
|
];
|
|
|
|
$mockResourceInstance = new class () {
|
|
public function read(string $uri): array
|
|
{
|
|
return ['content' => 'test content', 'mimeType' => 'text/plain'];
|
|
}
|
|
};
|
|
|
|
$this->resourceRegistry
|
|
->shouldReceive('getResource')
|
|
->with('framework://test')
|
|
->andReturn($mockResource);
|
|
|
|
$this->container
|
|
->shouldReceive('get')
|
|
->with('TestResourceClass')
|
|
->andReturn($mockResourceInstance);
|
|
|
|
$request = json_encode([
|
|
'jsonrpc' => '2.0',
|
|
'method' => 'resources/read',
|
|
'params' => [
|
|
'uri' => 'framework://test',
|
|
],
|
|
'id' => 1,
|
|
]);
|
|
|
|
$response = $this->mcpServer->handleRequest($request);
|
|
$decoded = json_decode($response, true);
|
|
|
|
expect($decoded)->toHaveKey('result')
|
|
->and($decoded['result']['contents'])->toHaveCount(1)
|
|
->and($decoded['result']['contents'][0]['uri'])->toBe('framework://test');
|
|
});
|