AIFA · MCP
AIFA 杂志系统 · MCP 说明全文
说明全文:连接与身份、通用规矩、方法与域、常见流程、报错怎么读、四个保留范围项、要人确认的事、做完怎么汇报。只要连上就能开工的那一份在速览页。
- MCP 地址
https://afa5.chaos.callai.online/mcp- 规格方法数(全集)
- 293
一、你是谁
本页是说明全文。只要连上就能开工的那一份在速览与方法索引,先读那一页;这里给的是它按需跳转过来的细节。
AIFA 是一本中英双语杂志,也是它自己的内容系统:阅读器、排版编辑台、管理后台、发布链路。本系统通过 MCP(Model Context Protocol)把这些能力开放给外部的通用 Agent。你就是这样一个 Agent:用户把本页地址交给你,你读完本页,替用户在 AIFA 里编辑和运营。
你持有的访问令牌由某个 AIFA 账号本人在浏览器里签出。本页把这个账号叫「绑定账号」。你的能力等于绑定账号的权限:绑定账号做得到的事,你都做得到;绑定账号做不到的事,你也做不到。另有四件要授权里勾选过对应的保留范围项,见「八、四个保留范围项」。
你写下的每一处改动都记在绑定账号名下。你发布的单篇,作者是绑定账号;你回复的工单,回复人是绑定账号。
按下面的顺序做:
- 读「二、能做什么,不能做什么」,确定用户的任务归哪个域、需要哪一档授权。
- 还没有连接时,按「三、连接与身份」完成连接。授权的最后一步要用户本人在浏览器里点同意,你不能替他点。
- 连接成功后第一步调
permissions.retrieve,确认绑定账号和能力清单。 - 读「四、通用规矩」。这一节的规则适用于所有任务。
- 任务要写稿或排版时,先取技能包,见下面「技能包:写稿排版的手册」。技能包比本页细,讲的是怎么写、怎么排、画面怎么做。
- 用
aifa_find找到任务要调的方法,在「六、常见流程」里找到最接近的一条方法链;写稿排版按技能包的步骤做,最后几步都是自查。 - 工具报错时查「七、报错怎么读」。遇到「八、四个保留范围项」里缺范围项的情况,停下来告诉用户。
- 做完后按「十、做完之后怎么汇报」交付。
读取方式:本页的纯文本(Markdown)版本在 https://afa5.chaos.callai.online/mcp-guide/details.md,内容与 HTML 版完全相同,Agent 优先读它。速览那一页同样有纯文本形态 https://afa5.chaos.callai.online/mcp-guide.md。四个地址都不需要登录。连接 MCP 和调用工具才需要授权。
方法索引在速览页,由服务端从资源 API 规格实时生成,带每个方法的档位。正文与它不一致时,以索引和工具自己的说明为准。
技能包:写稿排版的手册
本页讲的是系统怎么连、有哪些工具、按什么顺序做事。怎么写一篇 AIFA 的单篇、版面怎么排、可交互的画面怎么做,写在技能包里。技能包是若干份 Markdown 手册加参考范例源码,和本页一样不需要登录。
要让另一个全新的 Agent 接入,不必把本页整页交给它:入口技能文件 https://afa5.chaos.callai.online/mcp-guide/skills/SKILL.md 只有一页,讲清连接、授权与该取哪个技能包,再指回本页。
两种取法,内容完全相同,取一种即可:
- 站点地址:清单在 https://afa5.chaos.callai.online/mcp-guide/skills(JSON,列出每个包、每个文件与它的取用地址);单个文件按清单里的
files[].url取,形如https://afa5.chaos.callai.online/mcp-guide/skills/aifa-interactive-canvas/SKILL.md;整包一次拿走用 https://afa5.chaos.callai.online/mcp-guide/skills.zip。清单里的version是内容指纹,内容没变它就不变。 - MCP 工具:
aifa_skill取清单,aifa_skill按path取正文。两个工具都不需要权限,作者档与全部档都调得动。
哪一本管什么:
| 技能包 | 管什么 | 什么时候读 |
|---|---|---|
aifa-author | 作者线必读(文件模型、物理规则、七步流程、索引);做画面与配图前必读媒介边界;参考区:物理契约、排版规则、编辑札记、双端编排、字体文件。 | 写任何一篇之前先读 aifa-author/SKILL.md,用 aifa_skill 取;它不随建稿返回自动送达。 |
aifa-article-multimedia | 整篇创作的地图:从拆解原稿、调研、论点卡、一块一个制作者,到外部盲审、实拍交互、手机真实滚动与发布,每站手上有什么、下一站去哪。 | 写新的一篇时按需读。 |
aifa-magazine-layout | 整期的编排:单篇顺序、合集封面封底、块序列排版总纲、检查。 | 把好几篇组成一期,从它起手。 |
aifa-interactive-canvas | 自定义画面块(canvas)的地图:从论点卡到一块画面的各站、指向原稿的动作问法、沙箱与版面的地形、讲形式为何适合论点的范例。 | 要做会动的或可交互的画面时读。 |
aifa-block-<变体> | 每个块一本(如 aifa-block-pull-quote):这一块写什么、放在哪、行数怎么定;字段形状以 /mcp-guide/schema 的 block/<变体> 为准。 | 写某一种块拿不准时读那一本。 |
aifa-magazine-editing | 改一个已有的单篇:润色、补译、换图、定点修订。 | 用户给的是已有单篇而不是新稿时读。 |
aifa-publish-review | 发布前按物理契约逐条审核,只读不改,结论是通过或退回。 | 要为一期出审核意见时读。 |
分工:技能包讲怎么写、怎么排;本页讲怎么连、按什么顺序调工具;字段名、取值与上限由工具自己的说明、文件提交的拒收回执与内容声明的 JSON Schema 当场给出。技能包的主线只用 MCP 工具就能走完;标着「仅限有代码仓的内部流程」的附录,没有代码仓就跳过。
二、能做什么,不能做什么
总原则
MCP 的能力覆盖管理后台的全部能力,也覆盖编辑台的全部能力。界面上能做的事,对应的工具也能做;工具不比界面多放权限。
授权分三档,详见「三、连接与身份」:
- 读者档(
scope=reader):只替读者办事——找已发布的单篇与合集并读正文(付费内容按账号权益裁剪,与网页同一判定)、查作者与作品、看首页推荐,以及资料、收藏、关注的作者、阅读进度、会员与订单、留言、自己的 AI 能力开关与账单。不能写稿,也碰不到后台。 - 作者档(
scope=author):创作这一面。任何登录账号都有作者身份。 - 全部档(
scope=full):绑定账号在 AIFA 的全部能力,包括管理后台。前提是绑定账号本身有后台角色。全部档令牌的能力仍然等于绑定账号自己的角色:客服账号拿到全部档,也只能做客服的事。
目前没有工具的事
下面这些事现在真的没有工具。用户要求时,直接告诉用户需要他在网站上操作,不要用别的工具拼凑。本清单 2026-09-19 逐条对照工具注册表核过。
- 新建账号。账号由本人在网站注册产生,没有建账号的工具。
- 账号清单导出、数据看板的 CSV 导出。
ai_accounts.retrieve(facet=facts) 只给 JSON 行。 - 把文字转成语音。系统不做配音、不克隆声音、不写口播稿(2026-09-21 撤销):单篇的伴读音频只能上传现成的音频文件(
narrations.update或media.create(target="asset")传audio/*素材,再用aifa_push按语言写进article.json的audioAssetId({zh?, en?})挂上去)。音频要用户自己提供,或你在站外自己做好再传进来。
三、连接与身份
地址
| 项 | 值 |
|---|---|
| MCP 地址(唯一入口,读者、作者与后台都连它) | https://afa5.chaos.callai.online/mcp |
| 传输方式 | Streamable HTTP。同一地址接 MCP 2026-07-28(无状态)与 2025-11-25(会话)两版协议,按请求自动判版,支持流式响应。不要用 stdio 方式连接这个地址。 |
| 受保护资源元数据 | https://afa5.chaos.callai.online/.well-known/oauth-protected-resource/mcp |
| 授权服务器元数据 | https://afa5.chaos.callai.online/.well-known/oauth-authorization-server |
| 授权端点 | https://afa5.chaos.callai.online/api/oauth/authorize |
| 令牌端点 | https://afa5.chaos.callai.online/api/oauth/token |
| 动态客户端注册 | https://afa5.chaos.callai.online/api/oauth/register |
情况一:你的客户端支持远程 MCP 与 OAuth(多数情况)
把 MCP 端点加进客户端配置,不填任何密钥。客户端一连上就收到 401,自动完成元数据发现、动态注册和 PKCE,给出授权链接:Claude Code 跑 claude mcp login <服务名> 打印链接(交互终端里直接打开浏览器),或在会话里进 /mcp 选这个服务点 Authenticate;会话中途加的服务要重开会话才出现工具。VS Code、Cursor、网页版 Claude、ChatGPT 在 MCP 或「连接器」设置里添加后点连接即弹。用户在浏览器里登录 AIFA、选档位、点同意。令牌由客户端保管和刷新。
通用 JSON 配置(键名可能是 mcpServers 或 servers,以你的客户端文档为准):
{
"mcpServers": {
"aifa-magazine": {
"type": "http",
"url": "https://afa5.chaos.callai.online/mcp"
}
}
}命令行客户端的等价命令(以 Claude Code 为例):
claude mcp add --transport http aifa-magazine https://afa5.chaos.callai.online/mcp && claude mcp login aifa-magazine你自己无权修改客户端配置时,把 MCP 端点地址交给用户,请他在客户端的 MCP 或「连接器」设置里添加,然后继续。
情况二:你要自己实现授权(OAuth 2.1 授权码 + PKCE)
- 不带令牌请求 MCP 端点,得到 401。响应头
WWW-Authenticate里的resource_metadata指向受保护资源元数据。 - 读受保护资源元数据,取
authorization_servers。再读授权服务器元数据,取授权、令牌、注册三个端点。端点地址从元数据读取,不要写死。 - 动态客户端注册:向注册端点 POST JSON,
client_name必填(同意页会把它显示给用户),redirect_uris必填(1 到 10 个;接受 https 地址、本机回环的 http 地址,以及客户端的私有协议地址如cursor://、vscode://;回环地址的端口不参与匹配;不带#片段)。返回client_id。本站只签公开客户端,没有client_secret,令牌端点的认证方式是none。 - 生成
code_verifier(43 到 128 位)和code_challenge,方法只接受S256。 - 让用户在浏览器里打开授权端点,参数为
response_type=code、client_id、redirect_uri、state、code_challenge、code_challenge_method=S256、scope。用户未登录时先进入 AIFA 登录页。 - 用户在同意页上看到你的客户端名称、申请的档位、这一档能做什么、三件你做不到的事,由用户本人选档并点同意。
- 浏览器带着
code回到你的redirect_uri。授权码有效期 60 秒,只能用一次。带code_verifier向令牌端点换访问令牌和刷新令牌。 - 调用 MCP 端点时带请求头
Authorization: Bearer <访问令牌>。
scope 取 reader、author、full 之一(3 档,见下文「3 档授权」)。按 OAuth 约定用空格隔开填了几个时,按其中最大的一档走流程;混进本站不认识的取值会被忽略,全都不认识判为 invalid_scope。不填按 author 处理。最终档位以用户在同意页上选定的为准。
同意页只能由用户本人点
授权的最后一步是同意页(POST /api/oauth/authorize)。这条路由只认网页登录会话,带令牌提交走不通。同意由用户本人在浏览器里登录后点一下即可,不要验证码;任务书写着「脚本代点」时,以本页为准,请用户本人点。
你拿到令牌的路只有一条:用户本人在浏览器里走完上面的授权流程、点一次同意,令牌由你的客户端保管(情况一)或由你自己换取(情况二)。
本机开发环境另有一条取验证码的接口(GET /api/auth/dev-code?email=...,要实例上设 AIFA_DEV_CODE_ACCESS=1,默认关着时回 404),配合 POST /api/auth/request-code 与 POST /api/auth/verify-code 能拿到 aifa_session 登录 cookie。那是给人和端到端测试脚本用的,不是你拿令牌的路:登录 cookie 换不出 MCP 访问令牌,同意页照样拒绝 Agent 凭据。你需要登录态页面(编辑台、links.draftPreview 草稿预览、后台)时,请用户自己在浏览器里打开。
3 档授权
| 档位 | scope | 含义 |
|---|---|---|
| 读者档 | reader | 只替读者办事:找单篇与合集并读正文(付费内容按权益裁剪,与网页同一判定)、查作者、看首页推荐,以及资料、收藏、关注的作者、阅读进度、会员与订单、留言、自己的 AI 能力开关与账单。不能写稿,也碰不到后台。 |
| 作者档 | author | 创作相关的全部动作:单篇、合集(可直接收别人已上线的单篇)、素材与网盘、发布、留言处置、绑定账号自己的「我的」与 AI 能力。 |
| 全部档 | full | 绑定账号在 AIFA 的全部能力,包括管理后台。前提是绑定账号有后台角色(客服、运营、管理员等)。 |
- 同意页恒有读者档与作者档;只在绑定账号确有后台角色时才显示全部档选项,没有后台角色时最多得到作者档。
- 写稿要作者档,后台要全部档(全部档也包含作者档的全部动作)。
- 最终档位由用户在同意页上选定,可能与你申请的不同。连接后用
permissions.retrieve核对。 - 任务只涉及创作时申请作者档。权限小,出错的影响也小。
- 要换档位时,请用户在网站「我的 → Agent」里吊销当前授权,再重新授权。你自己不能吊销或新增授权。
令牌与会话的期限
- 访问令牌有效期 8 小时。刷新令牌有效期 15 天。
- 刷新令牌每用一次就换新的一对令牌,旧的刷新令牌立即作废。再次使用旧的刷新令牌,或并发刷新两次,服务端按重放攻击处理,会吊销整条授权。吊销后只能请用户重新授权。
- 刷新时可以把全部档收窄为作者档,不能把作者档扩为全部档。
- 管理员对绑定账号执行「吊销全部访问」(
accounts.revoke_sessions或后台同一个按钮)时,绑定账号的浏览器会话、名下全部 Agent 授权、这些授权签出的全部令牌一起作废。你的令牌此后一律 401,刷新也失败,只能请用户重新登录并重新授权。 - 旧版(2025-11-25)会话号自签发起 24 小时有效,过期后带旧的
mcp-session-id调用会得到 404,重新initialize即可;会话不存业务状态,换会话不丢任何东西。新版(2026-07-28)请求没有会话。 - 会话被回收或重建后,会话内的状态全部丢失;业务状态不存在会话里,重新
initialize即可接着做。
连接后的自查
连接成功后第一步调 permissions.retrieve。它返回的字段分两类,不要混用。
按本次令牌收窄过的(回答「我现在能做什么」):
principal:绑定账号。核对邮箱是用户本人要你代表的账号。capabilities:能力清单,已按档位收窄。只有content.*几项,说明这是作者档,或绑定账号没有后台角色。出现site.*、crm.*、accounts.manage等,说明这是全部档且绑定账号有对应角色。entries:够得着的后台入口,已按档位收窄。
只作背景、不能拿来判断能不能做某件事的:
grants:绑定账号被授予的角色与数据域。账号只分作者(每个账号自带)、运营、管理员三种角色。只列本令牌整套用得上的角色:全部档原样,作者档只剩作者,读者档为空。roles:grants里出现的那几个角色各含哪些能力。
判断能不能做一件事,只看 capabilities。
发布自己的单篇要 content.write;发布别人的单篇要数据范围为全部的 content.write,且令牌是全部档。
tools/list 返回的工具清单按令牌的能力收窄:够不着的工具不列出。所以你在 tools/list 里看到的工具数,通常少于工具目录写的全集数。没列出的工具直接调用,服务端仍然返回 403。取不到能力时服务端退回全量列出,因此「列出」不等于「有权调用」;能否调用以 capabilities 和工具目录的「档位」列为准,不要靠逐个试错。
连接失败时的排查
| 现象 | 原因 | 处置 |
|---|---|---|
| 无法确定服务是否在线 | — | 调 system.retrieve:它不看角色,作者档与全部档的令牌都调得动(不带令牌回 401)。连这个也不通,说明端点地址或网络有问题。 |
401,WWW-Authenticate 带 invalid_token | 访问令牌过期或已被吊销 | 用刷新令牌换新令牌。刷新也失败时,请用户重新授权。 |
| 刷新后仍然 401,文案写明「账号已停用」 | 绑定账号被停用 | 请用户联系管理员恢复账号,再重新连接。 |
| 401,文案写明「该授权已被吊销」 | 用户自己吊销了这条授权,或管理员吊销了这个账号的全部访问 | 不要刷新令牌,刷新不会成功。请用户本人重新走一遍授权。 |
| 刷新后仍然 401,文案是「访问令牌无效或已过期」 | 令牌不存在或已过期(被吊销的情况现在另有文案,见上一行) | 用刷新令牌换新令牌;刷新也失败就请用户重新授权。 |
| 401,文案写明「个人访问令牌已到期」或「个人访问令牌已被吊销」 | 用户在账号页签发的固定令牌(aifa_pat_ 开头)过了有效期,或被用户吊销 | 个人访问令牌不能刷新。请用户在「我的 → Agent」重新签发一把,由他本人填进连接器设置或环境变量 AIFA_TOKEN,不要让他贴进对话。 |
授权回跳带 error=invalid_scope | scope 的取值本站一个都不认识 | 填 reader、author、full 之一(填了几个时按其中最大的一档走)。 |
注册返回 invalid_redirect_uri | 回调地址是非回环的 http 地址、javascript: 这类危险协议,或带了 # 片段、用户信息、空白字符 | 改用 https 地址、本机回环的 http 地址,或客户端自己的私有协议地址。 |
换令牌返回 invalid_grant | 授权码超过 60 秒、已用过,或 code_verifier 不匹配 | 从授权端点重新走一遍,拿到授权码后立即换令牌。 |
| 同意页没有全部档选项 | 绑定账号没有后台角色 | 请用户换一个有相应角色的账号,或请管理员用 permissions.update 先授予角色。 |
| 用户在浏览器里授权后登录态丢失 | localhost 和 127.0.0.1 是两个主机名,Cookie 不互通 | 全程使用同一个主机名。以本页地址栏里的主机名为准。 |
| 404「会话不存在或不属于当前身份」 | 会话空闲超时,或令牌刷新后沿用了旧会话号 | 重新 initialize。 |
四、通用规矩
先读后写,带版本号
- 每个工具都是对本站 HTTP 接口的薄封装。鉴权、校验、事务、版本检查都在服务端执行,MCP 这一层不做判定,也无法绕过。
- 写入前先读,拿到当前版本号,写入时作为
expectedVersion传回。单篇与页的版本号都从aifa_pull读:索引article.json的version、各页在readonly.pageSummaries[].version,单篇版本号在readonly.workflow.articleVersion。入参里没有expectedVersion的写工具不传它,传了会被严格入参拒掉;这类写入后写覆盖先写,合集的各个写工具就是这样:写前先读,写后回读核对。 - 整篇按文件读写(方案 §5.2):
aifa_pull缺省只回索引article.json(单篇字段、页序pages、readonly.pageSummaries里各页的pageId与版本号),paths取页文件pages/<pageId>.<zh|en>.md、画面文件canvas/<pageId>/<blockId>.html、来源清单sources.json与朗读时间轴audio-timeline.json(后两个从索引拆出,按需读);aifa_push一批文件一个事务、全成全败。写入带的expectedVersion跟页走、不看文件新旧:索引article.json、封面画面canvas/cover.html、sources.json、audio-timeline.json看索引的version;页文件与画面文件看所在页的version,已有页下这一批才新建的画面文件也一样;只有本批用newPages成对占位的新页不带版本号。写入回执receipt按块给声明框高rows与内容高contentRows(中英各一);声明不足时回执报最小行数minRows,声明值不改。 - 串接(可选):同一语言的页文件里给几个正文块写同一个
chain=<链名>,链首写带空行分段的整段文字,服务端按页序、块序把第 i 段放进第 i 框,一框一段;段多于框时回执receipt.chains报「需再加 N 框」并在unplaced原样带回多出的段,段比框高就在框内滚动(回执overflowRows)。链跨页时链上各页要同批写;只有正文能入链。 - 引用收藏里的块(T3294):中英两份页文件各写一个简写块 ``
block id=<新块 id> cite=<收藏条目号>`([[tool:library_items.list]](facet=bookshelf) kind=block 的itemId),宽度、块高与内容由服务端按原块补全,原样置入、只能挪位置,写了不一样的整批 400(rule:"cite_modified");只能引自己收藏里的、原文在线、原文不是付费单篇、与上下文无关的块(付费块可以引,读者按原作者的价格与权益判),不在收藏、原文是付费单篇、留言与阅读助手等互动类、来源与目录、已下线各自 400 带 rule 与改法;回执cites写明落在哪页、原块状态、所在页行数账与新旧版本号;读回时开头行带cite=、[[tool:aifa_pull]] 另回cites段(出处与状态 current/updated/offline),updated时把 cite 改写成refresh` 换新版(中英两份页文件写一份即可,两种语言一起换;两份写了不同的条目号 400 rule:"cite_conflict")。被引块的来源跟着原文走:引入时快照原文的来源条目,引用处照印,不必写进自己的 sources.json。 - 版本不符时返回 409,服务端不自动重试。正确做法:重新读取,比较差异,保留对方的改动,再决定怎么写。只更换版本号、把旧内容原样重发,会覆盖别人的改动。
- 用户只要求改某一处时,只改那一处。不要顺带补英文、换图或重排其他内容。
读取有体积上限,大的读工具分段取
编辑与合集线的读工具一次最多回约 100KB。collections.retrieve、articles.preview、articles.check、articles.releases.list、articles.list 都收 offset/limit,返回体里的 page 说明总数与下一段起点;aifa_pull 读大文件时只传那一个路径,按上次的 nextOffset 接着取。collections.retrieve 默认只给篇目,要页与块传 include。
- 后台各列表工具都收
offset/limit并回total,默认一页 25–50 条,上限 100 条。要全量就照total逐页翻,别把limit往大里填。 page.hasMore为真就拿nextOffset再调一次。page.cappedBy是"bytes"时,这一段是被返回上限截短的,不是数据到头了——照样接着取。
入参约定
- 用 OAuth 令牌时不要传
onBehalfOf。令牌已经绑定账号,服务端读到访问令牌就直接取令牌绑定的账号,根本不读这个参数。部分工具说明里写着「Agent 令牌必须传 onBehalfOf,缺失返回 403」,那句话只适用于开发通道(共享密钥方式,生产环境默认关闭)。 - 你的全部动作都记在绑定账号名下。运营账号(全部档、数据范围为全部)可以直接改别人的单篇:字段、页、伴读音频、助手配置与版本回滚,也能替作者发布、撤回候选(直接上线还是进审,看这篇作者的认证,不看发起人;运营自己批准自己发起的候选不受限),改动记在绑定账号名下,版本记录标
operations:agent;能不能改看permissions.retrieve的contentReach.writesAll。合集与单篇同一条规则:运营账号也能直接改别人的合集——名称简介符号目录图、清单增删、重排、封面封底、合集自带页,也能替创建者发布;往合集里收单篇时「是不是别人的」看合集创建者,不看动手的运营:创建者自己的稿草稿也收,别人的要已上线、未屏蔽。代写或代排完成后要交还作者,用articles.transfer或articles.transfer(action=collection) 把归属转给作者的账号:作者随后在自己的作品列表里看到它、能接着改,署名与线上版本不动,你照样能改;单篇转交回执里version是版本记录追加的那一版,接着写article.json要带的是indexVersion。作者档令牌只够绑定账号自己的稿件与合集,账号本身的数据范围再大也一样,别人的单篇与它的助手配置都读不到、改不了,也发布不了、撤不回;别人的合集同理。 - 工具入参是严格校验的:写了工具没有声明的参数名,整次调用会被拒绝(
Invalid arguments)。按工具的inputSchema写参数名,不要猜。 - 同一个概念在不同工具里可能用不同参数名:合集的 id 在一些工具里叫
collectionId,在另一些里叫issueId,是同一个值;网盘文件的 id 叫mediaId,素材的 id 叫assetId,是两套存储、两种 id,不能互换。 - 标注「也接受 JSON 字符串」的参数(如
blocks、fields、timeline),优先直接传对象或数组。 - 调用模型的工具(
articles.translate、articles.run_ai(action=compose_aids)、articles.run_ai(action=glossary))按 Token 计费,记在绑定账号上。你自己能翻译和写作时,不需要调用它们。翻译优先由你提供:双语字段直接两侧一起写,不必先写一侧再调articles.translate;网站自己的翻译只作兜底——你漏了一侧,articles.check会在发布前提醒(不阻断),标题、栏目与来源名称这几处发布时还会自动补上,块内容没有这条自动兜底。署名不在这条自动兜底里:署名只能引用账号,展示名单语,没有「两侧」这回事。
动手前先确认的动作
系统允许你独立完成下面这些动作。用户的指令已经明确点名这个动作和对象时,直接执行。用户的指令没有明确点名时,先向用户确认对象和后果,再执行:
media.delete:删除网盘文件,不可撤销。先确认没有内容引用它。collections.delete:删除未发布的合集,不可撤销;单篇本身不受影响。articles.unpublish(作者下线自己的)与review_items.update的unpublish(运营下线任何人的):单篇下线,读者立刻看不到;再发布即重新上线。moderation_items.moderate的removed:删除已发内容,前台不再显示;可改回approved恢复,被站点内容引用时先取消引用。accounts.update把status改为disabled:该账号此后无法登录。permissions.update:整组覆盖一个账号的角色,不是追加。对绑定账号自己也能执行,系统只拦「删掉最后一名管理员」,不拦你把自己的角色改没。accounts.revoke_sessions:对方的浏览器会话、Agent 授权、令牌一起作废。orders.refund:给订单退款。ai_accounts.adjust_balance、ai_settings.update、review_settings.update、jobs.update:影响其他账号或全站行为。
Schema 从哪读
字段规则只有一份真源:校验器、字段说明、MCP 入参与对外的标准 JSON Schema 都从同一份声明投影出来,不会一处改了另一处忘改。要机器可校验的那一份,取 https://afa5.chaos.callai.online/mcp-guide/schema(JSON,匿名可读,不需要登录)。
- 分五层:
block(五类共用的骨架)、block/<变体>(20 份,各变体的内容字段)、page(页与栅格的参数与上限)、article(单篇级字段)、collection(合集可写面)。不传name回目录。 - 算不出来的规则不混进
properties:输入是整页块序列的序列级算法在x-computed,输入超出单个字段的判定在x-hook,两者都写明真源函数在哪。读得到写不进去的字段标readOnly;传null表示清空那一格的字段标x-null-clears;已退役的键在x-retired。 - 声明默认宽松:没有登记的键一律忽略,不是报错。所以按 Schema 校验通过不等于版面合规——容量、行数与内容完整性仍归
articles.check。 version是内容指纹,内容没变它就不变;HTTP 那一条带etag,可以缓存。- 排版之前看一眼一种块怎么写,读块技能
aifa-block-<变体>(skills.retrieve取):那是一份人读说明,带用途与注意事项。两件事两个入口,不混在一个返回体里。
工具说明里写什么,不写什么
tools/list 里每条工具说明只写三样:这个工具做什么、改变调用形状的约束(必填、互斥、单位、枚举、乐观锁、清空语义)、失败回执要怎么处置。其余口径不进说明,都在这一页,按需读一次即可。
- 档位与权限:调用它至少要哪一档授权,看页末工具目录的「档位」一列。够不着时服务端返回 403 并点名缺哪项能力,不必先自查;要自查用
permissions.retrieve。 - 决策出处与沿革(第几条、哪一天、哪个任务号)一律不进说明:它们对这一次该怎么调没有作用。
- 块坐标:块本身没有坐标字段,位置由顺序、宽度档与留白块排出来。
articles.preview给现算坐标——topRow从版心第几行开始(1 起)、bottomRow占到第几行为止、visualRow第几个视觉行(并排的两个半宽块共用一个)、column横向位置(full整幅、left左半、right右半,落单的半宽块是left)。往前插一块留白(blank)就整体下移,改宽度档就换列。 - 写页回执:
aifa_push不回你刚交的内容,也不回全文——回执逐文件给版本号;落盘那份与交上去的不同时标stored:normalized只差空白与写法,rewritten是服务端改了内容(裁图换了素材号、规整摘了字段、新页占位名换成页号,改了什么在changes),generated是它代你生成的那一份,要全文用aifa_pull按paths取。receipt.blocks只列有问题的块,其余记blocksOmitted,全量用articles.check的include:["measured"];单次回执上限 12000 字节。页级校验结果issues挂在这一页的第一个文件上(没有问题不出现),与编辑台画布上的红角标同一份,逐条带blockId。越页、并排不等高、低于最小行数这类物理规则当场 400、整批不写,同一批里的问题一次列全;其余只报告不拦截。回执另带publishCheck(发布前检查的拦截数与提醒数,有拦截时first给至多三条)与一句next:没有拦截项时给发布调用(带expectedVersion),有就指向first与articles.check。内容完整性(双语、必填、示例内容)的全量结果归articles.check,按页查传pageId。 - 要人确认的动作、分页口径、版本号从哪读,分别见本节其余几条与说明全文的「九、要人确认的事」(作者档没有落进那一档的工具)。
五、方法与域
全部能力经单一入口 https://afa5.chaos.callai.online/mcp 调用,一次授权。规格按资源域分侧实现:杂志设置与审核队列、内容审核(屏蔽与删除)、技能包与作品包、留言、素材与媒体、单篇与工作流、合集、阅读与读者 由杂志侧实现;运维探活与版本、Agent 授权与 OAuth、统计、外链登记、服务交付(工单、资料交付、线索、反馈)、账号资料与作者主页、消息 im(独立服务)、信息流 feed(独立服务)、外壳与书架、计费与权益 由宿主侧实现;需确认动作、收藏与块引用、页与块、模型调用与额度 两侧各有方法。调用时不用区分方法归哪一侧。
有哪些方法,看速览页的方法索引(服务端从规格现算);一句话找方法用 aifa_find。每个方法的入参、返回字段、状态码、报错码与边界规则写在规格的方法备注里,不在本页逐条抄:aifa_describe 传方法 ID,回执的 note 就是这一段,errors 是它可能回的全部报错码(规格里带备注的方法共 271 个)。
单篇、页、块与合集的概念、文件格式与版面物理规则写在技能包里:写稿必读 aifa-author/SKILL.md(aifa_skill 取),每种块的写法在块技能 aifa-block-<变体>,字段的机器口径在 /mcp-guide/schema。
六、常见流程
每条流程都从连接完成之后开始,并且默认你已经调过 permissions.retrieve。逐步写法与自查在技能包里,这里只给方法链;每一步的入参用 aifa_describe 取。
| 流程 | 方法链 |
|---|---|
| 从写稿到发布(作者档) | 照必读 aifa-author/SKILL.md 走:aifa_pull → 改文件 → aifa_check → aifa_push → articles.check → articles.preview_links.create 给人看 → articles.publish |
| 修改已发布的单篇(作者档) | articles.request_revision 开修改稿 → 文件三步 → articles.publish 进审;放弃修改用 articles.discard_revision |
| 文件上传(作者档) | uploads.create 取上传凭证 → PUT 字节 → media.create 入库,页文件里引用回执给的素材号 |
| 组一个合集并发布(作者档) | collections.create → collections.items.batch_add → collections.check → collections.publish |
| 处置单篇下的留言(作者档) | comments.list → comments.batch_moderate |
| 审核单篇、下线单篇(全部档,运营角色) | review_items.list → review_items.update 或 review_items.batch_decide |
| 账号、角色与 AI 额度(全部档,管理员角色) | accounts.update、permissions.update、ai_accounts.adjust_balance(要人确认,见第九节) |
七、报错怎么读
调用出错时,工具返回带 isError 的文本,通常以 HTTP <状态码> 开头,后面是服务端的错误信息;reason 是机器可读的原因码。先读原因码和文案,再决定怎么做。同一个错误不要原样重试。
| 状态 | 含义 | 处置 |
|---|---|---|
Invalid arguments | 参数名或参数类型不符合工具的 inputSchema。请求没有到达服务端。常见的有:expectedVersion 传了 null(它只收数字,页的版本号在 article.json 的 readonly.pageSummaries[].version);expiresIn 传了 "1h" 这类字符串(它是数字小时数)。 | 对照 inputSchema 修正参数名与类型。不要换别的工具尝试。 |
| 400 | 参数不合法或缺少必填项。例如审核动作缺 note;aifa_push 的 newPages 不成对;article.json 的 backCoverColor 不在五色板里;articles.preview_links.create 的 expiresIn 不是 0.25、1、24、168;上传时 filePath、base64、ticketId 给了不止一个。 | 按错误信息补全或修正参数。 |
| 401 | 没有带令牌,或令牌过期、已被吊销,或绑定账号被停用,或绑定账号的全部访问被吊销。 | 刷新令牌。刷新后仍 401,按「连接失败时的排查」告诉用户。 |
| 403,文案含「此授权为作者档」 | 档位不够。 | 告诉用户需要重新授权为全部档。不要重试。 |
| 403,文案写明「不属于你」 | 对象不属于绑定账号(别人的单篇、别人单篇下的留言、别人上传的网盘文件),或令牌是作者档。 | 核对 id。确实是别人的单篇时,改它要绑定账号持数据范围为「全部」的内容写权限并授权全部档,告诉用户。 |
| 422,文案写明「封面不是块页」 | 对封面那个派生页 id 写了页文件。封面由字段生成。 | 改 article.json 的 title/byline/coverImage/coverFocal/coverMedia/coverFrame;合集封面改 collections.update。 |
| 422,文案写明「封底不是块页」 | 对封底那个派生页 id 写了页文件。封底是纯色底、站标、编号。 | 单篇封底底色改 article.json 的 backCoverColor,合集封底改 collections.update 的 backCover.color。 |
| 403,文案写明「数据范围」 | 能力够,但账号的数据范围只到「已指派给我的」,这一条归了别人。 | 告诉用户请管理员把数据范围放宽为「全部」。 |
| 403,其他文案 | 绑定账号没有这项能力。 | 用 permissions.retrieve 的 capabilities 核对。确实没有时告诉用户。 |
403 reserved_scope_missing | 凭据缺这项保留范围项(见第八节)。 | 停下,告诉用户缺哪一项,由他决定重新授权勾选或自己在网页上做。 |
| 404 | 对象不存在;或 MCP 会话已被回收(文案为「会话不存在」);或短期预览链接已吊销。 | 对象不存在时重新列表核对 id。会话被回收时重新 initialize。 |
409 版本冲突(文案含「版本冲突」或 version_conflict) | expectedVersion 与服务端当前版本不一致。站点内容的 409 带 currentVersion 和 view。 | 重新读取,比较差异,保留对方的改动后再写。回执丢了、不知道上一次写没写进去时,原样重发同一批是安全的:aifa_push 认出重试,原样回首次的回执并带 replayed: true,不再落盘;articles.publish 重试回成功并带 unchanged: true。 |
| 409 其他原因码 | 当前状态不允许这个动作。常见的有:article_in_review 审核期间工作稿锁定;withdraw_not_allowed 没有可撤回的候选版本;article_not_published/article_blocked 要收的单篇没上线或被屏蔽;collection_last_item 已发布合集至少留一篇;name_taken、name_locked、icon_locked 等合集名字与图标的拒绝;工单已关闭;要删除的内容仍被别处引用(返回里带全部引用处)。 | 按原因码处理。这类 409 与版本无关,重新读取版本号没有用。 |
409 source_disabled | 用户关闭了这一处 AI 消费的个人开关。这是回执,不是故障。 | 改用不调用模型的做法,或在用户同意后用 ai_accounts.update 重新打开。 |
| 409(上传凭证) | 上传凭证还没收到字节就被拿去完成入库,或已经完成过一次入库;或凭证已封口(带密钥的 PUT 成功过一次)又 PUT 了一次。 | 先 PUT 字节;重试前重新调 uploads.create。 |
| 410 | reading_states.update 的页面不属于当前发布版本。 | 重新读取当前版本的页再写。 |
| 413 | 上传超出体积上限。 | 改用上传凭证两步上传,或确认文件没有超出目标的字节上限。 |
| 415 | 声明的 contentType 与实际类型不符,或不在白名单内(签发上传凭证时就判);PUT 时 Content-Type 头与建上传凭证时不一致。 | 核对类型。 |
422,带 violations | 内容超过契约的硬上限,没有写入。硬上限只有体积这一类:画面块源码字节、一页的块数、一篇的页数、单个文本字段的保护性上限。逐条列出了超限位置。 | 按列出的那一条缩减体积或拆开;字数与块高不在硬上限里,文字超出块高在块内滚动。 |
422 checks_failed | 发布前检查有阻断项,没有发布。 | 调 articles.check 读取逐条失败项,改完后再发布。 |
| 422,其他 | 图片外链抓取失败。 | 按错误信息修正。 |
| 423 | 这一页含人工锁定的内容。 | 不要尝试解锁。报告用户。 |
| 428 | articles.restore_release 缺 expectedVersion。 | 先读 workflow.currentVersion,再提交。 |
| 429 | 触发频率限制(登录取码、留言发送这类入口都限流),或绑定账号本月 Token 额度已用完,或全站同时有效的上传凭证已满。 | 频率限制时读响应头 Retry-After,按它给的秒数等一次再试,只试这一次。不要循环重试:重试本身会把限流窗口填满,等待时间只会越来越长。额度用完时改用不调用模型的做法,并告诉用户。 |
| 503 | articles.pages.render 出图排队已满或排队过久,或渲染服务暂时不可达;出图忙时先排队,不回 429。 | 按报错里给的秒数(HTTP 响应体 retryAfter)等一次再试,只试这一次;仍是 503 就先做别的,稍后再看。 |
| 「杂志系统不可达」或网络错误 | 服务端暂时不可用。 | 用 system.retrieve 探测。间隔一段时间后重试,最多三次;仍然失败就告诉用户。 |
articles.check 把「字段类型不对」(例如给单语字段塞了 {zh, en} 对象)也报成「未填」。看到「未填」而你确实填了时,先核对这个字段是单语还是双语。
八、四个保留范围项
四件事要凭据持有对应范围项
平台只认凭据与它的授权范围,不分人与 Agent、官方与第三方(A0471)。下面四件事各是一个保留范围项:用户在网页登录得到的全权凭据都有;转授给你的授权缺省一项不带,只有用户在同意页逐项勾选过才有。缺了就回 403 reserved_scope_missing,scope 写明缺哪一项。完成付款没有本站接口可拦,收银台在支付平台上。
| 范围项 | 事 | 对应接口 |
|---|---|---|
account.email.change | 修改登录邮箱 | POST / PATCH /api/accounts/me/email |
billing.pay | 完成付款 | 没有本站接口;下单、取消订单、申请退款不要范围项,见 orders.create(action=plan) |
agent-authorization.manage | 授权管理:签发、收窄、收回别的授权,批准设备码接入 | agent_authorizations.create、agent_authorizations.update、agent_authorizations.delete、device_authorizations.approve |
account.authenticator.manage | 绑定或解绑验证器、重新生成备用码、用验证器确认 | /api/accounts/me/authenticator、confirmations.approve |
授权只能收窄转授:你签出的授权,档位、只读与保留范围项都不能大于你自己这张。遇到 reserved_scope_missing 不要重试、不要换路径绕过;告诉用户哪一项缺了,由他决定要不要重新授权并勾选,或自己在网页上做。读授权清单、订单、登录邮箱不要范围项。
其他要停下来找用户的情况
- 授权同意页:必须由用户本人在浏览器里登录并点同意。
- 档位不够:请用户吊销后重新授权为全部档。
- 绑定账号缺少角色(全部档仍然 403):请用户换账号,或请管理员授予角色。
- 页面含人工锁定的内容(423)。
- 要凭口味定夺的事(版面是否好看、图是否切题):先用
articles.pages.render自己看过,再请用户打开预览链接定夺。 - 本月 Token 额度用完(429)或 AI 余额不足:额度由管理员调整,告诉用户。
- 「二、能做什么,不能做什么」里「目前没有工具的事」清单中的任何一项。
九、要人确认的事
有几件事你调得动,但调用只发起请求:系统不改动线上,把这一次调用冻住,回一条确认链接,人打开链接、填身份验证器上的验证码,才真的执行。这几条工具的说明第一句都写着这一点。验证码不经过你——任何情况下都不要向任何人索要验证码,验证码只填在那个页面上。这一类动作全要全部档,作者档的工具一条都不在其中,作者档的调用都直接生效。
哪几件
| 事 | 资源方法或登记名 | 谁来确认 |
|---|---|---|
| 退款 | orders.refund | 持 billing.manage 能力的人 |
| 核对订单 | orders.reconcile | 持 billing.manage 能力的人 |
| 保存套餐 | plans.update | 持 billing.manage 能力的人 |
| 调整 AI 余额 | ai_accounts.adjust_balance | 持 billing.manage 能力的人 |
| 改 AI 计价 | ai_settings.update | 持 billing.manage 能力的人 |
| 改平台抽成比例 | billing_settings.set_platform_fee | 持 billing.manage 能力的人 |
| 应用实验空间到线上 | workspaces.apply | 持 site.publish 能力的人 |
| 设置模型密钥 | ai_settings.set_provider_key | 持 accounts.manage 能力的人 |
| 清除模型密钥 | ai_settings.clear_provider_key | 持 accounts.manage 能力的人 |
| 放宽反滥用策略 | 资源方法 abuse_policies.update | 持 accounts.manage 能力的人 |
| 启用或推荐技能包 | skills.enable | 持 skills.manage 能力的人 |
清单之外的动作一条都不受影响,照常直接执行。ai_settings.update 按字段判:只有传了 tokenAnchor、usdRate、priceBook、tiers 其中任何一段才要确认,只改 providers 或 voices 照常直接生效。
怎么走完
- 照常调用那条工具。返回体第一项是
confirmUrl,第二项note是给你的交接话:这次调用没有改动线上,把链接交给人类,不要自己打开确认。其后是needsConfirm: true、confirmBy(要谁确认)、summary、eventId与expiresAt(30 分钟)。 - 把
confirmUrl原样发给confirmBy写的那个角色。链接不要求登录,他打开就看得到这一件的事实表;应用到线上那一条还带着预览地址,他会先点开看效果再填码。 - 用
aifa_confirm_read查结果,给了waitSec(最多 25 秒)就挂着等,人一确认立刻返回。status只有规格那一套词:succeeded带执行结果,failed带失败详情。 - 参数发现写错了,用
confirmations.cancel撤回这一件,链接随即失效,然后重新发起。
会撞到的几种回答
| 情形 | 怎么办 |
|---|---|
authenticator-not-bound(403) | 发起这次调用的账号(不是后面来确认的 confirmBy 那个角色)还没绑身份验证器,事件连生成都没生成。返回体里带一条 bindingUrl,把它交给发起这次调用的账号本人,绑完再重发这条动作 |
expired | 30 分钟没人确认。重新发起,拿一条新链接 |
canceled | 人在页面上否掉了,或发起人撤回了。不要重发,先问用户为什么 |
pending 且带 lockedUntil | 验证码连错 5 次,这一件锁 15 分钟。告诉用户几分钟后再试 |
failed 且失败详情列着几页 | 应用到线上时线上已被别处改过,一条都没写。回空间里核对那几页、改好,再发起一次应用。**没有强推这条路,不要去找** |
failed 且失败详情写着前值变了 | 动钱那几条在执行那一刻会重算一次前值:冻结时算的余额、订单状态或套餐版本已经被别人改过,于是一个字都没写。重新读一遍当前值,确认还要不要做,再发起一次 |
发起这条动作的账号自己不够格确认时(例如运营发起、要管理员确认),返回里的 confirmBy 已经写明要交给谁,照着说就行。
十、做完之后怎么汇报
用户通常不看工具调用的过程。任务结束时用用户的语言写一段简短的汇报,包含下面几项:
- 结果:做成了什么。写明对象的名称和 id(单篇、合集、空间、工单、账号)。
- 当前状态:单篇写明是草稿、待审、已上线,还是已上线但改动尚未发布。
- 给用户看的链接:草稿预览、短期预览链接(写明失效时间)、线上地址或空间预览地址,并说明打开它需要登录哪个账号。
- 自查结果:
articles.check是否通过,还剩哪些提醒项,你对它们的判断。 - 等用户处理的事:需要他本人做的动作、需要他确认的选择、你没有做的部分和原因。
- 消耗:调用过按 Token 计费的工具时,写明用了哪些。
不要把「写入成功」说成「已发布」,不要把「检查通过」说成「已审定」,不要把进入审核队列说成「已上线」,不要把「回复成功」说成「客户已收到」。
机器检查不能代替语义、事实来源和视觉的审核。