LearnNewsExamplesServices
Frontmatter
id14542
titlefix(neural-link): check_namespace + get_namespace_tree missing x-pass-as-object → object-handler arg-shape mismatch
stateClosed
labels
bugai
assigneesneo-opus-ada
createdAtJul 3, 2026, 10:59 AM
updatedAtJul 3, 2026, 11:22 AM
githubUrlhttps://github.com/neomjs/neo/issues/14542
authorneo-opus-ada
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 3, 2026, 11:22 AM

fix(neural-link): check_namespace + get_namespace_tree missing x-pass-as-object → object-handler arg-shape mismatch

neo-opus-ada
neo-opus-ada commented on Jul 3, 2026, 10:59 AM

Problem

Two Neural Link MCP tools mis-pass their arguments to their handlers: check_namespace and get_namespace_tree. The call reaches the handler with the wrong argument shape, so the tool fails for every agent/harness. Surfaced by @neo-gpt (Euclid) as generic NL friction — not app-specific (a cross-repo harness start made it visible, but the defect is harness-independent).

Root cause

ToolService dispatch (ai/mcp/ToolService.mjs:99-104) branches on x-pass-as-object:

if (tool.passAsObject) {
    return tool.handler(validatedArgs);          // pass the single validated object
}
const handlerArgs = tool.argNames.map(name => validatedArgs[name]);
return tool.handler(...handlerArgs);             // else: spread positionally

Both tools bind to RuntimeService handlers that destructure a single object:

  • check_namespaceRuntimeService.checkNamespace({namespace, sessionId}) (ai/services/neural-link/RuntimeService.mjs:44)
  • get_namespace_treeRuntimeService.getNamespaceTree({root, sessionId}) (ai/services/neural-link/RuntimeService.mjs:86)

…but their OpenAPI operations (ai/mcp/server/neural-link/openapi.yaml) are missing x-pass-as-object: true. So dispatch spreads positionally — checkNamespace(namespaceString) — and the {namespace, sessionId} destructure yields undefineds → the tool silently mis-behaves. Every sibling read-tier tool with an object requestBody carries the marker (40+ ops). These two are the only x-handler operations in the spec, and both omit it.

Audit — the "same handler-shape mismatch" check (all 6 marker-less ops)

op handler verdict
check_namespace checkNamespace({namespace, sessionId}) fix
get_namespace_tree getNamespaceTree({root, sessionId}) fix
get_worker_topology getWorkerTopology() (nullary, empty requestBody) correct as-is
get_window_topology getWindowTopology() (nullary, empty requestBody) correct as-is
healthcheck healthcheck() (nullary) correct as-is
get_mcp_tool_handbook toolId => … (single positional arg) correct as-is

Fix

Add x-pass-as-object: true to the check_namespace and get_namespace_tree operations in ai/mcp/server/neural-link/openapi.yaml.

Acceptance Criteria

  • check_namespace + get_namespace_tree operations carry x-pass-as-object: true.
  • Regression test: ToolService builds both tools with passAsObject === true (the object reaches the destructuring handler intact).
  • Recurrence guard: assert every x-handler operation in the NL OpenAPI has x-pass-as-object: true (the current invariant — both x-handler ops bind object-destructuring handlers).

Diagnosis credit: @neo-gpt (Euclid).

tobiu closed this issue on Jul 3, 2026, 11:22 AM
tobiu referenced in commit 70ef63f - "fix(neural-link): pass check_namespace + get_namespace_tree args as an object (#14542) (#14543) on Jul 3, 2026, 11:22 AM