Skip to content

fix(core): --server with an Object.prototype name reports not found (#2537) - #2583

Merged
cliffhall merged 1 commit into
v2/mainfrom
v2/fix/2537-own-property-server-lookup
Oct 5, 2026
Merged

cliffhall merged 1 commit into
v2/mainfrom
v2/fix/2537-own-property-server-lookup

Conversation

@cliffhall

@cliffhall cliffhall commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Closes #2537

Problem

--server constructor (or toString, hasOwnProperty, ...) against a source that has no such server resolved to the inherited Object.prototype member on a bare map[name] read. The CLI then failed with Cannot use 'in' operator to search for 'type' in undefined instead of Server 'constructor' not found.

Fix

Both by-name server lookups on the --server path now use the existing getOwnEntry helper (core/storage/own-entry.ts, an Object.hasOwn read that the repo already uses for the OAuth maps):

  • selectServerEntry (core/mcp/node/servers.ts). The issue's CLI repro actually reaches this one: runCli → loadServerEntries → selectServerEntry(entries, options.server). It is also behind servers list <name>.
  • loadServerFromConfig (core/mcp/node/config.ts). The issue names this one. It is reached by resolveServerConfigs(..., "single") (web --config + --server).

A server that really is named constructor still resolves normally.

Audit of other dynamic reads on this path

I checked the remaining user-keyed reads that --server passes through. I left them alone because none of them is a defect of this class:

  • rehydrateMcpConfigFromKeychain: secrets[id] ?? {}. secrets comes from secretStoreGetMany, which writes an own entry (setOwnEntry) for every requested id. Even when a store's getMany omits an id, the inherited value is only read for the oauth-client-secret / env: field names, which no Function property shadows, so it behaves exactly like {}.
  • Writes that rebuild the maps (normalizedServers[name] = …, result[entry.name] = …) only matter for __proto__. The repo already treats __proto__ as a reserved id: the routes reject it, and /api/servers drops it with a warning. Changing that is a different issue, so I kept it out of this PR. --server __proto__ now reports "not found", which the new tests pin.

Tests

  • clients/web/src/test/core/mcp/node/config.test.ts: resolveServerConfigs single mode reports an absent constructor / toString / hasOwnProperty / __proto__ as not found, and resolves a server that really is named constructor.
  • clients/web/src/test/core/mcp/node/servers.test.ts: the same cases for selectServerEntry.

Gate

npm run format and npm run local:gate. In this sandbox, several failures had nothing to do with this diff, so I ran some stages separately:

  • local:validate, verify:skills:cli: green.
  • coverage:web: one failure, secret-store-selection.test.ts > isOnMountPoint > is false when the path itself can't be resolved. The sandbox worktree sits on a mounted volume, so it fails on any branch; a sibling worktree (CLI stored-auth flags (--use-stored-auth, --list-stored-auth, --wait-for-auth) miss tokens stored under byIssuer #2517) sees the same thing. All other 452 files passed. The integration tests that call loopback servers had to run with the sandbox's HTTP(S)_PROXY unset, because the egress proxy otherwise intercepts them with a 502.
  • coverage:cli, coverage:tui, coverage:launcher, verify:build-gate, verify:bundle-externals, smoke:launcher, smoke:cli, smoke:tui, smoke:web:firefox, local:storybook: green. I ran these individually because the machine-wide gate lease queue was jammed.
  • smoke:web, smoke:web:chromium, smoke:web:tabs: not run locally. The machine-wide gate lease gave up twice after ~46 minutes queued, and running these fixed-port smokes without the lease would collide with other worktrees' gates. CI runs them. This diff only touches the by-name lookups behind CLI --server and web --config --server single mode.

🤖 Generated with Claude Code

… not found

A server name that matches an inherited Object.prototype member
(`constructor`, `toString`, ...) resolved to the inherited function on a
bare `map[name]` read, so the CLI failed with an unrelated
"Cannot use 'in' operator" error instead of "Server 'constructor' not
found".

Both by-name lookups on the --server path now go through the existing
`getOwnEntry` helper (an `Object.hasOwn` read):
- `selectServerEntry` in core/mcp/node/servers.ts, which is the lookup
  the CLI's `--server` actually reaches (and `servers list <name>`);
- `loadServerFromConfig` in core/mcp/node/config.ts, the lookup named
  in the issue (web `--config` + `--server` single mode).

Closes #2537

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

The narrow fixes reuse the existing helper, preserve valid entries, and include targeted regression coverage with no blocking issues identified.

Review effort: Balanced
Findings: None

What changed in this PR

Fixes #2537 by making shared server-name lookups ignore inherited properties while preserving servers genuinely named constructor.

Changes:

  • Uses getOwnEntry in both by-name lookup paths.
  • Adds regression tests for absent prototype names and valid constructor entries.
File Description
core/​mcp/​node/​servers.ts Restricts entry selection to own properties.
core/​mcp/​node/​config.ts Restricts config lookup to own properties.
clients/​web/​src/​test/​core/​mcp/​node/​servers.test.ts Tests inherited-name rejection and valid entries.
clients/​web/​src/​test/​core/​mcp/​node/​config.test.ts Tests equivalent behavior in single-server config resolution.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

@cliffhall

Copy link
Copy Markdown
Member Author

Copilot review closed. Round 1 (review 5411262662) was clean: no inline comments, "Findings: None" in the headline, and no suppressed comments. Per pr-flow 7c, one clean round ends the loop, so I'm not requesting another.

@cliffhall
cliffhall merged commit cedea8b into v2/main Oct 5, 2026
6 checks passed
@cliffhall
cliffhall deleted the v2/fix/2537-own-property-server-lookup branch October 5, 2026 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Issues and PRs for v2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CLI --server with an Object.prototype name (e.g. 'constructor') fails with an unrelated error instead of 'not found'

2 participants