news 2026/9/29 2:38:09

SuperPlane Workspace Agent Resources:为 Factory 工作区统一注入 MCP 服务器与 SKILL.md 技能的 PRD 落地实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SuperPlane Workspace Agent Resources:为 Factory 工作区统一注入 MCP 服务器与 SKILL.md 技能的 PRD 落地实践

【免费下载链接】superplane

Open source factory for one-shot engineering

项目地址:https://gitcode.com/gh_mirrors/su/superplane
点击查看免费下载

导读:docs/prd/workspace-agent-resources.md是 SuperPlane 中"工作区级 Agent 资源"(Workspace Agent Resources)的设计蓝图(playbook),它定义了一个统一的目录(catalog):管理员只需在工作区设置页添加一次 MCP 服务器或内联 SKILL.md 技能,此后 factory 每次任务构建时都会自动把它们注入到 Claude Code、Codex、OpenCode 等 runner CLI 中,让包括任务细化(task refinement)在内的每一步都能使用这些资源。读完本文,你将掌握该功能的领域模型、配置 schema、OAuth 接入流程、运行时注入机制,以及当前仓库中对应的源码、迁移文件与测试实现,可以直接基于此进行二次开发或排查问题。


1. 功能定位与已锁定决策

这份 playbook 是 SuperPlane 中workspace MCP 服务器与技能(skills)的唯一事实来源。它开篇给出了 6 条"已锁定决策"(Locked decisions),这些决策直接决定了后续所有表结构、接口与注入路径的形态:

  1. 单一工作区目录表:所有资源都存进factory_agent_resources一张表,kind区分mcp_server与skill两种;一个 attach 函数统一注入启用的行。禁止新增第二张目录表。
  2. MCP 与 Skills 设置页分离:两个页面都位于 Workspace 设置下,权限为factories:update;实验性开关为workspace_mcp与workspace_skills;旧的workspace/agent-resources路由重定向到新页面。
  3. MCP v1 认证只支持 headers 或 OAuth:SuperPlane 在管理员浏览器里完成 OAuth,runner 只拿到 Bearer access token,绝不把 refresh token 写到 runner。
  4. 注入发生在任务构建(task build)阶段,而不是写进 canvas YAML:工作区 MCP 与第一方planning_session_mcp.js服务器合并;名字superplane被保留。
  5. Skills v1 只支持单个 SKILL.md 文件:管理员在整页编辑器粘贴 markdown,SuperPlane 存{ "source": "inline", "markdown": "..." }并把它写到 runner 上;GitHub 包(repository、ref、path)作为后续第三方技能来源,不引入npx skills安装。
  6. Storybook 是视觉规范:每个页面状态都必须在页面完成前有命名 story。

从源码看,这些决策已经被完整执行:表结构与第 1 条一致(见下文迁移文件),特性开关FeatureWorkspaceMCP = "workspace_mcp"与FeatureWorkspaceSkills = "workspace_skills"定义在 pkg/features/features.go,注入函数AttachWorkspaceAgentResources定义在 pkg/components/runner/workspace_agent_resources.go。

2. 目标与"不重复造轮子"清单

Goal(目标):工作区管理员只需添加一次 MCP 服务器和内联技能,factory runner 的**每一个步骤(包括任务细化)**都能使用这些资源;GitHub 技能包将来可以填进同一个目录,无需第二张表。

playbook 同时用"今天已存在什么"(What exists today)划清边界,避免重复实现:

  • factory runner 任务已经为任务细化附加了第一方 stdio MCP 服务器(planning_session_mcp.js)。
  • Organization integrations 是带 setup wizard 和 webhooks 的产品应用,不是通用 MCP URL 目录。
  • Organization secrets 已经能存 header 值,runner 的environmentFrom已经能解析这些 secrets。
  • GitLab 和 Jira 已经能在浏览器完成 OAuth,并在 SuperPlane 中加密、刷新 token。
  • Canvas YAML 与environmentFrom按节点绑定 secrets——这条路会漏掉现有自动化和细化节点,除非重写每个模板,所以注入必须发生在任务构建层。

3. 产品规则总表

playbook 用一张表把产品规则钉死,逐条对应源码中的常量与校验逻辑:

主题规则源码依据
Catalog一张表,调用方传factory_id并按kind过滤pkg/models/factory_agent_resource.goListAgentResources
Kindsmcp_server和skill同文件FactoryAgentResourceKindMCPServer/FactoryAgentResourceKindSkill
Nameslug,factory 内唯一;superplane保留factoryAgentResourceNamePattern、ReservedFactoryAgentResourceName = "superplane"
MCP transportv1 仅 HTTP / streamable HTTP,不支持 stdio 或npxFactoryAgentResourceConfig.Transport
Header auth可选;把 header 名映射到 organization secret 名与 keyFactoryAgentResourceHeader{Name, SecretName, SecretKey}
OAuthSuperPlane 是 MCP OAuth 客户端,任务开始时注入 BearerStartFactoryAgentResourceOAuth与/api/v1/mcp-oauth/callback
Cap每个 workspace 最多 20 个启用的 MCP 服务器MaxEnabledFactoryMCPServers = 20与ensureEnabledMCPCapacity
Skills v1仅内联 SKILL.md;不包含额外文件和脚本ValidateSkill拒绝非 inline source
Flagsworkspace_mcp与workspace_skillspkg/features/features.go
设置页Workspace / MCP servers 与 Workspace / Skills见第 6 节前端文件
路由.../settings/workspace/mcp与.../settings/workspace/skills;skill 新建/编辑用/new与/:resourceId前端 pages 目录
ToolsWorkspacedisabledTools加节点disabledAgentResourceTools;新工具默认开启assembleWorkspaceMCPServer中NormalizeDisabledTools合并两处配置
InjectAttachWorkspaceAgentResources在 broker-task 构建时执行,仅在对应 flag 打开时附加对应 kindpkg/components/runner/superplane/component.go
StorybookFactories/Pages/Settings/MCP and skills列出每个页面状态FactorySettingsAgentResources.stories.tsx

4. 领域模型与表结构

playbook 给出的领域模型层级:

factory (workspace) └── factory_agent_resources kind: mcp_server | skill name, enabled, config JSONB └── factory_agent_resource_secrets (encrypted OAuth tokens) └── AttachWorkspaceAgentResources └── Claude / Codex / OpenCode run.js

它已由迁移 db/migrations/20260918231901_add-factory-agent-resources.up.sql 落实:

  • factory_agent_resources:id(UUID PK)、organization_id、factory_id(均ON DELETE RESTRICT)、kind、name、enabled(默认 true)、config JSONB,以及一组 OAuth 相关列:oauth_status、oauth_error、oauth_connected_by、oauth_connected_at、oauth_metadata、oauth_pending_state、oauth_pending_expiry,外加时间戳。
  • 三个关键索引:(factory_id, name)唯一(保证名字唯一)、(factory_id, kind)(按 kind 过滤)、以及oauth_pending_state的部分唯一索引(用于 OAuth 回调时按 state 反查资源)。
  • factory_agent_resource_secrets:resource_id外键ON DELETE CASCADE、name、value BYTEA(加密存储),(resource_id, name)唯一。

模型层 pkg/models/factory_agent_resource.go 则把规则编码成常量与校验函数:

  • 认证方式:headers/oauth;OAuth 状态机:not_connected/connected/needs_reconnect/vendor_rejected;
  • secrets 命名约定:refresh_token、access_token、client_secret、code_verifier;
  • 技能 markdown 上限:MaxFactoryAgentSkillMarkdownBytes = 64 * 1024(64 KiB);
  • 名字正则^[a-z][a-z0-9-]{0,62}$,保留名superplane;
  • CanonicalMCPServerURL对 URL 做规范化(小写 scheme/host、去尾部斜杠、去 fragment),用于"同一 URL 不允许重复连接"的判定。

4.1 MCPconfig:OAuth 认证

{ "transport": "http", "url": "https://api.mobbin.com/mcp", "auth": "oauth" }

4.2 MCPconfig:Header 认证

{ "transport": "http", "url": "https://mcp.example.com/mcp", "auth": "headers", "headers": [ { "name": "Authorization", "secretName": "vendor-mcp", "secretKey": "token" } ], "disabledTools": ["create_issue"] }

要点(playbook + 源码共同确认):

  • config里绝不存 token。OAuth 的 refresh / access token 加密存放在factory_agent_resource_secrets;header 值在任务构建时从 organization secrets 解析(ctx.Secrets.GetKey(secretName, secretKey),见 workspace_agent_resources.go)。
  • MCP URL 必须校验为https,拒绝 loopback、link-local 与私有主机——对应 gRPC 层的validateMCPURL→mcp.ValidatePublicHTTPSURL(pkg/grpc/actions/factories/factory_agent_resources.go)。
  • disabledTools支持在服务器级预置(config 内),也会与节点/工作区级禁用手动工具合并去重。

4.3 Skillconfig:内联 SKILL.md(v1 唯一允许的创建方式)

{ "source": "inline", "markdown": "---\nname: review-copy\ndescription: Review UI copy.\n---\n\nWrite STE copy." }

4.4 Skillconfig:GitHub 包(后续版本;v1 创建时不允许持久化)

{ "source": "github", "repository": "nextlevelbuilder/ui-ux-pro-max-skill", "ref": "<tag-or-sha>", "path": "." }

4.5 OAuth 连接状态(行级字段)

  • not_connected— 已保存,仍需 Connect
  • connected— refresh token 已存在
  • needs_reconnect— refresh 失败
  • vendor_rejected— discovery、DCR 或 allowlist 失败

模型层的OAuthState()与MCPConnectionEstablished()直接消费这些状态:OAuth 连接的 MCP 只有connected才算建立;header 连接的 MCP 只要有 URL 就算建立(pkg/models/factory_agent_resource.go)。

5. 设置页面(Settings pages)

页面沿用 factory settings 的外观框架,标题为MCP servers与Skills,结构如下:

Workspace settings MCP servers catalog picker 或 Custom list 或 empty state primary action: Add MCP server Skills list 或 empty state primary action: Add skill full-page editor at /skills/new and /skills/:id
  • MCP server 行:绿色状态点(已连接)、name、URL、auth(Header 或 Sign-in)、状态(Connected / Not connected / Reconnect)、enable 开关、可展开的工具列表、菜单(Edit、Disconnect、Delete)。
  • 工具行:name 加 Read 或 Write 标识,按 name、read-first 或 write-first 排序,不显示 description;在某处关闭的工具对所有自动化都关闭(这正是"Tools"产品规则的意义)。
  • Skills 行:name、来源(内联显示为SKILL.md)、enable 开关、菜单(Edit、Delete)。编辑器包含 name 字段、/command建议、以及整页 markdown 编辑器。
  • 空状态文案:MCP 为空时显示 "No MCP servers yet. Add an MCP server so agents can use it on every run.";Skills 为空时显示 "No skills yet. Add a SKILL.md so agents can use it on every run."
  • 文案统一使用 SuperPlane、workspace、MCP server、skill、agent 作为稳定名词。

前端落地文件(playbook 的 Maintenance notes 明确列出):

  • MCP 页:FactorySettingsMCPPage.tsx
  • Skills 页:FactorySettingsSkillsPage.tsx
  • Skill 编辑器:FactorySettingsSkillEditorPage.tsx
  • 路由:/{org}/workspaces/{key}/settings/workspace/mcp与.../skills
  • Storybook:FactorySettingsAgentResources.stories.tsx,标题Factories/Pages/Settings/MCP and skills

6. OAuth 流程:浏览器完成授权,runner 只拿 Bearer

核心约束:fleet runner 是无头的,无法打开登录窗口,所以 MCP OAuth 必须由 SuperPlane 在管理员浏览器中完成。playbook 给出的六步流程:

  1. 探测 MCP URL:读取 RFC 9728 protected-resource metadata。
  2. 发现授权服务器:RFC 8414 或 OpenID Connect discovery。
  3. 获取 client id:使用 Client ID Metadata Documents;若服务器通告了 Dynamic Client Registration(DCR)则用之。
  4. 授权码 + PKCE:重定向到/api/v1/mcp-oauth/callback。
  5. 加密 refresh token,记录谁在何时连接的。
  6. 任务构建时:刷新 access token 并注入Authorization: Bearer。

补充要求:

  • authorize 与 token 请求都发送 RFC 8707 的resource=<canonical MCP URL>。
  • 如果 vendor 只 allowlist 了 Claude、Cursor 或 Codex,Connect 直接失败并给出明确错误;对同时提供 API key 的 vendor 保留 header auth。
  • v1只在任务开始时刷新 access token,短 token 可能在长任务运行中过期;v1 不引入 SuperPlane MCP proxy。

源码对应:OAuth 回调处理器在 pkg/public/mcp_oauth.go(HandleMCPOAuthCallback,路由即/api/v1/mcp-oauth/callback),token 铸造在pkg/mcp/factory_tokens.go的MintFactoryAgentResourceAccessToken,由 workspace_agent_resources.go 在组装 MCP 服务器时调用——拿到 token 后拼进Authorization: Bearer <token>请求头。

7. 运行时注入:AttachWorkspaceAgentResources 的完整调用链

这是整个 playbook 的技术核心。每个 runner 组件已经会调用ResolveEnvironment和AttachPlanningSessionEnv,在此基础上新增AttachWorkspaceAgentResources。playbook 给出的六步流程:

  1. 从 canvas 解析 factory(workflows.factory_id);canvas 不属于任何 factory 时直接 no-op。
  2. 加载启用的mcp_server与skill行。
  3. 解析 header secrets,或铸造 OAuth access token。
  4. 在SUPERPLANE_TASK_DIR下产出workspace_mcp.json,并把环境变量SUPERPLANE_WORKSPACE_MCP_CONFIG设为$SUPERPLANE_TASK_DIR/workspace_mcp.json。
  5. 每个run.js在 planning 开启时把远端服务器与 SuperPlane 的 stdio MCP 合并。
  6. 把每个内联技能写到SUPERPLANE_TASK_DIR下的.claude/skills/<name>/SKILL.md与.agents/skills/<name>/SKILL.md;提示步骤在 CLI 启动前把这些文件拷进 agent 工作目录;如果仓库里已有同名技能目录,保留项目文件、跳过工作区拷贝。

7.1 源码级实现

实现位于 pkg/components/runner/workspace_agent_resources.go:

  • 入口AttachWorkspaceAgentResources(ctx, environment, files):先解析 orgID,检查两个特性 flag(FeatureWorkspaceMCP/FeatureWorkspaceSkills,见 pkg/features/features.go);flag 全关时直接原样返回。随后用FindFactoryIDForCanvas确认 canvas 归属 factory(非 factory 画布 no-op)。
  • 每类资源只在对应 flag 打开时加载:factory.ListEnabledMCPServers(db)与factory.ListEnabledSkills(db),均按 name 升序。
  • 工作区级与节点级的禁用机制:配置键disabledAgentResourceIds(按资源 ID 整体剔除)与disabledAgentResourceTools(按资源 ID 禁用具体工具)在disabledAgentResourceIDs/disabledAgentResourceTools中解析,rejectDisabledAgentResources做剔除。
  • attachWorkspaceMCPServers:逐行调用assembleWorkspaceMCPServer——header 认证从ctx.Secrets.GetKey解析值;OAuth 认证走mcp.MintFactoryAgentResourceAccessToken;保留名superplane或 URL 为空直接跳过。最终序列化为{"servers":[...]}写入workspace_mcp.json(mode 0644),并追加环境变量SUPERPLANE_WORKSPACE_MCP_CONFIG=$SUPERPLANE_TASK_DIR/workspace_mcp.json。
  • appendWorkspaceSkillFiles:跳过空 markdown、保留名与校验失败的技能,把同一份 markdown 同时写入.claude/skills/<name>/SKILL.md和.agents/skills/<name>/SKILL.md。
  • appendWorkspaceAgentResourcesHint:把一段提示文本("You can use these resources. MCP servers: ... / Skills: ...")追加到prompts/*.txt提示文件末尾,让模型知道本次任务可用的资源。

调用位置:每个 runner 组件构建 broker 任务时统一调用。例如 pkg/components/runner/superplane/component.go 中environment, files = runner.AttachWorkspaceAgentResources(ctx, environment, files),claude / codex / openrouter 等组件的 component.go 同样接入。

7.2 各 CLI 的合并方式

CLI合并机制
Claude Code写mcp.runtime.json,条目形如{ type: "http", url, headers };只要存在工作区 MCP 就每次运行都写该文件;planning allowlist 包含mcp__<name>;禁用工具以mcp__<server>__<tool>传给--disallowedTools;技能从.claude/skills加载
CodexTOML 的mcp_servers.<name>字段:url、headers、disabled_tools;技能从.agents/skills加载
OpenCodeconfig.mcp.<name>记为type: "remote";用permission.<server>_<tool>拒绝禁用工具;技能从.agents/skills加载

以 Claude 为例,pkg/components/runner/claude/run.js 中workspaceMCPConfigPath会展开$SUPERPLANE_TASK_DIR并从候选路径查找workspace_mcp.json(候选含SUPERPLANE_WORKSPACE_MCP_CONFIG展开值、原值、taskDir/workspace_mcp.json兜底);workspaceMCPServers解析 JSON 并跳过名为superplane的保留服务器;writeClaudeMCPConfig把远端服务器与(planning 开启时的)SuperPlane stdio MCP 一起写进mcp.runtime.json。Codex 与 OpenCode 的 run.js 也有同样的候选路径逻辑(pkg/components/runner/codex/run.js、pkg/components/runner/openrouter/run.js)。

安全边界:playbook 特别提醒——自定义 HTTP MCP 工具可能在细化过程中改变外部系统,而仓库保持只读,这一点必须在 helper text 中写明。

8. Skills 后续演进(GitHub 包)

GitHub 技能包不在 v1 create 中,但 Storybook 中保留SkillsGitHub作为后续布局。当 GitHub 包落地时:

  1. 在添加时把 GitHub tree 快照进 SuperPlane blob storage,按 SHA 固定版本。
  2. 在 runner 的共享 skills 根目录解包,拷贝到 Claude 的.claude/skills/<name>/与 Codex/OpenCode 的.agents/skills/<name>/。
  3. 不重写 canvas YAML。
  4. 不运行 vendor 安装器(如uipro或npx skills add)。

基础设施前提:fleet runner 镜像必须包含python3(供跑搜索脚本的技能使用);优先公共仓库,私有 GitHub 技能将来需要 workspace VCS token。

9. Out of scope(v1 明确不做)

  • runner 上的 stdio /npxMCP
  • SuperPlane MCP proxy 或运行中 token 刷新
  • Canvas AI chat 自定义工具
  • Anthropic Managed Agent vault MCP
  • 按步骤单独 opt-out 与组织级共享
  • 交互式 MCP Apps UIs
  • 第一方 vendor connector 注册
  • 技能包安装与快照
  • SKILL.md 之外的技能脚本、引用与额外文件

这些边界与第 1 节的锁定决策互相印证——例如"不做 SuperPlane MCP proxy"正是第 3 条"不写 refresh token 到 runner"的自然延伸。

10. 测试计划与 Storybook 覆盖

playbook 给出了 14 条验收测试,覆盖三层:数据层(创建 header 连接并列表)、注入层(启用后 runner 任务产出workspace_mcp.json;Claude/Codex/OpenCode 都能合并远端服务器;禁用工具出现在 JSON 与三个 CLI 的 denylist;planning 会话仍附加 SuperPlane stdio MCP)、OAuth 层(mock 授权服务器完成回调;vendor allowlist 失败显示 Reconnect 与错误文本)、校验层(拒绝私有 URL 与httpURL)、技能层(内联技能落盘到两个技能目录;空 markdown 与 GitHub source 被拒绝)、UI 层(Storybook 全状态走查)。

仓库中已存在对应测试,可直接对照验收:

  • pkg/components/runner/workspace_agent_resources_test.go:TestAttachWorkspaceAgentResourcesSkipsNonFactoryCanvas(非 factory 画布不产出任何文件)、TestAttachWorkspaceAgentResourcesWritesHeaderServers(启用后只写启用的服务器,环境变量为$SUPERPLANE_TASK_DIR/workspace_mcp.json,header 值正确解析)、TestAttachWorkspaceAgentResourcesWritesPublicServersWithoutHeaders(无认证的公共服务器不带 headers)等。
  • 三个 CLI 的 run_test.go(如 claude/run_test.go、codex/run_test.go、openrouter/run_test.go)都直接写入workspace_mcp.json并断言SUPERPLANE_WORKSPACE_MCP_CONFIG的注入行为。
  • 模型层 pkg/models/factory_agent_resource_test.go 与 gRPC 层 pkg/grpc/actions/factories/factory_agent_resources_test.go 覆盖目录 CRUD、容量上限与 URL 唯一性。

Storybook 目录(FactorySettingsAgentResources.stories.tsx):

  • MCP servers 页:MCPEmpty、MCPCatalog、HeaderAuth、OAuthNotConnected、ConnectedGreenDot、OAuthNeedsReconnect、OAuthVendorRejected、Mixed。
  • Skills 页:SkillsEmpty、SkillsInline、SkillsGitHub(mocknextlevelbuilder/ui-ux-pro-max-skill)、SkillEditor。
  • 另保留Factories/Pages/Settings/MCP catalog、MCP status、MCP tools(对应 picker、绿点、工具排序与8/12计数),且页面必须能从Settings.stories.tsx的 sidebar 触达。

11. 维护清单:已上线表面与后续演进约束

已上线的表面(shipped surfaces,playbook 明确列出,均已在仓库中确认存在):

  • MCP 页:FactorySettingsMCPPage.tsx
  • Skills 页:FactorySettingsSkillsPage.tsx
  • Skill 编辑器:FactorySettingsSkillEditorPage.tsx
  • 路由:/{org}/workspaces/{key}/settings/workspace/mcp与.../skills
  • Stories:FactorySettingsAgentResources.stories.tsx
  • Catalog RPCs:List/Create/Update/DeleteFactoryAgentResource,定义于 protos/factories.proto,实现于 pkg/grpc/actions/factories/factory_agent_resources.go
  • OAuth:StartFactoryAgentResourceOAuth与/api/v1/mcp-oauth/callback(pkg/public/mcp_oauth.go)
  • Inject:pkg/components/runner/workspace_agent_resources.go

当接入 GitHubkind=skill包时的六条约束(playbook 收尾):

  1. 更新本 playbook,保持锁定决策 1、3、5 不变。
  2. 保留 Skills 页,不新增第二张目录表。
  3. 只扩展AttachWorkspaceAgentResources,不新增第二条注入路径。
  4. 为 fetch 失败与就绪的 GitHub skill 行新增 stories,保留SkillsEmpty与SkillsInline。
  5. make pb.gen后保持 proto 字段号连续。
  6. 以 GitHubrepository、ref、path作为包来源,不引入npx skills安装。

12. 结语:一张表、一个注入函数、三类 CLI

回顾整份 playbook,Workspace Agent Resources 的设计可以用"一、二、三"概括:一张目录表(factory_agent_resources)承载 MCP 与技能两类资源;一个注入函数(AttachWorkspaceAgentResources)在任务构建时统一发货;三个 CLI(Claude Code、Codex、OpenCode)各自把远端 MCP 服务器合并进自己的配置格式。管理员在设置页配置一次,所有 factory runner 步骤(含任务细化)即可自动使用这些资源——这正是把"每步都能用 Agent 能力"这个目标落到工程实现的关键路径。若要在 SuperPlane 上扩展第三方技能或新增 CLI 支持,本文第 11 节的约束清单就是必须遵守的扩展契约。

【免费下载链接】superplane

Open source factory for one-shot engineering

项目地址:https://gitcode.com/gh_mirrors/su/superplane
点击查看免费下载

相关推荐

上一篇:Janus-Pro-1B-OrangePi开发者指南:从源码解析到自定义模型优化
下一篇:Capybara测试数据管理:保持测试隔离的艺术

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 2:34:05

AI PPT生成器实战指南:十分钟搞定毕业论文答辩PPT

周五晚上十一点&#xff0c;隔壁寝室的学弟发来消息&#xff1a;“学姐&#xff0c;答辩PPT能不能借我改改&#xff1f;我还有三页没做完。”我回他&#xff1a;“你先拿Paperzz生成一版&#xff0c;我再帮你捋逻辑。”这不是敷衍&#xff0c;是我这几年帮人改PPT总结出来的工作…

作者头像 李华