Build Stack Review

Tool Availability Contracts for MCP-Native Agent Workflows

Most agent failures stem from missing tools, not bad reasoning.

Senior Writer · · 13 min read
Cover illustration for “Tool Availability Contracts for MCP-Native Agent Workflows”
AI Agent Development Environments · September 5, 2026 · 13 min read · 2,915 words

The instinct, when an MCP agent gives a wrong answer, is to blame the model: retune the prompt, swap in a bigger model, bolt on another guardrail. That instinct is wrong more often than the industry admits. Most of the time, the agent isn't reasoning badly; it's reasoning correctly over bad inputs, or no inputs at all, because a tool it expected to find wasn't there, or was there under a different schema, or was running a version nobody had checked in months. The fix isn't a smarter agent. It's a platform team that treats tool availability as a contract, not an assumption, and the industry's failure to do this consistently is the actual subject of this piece.

MCP agents rarely fail loudly, and that's what makes the bug so persistent. When a tool is missing, most implementations don't throw an error and stop; the agent adapts, guesses at an alternative, or produces a plausible-looking answer built on a gap it never flagged. Whoever looks at the output sees a reasoning failure. What actually happened was an infrastructure failure wearing a reasoning failure's clothes. Stable platform contracts beat clever agent behavior every time, and once that's accepted, the whole problem moves out of prompt engineering and into platform engineering. The rest of this piece works through what that move actually requires.

What MCP is and why its scale makes the contract problem urgent

The Model Context Protocol is an open standard, built on JSON-RPC, that lets AI applications discover and call tools, prompts, and resources hosted on remote servers, through a session that used to be stateful and is increasingly stateless. Anthropic launched it in November 2024, and it did not stay a niche experiment. Something like 97 million monthly SDK downloads and more than 9,400 public servers now run on it, with native support from Anthropic, OpenAI, Google DeepMind, and Microsoft. That's not one vendor's pet project; that's the entire set of major model providers agreeing on how agents should talk to tools.

The governance changed too. In December 2025, Anthropic handed MCP over to the Agentic AI Foundation, a Linux Foundation project co-founded with Block and OpenAI, moving it from a single company's API to a standard the whole community maintains. Gartner expects 75% of API gateway vendors to ship MCP support by the end of 2026. Infrastructure vendors already treat this as something they have to support, not something they're watching from the sidelines.

Scale is exactly why the tool-availability problem stops being a team-level annoyance and becomes systemic. When ten teams each run their own MCP servers with their own informal assumptions about what's installed and at what version, you get ten small inconsistencies. When the ecosystem is thousands of public servers feeding agents across every major provider, those small inconsistencies compound into something closer to an infrastructure risk: one that shows up as unpredictable agent behavior across an entire industry, not one team's Slack channel.

How MCP's protocol actually handles tool discovery — and where it leaves a gap

Discovery under MCP isn't a single "give me the list" call. It starts with a JSON-RPC 2.0 handshake that negotiates protocol version, transport, and supported extensions, and only after that negotiation does tool enumeration happen. Servers declare which primitives they support, tools, resources, prompts, and whether their tool list can change dynamically. That's capability advertisement built into the protocol itself, and it's a genuinely useful piece of design.

But advertisement only means something if the server advertising it is actually there and reachable. The protocol specifies the handshake; it says nothing about whether what's on the other end matches what was expected. That's the gap, and it's the gap this whole piece is about.

One 2026 roadmap item, Progressive Tool Discovery, tries to solve a related but different problem: decoupling the size of a tool catalog from the size of the context window, so an agent doesn't need hundreds of JSON schemas stuffed into its prompt just to know what's available. That matters, because feeding a model hundreds of tool definitions at once dilutes its reasoning, raises the odds of hallucination, and runs up token costs for no benefit. But smarter negotiation between client and server doesn't fix the underlying issue. A client that dynamically negotiates capabilities against an environment with no conformance guarantees just inherits whatever non-determinism that environment already has.

The July 2026 shift to a stateless protocol core makes this sharper, not softer. Every request now has to describe itself fully, since any server instance can serve any request behind a round-robin load balancer. That's better for scaling, but it also means tool availability can no longer be assumed to carry over from session state; each request has to prove it on its own. The 2026-07-28 release did add a formal deprecation policy, so tools a platform declares available get a lifecycle instead of vanishing without notice, a real if modest first step toward a contract model. But the specification still doesn't say what should happen when a declared tool is absent or its schema doesn't match. It describes how discovery works. It doesn't mandate what to do when discovery finds nothing, or finds something different from what was promised.

What a tool availability contract actually needs to specify

A tool availability contract isn't a runtime check that fires when something breaks. It's written down ahead of time: exactly which tools must exist, at what version, with what schema, on what architecture, before an agent workflow is even allowed to start.

Four things belong in a contract that actually holds up, and skipping any one of them is where most of these failures start. Presence is the most basic: the tool exists, and the server hosting it answers when called, a condition still left to blind trust in most setups today. Version pinning comes next: a specific version, or a range locked to a lockfile, not "latest" and not whatever happens to resolve when the pull runs. Schema conformance is the one people miss most often, because a tool sitting at the exact right version can still hand back a different response shape if it was built in a different environment than the one that generated the contract. Architecture consistency closes the list: the contract has to say which operating systems and chip architectures are in scope, because a tool that works fine on x86 Linux doesn't automatically work on ARM macOS, or inside whatever runner the CI pipeline happens to use that week.

That contract belongs in version control, sitting in the same repository as the agent workflow it governs, not in a wiki page or a team's tribal memory. It needs to be checked when the environment spins up, not when the agent gets around to calling the tool; by the time the agent makes that call, the missing dependency has already done its damage. One distinction worth holding onto: availability is upstream of authorization. MCP's 2026 Enterprise-Managed Authorization model governs what an agent is allowed to do. The availability contract governs what actually exists for it to do in the first place. Get the second one wrong, and the first one answers a question that doesn't apply.

How environment drift turns undeclared tool assumptions into agent failures

Diagram: Environment Drift by the Numbers. Visualizes: Visualize three concrete statistics that together prove tool-environment drift is the norm, not an edge case.

Here's the shape of the problem in practice. The same SETUP.md file, followed exactly, resolves to different tool versions depending on where it runs: Python 3.13.1 on a developer's laptop, 3.12.7 in CI, Node.js 22.3.0 in two environments and 20.11.1 in a third, OpenSSL splitting across all three in ways nobody planned. No two environments match, even though every one of them claims to follow the same instructions.

For an MCP agent, that divergence isn't cosmetic. It changes behavior directly: a tool that returns one schema shape in a developer's local setup returns a different shape in CI, and the agent has no way of knowing which one is the "real" one, because nothing told it there were two versions to choose between in the first place.

The data backs up how common this is. A study of 5,298 Docker builds (Malka et al., January 2026) found that only 6.4% of rebuilt images matched the original's installed package versions exactly. The assumption that containers guarantee reproducibility is false for the overwhelming majority of builds, not a minority edge case. In a separate look at LLM-generated software engineering artifacts, leaving out machine-readable dependency lists or explicit system details led to unreproducible results in roughly 21% of cases (Siddiq et al., November 2025). And environment changes by themselves, no change to the model, no change to the prompt, produced test-accuracy drift greater than 6% for classifiers and greater than 8% for LSTM models across different hardware (Coakley et al., 2023). Translate that into MCP terms: tool-schema drift produces agent-output drift, on the same order of magnitude, for the same reason.

Most organizations already run two separate environment configurations, one for developer machines, one for CI, and neither is fully solved today. MCP agents become a third consumer of environment state, and a third source of drift, stacked on top of a problem nobody had actually fixed for the first two. Floating dependencies are the actual mechanism underneath all of this: a Dev Container built from an image tag instead of a digest, or a package spec with no lockfile, can quietly resolve to a different tool version the next time someone pulls it. That's a configuration discipline problem, plain and simple, and it stays invisible right up until it surfaces as an agent bug that looks, to whoever's debugging it, like a reasoning failure.

The platform engineering approach to enforcing tool availability contracts

Tool availability needs to be treated as infrastructure, the same category as CI runners or a container registry, owned by a platform team rather than left to whatever convention each project team happens to adopt. Leaving it to convention is the mistake most organizations are currently making, whether they'd phrase it that way or not.

That starts with declarative environment definitions: tools, runtimes, and MCP server versions written into a single machine-readable file, checked into version control next to the workflow that depends on it, which is the core problem Flox addresses with a single manifest.toml pinning dependencies across dev, CI, and production. A lockfile isn't optional here. A declared environment with no lockfile is a wish, not a contract; without it, "the same version" quietly becomes "whatever resolved today."

On the reproducibility spectrum, Nix-based tooling, including NixOS and Devbox, offers the strongest guarantee available: builds that come out identical, down to the byte, across completely different machines, because the approach is declarative and purely functional rather than imperative. The tradeoff is a steeper learning curve than most teams are used to coming from Docker. Devbox in particular lowers that barrier: a project declares its environment in a simple config file, pins exact versions through a lockfile, and can generate Dockerfiles or devcontainer configs so the same declaration drives both a laptop setup and a containerized one. Dev Containers on their own are widely used and easy to adopt, but the common failure mode is a floating image tag; without pinning to a digest instead of just a version tag, "reproducible" is more aspiration than guarantee, and most teams using Dev Containers today are living with that aspiration rather than the guarantee.

Validation belongs at the moment an environment spins up, not at the moment an agent calls a tool. That means a pre-flight check, built into activation itself, that catches a missing or mismatched tool before the workflow ever starts, plus schema validation run in CI against the tool's declared input and output shape, not discovered for the first time in production.

The goal is one environment shared by every consumer: the developer's laptop, the CI runner, and the MCP agent all activate from the same declared source, closing off the three-way divergence described above. It's the same principle behind "test in an environment that matches production," extended to treat the agent as a first-class consumer of that environment rather than an afterthought. Architecture coverage has to be explicit too: which combinations of OS and CPU are actually supported, validated in CI on every one of them, not just on whichever machine the original developer happened to be using. And to keep this from turning the platform team into a bottleneck, the practical model is publishing governed base environments that project teams extend, rather than every team building its own from scratch and slowly drifting from everyone else's.

Why tool availability contracts are also a supply chain security boundary

An MCP server dependency with no version pin is an open door. Whatever resolves when the pull happens is what the agent runs on, and that resolution is exactly the kind of thing an attacker can tamper with.

This isn't hypothetical. Sonatype identified more than 454,600 new malicious packages in 2025, with 99% of them concentrated in npm, and MCP's SDK ecosystem is heavily npm and Python based, which puts it squarely in the blast radius. Traditional CVE scanning misses most of this activity: Socket reported detecting more than 1,700 malicious packages tied to a single North Korean campaign in the first half of 2025, most carrying no CVE at all, which means a clean scan tells you almost nothing about whether a package is actually clean. The attack surface isn't limited to package registries, either. Attackers modified the historical Git tags of a popular GitHub Action used by an estimated 23,000-plus repositories to exfiltrate CI/CD secrets, which means a compromised CI action can just as easily hand a malicious MCP server binary to every pipeline that trusts it.

The thread connecting all of this back to the contract is simple: you cannot sign or attest to something you can't reproducibly identify in the first place. A pinned, version-controlled, validated availability contract is the precondition for any supply chain claim being meaningful at all. Over 70% of organizations reported at least one supply chain incident tied to third-party software in 2025, and MCP tool dependencies are, by definition, third-party software. That exposure isn't a special case. It's the general case, applied to agents.

Embedding SBOMs and provenance into the tool availability contract

Diagram: SLSA Provenance Levels: From Document to Proof. Visualizes: Show the three SLSA provenance levels as a stepped progression, illustrating how each level strengthens the tool-availability contract's guarantee.

An SBOM for an MCP environment isn't a compliance checkbox filed away for an audit nobody reads. It's the evidence, in machine-readable form, that the contract was actually honored: these specific tools, at these specific versions, built from these specific sources.

Regulation is pushing this from optional to required, and treating it as optional now is a bet against where the rules are already headed. U.S. Executive Order 14028 requires SBOMs from federal software vendors, and the EU's Cyber Resilience Act extends comparable requirements across the EU market, which means MCP server operators in regulated industries are already inside the scope of these rules whether they've built for it or not. SBOMs, SLSA, and Sigstore have moved from things people mentioned at conferences to things operations teams are actually expected to run.

SLSA's provenance levels give a useful way to grade how strong a contract's guarantee actually is. Level 1 just means a provenance document exists somewhere: a low bar, but better than nothing. Level 2 means that provenance is signed, so the build's origin can be verified rather than taken on faith. Level 3 adds build isolation and verified authenticity, the strongest tier, where the tool that ran in CI is provably the same tool that got signed, not something swapped in along the way. Sigstore's tooling is the practical layer that makes L2 and L3 achievable: cosign signs artifacts, Fulcio issues short-lived certificates tied to OIDC identity instead of long-lived keys, and Rekor keeps a public, tamper-evident log of what got signed and when.

A static SBOM, generated once and filed away, ages badly in an environment where MCP server versions change constantly. A continuously updated Pipeline Bill of Materials, tracking component and dependency changes across every build rather than just at one snapshot in time, matches how live MCP environments actually behave. The payoff shows up during an incident: with a queryable, current SBOM for every declared tool, figuring out the blast radius of a coordinated supply chain attack becomes a matter of minutes instead of days, because the contract itself doubles as the audit trail. Provenance needs to be generated at the moment the environment is built, not bolted on afterward once someone asks for it. That's the difference between a security practice and a security performance.

Applying availability contracts to agent-to-agent and multi-agent topologies

MCP's 2026 roadmap adds agent-to-agent communication, where a receiving MCP server acts as an autonomous actor with its own domain, not just a passive endpoint waiting to be called. That single change multiplies the contract problem instead of just relocating it.

In a delegation chain, agent A hands work to agent B on the assumption that tool X is available. But agent B operates inside its own environment, with its own tool set, its own versions, its own schema guarantees, none of which agent A has any visibility into. Without a contract that travels with the delegation itself, agent A's assumption is just a guess dressed up as a plan. Everything covered in this piece, tool presence, version, schema, architecture, all needing to be pinned and validated ahead of time, doesn't disappear in a multi-agent topology. It just gets a second link in the chain, and a second place for a silent failure to hide.

More in AI Agent Development Environments