{
  "openapi": "3.1.0",
  "info": {
    "title": "XCut AI MCP server",
    "version": "1.0.0",
    "summary": "Remote Model Context Protocol server for XCut AI: outlier posts, Meta Ad Library research, video breakdowns, and scripts written with brand memory.",
    "description": "XCut AI exposes its agent-facing API as a remote MCP server (Streamable HTTP, JSON-RPC 2.0). Hook templates, playbooks and quick tools work without an account; tools that read or change the user's XCut AI canvases, brand memory, imports or credits require an OAuth 2.1 access token carrying the scopes below, or a personal API key from XCut AI Settings → Connected apps. Tool and prompt names, schemas and per-tool scopes come from the server itself (tools/list after initialize); this document declares the machine-readable security model. Setup guide: https://xcut.ai/mcp. Agent index: https://xcut.ai/llms.txt.",
    "termsOfService": "https://xcut.ai/terms-conditions",
    "contact": { "name": "XCut AI", "url": "https://xcut.ai/mcp", "email": "info@xcut.ai" }
  },
  "externalDocs": {
    "description": "How to connect XCut AI to ChatGPT, Claude, Grok, Meta Muse, Gemini and other MCP clients",
    "url": "https://xcut.ai/mcp"
  },
  "servers": [
    { "url": "https://mcp.xcut.ai", "description": "Production. OAuth 2.1 metadata: /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource (RFC 9728)." }
  ],
  "security": [
    { "oauth2": ["xcut.read"] },
    { "apiKey": [] },
    {}
  ],
  "paths": {
    "/mcp": {
      "post": {
        "operationId": "mcp",
        "summary": "MCP endpoint (full build, with AI image generation)",
        "description": "Streamable HTTP transport. Send one JSON-RPC 2.0 request per POST: initialize, tools/list, tools/call, prompts/list, prompts/get, resources/list. Stateless: no session header is needed. Anonymous calls may use the free tools; a call to a tool that needs an account answers 401 with WWW-Authenticate: Bearer resource_metadata=\"https://mcp.xcut.ai/.well-known/oauth-protected-resource/mcp\" and the scope it requires.",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JsonRpcRequest" } } }
        },
        "responses": {
          "200": { "description": "JSON-RPC 2.0 response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JsonRpcResponse" } } } },
          "401": { "description": "Sign-in required for this tool. WWW-Authenticate names the protected-resource metadata URL and the missing scope.", "$ref": "#/components/responses/Unauthorized" },
          "403": { "description": "Token lacks the scope this tool requires (insufficient_scope)." },
          "429": { "description": "Rate limit reached (per user, or the shared anonymous allowance)." }
        },
        "security": [ { "oauth2": ["xcut.read", "xcut.write"] }, { "apiKey": [] }, {} ]
      }
    },
    "/claude/mcp": {
      "post": {
        "operationId": "mcpClaude",
        "summary": "MCP endpoint (Claude build: same server without AI image generation)",
        "description": "Identical transport and auth to /mcp. Its protected-resource metadata is at /.well-known/oauth-protected-resource/claude/mcp.",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JsonRpcRequest" } } }
        },
        "responses": {
          "200": { "description": "JSON-RPC 2.0 response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JsonRpcResponse" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "description": "Token lacks the scope this tool requires (insufficient_scope)." },
          "429": { "description": "Rate limit reached." }
        },
        "security": [ { "oauth2": ["xcut.read", "xcut.write"] }, { "apiKey": [] }, {} ]
      }
    },
    "/.well-known/oauth-protected-resource": {
      "get": {
        "operationId": "protectedResourceMetadata",
        "summary": "RFC 9728 protected-resource metadata (scopes_supported, authorization_servers)",
        "security": [ {} ],
        "responses": { "200": { "description": "JSON metadata document", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },
    "/.well-known/oauth-authorization-server": {
      "get": {
        "operationId": "authorizationServerMetadata",
        "summary": "RFC 8414 authorization-server metadata (PKCE S256, dynamic client registration, client ID metadata documents)",
        "security": [ {} ],
        "responses": { "200": { "description": "JSON metadata document", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "oauth2": {
        "type": "oauth2",
        "description": "OAuth 2.1 authorization code with PKCE (S256). Public clients register dynamically at the registration endpoint or present a client ID metadata document. Request only the scopes the task needs: xcut.read for research and reading the user's workspace, xcut.write for anything that imports, runs an agent, or adds to a canvas or calendar and therefore spends credits. offline_access adds a refresh token.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://mcp.xcut.ai/oauth/authorize",
            "tokenUrl": "https://mcp.xcut.ai/oauth/token",
            "refreshUrl": "https://mcp.xcut.ai/oauth/token",
            "scopes": {
              "xcut.read": "See the user's canvases, brand memory, calendar, imported content and credit balance",
              "xcut.write": "Import content, run analyses and agents, and add to the user's canvases and calendar, using their credits",
              "offline_access": "Receive a refresh token so the connection survives the access token's expiry"
            }
          }
        }
      },
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Personal API key created in XCut AI under Settings → Connected apps, sent as Authorization: Bearer <key>. For clients that cannot complete the OAuth flow (for example Meta Muse custom connectors). A key authenticates as the account that created it and carries the scopes (xcut.read, xcut.write) assigned to it when it was created; it can be revoked in the same settings page."
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "No credentials, or credentials that do not cover this tool. The WWW-Authenticate header follows RFC 9728 §5.1: Bearer resource_metadata=\"<metadata URL>\", scope=\"<required scope>\".",
        "headers": {
          "WWW-Authenticate": { "schema": { "type": "string" }, "example": "Bearer resource_metadata=\"https://mcp.xcut.ai/.well-known/oauth-protected-resource/mcp\", scope=\"xcut.read\"" }
        }
      }
    },
    "schemas": {
      "JsonRpcRequest": {
        "type": "object",
        "required": ["jsonrpc", "method"],
        "properties": {
          "jsonrpc": { "type": "string", "const": "2.0" },
          "id": { "oneOf": [ { "type": "string" }, { "type": "integer" } ] },
          "method": { "type": "string", "examples": ["initialize", "tools/list", "tools/call", "prompts/list", "resources/list"] },
          "params": { "type": "object" }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": ["jsonrpc"],
        "properties": {
          "jsonrpc": { "type": "string", "const": "2.0" },
          "id": { "oneOf": [ { "type": "string" }, { "type": "integer" }, { "type": "null" } ] },
          "result": { "type": "object" },
          "error": { "type": "object", "properties": { "code": { "type": "integer" }, "message": { "type": "string" }, "data": {} } }
        }
      }
    }
  }
}
