{
  "openapi": "3.1.0",
  "info": {
    "title": "discap.bot website: agent files and MCP endpoint",
    "version": "2.0.0",
    "description": "What the public discap.bot website serves to agents. Discap is a Discord bot that records voice calls and posts recaps; this is not an API to Discap's product data. A server's recaps, transcripts and audio stay inside Discord and nothing here returns them. Four entries are static files served as they are; /api/markdown and /mcp are small read-only functions of the website. None needs a key, a token or a signup, and all are free. Docs: https://discap.bot/docs/api",
    "contact": {
      "name": "Discap support",
      "email": "support@discap.bot",
      "url": "https://discap.bot/contact"
    },
    "termsOfService": "https://discap.bot/terms"
  },
  "servers": [
    {
      "url": "https://discap.bot"
    }
  ],
  "externalDocs": {
    "description": "Docs with curl examples",
    "url": "https://discap.bot/docs/api"
  },
  "security": [],
  "paths": {
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "Product facts for language models (static file)",
        "description": "A static plain-text file: what Discap does, its pages, its slash commands and the discovery files for agents.",
        "responses": {
          "200": {
            "description": "The llms.txt file.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                },
                "example": "# Discap\n\n> Discap is a Discord bot that records voice calls and turns them into notes. It joins a voice channel, transcribes each speaker, and when the call ends posts a recap (summary, decisions, action items, open questions), the full transcript and the audio to the server. It is free.\n"
              }
            }
          }
        }
      }
    },
    "/.well-known/api-catalog": {
      "get": {
        "operationId": "getApiCatalog",
        "summary": "API catalog, RFC 9727 linkset (static file)",
        "description": "A static linkset that points to this OpenAPI file, the MCP server card, the docs page and llms.txt.",
        "responses": {
          "200": {
            "description": "The API catalog.",
            "content": {
              "application/linkset+json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "linkset"
                  ],
                  "properties": {
                    "linkset": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                },
                "example": {
                  "linkset": [
                    {
                      "anchor": "https://discap.bot/",
                      "service-desc": [
                        {
                          "href": "https://discap.bot/openapi.json",
                          "type": "application/json"
                        },
                        {
                          "href": "https://discap.bot/.well-known/mcp/server-card.json",
                          "type": "application/json"
                        }
                      ],
                      "service-doc": [
                        {
                          "href": "https://discap.bot/docs/api",
                          "type": "text/html"
                        },
                        {
                          "href": "https://discap.bot/llms.txt",
                          "type": "text/plain"
                        }
                      ],
                      "status": [
                        {
                          "href": "https://discap.bot/"
                        }
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/mcp/server-card.json": {
      "get": {
        "operationId": "getMcpServerCard",
        "summary": "MCP server card (static file)",
        "description": "A static JSON card that describes the MCP server at /mcp: its transport, protocol version, tools, and that it needs no authentication.",
        "responses": {
          "200": {
            "description": "The server card.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "serverInfo",
                    "url",
                    "transport",
                    "capabilities"
                  ],
                  "properties": {
                    "serverInfo": {
                      "type": "object"
                    },
                    "description": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "transport": {
                      "type": "object"
                    },
                    "protocolVersion": {
                      "type": "string"
                    },
                    "capabilities": {
                      "type": "object"
                    },
                    "authentication": {
                      "type": "object"
                    },
                    "tools": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                },
                "example": {
                  "serverInfo": {
                    "name": "discap",
                    "title": "Discap website",
                    "version": "1.0.0"
                  },
                  "description": "Read-only MCP server for the public discap.bot website: Discap product facts and the site's public pages. No sign-in, no signup, free. It has no access to any Discord server, recording, transcript or recap.",
                  "url": "https://discap.bot/mcp",
                  "transport": {
                    "type": "streamable-http",
                    "url": "https://discap.bot/mcp"
                  },
                  "protocolVersion": "2025-11-25",
                  "capabilities": {
                    "tools": {
                      "listChanged": false
                    }
                  },
                  "authentication": {
                    "required": false
                  },
                  "tools": [
                    {
                      "name": "get_product_info",
                      "description": "What Discap is, who makes it, what it costs, its slash commands and the main links."
                    },
                    {
                      "name": "list_public_pages",
                      "description": "Lists the public pages of discap.bot from its sitemap, optionally by section."
                    },
                    {
                      "name": "search_public_pages",
                      "description": "Finds discap.bot pages whose title, description or address match a query."
                    }
                  ],
                  "documentationUrl": "https://discap.bot/docs/api"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/agent-skills/index.json": {
      "get": {
        "operationId": "getAgentSkillsIndex",
        "summary": "Agent skills index (static file)",
        "description": "A static index of two SKILL.md files, each with the sha256 digest of its exact bytes.",
        "responses": {
          "200": {
            "description": "The skills index.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "skills"
                  ],
                  "properties": {
                    "skills": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                },
                "example": {
                  "$schema": "https://schemas.agentskills.io/discovery/0.2.0/schema.json",
                  "skills": [
                    {
                      "name": "add-discap-to-discord",
                      "type": "skill-md",
                      "description": "Add the Discap bot to a Discord server so it records and recaps voice calls.",
                      "url": "/.well-known/agent-skills/add-discap-to-discord/SKILL.md",
                      "digest": "sha256:e3ba3abae78891c4ba6f5a1d51734e310b4f60f8ad1385fc9de9af0933b40ade"
                    },
                    {
                      "name": "discap-recording-controls",
                      "type": "skill-md",
                      "description": "Explain how members of a Discord server stop, pause or keep their voice out of a Discap recording.",
                      "url": "/.well-known/agent-skills/discap-recording-controls/SKILL.md",
                      "digest": "sha256:84ac20131a9156769d41624a0e937f6c4ac24a0cca7931d399fa0375699411a4"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/markdown": {
      "get": {
        "operationId": "getPageMarkdown",
        "summary": "A page of this site as markdown (function)",
        "description": "Converts one page of discap.bot to markdown. Sending `Accept: text/markdown` to a page URL gives the same result. It only reads pages of this site, never another host. Answers are `private` and keep the page's own `X-Robots-Tag`. A missing page answers 404 with a short markdown body that points at llms.txt and the sitemap.",
        "parameters": [
          {
            "name": "path",
            "in": "query",
            "required": true,
            "description": "An absolute path on discap.bot, such as /about or /docs/api.",
            "schema": {
              "type": "string",
              "pattern": "^/"
            },
            "example": "/about"
          }
        ],
        "responses": {
          "200": {
            "description": "The page as markdown.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                },
                "example": "About\n\n# About Discap\n\nDiscap is a Discord bot that turns voice calls into notes. It joins a voice channel when people start talking, records each speaker on their own track, and writes down what was said as the call goes.\n"
              }
            }
          },
          "400": {
            "description": "The path is not a plain absolute path on this site."
          },
          "404": {
            "description": "No page at that path.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                },
                "example": "# Page not found\n\nThere is no page at /nope on discap.bot. It may have moved or never existed.\n\nMore: https://discap.bot/llms.txt and https://discap.bot/sitemap.xml\n"
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "postMcpMessage",
        "summary": "MCP server, Streamable HTTP (function)",
        "description": "A stateless, read-only MCP server. POST one JSON-RPC 2.0 message per request with `Content-Type: application/json` and `Accept: application/json, text/event-stream`; the answer is always one JSON object, never an SSE stream. Methods: initialize, ping, tools/list, tools/call. Tools: get_product_info, list_public_pages, search_public_pages; they read only the site's own public pages and product facts. No session id is issued. GET and other methods answer 405. A browser Origin other than discap.bot answers 403.",
        "parameters": [
          {
            "name": "MCP-Protocol-Version",
            "in": "header",
            "required": false,
            "description": "The negotiated protocol version. An unsupported value answers 400.",
            "schema": {
              "type": "string",
              "enum": [
                "2025-11-25",
                "2025-06-18",
                "2025-03-26"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jsonrpc",
                  "method"
                ],
                "maxProperties": 4,
                "properties": {
                  "jsonrpc": {
                    "const": "2.0"
                  },
                  "id": {
                    "type": [
                      "string",
                      "integer"
                    ]
                  },
                  "method": {
                    "type": "string"
                  },
                  "params": {
                    "type": "object"
                  }
                }
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tools/call",
                "params": {
                  "name": "search_public_pages",
                  "arguments": {
                    "query": "consent"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The JSON-RPC response: a result, or a JSON-RPC error such as -32601 (method not found) or -32602 (unknown tool).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "jsonrpc",
                    "id"
                  ],
                  "properties": {
                    "jsonrpc": {
                      "const": "2.0"
                    },
                    "id": {
                      "type": [
                        "string",
                        "integer"
                      ]
                    },
                    "result": {
                      "type": "object"
                    },
                    "error": {
                      "type": "object"
                    }
                  }
                },
                "example": {
                  "jsonrpc": "2.0",
                  "id": 1,
                  "result": {
                    "protocolVersion": "2025-11-25",
                    "capabilities": {
                      "tools": {
                        "listChanged": false
                      }
                    },
                    "serverInfo": {
                      "name": "discap",
                      "title": "Discap website",
                      "version": "1.0.0",
                      "websiteUrl": "https://discap.bot/docs/api"
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "A notification (for example notifications/initialized) was accepted. No body."
          },
          "400": {
            "description": "Not one valid JSON-RPC 2.0 message (parse error -32700 or invalid request -32600), a batch, or an unsupported MCP-Protocol-Version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcError"
                }
              }
            }
          },
          "403": {
            "description": "The Origin header names another site.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcError"
                }
              }
            }
          },
          "405": {
            "description": "Only POST is supported.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcError"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header does not list both application/json and text/event-stream.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcError"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than 16384 bytes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcError"
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type is not application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "JsonRpcError": {
        "type": "object",
        "required": [
          "jsonrpc",
          "id",
          "error"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "type": [
              "string",
              "integer",
              "null"
            ]
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}
