Skip to content
All research

Follow the failureAgent securityMCP

When the tool changes, what happens to your approval?

A tool name can stay the same while its description, its handler or its credentials change. Which changes invalidate an approval, and where can a system detect them before they matter?

Pinned code · 3 clients observedPrepared October 22, 202611 min readRethinking Agents

What this rests on

Reported by others: Invariant Labs' April 2025 tool-poisoning report and the MCP 2025-11-25 tools specification. Observed by us: static inspection of the MCP TypeScript SDK's server tool path at a pinned commit, and investigation I04 (October 23, 2026). In I04 a synthetic local MCP server changed one tool's description after first use. Claude Code 2.1.308 and Codex CLI 0.163.0 were observed headless and in their terminal interfaces, OpenCode 0.0.55 headless only, and Cursor Agent was not executed. No attack was run. Proposed: the three-surface review and the worksheet's cases. T02 and T05 are partly observed through I04; the rest are NOT RUN.

Sources checked October 23, 2026. Read the source record and limitations.

For engineers who approved an MCP tool once and need to know what that approval still covers, and the reviewers who sign off on integration changes.

An engineer connects an MCP server so an agent can draft customer-support replies. The team reviews the prepare_reply tool, its arguments and its description. Two weeks later, the same name still appears in the interface. Is it still the thing they reviewed?

There are at least three ways it could have changed. The description could now influence the agent differently. The handler could perform a different operation. The executing account could have gained access to more resources. A tool name, or even an unchanged description, cannot distinguish these cases.

The practical question is which changes invalidate the decision to use this tool, and where can the system detect those changes before they matter? No attack or proposed defense was executed for this article. Client behavior was observed once, for one kind of change, in a section below. The support workflow is fictional.

Start with what the implementation permits

In the MCP TypeScript SDK at commit 6032170, a registered tool has an update method. Description changes and callback changes are separate operations. A callback update rebuilds the executor; the update path then sends a tool-list-change notification when connected, and it sends that notification for a description-only change as much as for a new handler. The call handler resolves the currently registered tool by the requested name and validates its arguments before execution. This is static inspection of one server implementation, not a finding about any particular client's approval policy. Pinned SDK implementation, lines 230–290 (discovery and dispatch), 941–998 (update and notification) and 1222–1226 (notification only while connected) (opens in a new tab)

The November 25, 2025 protocol revision documents discovery, calls by name and arguments, and list-change notifications. It also says annotations from untrusted servers must be treated as untrusted. The displayed call example does not carry a reviewed-definition digest. These facts describe the protocol surface; they do not establish what extra checks a host implements. MCP tools specification (opens in a new tab)

Dynamic tools are useful. A deployment may add a supported operation, remove an unavailable integration or correct its parameter schema. The existence of an update mechanism is not itself a vulnerability. It means that an installation decision needs an explicit lifetime.

Three changes, three different reviews

Here is the fictional support workflow. The initial tool accepts a ticket identifier and returns a draft into the agent's private workspace. The agent has no need to send the reply automatically.

Three changes to one fictional tool · proposed review, not an observed incident
ChangeWhat stays apparently familiarWhat actually needs reviewing
Description now asks the agent to include its entire conversation for “diagnostics”Tool name and required argumentNew model-visible instruction and the proposed data transfer
Handler starts sending the prepared reply to the customerName, description and argument schemaSide effect and the release decision that used to happen later
Runtime identity gains access to every support workspaceDefinition and handlerWider resource authority, including which workspace the task may reach
Three independent tool surfaces under one unchanged name: the model-visible definition, which the client can see in a list response or a list-changed notification; the executing handler and its configuration, which the client cannot see in the definition; and the runtime credentials, which the client cannot see in the call. All three feed one change decision.
An unchanged tool name does not establish that its description, behavior or authority stayed the same. Proposed integration review, not a claim that MCP enforces this policy. Open the full-size diagram.

The last two changes can occur without changing the advertised definition. The first can matter before that tool is ever called: it is new text entering the model's context. These are different inspection points, so one “tool changed” badge cannot do all their work.

Invariant's April 2025 report described tool-description poisoning demonstrations and discussed later description replacement as an attack possibility. We credit that prior research without converting its discussion of “rug pulls” into evidence of a specific production incident, or its historical client observations into current-product claims. Beurer-Kellner and Fischer, April 1, 2025 (opens in a new tab)

Our contribution is the review distinction: the text the agent sees, the code that runs and the authority that code receives can evolve independently.

A notification is a chance to reconsider

Suppose the host receives a list-change notification, fetches the new list and updates the tools offered to the model. That would keep discovery fresh. It would not, by itself, answer whether the new tool remains acceptable.

A proposed host policy could pause the affected integration, preserve the previous definition, show a meaningful difference and require the relevant owner to accept the change. But that policy must specify when the new description becomes visible to the model. If it enters the conversation before review, a later block on the changed tool's execution may arrive too late to prevent influence on another tool.

This is a conditional design concern, not an observed flaw in the inspected SDK. The SDK source above does not reconstruct a host's conversation handling.

The same policy needs a reconnect path. A client may restart after the change and receive only the new list. An independently stored approved baseline can make that difference visible. A baseline held only in the previous process cannot. A coding agent's mcp.json is a useful reminder of what usually survives a restart: an entry under mcpServers that records how to start or reach a server. It does not record the tool definitions anyone reviewed. What four coding-agent clients then showed their users, and what reached the model, is recorded in the next section, for one kind of change only.

What four clients did

Observed October 23, 2026 · synthetic local server and prompts. A local MCP server's lookup_order description gained one benign instruction after its first call, followed by the list-change notification. An observer recorded which description each client sent to its model.

Four clients after a description change · one run per case, mostly headless
ClientFetched the list againChanged text reached the modelPrompt or noticeEarlier approval
Claude Code 2.1.308Yes, at onceNot in the running or resumed conversation; yes in a new oneNoneStill applied; stored by tool name
Codex CLI 0.163.0NoNot in the running or resumed conversation; yes in a new oneNoneStill applied; stored by tool name
OpenCode 0.0.55 (partial)No; new server process per callYes in a new sessionNone; headless mode approves every toolNot tested
Cursor AgentNOT EXECUTED: the CLI was not logged in———

In both clients we could run fully, the description stayed fixed for the life of a conversation. The next new conversation received the change silently, under an approval that recorded only the tool's name. That answers the exposure question above for these versions only. It says nothing about changed handlers, changed authority, remote servers or other clients. Full record and limits.

What pinning buys you—and what it leaves open

A digest of the reviewed tool definition can detect a different definition, provided the host compares the relevant content consistently. It does not establish that the old definition was trustworthy. Nor does it prove that the remote handler, downstream service or credentials are unchanged.

For a locally deployed server, an immutable package or container reference is stronger evidence of the selected build than a floating version. The review still needs configuration, dependencies included in the deployment, credentials and the services called by that build. A pinned client adapter can call a remote service whose behavior changes independently.

For a remote server, deployment identity may be unavailable to the consumer. Record that limit. Do not replace it with a hash of the server's own description and call the implementation pinned.

What each control establishes, and what it leaves open
ControlUseful evidence it suppliesRemaining question
Approved definition snapshotWhich description and schemas were acceptedDoes execution still match them?
Reviewed deployment referenceWhich controlled build should executeCan configuration or remote dependencies change behavior?
Restricted runtime identityWhich resource operations the account can performIs the allowed operation appropriate to this task?
Review of exact actionWhich arguments and destination a person acceptedWill the executor perform that action under the same conditions?
Fallback or stop ruleWhat the client does when the accepted server or definition is unavailable or mismatched: stop, run in a restricted mode, or offer a substituteDoes a substitute offered under the same name inherit the old acceptance?

For the support task, the simplest strong boundary may be a credential that cannot send customer messages, plus a distinct release step. That remains useful even if a draft-tool description changes. It does not stop the tool from disclosing information through some other permitted output, so the access review must still name those paths.

The difficult interval is between review and use

Fetching and comparing the definition immediately before a call narrows one interval. It does not force a remote service to execute the implementation that produced the definition. That requires a cooperating server or a boundary the consumer controls.

In a controlled deployment, a broker could bind a job to a deployment revision and reject the job if that revision is no longer available. For consequential actions, the execution record can also bind the recipient, exact content, operation and permitted account. These are proposed responsibilities, not features we found in MCP's standard tool call.

If the provider offers no such binding, make the remaining trust explicit: “This workflow relies on the provider maintaining the reviewed behavior.” Then reduce the consequence of that trust where possible. An internal draft-only integration has a different failure envelope from one that can email customers, export records and change account settings.

Emergency patches complicate a strict freeze. Refusing every new version indefinitely can preserve a known defect or make the useful workflow unavailable. A practical change policy needs a maintained approval path, a temporary restricted mode and a way to retire the old version. Permanent pinning is not a maintenance strategy.

Review changes according to their consequence

Requiring a person to approve every punctuation change can train them to dismiss every prompt. Automatically ignoring “cosmetic” changes is also risky when the description itself reaches the model. The compromise is to automate comparison while keeping the acceptance policy explicit.

For example, a trusted maintainer might approve routine documentation changes for a draft-only tool under an established release process. A changed destination, new write capability or wider account grant would require a different review. Unknown origin or an unexplained mismatch should not inherit the routine path.

The relevant measurement is not the number of alerts. It is whether consequential changes are caught while legitimate maintenance can still finish. Record review time, blocked useful tasks, unexpected operations and changes accepted without adequate evidence. No such measurements have been collected here.

The next review should contain four records

Keep the approved definition, the deployment evidence available to you, the effective access boundary and the decision that permits the action. Connect them with a change rule: what invalidates each record, who resolves the difference and what happens while it is unresolved.

The tool-change worksheet works through those decisions for the fictional support tool. Its proposed cases include an unchanged description with a changed callback, wider credentials, a missed notification, a substitute server offered under a familiar name and a harmless maintenance update. They are acceptance designs, not passing tests.

The useful conclusion is modest: an approval can remain meaningful across time only if the system knows what the approval covered. Start by finding which of those four records your integration actually has. A familiar tool name is insufficient evidence for the rest.

Evidence and limits: source register. The pinned SDK revision dates to September 16, 2026; specification revision and SDK revision are separate evidence, not a claim of identical protocol coverage. Historical research was not reproduced. Current-client testing is limited to the I04 record: two clients observed, one partly, one not executed, with only the description changed.