Skip to content

feat(mcp-server): add triggerWorkflow tool (PRD-738) - #1777

Merged
christophebrun-forest merged 6 commits into
feature/prd-49-expose-workflow-tools-in-forest-mcp-serverfrom
feature/prd-738-mcp-ms6-triggerworkflow-tool
Jul 27, 2026
Merged

feat(mcp-server): add triggerWorkflow tool (PRD-738)#1777
christophebrun-forest merged 6 commits into
feature/prd-49-expose-workflow-tools-in-forest-mcp-serverfrom
feature/prd-738-mcp-ms6-triggerworkflow-tool

Conversation

@christophebrun-forest

@christophebrun-forest christophebrun-forest commented Jul 23, 2026

Copy link
Copy Markdown
Member

MS6 — triggerWorkflow MCP tool

Exposes the triggerWorkflow tool so an LLM can start a run on a specific record and get a runId back. Non-blocking by design — the run continues server-side and status is observed via getWorkflowRun (MS8).

fixes PRD-738

What's in it

  • New tool packages/mcp-server/src/tools/trigger-workflow.ts: args { workflowId, recordId }, identity from the OAuth auth context (forestServerToken + renderingId), wrapped in withActivityLog (action triggerWorkflow) so MCP-triggered runs get a local MCP audit entry under the caller.
  • forestadmin-client: WorkflowsService.triggerMcpWorkflow + ForestHttpApi call the MS5 endpoint over HTTP (POST /api/workflow-orchestrator/mcp-workflows/:workflowId/start, body { recordId }, forest-rendering-id header). No private-api internals imported.
  • Server errors bubble up as tool errors (isError: true) with the server's message passed through — 404 (not MCP-enabled / unknown workflow), 409 (run already ongoing, no resume), 403 (unauthorized). No status-specific remapping is done client-side. recordId not validated at trigger time.
  • collectionId is derived server-side (MS5, aligned on the webhook), so the tool contract stays { workflowId, recordId }.

Tests

mcp-server 631/631, forestadmin-client 292/292, lint clean.

Stacking & dependencies

🤖 Generated with Claude Code

Note

Add triggerWorkflow tool to the MCP server

  • Registers a new triggerWorkflow MCP tool in server.ts that lets agents trigger Forest Admin workflow runs, implemented in trigger-workflow.ts.
  • The tool validates the requested workflowId against the list of MCP-enabled workflows, then POSTs to /api/workflow-orchestrator/mcp-workflows/{workflowId}/start via a new triggerMcpWorkflow method on WorkflowsService.
  • Activity logs are emitted for each invocation, classified as write operations.
  • The HTTP path for listMcpEnabledWorkflows is updated from /workflows to /mcp-workflows.
  • Behavioral Change: WorkflowsService.listMcpEnabledWorkflows now throws if the configured transport does not implement the method, instead of calling undefined.

Macroscope summarized 5b0499c.

@linear-code

linear-code Bot commented Jul 23, 2026

Copy link
Copy Markdown

PRD-738

@qltysh

qltysh Bot commented Jul 23, 2026

Copy link
Copy Markdown

1 new issue

Tool Category Rule Count
qlty Structure Function with many parameters (count = 4): triggerMcpWorkflow 1

@christophebrun-forest
christophebrun-forest changed the base branch from feature/prd-49-expose-workflow-tools-in-forest-mcp-server to main July 24, 2026 10:29

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Medium src/forest-admin-client-with-cache.ts:36

Adding workflowsService in the middle of the ForestAdminClientWithCache constructor's positional argument list breaks existing JavaScript consumers that instantiate this class directly. Existing calls using the previous argument order still run, but each argument after the insertion point shifts by one: authService receives the model-customization service, and eventsHandler becomes undefined, causing runtime failures. Consider appending the new dependency at the end of the parameter list instead of inserting it in the middle.

    public readonly activityLogsService: ActivityLogsService,
-    public readonly workflowsService: WorkflowsService,
    public readonly authService: ForestAdminAuthServiceInterface,
    public readonly modelCustomizationService: ModelCustomizationService,
    public readonly mcpServerConfigService: McpServerConfigService,
    protected readonly eventsSubscription: BaseEventsSubscriptionService,
    protected readonly eventsHandler: RefreshEventsHandlerService,
+    public readonly workflowsService: WorkflowsService,
  ) {}
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @packages/forestadmin-client/src/forest-admin-client-with-cache.ts around lines 36-42:

Adding `workflowsService` in the middle of the `ForestAdminClientWithCache` constructor's positional argument list breaks existing JavaScript consumers that instantiate this class directly. Existing calls using the previous argument order still run, but each argument after the insertion point shifts by one: `authService` receives the model-customization service, and `eventsHandler` becomes `undefined`, causing runtime failures. Consider appending the new dependency at the end of the parameter list instead of inserting it in the middle.

@qltysh

qltysh Bot commented Jul 24, 2026

Copy link
Copy Markdown

Qlty


Coverage Impact

Unable to calculate total coverage change because base branch coverage was not found.

Modified Files with Diff Coverage (6)

RatingFile% DiffUncovered Line #s
New Coverage rating: D
packages/agent-testing/src/forest-admin-client-mock.ts100.0%
New Coverage rating: A
packages/forestadmin-client/src/workflows/index.ts100.0%
New Coverage rating: A
packages/mcp-server/src/http-client/mcp-http-client.ts100.0%
New Coverage rating: A
packages/mcp-server/src/tools/trigger-workflow.ts100.0%
New Coverage rating: A
packages/mcp-server/src/server.ts100.0%
New Coverage rating: A
packages/forestadmin-client/src/permissions/forest-http-api.ts100.0%
Total100.0%
🚦 See full report on Qlty Cloud »

🛟 Help
  • Diff Coverage: Coverage for added or modified lines of code (excludes deleted files). Learn more.

  • Total Coverage: Coverage for the whole repository, calculated as the sum of all File Coverage. Learn more.

  • File Coverage: Covered Lines divided by Covered Lines plus Missed Lines. (Excludes non-executable lines including blank lines and comments.)

    • Indirect Changes: Changes to File Coverage for files that were not modified in this PR. Learn more.

@christophebrun-forest
christophebrun-forest changed the base branch from main to feature/prd-736-mcp-ms4-listworkflows-tool July 24, 2026 12:16
Base automatically changed from feature/prd-736-mcp-ms4-listworkflows-tool to feature/prd-49-expose-workflow-tools-in-forest-mcp-server July 24, 2026 12:51
Expose the triggerWorkflow MCP tool so an LLM can start a run on a
specific record and get a runId back. Non-blocking by design: the run
continues server-side and status is observed via getWorkflowRun (MS8).

- tool args { workflowId, recordId }; identity from the OAuth auth
  context (forestServerToken + renderingId), wrapped in withActivityLog
  so MCP-triggered runs are audited locally under the caller.
- forestadmin-client: WorkflowsService.triggerMcpWorkflow calls the
  MCP-dedicated start endpoint over HTTP
  (POST /api/workflow-orchestrator/workflows/:workflowId/start), no
  private-api internals imported.
- collectionId is derived server-side from the workflow (MS5), so the
  tool contract stays { workflowId, recordId } — consistent with the
  webhook trigger.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@christophebrun-forest
christophebrun-forest force-pushed the feature/prd-738-mcp-ms6-triggerworkflow-tool branch from 259931d to 165c96f Compare July 24, 2026 13:23
christophebrun-forest and others added 5 commits July 27, 2026 16:11
…ore trigger (PRD-738)

- Point listMcpEnabledWorkflows and triggerMcpWorkflow at the
  /api/workflow-orchestrator/mcp-workflows route (aligned with the MS5 server contract).
- triggerWorkflow pre-checks the workflow via listMcpWorkflows so an unknown or
  non-MCP-enabled id fails with an actionable error, and the activity-log entry
  carries the workflow name and collection instead of the raw id.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ument trigger audit (PRD-738)

- WorkflowsService throws an explicit error when the transport does not
  implement triggerMcpWorkflow / listMcpEnabledWorkflows instead of a cryptic
  runtime TypeError
- document why a pre-trigger rejection is not audited (no resource to attach,
  server drops resource-less MCP activity logs) and reference PRD-831 for the
  by-id lookup optimization

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Mock (PRD-738)

triggerMcpWorkflow became a required member of WorkflowsServiceInterface;
the test mock only implemented listMcpEnabledWorkflows, breaking the build
(TS2741).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…y (PRD-738)

Same required-interface break as the agent-testing mock: the agent test
factory's workflowsService only implemented listMcpEnabledWorkflows,
failing every suite that imports it (TS2741).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bs (PRD-738)

The triggerMcpWorkflow mock stub was the only uncovered diff line, dropping
qlty diff coverage below the 98% threshold.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@christophebrun-forest
christophebrun-forest merged commit ad7777a into feature/prd-49-expose-workflow-tools-in-forest-mcp-server Jul 27, 2026
32 checks passed
@christophebrun-forest
christophebrun-forest deleted the feature/prd-738-mcp-ms6-triggerworkflow-tool branch July 27, 2026 16:24
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