{"openapi":"3.1.1","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"Swarmz public API","version":"1.0.0","description":"Public discovery, OAuth, MCP, and build-skill endpoints for Swarmz agents and developer tools.","contact":{"name":"Swarmz developer support","url":"https://docs.swarmz.net"}},"servers":[{"url":"https://swarmz.net"}],"externalDocs":{"description":"Swarmz developer documentation","url":"https://docs.swarmz.net"},"security":[],"tags":[{"name":"MCP","description":"Swarmz Model Context Protocol transport"},{"name":"OAuth","description":"OAuth 2.0 authorization and discovery"},{"name":"Skills","description":"Public build-skill metadata"}],"paths":{"/mcp":{"get":{"tags":["MCP"],"operationId":"probeMcpServer","summary":"Probe the Swarmz MCP server","description":"Returns a short, unauthenticated server-sent event probe. Use POST for JSON-RPC requests.","responses":{"200":{"description":"MCP probe","content":{"text/event-stream":{"schema":{"type":"string","example":": swarmz mcp probe ok\n\n"}}}}}},"post":{"tags":["MCP"],"operationId":"sendMcpRequest","summary":"Send an MCP JSON-RPC request","description":"Sends a stateless MCP Streamable HTTP request. Accept must list both application/json and text/event-stream. The two media ranges can appear in either order, with other ranges or standard parameters. Supply an access token issued by https://auth.swarmz.net for https://mcp.swarmz.net. OAuth clients must use authorization-code PKCE with S256.","security":[{"OAuth2":[]},{"BearerToken":[]}],"x-required-accept-media-types":["application/json","text/event-stream"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcPostBody"}}}},"responses":{"200":{"description":"MCP JSON-RPC responses framed as a server-sent event stream","content":{"text/event-stream":{"schema":{"type":"string","description":"Server-sent events carrying MCP JSON-RPC messages."}}}},"202":{"description":"Notification accepted"},"400":{"description":"Invalid JSON-RPC or MCP request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcHttpErrorResponse"}}}},"401":{"description":"Missing, expired, revoked, or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcHttpErrorResponse"}}}},"406":{"description":"Accept does not contain both application/json and text/event-stream","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcHttpErrorResponse"}}}},"415":{"description":"Content-Type is not application/json","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcHttpErrorResponse"}}}},"500":{"description":"MCP request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcHttpErrorResponse"}}}},"503":{"description":"MCP is temporarily disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcHttpErrorResponse"}}}}}},"delete":{"tags":["MCP"],"operationId":"deleteMcpSession","summary":"Send an MCP Streamable HTTP DELETE","description":"Passes an authenticated DELETE request to the stateless MCP transport. This deployment does not issue session IDs, so a valid request returns an empty 200 response.","security":[{"OAuth2":[]},{"BearerToken":[]}],"responses":{"200":{"description":"Stateless transport closed"},"400":{"description":"Unsupported MCP protocol version","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcHttpErrorResponse"}}}},"401":{"description":"Missing, expired, revoked, or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcHttpErrorResponse"}}}},"500":{"description":"MCP request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcHttpErrorResponse"}}}},"503":{"description":"MCP is temporarily disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcHttpErrorResponse"}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"tags":["OAuth"],"operationId":"getAuthorizationServerMetadata","summary":"Get Swarmz OAuth authorization-server metadata","responses":{"200":{"description":"OAuth authorization-server metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizationServerMetadata"}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"tags":["OAuth"],"operationId":"getProtectedResourceMetadata","summary":"Get Swarmz MCP protected-resource metadata","responses":{"200":{"description":"OAuth protected-resource metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProtectedResourceMetadata"}}}}}}},"/oauth/register":{"post":{"tags":["OAuth"],"operationId":"registerOAuthClient","summary":"Register a public OAuth client","description":"Registers a public client with no client secret. Redirect URIs must use HTTPS, except loopback localhost URIs may use HTTP.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicClientRegistrationRequest"}}}},"responses":{"201":{"description":"Client registered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicClientRegistrationResponse"}}}},"400":{"description":"Invalid client metadata or redirect URI","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"413":{"description":"Request body exceeds 16 KiB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"429":{"description":"Registration rate limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"500":{"description":"Client registration failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"503":{"description":"The client IP could not be determined","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/oauth/authorize":{"get":{"tags":["OAuth"],"operationId":"authorizeOAuthClient","summary":"Start authorization-code approval","description":"Valid requests create a short-lived authorization request and redirect to the Swarmz consent screen. Validation failures return a JSON OAuth error without redirecting. PKCE with S256 is required on public deployments.","parameters":[{"name":"response_type","in":"query","required":true,"description":"Must be code.","schema":{"type":"string","const":"code"}},{"name":"client_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"redirect_uri","in":"query","required":true,"description":"Must exactly match a redirect URI registered for the client.","schema":{"type":"string","format":"uri"}},{"name":"scope","in":"query","required":false,"description":"Space-separated Swarmz scopes. Unsupported scope names are removed and the read scope is the fallback.","schema":{"type":"string","default":"swarmz:read"}},{"name":"state","in":"query","required":false,"description":"Opaque client state, returned after approval.","schema":{"type":"string","maxLength":1024}},{"name":"code_challenge","in":"query","required":true,"description":"Base64url-encoded PKCE challenge for the S256 verifier method.","schema":{"type":"string","minLength":43,"maxLength":128}},{"name":"code_challenge_method","in":"query","required":false,"description":"Only S256 is accepted. An omitted value is stored as S256.","schema":{"type":"string","const":"S256","default":"S256"}},{"name":"resource","in":"query","required":true,"description":"Must exactly identify the Swarmz MCP protected resource.","schema":{"type":"string","const":"https://mcp.swarmz.net"}}],"responses":{"302":{"description":"Redirect to the Swarmz MCP consent screen","headers":{"Location":{"description":"Swarmz consent-screen URL for the authorization request","schema":{"type":"string","format":"uri"}},"Set-Cookie":{"description":"Short-lived HttpOnly authorization session cookie","schema":{"type":"string"}}}},"400":{"description":"Invalid authorization request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"429":{"description":"Authorization rate limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"500":{"description":"Authorization request could not be stored","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/oauth/token":{"post":{"tags":["OAuth"],"operationId":"exchangeOAuthToken","summary":"Exchange or refresh an OAuth token","description":"Exchanges an authorization code with its PKCE verifier, or rotates a refresh token. The resource must exactly match https://mcp.swarmz.net. The handler accepts form-encoded and JSON objects.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/OAuthTokenRequest"}},"application/json":{"schema":{"$ref":"#/components/schemas/OAuthTokenRequest"}}}},"responses":{"200":{"description":"Access and refresh token pair","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthTokenResponse"}}}},"400":{"description":"Invalid grant, target, request, or grant type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"429":{"description":"Token endpoint rate limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/oauth/revoke":{"post":{"tags":["OAuth"],"operationId":"revokeOAuthToken","summary":"Revoke an OAuth token","description":"Revokes a token for the supplied public client. Unknown tokens and client mismatches also return 200. The handler accepts form-encoded and JSON objects.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/OAuthRevocationRequest"}},"application/json":{"schema":{"$ref":"#/components/schemas/OAuthRevocationRequest"}}}},"responses":{"200":{"description":"Revocation request processed"},"400":{"description":"Invalid revocation request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"413":{"description":"Request body exceeds 16 KiB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"429":{"description":"Revocation endpoint rate limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/api/skills/public":{"get":{"tags":["Skills"],"operationId":"listPublicBuildSkills","summary":"List public build skills","description":"Returns built-in and public technical skills available to anonymous build prompts. Skill bodies and private skills are not returned.","responses":{"200":{"description":"Public build-skill list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSkillsResponse"}}}},"500":{"description":"Skill catalog query failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}}},"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","description":"OAuth 2.0 authorization-code flow for the Swarmz MCP resource. Public clients use PKCE with S256 and do not receive a client secret.","flows":{"authorizationCode":{"authorizationUrl":"https://auth.swarmz.net/oauth/authorize","tokenUrl":"https://auth.swarmz.net/oauth/token","refreshUrl":"https://auth.swarmz.net/oauth/token","scopes":{"swarmz:read":"Read workspaces and projects.","swarmz:write":"Create projects and start builds.","swarmz:deploy":"Publish a project.","swarmz:manage":"Change workspace-managed resources."}}}},"BearerToken":{"type":"http","scheme":"bearer","bearerFormat":"opaque OAuth access token","description":"Bearer token issued by https://auth.swarmz.net/oauth/token for https://mcp.swarmz.net."}},"schemas":{"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"additionalProperties":false},"DynamicClientRegistrationRequest":{"type":"object","required":["redirect_uris"],"properties":{"client_name":{"type":"string","maxLength":64},"redirect_uris":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"string","format":"uri"}},"grant_types":{"type":"array","minItems":1,"items":{"type":"string"},"default":["authorization_code","refresh_token"]},"scope":{"type":"string","default":"swarmz:read"}},"additionalProperties":true},"DynamicClientRegistrationResponse":{"type":"object","required":["client_id","client_name","redirect_uris","grant_types","token_endpoint_auth_method","scope","resource"],"properties":{"client_id":{"type":"string"},"client_name":{"type":["string","null"]},"redirect_uris":{"type":"array","items":{"type":"string","format":"uri"}},"grant_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string","const":"none"},"scope":{"type":"string"},"resource":{"type":"string","const":"https://mcp.swarmz.net"}},"additionalProperties":false},"AuthorizationCodeTokenRequest":{"type":"object","required":["grant_type","code","redirect_uri","client_id","code_verifier","resource"],"properties":{"grant_type":{"type":"string","const":"authorization_code"},"code":{"type":"string"},"redirect_uri":{"type":"string","format":"uri"},"client_id":{"type":"string"},"code_verifier":{"type":"string","minLength":43,"maxLength":128},"resource":{"type":"string","const":"https://mcp.swarmz.net"}},"additionalProperties":true},"RefreshTokenRequest":{"type":"object","required":["grant_type","refresh_token","client_id","resource"],"properties":{"grant_type":{"type":"string","const":"refresh_token"},"refresh_token":{"type":"string"},"client_id":{"type":"string"},"resource":{"type":"string","const":"https://mcp.swarmz.net"}},"additionalProperties":true},"OAuthTokenRequest":{"oneOf":[{"$ref":"#/components/schemas/AuthorizationCodeTokenRequest"},{"$ref":"#/components/schemas/RefreshTokenRequest"}]},"OAuthTokenResponse":{"type":"object","required":["access_token","token_type","expires_in","refresh_token","scope"],"properties":{"access_token":{"type":"string"},"token_type":{"type":"string","const":"Bearer"},"expires_in":{"type":"integer","const":3600},"refresh_token":{"type":"string"},"scope":{"type":"string"}},"additionalProperties":false},"OAuthRevocationRequest":{"type":"object","required":["token","client_id"],"properties":{"token":{"type":"string","minLength":1,"maxLength":256},"token_type_hint":{"type":"string"},"client_id":{"type":"string","minLength":1,"maxLength":128}},"additionalProperties":true},"JsonRpcId":{"oneOf":[{"type":"string"},{"type":"integer"}]},"JsonRpcRequest":{"type":"object","required":["jsonrpc","id","method"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"$ref":"#/components/schemas/JsonRpcId"},"method":{"type":"string","example":"tools/list"},"params":{"type":"object","additionalProperties":true}},"additionalProperties":false},"JsonRpcNotification":{"type":"object","required":["jsonrpc","method"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"method":{"type":"string","example":"notifications/initialized"},"params":{"type":"object","additionalProperties":true}},"additionalProperties":false},"JsonRpcMessage":{"oneOf":[{"$ref":"#/components/schemas/JsonRpcRequest"},{"$ref":"#/components/schemas/JsonRpcNotification"},{"$ref":"#/components/schemas/JsonRpcSuccessResponse"},{"$ref":"#/components/schemas/JsonRpcProtocolErrorResponse"}]},"JsonRpcPostBody":{"oneOf":[{"$ref":"#/components/schemas/JsonRpcMessage"},{"type":"array","items":{"$ref":"#/components/schemas/JsonRpcMessage"}}]},"JsonRpcSuccessResponse":{"type":"object","required":["jsonrpc","result","id"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"result":{"type":"object","additionalProperties":true},"id":{"$ref":"#/components/schemas/JsonRpcId"}},"additionalProperties":false},"JsonRpcProtocolErrorResponse":{"type":"object","required":["jsonrpc","error"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"error":{"$ref":"#/components/schemas/JsonRpcError"},"id":{"$ref":"#/components/schemas/JsonRpcId"}},"additionalProperties":false},"JsonRpcHttpErrorResponse":{"type":"object","required":["jsonrpc","error","id"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"error":{"$ref":"#/components/schemas/JsonRpcError"},"id":{"type":"null"}},"additionalProperties":false},"JsonRpcError":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer"},"message":{"type":"string"},"data":{}},"additionalProperties":true},"AuthorizationServerMetadata":{"type":"object","required":["issuer","authorization_endpoint","token_endpoint","registration_endpoint","revocation_endpoint","response_types_supported","grant_types_supported","code_challenge_methods_supported","token_endpoint_auth_methods_supported","scopes_supported"],"properties":{"issuer":{"type":"string","const":"https://auth.swarmz.net"},"authorization_endpoint":{"type":"string","const":"https://auth.swarmz.net/oauth/authorize"},"token_endpoint":{"type":"string","const":"https://auth.swarmz.net/oauth/token"},"registration_endpoint":{"type":"string","const":"https://auth.swarmz.net/oauth/register"},"revocation_endpoint":{"type":"string","const":"https://auth.swarmz.net/oauth/revoke"},"revocation_endpoint_auth_methods_supported":{"type":"array","items":{"type":"string"}},"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","const":"S256"}},"token_endpoint_auth_methods_supported":{"type":"array","items":{"type":"string","const":"none"}},"scopes_supported":{"type":"array","items":{"type":"string"}}},"additionalProperties":false},"ProtectedResourceMetadata":{"type":"object","required":["resource","authorization_servers","scopes_supported","bearer_methods_supported"],"properties":{"resource":{"type":"string","const":"https://mcp.swarmz.net"},"authorization_servers":{"type":"array","items":{"type":"string","const":"https://auth.swarmz.net"}},"scopes_supported":{"type":"array","items":{"type":"string"}},"bearer_methods_supported":{"type":"array","items":{"type":"string","const":"header"}}},"additionalProperties":false},"PublicSkill":{"type":"object","required":["id","slug","name","description","category","icon","scope","owner_type","visibility","use_count"],"properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"category":{"type":["string","null"]},"icon":{"type":["string","null"]},"scope":{"type":"string","enum":["build","both"]},"owner_type":{"type":"string"},"visibility":{"type":"string","enum":["builtin","public"]},"use_count":{"type":["integer","null"]}},"additionalProperties":false},"PublicSkillsResponse":{"type":"object","required":["skills"],"properties":{"skills":{"type":"array","items":{"$ref":"#/components/schemas/PublicSkill"}}},"additionalProperties":false}}}}