feat(integrations): fx harness example (MCP config) - #2776
Conversation
fx (Vercel Labs' Zig coding agent, v0.0.3) consumes the facade as a standard stdio MCP server; native tools and SDK embedding are not possible (no plugin API; libfx hard-disables MCP mounting). Ships the user-global mcp.json template (no environment block — fx replaces the child env wholesale when one is set, so shell inheritance is the safe path), a project .fx.json raising max_tool_result_bytes past snapshot size and max_agent_steps past the MCP discovery round trips, the headless permission allowlist (rule-key shape verified empirically), and a stagehand-facade skill generated from FACADE_AGENT_INSTRUCTIONS with an fx preamble naming the exact generated tool ids — fx v0.0.3's mcp_search_tools returns no results for the server, and exact-name mcp_select_tool is the working path. Smoke (fx ask --json, sandboxed HOME, Browserbase): skill -> select x2 -> run -> snapshot, 'Example Domain' [0-19], 5 steps, reproduced twice.
Field testing showed a run outside the example directory (skill not loaded) stalls in tool discovery and falls back to native run_command exploration — which dumped the shell environment, credentials included, into the model transcript. The README now marks the working directory as required and recommends denying run_command for browser-only headless workflows.
|
There was a problem hiding this comment.
2 issues found across 4 files
Confidence score: 2/5
packages/integrations/fx/mcp.jsonhas noenvironmentallowlist, so agent-provider credentials from the shell can be passed to the MCP child and consumed by the facade, weakening the intended credential boundary — explicitly allowlist only the required variables.packages/integrations/fx/README.mddocuments a no-environmentsetup that forwards all shell variables, including OpenAI, Anthropic, and Google provider keys, which could encourage unintended credential exposure — update the example to use the same restricted environment configuration.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/integrations/fx/README.md">
<violation number="1" location="packages/integrations/fx/README.md:106">
P2: With the documented no-`environment` setup, fx passes every shell variable to the facade, and `stagehandFacadeConfigFromEnv` reads provider keys such as `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, and Google keys. Correct this security claim and direct users to configure the MCP child with `STAGEHAND_MODEL_NAME`/`STAGEHAND_MODEL_API_KEY`, separate from fx's `AI_GATEWAY_API_KEY`, so unrelated host credentials are not silently consumed.</violation>
</file>
<file name="packages/integrations/fx/mcp.json">
<violation number="1" location="packages/integrations/fx/mcp.json:3">
P2: When the shell contains agent-provider credentials, this entry passes them into the MCP child because it has no `environment` allowlist. The facade can consume those credentials, contradicting the MCP credential boundary; provide an explicit Stagehand/Browserbase allowlist while preserving `PATH` and `HOME`.
(Based on your team's feedback about explicit credentials for MCP children.)</violation>
</file>
Architecture diagram
sequenceDiagram
participant User as User / Terminal
participant FX as fx CLI (v0.0.3)
participant Skill as stagehand-facade Skill
participant MCPCfg as ~/.fx/mcp.json
participant FXConfig as .fx.json
participant Permission as ~/.fx/settings.json
participant MCP as MCP Server (stdio-server.mjs)
participant Facade as Stagehand Facade
participant Browser as Browserbase Browser
Note over User,Browser: fx + Stagehand MCP Integration Flow
User->>FX: cd packages/integrations/fx
User->>FX: fx ask --json "browser instructions"
Note over FX: Loads project config
FX->>FXConfig: Read max_agent_steps: 60, max_tool_result_bytes: 262144
Note over FX: Loads skill guidance
FX->>Skill: Parse SKILL.md
alt Tool discovery phase
FX->>MCPCfg: Read MCP server config
MCPCfg-->>FX: stagehand: stdio server definition
FX->>MCP: Spawn node /path/to/stdio-server.mjs
Note over FX,MCP: 10s startup timeout enforced by fx
FX->>MCP: mcp_search_tools()
Note over FX: v0.0.3 bug: returns empty for this server
alt Skill provides exact tool names
FX->>Skill: mcp_select_tool("mcp_stagehand_run")
Skill-->>FX: Tool selected
FX->>Skill: mcp_select_tool("mcp_stagehand_snapshot")
Skill-->>FX: Tool selected
FX->>Skill: mcp_select_tool("mcp_stagehand_screenshot")
Skill-->>FX: Tool selected
end
end
alt Permission check
FX->>Permission: Check rule shape for mcp_stagehand_run
alt Pre-allowed in settings.json
Permission-->>FX: allow
else No pre-allow
FX->>User: Permission prompt (headless fails)
alt --auto flag
FX->>FX: Model-based adjudication
end
end
end
Note over FX,Browser: Tool execution (happy path)
FX->>MCP: mcp_stagehand_run({ code: "..." })
MCP->>Facade: Execute browser action
Facade->>Browser: Launch browser (lazy)
Browser-->>Facade: Page ready
Facade->>Browser: Execute JavaScript
Browser-->>Facade: Result
Facade-->>MCP: Tool response
MCP-->>FX: Result
FX->>MCP: mcp_stagehand_snapshot()
MCP->>Facade: Snapshot page
Facade->>Browser: Capture DOM state
Browser-->>Facade: Snapshot data
Facade-->>MCP: Snapshot response
MCP-->>FX: Snapshot
FX-->>User: Final result
Note over FX,Facade: Unhappy path: fallback to shell
alt Skill not loaded (wrong directory)
FX->>User: run_command exploration
Note over User: Leaks host env into transcript
alt run_command denied in settings
FX->>Permission: Check run_command: deny
Permission-->>FX: Blocked
FX-->>User: Error: tool not available
end
end
Note over FX,MCP: fx discards MCP server stderr
Note over MCP,Facade: Debug standalone if issues
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
… test The facade can infer model-provider keys from an inherited environment for optional Stagehand model config, so the security section now says so and documents the environment-allowlist alternative (with the PATH/HOME restatement fx requires). Also bound the sdk-parity notification test at 30s — third test to trip the 5s default on cold runners.
There was a problem hiding this comment.
1 issue found across 2 files (changes from recent commits).
Confidence score: 3/5
- The allowlisting example in
packages/integrations/fx/README.mdomits Stagehand model credentials, soact,extract, andobservecalls can fail while browser-only operations continue to work; update the example to include the required credentials or clearly document the limitation.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/integrations/fx/README.md">
<violation number="1" location="packages/integrations/fx/README.md:116">
P2: When allowlisting the MCP child for `run` code that calls `act`, `extract`, or `observe`, this example passes no Stagehand model credentials, so those calls fail even though browser-only page operations work. State that these calls require separate `STAGEHAND_MODEL_NAME` and `STAGEHAND_MODEL_API_KEY` values, and include them in the allowlist example or explicitly scope the example to browser-only code.
(Based on your team's feedback about documenting separate Stagehand model credentials for MCP children.) .</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Summary
packages/integrations/fx— config-only integration for fx (Vercel Labs' coding agent, v0.0.3)~/.fx/mcp.jsontemplate, a project.fx.jsonsized for snapshots and MCP discovery, the headless permission allowlist, and astagehand-facadeskill generated fromFACADE_AGENT_INSTRUCTIONSWhy
fx only consumes MCP from user-global config: it has no plugin API and
libfxhard-disables MCP mounting, so the native-tools and SDK-embedded shapes don't apply. The skill is load-bearing — fx v0.0.3'smcp_search_toolsreturns no results for the server, so the skill teaches the exactmcp_stagehand_*names; without it, runs stall and fall back torun_commandexploration (which can dump env credentials into the transcript — README recommends denying it for headless browser work). The template omitsenvironmentbecause fx replaces the child env wholesale when one is set.Testing
fx ask --jsonsmoke with the pinned v0.0.3 binary, sandboxedHOME, Browserbase: skill → exact-name select →run→snapshot→ "Example Domain"[0-19], 5 steps, reproduced twicemcp_stagehand_run) and no-environmentinheritance verified empiricallypnpm run fmt:check;vitest run rules/ast-grep/sdk-parity.test.ts(14/14)Docs PR fast-follows as a stack. ACP-client route (
fx acpper-session mounts) tracked as follow-up for evals/embedding; ACP rejects image blocks.