Context
v3.0.0 renames every Gateway product tool from hookdeck_* to gateway_* (#352, epic #354).
The v3.0.0-beta.1 release notes already handle the out-of-band half of this well: a full old → new rename table, an explicit warning that per-tool permission grants and allowedTools entries do not survive a rename, and a recommendation to prefer server-scoped patterns like mcp__hookdeck__*.
What we do not have is any in-band handling. This issue covers the two gaps.
Gap 1: no transitional alias on tools/call
An agent that calls hookdeck_events after upgrading gets a JSON-RPC -32602 Unknown tool. The MCP spec draws a deliberate distinction here:
Clients MAY provide protocol errors to language models, though these are less likely to result in successful recovery.
Clients SHOULD provide tool execution errors to language models to enable self-correction.
So the one channel that can reach the model and get it to retry correctly is the one we are not using. Whatever is cached, hardcoded in a prompt, or written into an AGENTS.md hits a dead end with no pointer to the replacement.
Two options, either acceptable:
- Alias middleware on
tools/call that maps hookdeck_* to the gateway_* equivalent, forwards the call, and appends a deprecation notice to the result. Keep aliases out of tools/list so we do not double the tool count or bloat context.
- Fail loudly but usefully: return a tool execution error (
isError: true) naming the replacement rather than a protocol Unknown tool. Forces migration, but the agent is told where to go.
Worth noting we already do exactly this pattern on the CLI surface: cobra commands carry Aliases (pkg/cmd/event.go, destination.go, request.go and others) and connectionDeprecationNotice in pkg/cmd/connection.go prints a migration message on the deprecated path. The MCP tool surface never got the equivalent.
Note that a CLI-distributed MCP server has no URL to version, so there is no side-by-side v2/v3 migration path the way a remote server would have. An upgrade swaps the tool surface underneath the user with no seam, which is what makes the in-band alias worth more here than it would be elsewhere.
Gap 2: the release notes describe the annoying failure, not the dangerous one
The notes say grants will need re-approving. That is the allow case, and it fails closed: the user is prompted again and re-approves.
The deny case fails open and is worth calling out separately. From the Claude Code permissions docs:
A deny or ask rule whose tool name matches no known tool produces a startup warning to catch typos. Tool names containing _ or * are exempt from the check.
Every MCP tool name contains __ by construction (mcp__<server>__<tool>), so every MCP permission rule is exempt from that warning. A user who wrote mcp__hookdeck__hookdeck_events into a deny rule to block something has that guardrail silently stop matching after the rename, with no startup warning and nothing in the UI. That is a security note, not an ergonomics one, and it should be explicit in the release notes.
Suggested scope
Context
v3.0.0 renames every Gateway product tool from
hookdeck_*togateway_*(#352, epic #354).The
v3.0.0-beta.1release notes already handle the out-of-band half of this well: a full old → new rename table, an explicit warning that per-tool permission grants andallowedToolsentries do not survive a rename, and a recommendation to prefer server-scoped patterns likemcp__hookdeck__*.What we do not have is any in-band handling. This issue covers the two gaps.
Gap 1: no transitional alias on
tools/callAn agent that calls
hookdeck_eventsafter upgrading gets a JSON-RPC-32602 Unknown tool. The MCP spec draws a deliberate distinction here:So the one channel that can reach the model and get it to retry correctly is the one we are not using. Whatever is cached, hardcoded in a prompt, or written into an
AGENTS.mdhits a dead end with no pointer to the replacement.Two options, either acceptable:
tools/callthat mapshookdeck_*to thegateway_*equivalent, forwards the call, and appends a deprecation notice to the result. Keep aliases out oftools/listso we do not double the tool count or bloat context.isError: true) naming the replacement rather than a protocolUnknown tool. Forces migration, but the agent is told where to go.Worth noting we already do exactly this pattern on the CLI surface: cobra commands carry
Aliases(pkg/cmd/event.go,destination.go,request.goand others) andconnectionDeprecationNoticeinpkg/cmd/connection.goprints a migration message on the deprecated path. The MCP tool surface never got the equivalent.Note that a CLI-distributed MCP server has no URL to version, so there is no side-by-side v2/v3 migration path the way a remote server would have. An upgrade swaps the tool surface underneath the user with no seam, which is what makes the in-band alias worth more here than it would be elsewhere.
Gap 2: the release notes describe the annoying failure, not the dangerous one
The notes say grants will need re-approving. That is the allow case, and it fails closed: the user is prompted again and re-approves.
The
denycase fails open and is worth calling out separately. From the Claude Code permissions docs:Every MCP tool name contains
__by construction (mcp__<server>__<tool>), so every MCP permission rule is exempt from that warning. A user who wrotemcp__hookdeck__hookdeck_eventsinto adenyrule to block something has that guardrail silently stop matching after the rename, with no startup warning and nothing in the UI. That is a security note, not an ergonomics one, and it should be explicit in the release notes.Suggested scope
hookdeck_*→gateway_*renames, resolved attools/call, absent fromtools/list, with a deprecation notice on the resultdeny-rule warning to the v3 release notes and upgrade docs