[BUG] Custom fileSuggestion command: .map() passes the array index as each file's score, so MCP resources outrank every file except the first

Open 💬 2 comments Opened Jul 3, 2026 by juan-gm

Preflight Checklist

  • [x] I have searched existing issues — the symptom was reported in #30747 (auto-closed as a duplicate of the unrelated #22737), #22021, #17681 and #36329, but the root cause below has never been identified and no open issue tracks it
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code (2.1.199)

What's Wrong?

When fileSuggestion is set to a custom command, the @ picker ranks every fuzzy-matching MCP resource and agent above every file the command returns, except the first one. With a resource-heavy MCP server connected (e.g. Figma, which publishes ~100 resources: docs, skills, skill references), a query like @author renders:

app/models/author.rb                        ← file #1 from the custom command
figma:skill://figma/figma-use/SKILL.md      ← MCP resource
figma:file://figma/docs/…                   ← MCP resource
figma:skill://figma/figma-generate-…        ← MCP resource
app/models/author_follow.rb                 ← file #2, buried
app/helpers/authors_helper.rb               ← file #3
…

The custom command's output is correct and correctly ordered (verified by running it directly). The built-in file picker does not exhibit this — it's specific to fileSuggestion: { "type": "command" }.

Root cause (verified against the 2.1.199 binary)

The suggestion object builder takes an optional score:

function har(e, t) {
  return { id: `file-${e}`, displayText: e, metadata: t !== void 0 ? { score: t } : void 0 }
}

The built-in index path calls it correctly with a real fuzzy score:

e.search(t, V4o).map((r) => har(r.path, r.score))

But the custom-command path passes the function reference straight to .map():

if (type === "command") { ... return (await J4o(s)).slice(0, V4o).map(har) }

Array.prototype.map invokes the callback as (element, index, array), so t receives the array index: file #1 gets score: 0, file #2 gets score: 1, file #3 gets score: 2, … (the classic ['1','10','11'].map(parseInt) footgun).

Those scores then enter the unified @ mention merge, which sorts ascending on a 0–1 scale:

for (let f of l) p.push({ source: f, score: f.score ?? 0.5 });      // files
// MCP resources / agents matched with Fuse.js:
new Bee(d, { includeScore: true, threshold: 0.6, keys: [...] }).search(t, { limit: msn });
let h = g.item.type === "mcp_resource" ? 0.15 : 0;                  // resource penalty
p.push({ source: g.item, score: (g.score ?? 0.5) + h });
p.sort((f, m) => f.score - m.score);

Fuse scores are 0–0.6 (threshold), +0.15 resource penalty → the worst possible resource scores 0.75, while the custom command's second-best file scores 1. So command files 2–15 lose to every resource/agent that scrapes past the (permissive) 0.6 threshold. With ~100 Figma resources with long descriptions, almost any query matches something.

Two details confirm this is unintended:

  1. The merge has an explicit provision for score-less command results — f.score ?? 0.5 — and har guards t !== void 0. Both are dead code, because .map(har) always supplies the index.
  2. The 2.1.89 changelog fix ("Improved @-mention typeahead to rank source files above MCP resources with similar names" — the +0.15 penalty) works for the built-in path but is mathematically irrelevant against integer index scores, so custom-command users never got that fix.

Steps to Reproduce

  1. settings.json:

``json
{ "fileSuggestion": { "type": "command", "command": "bash ~/.claude/my-finder.sh" } }
``
where the script prints, say, 20 relevant paths for the query (any correct finder reproduces it).

  1. Connect an MCP server that publishes resources, e.g. Figma: claude mcp add --transport http figma https://mcp.figma.com/mcp
  2. Type @ + any query that matches multiple project files.

Expected Behavior

Files returned by the custom command rank according to the command's ordering, competing with MCP resources on comparable score scales — at minimum, an exact filename hit should not rank below a loose fuzzy match on an MCP resource description.

Actual Behavior

Only the command's first result ranks at the top; results 2–15 rank below every matching MCP resource and agent.

Suggested Fix

Minimal: .map(har).map((p) => har(p)), so command results get the intended score-less treatment (?? 0.5).

Better: preserve the command's ordering on the 0–1 scale, e.g. .map((p, i, arr) => har(p, i / arr.length * 0.1)) — command results keep their relative order, outrank loose resource matches, and a strong resource match can still surface.

Environment

  • Claude Code 2.1.199 (native installer), macOS (Darwin 24.6, x86_64)
  • Reproduced in CLI interactive mode

Related

  • #30747 — same symptom, auto-closed as duplicate of #22737 (which is a different bug: command not invoked / query not passed, since fixed)
  • #22021 / #17681 — requests to hide MCP resources from the picker (no such setting exists as of 2.1.199)
  • #36329 — resource flooding variant

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗