Skip to content

feat(studio-mcp): add 25+ MCP tools for full agent coverage#312

Merged
betterclever merged 10 commits intomainfrom
feat/studio-mcp-tools
Feb 24, 2026
Merged

feat(studio-mcp): add 25+ MCP tools for full agent coverage#312
betterclever merged 10 commits intomainfrom
feat/studio-mcp-tools

Conversation

@betterclever
Copy link
Contributor

Summary

  • Refactored monolithic studio-mcp.service.ts into modular tool files under tools/ directory
  • Added 25 new MCP tools across 5 domains, giving the ShipSec agent full coverage of backend functionality:
    • Run details (6): get_run_config, get_run_trace, list_run_node_io, get_node_io (with full data fetch), get_run_logs (cursor pagination), list_child_runs
    • Artifacts (3): list_artifacts (filter by workflow/search), list_run_artifacts, view_artifact (byte-level windowing for large files, text/binary detection)
    • Schedules (8): list_schedules, get_schedule, create_schedule, update_schedule, delete_schedule, pause_schedule, resume_schedule, trigger_schedule
    • Secrets (5): list_secrets, create_secret, rotate_secret, update_secret, delete_secret (values never exposed)
    • Human inputs (3): list_human_inputs, get_human_input, resolve_human_input (approve/reject)
  • Wired up DI for all new services (ArtifactsService, NodeIOService, TraceService, LogStreamService, SchedulesService, SecretsService, HumanInputsService) with @Optional() for graceful degradation
  • Updated tests to cover new tool registrations and exported monitorWorkflowRun

Test plan

  • All 659 tests pass (0 failures)
  • TypeScript compiles cleanly (no new errors)
  • ESLint passes
  • Verify new tools appear in MCP tool listing via Studio chat agent
  • Test artifact windowing with a large file
  • Test schedule CRUD cycle
  • Test secret create/rotate/delete cycle

🤖 Generated with Claude Code

betterclever and others added 6 commits February 24, 2026 15:47
Extract 13 existing MCP tools from monolithic studio-mcp.service.ts
(727 lines) into separate files under tools/ directory:

- tools/types.ts: shared types, permission checker, result helpers
- tools/workflow.tools.ts: 7 workflow tools + task monitor
- tools/component.tools.ts: 2 component tools
- tools/run.tools.ts: 4 run tools

Service is now a thin orchestrator (~55 lines) that creates the
MCP server and delegates to tool registration functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
… children)

Expand StudioMcpDeps interface with optional services for trace, node-io,
log-stream, artifacts, schedules, secrets, and human-inputs. Add 6 new
run-scoped tools: get_run_config, get_run_trace, list_run_node_io,
get_node_io (with full data fetch), get_run_logs (cursor pagination),
and list_child_runs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
Add 3 artifact tools: list_artifacts (filter by workflow/search),
list_run_artifacts, and view_artifact with byte-level windowing for
large files. Includes text/binary detection via MIME type and content
heuristics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
Add 16 new MCP tools:
- Schedules (8): list, get, create, update, delete, pause, resume, trigger
- Secrets (5): list, create, rotate, update_metadata, delete (no value exposure)
- Human inputs (3): list, get, resolve (approve/reject)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
Import StorageModule, NodeIOModule, SchedulesModule, SecretsModule, and
HumanInputsModule into StudioMcpModule. Inject all services into
StudioMcpService (@optional for graceful degradation) and register all
tool groups. Export SchedulesService from SchedulesModule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
Update tool list assertion with 17 new tools. Export monitorWorkflowRun
from workflow.tools.ts and update test to call it directly instead of
via service instance.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d06fc4675f

ℹ️ 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".

},
},
async (args: { workflowId?: string; search?: string; limit?: number }) => {
const gate = checkPermission(auth, 'artifacts.read');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Extend API-key scopes before gating new MCP tools

This gate checks artifacts.read, but API-key auth currently normalizes permissions to only workflows, runs, and audit (see backend/src/auth/auth.guard.ts), so checkPermission will always reject this scope for API-key callers. The same pattern is used across the newly added artifact/secret/schedule/human-input tools, making those tools effectively unusable for standard /studio-mcp API-key sessions.

Useful? React with 👍 / 👎.

workflowId: args.workflowId,
name: args.name,
cronExpression: args.cronExpression,
inputs: args.inputs,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Map schedule inputs to inputPayload before create

The schedule service consumes dto.inputPayload (runtimeInputs/nodeOverrides), but this DTO is populated with inputs instead, so user-supplied schedule inputs are silently ignored and scheduled runs execute with the default empty payload. This breaks workflows that depend on runtime inputs and can produce incorrect scheduled execution results.

Useful? React with 👍 / 👎.

try {
const result = await humanInputsService.resolve(
args.inputId,
{ action: args.action, data: args.data },

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Send ResolveHumanInputDto shape to resolve service

This passes { action, data }, but humanInputsService.resolve expects ResolveHumanInputDto with responseData; in the service, approval is derived from dto.responseData?.status. Because responseData is missing here, a reject action is interpreted as approved, so MCP-driven rejections can incorrectly approve pending human-input gates.

Useful? React with 👍 / 👎.

if (!gate.allowed) return gate.error;
try {
const result = await schedulesService.trigger(auth, args.scheduleId);
return jsonResult(result);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Return explicit success payload for trigger_schedule

schedulesService.trigger returns void, so wrapping its return value with jsonResult(result) serializes undefined instead of a concrete response body. Clients calling trigger_schedule won’t receive a reliable success payload, which makes tool behavior ambiguous despite successful execution.

Useful? React with 👍 / 👎.

betterclever and others added 4 commits February 24, 2026 16:47
- Extend ApiKeyPermissions with artifacts, schedules, secrets, and
  human-inputs scopes so API-key callers can access new MCP tools
- Normalize new scopes in auth guard alongside existing ones
- Map schedule inputs to inputPayload.runtimeInputs (not flat inputs)
- Map human-input resolve action to responseData.status DTO shape
- Return explicit { triggered: true } for trigger_schedule (void return)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
- Prevent data.status from overriding action in resolve_human_input by
  spreading args.data before setting status (P1: approval bypass)
- Add ensureRunAccess check to get_node_io to prevent cross-org data
  access via direct runId lookup (P1: org isolation)
- Add new permission scopes to ApiKeyPermissionsSchema Zod validator
  so API keys can actually be granted the new MCP permissions (P2)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
68 new tests across 3 test files:

- run-detail-tools.spec.ts (23 tests): get_run_config, get_run_trace,
  list_run_node_io, get_node_io (with ensureRunAccess security check),
  get_run_logs, list_child_runs, permission gating
- artifact-tools.spec.ts (24 tests): list_artifacts, list_run_artifacts,
  view_artifact (text windowing, binary detection, offset/limit, hasMore),
  unavailable service fallback, permission gating
- domain-tools.spec.ts (21 tests): schedule CRUD (inputPayload mapping),
  secret CRUD, human-input resolve (DTO shape, status override prevention),
  permission gating for all domains

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
Separate schedule, secret, and human-input tests into individual files
for better organization and discoverability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: betterclever <paliwal.pranjal83@gmail.com>
@betterclever betterclever merged commit 9213d5c into main Feb 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant