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
Tool definition drift: 124 of 131 definitions changed in v2.0.0 (data + a pinning fix) #3466
I track how MCP server tool definitions change across releases for an agent security project.
In v2.0.0, 124 of 131 tool definitions changed, with no new capabilities advertised. The count still holds at v2.0.2, since PR #3454 only touches HTTP header validation.
Why it matters to your users:
Teams that pin definition hashes for injection review were forced into a full re-review by this release. Teams that don't pin absorbed 124 changed descriptions into running agents without noticing. Most teams don't know which of those two groups they're in.
I have per-release tables back through v1.14.0, reproduced independently twice, and a two-tier pinning scheme that separates meaningful changes from cosmetic ones so a release like this doesn't force a full re-review.
Independent confirmation and decomposition. We pin tool contracts (name + description + inputSchema + annotations) via sha-256, diff on update, and grade changes by direction. Running the same comparison on the __toolsnaps__ files at v1.14.0 vs v2.0.0:
Numbers match: 123 of 131 tools changed (you said 124 - the one-tool difference is likely a formatting boundary in one snap file). 8 unchanged, 10 added, 0 removed.
But the decomposition matters more than the count. Every single one of the 123 changes is the same thing: an outputSchema was added. The inputSchema, description, and annotations are byte-identical between versions for all 123 tools. This is a Go SDK upgrade artifact (output schema support landed in the SDK), not a semantic change to any tool.
The 8 unchanged tools are the list/search family (list_branches, list_issues, search_code, etc.) - they didn't get outputSchemas in-place. Instead, 10 new *_output variants were added alongside them (list_branches_output, search_code_output, etc.) with outputSchemas and the same operation. So the list/search tools have both an original (no outputSchema) and an _output variant (with outputSchema) in v2.0.0.
Why this matters for the pinning scheme you're proposing: a naive hash-pin flags all 123 tools and forces exactly the re-review storm you described. But if the pin grades changes by what actually moved, this entire release is:
0 BREAKING (no inputSchema change, no description rewrite, no annotation flip)
A reviewer seeing "123 NOTATION, 0 BREAKING" clicks through in seconds. A reviewer seeing "123 tools changed" without decomposition spends an afternoon. The grading is what makes pinning survive contact with SDK upgrades.
For calibration on how common SDK-upgrade waves are: we saw the identical pattern in chrome-devtools-mcp (MCP SDK v2 migration re-serialized all 28 tool schemas - dialect declaration, key order, additionalProperties form - with zero parameter-level edits). Graded, that wave scores 0 BREAKING + 30 NOTATION. Without grading, both releases look like emergencies.
Happy to share the full per-tool comparison table if useful. We also keep a public corpus of benign/weaponized contract pairs for testing pinning schemes against real attack shapes (description rewrites, schema mutations, sleeper tools): https://github.com/Paraphern/rugsnare
Agreed on the headline: 0 caller-breaking schema changes, and grading by type is what makes pinning survivable. Re-checking field by field against the v1.14.0 and v2.0.0 tags, three corrections:
- The 7 *_output.snap files carry "name": "list_branches" etc. — they are output-schema snapshots of the same tools, not new tools. Per served tool, 131/131 gained an outputSchema.
- get_job_logs.snap is byte-identical in both tags because it is unused; the served tool is snapshot-tested as get_job_logs_actions (actions_test.go), and that one changed.
- inputSchema is not byte-identical for 48 tools. 46 only add the x-mcp-header keyword (notation). Two are real: the feature-flagged find_duplicate lowers page/perPage minimum from 1 to 0 (loosened), and search_repositories now documents that with minimal_output=false modern clients receive “curated repository details, not the complete GitHub API object” — a behaviour change carried in a parameter description.
Graded: 0 breaking at the schema level, 1 loosened, 1 documented behaviour change, the rest notation. Our original “124 of 131” was right only because two errors offset; the graded figures above replace it.
On Saturday, October 10th, 2026 at 10:59 AM, GERALD MUDDLETHWACK ***@***.***> wrote:
Paraphern left a comment [(github/github-mcp-server#3466)](#3466 (comment))
Independent confirmation and decomposition. We pin tool contracts (name + description + inputSchema + annotations) via sha-256, diff on update, and grade changes by direction. Running the same comparison on the __toolsnaps__ files at v1.14.0 vs v2.0.0:
Numbers match: 123 of 131 tools changed (you said 124 - the one-tool difference is likely a formatting boundary in one snap file). 8 unchanged, 10 added, 0 removed.
But the decomposition matters more than the count. Every single one of the 123 changes is the same thing: an outputSchema was added. The inputSchema, description, and annotations are byte-identical between versions for all 123 tools. This is a Go SDK upgrade artifact (output schema support landed in the SDK), not a semantic change to any tool.
The 8 unchanged tools are the list/search family (list_branches, list_issues, search_code, etc.) - they didn't get outputSchemas in-place. Instead, 10 new *_output variants were added alongside them (list_branches_output, search_code_output, etc.) with outputSchemas and the same operation. So the list/search tools have both an original (no outputSchema) and an _output variant (with outputSchema) in v2.0.0.
Why this matters for the pinning scheme you're proposing: a naive hash-pin flags all 123 tools and forces exactly the re-review storm you described. But if the pin grades changes by what actually moved, this entire release is:
- 0 BREAKING (no inputSchema change, no description rewrite, no annotation flip)
- 0 LOOSENED (no constraint dropped)
- 123 NOTATION (outputSchema added, input/description unchanged)
- 10 NEW (output-variant tools)
A reviewer seeing "123 NOTATION, 0 BREAKING" clicks through in seconds. A reviewer seeing "123 tools changed" without decomposition spends an afternoon. The grading is what makes pinning survive contact with SDK upgrades.
For calibration on how common SDK-upgrade waves are: we saw the identical pattern in chrome-devtools-mcp (MCP SDK v2 migration re-serialized all 28 tool schemas - dialect declaration, key order, additionalProperties form - with zero parameter-level edits). Graded, that wave scores 0 BREAKING + 30 NOTATION. Without grading, both releases look like emergencies.
Happy to share the full per-tool comparison table if useful. We also keep a public corpus of benign/weaponized contract pairs for testing pinning schemes against real attack shapes (description rewrites, schema mutations, sleeper tools): https://github.com/Paraphern/rugsnare
(Disclosure: I maintain the pinning/diff tool referenced above - open source, zero deps. The 218-finding drift audit across the npm MCP top is its output: https://github.com/Paraphern/rugsnare/blob/main/audits/npm-top-mcp-drift-2026-10.md)
—
Reply to this email directly, [view it on GitHub](#3466?email_source=notifications&email_token=CRBDEPIC3SPZT6UJ6P5QSKT5TJ2IHA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTMMJQGA2TEMZXGQ32M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KYZTPN52GK4S7MNWGSY3L#issuecomment-6100523747), or [unsubscribe](https://github.com/notifications/unsubscribe-auth/CRBDEPKH2QOABCDO3BP6FHT5TJ2IHAVCNFSNUABFKJSXA33TNF2G64TZHM4TIMRXG4YTEOBUHNEXG43VMU5TKNZXGA3TGOJUGI4KC5QC).
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for [iOS](https://github.com/notifications/mobile/ios/CRBDEPI2VNK2HVZ4HKRO2JT5TJ2IHA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTMMJQGA2TEMZXGQ32M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KUZTPN52GK4S7NFXXG) and [Android](https://github.com/notifications/mobile/android/CRBDEPNHFMYRCI6VABAPFU35TJ2IHA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTMMJQGA2TEMZXGQ32M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2K4ZTPN52GK4S7MFXGI4TPNFSA). Download it today!
You are receiving this because you authored the thread.Message ID: ***@***.***>
All three corrections verified against both tags - and our comment above was wrong where you said it was. The "inputSchema byte-identical for all 123" claim fails on 48 tools: 46 add the x-mcp-header keyword (46 snap files carry it at v2.0.0, zero at v1.14.0 - notation), and two are real:
find_duplicate_ff_duplicate_detection: page and perPage minimum 1 -> 0 (confirmed in both snaps) - a genuine LOOSENED, on a feature-flagged tool as you note.
search_repositories.minimal_output: v2.0.0 documents "modern clients receive additional curated repository details, not the complete GitHub API object. Legacy clients retain full GitHub API repository objects" - a behavior change carried in a parameter description, which also quietly introduces a legacy/modern client split.
We also misread the 7 *_output snaps as new served tools rather than output-schema snapshots. Thank you for the field-by-field recheck - our decomposition used the same snap files and inherited the same blind spots.
The corrected shared result is stronger than either original: 0 breaking at schema level, 1 loosened, 1 documented behavior change, the rest notation. And this thread is now itself the best argument for the method: two independent analyses publicly correcting each other down to graded truth, in front of the repo that needs it. For pinned users the actionable line is exactly yours - nothing breaks callers, but find_duplicate accepting page 0 and search_repositories changing shape for modern clients are the two things a changelog should have named.
Sometimes our tool surface changes, in this case adding output schemas and structured outputs.
It's broadly a noop beyond output schemas, but we reserve the right to change our offered tool schemas from time to time and so I'll close this as it's expected that we may decide to do this as models and agents evolve, to ensure we stay fit for purpose.
In this case it is an effort to support code mode clients.
Activity
Paraphern commentedon Oct 10, 2026
Independent confirmation and decomposition. We pin tool contracts (name + description + inputSchema + annotations) via sha-256, diff on update, and grade changes by direction. Running the same comparison on the
__toolsnaps__files at v1.14.0 vs v2.0.0:Numbers match: 123 of 131 tools changed (you said 124 - the one-tool difference is likely a formatting boundary in one snap file). 8 unchanged, 10 added, 0 removed.
But the decomposition matters more than the count. Every single one of the 123 changes is the same thing: an
outputSchemawas added. TheinputSchema,description, andannotationsare byte-identical between versions for all 123 tools. This is a Go SDK upgrade artifact (output schema support landed in the SDK), not a semantic change to any tool.The 8 unchanged tools are the list/search family (
list_branches,list_issues,search_code, etc.) - they didn't get outputSchemas in-place. Instead, 10 new*_outputvariants were added alongside them (list_branches_output,search_code_output, etc.) with outputSchemas and the same operation. So the list/search tools have both an original (no outputSchema) and an_outputvariant (with outputSchema) in v2.0.0.Why this matters for the pinning scheme you're proposing: a naive hash-pin flags all 123 tools and forces exactly the re-review storm you described. But if the pin grades changes by what actually moved, this entire release is:
A reviewer seeing "123 NOTATION, 0 BREAKING" clicks through in seconds. A reviewer seeing "123 tools changed" without decomposition spends an afternoon. The grading is what makes pinning survive contact with SDK upgrades.
For calibration on how common SDK-upgrade waves are: we saw the identical pattern in chrome-devtools-mcp (MCP SDK v2 migration re-serialized all 28 tool schemas - dialect declaration, key order, additionalProperties form - with zero parameter-level edits). Graded, that wave scores 0 BREAKING + 30 NOTATION. Without grading, both releases look like emergencies.
Happy to share the full per-tool comparison table if useful. We also keep a public corpus of benign/weaponized contract pairs for testing pinning schemes against real attack shapes (description rewrites, schema mutations, sleeper tools): https://github.com/Paraphern/rugsnare
(Disclosure: I maintain the pinning/diff tool referenced above - open source, zero deps. The 218-finding drift audit across the npm MCP top is its output: https://github.com/Paraphern/rugsnare/blob/main/audits/npm-top-mcp-drift-2026-10.md)
AAtomless commentedon Oct 12, 2026
Paraphern commentedon Oct 12, 2026
All three corrections verified against both tags - and our comment above was wrong where you said it was. The "inputSchema byte-identical for all 123" claim fails on 48 tools: 46 add the
x-mcp-headerkeyword (46 snap files carry it at v2.0.0, zero at v1.14.0 - notation), and two are real:find_duplicate_ff_duplicate_detection:pageandperPageminimum 1 -> 0 (confirmed in both snaps) - a genuine LOOSENED, on a feature-flagged tool as you note.search_repositories.minimal_output: v2.0.0 documents "modern clients receive additional curated repository details, not the complete GitHub API object. Legacy clients retain full GitHub API repository objects" - a behavior change carried in a parameter description, which also quietly introduces a legacy/modern client split.We also misread the 7
*_outputsnaps as new served tools rather than output-schema snapshots. Thank you for the field-by-field recheck - our decomposition used the same snap files and inherited the same blind spots.The corrected shared result is stronger than either original: 0 breaking at schema level, 1 loosened, 1 documented behavior change, the rest notation. And this thread is now itself the best argument for the method: two independent analyses publicly correcting each other down to graded truth, in front of the repo that needs it. For pinned users the actionable line is exactly yours - nothing breaks callers, but
find_duplicateaccepting page 0 andsearch_repositorieschanging shape for modern clients are the two things a changelog should have named.SamMorrowDrums commentedon Oct 12, 2026
Sometimes our tool surface changes, in this case adding output schemas and structured outputs.
It's broadly a noop beyond output schemas, but we reserve the right to change our offered tool schemas from time to time and so I'll close this as it's expected that we may decide to do this as models and agents evolve, to ensure we stay fit for purpose.
In this case it is an effort to support code mode clients.