# io.github.AvatarGaia/canvas-mcp

> TeamAgent Canvas MCP（服务端 0.4.0）：91 个工具——开岗、改配置、跑动作、看数据、发布并配知识库。可匿名试用，带 Key 解锁全部。

- name: io.github.AvatarGaia/canvas-mcp
- version: 0.1.4
- connection class: R0 (autonomous)
- trust: 97/100
- quality: 75/100 (good)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/io.github.AvatarGaia%2Fcanvas-mcp
- tools: https://api.protogrid.dev/v1/servers/io.github.AvatarGaia%2Fcanvas-mcp/tools

**An agent can connect right now, no human step.** Remote endpoint, no authentication, reachable on the last probe.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "canvas-mcp": {
      "type": "http",
      "url": "https://agent.avatargaia.top/api/mcp/canvas",
      "headers": {
        "Authorization": "Bearer ${CANVAS_MCP_TOKEN}"
      }
    }
  }
}
```

Placeholders to fill: `${CANVAS_MCP_TOKEN}`.

## Trust

- hygiene: 100
- liveness: 100
- freshness: 100
- provenance: 90
- drivers: +repository +namespace-matches-repo +website +reachable +uptime-99% +updated-17d-ago
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 75/100 (good)

### protocol: 75 (weight 25)

- warn `protocol.modern`: newest supported version is 2025-11-25; 2026-07-28 not supported, older versions are deprecated until 2027-07-28
- n/a `protocol.stateless`: only applies to 2026-07-28 servers
- pass `protocol.transport`: streamable HTTP
- n/a `protocol.list_ttl`: only applies to 2026-07-28 servers

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 100 (weight 30)

- pass `tools.descriptions`: every tool has a description
- pass `tools.description_length`: descriptions are concise
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 18 of 18 tools declare readOnlyHint or destructiveHint
- pass `tools.directory_hints`: every tool declares readOnlyHint, destructiveHint, idempotentHint and openWorldHint
- pass `tools.token_cost`: about 2,995 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump

### stability: 25 (weight 15)

- warn `stability.changes`: 23 tool changes in 30 days
- fail `stability.rug_pull`: 2 tools kept their name but changed most of their description in 30 days; review before trusting them

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: deps.dev does not know @avatargaia/canvas-mcp@0.1.4

- tools: 18, about 2,995 tokens to load them all
- tool set hash: 7a4a5ce8649b1546fe36f7aa482956b5
- tools last changed: 2026-10-20T08:08:48.887Z
- badge: [![protogrid quality](https://protogrid.dev/badge/io.github.AvatarGaia/canvas-mcp.svg)](https://protogrid.dev/servers/io.github.AvatarGaia/canvas-mcp)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

- 2026-10-20 `set_staff_kbs` changed (description) **meaning changed**
  - before: 设定一个岗位用哪些知识库（整体替换）。参数：slug 必填；kbs 是库名数组，只能填我名下已发布的库（list_kbs 里有的），别人的库名会被忽略；传 [] = 这个岗位不用任何库。改完立刻生效。
  - after: 设定一个岗位用哪些知识库（整体替换）。参数：slug 必填；kbs 是库名数组：我名下的库写库名；工作区的库或别人共享的库写 list_kbs 返回里的 ref（如 ws:xxx/库名）。别人的库要授权时勾了「可对外」才配得上，不满足的会被忽略并在 kbDropped 里说明；传 [] = 这个岗位不用任何库。改完立刻生效。
- 2026-10-20 `publish_kb` changed (description, inputSchema)
  - before: 把一套整理好的 Markdown 发布成知识库（发布到我名下；带 slug 则同时配给那个岗位）。结构：wiki/index.md 是总目录（每篇一行：链接 + 一句摘要 + 更新日期，数字员工靠它挑页，摘要要准）；其余 wiki/<主题>/<文章>.md，一个概念一篇，标题用访客会问的说法，单篇别超过 6000 字。规矩：①数字、日期、引文必须照原始资料逐字写，不改写不推算；②只收 wiki/ 下的 .md，原始资料不要发上来；③同名再发是整库替换，更新前先 read_kb 把现有页面读回来合并；④发布等于公开——岗位是匿名访客都能聊的，个人隐私、客户资料、令牌、内部运维内容一律不放（平台会拦身份证号和令牌，其它靠你自检）。checked 必须为 true 才会发。上限 200 个文件 / 单个 64KB / 合计 2MB。参数示例：{"name":"选课指南","checked":true,"files":[{"path":"wiki/index.md","content":"# Knowledge Base Index\n..."},{"path":"wiki/xuanke/rules.md","content":"# 选课时间与学分上限\n..."}]}（files 是数组，每项一个 {path, content}，不是 {路径: 内容} 的对象）。这是写操作，发之前跟用户确认库名和要不要配给岗位。
  - after: 把一套整理好的 Markdown 发布成知识库（发布到我名下；带 slug 则同时配给那个岗位；带 owner=ws:<工作区id> 则发布成那个工作区的库，要求我是该工作区 owner/admin）。结构：wiki/index.md 是总目录（每篇一行：链接 + 一句摘要 + 更新日期，数字员工靠它挑页，摘要要准）；其余 wiki/<主题>/<文章>.md，一个概念一篇，标题用访客会问的说法，单篇别超过 6000 字。页面要带图片 / 视频 / 三维模型 / 外链时，在页里写一个 ```kb-media 围栏，一行一个「类型 | 标题 | 链接 | 说明」，类型 image / video / model(.glb) / link / embed(只认白名单站点)，链接用 https:// 或本站 /static/ /uploads/ /apps/ 路径——素材只放链接，不要把文件内容塞进来；数字员工回答时会把素材显示给访客。库主人可以开「只用已校验的页」，那时你新发或改过的页都是待校验，要人在网页上核对后才对访客生效，你不能自己批。规矩：①数字、日期、引文必须照原始资料逐字写，不改写不推算；②只收 wiki/ 下的 .md，原始资料不要发上来；③同名再发是整库替换，更新前先 read_kb 把现有页面读回来合并；④发布等于公开——岗位是匿名访客都能聊的，个人隐私、客户资料、令牌、内部运维内容一律不放（平台会拦身份证号和令牌，其它靠你自检）。checked 必须为 true 才会发。上限 200 个文件 / 单个 64KB / 合计 2MB。参数示例：{"name":"选课指南","checked":true,"files":[{"path":"wiki/index.md","content":"# Knowledge Base Index\n..."},{"path":"wiki/xuanke/rules.md","content":"# 选课时间与学分上限\n..."}]}（files 是数组，每项一个 {path, content}，不是 {路径: 内容} 的对象）。这是写操作，发之前跟用户确认库名和要不要配给岗位。
- 2026-10-20 `read_kb` changed (description, inputSchema)
  - before: 读一个知识库。参数名是 name（库名，就是 list_kbs 返回里的 kbName）和 page（页面路径，取自页面清单里的 path）。只传 name → 这个库的版本和页面清单；再传 page（如 wiki/index.md）→ 那一页的原文。要更新一个库之前先用它把现有页面读回来——publish_kb 是整库替换，没带上的页面会消失。
  - after: 读一个知识库。参数名是 name（库名，就是 list_kbs 返回里的 kbName）和 page（页面路径，取自页面清单里的 path）。只传 name → 这个库的版本和页面清单；再传 page（如 wiki/index.md）→ 那一页的原文。要更新一个库之前先用它把现有页面读回来——publish_kb 是整库替换，没带上的页面会消失。读工作区的库或别人共享的库要加 owner（list_kbs 返回里的 ownerKey，如 ws:xxx）。
- 2026-10-20 `list_kbs` changed (description) **meaning changed**
  - before: 列出我名下已发布的知识库（库名 / 版本 / 发布时间 / 篇数 / 每页的 path 与标题），以及我名下每个岗位各自配了哪些库。用户问"我有哪些知识库""这个岗位用的什么资料"时用。知识库是数字员工回答业务问题的依据：岗位配了库，访客问到时它会先查库再答。
  - after: 列出我名下已发布的知识库（库名 / 版本 / 发布时间 / 篇数 / 每页的 path 与标题），以及我名下每个岗位各自配了哪些库；还有 workspaces（我所在工作区自己的库 + 工作区引用的库）和 shared（别人授权给我的库），这些库各带 ownerKey 与 ref。在某个工作区里干活时，优先读那个工作区的库和它引用的库，说法冲突时都列出来。用户问"我有哪些知识库""这个岗位用的什么资料"时用。知识库是数字员工回答业务问题的依据：岗位配了库，访客问到时它会先查库再答。
- 2026-10-03 `hire_staff` added
  - 开一个新的数字员工岗位。参数：templateId 必填（list_templates 里 canOpen=true 的，如 kb-assistant 知识库问答员）；name 员工名字；kbs 开岗时就配上的知识库。返回 slug、画布链接 canvasUrl（发给顾客 / 挂服务号的就是它）和实际配上的知识库 kbs（名下没有的库名会被忽略，以返回为准）。代价：新岗位先免费试用几天，之后按月从主人余额扣 Token，对话按次另计——开之前跟用户确认；每个账号岗位数有上限，到上限会报错，让用户先删掉不用的。
- 2026-10-03 `set_staff_kbs` added
  - 设定一个岗位用哪些知识库（整体替换）。参数：slug 必填；kbs 是库名数组，只能填我名下已发布的库（list_kbs 里有的），别人的库名会被忽略；传 [] = 这个岗位不用任何库。改完立刻生效。
- 2026-10-03 `publish_kb` added
  - 把一套整理好的 Markdown 发布成知识库（发布到我名下；带 slug 则同时配给那个岗位）。结构：wiki/index.md 是总目录（每篇一行：链接 + 一句摘要 + 更新日期，数字员工靠它挑页，摘要要准）；其余 wiki/<主题>/<文章>.md，一个概念一篇，标题用访客会问的说法，单篇别超过 6000 字。规矩：①数字、日期、引文必须照原始资料逐字写，不改写不推算；②只收 wiki/ 下的 .md，原始资料不要发上来；③同名再发是整库替换，更新前先 read_kb 把现有页面读回来合并；④发布等于公开——岗位是匿名访客都能聊的，个人隐私、客户资料、令牌、内部运维内容一律不放（平台会拦身份证号和令牌，其它靠你自检）。checked 必须为 true 才会发。上限 200 个文件 / 单个 64KB / 合计 2MB。参数示例：{"name":"选课指南","checked":true,"files":[{"path":"wiki/index.md","content":"# Knowledge Base Index\n..."},{"path":"wiki/xuanke/rules.md","content":"# 选课时间与学分上限\n..."}]}（files 是数组，每项一个 {path, content}，不是 {路径: 内容} 的对象）。这是写操作，发之前跟用户确认库名和要不要配给岗位。
- 2026-10-03 `read_kb` added
  - 读一个知识库。参数名是 name（库名，就是 list_kbs 返回里的 kbName）和 page（页面路径，取自页面清单里的 path）。只传 name → 这个库的版本和页面清单；再传 page（如 wiki/index.md）→ 那一页的原文。要更新一个库之前先用它把现有页面读回来——publish_kb 是整库替换，没带上的页面会消失。
- 2026-10-03 `list_kbs` added
  - 列出我名下已发布的知识库（库名 / 版本 / 发布时间 / 篇数 / 每页的 path 与标题），以及我名下每个岗位各自配了哪些库。用户问"我有哪些知识库""这个岗位用的什么资料"时用。知识库是数字员工回答业务问题的依据：岗位配了库，访客问到时它会先查库再答。
- 2026-10-03 `patch_staff_config` changed (description)
  - before: 局部修改岗位配置，patch 只放要改的字段：personaPrompt(人设) / serviceFlow(服务流程，一行一步) / promotionConfig({categories:[{name,priority,url}]}) / productSources([{key,label,searchUrl,weAppId?,weAppUsername?}]) / layoutStyle(split|pip|classic) / contextMode(inline|webhook) / contextWebhookUrl / name。参数：slug、patch 都必填。这是写操作，改的是客户的岗位，改完立刻生效；不确定用户真要改时先复述一遍再调。
  - after: 局部修改岗位配置，patch 只放要改的字段：personaPrompt(人设) / serviceFlow(服务流程，一行一步) / promotionConfig（只放要改的键，其余保留：categories:[{name,priority,url}] 主推；look:{brandName,slogan,intro,avatarUrl,theme(ember|green|blue|purple),particles,startText,footer,placeholder,emptyTitle,emptyHint,showPhoto} 画布外观与文案；sell:{sop,pdd} 是否推荐服务包 / 拼多多商品；kbs:[库名] 用哪些知识库，也可用 set_staff_kbs）/ productSources([{key,label,searchUrl,weAppId?,weAppUsername?}]) / layoutStyle(split|pip|classic) / contextMode(inline|webhook) / contextWebhookUrl / name。参数：slug、patch 都必填。这是写操作，改的是客户的岗位，改完立刻生效；不确定用户真要改时先复述一遍再调。

Full history: https://api.protogrid.dev/v1/servers/io.github.AvatarGaia%2Fcanvas-mcp/changes

## Dependencies

- npm @avatargaia/canvas-mcp@0.1.4: unknown

Dependency graphs from deps.dev; advisories from OSV.dev, including the GitHub Advisory Database and the PyPI Advisory Database; all CC BY 4.0.

## Remotes

- https://agent.avatargaia.top/api/mcp/canvas (streamable-http, auth none, reachable true, uptime30d 0.99159664)

## Packages

- npm @avatargaia/canvas-mcp@0.1.4 secrets: --token

## Tools (18)

- `canvas_action`: 执行一个岗位动作（如 AICare 的 preflight / list_checks / gen_report / run_detection / resolve_user）。参数：slug、action 必填；params 按 list_actions 的 schema 填；session_id 想让结果落在某次会话里就带；hostUserId 宿主用户标识可选。返回 {ok, mode:"sync", data} 直接用；{ok, mode:"job", jobId, pollSec} 用 get_job 轮询。代价：list_actions 标 paid 的会从岗位出资人余额扣 credits（出报告 5 / 跑检测 2），失败不扣；同键（如同对象同一天）重复调用返回缓存结果（cached 标记）不重复扣，用户催第二次可放心重试。典型编排：list_actions → canvas_action(preflight) 拿背景 → canvas_action(gen_report) → get_job → 用自然语言讲给用户。公共岗位：gaia-academy（龙虾学院 · Agent 进修）的动作标 public:true——任何持有效 Key 的调用方都能跑，不需要拥有该岗位；学员身份取调用方 Key 的用户，非 public 动作对非归属方仍 403。典型用法：canvas_action(gaia-academy, search_courses → start_exam → submit_exam → get_principle)。
- `get_job`: 按 job_id 查长任务：queued / running / done(带 result) / failed(带 error)。建议每 3 秒查一次。error 是人话（如"关爱对象不存在或已删除"），照原话转述给用户，不要改写成"系统繁忙"，也不要拿同参数重试。
- `get_session_log`: 单个会话按时间正序的完整流水：用户消息 / AI 回复(带 tokens) / 埋点 / 动作调用 / 推屏。参数：slug 和 session_id 两个都必填（slug 用于显式鉴权）。调用前先从 list_sessions 或 open_canvas 拿到合法 session_id。隐私边界：只能读自己岗位的记录。需要有效 Key，匿名不开。
- `get_staff_config`: 读岗位配置：personaPrompt / serviceFlow / promotionConfig / productSources / contextMode / layoutStyle / templateId / llmMode（只说是否 BYOK，不给密钥）/ tts。参数：slug 必填。改之前先读，否则会用"想当然的人设"覆盖客户调过的版本。
- `get_stats`: 岗位一段时间的汇总：会话数、真人对话轮数、埋点数、动作调用数、tokens、按日曲线。参数：slug 必填；from/to ISO 时间，默认最近 30 天。用户问"这岗位最近怎么样/今天多少人来"就用它，不要靠聊天历史猜数字。需要有效 Key，匿名不开。
- `hire_staff`: 开一个新的数字员工岗位。参数：templateId 必填（list_templates 里 canOpen=true 的，如 kb-assistant 知识库问答员）；name 员工名字；kbs 开岗时就配上的知识库。返回 slug、画布链接 canvasUrl（发给顾客 / 挂服务号的就是它）和实际配上的知识库 kbs（名下没有的库名会被忽略，以返回为准）。代价：新岗位先免费试用几天，之后按月从主人余额扣 Token，对话按次另计——开之前跟用户确认；每个账号岗位数有上限，到上限会报错，让用户先删掉不用的。
- `list_actions`: 列出这个岗位（按其模板）能做的动作：id / title / description / cost / credits / anonymous / job / params(JSON Schema)。参数：slug 必填。调 canvas_action 前先调它，不要猜 action 名——各岗位动作集不同，params 按它给的 schema 填。
- `list_kbs`: 列出我名下已发布的知识库（库名 / 版本 / 发布时间 / 篇数 / 每页的 path 与标题），以及我名下每个岗位各自配了哪些库；还有 workspaces（我所在工作区自己的库 + 工作区引用的库）和 shared（别人授权给我的库），这些库各带 ownerKey 与 ref。在某个工作区里干活时，优先读那个工作区的库和它引用的库，说法冲突时都列出来。用户问"我有哪些知识库""这个岗位用的什么资料"时用。知识库是数字员工回答业务问题的依据：岗位配了库，访客问到时它会先查库再答。
- `list_my_staff`: 列出我名下的数字员工岗位（slug / 名称 / 模板 / 画布链接）。用户问"我有哪些岗位"用它；后续所有按岗位操作的工具都要 slug，slug 一律从这里拿，不要凭记忆拼。参数：无。
- `list_sessions`: 岗位的访客会话列表（最近优先）：session_id、宿主用户标识、轮数、时间。参数：slug 必填；q 按宿主用户标识模糊搜；from/to；limit；cursor 翻页传上一页返回的 nextCursor。想看"最近都服务了哪些人"用它，再拿 session_id 看明细。需要有效 Key，匿名不开。
- `list_templates`: 列出可开岗的数字员工模板。用于：想知道"系统能开哪些岗位"、或用户要开通新岗位时。返回每个模板的 templateId / 名称 / 说明 / canOpen / missingHandlers / 动作清单。别用它找"已开好的岗位"——那是 list_my_staff。canOpen=false 的模板不可开通（缺实现），别推荐用户选。参数：无。
- `open_canvas`: 为岗位生成画布链接 + 会话 ID。用于用户需要"看得见的界面"（看报告/看商品/做检测）。参数：slug 必填；hostUserId 宿主用户标识（强烈建议带，会话归属和离线补推都靠它）；targetId 关爱/业务对象；app 指定画布页（如 aicare-kf）。返回 {url, session_id}——把 session_id 存下来，get_session_log / push_screen 都用它。会话在返回时已建立：现在就能 push_screen 给"还没来的人"备卡片，用户打开链接即补推；人打开后聊天/埋点都归到同一个 session_id。
- `patch_staff_config`: 局部修改岗位配置，patch 只放要改的字段：personaPrompt(人设) / serviceFlow(服务流程，一行一步) / promotionConfig（只放要改的键，其余保留：categories:[{name,priority,url}] 主推；look:{brandName,slogan,intro,avatarUrl,theme(ember|green|blue|purple),particles,startText,footer,placeholder,emptyTitle,emptyHint,showPhoto} 画布外观与文案；sell:{sop,pdd} 是否推荐服务包 / 拼多多商品；kbs:[库名] 用哪些知识库，也可用 set_staff_kbs）/ productSources([{key,label,searchUrl,weAppId?,weAppUsername?}]) / layoutStyle(split|pip|classic) / contextMode(inline|webhook) / contextWebhookUrl / name。参数：slug、patch 都必填。这是写操作，改的是客户的岗位，改完立刻生效；不确定用户真要改时先复述一遍再调。
- `publish_kb`: 把一套整理好的 Markdown 发布成知识库（发布到我名下；带 slug 则同时配给那个岗位；带 owner=ws:<工作区id> 则发布成那个工作区的库，要求我是该工作区 owner/admin）。结构：wiki/index.md 是总目录（每篇一行：链接 + 一句摘要 + 更新日期，数字员工靠它挑页，摘要要准）；其余 wiki/<主题>/<文章>.md，一个概念一篇，标题用访客会问的说法，单篇别超过 6000 字。页面要带图片 / 视频 / 三维模型 / 外链时，在页里写一个 ```kb-media 围栏，一行一个「类型 | 标题 | 链接 | 说明」，类型 image / video / model(.glb) / link / embed(只认白名单站点)，链接用 https:// 或本站 /static/ /uploads/ /apps/ 路径——素材只放链接，不要把文件内容塞进来；数字员工回答时会把素材显示给访客。库主人可以开「只用已校验的页」，那时你新发或改过的页都是待校验，要人在网页上核对后才对访客生效，你不能自己批。规矩：①数字、日期、引文必须照原始资料逐字写，不改写不推算；②只收 wiki/ 下的 .md，原始资料不要发上来；③同名再发是整库替换，更新前先 read_kb 把现有页面读回来合并；④发布等于公开——岗位是匿名访客都能聊的，个人隐私、客户资料、令牌、内部运维内容一律不放（平台会拦身份证号和令牌，其它靠你自检）。checked 必须为 true 才会发。上限 200 个文件 / 单个 64KB / 合计 2MB。参数示例：{"name":"选课指南","checked":true,"files":[{"path":"wiki/index.md","content":"# Knowledge Base Index\n..."},{"path":"wiki/xuanke/rules.md","content":"# 选课时间与学分上限\n..."}]}（files 是数组，每项一个 {path, content}，不是 {路径: 内容} 的对象）。这是写操作，发之前跟用户确认库名和要不要配给岗位。
- `push_screen`: 把内容推到某个画布会话的屏上。参数：session_id 必填（来自 open_canvas 或 list_sessions）；content 必填，写成一条"助手回复"文本，可含 ```canvas-md（Markdown 卡片）/ ```canvas-html（完整 HTML 文档）/ ```canvas（JSON 块）围栏，围栏外文字显示为字幕；speak=true 朗读字幕；title 可选。会话在线立即上屏；不在线（含还没人打开过的）存为待展示，该会话或同岗位同一 hostUserId 下次打开自动补推。屏属于会话不属于人：别复用别人的 session_id；要执行有副作用的动作（出报告/跑检测）用 canvas_action。需要有效 Key，匿名不开。
- `query_events`: 跨会话按类型拉事件（倒序）：type = chat_user / chat_assistant / track / action_call / page_open / push。参数：slug 必填；type、from/to、limit(≤500)。每条带 source（mcp / page / server，看得出谁发起的）；action_call 的 payload 有 params/ok/ms/credits/cached/jobId——计费与排障的证据链；push 的 payload 有 preview。需要有效 Key，匿名不开。
- `read_kb`: 读一个知识库。参数名是 name（库名，就是 list_kbs 返回里的 kbName）和 page（页面路径，取自页面清单里的 path）。只传 name → 这个库的版本和页面清单；再传 page（如 wiki/index.md）→ 那一页的原文。要更新一个库之前先用它把现有页面读回来——publish_kb 是整库替换，没带上的页面会消失。读工作区的库或别人共享的库要加 owner（list_kbs 返回里的 ownerKey，如 ws:xxx）。
- `set_staff_kbs`: 设定一个岗位用哪些知识库（整体替换）。参数：slug 必填；kbs 是库名数组：我名下的库写库名；工作区的库或别人共享的库写 list_kbs 返回里的 ref（如 ws:xxx/库名）。别人的库要授权时勾了「可对外」才配得上，不满足的会被忽略并在 kbDropped 里说明；传 [] = 这个岗位不用任何库。改完立刻生效。
