feat(backend): expose Studio as Streamable HTTP MCP server#287
feat(backend): expose Studio as Streamable HTTP MCP server#287betterclever merged 5 commits intomainfrom
Conversation
…al agents Add studio-mcp module that enables any MCP client (Claude Code, Cursor, etc.) to connect to Studio using API keys and interact via 9 tools: list_workflows, get_workflow, run_workflow, list_components, get_component, list_runs, get_run_status, get_run_result, cancel_run. Uses StreamableHTTPServerTransport (new MCP standard), session management, and org-scoped auth via existing API key infrastructure. Refs: ENG-191 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
…erver Unit tests verify tool registration, auth context isolation, and all 9 tool handlers. E2e test uses @ai-sdk/mcp createMCPClient + generateText with stepCountIs for proper agent loop validation against the Streamable HTTP MCP endpoint. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
…erver Unit tests verify tool registration, auth context isolation, and all 9 tool handlers. E2e test uses @ai-sdk/mcp createMCPClient + generateText with stepCountIs for proper agent loop validation against the Streamable HTTP MCP endpoint. Uses z.ai coding API with glm-4.7 model. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
Tool calls use `input` (not `args`) and tool results use `output` for the dynamic MCP tool types in AI SDK v6. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 659fb0e1c0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const handle = await this.workflowsService.run( | ||
| args.workflowId, | ||
| { inputs: args.inputs ?? {}, versionId: args.versionId }, | ||
| auth, |
There was a problem hiding this comment.
Enforce API-key permissions for MCP workflow/run tools
The MCP handlers invoke workflow and run operations directly without any API-key permission gate, so keys that intentionally disable actions (for example workflows.run or runs.cancel) can still execute them through this endpoint. This is a privilege-escalation path for least-privilege API keys because run_workflow (and similarly list_workflows, get_workflow, list_runs, get_run_status, get_run_result, cancel_run) only depends on authenticated context, not the key’s permission matrix.
Useful? React with 👍 / 👎.
| if (sessionId) { | ||
| const transport = this.transports.get(sessionId); | ||
| if (!transport) { |
There was a problem hiding this comment.
Bind MCP session reuse to the same authenticated principal
Requests with an existing mcp-session-id are accepted based only on transport lookup, but each transport was initialized with the original caller’s auth context. That means any authenticated caller who obtains a live session ID can continue issuing tool calls under the creator’s organization/identity, creating cross-tenant/cross-user access if the session ID leaks via logs, proxies, or shared clients. Session metadata should include the creator identity and reject mismatched req.auth on reuse.
Useful? React with 👍 / 👎.
Address Codex P1 review findings: 1. Permission gating: All workflow/run MCP tools now check auth.apiKeyPermissions before executing. Keys with restricted permissions (e.g. workflows.run=false) are properly denied. Component tools remain ungated (static metadata). 2. Session identity binding: MCP sessions store the creator's userId + organizationId. Subsequent requests verify the caller matches the session creator, returning 403 on mismatch to prevent cross-tenant session hijacking. 3. Extended AuthContext with optional apiKeyPermissions field, populated during API key authentication in AuthGuard. Tests: 26 pass (19 service + 7 controller), 61 assertions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
Summary
/api/v1/studio-mcpfor external AI agentslist_workflows,get_workflow,run_workflow,list_components,get_component,list_runs,get_run_status,get_run_result,cancel_runBearer sk_live_...) with permission-based access controlTest plan
createMCPClientconnects over Streamable HTTP, discovers all 9 toolslist_componentsthrough MCP and reports resultsrun_workflow→get_run_status→get_run_resultsequence through MCPtsc --buildpasses cleanCloses ENG-191
🤖 Generated with Claude Code