{
  "openapi": "3.0.3",
  "info": {
    "title": "Cloaktail Headless Browser API",
    "description": "API specification for Cloaktail - a stealth headless browser with CDP and MCP support. Cloaktail provides Chrome DevTools Protocol (CDP) endpoints for browser automation and Model Context Protocol (MCP) tools for AI-assisted browsing.",
    "version": "1.0.0",
    "contact": {
      "name": "Cloaktail Team",
      "url": "https://cloaktail.io"
    },
    "license": {
      "name": "AGPL-3.0",
      "url": "https://www.gnu.org/licenses/agpl-3.0.html"
    }
  },
  "servers": [
    {
      "url": "ws://localhost:9222",
      "description": "CDP WebSocket server (default)"
    },
    {
      "url": "http://localhost:9090",
      "description": "MCP HTTP server"
    }
  ],
  "tags": [
    { "name": "CDP Base", "description": "CDP base HTTP endpoints" },
    { "name": "MCP", "description": "Model Context Protocol tools" },
    { "name": "Page", "description": "Page manipulation and navigation (CDP Page domain)" },
    { "name": "Network", "description": "Network request handling (CDP Network domain)" },
    { "name": "Runtime", "description": "JavaScript execution (CDP Runtime domain)" },
    { "name": "DOM", "description": "DOM inspection and manipulation (CDP DOM domain)" },
    { "name": "Performance", "description": "Performance metrics (CDP Performance domain)" },
    { "name": "Target", "description": "Target management (CDP Target domain)" },
    { "name": "Input", "description": "User input simulation (CDP Input domain)" },
    { "name": "Storage", "description": "Storage and cookies (CDP Storage domain)" },
    { "name": "Emulation", "description": "Device emulation (CDP Emulation domain)" },
    { "name": "Log", "description": "Logging and debugging (CDP Log domain)" },
    { "name": "Security", "description": "Security settings (CDP Security domain)" }
  ],
  "paths": {
    "/json": {
      "get": {
        "summary": "List Targets",
        "description": "Returns list of available CDP targets (pages, workers, etc.)",
        "tags": ["CDP Base"],
        "operationId": "listTargets",
        "responses": {
          "200": {
            "description": "List of available targets",
            "content": {
              "application/json": {
                "example": [
                  {
                    "id": "target-id",
                    "type": "page",
                    "url": "about:blank",
                    "webSocketDebuggerUrl": "ws://localhost:9222/devtools/page/target-id",
                    "title": "",
                    "devtoolsFrontendUrl": "/devtools/inspector.html?ws=localhost:9222/devtools/page/target-id"
                  }
                ]
              }
            }
          }
        }
      }
    },
    "/json/version": {
      "get": {
        "summary": "Protocol Version",
        "description": "Returns CDP protocol version information",
        "tags": ["CDP Base"],
        "operationId": "getProtocolVersion",
        "responses": {
          "200": {
            "description": "Version info",
            "content": {
              "application/json": {
                "example": {
                  "Browser": "Cloaktail/1.0.0",
                  "Protocol-Version": "1.3",
                  "User-Agent": "Cloaktail/1.0.0"
                }
              }
            }
          }
        }
      }
    },
    "/json/protocol": {
      "get": {
        "summary": "Protocol JSON",
        "description": "Returns the complete CDP protocol JSON schema",
        "tags": ["CDP Base"],
        "operationId": "getProtocol",
        "responses": {
          "200": {
            "description": "Protocol schema"
          }
        }
      }
    },
    "/metrics": {
      "get": {
        "summary": "Prometheus Metrics",
        "description": "Prometheus-compatible metrics endpoint for monitoring",
        "tags": ["CDP Base"],
        "operationId": "getMetrics",
        "responses": {
          "200": {
            "description": "Metrics in Prometheus format",
            "content": {
              "text/plain": {
                "example": "cloaktail_requests_total 1234\ncloaktail_page_load_duration_ms 1500.5\n"
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "CDPMessage": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "description": "Message ID for correlation" },
          "method": { "type": "string", "description": "CDP method name (e.g., 'Page.navigate')" },
          "params": { "type": "object", "description": "Method parameters" }
        }
      },
      "CDPResponse": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "result": { "type": "object", "description": "Result object" },
          "error": { "$ref": "#/components/schemas/CDPError" }
        }
      },
      "CDPError": {
        "type": "object",
        "properties": {
          "code": { "type": "integer", "description": "Error code (-32000 to -32099)" },
          "message": { "type": "string", "description": "Error message" },
          "data": { "type": "object", "description": "Additional error data" }
        }
      },
      "MCPTool": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "description": { "type": "string" },
          "inputSchema": { "type": "object" }
        }
      },
      "PageNavigateParams": {
        "type": "object",
        "required": ["url"],
        "properties": {
          "url": { "type": "string", "description": "URL to navigate to" }
        },
        "example": {
          "url": "https://example.com"
        }
      },
      "PageCaptureScreenshotParams": {
        "type": "object",
        "properties": {
          "format": { "type": "string", "enum": ["png", "jpeg"], "default": "png" },
          "quality": { "type": "integer", "description": "JPEG quality (0-100)" },
          "clip": { "$ref": "#/components/schemas/Viewport" },
          "fromSurface": { "type": "boolean", "default": true }
        }
      },
      "Viewport": {
        "type": "object",
        "properties": {
          "x": { "type": "number" },
          "y": { "type": "number" },
          "width": { "type": "number" },
          "height": { "type": "number" },
          "scale": { "type": "number", "default": 1 }
        }
      },
      "DOMNode": {
        "type": "object",
        "properties": {
          "nodeId": { "type": "integer" },
          "nodeType": { "type": "integer" },
          "nodeName": { "type": "string" },
          "localName": { "type": "string" },
          "nodeValue": { "type": "string" },
          "children": { "type": "array", "items": { "$ref": "#/components/schemas/DOMNode" } },
          "attributes": { "type": "array", "items": { "type": "string" } }
        }
      },
      "RuntimeEvaluateParams": {
        "type": "object",
        "required": ["expression"],
        "properties": {
          "expression": { "type": "string", "description": "JavaScript expression to evaluate" },
          "returnByValue": { "type": "boolean", "default": false },
          "awaitPromise": { "type": "boolean", "default": false },
          "userGesture": { "type": "boolean", "default": false }
        },
        "example": {
          "expression": "document.title"
        }
      },
      "NetworkSetCookieParams": {
        "type": "object",
        "required": ["name", "value"],
        "properties": {
          "name": { "type": "string" },
          "value": { "type": "string" },
          "url": { "type": "string" },
          "domain": { "type": "string" },
          "path": { "type": "string", "default": "/" },
          "expires": { "type": "number", "description": "Expiration time as Unix timestamp" },
          "secure": { "type": "boolean", "default": false },
          "httpOnly": { "type": "boolean", "default": false },
          "sameSite": { "type": "string", "enum": ["Strict", "Lax", "None"] }
        }
      },
      "PerformanceMetrics": {
        "type": "object",
        "properties": {
          "nodes": { "type": "number", "description": "Number of DOM nodes" },
          "layoutCount": { "type": "number", "description": "Number of layout operations" },
          "styleRecalcCount": { "type": "number", "description": "Number of style recalculations" },
          "layoutDuration": { "type": "number", "description": "Layout duration in ms" },
          "paintDuration": { "type": "number", "description": "Paint duration in ms" },
          "jsHeapUsedSize": { "type": "number", "description": "JS heap used size in bytes" },
          "jsHeapTotalSize": { "type": "number", "description": "JS heap total size in bytes" }
        }
      },
      "MCPToolsListResponse": {
        "type": "object",
        "properties": {
          "tools": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/MCPTool" }
          }
        }
      }
    }
  },
  "x-cdp-methods": {
    "Page": {
      "description": "Page domain for page manipulation",
      "methods": [
        { "name": "Page.enable", "description": "Enables page domain events" },
        { "name": "Page.disable", "description": "Disables page domain events" },
        { "name": "Page.navigate", "description": "Navigates to URL", "params": { "$ref": "#/components/schemas/PageNavigateParams" } },
        { "name": "Page.captureScreenshot", "description": "Captures page screenshot", "params": { "$ref": "#/components/schemas/PageCaptureScreenshotParams" } },
        { "name": "Page.printToPDF", "description": "Prints page to PDF" },
        { "name": "Page.getFrameTree", "description": "Gets frame tree" },
        { "name": "Page.getLayoutMetrics", "description": "Gets layout metrics" }
      ]
    },
    "Runtime": {
      "description": "Runtime domain for JS execution",
      "methods": [
        { "name": "Runtime.enable", "description": "Enables runtime domain" },
        { "name": "Runtime.evaluate", "description": "Evaluates JavaScript", "params": { "$ref": "#/components/schemas/RuntimeEvaluateParams" } },
        { "name": "Runtime.callFunctionOn", "description": "Calls function on object" },
        { "name": "Runtime.getProperties", "description": "Gets object properties" },
        { "name": "Runtime.releaseObject", "description": "Releases object" }
      ]
    },
    "DOM": {
      "description": "DOM domain for DOM manipulation",
      "methods": [
        { "name": "DOM.enable", "description": "Enables DOM domain" },
        { "name": "DOM.getDocument", "description": "Gets document node" },
        { "name": "DOM.querySelector", "description": "Query selector single node" },
        { "name": "DOM.querySelectorAll", "description": "Query selector all nodes" },
        { "name": "DOM.getOuterHTML", "description": "Gets outer HTML" },
        { "name": "DOM.setOuterHTML", "description": "Sets outer HTML" },
        { "name": "DOM.getBoxModel", "description": "Gets box model" },
        { "name": "DOM.resolveNode", "description": "Resolves node to backend node" }
      ]
    },
    "Network": {
      "description": "Network domain for request handling",
      "methods": [
        { "name": "Network.enable", "description": "Enables network tracking" },
        { "name": "Network.disable", "description": "Disables network tracking" },
        { "name": "Network.setUserAgentOverride", "description": "Sets user agent" },
        { "name": "Network.setExtraHTTPHeaders", "description": "Sets extra HTTP headers" },
        { "name": "Network.setCookie", "description": "Sets cookie", "params": { "$ref": "#/components/schemas/NetworkSetCookieParams" } },
        { "name": "Network.getCookies", "description": "Gets all cookies" },
        { "name": "Network.deleteCookies", "description": "Deletes cookies" },
        { "name": "Network.clearBrowserCookies", "description": "Clears all browser cookies" },
        { "name": "Network.getResponseBody", "description": "Gets response body" }
      ]
    },
    "Performance": {
      "description": "Performance domain for metrics",
      "methods": [
        { "name": "Performance.enable", "description": "Enables performance metrics" },
        { "name": "Performance.disable", "description": "Disables performance metrics" },
        { "name": "Performance.getMetrics", "description": "Gets performance metrics", "returns": { "$ref": "#/components/schemas/PerformanceMetrics" } }
      ]
    },
    "Input": {
      "description": "Input domain for user interaction",
      "methods": [
        { "name": "Input.dispatchMouseEvent", "description": "Dispatches mouse event" },
        { "name": "Input.dispatchKeyEvent", "description": "Dispatches keyboard event" }
      ]
    },
    "Storage": {
      "description": "Storage domain for storage management",
      "methods": [
        { "name": "Storage.enable", "description": "Enables storage tracking" },
        { "name": "Storage.clearDataForOrigin", "description": "Clears data for origin" },
        { "name": "Storage.getStorageKeyForFrame", "description": "Gets storage key" }
      ]
    },
    "Target": {
      "description": "Target domain for target management",
      "methods": [
        { "name": "Target.setAutoAttach", "description": "Sets auto-attach behavior" },
        { "name": "Target.createTarget", "description": "Creates new target" }
      ]
    },
    "Emulation": {
      "description": "Emulation domain for device emulation",
      "methods": [
        { "name": "Emulation.setDeviceMetricsOverride", "description": "Sets device metrics" },
        { "name": "Emulation.setViewportOverride", "description": "Sets viewport override" }
      ]
    }
  },
  "x-mcp-tools": [
    {
      "name": "goto",
      "description": "Navigate to a specified URL and load the page in memory so it can be reused later for info extraction.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": { "type": "string", "description": "The URL to navigate to, must be a valid URL." }
        },
        "required": ["url"]
      }
    },
    {
      "name": "markdown",
      "description": "Get the page content in markdown format. If a url is provided, it navigates to that url first.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": { "type": "string", "description": "Optional URL to navigate to before fetching markdown." }
        }
      }
    },
    {
      "name": "links",
      "description": "Extract all links in the opened page. If a url is provided, it navigates to that url first.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": { "type": "string", "description": "Optional URL to navigate to before extracting links." }
        }
      }
    },
    {
      "name": "evaluate",
      "description": "Evaluate JavaScript in the current page context. If a url is provided, it navigates to that url first.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "script": { "type": "string" },
          "url": { "type": "string", "description": "Optional URL to navigate to before evaluating." }
        },
        "required": ["script"]
      }
    },
    {
      "name": "semantic_tree",
      "description": "Get the page content as a simplified semantic DOM tree for AI reasoning. If a url is provided, it navigates to that url first.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": { "type": "string", "description": "Optional URL to navigate to before fetching the semantic tree." },
          "backendNodeId": { "type": "integer", "description": "Optional backend node ID to get the tree for a specific element instead of the document root." },
          "maxDepth": { "type": "integer", "description": "Optional maximum depth of the tree to return. Useful for exploring high-level structure first." }
        }
      }
    },
    {
      "name": "interactiveElements",
      "description": "Extract interactive elements from the opened page. If a url is provided, it navigates to that url first.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": { "type": "string", "description": "Optional URL to navigate to before extracting interactive elements." }
        }
      }
    },
    {
      "name": "structuredData",
      "description": "Extract structured data (like JSON-LD, OpenGraph, etc) from the opened page. If a url is provided, it navigates to that url first.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": { "type": "string", "description": "Optional URL to navigate to before extracting structured data." }
        }
      }
    },
    {
      "name": "click",
      "description": "Click on an interactive element. Returns the current page URL and title after the click.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "backendNodeId": { "type": "integer", "description": "The backend node ID of the element to click." }
        },
        "required": ["backendNodeId"]
      }
    },
    {
      "name": "fill",
      "description": "Fill text into an input element. Returns the filled value and current page URL and title.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "backendNodeId": { "type": "integer", "description": "The backend node ID of the input element to fill." },
          "text": { "type": "string", "description": "The text to fill into the input element." }
        },
        "required": ["backendNodeId", "text"]
      }
    },
    {
      "name": "scroll",
      "description": "Scroll the page or a specific element. Returns the scroll position and current page URL and title.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "backendNodeId": { "type": "integer", "description": "Optional: The backend node ID of the element to scroll. If omitted, scrolls the window." },
          "x": { "type": "integer", "description": "Optional: The horizontal scroll offset." },
          "y": { "type": "integer", "description": "Optional: The vertical scroll offset." }
        }
      }
    },
    {
      "name": "waitForSelector",
      "description": "Wait for an element matching a CSS selector to appear in the page. Returns the backend node ID of the matched element.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "selector": { "type": "string", "description": "The CSS selector to wait for." },
          "timeout": { "type": "integer", "description": "Optional timeout in milliseconds. Defaults to 5000." }
        },
        "required": ["selector"]
      }
    }
  ]
}