{
  "name": "cnvs.app",
  "description": "Free, no-signup real-time collaborative whiteboard. Every board at https://cnvs.app/#<id> can be read and mutated by an AI agent alongside human collaborators — strokes, text and images sync live in ~100ms.",
  "documentation": "https://cnvs.app/llms.txt",
  "skills": {
    "cnvs-whiteboard": {
      "description": "Agent Skill that teaches an AI agent how to collaborate on a cnvs.app board — read shared state, add/update/move/delete text/links/strokes/images via REST, subscribe to live edits via MCP, and render the SVG preview when the board has drawings. Use when the user references any cnvs.app board or asks to annotate/edit a shared whiteboard.",
      "canonical": "https://cnvs.app/cnvs-whiteboard/SKILL.md",
      "repository": "https://github.com/lksrz/cnvs-whiteboard-skills",
      "files": {
        "SKILL.md": "https://cnvs.app/cnvs-whiteboard/SKILL.md"
      },
      "pairs_with": "mcp-listen"
    },
    "mcp-listen": {
      "description": "Generic Claude Code / Agent Skill that subscribes to any Streamable-HTTP MCP server's resource updates and emits one JSON line per push on stdout — designed to be wrapped by the Monitor tool so each event becomes an in-chat notification. Not cnvs-specific.",
      "canonical": "https://cnvs.app/mcp-listen/SKILL.md",
      "repository": "https://github.com/lksrz/cnvs-whiteboard-skills",
      "files": {
        "SKILL.md": "https://cnvs.app/mcp-listen/SKILL.md",
        "scripts/listen.mjs": "https://cnvs.app/mcp-listen/scripts/listen.mjs",
        "package.json": "https://cnvs.app/mcp-listen/package.json"
      }
    }
  },
  "httpApi": {
    "openapi": "https://cnvs.app/openapi.json",
    "quotas": "https://cnvs.app/quotas.json",
    "note": "Full HTTP fallback for AI agents that cannot use MCP — covers reads AND mutations (add/update/move/delete texts, strokes, images, links). Same validator + live broadcast as MCP. MCP additionally provides live resource subscriptions and the wait_for_update long-poll. Live, machine-readable limits manifest at /quotas.json."
  },
  "servers": [
    {
      "name": "cnvs",
      "url": "https://cnvs.app/mcp",
      "transport": "streamable-http",
      "protocolVersion": "2025-06-18",
      "authentication": "none",
      "notes": "The board ID is the access key. Anyone who knows the board ID can read and write to that board, identical to sharing the browser URL."
    }
  ],
  "quotasManifest": "https://cnvs.app/quotas.json",
  "quotas": {
    "perRequest": {
      "maxBodyBytes": 5242880,
      "note": "Single request body cap. Enforced up-front via Content-Length AND during the streamed body read, so chunked / header-less clients cannot bypass it. HTTP 413 / JSON-RPC -32000 code:payload_too_large."
    },
    "perBoard": {
      "maxTexts": 500,
      "maxTextContentChars": 100000,
      "maxImages": 50,
      "maxImageBytesTotal": 10485760,
      "maxImageBytesPerItem": 900000,
      "maxStrokes": 2000
    },
    "rateLimit": {
      "requests": 60,
      "windowSeconds": 10,
      "per": "board",
      "appliesTo": ["browser-ws", "rest-reads", "rest-mutations", "mcp"],
      "enforcement": "best-effort sliding window. REST/MCP share a Worker-isolate-local bucket; browser WebSockets are enforced inside the BoardServer Durable Object (per-board, strong within that DO instance). The two buckets are independent.",
      "onExceeded": { "rest": "HTTP 429 + Retry-After", "mcp": "-32000 code:rate_limited", "ws": "{type:\"error\", code:\"rate_limited\"} frame" }
    },
    "cors": {
      "allowOrigin": "*",
      "allowMethods": ["GET", "POST", "DELETE", "OPTIONS"],
      "preflightSupported": true
    },
    "onExceeded": "MCP returns JSON-RPC error -32000; REST returns HTTP 413; browser WebSocket receives {type:\"error\", code:\"quota_exceeded\"} which surfaces as a toast."
  },
  "capabilities": {
    "tools": [
      "open_board",
      "get_board",
      "get_preview",
      "add_text",
      "add_link",
      "add_image",
      "draw_stroke",
      "move",
      "erase",
      "wait_for_update"
    ],
    "resources": [
      "cnvs://board/{id}/state.json",
      "cnvs://board/{id}/preview.svg"
    ],
    "subscribe": true,
    "notifications": {
      "resources/updated": {
        "debounceMs": 3000,
        "transport": "GET /mcp SSE"
      }
    }
  },
  "clientConfig": {
    "claudeDesktop": {
      "mcpServers": {
        "cnvs": {
          "type": "http",
          "url": "https://cnvs.app/mcp"
        }
      }
    },
    "claudeCode": "claude mcp add --transport http cnvs https://cnvs.app/mcp"
  }
}
