Skip to content

the two new tools answered nothing on the question they were built for - #2765

Merged
Flotapponnier merged 1 commit into
mainfrom
fix/mcp-filters
Oct 1, 2026
Merged

Flotapponnier merged 1 commit into
mainfrom
fix/mcp-filters

Conversation

@Flotapponnier

Copy link
Copy Markdown
Collaborator

Follow-up to #2764. Both bugs found by calling production, not by the tests, which exercised the shaping and never the filter path.

recommend_provider returned nothing whenever a chain was given

recommend_provider({ use_case: "solana trading bot", chain: "solana" })
-> { recognisedAs: "trading-bot", guidance: "...", benchmarks: [], alsoRelevant: [] }

It passed the chain straight to getBenchmark, but a chain RPC bench IS a chain: solana-rpc declares no chain dimension, so getBenchmark("solana-rpc", { chain: "solana" }) resolves to nothing and every match was dropped. Verified directly — that call returns unknown_slug on production.

The search was fine; search_benchmarks({ query: "solana solana trading bot", category: "RPCs" }) returns 3 matches. They were all discarded one step later.

This is the common case, not an edge: every RPC bench is per-chain, and the chain is the most natural thing for a user to say.

compare_providers could not reach the keyed cohort

Chain RPC benches rank two cohorts apart:

cohort providers on solana-rpc
public (default) Solana Labs, PublicNode, Solana Vibe Station, LeoRPC
keyed GetBlock, QuickNode, Alchemy, Chainstack

get_benchmark takes a tier; compare_providers did not. So "compare Alchemy and QuickNode on Solana" answered that neither is measured — about two providers sitting on the other tab.

The fix

resolveBenchmark applies only the filters a bench declares and drops the rest, so passing a chain is harmless where it is meaningless.

compare_providers now takes a tier, reports which cohort it answered on, and when a provider is missing it checks the other cohorts before saying so:

{ "missing": ["alchemy"],
  "measuredOnAnotherCohort": { "alchemy": "keyed" },
  "note": "Not on this cohort, but measured on: keyed. Call again with that tier." }

"Not measured" when the answer is one tab away is the wrong answer, and the whole point of the missing-vs-loser rule was to stop the tool saying wrong things about providers.

Verified: tsc clean, 406 tests pass, pnpm validate passes, lint 0 errors.

Both found by calling production after #2764 shipped, not by the tests, which
exercised the shaping and never the filter path.

recommend_provider returned an empty benchmark list whenever a chain was
given. It passed the chain straight to getBenchmark, but a chain RPC bench IS
a chain: solana-rpc declares no chain dimension, so the filter made it
unresolvable and every match was dropped. "A Solana trading bot" came back
with the guidance and nothing to apply it to. That is the common case rather
than an edge, since every RPC bench is per-chain.

compare_providers could not reach the keyed cohort. Chain RPC benches rank
public endpoints and API-key providers apart, the default is public, and the
tool took no tier. Asking it to compare Alchemy and QuickNode on Solana
answered that neither is measured, about two providers sitting on the keyed
tab.

resolveBenchmark now applies only the filters a bench declares and drops the
rest, so passing a chain is harmless where it is meaningless. compare_providers
takes a tier, reports which cohort it answered on, and when a provider is
missing it looks on the other cohorts before saying so: "not measured" when
the answer is one tab away is the wrong answer.
@Flotapponnier
Flotapponnier merged commit 31a162f into main Oct 1, 2026
2 checks passed
Flotapponnier added a commit that referenced this pull request Oct 17, 2026
…3019)

Preparing the dev to main merge, the conflict triage turned up one file
group where dev is not ahead but behind, and behind on a leak.

`src/lib/mcp-tools.ts` and the MCP route exist on both branches and were
written independently, so they conflict as add/add. main's copies carry five
commits dev never received: a thousandfold error and a 35k-token catalogue
(#2764), the search endpoint handing back an API key it had been asked to
search for (#2766), two tools that answered nothing (#2765), a third
annotation the submission scan reads (#2768), and a chain name outranking
the subject of the question (#2770).

Measured rather than inferred from the titles: `redact` appears 7 times in
main's mcp-tools.ts and 3 times in its route, and 0 times in either of dev's.
Resolving those conflicts in dev's favour, which a bulk resolution would do,
reintroduces the leak.

Checked before overwriting: the dev-to-main diff is additive. main adds
category-aware scoring, a minimum score that cuts prefix-only noise, and
redactSecrets(); the only lines it removes are the ones it replaces. dev
holds nothing in these files that main lacks.

The privacy page is the same shape without the security edge: main's is 219
lines against dev's 140 and is alone in documenting retention and the Vercel
dependency. dev's predates it, from when the page existed only because the
app directory requires a policy URL.

Doing this now, in its own change, means the merge no longer has a
resolution that can silently restore a credential leak.

Gates: tsc clean, eslint clean, 567 tests (up from 561: main's test file
carries six more).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant