MCP will find the tool. It will not vouch for the hand that calls it.
The catalog finds the tool. The hook decides whether it fires. Neither one can tell you who the agent is when the call leaves the process.
That is the hole this week has been circling. MCP made tools discoverable. Composio put a thousand of them behind seven meta-tools and a session. Strands put a cancel hook on the path you already own. Discovery is, for the first time, a solved class of problem. Authentication is not. Every one of those tools still opens with a credential minted for a human, stuffed into an environment variable, or refreshed by a browser tab someone has to keep clicking.
I keep watching teams collapse three different auth problems into one sentence, then wonder why the sentence does not hold.
The first problem is client to server. The MCP 2026-07-28 spec finally treats an MCP server as an OAuth 2.1 resource server. Protected Resource Metadata is required. Resource Indicators bind a token to one audience, so a hostile server cannot harvest a token meant for another. Client ID Metadata Documents replace the Dynamic Client Registration mess. Strands 1.53.0 shipped client OAuth on streamable HTTP on August 21. That is real work. It authenticates the MCP client to the MCP server. It does not authenticate the agent to GitHub, or to the payer portal, or to the billing API the refund tool is about to hit.
The second problem is credential exfiltration. We covered that in July. Infisical Agent Vault sits on the wire as a TLS-intercepting proxy, swaps a placeholder for the real key, and never lets the secret enter the agent’s context. The repo sits at 2,129 stars, up from about 1,900 a month ago. v0.39.1 landed August 4. Last push was August 23. Harbor SDK takes the other cut: the agent invokes an abstract tool, the connector holds the key in another process, and the agent never learns the endpoint exists as a network primitive. Harbor is at 385 stars. The latest tag is v0.1.2, published June 5. Nothing has shipped since. A proxy that hides the key and a sandbox that hides the tool both answer “how do I stop a prompt-injected agent from walking out with a PAT.” They do not answer “how does this agent prove it is allowed to act.”
The third problem is the one nobody has a protocol for. The agent itself needs an identity. Not a service account copied from the CI pipeline. Not the intern’s Google login that Composio asked them to approve in a browser. A principal the authorization server can issue a short-lived, audience-bound token to, without a human in the loop every ninety days.
Composio’s first-connection flow is the honest picture of where the industry sits. The agent needs Gmail. Composio generates an OAuth link. A human opens a browser, clicks Allow, and the connection sticks to that user_id. After that, refresh tokens keep it alive until they don’t. When Google or Microsoft forces reconsent, or the refresh token is revoked, or the engineer who clicked Allow leaves the company, the agent stops. That is a solved onboarding ceremony for a product with users. It is not agent-scale authentication. It is a human workflow with an SDK wrapped around it.
The reason this keeps getting papered over is that OAuth was designed for a person sitting in front of a browser. PKCE protects the code exchange. It does not prove which workload asked. If any process can start a PKCE flow, the flow is not authenticating an agent. It is authenticating whoever showed up. Infrastructure-asserted identity is how we already solve this for services: an IAM role on a Lambda, a Kubernetes service account token projected into a pod, a federated credential on a workload identity. The authorization server attests the runtime, then mints an ephemeral token. No long-lived secret. No ninety-day click. Agents do not get that treatment because we keep modeling them as chat users who happen to call APIs.
Microsoft noticed. Entra Agent ID went generally available in April. Agent identities in Entra do not hold credentials of their own. They acquire tokens through an identity blueprint using federated credentials. That is the right shape: the agent is a principal, the secret lives elsewhere, Conditional Access can attach to it. It is also a Microsoft-shaped answer. If your estate is Copilot and Agent 365, you have a path. If your estate is Hermes on a desktop, a Strands loop on Lambda, and a Composio session for the SaaS tail, Entra does not cover the call that will page you.
The audit problem sits under all three. An examiner does not want to know that a token was valid. They want to know which agent, acting for which user, called which tool, against which resource, under which policy, and why the runtime allowed it. Agent Vault logs destination, status, latency, and actor name. That is a request log, which is better than nothing and not an authorization decision. Strands can cancel a refund in BeforeToolCallEvent and leave a trace. Composio’s hosted MCP path skips the SDK hooks, so the reason code never gets written. MCP itself still treats authorization as optional. A server that never asks for a token is spec-compliant. Spec-compliant and unauthenticated is how you get a public MCP port with a production database behind it.
Here is what I would actually build while the standard catches up.
Treat the three problems as three layers, because collapsing them is how the incident starts. Client-to-server auth belongs on the MCP transport: OAuth 2.1, resource indicators, short-lived tokens, refuse servers that skip it. Credential brokering belongs under the agent. Use Agent Vault if you want a network guarantee and you can own the CA and the egress firewall. Treat Harbor’s connector model as a pattern if the blast radius of a free-form tool call is the thing you cannot accept, and treat the SDK as a pattern too: eighty days without a tag is not a product you bet a control plane on. Agent identity belongs in the runtime you already run. Internals should use the workload identity the platform already knows how to attest. User-delegated SaaS can keep the browser consent if you bind it to a real user_id and put a rotation alarm on the refresh token instead of discovering expiry in the incident channel. The call that is the product stays in-process, with the intersection in the hook: what this agent is allowed to do and what this user is allowed to do, evaluated per action. Never the union. If a user cannot issue a refund, the agent acting for them cannot either, no matter what IAM role the process was launched with.
The decision rule is simpler than the architecture. If a human has to click Allow for the agent to keep working, you do not have agent-scale authentication. You have a demo with a calendar reminder. If the agent holds a static key, you have a prompt-injection exfil waiting on the next poisoned document. If the only identity in the audit log is a shared service account, you cannot answer the question a CISO will ask after the first bad tool call.
Tomorrow I will put the layers on one diagram: discovery, authentication, execution, observability, and the one design choice that decides whether a credential rotation takes the agent down. Leave a blank where the agent’s name should be and you will feel the outage before you feel the architecture.
If this was useful, forward it to one engineer who needs less noise in their feed.


