Skip to content

fix(workflow-executor): align getMcpServerConfigs port with Record shape#1583

Open
hercemer42 wants to merge 2 commits into
feat/prd-214-server-step-mapperfrom
fix/prd-357-fetchremotetools-record-shape
Open

fix(workflow-executor): align getMcpServerConfigs port with Record shape#1583
hercemer42 wants to merge 2 commits into
feat/prd-214-server-step-mapperfrom
fix/prd-357-fetchremotetools-record-shape

Conversation

@hercemer42
Copy link
Copy Markdown

@hercemer42 hercemer42 commented May 18, 2026

Summary

  • Runner.fetchRemoteTools() crashed with TypeError: configs.map is not a function on every MCP-typed step. The orchestrator's GET /liana/mcp-server-configs-with-details returns Record<string, ToolConfig>, but the executor port was typed Promise<McpConfiguration[]> and the runner called .map on the object.
  • Aligns the executor with the wire contract: port now returns McpServers (Record<string, McpServerConfig>, from @forestadmin/ai-proxy), runner wraps the record into { configs } for loadRemoteTools, with an empty-Record short-circuit.
  • Updates 9 test mock sites (8 mockResolvedValue([]) plus the [{ configs: {} }] as never cast in runner.test.ts) to the real Record shape so the contract can't silently regress again. Adds two TDD tests under MCP lazy loading (via once thunk) for the non-empty-Record happy path and the empty-Record short-circuit.

Dependency bumps (heads-up)

packages/workflow-executor/package.json bumps:

  • @forestadmin/ai-proxy 1.8.0 → 1.9.0 — load-bearing for this fix (the McpServers type only exists from 1.9.0 onward).
  • @forestadmin/forestadmin-client 1.39.5 → 1.39.7 — incidental, was already staged in the user's pre-existing main-branch state.

These cannot be split into a separate PR because the workspace-resolved import in src/ports/workflow-port.ts would fail to compile against ai-proxy 1.8.0.

Test plan

  • yarn workspace @forestadmin/workflow-executor jest --runInBand --forceExit --testMatch='**/runner.test.ts' — 83/83 pass (including 3 new MCP-lazy-loading tests)
  • yarn workspace @forestadmin/workflow-executor jest --runInBand --forceExit on the 9 changed test files — 361 tests green
  • npx eslint, npx prettier --check, npx tsc --noEmit on all 13 changed files — clean
  • End-to-end repro against data-gouv MCP server on the executor dev project — pre-fix run aborted with the generic "An unexpected error occurred." (masking the TypeError); post-fix run reports NoMcpToolsError cleanly, which is the legitimate downstream behaviour when no tools materialize

Refs: PRD-357

Note

Fix getMcpServerConfigs return type to use McpServers Record shape in workflow-executor

  • Replaces McpConfiguration[] array with McpServers (a Record<string, ToolConfig> map) as the return type of getMcpServerConfigs across workflow-port.ts, forest-server-workflow-port.ts, and the public exports in index.ts.
  • Updates Runner.fetchRemoteTools in runner.ts to skip calling aiModelPort.loadRemoteTools when the config map is empty, and passes { configs } (the Record wrapped in an object) when non-empty.
  • Bumps @forestadmin/ai-proxy to 1.9.0 and @forestadmin/forestadmin-client to 1.39.7.
  • Behavioral Change: loadRemoteTools is no longer called when the orchestrator returns an empty MCP config map; callers relying on the old array format for getMcpServerConfigs will need to update to the Record shape.

Macroscope summarized 32c1afb.

The orchestrator's /liana/mcp-server-configs-with-details endpoint returns
Record<string, ToolConfig>, but the executor port was typed McpConfiguration[]
and runner.fetchRemoteTools called .map on it — every MCP-typed step crashed
with "TypeError: configs.map is not a function" before reaching loadRemoteTools.

Tests masked the bug by mocking mockResolvedValue([]) at 8 call sites, which
matched the wrong type and short-circuited the buggy branch.

Refs: PRD-357
@linear
Copy link
Copy Markdown

linear Bot commented May 18, 2026

PRD-357

@qltysh
Copy link
Copy Markdown

qltysh Bot commented May 18, 2026

Qlty


Coverage Impact

This PR will not change total coverage.

Modified Files with Diff Coverage (2)

RatingFile% DiffUncovered Line #s
Coverage rating: A Coverage rating: A
packages/workflow-executor/src/runner.ts100.0%
Coverage rating: A Coverage rating: A
.../workflow-executor/src/adapters/forest-server-workflow-port.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.

Comment thread packages/workflow-executor/src/ports/workflow-port.ts Outdated
Comment thread packages/workflow-executor/src/index.ts Outdated
Comment thread packages/workflow-executor/test/runner.test.ts Outdated
…mize test server name

Per @hercemer42:
- Remove `McpConfiguration` re-export from the port and barrel: it's only used internally by the AiModelPort/adapters now, imported directly from @forestadmin/ai-proxy.
- Drop the wire-shape comment on getMcpServerConfigs: the McpServers type and the route URL in the adapter are self-documenting.
- Rename test config key from "data-gouv" to "mcp-server-1" to keep the test free of real-world references.

Refs: PRD-357
@hercemer42 hercemer42 marked this pull request as ready for review May 18, 2026 15:24
"@langchain/openai": "1.2.5",
"@forestadmin/forestadmin-client": "1.39.5",
"@forestadmin/forestadmin-client": "1.39.7",
"@koa/bodyparser": "^6.1.0",
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@Scra3 can you confirm it's ok to bump these deps ?

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