LearnNewsExamplesServices
Frontmatter
id17607
titleDefault MCP client launches Neural Link without its required cwd
stateClosed
labels
bugdeveloper-experienceaitestingagent-os
assigneesneo-gpt
createdAtAug 23, 2026, 7:55 AM
updatedAtAug 23, 2026, 1:31 PM
githubUrlhttps://github.com/neomjs/neo/issues/17607
authorneo-gpt-emmy
commentsCount0
parentIssuenull
subIssues
17611 The Codex harness launches Neo''s MCP servers with no cwd, so npm resolves the script from wherever the GUI started
subIssuesCompleted0
subIssuesTotal1
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 23, 2026, 1:31 PM

Default MCP client launches Neural Link without its required cwd

Closed Backlog/active-chunk-18 bugdeveloper-experienceaitestingagent-os
neo-gpt-emmy
neo-gpt-emmy commented on Aug 23, 2026, 7:55 AM

Context

The canonical MCP health spec failed during a bounded self-repair check on current dev:

npm run test-unit -- test/playwright/unit/ai/mcp/client/McpServersHealth.spec.mjs

6 passed, 1 failed
Server 'neural-link' ... Expected ["healthy", "degraded"]; received "unhealthy"
[ConnectionService] Bridge auto-connect deferred: awaiting entrypoint-supplied cwd.

The live attached Neural Link is healthy on port 8081 and every Agent OS container is healthy. This is not a service outage. It is the default client launch path constructing a valid stdio MCP process without the Bridge working-directory input that Neural Link deliberately requires.

The Problem

ai/mcp/client/config.mjs launches Neural Link as:

args: ["run", "ai:mcp-server-neural-link"]

The Neural Link entrypoint owns an explicit --cwd option. Server#boot() assigns that value to ConnectionService.cwd before driving the connection. Without it, ConnectionService#initAsync() deliberately defers auto-connect rather than reviving the removed ambient process.cwd() fallback; the server completes MCP negotiation but reports unhealthy.

That makes the default Neo.ai.mcp.client.Client configuration internally incomplete and turns the repository’s own JSON-RPC health source-of-truth red. Downgrading the health result or weakening the test would be a false green: most Neural Link tools really are unavailable until the Bridge connects.

The Architectural Reality

  • ai/mcp/client/config.mjs owns named default MCP connection definitions.
  • Client#createTransport() constructs StdioClientTransport with command, args, and env, but carries no cwd.
  • The installed MCP SDK’s StdioServerParameters already defines optional cwd; no SDK change is needed.
  • ai/mcp/server/neural-link/mcp-server.mjs accepts --cwd; Server#boot() propagates it before ensureBridgeAndConnect().
  • ConnectionService#spawnBridge() must continue refusing an unresolved cwd. #16429 removed the unsafe hidden fallback.
  • #17402 established the controlling rule for a second entrypoint: derive the root from the entrypoint/module location, validate it, and never substitute ambient process.cwd().
  • Structure map: ai/mcp/client/ has four files; Client.mjs and config.mjs are the existing transport/config owners. No new directory or file role is needed.

The Fix

  1. Add an optional cwd connection field to Neo.ai.mcp.client.Client; forward it only to StdioClientTransport.
  2. In the default Neural Link client definition, derive the repository/package root from config.mjs’s own module location.
  3. Supply that same validated root as both:
    • the stdio child-process cwd, so npm run ai:mcp-server-neural-link resolves from a foreign invocation directory;
    • the explicit Neural Link --cwd value, so the Bridge owner receives its required input.
  4. Keep other default stdio and remote definitions behaviorally unchanged.
  5. Add a foreign-cwd control and rerun the canonical health spec.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
Client.cwd (new optional connection field) MCP SDK StdioServerParameters.cwd Forward to stdio transport creation only null / absent preserves current inherited-cwd behavior for existing definitions Client config JSDoc transport-construction unit with injected connection config
ClientConfig.mcpServers.neural-link Neural Link mcp-server.mjs --cwd + Server#boot() Use one module-derived, validated package root for transport cwd and Bridge --cwd Fail loud if the package root cannot be established; never use ambient process.cwd() config inline authority note foreign-cwd process arm + health payload
McpServersHealth.spec.mjs Neural Link row the real default client config Boot, negotiate JSON-RPC, and return healthy or degraded because the required Bridge input was supplied A genuine spawn/connect failure remains unhealthy and fails the spec existing suite JSDoc/comment current 6/7 RED → 7/7 GREEN

Decision Record impact

none — this restores the explicit entrypoint-input boundary already established by #16429 / #17402.

Acceptance Criteria

  • The current red is reproduced: the unmodified default client reports Neural Link unhealthy with “awaiting entrypoint-supplied cwd.”
  • The default Neural Link definition supplies a module-derived, validated package root as both stdio transport cwd and explicit --cwd.
  • A foreign invocation directory cannot change the resolved root; an ambient-process.cwd() mutant fails the control.
  • npm run test-unit -- test/playwright/unit/ai/mcp/client/McpServersHealth.spec.mjs passes 7/7.
  • The green requires an actually connected Bridge; neither HealthService’s unhealthy semantics nor the suite’s accepted-status set is weakened.
  • Other stdio definitions preserve their existing behavior, and remote HTTP definitions do not receive a cwd.
  • The explicit unresolved-cwd refusal remains intact.

Out of Scope

  • Restarting or changing the live Bridge.
  • Weakening McpServersHealth to accept an unusable default Neural Link client.
  • Restoring any ambient process.cwd() fallback.
  • Changing the whitebox fixture delivered by #17402.
  • Memory Core identity/B-prime authority (#17447) or backup maintenance state.

Avoided Traps

  • Treating transport negotiation as service health. The server can answer healthcheck while its possession tools are correctly gated.
  • Changing the health label. Calling an unusable client degraded makes the test green without supplying the missing owner input.
  • Using the caller’s cwd. A valid absolute-config invocation can start anywhere; #17402 already falsified that premise.
  • Restarting containers. Neural Link is host/harness-spawned, and the live attached process is healthy.

Related

Related: #16429 · #17402 · #16992

Live latest-open sweep: checked the latest 20 open issues immediately before creation at 2026-08-23T05:55Z; no equivalent. The latest 30 A2A messages across all read states contained no overlapping lane claim or intent. Exact GitHub search found no equivalent ticket.

Origin Session ID: 6ca355f6-8cf2-4799-b02b-ac43b9043d55

Retrieval Hint: McpServersHealth neural-link default Client config missing --cwd Bridge auto-connect deferred foreign invocation directory

tobiu referenced in commit 3b43eaa - "feat(mcp): supply Neural Link client cwd (#17607) (#17610)" on Aug 23, 2026, 1:31 PM
tobiu closed this issue on Aug 23, 2026, 1:31 PM