{"openapi":"3.1.0","info":{"title":"RunVector MCP and OAuth integration","version":"1.0.0","description":"This version identifies the supported MCP and OAuth integration contract. RunVector does not offer a versioned REST athlete API."},"servers":[{"url":"https://runvector.io"}],"paths":{"/api/mcp":{"get":{"summary":"MCP GET is not supported by this endpoint","operationId":"mcpGet","security":[{"oauth2":[]}],"responses":{"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"405":{"description":"JSON-RPC method-not-allowed error serialized as text/plain by the MCP handler","content":{"text/plain":{"schema":{"type":"string"}}}}}},"post":{"summary":"Send an authenticated MCP JSON-RPC request","operationId":"mcpPost","security":[{"oauth2":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcRequest"}}}},"responses":{"200":{"description":"MCP JSON-RPC response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcResponse"}},"text/event-stream":{"schema":{"type":"string"}}}},"202":{"description":"JSON-RPC notification accepted without a response body"},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}},"delete":{"summary":"MCP DELETE is not supported by this endpoint","operationId":"mcpDelete","security":[{"oauth2":[]}],"responses":{"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"405":{"description":"JSON-RPC method-not-allowed error serialized as text/plain by the MCP handler","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/oauth/register":{"post":{"summary":"Register a public OAuth client","operationId":"registerOAuthClient","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientRegistrationRequest"}}}},"responses":{"201":{"description":"Registered public client","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientRegistrationResponse"}}}},"400":{"description":"Invalid client metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}},"headers":{"Retry-After":{"schema":{"type":"string"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/api/oauth/token":{"post":{"summary":"Exchange an authorization code with PKCE","operationId":"exchangeOAuthCode","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}}},"responses":{"200":{"description":"Bearer access token","headers":{"X-RateLimit-Remaining":{"schema":{"type":"string"}},"X-RateLimit-Reset":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"400":{"description":"OAuth error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}},"headers":{"Retry-After":{"schema":{"type":"string"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"summary":"Read OAuth authorization server metadata","operationId":"getOAuthAuthorizationServerMetadata","responses":{"200":{"description":"OAuth authorization server metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizationServerMetadata"}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"summary":"Read OAuth protected resource metadata","operationId":"getOAuthProtectedResourceMetadata","responses":{"200":{"description":"OAuth protected resource metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProtectedResourceMetadata"}}}}}}},"/.well-known/oauth-protected-resource/api/mcp":{"get":{"summary":"Read MCP OAuth protected resource metadata","operationId":"getMcpOAuthProtectedResourceMetadata","responses":{"200":{"description":"OAuth protected resource metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProtectedResourceMetadata"}}}}}}}},"components":{"securitySchemes":{"oauth2":{"type":"oauth2","flows":{"authorizationCode":{"authorizationUrl":"https://runvector.io/authorize","tokenUrl":"https://runvector.io/api/oauth/token","scopes":{"read":"RunVector read access","training:read":"RunVector training:read access","activities:read":"RunVector activities:read access","races:read":"RunVector races:read access","predictions:read":"RunVector predictions:read access"},"x-pkce-required":true}}}},"schemas":{"OAuthError":{"type":"object","required":["error","error_description"],"properties":{"error":{"type":"string"},"error_description":{"type":"string"},"error_uri":{"type":"string","format":"uri"}}},"ClientRegistrationRequest":{"type":"object","required":["redirect_uris"],"properties":{"redirect_uris":{"type":"array","minItems":1,"items":{"type":"string","format":"uri"}},"client_name":{"type":"string"}}},"ClientRegistrationResponse":{"type":"object","required":["client_id","client_name","redirect_uris","token_endpoint_auth_method","grant_types","response_types"],"properties":{"client_id":{"type":"string"},"client_name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string","format":"uri"}},"token_endpoint_auth_method":{"type":"string","const":"none"},"grant_types":{"type":"array","items":{"type":"string","const":"authorization_code"}},"response_types":{"type":"array","items":{"type":"string","const":"code"}}}},"TokenRequest":{"type":"object","required":["grant_type","code","code_verifier","client_id","redirect_uri"],"properties":{"grant_type":{"type":"string","const":"authorization_code"},"code":{"type":"string"},"code_verifier":{"type":"string"},"client_id":{"type":"string"},"redirect_uri":{"type":"string","format":"uri"}}},"TokenResponse":{"type":"object","required":["access_token","token_type","expires_in","scope"],"properties":{"access_token":{"type":"string"},"token_type":{"type":"string","const":"bearer"},"expires_in":{"type":"integer"},"scope":{"type":"string"}}},"ProtectedResourceMetadata":{"type":"object","required":["resource","authorization_servers","scopes_supported"],"properties":{"resource":{"type":"string","format":"uri"},"authorization_servers":{"type":"array","items":{"type":"string","format":"uri"}},"scopes_supported":{"type":"array","items":{"type":"string"}}}},"AuthorizationServerMetadata":{"type":"object","required":["issuer","authorization_endpoint","token_endpoint","registration_endpoint","response_types_supported","grant_types_supported","code_challenge_methods_supported","token_endpoint_auth_methods_supported","scopes_supported"],"properties":{"issuer":{"type":"string","format":"uri"},"authorization_endpoint":{"type":"string","format":"uri"},"token_endpoint":{"type":"string","format":"uri"},"registration_endpoint":{"type":"string","format":"uri"},"response_types_supported":{"type":"array","items":{"type":"string"}},"grant_types_supported":{"type":"array","items":{"type":"string"}},"code_challenge_methods_supported":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_methods_supported":{"type":"array","items":{"type":"string"}},"scopes_supported":{"type":"array","items":{"type":"string"}}}},"JsonRpcRequest":{"type":"object","required":["jsonrpc","method"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"number"}]},"method":{"type":"string"},"params":{"type":"object","additionalProperties":true}}},"JsonRpcResponse":{"oneOf":[{"type":"object","required":["jsonrpc","id","result"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"number"}]},"result":{}}},{"type":"object","required":["jsonrpc","id","error"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"null"}]},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"number"},"message":{"type":"string"},"data":{}}}}}]}}}}