关于 Creatif Space
Creatif Space 是用于通过 AI 客户端管理社交内容的远程 MCP 服务,涵盖起草、审批、发布和报告,并在发布操作前提供预览与确认。
主要功能
- 01查看频道、帖子和文件
- 02起草和编辑社交帖子
- 03创建并跟踪审批链接
- 04预览并确认发布
- 05查看洞察与报告
适用场景
- 01为营销活动准备社交帖子
- 02将草稿发送给客户审批
- 03安排或重试社交帖子
- 04分享表现报告
MCP 相关
它将 Creatif Space 账户、内容、审批、发布和洞察操作作为 MCP 工具提供。服务使用调用者的 bearer token 访问现有 V1 API。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://mcp.creatif.space/mcpclaude mcp add --transport http creatifren-creatif-space https://mcp.creatif.space/mcp{"mcpServers":{"creatifren-creatif-space":{"type":"http","url":"https://mcp.creatif.space/mcp"}}}在 Cursor 中打开{"servers":{"creatifren-creatif-space":{"type":"http","url":"https://mcp.creatif.space/mcp"}}}在 VS Code 中打开{"mcpServers":{"creatifren-creatif-space":{"type":"http","url":"https://mcp.creatif.space/mcp"}}}{"mcpServers":{"creatifren-creatif-space":{"serverUrl":"https://mcp.creatif.space/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
creatif.space MCP 服务
面向 creatif.space 的远程 MCP 服务。连接器
URL:https://mcp.creatif.space/mcp(也支持 /)。采用 Streamable HTTP、无状态,基于 Node 22 和
官方 @modelcontextprotocol/sdk。
它只是一个薄薄的接入层:每个工具都使用调用者自己的 Bearer 令牌调用现有的 V1 API,因此所有权、套餐、Credits 和验证都由 Laravel 负责。此处不包含业务逻辑。
60 秒上手(Claude)
- 在 Claude 中,打开 Settings → Connectors → Add custom connector,将其命名为
creatif.space,并粘贴连接器 URL:https://mcp.creatif.space/mcp - 点击 Connect,登录 creatif.space 并授权访问。现在 Claude 可以看到 你的频道、草稿和审批链接。未经你同意,不会发布任何内容: 每次发送前都会先显示预览。
- 试着提出以下任一请求——每个请求都会运行一个现成的提示词(也可在 Claude 的
提示词菜单中找到):
- “规划下周内容:为我们的冬季新品发布准备 5 条 Instagram 帖子。” →
plan_week会在你的频道中起草这些帖子。只会生成草稿,不会发布。 - “把我的草稿发送给 [email protected] 审批。” →
send_for_approval会生成审批链接,供客户审批或提出修改意见。 - “这周表现如何?给我一个可以发给客户的链接。” →
weekly_results会汇总过去 7 天的数据,并生成任何人都能打开的链接。 - “为客户制作上个月的报告。” →
monthly_report会汇总整个月的数据,并生成同类链接。
- “规划下周内容:为我们的冬季新品发布准备 5 条 Instagram 帖子。” →
端点
| 路径 | 说明 |
|---|---|
POST /mcp(以及 POST /) | MCP JSON-RPC(需要 Bearer 令牌) |
GET /health | 存活状态检查,无需认证:{ok, name, version} — 与 serverInfo 中的版本相同(来自 package.json;参见 CHANGELOG.md) |
GET /.well-known/glama.json | Glama 连接器声明,无需认证(也支持 HEAD);相同文档也可通过 GET /mcp/.well-known/glama.json 访问 |
GET /.well-known/oauth-protected-resource | RFC 9728 元数据:resource: "https://mcp.creatif.space/mcp",authorization_servers: ["https://api.creatif.space"] |
GET /.well-known/oauth-protected-resource/mcp | RFC 9728 路径格式下的相同文档 |
POST /free | Creatif Space Free Tools — 独立的 MCP 服务,无需认证,每个 IP 每分钟 30 次调用 |
/mcp、/ 和 /free 上的 CORS(适用于浏览器客户端:MCP Inspector 网页版、Web IDE):OPTIONS → 204,并返回 Access-Control-Allow-Origin: *(不含凭据——仅通过 Bearer 请求头认证)、Allow-Methods: GET, POST, DELETE, OPTIONS、Allow-Headers: authorization, content-type, mcp-protocol-version, mcp-session-id, last-event-id、Expose-Headers: mcp-session-id, www-authenticate、Max-Age: 600。这些路径的所有响应(包括 401 和 429)都会包含相同的请求头。此功能由 Node 应用处理(src/cors.ts);nginx 会转发 OPTIONS 请求,且不得添加自己的 Access-Control-* 请求头。
缺少令牌或令牌无效 → 返回 401,并带有
WWW-Authenticate: Bearer resource_metadata="https://mcp.creatif.space/.well-known/oauth-protected-resource/mcp"(RFC 9728 路径格式,根据源站构建;根路径下的 well-known 端点提供相同文档)。
身份验证
令牌(Passport OAuth 2.1 访问令牌或 cs_live_… API 密钥)通过
POST {V1_API_URL}/oauth/introspect 进行检查,请求头为 X-MCP-Secret,请求体为 {token},返回
{active, user_ulid, scopes[], client_id, client_name, token_type, exp}。
检查结果会缓存 60 秒(不会超过 exp)。随后,同一 Bearer 令牌会转发到 V1 路由
(守卫 mcp,在 OAuth PR 中内置)。
作用域(scopes_supported):read、draft、approve、publish、approvals:decide——与 API 上
config/mcp.php 中的名称相同。每次 V1 调用都会携带 X-MCP-Tool 和
X-MCP-Client,供 API 的审计日志记录(不记录内容)。
速率限制:每个令牌每分钟 60 次请求(429 + Retry-After)。
客户端通过动态客户端注册(POST /oauth/register)或 OAuth 客户端 ID 元数据文档获取
client_id:client_id 是一个 https URL,提供 {client_id, client_name, redirect_uris, token_endpoint_auth_method: "none"}。API 会获取该文档
(仅限公共地址,不跟随重定向,≤ 5 KB,按照 Cache-Control 缓存
5 分钟至 24 小时),并声明 client_id_metadata_document_supported: true。
工具
| 工具 | 范围 | V1 端点 |
|---|---|---|
list_channels — 需要重新连接的频道会附带 reconnect {reason, next_step},并列在 needs_reconnect 中 | 读取 | GET /social-accounts |
list_posts (status: draft, waiting, changes_requested, scheduled, published, failed, cancelled;from/to 可设为日期或时间;channel_id, limit) — waiting / changes_requested 会按 status=scheduled 读取,并按审批状态筛选帖子 | 读取 | GET /social-posts?status&from&to&account_id&limit |
list_failed_posts (limit, cursor) — 最近 30 天内的数据;按频道显示 failure_code + reason;部分发布的帖子仅列出发布失败的频道 | 读取 | GET /social-posts?status=failed + ?status=published (from/to = 最近 30 天) |
get_post | 读取 | GET /social-posts/{id} |
list_files (search, type, folder_id, limit) | 读取 | GET /files |
draft_post (caption, channel_ids, file_ids, media_urls, captions_by_channel, type) | 草稿 | POST /social-posts,并设置 draft: true |
get_account_summary — 一次调用完成引导:套餐、已用/剩余限额、剩余 Credits、已连接/需要重新连接的频道、已用存储空间、failed_posts (最近 30 天)、approvals {waiting, changes_requested}、next_steps | 读取 | GET /credits, GET /social-accounts, GET /files/usage, GET /social-posts?status=failed + ?status=published (与 list_failed_posts 相同), GET /social-posts?status=scheduled |
get_onboarding — “Get started” 检查清单(连接、起草、发送、发布),每项包含 {done, at},以及 next {step, tool, suggest}:建议的下一步 | 读取 | GET /me/onboarding |
get_credits — 套餐、限额、Credits;spend (本周期按操作分类:publish, reply, ai) 和 renewal (resets_at, days_until) | 读取 | GET /credits (limits.spend) |
create_approval_link (post_ids — 或 Content Plan:date_from, date_to, timezone, channel_ids — approver_email(必填 — 客户端使用此邮箱登录并作出决定)、title, client_name, expires_in_hours) — 适用于所有套餐;Free:一位客户(按 approver_email 识别)、7 天窗口、最多 10 个排队帖子 | 审批 | POST /social-approval-links (接受草稿) |
create_content_plan (date_from, date_to, timezone, channel_ids, approver_email, title, client_name, expires_in_hours, confirm) — 先预览;confirm: true 会创建 Content Plan 并向审批人发送邮件 | 审批 | GET /social-accounts, GET /social-posts?from&to (预览);confirm: true → POST /social-approval-links,并设置 notify_approver: true |
check_approval_status (post_id | link_id) | 读取 | GET /social-posts/{id} 或 GET /social-approval-links/{id} |
send_approval_reminder (link_id) | 审批 | POST /social-approval-links/{id}/remind (每个链接每 12 小时一次) |
update_post (caption, scheduled_at, labels, file_ids | add_file_ids) | 草稿(仅限草稿和等待审批的帖子) | PATCH /social-posts/{id} |
schedule_posts (posts: [{post_id, scheduled_at}] 最多 10 个,confirm) — 一次预览所有帖子及 Credits 总额;confirm: true 会全部安排发布,否则全部不安排 | 发布 | 对每个帖子预览 GET /social-posts/{id}/send-preview;confirm: true → POST /social-posts/send-batch(先检查全部帖子;若有一个被拒绝,则撤回已发送的帖子) |
schedule_post (post_id, scheduled_at, confirm) | 发布 | 预览 GET /social-posts/{id}/send-preview;confirm: true → POST /social-posts/{id}/send |
publish_post (post_id, confirm) | 发布 | 相同,但立即发送 |
retry_post (post_id, confirm) — 再次发布帖子的失败频道;预览会显示各频道的 failure_code 和原因 | 发布 | 预览 GET /social-posts/{id}/retry-preview;confirm: true → POST /social-posts/{id}/retry |
get_insight_summary (period: {month} | {from, to} ≤ 92 天, channel_ids) — Pro / Max;Free → plan_required | 读取 | GET /insight/summary?month | from&to&channel_ids |
list_top_posts (period: {month} | {from, to} ≤ 92 天, channel_ids, limit, cursor) — Pro / Max;Free → plan_required | 读取 | GET /insight/top-posts?month | from&to&channel_ids |
get_best_times (days 7–92, channel_ids) — Pro / Max;Free → plan_required | 读取 | GET /insight/best-times?days&channel_ids |
get_insight_csv_link (from, to ≤ 366 天, channel_ids) — Pro / Max;Free → plan_required | 读取 | POST /insight/export-csv-link |
get_insight_report_link (from, to ≤ 92 天, format onepage|deck|details, channel_ids, locale) — Insight PDF 的 15 分钟有效签名下载链接(单页、16:9 演示文稿或详细报告);Pro / Max | 读取 | POST /insight/export-link |
create_insight_share_link (from, to ≤ 92 天, channel_ids, recipient_email) — Insight 报告的只读网页链接,无需账号即可访问,有效期 30 天;填写 recipient_email 后会向该邮箱发送一次邮件,对方也会在 list_shared_with_me 中看到报告 | 审批 | POST /insight/share |
revoke_insight_share_link (share_id) — 立即停用已分享的 Insight 链接 | 审批 | DELETE /insight/share/{id} |
request_media_upload (filename, mime, size_bytes, folder_id) | 草稿 | POST /files/presign → file_id + 预签名 PUT URL (15 分钟有效) |
confirm_media_upload (file_id) | 草稿 | POST /files/{id}/complete (409 → GET /files/{id}:返回已就绪的文件) |
list_conversations (type comment|dm, channel_id, unread_only, since, limit, cursor) — 在一个列表中显示 Engage 评论和私信,按最新优先排序 | 读取 | GET /inbox/feed?type&account&unread&since&per_page&cursor |
reply_to_conversation (conversation_id, text, confirm) — 在对话串中发送私信,或在评论下公开回复 | 发布 | 预览 GET /inbox/feed/{id};confirm: true → POST /inbox/feed/{id}/reply |
get_storage_usage — 已用空间与配额(Free:总计 1 GB;付费套餐:Keep 配额)以及保留与自动删除文件(按最早日期排序),统计最新的 300 个文件 | 读取 | GET /files/usage + GET /files?per_page=60&page=1..5 |
keep_file (file_id) — Pro/Max;Free → plan_required,配额已满 → storage_full,文件未就绪 (409) → file_not_ready | 草稿 | POST /files/{id}/keep |
unkeep_file (file_id) — 恢复适用保留规则;返回 auto_delete_at | 草稿 | DELETE /files/{id}/keep |
suggest_caption (brief, platform) — 按用户风格生成文案和标签;不保存任何内容。Pro/Max;AI_CAPTION_ENABLED 关闭时返回 404 → not_enabled(“请自行撰写文案”),Free → plan_required | 草稿 | POST /ai/caption |
discard_draft (post_id, confirm) — 仅删除草稿;先预览,confirm: true 后删除;scheduled / published / failed → not_draft 并提供下一步 | 草稿 | GET /social-posts/{id},然后 DELETE /social-posts/{id}/draft |
list_approval_links (status active|expired|revoked|all, limit) — 状态、审批人邮箱、帖子数量、已批准/等待中/需修改数量 | 读取 | GET /social-approval-links |
revoke_approval_link (link_id, confirm) — 先预览,然后永久撤销链接;未获答复的帖子会退回给用户 | 审批 | 先 GET,然后 DELETE /social-approval-links/{id} |
list_waiting_approvals — 其他用户发送给此用户审批的帖子 | approvals:decide | GET /me/approvals/waiting |
decide_approval (link, post_id, decision approve|revise, reason, confirm) — 审批人端;规则与审批页面相同,审计记录为 mcp | approvals:decide | 预览 GET /me/approvals/{post}/preview;confirm: true → POST /me/approvals/{post}/decision |
list_spaces (status draft|published|archived, search, limit) — Pro/Max | 读取 | GET /spaces?tab&search |
create_space_from_files (title, file_ids 1–100, view_mode) — 始终创建为 Draft+Private Space,不会发布;Pro/Max | 草稿 | POST /spaces,并传入 file_ids(创建前会先检查) |
publish_space (space_id, confirm) — Pro/Max | 发布 | 预览 GET /spaces/{id}/publish-preview;confirm: true → POST /spaces/{id}/publish |
get_approval_history (post_id) — 某一帖子的所有决定,按时间从早到晚排列:审批人(邮箱已隐藏)、时间、决定、评论 | 读取 | GET /social-posts/{id}/approval-audit |
get_plan_calendar_link (link_id) — Content Plan 的 ICS 订阅源 URL(计划发布的帖子、文案的前 60 个字符);只读,URL 稳定 | 读取 | GET /social-approval-links/{id}/calendar |
get_approval_audit (link_id) — 用户某个链接下的所有决定:审批人、帖子、时间、决定、评论;支持表格和 CSV | 读取 | GET /social-approval-links/{id}/audit.csv |
send_feedback (kind bug|idea|other, message, page) — 发送给 creatif.space 团队;不会公开显示,不消耗 Credits;每位用户每小时最多 10 条 | 草稿 | POST /feedback |
get_notification_settings — 用户会收到哪些邮件:post_missed_or_failed(“Post missed / failed”;除非 API 提供自己的键,否则对应 publish_failed 开关)、approval_decided、weekly_digest | 读取 | GET /me/notification-settings |
update_notification_settings (post_missed_or_failed — 或旧名称 publish_failed —, approval_decided, weekly_digest: true/false;周一 08:00 摘要所用时区;至少启用一项) | 草稿 | PATCH /me/notification-settings |
list_shared_with_me —“与您分享的报告”:其他用户分享给此用户邮箱的 Content Plans 和 Insight 报告 | approvals:decide | GET /me/reports/shared |
get_connect_link (network) — 应用的连接页面(https://creatif.space/social/connect?network=…)及相关步骤;响应中不含令牌;套餐已满时添加新网络 → plan_required | 读取 | GET /social-accounts + GET /credits(绝不调用 POST /social-accounts/auth-url) |
媒体上传。 request_media_upload → 客户端将确切的字节 PUT 到 | ||
该 URL(Content-Type 和 Content-Length 都经过签名)→ confirm_media_upload | ||
→ ID 会放入 draft_post / update_post 的 file_ids 中。预签名和 | ||
| 完成流程与应用相同,因此所有规则都由 Laravel 执行:Free 总容量 1 GB,Pro 25 GB | ||
| / Max 50 GB Keep 配额、单文件上限、可接受的格式、魔数检查。 | ||
拒绝操作时会返回 storage_full(包含释放空间的 files_url + 升级链接 | ||
billing_url)、file_too_large、unsupported_format、upload_limit、 | ||
upload_incomplete(在 PUT 之前确认)、file_not_ready(帖子中包含未确认或 | ||
来自其他用户的 ID);其他工作区的 ID 会返回 not_found。 |
schedule_post / publish_post 若没有 confirm: true,只会返回预览
(渠道、Credit 花费、今日剩余发送次数,以及任何阻止发送的事项)。使用 bearer
令牌发送的次数上限为每位用户每天 20 次(UTC),由 Laravel
(CapTokenSends,429 daily_send_cap)强制执行;应用的 Cookie 会话不受此限制。
confirm_token。 发送预览会返回由 API 签名的 confirm_token(使用应用密钥进行
HMAC;绑定用户、帖子、目标 ID 和 Credit 价格;有效期 10
分钟)。使用 bearer 令牌(MCP guard 或 API 密钥)发送时,必须将其一并传回:缺少令牌
→ 422 confirm_token_required;令牌不匹配、已过期或伪造 → 409
preview_stale。暂存草稿以供审批以及应用的 Cookie 会话都不需要此令牌。本服务会在内存中
保存每位用户 + 每个帖子最近一次预览的令牌,并在 confirm: true 时将其发送——模型不会看到它。
没有可用的预览记录(从未显示、已过期、已使用或服务器重启)→ 重新生成预览,不会发送任何内容;
409 → 工具错误 preview_stale,并在 details.preview 中附上新预览。
审批和编辑遵循 API 规则。 需要由客户审批(或客户要求修改)的草稿,不会通过应用或令牌发送或
安排发送(409 approval_required);只能再次暂存给客户。令牌也不能跳过编辑者自己的审批步骤。
令牌只能编辑等待审批的草稿和帖子(409 not_editable)。
Spaces。 对已连接的应用仅限 Pro 和 Max:令牌可访问的每个 Spaces 路由都列在
config('mcp.route_features') 中,因此 Free 用户会在控制器运行前由 EnforceTokenScope
收到标准的 402 plan_required(feature: "spaces")响应——但应用仍会列出 Free 用户已有的
Spaces。publish_space 与 publish_post 的工作方式相同:预览会返回一个
confirm_token(对用户 + Space + 标题、地址、可见性、密码、
到期时间和文件进行 HMAC;有效期 10 分钟),本服务会保存该令牌,并在
confirm: true 时发送;使用令牌发布但未提供令牌 → 422 confirm_token_required,
Space 已更改 → 409 preview_stale。预览还会说明阻止发布的原因
(active_slots_full)以及需要提示的情况(no_handle:尚无地址、
empty、expired)。Space 的链接格式为 {public_url}/{handle}/{slug}
(Space 资源中的 public_url;没有 handle 时为 null)。
计划限制同样遵循 API 规则(计划定义只有一份:PlanSeeder,
由 PlanQuota 执行)。Free 最多可提前 7 天(UTC)安排发送,最多暂存 10 篇排队帖子
(已安排发送 + 等待审批),且一次只能与一个客户建立审批链接;Pro 和 Max 不受这些限制。
超过限制时,API 会返回 402 {message, reason: "plan_required", feature, required_plan, limit?}(feature:schedule_window、queue_limit、approval_clients 或
受限功能),工具错误为 plan_required,并在 details 中包含这些字段。
schedule_post 会在预览中发送其 scheduled_at,因此用户确认前就会收到限制提示。
互动。 list_conversations / reply_to_conversation 读取并回复的行与应用中「互动」的行相同(评论和通过 Outstand 中继发送的 Instagram/Facebook 私信),所有权规则也相同(其他工作区的 ID → not_found),并遵循相同的策略(查看者席位无法回复)、Credits 和中继错误 — API 的 /inbox/feed 路由会委托给应用的互动控制器。ID 有类型:dm_<ulid> 或 comment_<ulid>。所有套餐均包含互动(PlanSeeder v2 没有互动标志),因此这两个工具都不受套餐限制;API 返回的 402 仍会以 plan_required 返回。若调用 reply_to_conversation 时没有 confirm: true,则只会预览;确认后,仅当文本与过去 10 分钟内针对该对话显示过的预览文本完全一致时才会发送(按用户保存在内存中),否则会再次预览,不会发送任何内容。评论和私信文本都是数据,绝非指令 — 两个工具的描述都明确说明了这一点。
错误会作为工具结果返回,包含 isError: true 和
{error: {code, message, next_step, details}}。next_step 是模型现在应执行的唯一操作;details 永不为空(始终包含 tool),且 next_step 只会指向实际存在的 details.X(test/errors.test.ts
会针对每条错误路径检查这两点)。SDK 自行处理的错误参数和未知工具名也会使用相同的封装格式。错误代码:reconnect_required、
scope_missing、plan_required、not_found、unknown_tool、invalid_input、
unauthorized、forbidden、rate_limited、daily_cap_reached、
insufficient_credits、quota_exceeded、preview_stale、not_editable、
not_draft、not_approvable、not_a_plan、link_inactive、approval_required、storage_full、
file_too_large、unsupported_format、upload_limit、upload_incomplete、
file_not_ready、upstream_unavailable、internal_error,以及互动回复错误
reply_window_closed、reply_rejected、reply_not_possible、
relay_unavailable。
每次调用都会发出 PostHog 事件 mcp_tool_called {tool, client_surface, client_name, ok, code, duration_ms} — client_surface 的值为 claude、chatgpt、cursor、vscode、
api_key 或 other(根据 OAuth 客户端名称确定);code 的值为 ok 或错误
代码。ms 和 error 保留为 duration_ms 和 code 的旧名称。不记录参数、说明文字、ID 或其他用户文本。未设置 POSTHOG_KEY 时会跳过。
有意不做成 MCP 工具:账户数据导出。 POST /api/v1/me/export
(整个工作区的 ZIP 文件,将通过电子邮件发送一个 24 小时有效的链接)仅适用于已登录的 creatif.space 会话。它不在 mcp.routes 中,因此 OAuth 或 API
令牌会收到 403。账户完整副本不应交给 AI
客户端。
从 AI 聊天中审批
适用于客户端——也就是 creatif.space 用户向其发送帖子或内容
计划以供审批的人。他们使用自己的账号(即收到链接的邮箱)将
creatif.space 连接到 Claude 或 ChatGPT,在授权页面允许 决定审批
(approvals:decide),之后无需打开审批页面即可查看并作出决定。
| 工具 | 功能 |
|---|---|
list_shared_with_me | “与你共享的报告”:与用户已验证邮箱共享的内容计划和洞察报告——标题、日期、发送者、链接(对于计划,还会显示有多少帖子待处理)。 |
list_waiting_approvals | 所有仍在等待用户决定的帖子,附带用于作出决定的链接 ID 和帖子 ID。 |
decide_approval | 批准,或说明原因并要求修改。始终先显示预览;仅在用户同意后,才使用 confirm: true 作出决定。 |
所有者一侧还有另外两个工具(权限范围 read):get_approval_audit——以行和 CSV 的形式显示某个自有链接的决定内容、决定者和时间;以及 get_approval_history——针对某个帖子,汇总其所在所有链接的相同信息,并遮蔽审批者的邮箱。
这些工具会遵守的规则(由 API 强制执行;工具仅作说明):
- 仅限发给用户已验证邮箱的链接。其他人会收到
forbidden,并附上预期邮箱的提示;来自其他工作区的 ID 会返回not_found。 - 每次决定都分为两步:预览,然后确认。确认请求会携带一个签名令牌(有效期 10 分钟),该令牌绑定用户看到的确切帖子;如果帖子在此期间被编辑,系统会返回包含新预览的
preview_stale,且不会作出决定。令牌不会传递给模型。 - 规则与审批页面相同:帖子必须在计划的日期范围和渠道内,且仍在等待审批;Free 发送者的计划仅允许决定未来 7 天内的帖子(返回
invalid_input,并附带decidable_from)。 - 每项决定都会记录审计信息,标记为
source: mcp;发送者收到的通知与通过页面作出决定时完全相同。 - 第一篇待审批帖子发布前一天,审批者会收到一封提醒邮件(每个计划一次;他们可以通过邮件关闭提醒,所有者也可以使用
PATCH /social-approval-links/{id}{reminders: false}关闭)。
对话示例
Rani: 这周有什么需要我审批的吗?
Claude 调用
list_shared_with_me和list_waiting_approvals。Claude: Bro 与你共享了一份内容计划:12 月 (12 月 1 日至 31 日,Asia/Jakarta)。有两篇帖子在等你审批:
- “发布日——全场 8 折……”——Instagram,12 月 2 日周三 09:00
- “工作室幕后花絮”——Instagram,12 月 4 日周五 18:00
Rani: 批准第一篇。第二篇请他们换成有团队成员入镜的照片。
Claude 对第 1 篇帖子调用
decide_approval,参数为decision: "approve";对第 2 篇调用该工具,参数为decision: "revise"、reason: "Please use the photo with the team in it"——两次都不带confirm,因此都会返回预览。Claude: 我将这样处理:
- 批准“发布日……”——它将在 12 月 2 日周三 09:00 发布到 Instagram。
- 对“工作室幕后花絮……”要求修改,并告诉 Bro:“Please use the photo with the team in it.”
现在要继续吗?
Rani: 好。
Claude 再次对每篇帖子分别调用
decide_approval,使用相同参数并添加confirm: true。Claude: 已完成。“发布日……”已获批准,将于周三 09:00 发布;Bro 已收到你对“工作室幕后花絮……”的备注。没有其他待审批内容。
之后,在所有者一侧:
Bro: 谁审批了 12 月的发布帖子?什么时候审批的?
Claude 使用计划的链接 ID 调用
get_approval_audit。Claude: Rani([email protected])于 12 月 1 日 03:10 UTC 要求修改“工作室幕后花絮……”(“Please use the photo with the team in it”),并于 03:10 UTC 批准了“发布日……”,两项决定均来自 AI 聊天。需要 CSV 吗?
工具注释
每个工具都有一个面向用户的 title,并将四个 MCP 提示显式设置为布尔值。list_*、get_* 和 check_* 工具的 readOnlyHint 为 true。任何会公开发布、删除、撤销或记录不可撤回决策的工具,其 destructiveHint 为 true:publish_post、schedule_post、schedule_posts、reply_to_conversation、retry_post、publish_space、discard_draft、unkeep_file、decide_approval、revoke_insight_share_link。只有会公开发布到社交网络或公共网络的工具,其 openWorldHint 为 true:publish_post、schedule_post、schedule_posts、reply_to_conversation、retry_post、publish_space。供目录审核表单使用的每个工具对应的一行说明见 docs/tool-justifications.md。test/annotations.test.ts 会检查这些规则和该文件,并在快照中固定每个工具的提示。完整参考文档列出了每个工具的范围、提示、描述和输入,见 docs/mcp-tools.md;该文档由服务返回的工具列表通过 npm run docs:tools 生成;如果内容过期,test/tools-doc.test.ts 会导致 CI 失败。
计划错误与 ChatGPT
任何工具描述都不会提及价格、计划层级或升级,无论客户端为何(test/no-upsell.test.ts)。当 OAuth 客户端为 ChatGPT 时——API 的 introspection 返回 client_surface: "chatgpt"(DCR 名称或 chatgpt.com / openai.com 重定向主机),或者客户端名称包含 ChatGPT / OpenAI——任何 402 或 plan_required 错误都会变为:
{ "error": { "code": "not_available_on_plan", "message": "This isn’t available on this account’s plan.", "next_step": "…no plan change or purchase…", "details": { "tool": "…" } } }
不包含升级链接或定价步骤;其他错误也会移除账单 / 充值链接。其他客户端会原样收到 API 的消息和链接(test/chatgpt-surface.test.ts)。
速率限制(429)
每个工具都会将 API 的 429 转换为相同的信封:
{code: 'rate_limited', message, next_step, details: {retryable: true, retry_after_seconds}}。
- **
message:**API 自身的文本。 - **
retry_after_seconds:**取自响应正文中的retry_after;如果没有,则取自Retry-After标头(EnforceTokenScope的令牌限制只发送标头);如果仍没有,则为 60。
以下两种 429 会保留各自的代码:upload_limit(今日暂停上传)和 daily_cap_reached(已连接应用每日发送 20 次)。test/ratelimit.test.ts 会向每个工具发送 429。
幂等性(重复提交)
API 会在每位用户和每个键的范围内,对携带 Idempotency-Key 的 POST 请求执行一次,期限为 24 小时。重复请求会返回首次响应(带有 Idempotent-Replayed: true),且不会再次执行。这适用于发布 / 排期(/send)、/retry 和审批链接创建。服务端会为每次确认发送一个键:
publish_post、schedule_post和retry_post会根据已确认预览的令牌生成键。重复发送确认只会发送一次,也只会扣费一次。create_approval_link会根据其参数在 10 分钟的时间窗口内生成键。重复请求同一个链接只会创建一次。
该键是哈希值:不会包含令牌或参数。只有 2xx 响应会被保留,因此修复导致确认被拒绝的原因后,可以重新发送该确认。
分页
每个 list_* 工具都使用相同的分页方式。它接受 limit 和 cursor,并返回 next_cursor(没有更多结果时为 null)。要请求下一页,请将 next_cursor 作为 cursor 传回,并使用相同的筛选条件。
- **不透明游标:**其中包含工具、位置以及筛选条件的指纹。来自其他列表的游标,或与其他筛选条件一起重用的游标,会被拒绝为
invalid_input,下一步提示为“start again without cursor”。 - **
list_posts:**通过GET /social-posts使用limit+offset分页,并额外请求一行,以确定是否还有下一页。 - **
list_files:**遵循 API 的页码。游标会保留第一页的页面大小。 - **
list_conversations:**使用收件箱自身的游标。 - **其他列表:**API 会返回全部结果,服务端负责分页。
src/tools/paging.ts;测试位于 test/pagination.test.ts。
结构化输出
list_channels、list_posts、get_post、get_credits、
list_waiting_approvals、check_approval_status、get_insight_summary、
list_files、list_spaces 和 get_storage_usage 声明了 outputSchema
并返回 structuredContent。为兼容旧客户端,文本块中仍包含相同的 JSON。架构(src/tools/outputs.ts)会为 Agent 所依赖的字段命名并指定类型,同时允许新增字段,因此 API 添加字段时不会导致调用失败。错误结果不包含 structuredContent;错误封装位于文本中。
提示词
prompts/list / prompts/get 提供三个现成的工作流。每个工作流都是一条用户消息,引导模型仅使用现有工具(每次发送仍须经过工具自身的预览和 confirm);用户输入的参数会加引号并标记为数据。定义于 src/prompts.ts。
| 提示词 | 参数 | 使用的工具 |
|---|---|---|
plan_week(“规划下周”)——为某个频道拟定一周的帖子(仅草稿) | channel_id*、week_start、theme、posts(1–7) | list_channels、list_posts、suggest_caption、draft_post |
send_for_approval(“发送给客户以供审批”)——将草稿汇总到一个审批链接中 | approver_email*、post_ids(逗号分隔)、client_name | list_posts、get_post、create_approval_link、check_approval_status |
weekly_results(“每周结果”)——汇总过去 7 天(或一个月)的数据 + 分享链接 | month(YYYY-MM;代替过去 7 天)、share(yes|no) | get_insight_summary、create_insight_share_link |
monthly_report(“月度报告”)——汇总一个月的数据 + 分享链接 | month(YYYY-MM,默认为上个月)、share(yes|no) | get_insight_summary、create_insight_share_link |
注册表元数据
mcp/server.json:官方 MCP 注册表条目(io.github.creatifren/creatif-space,远程地址为https://mcp.creatif.space/mcp,条目版本为1.2.2)。发布者提供的_meta列出了 OAuth 详情(授权服务器、受保护资源元数据、作用域)、所有工具、所有提示词以及服务版本。mcp/free-tools/server.json:免费工具条目(io.github.creatifren/creatif-space-free-tools,远程地址为https://mcp.creatif.space/free,无需身份验证,包含三个工具,条目版本为1.1.0)。glama.json(仓库根目录):Glama 维护者,与注册表命名空间中的所有者相同。test/registry.test.ts会确保这些信息与服务保持一致:工具、提示词、作用域和版本均相同;README 的 Tools 表格中的工具数量相同;仅包含架构字段。- 发布需手动完成,此处不会执行:
.github/workflows/mcp-registry.yml仅在workflow_dispatch时运行。发布是由 Rizal 执行的公开操作;两个条目的具体命令见docs/registry-publish.md。
资源
resources/list 和 resources/read 提供两个只读 JSON 资源,作用域为 read。定义于 src/resources.ts。
| URI | 内容 | 数据结构与以下内容相同 |
|---|---|---|
creatif://channels | 已连接的频道,以及需要重新连接的频道 | list_channels(limit 100) |
creatif://schedule/next-7-days | 从现在起至现在 + 7 天内安排的帖子(最多 100 条),按时间从近到远排列,并包含 {from, to, count} | list_posts,状态为 scheduled |
- **错误:**缺少作用域或 API 错误会作为 JSON-RPC 错误返回,其
data为常规的{code, message, next_step, details}封装。 - **审计:**API 调用会携带
X-MCP-Tool: resource.channels/resource.schedule,因此会显示在审计日志和mcp:usage中。
免费工具(/free)
同一进程中的第二个无状态 MCP 服务:check_caption、
approval_request_template、connect_guide。无需登录,不存储用户数据;
每次调用都会发送 PostHog 事件 free_tool_called {tool, network}(不包含
文案文本),使用现有的 POSTHOG_KEY。文案和限制保存在
free-tools/*.json 中(caption-rules.json、按细分领域索引的
approval-templates.json、包含 file:line 证据的 connect-guides.json;
这些证据绝不会发送给调用方)。connect_guide 还会返回 account_type:
每个条目要么是 confirmed(引用代码作为依据),要么是 check in app
(代码无法证实,因此不会猜测)。注册表条目 free-tools/server.json
(io.github.creatifren/creatif-space-free-tools)不会由注册表工作流发布,
该工作流只发布 mcp/server.json。
环境
| 变量 | 默认值 | 说明 |
|---|---|---|
PORT | 3010 | |
HOST | 127.0.0.1 | 前置 nginx |
V1_API_URL | https://api.creatif.space/api/v1 | |
MCP_RESOURCE_URL | https://mcp.creatif.space/mcp | 精确的连接器 URL = 资源 ID;与 Laravel 的 MCP_RESOURCE_URL 值相同 |
MCP_AUTHORIZATION_SERVER | https://api.creatif.space | |
MCP_INTROSPECT_SECRET | — | 真实模式下必需;与 Laravel 中的值相同 |
MCP_AUTH_MODE | real | stub 仅用于测试,在 NODE_ENV=production 时会被拒绝(令牌格式为 stub:<user_ulid>:<scopes>) |
POSTHOG_KEY | — | 未设置 → 不进行分析 |
POSTHOG_HOST | https://us.i.posthog.com | |
GLAMA_CLAIM | 已发布的声明 | 在 GET /.well-known/glama.json 和 GET /mcp/.well-known/glama.json 提供(公开,必须保持已发布状态) |
OPENAI_APPS_CHALLENGE | — | OpenAI Apps 域名验证令牌,在 GET /.well-known/openai-apps-challenge 以 text/plain 提供;未设置 → 404 |
MCP_PUBLIC_DISCOVERY | 关闭 | 设为 true 后,initialize、notifications/initialized、ping 和 tools/list 无需令牌即可响应(注册表爬虫、客户端预览;每个 IP 每分钟 30 次)。tools/call 和其他所有请求仍会收到带有 WWW-Authenticate(resource_metadata)的 401 登录质询;携带令牌的请求始终采用正常的身份验证流程。请在 QA 验证前保持关闭。 |
开发
cd mcp
npm ci
npm run lint && npm run typecheck && npm test && npm run build
MCP_AUTH_MODE=stub npm start # local only
部署检查清单(QA)
- 服务器已安装 Node 22 LTS(
node -v→ v22.x)和 nginx;DNS 将mcp.creatif.space指向此主机;TLS 证书已签发(certbot --nginx -d mcp.creatif.space)。 - 先部署 API 端:OAuth PR 已部署且迁移已运行;Laravel
.env中设有MCP_INTROSPECT_SECRET和MCP_RESOURCE_URL=https://mcp.creatif.space/mcp。 两端的MCP_RESOURCE_URL都必须精确为https://mcp.creatif.space/mcp(Laravel.env和/etc/creatif-mcp.env)——不能只填源站地址。 /etc/creatif-mcp.env(权限模式 600,所有者为 root)中包含以下变量名:PORT、HOST、V1_API_URL、MCP_RESOURCE_URL、MCP_AUTHORIZATION_SERVER、MCP_INTROSPECT_SECRET(与 Laravel 中的值相同)、MCP_AUTH_MODE(real,或不设置)、POSTHOG_KEY、POSTHOG_HOST。切勿在此处设置MCP_AUTH_MODE=stub。cd /var/www/creatif.space-api && git pull && cd mcp && npm ci && npm run build && npm prune --omit=dev- 安装下面的 systemd 单元,执行
systemctl daemon-reload && systemctl enable --now creatif-mcp;后续部署时执行systemctl restart creatif-mcp。 - 安装下面的 nginx 虚拟主机配置,执行
nginx -t && systemctl reload nginx。 - 冒烟测试:
curl -s https://mcp.creatif.space/health→{"ok":true,...}curl -si -X POST https://mcp.creatif.space/mcp | grep -i www-authenticate→Bearer resource_metadata="https://mcp.creatif.space/.well-known/oauth-protected-resource/mcp"curl -s https://mcp.creatif.space/.well-known/oauth-protected-resource/mcp→"resource":"https://mcp.creatif.space/mcp"journalctl -u creatif-mcp -n 20显示listening on http://127.0.0.1:3010 (auth: real)
- 在 Claude 中:Settings → Connectors → Add custom connector →
https://mcp.creatif.space/mcp,登录,然后运行list_channels。
使用报告(每日启动检查)
在 API 主机上运行:php artisan mcp:usage --days=7(1–90;添加 --json 可获取机器可读版本)。数据来自 mcp_audit_logs:每个工具的 API 调用次数、错误(HTTP ≥ 400)、错误率以及最常见的错误代码(状态码映射为模型看到的 MCP 代码:402 → plan_required,404 → not_found,5xx → upstream_unavailable……)。仅包含汇总数据——不包含用户、令牌、IP 或客户端名称。统计的是 API 请求,而不是工具调用(一次工具调用可能产生多个请求);在此服务内部被拒绝的调用(参数错误、缺少作用域)不会到达 API,因此不在统计范围内。
延迟:过去 24 小时内每个工具的 p50 / p95(以及计时调用数和错误数),数据来自 mcp_audit_logs.duration_ms。这是 API 自身的响应时间,由 EnforceTokenScope 写入。该列出现之前的记录没有计时数据,因此会被排除。按 p95 从慢到快排序;在 --json 中,字段名为 latency_24h。
在生产环境中运行
每次部署构建一次:npm ci && npm run build(然后运行 npm prune --omit=dev)。
systemd — /etc/systemd/system/creatif-mcp.service
[Unit]
Description=creatif.space MCP server
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/creatif.space-api/mcp
EnvironmentFile=/etc/creatif-mcp.env
Environment=NODE_ENV=production
ExecStart=/usr/bin/node dist/index.js
Restart=always
RestartSec=3
NoNewPrivileges=true
ProtectSystem=full
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload && sudo systemctl enable --now creatif-mcp
或使用 pm2 — mcp/ecosystem.config.cjs
module.exports = {
apps: [{
name: 'creatif-mcp',
cwd: '/var/www/creatif.space-api/mcp',
script: 'dist/index.js',
env: { NODE_ENV: 'production', PORT: 3010 }, // secrets via the shell env / .env loader
max_memory_restart: '300M',
}],
};
nginx — mcp.creatif.space
兼容 SSE:禁用缓冲、延长读取超时时间,并使用 HTTP/1.1 连接上游。
server {
listen 443 ssl http2;
server_name mcp.creatif.space;
ssl_certificate /etc/letsencrypt/live/mcp.creatif.space/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mcp.creatif.space/privkey.pem;
client_max_body_size 2m;
location / {
proxy_pass http://127.0.0.1:3010;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Streamable HTTP / SSE
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding on;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
add_header X-Accel-Buffering no;
}
}
server {
listen 80;
server_name mcp.creatif.space;
return 301 https://$host$request_uri;
}
检查:curl -s https://mcp.creatif.space/health 和
curl -si -X POST https://mcp.creatif.space/mcp | grep -i www-authenticate。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。