You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Benchmark and improve tool-search ranking with indexed BM25 #2996
Describe the feature or problem you’d like to solve
The GitHub MCP Server already exposes tool discovery/search functionality, but
there is no repeatable benchmark for measuring how reliably natural-language
queries retrieve the intended MCP tool.
As the tool inventory grows, a benchmark would make ranking changes measurable
and help prevent retrieval regressions.
This is separate from host-side deferred tool loading discussed in #1680. The
proposal only concerns ranking inside the server's existing tool-search
implementation.
Proposed solution
Add a hand-labelled benchmark covering natural-language intents across the
server's major toolsets, then compare the current heuristic with an indexed
BM25 implementation.
A prototype benchmark contains 49 queries over 115 unique tools and produced:
Strategy
Recall@1
Recall@3
MRR@10
Query latency
Current heuristic
71.4%
81.6%
0.792
~2.25 ms
Indexed BM25
71.4%
87.8%
0.802
~34 µs
Hybrid RRF
73.5%
87.8%
0.823
~2.38 ms
Indexed BM25 improved Recall@3 by 6.1 percentage points and was approximately
66x faster per query. The hybrid produced the strongest ranking quality.
Before submitting a PR, I would appreciate maintainer guidance on the preferred
scope:
Benchmark harness only
Benchmark plus indexed BM25
Benchmark plus a hybrid ranking experiment
Example prompts or workflows
"Find open issues assigned to me across repositories"
"Read the files, reviews, and diff for a pull request"
"Download logs for a failed workflow job"
"Find exposed secrets detected in a repository"
"Add an issue to a GitHub project"
Additional context
The benchmark uses the complete current tool inventory and validates that every
labelled relevant tool exists. The prototype includes unit tests for indexing
tool names, descriptions, parameter names, and parameter descriptions.
I independently prototyped the benchmark-only scope against current main (64a49f3) and think option 1 is the safest first step. It creates a measurable review surface without changing production ranking before the relevance labels themselves have been reviewed.
The prototype uses 31 static, hand-labelled natural-language cases across 19 toolsets. It builds the real inventory through NewInventory(...).WithToolsets([]string{"all"}).Build(), then fails if a labelled tool is missing or belongs to a different toolset. On the current heuristic it measured:
Metric
Result
Recall@1
0.903
Recall@3
0.968
MRR@10
0.942
Two implementation details seem worth preserving in an upstream harness:
Validate labels against the current inventory before calculating metrics. That turns tool removal/renaming into an explicit benchmark-data failure instead of silently changing the denominator.
Assert labelled target ranks and aggregate metrics across repeated inventory builds, not the complete ordering of irrelevant results. SearchTools currently has no explicit tie-breaker for equal scores, so requiring full result-list equality would encode an ordering that production does not promise.
Local verification with Go 1.25.12 passed:
go test ./pkg/tooldiscovery
go vet ./pkg/tooldiscovery
go test ./pkg/inventory
A separate Go benchmark over the same 31 queries measured about 67.9 ms per full run, 26.7 MB, and 53,765 allocations on my Windows amd64 machine. I would keep latency/allocation reporting informational at first because those numbers are hardware-sensitive, while label validity, determinism, Recall@k, and MRR are appropriate regression checks after maintainers review the dataset.
This dataset is smaller and independently labelled, so its absolute scores are not directly comparable to the 49-query prototype in the issue. The replication does support the proposed sequencing: land an auditable benchmark harness first, then evaluate BM25/hybrid changes in a separate patch against the accepted labels.
Follow-up with a separate benchmark-only replication. This is intentionally not treated as the same dataset as the issue's 49-query/115-tool prototype, so the absolute numbers below are not directly comparable.
Against the current main snapshot 64a49f3, I ran a second 49-case natural-language corpus over the complete registered inventory. The harness validates every labelled tool against the production constructor and checks toolset membership before scoring; repeated inventory builds also produced the same corpus keys and tool-name sequence.
Observed current-heuristic results:
Metric
Result
Cases / deduplicated tools
49 / 117
Recall@1
0.367
Recall@3
0.571
MRR@10
0.478
Local verification on Windows amd64 (Intel Core Ultra 5 125H, Go 1.25.12) passed:
go test ./pkg/tooldiscovery -run 'TestToolSearchBenchmark' -count=1 -v
go vet ./pkg/tooldiscovery
The benchmark run measured about 8.25–8.64 ms/query, 1.13 MB/op, and 2,739–2,740 allocs/op. I would keep those performance values informational because they are machine- and corpus-sensitive.
The result reinforces the sequencing in the issue, but does not by itself justify changing production ranking: first agree on a canonical relevance-labelled corpus and inventory/snapshot semantics; then compare the current heuristic, BM25, and hybrid approaches against that corpus; only then consider a production change. I have not opened a PR or changed the ranking implementation.
Activity
CAOShurong commentedon Aug 23, 2026
I independently prototyped the benchmark-only scope against current
main(64a49f3) and think option 1 is the safest first step. It creates a measurable review surface without changing production ranking before the relevance labels themselves have been reviewed.The prototype uses 31 static, hand-labelled natural-language cases across 19 toolsets. It builds the real inventory through
NewInventory(...).WithToolsets([]string{"all"}).Build(), then fails if a labelled tool is missing or belongs to a different toolset. On the current heuristic it measured:Two implementation details seem worth preserving in an upstream harness:
SearchToolscurrently has no explicit tie-breaker for equal scores, so requiring full result-list equality would encode an ordering that production does not promise.Local verification with Go 1.25.12 passed:
A separate Go benchmark over the same 31 queries measured about 67.9 ms per full run, 26.7 MB, and 53,765 allocations on my Windows amd64 machine. I would keep latency/allocation reporting informational at first because those numbers are hardware-sensitive, while label validity, determinism, Recall@k, and MRR are appropriate regression checks after maintainers review the dataset.
This dataset is smaller and independently labelled, so its absolute scores are not directly comparable to the 49-query prototype in the issue. The replication does support the proposed sequencing: land an auditable benchmark harness first, then evaluate BM25/hybrid changes in a separate patch against the accepted labels.
CAOShurong commentedon Aug 23, 2026
Follow-up with a separate benchmark-only replication. This is intentionally not treated as the same dataset as the issue's 49-query/115-tool prototype, so the absolute numbers below are not directly comparable.
Against the current
mainsnapshot64a49f3, I ran a second 49-case natural-language corpus over the complete registered inventory. The harness validates every labelled tool against the production constructor and checks toolset membership before scoring; repeated inventory builds also produced the same corpus keys and tool-name sequence.Observed current-heuristic results:
Local verification on Windows amd64 (Intel Core Ultra 5 125H, Go 1.25.12) passed:
The benchmark run measured about 8.25–8.64 ms/query, 1.13 MB/op, and 2,739–2,740 allocs/op. I would keep those performance values informational because they are machine- and corpus-sensitive.
The result reinforces the sequencing in the issue, but does not by itself justify changing production ranking: first agree on a canonical relevance-labelled corpus and inventory/snapshot semantics; then compare the current heuristic, BM25, and hybrid approaches against that corpus; only then consider a production change. I have not opened a PR or changed the ranking implementation.