loadRegistry(); $this->loadServers(); return [ 'openapi' => '3.0.3', 'info' => $this->buildInfo(), 'servers' => $this->buildServers(), 'tags' => $this->buildTags(), 'paths' => $this->buildPaths(), 'components' => $this->buildComponents(), ]; } public function toJson(): string { return json_encode($this->generate(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); } public function toYaml(): string { return Yaml::dump($this->generate(), 10, 2); } protected function loadRegistry(): void { $path = resource_path('mcp/registry.yaml'); $this->registry = file_exists($path) ? Yaml::parseFile($path) : ['servers' => []]; } protected function loadServers(): void { foreach ($this->registry['servers'] ?? [] as $ref) { $path = resource_path("mcp/servers/{$ref['id']}.yaml"); if (file_exists($path)) { $this->servers[$ref['id']] = Yaml::parseFile($path); } } } protected function buildInfo(): array { return [ 'title' => 'Host UK MCP API', 'description' => 'HTTP API for interacting with Host UK MCP servers. Execute tools, read resources, and discover available capabilities.', 'version' => '1.0.0', 'contact' => [ 'name' => 'Host UK Support', 'url' => 'https://host.uk.com/contact', 'email' => 'support@host.uk.com', ], 'license' => [ 'name' => 'Proprietary', 'url' => 'https://host.uk.com/terms', ], ]; } protected function buildServers(): array { return [ [ 'url' => 'https://mcp.host.uk.com/api/v1/mcp', 'description' => 'Production', ], [ 'url' => 'https://mcp.test/api/v1/mcp', 'description' => 'Local development', ], ]; } protected function buildTags(): array { $tags = [ [ 'name' => 'Discovery', 'description' => 'Server and tool discovery endpoints', ], [ 'name' => 'Execution', 'description' => 'Tool execution endpoints', ], ]; foreach ($this->servers as $id => $server) { $tags[] = [ 'name' => $server['name'] ?? $id, 'description' => $server['tagline'] ?? $server['description'] ?? '', ]; } return $tags; } protected function buildPaths(): array { $paths = []; // Discovery endpoints $paths['/servers'] = [ 'get' => [ 'tags' => ['Discovery'], 'summary' => 'List all MCP servers', 'operationId' => 'listServers', 'security' => [['bearerAuth' => []], ['apiKeyAuth' => []]], 'responses' => [ '200' => [ 'description' => 'List of available servers', 'content' => [ 'application/json' => [ 'schema' => [ '$ref' => '#/components/schemas/ServerList', ], ], ], ], ], ], ]; $paths['/servers/{serverId}'] = [ 'get' => [ 'tags' => ['Discovery'], 'summary' => 'Get server details', 'operationId' => 'getServer', 'security' => [['bearerAuth' => []], ['apiKeyAuth' => []]], 'parameters' => [ [ 'name' => 'serverId', 'in' => 'path', 'required' => true, 'schema' => ['type' => 'string'], 'description' => 'Server identifier', ], ], 'responses' => [ '200' => [ 'description' => 'Server details with tools and resources', 'content' => [ 'application/json' => [ 'schema' => [ '$ref' => '#/components/schemas/Server', ], ], ], ], '404' => ['description' => 'Server not found'], ], ], ]; $paths['/servers/{serverId}/tools'] = [ 'get' => [ 'tags' => ['Discovery'], 'summary' => 'List tools for a server', 'operationId' => 'listServerTools', 'security' => [['bearerAuth' => []], ['apiKeyAuth' => []]], 'parameters' => [ [ 'name' => 'serverId', 'in' => 'path', 'required' => true, 'schema' => ['type' => 'string'], ], ], 'responses' => [ '200' => [ 'description' => 'List of tools', 'content' => [ 'application/json' => [ 'schema' => [ '$ref' => '#/components/schemas/ToolList', ], ], ], ], ], ], ]; // Execution endpoint $paths['/tools/call'] = [ 'post' => [ 'tags' => ['Execution'], 'summary' => 'Execute an MCP tool', 'operationId' => 'callTool', 'security' => [['bearerAuth' => []], ['apiKeyAuth' => []]], 'requestBody' => [ 'required' => true, 'content' => [ 'application/json' => [ 'schema' => [ '$ref' => '#/components/schemas/ToolCallRequest', ], ], ], ], 'responses' => [ '200' => [ 'description' => 'Tool executed successfully', 'content' => [ 'application/json' => [ 'schema' => [ '$ref' => '#/components/schemas/ToolCallResponse', ], ], ], ], '400' => ['description' => 'Invalid request'], '401' => ['description' => 'Unauthorized'], '404' => ['description' => 'Server or tool not found'], '500' => ['description' => 'Tool execution error'], ], ], ]; // Resource endpoint $paths['/resources/{uri}'] = [ 'get' => [ 'tags' => ['Execution'], 'summary' => 'Read a resource', 'operationId' => 'readResource', 'security' => [['bearerAuth' => []], ['apiKeyAuth' => []]], 'parameters' => [ [ 'name' => 'uri', 'in' => 'path', 'required' => true, 'schema' => ['type' => 'string'], 'description' => 'Resource URI (server://path)', ], ], 'responses' => [ '200' => [ 'description' => 'Resource content', 'content' => [ 'application/json' => [ 'schema' => [ '$ref' => '#/components/schemas/ResourceResponse', ], ], ], ], ], ], ]; return $paths; } protected function buildComponents(): array { return [ 'securitySchemes' => [ 'bearerAuth' => [ 'type' => 'http', 'scheme' => 'bearer', 'description' => 'API key in Bearer format: hk_xxx_yyy', ], 'apiKeyAuth' => [ 'type' => 'apiKey', 'in' => 'header', 'name' => 'X-API-Key', 'description' => 'API key header', ], ], 'schemas' => $this->buildSchemas(), ]; } protected function buildSchemas(): array { $schemas = [ 'ServerList' => [ 'type' => 'object', 'properties' => [ 'servers' => [ 'type' => 'array', 'items' => ['$ref' => '#/components/schemas/ServerSummary'], ], 'count' => ['type' => 'integer'], ], ], 'ServerSummary' => [ 'type' => 'object', 'properties' => [ 'id' => ['type' => 'string'], 'name' => ['type' => 'string'], 'tagline' => ['type' => 'string'], 'status' => ['type' => 'string', 'enum' => ['available', 'beta', 'deprecated']], 'tool_count' => ['type' => 'integer'], 'resource_count' => ['type' => 'integer'], ], ], 'Server' => [ 'type' => 'object', 'properties' => [ 'id' => ['type' => 'string'], 'name' => ['type' => 'string'], 'tagline' => ['type' => 'string'], 'description' => ['type' => 'string'], 'tools' => [ 'type' => 'array', 'items' => ['$ref' => '#/components/schemas/Tool'], ], 'resources' => [ 'type' => 'array', 'items' => ['$ref' => '#/components/schemas/Resource'], ], ], ], 'Tool' => [ 'type' => 'object', 'properties' => [ 'name' => ['type' => 'string'], 'description' => ['type' => 'string'], 'inputSchema' => [ 'type' => 'object', 'additionalProperties' => true, ], ], ], 'Resource' => [ 'type' => 'object', 'properties' => [ 'uri' => ['type' => 'string'], 'name' => ['type' => 'string'], 'description' => ['type' => 'string'], 'mimeType' => ['type' => 'string'], ], ], 'ToolList' => [ 'type' => 'object', 'properties' => [ 'server' => ['type' => 'string'], 'tools' => [ 'type' => 'array', 'items' => ['$ref' => '#/components/schemas/Tool'], ], 'count' => ['type' => 'integer'], ], ], 'ToolCallRequest' => [ 'type' => 'object', 'required' => ['server', 'tool'], 'properties' => [ 'server' => [ 'type' => 'string', 'description' => 'Server ID', ], 'tool' => [ 'type' => 'string', 'description' => 'Tool name', ], 'arguments' => [ 'type' => 'object', 'description' => 'Tool arguments', 'additionalProperties' => true, ], ], ], 'ToolCallResponse' => [ 'type' => 'object', 'properties' => [ 'success' => ['type' => 'boolean'], 'server' => ['type' => 'string'], 'tool' => ['type' => 'string'], 'result' => [ 'type' => 'object', 'additionalProperties' => true, ], 'duration_ms' => ['type' => 'integer'], 'error' => ['type' => 'string'], ], ], 'ResourceResponse' => [ 'type' => 'object', 'properties' => [ 'uri' => ['type' => 'string'], 'content' => [ 'type' => 'object', 'additionalProperties' => true, ], ], ], ]; return $schemas; } }