{
  "openapi": "3.1.1",
  "info": {
    "title": "Quotae MCP API",
    "version": "1.0.0",
    "description": "Authenticated MCP integration for Quotae. Controlled rollout with preregistered OAuth clients and native owner approval. Internal mobile REST endpoints are outside this contract.",
    "contact": { "name": "Quotae support", "email": "use@quotae.app", "url": "https://quotae.app/en/contact/" },
    "termsOfService": "https://quotae.app/en/terms/"
  },
  "externalDocs": { "description": "Quotae API documentation", "url": "https://quotae.app/docs/" },
  "servers": [{ "url": "https://api.quotae.app" }],
  "paths": {
    "/.well-known/oauth-protected-resource/mcp": {
      "get": {
        "operationId": "getMcpResourceMetadata",
        "summary": "Discover MCP authorization servers and supported scopes",
        "security": [],
        "responses": {
          "200": {
            "description": "RFC 9728 protected-resource metadata for https://api.quotae.app/mcp",
            "content": { "application/json": { "schema": {
              "type": "object",
              "required": ["resource", "authorization_servers", "scopes_supported", "bearer_methods_supported"],
              "properties": {
                "resource": { "type": "string", "const": "https://api.quotae.app/mcp" },
                "authorization_servers": { "type": "array", "items": { "type": "string", "format": "uri" }, "minItems": 1 },
                "scopes_supported": { "type": "array", "items": { "type": "string" } },
                "bearer_methods_supported": { "type": "array", "items": { "type": "string", "enum": ["header"] } }
              }
            } } }
          },
          "429": { "description": "Rate limit reached" },
          "503": { "description": "Integration disabled or temporarily unavailable" }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "sendMcpMessage",
        "summary": "Send an authenticated MCP JSON-RPC message",
        "description": "Streamable HTTP. Send Accept: application/json, text/event-stream and the negotiated MCP-Protocol-Version after initialization. Complete initialize and notifications/initialized before tools/list or tools/call. Each tool's _meta.securitySchemes declares its required scope. The OAuth requirement here authenticates the transport; it does not grant every tool permission.",
        "externalDocs": { "description": "Quotae MCP tools and scope requirements", "url": "https://quotae.app/mcp/" },
        "security": [{ "QuotaeOAuth": [] }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": {
            "type": "object",
            "required": ["jsonrpc", "method"],
            "properties": {
              "jsonrpc": { "const": "2.0" },
              "id": { "type": ["string", "integer"] },
              "method": { "type": "string" },
              "params": { "type": "object" }
            }
          } } }
        },
        "responses": {
          "200": {
            "description": "MCP response; tool errors can appear in a successful JSON-RPC response",
            "content": {
              "application/json": { "schema": { "type": "object", "required": ["jsonrpc", "id"], "properties": { "jsonrpc": { "const": "2.0" }, "id": { "type": ["string", "integer", "null"] }, "result": { "type": "object" }, "error": { "type": "object" } } } },
              "text/event-stream": { "schema": { "type": "string" } }
            }
          },
          "202": { "description": "Notification accepted with no response body" },
          "400": { "description": "Invalid MCP message or protocol version" },
          "401": { "description": "Missing or invalid MCP token", "headers": { "WWW-Authenticate": { "schema": { "type": "string" }, "example": "Bearer resource_metadata=\"https://api.quotae.app/.well-known/oauth-protected-resource/mcp\"" } } },
          "403": { "description": "Origin or account access denied" },
          "406": { "description": "Client must accept application/json and text/event-stream" },
          "413": { "description": "Request exceeds 64 KiB" },
          "415": { "description": "Content-Type must be application/json" },
          "429": { "description": "Rate limit reached" },
          "503": { "description": "Integration disabled or temporarily unavailable" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "QuotaeOAuth": {
        "type": "oauth2",
        "description": "Preregistered OAuth client, PKCE S256 and explicit native approval. Request only needed scopes. Resource audience: https://api.quotae.app/mcp. No public API keys or dynamic registration.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://use.quotae.app/oauth/authorize",
            "tokenUrl": "https://api.quotae.app/oauth/token",
            "scopes": {
              "account:read": "Read business setup, defaults and available actions",
              "clients:read": "Search saved clients and addresses",
              "catalog:read": "Search saved catalogue items and prices",
              "quotes:read": "List and read quotes",
              "quotes:drafts:write": "Create or edit eligible unsent quote drafts and recover operations",
              "invoices:read": "List and read invoices and recorded payment facts",
              "reports:read": "Read reports and contributing entries"
            }
          }
        }
      }
    }
  }
}
