{
  "openapi": "3.1.0",
  "info": {
    "title": "CapsAI MCP Server API",
    "version": "2026-11-02",
    "summary": "Caption videos from an AI agent through CapsAI's Model Context Protocol server.",
    "description": "CapsAI's MCP server lets an agent caption a user's video, check the job, restyle the result, read the SRT transcript and see the account's minute balance. Transport: Model Context Protocol over Streamable HTTP at https://mcp.capsai.co/mcp. Authentication: OAuth 2.1 authorization code with PKCE; clients register dynamically. Limits: videos up to 10 minutes, MP4, MOV, M4V, WebM files, one file per job. There is no separate REST API.",
    "termsOfService": "https://capsai.co/terms-and-conditions",
    "contact": {
      "name": "CapsAI support",
      "email": "support@capsai.co",
      "url": "https://capsai.co/contact-us"
    }
  },
  "externalDocs": {
    "description": "CapsAI MCP server page",
    "url": "https://capsai.co/mcp"
  },
  "servers": [
    {
      "url": "https://mcp.capsai.co"
    }
  ],
  "security": [
    {
      "oauth2": [
        "captions"
      ]
    }
  ],
  "paths": {
    "/mcp": {
      "post": {
        "operationId": "mcp",
        "summary": "MCP endpoint (JSON-RPC 2.0 over Streamable HTTP)",
        "description": "Send MCP JSON-RPC messages. Without a valid bearer token the server answers 401 with a WWW-Authenticate header whose resource_metadata points at the RFC 9728 document below.",
        "security": [
          {
            "oauth2": [
              "captions"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response, as JSON or as a server-sent event stream.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid token.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "Bearer error=\"invalid_token\", resource_metadata=\"https://mcp.capsai.co/.well-known/oauth-protected-resource/mcp\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-protected-resource/mcp": {
      "get": {
        "operationId": "protectedResourceMetadata",
        "summary": "Protected resource metadata (RFC 9728)",
        "security": [],
        "responses": {
          "200": {
            "description": "resource, authorization_servers, scopes_supported, bearer_methods_supported.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProtectedResourceMetadata"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-authorization-server": {
      "get": {
        "operationId": "authorizationServerMetadata",
        "summary": "Authorization server metadata (RFC 8414)",
        "security": [],
        "responses": {
          "200": {
            "description": "Endpoints, scopes_supported, grant types and PKCE methods.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/register": {
      "post": {
        "operationId": "registerClient",
        "summary": "Dynamic client registration (RFC 7591)",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "client_name": {
                    "type": "string"
                  },
                  "redirect_uris": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "client_id and client_secret for the new client.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/authorize": {
      "get": {
        "operationId": "authorize",
        "summary": "OAuth 2.1 authorization endpoint (PKCE S256 required)",
        "security": [],
        "responses": {
          "302": {
            "description": "Redirects to redirect_uri with a code after the user signs in to CapsAI."
          }
        }
      }
    },
    "/token": {
      "post": {
        "operationId": "token",
        "summary": "OAuth 2.1 token endpoint",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "authorization_code",
                      "refresh_token"
                    ]
                  },
                  "code": {
                    "type": "string"
                  },
                  "code_verifier": {
                    "type": "string"
                  },
                  "refresh_token": {
                    "type": "string"
                  },
                  "client_id": {
                    "type": "string"
                  },
                  "client_secret": {
                    "type": "string"
                  },
                  "redirect_uri": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "access_token, token_type, expires_in, refresh_token, scope.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/revoke": {
      "post": {
        "operationId": "revoke",
        "summary": "Token revocation (RFC 7009)",
        "security": [],
        "responses": {
          "200": {
            "description": "The token is revoked."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "oauth2": {
        "type": "oauth2",
        "description": "OAuth 2.1 authorization code flow with PKCE (S256). Clients register at https://mcp.capsai.co/register. Metadata: https://mcp.capsai.co/.well-known/oauth-authorization-server",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://mcp.capsai.co/authorize",
            "tokenUrl": "https://mcp.capsai.co/token",
            "refreshUrl": "https://mcp.capsai.co/token",
            "scopes": {
              "captions": "Caption, restyle and read the signed-in user's own CapsAI videos, transcripts and minute balance."
            }
          }
        }
      }
    },
    "schemas": {
      "JsonRpcRequest": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ]
          },
          "method": {
            "type": "string",
            "description": "An MCP method, for example initialize, tools/list or tools/call."
          },
          "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": {}
            }
          }
        }
      },
      "OAuthError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "error_description": {
            "type": "string"
          }
        }
      },
      "ProtectedResourceMetadata": {
        "type": "object",
        "properties": {
          "resource": {
            "type": "string",
            "format": "uri"
          },
          "authorization_servers": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "scopes_supported": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "captions"
              ]
            }
          },
          "bearer_methods_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    }
  },
  "x-mcp-tools": [
    {
      "name": "get_account",
      "description": "The signed-in CapsAI account: minutes left for captioning, plan and limits.",
      "usesMinutes": false,
      "scope": "captions",
      "inputSchema": {
        "type": "object",
        "required": [],
        "properties": {}
      }
    },
    {
      "name": "list_caption_styles",
      "description": "CapsAI's caption styles as previews. Each style's id is the value the style parameter takes; available is false for Pro styles on a free plan.",
      "usesMinutes": false,
      "scope": "captions",
      "inputSchema": {
        "type": "object",
        "required": [],
        "properties": {}
      }
    },
    {
      "name": "caption_video",
      "description": "Starts a captioning job for a video file and returns an upload: a presigned HTTP PUT URL with the exact headers to send, an equivalent curl command, and a browser upload page. Transcription uses the account's minutes, one per minute of video.",
      "usesMinutes": true,
      "scope": "captions",
      "inputSchema": {
        "type": "object",
        "required": [],
        "properties": {
          "file_name": {
            "description": "The video's file name, for example vlog.mp4 (mp4, mov, m4v or webm).",
            "x-type": "string"
          },
          "file_size_bytes": {
            "description": "Exact file size in bytes, if known. The upload must then match it exactly.",
            "x-type": "integer"
          },
          "language": {
            "description": "Spoken language as an ISO code (en, hi, ...) or \"hinglish\" for Hindi written in Latin script.",
            "x-type": "string"
          },
          "style": {
            "description": "Caption style id from list_caption_styles. Defaults to the account's default style.",
            "x-type": "string"
          },
          "animated": {
            "description": "true for animated word-by-word captions, false for plain static subtitles.",
            "x-type": "boolean"
          },
          "words_per_caption": {
            "description": "Words on screen at once, 1 to 4.",
            "x-type": "integer"
          },
          "position": {
            "description": "Where captions sit on the frame.",
            "x-type": "\"top\" | \"middle\" | \"bottom\""
          }
        }
      }
    },
    {
      "name": "check_caption_job",
      "description": "Status of a caption job, moving it to the next step when ready: the render starts once transcription is done. Returns a download link when the video is finished.",
      "usesMinutes": false,
      "scope": "captions",
      "inputSchema": {
        "type": "object",
        "required": [
          "project_id"
        ],
        "properties": {
          "project_id": {
            "description": "The projectId from caption_video.",
            "x-type": "string"
          }
        }
      }
    },
    {
      "name": "restyle_video",
      "description": "Renders an already transcribed video again with a different caption look. Re-renders cost the video's length in minutes; the first render is free. Omitted settings keep their current value.",
      "usesMinutes": true,
      "scope": "captions",
      "inputSchema": {
        "type": "object",
        "required": [
          "project_id"
        ],
        "properties": {
          "project_id": {
            "description": "The projectId from caption_video.",
            "x-type": "string"
          },
          "style": {
            "description": "Caption style id from list_caption_styles.",
            "x-type": "string"
          },
          "animated": {
            "description": "true for animated captions, false for plain static subtitles.",
            "x-type": "boolean"
          },
          "words_per_caption": {
            "description": "Words on screen at once, 1 to 4.",
            "x-type": "integer"
          },
          "position": {
            "description": "Where captions sit on the frame.",
            "x-type": "\"top\" | \"middle\" | \"bottom\""
          }
        }
      }
    },
    {
      "name": "get_transcript",
      "description": "The video's transcript as SRT subtitles, available once it is transcribed.",
      "usesMinutes": false,
      "scope": "captions",
      "inputSchema": {
        "type": "object",
        "required": [
          "project_id"
        ],
        "properties": {
          "project_id": {
            "description": "The projectId from caption_video.",
            "x-type": "string"
          }
        }
      }
    },
    {
      "name": "list_videos",
      "description": "The user's most recent CapsAI projects, newest first.",
      "usesMinutes": false,
      "scope": "captions",
      "inputSchema": {
        "type": "object",
        "required": [],
        "properties": {
          "limit": {
            "description": "How many to return, 1 to 50.",
            "x-type": "integer"
          }
        }
      }
    }
  ]
}