{"openapi":"3.1.0","info":{"title":"xdog-orchestrator","description":"Public-auth MCP gateway for xdog-mcp.","version":"0.1.0"},"paths":{"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Health Health Get"}}}}}}},"/healthz":{"get":{"summary":"Healthz","operationId":"healthz_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Healthz Healthz Get"}}}}}}},"/mcp/":{"get":{"summary":"Mcp Get","description":"GET on the MCP endpoint. We do not serve a server-initiated SSE stream, but\nauth runs FIRST (via CurrentTenant), so an unauthenticated GET returns\n401 + WWW-Authenticate (OAuth discovery) instead of a bare 405 that makes\nbrowser MCP clients (Grok) treat the endpoint as dead.","operationId":"mcp_get_mcp__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Mcp Proxy","description":"Forward one MCP JSON-RPC call to the upstream xdog-mcp Cloud Run service.\n\nStreams SSE responses transparently. Surfaces non-2xx as 502 with the body.","operationId":"mcp_proxy_mcp__post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/mcp":{"get":{"summary":"Mcp Get","description":"GET on the MCP endpoint. We do not serve a server-initiated SSE stream, but\nauth runs FIRST (via CurrentTenant), so an unauthenticated GET returns\n401 + WWW-Authenticate (OAuth discovery) instead of a bare 405 that makes\nbrowser MCP clients (Grok) treat the endpoint as dead.","operationId":"mcp_get_mcp_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Mcp Proxy","description":"Forward one MCP JSON-RPC call to the upstream xdog-mcp Cloud Run service.\n\nStreams SSE responses transparently. Surfaces non-2xx as 502 with the body.","operationId":"mcp_proxy_mcp_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/tenants":{"get":{"summary":"List Tenants","description":"List all known tenants.","operationId":"list_tenants_admin_tenants_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Tenants Admin Tenants Get"}}}}}},"post":{"summary":"Create Tenant","description":"Create a new tenant. (Stripe customer creation is a later hook.)","operationId":"create_tenant_admin_tenants_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Tenant Admin Tenants Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/keys":{"get":{"summary":"List Keys","description":"List all issued API keys (metadata only — never the raw key).","operationId":"list_keys_admin_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Keys Admin Keys Get"}}}}}},"post":{"summary":"Issue Key","description":"Issue a new API key for a tenant. Returns the raw key ONCE.","operationId":"issue_key_admin_keys_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Issue Key Admin Keys Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tenants/{tenant_id}/admin":{"patch":{"summary":"Set Tenant Admin","description":"Grant or revoke a tenant's admin (full-tool-access) flag.\n\nAdmin = the xdog-mcp wildcard toolset (all tools). Non-admin = the customer\ndefault. Guards: ``main`` (and any PROTECTED_ADMINS) can't be demoted, and\nthe last remaining admin can't be removed.","operationId":"set_tenant_admin_admin_tenants__tenant_id__admin_patch","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Set Tenant Admin Admin Tenants  Tenant Id  Admin Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/keys/{key_id}":{"delete":{"summary":"Revoke Key","description":"Revoke an API key by its api_key_id.","operationId":"revoke_key_admin_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revoke Key Admin Keys  Key Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tenants/{tenant_id}/usage":{"get":{"summary":"Tenant Usage","description":"Usage rollup for a tenant. TODO: real query.","operationId":"tenant_usage_admin_tenants__tenant_id__usage_get","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}},{"name":"from_","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From "}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Tenant Usage Admin Tenants  Tenant Id  Usage Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tools":{"get":{"summary":"List Tools","description":"Cached mirror of xdog-mcp's tools/list. TODO: cache w/ TTL.","operationId":"list_tools_admin_tools_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Tools Admin Tools Get"}}}}}}},"/admin/cleanup-revoked":{"post":{"summary":"Cleanup Revoked","description":"Purge revoked keys and delete tenant docs left with no keys.\n\nOperator housekeeping for the Mission Control subscriber table:\n  1. Hard-delete every API-key doc that has ``revoked_at`` set.\n  2. Delete any tenant doc that, afterwards, has no remaining keys — UNLESS\n     it is protected (``main`` etc.) or still flagged ``is_admin`` (our infra\n     agents, which may have no customer-issued key but must never vanish).\n\nPass ``{\"dry_run\": true}`` to preview what would be removed without writing.","operationId":"cleanup_revoked_admin_cleanup_revoked_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Cleanup Revoked Admin Cleanup Revoked Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tenants/{tenant_id}":{"delete":{"summary":"Remove Tenant","description":"Delete a tenant and all of its API keys. Guards protected/admin tenants.","operationId":"remove_tenant_admin_tenants__tenant_id__delete","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Remove Tenant Admin Tenants  Tenant Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tools":{"get":{"summary":"List Tools","description":"Return the live tool catalogue from xdog-mcp. No auth required.","operationId":"list_tools_tools_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-protected-resource/mcp":{"get":{"tags":["oauth"],"summary":"Protected Resource Metadata","operationId":"protected_resource_metadata__well_known_oauth_protected_resource_mcp_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Protected Resource Metadata  Well Known Oauth Protected Resource Mcp Get"}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"tags":["oauth"],"summary":"Protected Resource Metadata","operationId":"protected_resource_metadata__well_known_oauth_protected_resource_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Protected Resource Metadata  Well Known Oauth Protected Resource Get"}}}}}}},"/.well-known/oauth-authorization-server/mcp":{"get":{"tags":["oauth"],"summary":"Authorization Server Metadata","operationId":"authorization_server_metadata__well_known_oauth_authorization_server_mcp_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Authorization Server Metadata  Well Known Oauth Authorization Server Mcp Get"}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"tags":["oauth"],"summary":"Authorization Server Metadata","operationId":"authorization_server_metadata__well_known_oauth_authorization_server_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Authorization Server Metadata  Well Known Oauth Authorization Server Get"}}}}}}},"/register":{"post":{"tags":["oauth"],"summary":"Register Client","operationId":"register_client_register_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/authorize":{"get":{"tags":["oauth"],"summary":"Authorize","operationId":"authorize_authorize_get","parameters":[{"name":"client_id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Client Id"}},{"name":"redirect_uri","in":"query","required":false,"schema":{"type":"string","default":"","title":"Redirect Uri"}},{"name":"response_type","in":"query","required":false,"schema":{"type":"string","default":"","title":"Response Type"}},{"name":"code_challenge","in":"query","required":false,"schema":{"type":"string","default":"","title":"Code Challenge"}},{"name":"code_challenge_method","in":"query","required":false,"schema":{"type":"string","default":"","title":"Code Challenge Method"}},{"name":"scope","in":"query","required":false,"schema":{"type":"string","default":"mcp","title":"Scope"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","default":"","title":"State"}},{"name":"resource","in":"query","required":false,"schema":{"type":"string","default":"","title":"Resource"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/requests/{request_id}":{"get":{"tags":["oauth"],"summary":"Get Request","operationId":"get_request_oauth_requests__request_id__get","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Request Oauth Requests  Request Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/approve":{"post":{"tags":["oauth"],"summary":"Approve","operationId":"approve_oauth_approve_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Approve Oauth Approve Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/revoke-tenant":{"post":{"tags":["oauth"],"summary":"Revoke Tenant","operationId":"revoke_tenant_oauth_revoke_tenant_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Revoke Tenant Oauth Revoke Tenant Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/token":{"post":{"tags":["oauth"],"summary":"Token","operationId":"token_token_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}