{
  "openapi": "3.1.0",
  "info": {
    "title": "cupie.app public documents and MCP endpoint",
    "version": "1.0.0",
    "description": "Read-only public content of cupie.app, the website of Cupie, the free video-call games app for couples: web pages (HTML or markdown), plain text summaries, the sitemap, discovery files and one read-only MCP endpoint. Free: no API key, no signup, no auth. There is no published rate limit; keep requests polite and follow robots.txt. This is not an API to the Cupie app: accounts, calls, messages and other app data are not reachable here. Human docs: https://cupie.app/docs/api",
    "contact": {
      "name": "Cupie support",
      "email": "support@cupie.app",
      "url": "https://cupie.app/help"
    },
    "termsOfService": "https://cupie.app/terms"
  },
  "servers": [
    {
      "url": "https://cupie.app"
    }
  ],
  "externalDocs": {
    "description": "Agent docs with curl examples",
    "url": "https://cupie.app/docs/api"
  },
  "security": [],
  "paths": {
    "/": {
      "get": {
        "operationId": "getHomepage",
        "summary": "Homepage as HTML or markdown",
        "description": "The cupie.app homepage, a static HTML page. Send `Accept: text/markdown` (q above 0) to get a markdown version of the same content, built on request from the HTML. Any other Accept header, including `*/*` or `text/markdown;q=0`, returns the HTML.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Accept"
          }
        ],
        "responses": {
          "200": {
            "description": "The homepage: `text/html` by default, `text/markdown` when asked for.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                },
                "example": "<!doctype html>\n<html lang=\"en\">\n<head>\n<title>Cupie: Video Call Games for Couples (Free App)</title>"
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                },
                "example": "# Cupie\n\n> Cupie is the free app to call your partner and play games together live: Minigolf, Four in a Row, Truth or Dare, quizzes and more. iPhone and Android.\n"
              }
            },
            "headers": {
              "Vary": {
                "description": "`Accept`: the HTML and markdown versions share one URL.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Markdown answers are `private, max-age=0, must-revalidate` (never stored by shared caches).",
                "schema": {
                  "type": "string"
                }
              },
              "X-Robots-Tag": {
                "description": "Markdown answers are `noindex`.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/{page}": {
      "get": {
        "operationId": "getPage",
        "summary": "A public page as HTML or markdown",
        "description": "A public page listed in /sitemap.xml, for example /about, /guides, /tools or a guide such as /couples-quiz. These are static HTML pages; send `Accept: text/markdown` for a markdown version built from the HTML. Only pages in the sitemap are meant for agents: invite links and app share previews are not listed, not indexed and not part of this description. Unknown pages return 404.",
        "parameters": [
          {
            "name": "page",
            "in": "path",
            "required": true,
            "description": "Page path from /sitemap.xml without the leading slash.",
            "schema": {
              "type": "string"
            },
            "example": "about"
          },
          {
            "$ref": "#/components/parameters/Accept"
          }
        ],
        "responses": {
          "200": {
            "description": "The page: `text/html` by default, `text/markdown` when asked for.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                },
                "example": "<!doctype html>\n<html lang=\"en\">"
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                },
                "example": "# About Cupie\n\nCupie is a free iPhone and Android app for couples. You call your partner inside the app and play games together live on the video call.\n"
              }
            },
            "headers": {
              "Vary": {
                "description": "`Accept`: the HTML and markdown versions share one URL.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Markdown answers are `private, max-age=0, must-revalidate` (never stored by shared caches).",
                "schema": {
                  "type": "string"
                }
              },
              "X-Robots-Tag": {
                "description": "Markdown answers are `noindex`.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No such page: the HTML 404 page, or a short markdown note when markdown was asked for.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                },
                "example": "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />"
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                },
                "example": "# Page not found\n"
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "Site summary for language models",
        "description": "A static plain text file (markdown formatted, llms.txt convention) with key facts about Cupie and a link to every public guide, tool and agent file.",
        "responses": {
          "200": {
            "description": "llms.txt summary.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                },
                "example": "# Cupie\n\n> Cupie is a free video-call app for couples (iPhone and Android).\n"
              }
            }
          }
        }
      }
    },
    "/llms-full.txt": {
      "get": {
        "operationId": "getLlmsFullTxt",
        "summary": "Full text of every guide",
        "description": "A static plain text file with the full text of every published cupie.app guide, for agents that want all content in one request.",
        "responses": {
          "200": {
            "description": "Full guide text.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                },
                "example": "# Cupie: full text of cupie.app guides\n"
              }
            }
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemap",
        "summary": "List of every public page",
        "description": "Static XML sitemap with every public page and its last-modified date. Use it to find valid values for /{page}.",
        "responses": {
          "200": {
            "description": "Sitemap.",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                },
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n<url><loc>https://cupie.app/</loc><lastmod>2026-10-30</lastmod><priority>1.0</priority></url>"
              }
            }
          }
        }
      }
    },
    "/.well-known/api-catalog": {
      "get": {
        "operationId": "getApiCatalog",
        "summary": "API catalog (RFC 9727)",
        "description": "Static RFC 9727 linkset that points to this OpenAPI file, the agent docs, llms.txt and the MCP server card.",
        "responses": {
          "200": {
            "description": "API catalog linkset.",
            "content": {
              "application/linkset+json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "linkset": [
                    {
                      "anchor": "https://cupie.app/",
                      "service-desc": [
                        {
                          "href": "https://cupie.app/openapi.json",
                          "type": "application/vnd.oai.openapi+json"
                        }
                      ],
                      "service-doc": [
                        {
                          "href": "https://cupie.app/docs/api",
                          "type": "text/html"
                        }
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/mcp/server-card.json": {
      "get": {
        "operationId": "getMcpServerCard",
        "summary": "MCP server card",
        "description": "Static JSON card that describes the MCP endpoint at /mcp: transport, capabilities (tools only), no auth, and the three tools.",
        "responses": {
          "200": {
            "description": "MCP server card.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "protocolVersion": "2025-11-25",
                  "serverInfo": {
                    "name": "cupie-app",
                    "title": "Cupie (cupie.app)",
                    "version": "1.0.0"
                  },
                  "url": "https://cupie.app/mcp",
                  "transport": {
                    "type": "streamable-http",
                    "endpoint": "/mcp"
                  },
                  "capabilities": {
                    "tools": {
                      "listChanged": false
                    }
                  },
                  "authentication": {
                    "required": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/agent-skills/index.json": {
      "get": {
        "operationId": "getAgentSkills",
        "summary": "Agent skills index",
        "description": "Static index of agent skills (SKILL.md files) that explain how to help a couple with Cupie and its free tools, each with a sha256 digest.",
        "responses": {
          "200": {
            "description": "Agent skills index.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "skills": [
                    {
                      "name": "get-cupie-app",
                      "type": "skill-md",
                      "description": "Explain the Cupie app and help two partners install it and pair their phones.",
                      "url": "/.well-known/agent-skills/get-cupie-app/SKILL.md"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "callMcp",
        "summary": "Read-only MCP endpoint (Streamable HTTP)",
        "description": "Model Context Protocol server, Streamable HTTP transport, stateless. Send one JSON-RPC 2.0 message per POST with `Content-Type: application/json` and `Accept: application/json, text/event-stream`. Methods: `initialize`, `ping`, `tools/list`, `tools/call`; notifications get 202 with no body. Tools: `get_product_info`, `list_public_pages`, `search_public_pages`. They only read public cupie.app content. No auth, no sessions, no SSE stream (GET returns 405). Bodies over 16 KB get 413; a foreign `Origin` header gets 403; an unsupported `MCP-Protocol-Version` gets 400. Supported protocol versions: 2025-11-25, 2025-06-18, 2025-03-26 (batches are not supported).",
        "externalDocs": {
          "description": "MCP Streamable HTTP transport",
          "url": "https://modelcontextprotocol.io/specification/2025-11-25/basic/transports"
        },
        "parameters": [
          {
            "name": "MCP-Protocol-Version",
            "in": "header",
            "required": false,
            "description": "Protocol version from initialize.",
            "schema": {
              "type": "string",
              "enum": [
                "2025-11-25",
                "2025-06-18",
                "2025-03-26"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tools/call",
                "params": {
                  "name": "search_public_pages",
                  "arguments": {
                    "query": "date night ideas",
                    "limit": 3
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response (a result, or an error such as -32601 Method not found or -32602 Unknown tool).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                },
                "example": {
                  "jsonrpc": "2.0",
                  "id": 1,
                  "result": {
                    "content": [
                      {
                        "type": "text",
                        "text": "{\"query\": \"date night ideas\", \"total\": 50, \"pages\": [{\"title\": \"Date night ideas at home (2026): 40 easy ideas for couples\", \"url\": \"https://cupie.app/date-night-ideas-at-home\", \"section\": \"guides\", \"summary\": \"The best date night ideas at home turn a normal evening into a plan...\"}]}"
                      }
                    ],
                    "isError": false
                  }
                }
              }
            }
          },
          "202": {
            "description": "Notification or response accepted. No body."
          },
          "400": {
            "description": "Parse error, invalid JSON-RPC message, batch, or unsupported MCP-Protocol-Version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                },
                "example": {
                  "jsonrpc": "2.0",
                  "id": null,
                  "error": {
                    "code": -32700,
                    "message": "Parse error"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Origin header from another site.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                },
                "example": {
                  "jsonrpc": "2.0",
                  "id": null,
                  "error": {
                    "code": -32600,
                    "message": "Origin not allowed"
                  }
                }
              }
            }
          },
          "405": {
            "description": "Any method other than POST. No SSE stream, no session to delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                },
                "example": {
                  "jsonrpc": "2.0",
                  "id": null,
                  "error": {
                    "code": -32600,
                    "message": "Use POST with one JSON-RPC message. This server has no SSE stream and no sessions."
                  }
                }
              }
            }
          },
          "406": {
            "description": "Accept header does not allow application/json."
          },
          "413": {
            "description": "Body over 16 KB."
          },
          "415": {
            "description": "Content-Type is not application/json."
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "Accept": {
        "name": "Accept",
        "in": "header",
        "required": false,
        "description": "`text/markdown` (with q above 0) returns markdown. Anything else returns HTML.",
        "schema": {
          "type": "string",
          "enum": [
            "text/html",
            "text/markdown"
          ]
        },
        "example": "text/markdown"
      }
    },
    "schemas": {
      "JsonRpcRequest": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "type": [
              "string",
              "integer"
            ]
          },
          "method": {
            "type": "string"
          },
          "params": {
            "type": "object"
          }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": [
          "jsonrpc",
          "id"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "type": [
              "string",
              "integer",
              "null"
            ]
          },
          "result": {
            "type": "object"
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}
