ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Activepieces MCP Server 深度指南:将工作流项目暴露为类型化 MCP 工具服务

Activepieces MCP Server 深度指南:将工作流项目暴露为类型化 MCP 工具服务 Activepieces MCP Server 深度指南将工作流项目暴露为类型化 MCP 工具服务【免费下载链接】activepiecesAI Agents MCPs AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepiecesActivepieces 的 MCP Server 能力将整个项目flows、connections、tables、runs通过标准 Model Context Protocol 暴露给 AI 客户端Claude Desktop、Claude Code、Cursor、Windsurf、Codex 等让 Agent 可以通过类型化工具接口直接读取和操作自动化资产。本文基于 mcp-server.md 并结合仓库源码完整讲解其数据模型、工具体系、OAuth 认证机制、平台级多项目上下文切换以及一线运维中容易踩中的关键陷阱帮助你安全地在 CE / EE / Cloud 各版本中启用并管控这一能力。概览一个项目即一个 MCP ServerActivepieces 以每项目一条记录的方式暴露 MCP 能力一个McpServer记录对应一个项目projectId上存在 UNIQUE 约束记录中包含 72 字符的token字段与disabledTools[]JSONB可空开关列表。该能力在 Community Edition、Enterprise Edition 与 Activepieces Cloud 中均可用。从上层视角看McpServer由 Fastify 插件mcpServerModule注册模块入口在 mcp/mcp-module.ts最终从 app.ts 挂载进应用export const mcpServerModule: FastifyPluginAsyncZod async (app) { await app.register(mcpServerController, { prefix: /v1/projects/:projectId/mcp-server }) await app.register(mcpPlatformController, { prefix: /v1/mcp-server }) }每次请求到来时服务端通过mcpServerService.buildServer()按请求动态构建一个McpServer实例构建顺序为server 元数据 → 动态 flow 工具 → 可控 锁定静态工具 → 空的 resources/prompts协议合规占位核心逻辑见 mcp-server-builder.ts。词汇表先统一领域术语该功能涉及若干容易混淆的术语仓库内部文档对此有严格约定见 mcp-server.md术语含义注意点Grant授权mcp_oauth_token表中的一行表示某位用户对某个已注册客户端的当前有效授权是 Connect 页面列出与吊销的最小单位域模型中名为McpOAuthGrant由/v1/mcp-oauth/grants提供Client客户端注册mcp_oauth_client表中的一行注册记录不是稳定身份Claude Code、Codex 每次登录都会重新执行 DCR同一产品会产生多行同一用户重复认证会产生多个 grant。不要用client指代被吊销的对象Connection连接属于 piece 认证体系AppConnection与 MCP 无关代码中禁止使用MCP connection界面上的 Connections 标签与/mcp-server/connectionsURL 是刻意采用的用户文案代码里app/routes/mcp-server/grants/统一叫 grantPieces标签页已连接客户端在一个项目内可调用的 piece 动作对应/mcp-server/pieces标签仅限 piece 动作不包含 flow / table / run 工具Reach 只是文案动词不是标签名Reach 作为标签名已被废弃读起来像名词却不指代任何对象Tools在项目设置中指可锁定/可控制的工具列表、Capabilities过度承诺暗示含非 piece 工具、Actions指 flow 步骤、PermissionsRBAC 语义且该页只是镜像、无可编辑项均不适宜作为该标签的名称。实体与数据模型MCP 相关的核心实体定义在 packages/core/shared/src/lib/automation/mcp/ 下的mcp.ts与mcp-oauth.ts。McpServer 记录export const McpServer z.object({ ...BaseModelSchema, platformId: z.nullable(ApId), projectId: z.nullable(ApId), type: z.enum([McpServerType.PLATFORM, McpServerType.PROJECT]), token: ApId, // 72 字符注意实际不参与认证见下文 Gotchas disabledTools: z.array(z.string()).nullable(), })token为 72 字符随机串disabledTools为 JSONB 数组null/[]均表示所有可控工具全部启用类型分为PROJECT项目级与PLATFORM平台级两种配置更新仅接受disabledTools字段UpdateMcpServerRequest。getOrCreate的默认创建逻辑mcp-service.ts会写入token: apId(72)与disabledTools: []并通过 UNIQUE 约束下的并发兜底冲突时回查已存在记录保证每项目/每平台只有一条。工具定义McpToolDefinition是工具注册的通用载体mcp.tsexport type McpToolDefinition { title: string description: string inputSchema: Recordstring, z.ZodTypeAny annotations?: { readOnlyHint?: boolean destructiveHint?: boolean idempotentHint?: boolean openWorldHint?: boolean } permission?: Permission execute: (args: Recordstring, unknown) PromiseMcpToolResult }inputSchema直接使用 Zod shape与 MCP 协议期望一致permission字段声明该工具所需的 RBAC 权限运行时由permissionChecker.wrapExecute统一包裹。工具体系锁定、可控、搜索与动态 Flow 工具工具按性质划分为四类注册逻辑集中在 tools/index.ts构建期过滤逻辑在 mcp-server-builder.ts。1. 锁定工具Locked Tools只要 MCP 启用就必然注册、无法被disabledTools关闭的工具主要为只读发现类ap_list_flows、ap_flow_structure、ap_read_step_code、ap_read_step_settings、ap_validate_flow、ap_research_pieces、ap_get_piece_props、ap_resolve_property_options、ap_resolve_property_chain、ap_validate_step_config、ap_list_connections、ap_list_ai_models、ap_list_tables、ap_find_records、ap_list_runs、ap_get_run、ap_setup_guide完整清单见LOCKED_TOOL_NAMES。注意锁定列表中还包含ap_search_actions与ap_search_triggers但这两个工具仅在环境变量AP_TOOL_SEARCH_ENABLED开启时才真正注册见下因此它们的锁定条目在开关关闭时是惰性的。2. 工具搜索工具Tool-search Toolsap_search_actions/ap_search_triggers提供对动作/触发器目录的语义搜索基于 pgvector并在关键词匹配不足时回退到关键字地板keyword-floor机制。注册条件严格受AP_TOOL_SEARCH_ENABLED控制...(isToolSearchEnabled() ? [apSearchActionsTool(mcp, log), apSearchTriggersTool(mcp, log)] : []),该环境变量是总开关与回滚路径关闭时工具根本不注册未注册的工具不可能被强制打开设置面板则通过TOOL_SEARCH_ENABLED标志展示对应条目。3. 可控工具Controllable Tools通过项目的disabledTools逐项开关覆盖 flow/step/branch 管理、发布、table 与 record 操作、测试与 run 管理见ALL_CONTROLLABLE_TOOL_NAMESap_build_flow、ap_create_flow、ap_duplicate_flow、ap_rename_flow、ap_update_trigger、ap_add_step、ap_update_step、ap_delete_step、ap_add_branch、ap_update_branch、ap_delete_branch、ap_lock_and_publish、ap_change_flow_status、ap_delete_flow、ap_manage_notes、ap_create_table、ap_delete_table、ap_manage_fields、ap_insert_records、ap_update_record、ap_delete_records、ap_test_flow、ap_test_step、ap_retry_run、ap_run_action。构建期的过滤逻辑为LOCKED_TOOL_NAMES中的工具或不在disabledTools中的工具才被注册const disabledToolSet new Set(mcp.disabledTools ?? []) const tools allTools.filter(t LOCKED_TOOL_NAMES.includes(t.title) || !disabledToolSet.has(t.title))4. 动态 Flow 工具Dynamic Flow Tools每个启用了 MCP 触发器 pieceactivepieces/piece-mcp的 flow都会成为一个可调用工具命名为{toolName}_{flowId[0..4]}执行时通过 webhook 提交returnsResponse为 true 时同步等待响应否则异步。触发器配置由extractMcpTriggerInput读取mcp-server-builder.tsexport function extractMcpTriggerInput(flow: PopulatedFlow): { toolName?: string, toolDescription: string, mcpInputs: McpProperty[], returnsResponse: boolean } { const mcpTrigger flow.version.trigger.settings as McpTrigger return { toolName: mcpTrigger.input?.toolName, toolDescription: mcpTrigger.input?.toolDescription ?? , mcpInputs: mcpTrigger.input?.inputSchema ?? [], returnsResponse: mcpTrigger.input?.returnsResponse ?? false, } }McpProperty支持Text / Boolean / Date / Number / Array / Object六种输入类型见 mcp-piece.ts。动态 flow 工具统一声明FLOW_TOOL_ANNOTATIONS { readOnlyHint: false, destructiveHint: false, openWorldHint: true }因为执行真实 flow 会改变第三方系统状态。只有FlowStatus.ENABLED的 flow 才会被列出registerFlowTools中的过滤且调用前会先做permissionChecker.check(Permission.WRITE_RUN, toolName)检查。实际执行走webhookService.handleWebhook超时受FLOW_TIMEOUT_SECONDS系统属性控制。工作原理协议端点、认证与传输协议端点MCP 主协议端点为域名根路径的POST /mcp另有POST /mcp/platform平台级StreamableHTTP均在server.ts中注册项目级配置走项目 APIGET/POST /v1/projects/:projectId/mcp-server。Fastify 启用了ignoreTrailingSlash: true因此/mcp/与/mcp命中同一路由且不会产生 301。认证仅 OAuthMCP 协议认证只接受 OAuthresolveIdentity仅当mcpOAuthTokenService.verifyAccessToken将Authorization: Bearer中的值验证为 audience 为JwtAudience.MCP_OAUTH_ACCESS的签名 JWT 时才放行。不存在静态 token 认证器也没有?token查询参数路径。OAuth 侧是完整的 OAuth 2.0 PKCE 流程metadata、authorize、token、revoke实现位于 mcp/oauth/mcp-oauth/ ├── client/ # DCR 注册register、client identity 推导 ├── code/ # authorize 页面、授权码实体与服务 ├── metadata/ # OAuth 授权服务器元数据 ├── token/ # 令牌签发、grants 列表、吊销 ├── mcp-oauth-validation.ts ├── mcp-oauth.pkce.ts授权服务器元数据会向客户端宣告支持的端点401 响应携带符合 RFC 9728 的WWW-Authenticate: Bearer resource_metadata…头。OAuth 发现 URL 通过domainHelper.getPublicUrlFromRequest构建因此子路径托管subpath-hosted的实例会通告正确的前缀宿主机根路径的.well-known/oauth-*仍须由运维把流量转发到 Activepieces。三种传输与 AI piecesAI pieces 通过SIMPLE_HTTP、STREAMABLE_HTTP、SSE三种传输消费 MCP 工具相关类型与客户端身份枚举claude、claude-code、chatgpt、cursor、vscode、codex、gemini-cli、opencode、windsurf、unknown定义在 mcp-oauth.ts。Embed SDK 集成Embed SDKpackages/ee/embed-sdk/src/index.ts新增三个公开方法authorizeMcp()— 在嵌入环境中发起 OAuth 授权同意流程mcpSettings()— 读取/管理 MCP 设置generateMcpToken()—免 OAuth 流程地铸造{ mcpServerUrl, mcpToken }背后由POST /v1/projects/:projectId/mcp-server/token支撑签发的是15 分钟有效期、项目级作用域的短期 token实现见 mcp-server-controller.ts 的issueInternalAccessToken。配置入口项目级与平台级 API项目级控制器mcp-server-controller.ts提供方法路由权限说明GET/v1/projects/:projectId/mcp-serverREAD_MCP获取项目 MCP 配置含 flow 列表POST/v1/projects/:projectId/mcp-serverWRITE_MCP更新disabledToolsPOST/v1/projects/:projectId/mcp-server/rotateWRITE_MCP轮换 token注意见 GotchasPOST/v1/projects/:projectId/mcp-server/tokenREAD_MCP生成 15 分钟短期 MCP token 与 URL更新请求体{ disabledTools: [ap_test_flow, ap_run_action] }平台级控制器mcp-platform-controller.ts提供GET/POST /v1/mcp-server与POST /v1/mcp-server/rotate且仅平台管理员可访问platformAdminOnly。平台级多项目上下文切换/mcp/platform是平台级端点它注册ap_set_project_context工具其余非平台级工具每次调用都会从 Redis 重新读取已选项目因为传输层是无状态的sessionIdGenerator: undefined每次 POST 都新建McpServer没有可承载选择的会话。选择键的格式为mcp-project-selection:client:{platformId}:{userId}:{clientId}其中clientId从访问令牌中读取。历史上该键是…:user:{platformId}:{userId}GIT-1831 之前导致同一个平台级授权上的两个客户端如 Claude Code 与 LibreChat 都指向/mcp/platform互相覆盖对方的项目选择表现为对一个明明存在、REST 读取正常的 flow 间歇性报 Flow not found。改为clientId后仍有两点固有行为客户端重新执行 DCR 登录时选择会重置同一注册的多个实例共享同一份选择。无状态请求上没有任何字段能区分这两种情况。实现见 mcp-project-selection.tsTTL 为 24 小时。ProjectSelectionScope曾携带{ conversationId }变体PR #13356fbfbcd7578已移除其唯一调用方改为使用会话自身的 PostgresprojectId内部聊天从不写入该键ap_set_project_context在CHAT_HIDDEN_TOOL_NAMES中。不要为外部客户端重新引入会话作用域——它们永远不会发送x-ap-conversation-id。权限模型RBAC 与提示注解的边界RBAC 权限检查在 CLOUD / ENTERPRISE 版本中每个工具调用都会经过resolvePermissionCheckermcp-permissions.ts根据调用用户在项目中的角色权限集合判定无权限时返回isError: true的拒绝消息用户在该项目中没有角色时凡声明了permission的工具一律拒绝。CE 版本使用ALLOW_ALLcheck: () null。const EDITION_REQUIRES_RBAC [ApEdition.CLOUD, ApEdition.ENTERPRISE].includes(system.getEdition())三类安全提示注解每个注册的工具都必须声明全部三个安全提示readOnlyHint、destructiveHint、openWorldHint。McpToolDefinition.annotations是可选字段buildToolConfig会原样透传——因此遗漏某个 hint 是静默的MCP 客户端会回退到协议默认值但 ChatGPT Apps 提交审核会把任何缺失的 hint 视为阻塞项。最容易遗漏的是两条动态路径它们在内部直接构建工具配置而不是从McpToolDefinition出发registerFlowTools每个启用 MCP 触发器的 flow 对应一个工具与registerPlaceholderTools未选择项目状态——这也是外部评审者最先见到的状态。占位工具按清单分别注解锁定名使用只读三元组可控名使用destructive: true, openWorld: true——占位工具永远不能把自己宣传得比它所代表的真实工具更安全。关于openWorldHint的关键语义它表示工具能否改变第三方系统状态而不是是否发起出站调用。执行真实连接器步骤的工具必须声明它ap_test_flow、ap_test_step、ap_retry_run、ap_run_action以及全部动态 flow 工具。仅为填充下拉菜单而调用已连接账号的只读工具ap_get_piece_props、ap_resolve_property_options、ap_resolve_property_chain则不需要。ap_retry_run曾在此处误标false——重试会重跑已发布 flow可能重发同一条 Slack 消息或重复一次出站写入因此必须为true。最后牢记这些提示只是给客户端的建议性元数据绝非强制执行。授权始终由permissionChecker.wrapExecute与每个工具的permission决定修改注解只改变客户端被告知什么不改变调用者实际被允许做什么。关键陷阱Gotchas以下来自项目内部一线经验直接影响安全与可用性mcp_server.token是死字段——没有任何代码读取它。它由getOrCreate默认值与/rotate两个路由mcpServerService.rotateToken/rotatePlatformToken写入但没有任何认证器查询它——轮换轮换的是一个不授予任何权限的秘密。它仍存在于公开的McpServerzod schema 上因此 API 仍在输出一个形似凭据、却不认证任何东西的 72 字符串。不要把它当凭据使用也不要让自托管用户这么做。设置面板与事实保持一致mcp-credentials.tsx只渲染 URL 与Authentication is handled via OAuth从不显示 token。删除该列、两个路由与 schema 字段属于破坏性 API 响应变更尚未实施。mcp_oauth_token.clientKey在登录时一次性决定。exchangeCode通过mcpOAuthClientIdentity从注册的 redirect URI 推导它因此 grants 列表可以在 SQL 中过滤分组而不是把平台上每一行mcp_oauth_client载入内存重新推导。两个后果日后改进该启发式不会为既有 grants 重新贴标签它们 30 天过期活跃客户端会在下次刷新时重新标记从而回填 NULL 键NULL不是第三种状态——它表示在该列存在之前登录在所有地方都显示为unknown包括?clientKeysunknown过滤器。Claude Code 与 Codex 每次登录都会重新执行 DCR注册的正是它们即将绑定的临时回环端口http://localhost:port/callback、http://127.0.0.1:port/callback/callback_id。因此精确字符串匹配的validateRedirectUri有效、无需 RFC 8252 的端口无关匹配——但每次登录都会新铸一行mcp_oauth_client与clientId所以clientId不是某个已连接客户端的稳定身份且这些行会无限累积2026-08-23 于 Claude Code 2.1.235、Codex 0.149.0 实测。在client_id仍按^[A-Za-z0-9_-]{1,64}$校验时绝不要通告client_id_metadata_document_supported。Claude Code 偏好 Client ID Metadata Document其client_id是 URL只有在服务端对 CIMD 保持沉默时才回退到 DCR。通告该能力却不放宽client_id形状会直接破坏 Claude Code 登录。对 MCP 客户端而言一个静态的Authorization头比没有更糟。Codex 中设置bearer_token_env_var或Authorization头会短路到 bearer 认证、完全跳过 OAuth 发现Claude Code 中被拒绝的Authorization头表现为连接失败而非回退到 OAuth。因此一个半成品静态 token 路径会静默禁用本来可用的 OAuth 路径。另外headless/CIclaude -p、SDK没有/mcp面板目前没有受支持的连接方式。Flow 归属ap_create_flow/ap_build_flow/ap_duplicate_flow会盖上ownerIdOAuth 用户与createdBy: { type: MCP, id }。遥测去重MCP_SERVER_CONNECTED通过telemetryDedupe.onceToday去重为每人/每 server/每天最多一条——它是日活信号而非请求量按次调用走MCP_TOOL_CALLED。MCP URL 必须无需重定向即可直达。跨域的301/302/307/308会在所有符合规范的客户端中剥掉Authorization头且跨域包含 scheme——所以代理处纯http→https的规范化与 apex→www 一样致命。它失败得看似正常发现过程由请求推导networkUtils.getRequestBaseUrl读取x-forwarded-proto/hostOAuth 登录在规范源上完成而客户端继续向它拿到的 URL POST造成永久401或反复重认证而不是干净的错误。Activepieces 自身从不在该处重定向——仅有的前缀是/mcp与/mcp/platform且 Fastify 开启ignoreTrailingSlash: true——所以这永远是运维的代理配置问题且服务端无法检测代理替它应答了重定向前的那次请求。DCR 在token_endpoint_auth_method缺省时必须签发 client secret。RFC 7591 §2 规定缺省值默认为client_secret_basic而非noneMicrosoft Copilot Studio 没有 client secret 会直接拒绝 DCR。把缺省方法默认成none看似解决了公共客户端被发了 secret的矛盾却用错误的方式解决了它破坏 Copilot并让省略该字段的客户端永远够不到client_secret_basic。正确做法是默认client_secret_basic并持续签发 secret。**x-ap-conversation-id头EE 聊天**可将 server 重绑到某会话的项目但仅在作用域与 token 匹配时生效——它永远无法扩大授权范围。禁用ap_run_action后目录仍完全可浏览且无法隐藏。piece 发现类工具ap_research_pieces、ap_search_actions、ap_search_triggers、ap_get_piece_props在LOCKED_TOOL_NAMES中disabledTools无法关闭——只有执行器ap_run_action可控。因此关闭运行动作的项目已连接客户端仍能枚举其理论上可调用的每个 piece 与动作。这一不对称正是 Pieces 标签在列表顶部警示而非隐藏行的原因。注意失败形态被禁用的工具从不registerTool客户端拿到的是协议层的 unknown-tool 错误而非工具内部的权限拒绝——每次调用都失败的说法方向正确但差了一层。Pieces 标签的服务端搜索Pieces 标签的搜索在服务端完成且只有在pieceDisplayName是 Fuse 键时才能工作。/v1/pieces?searchQuery会把每个 piece 的actions替换为匹配子集searchForSuggestion——对展示每 piece 动作数与破坏性徽标的页面这听起来是致命的——但searchForSuggestion搜索[pieceDisplayName, displayName, description]因此查询piece名会匹配其内部每个动作行内列表依旧完整。另有两点保证安全toPieceMetadataModelSummary从搜索前的audiencePieces计算summary.actions总数永不会被查询收窄搜索时标签会强制展开每一行渲染的计数与下方列表可见地一致。热门优先排序只用于未搜索视图——套用到搜索结果会丢弃 Fuse 的相关性排名。行级分组与计数在客户端由piecesUtils.toReachablePieces完成这是一个带独立单元测试的纯函数。设置面板与前端前端设置面板位于 packages/web/src/app/components/project-settings/mcp-server/负责凭据展示、flows-as-tools 与工具开关Connect / Pieces / Grants 三个标签在 packages/web/src/app/routes/mcp-server/独立 OAuth 同意页在 packages/web/src/app/routes/mcp-authorize/嵌入场景的embedded-mcp-*对话框在 packages/web/src/app/routes/embed/。builder 中单工具测试对话框在 mcp-tool-testing-dialog.tsx。注意ALL_CONTROLLABLE_TOOL_NAMES与前端mcp-tools-metadata.ts中的TOOL_CATEGORIES必须保持同步否则新增工具不会出现在设置面板中。关键文件索引入口模块与路由mcp/mcp-module.ts、mcp-server-controller.ts、mcp-platform-controller.ts服务与构建器mcp-service.ts、mcp-server-builder.ts工具定义mcp/tools/OAuth 流程mcp/oauth/权限与项目选择mcp-permissions.ts、mcp-project-selection.ts共享类型packages/core/shared/src/lib/automation/mcp/设置面板与标签页mcp-server/、routes/mcp-server/Embed SDKpackages/ee/embed-sdk/src/index.ts外部 MCP server 作为 agent 工具代理探针非 AP-as-server 功能packages/web/src/features/agents/agent-tools/使用建议小结认证统一走 OAuthPKCE不要为客户端配置静态 bearer 头也不要引导用户读取mcp_server.token安全最小化通过disabledTools关闭ap_run_action等高风险可控工具同时理解锁定工具仍会完整暴露 piece 目录代理确保/mcp、/mcp/platform与.well-known/oauth-*无重定向直达且 scheme 与 host 保持不变平台级使用多客户端共享/mcp/platform时注意项目选择按clientId隔离重新登录会重置选择工具注解所有工具尤其是动态 flow 工具与占位工具必须补齐三个安全 hint否则可能被客户端审核流程拒绝。【免费下载链接】activepiecesAI Agents MCPs AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepieces创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表