Finishing the DPoP profile and getting it adopted is on the MCP roadmap refreshed in late August, and the SDK work is already in progress. DPoP is one of three ways to reach the same goal, though, and the other two, HTTP Message Signatures and mutual TLS, keep walking back into the room, including in the last authorization maintainers call I sat in. If you run an MCP server, one of these will reach your stack within the year, and it helps to know what each one is for before it shows up in a pull request.
All three attack the same weakness, the bearer token. Today an MCP client gets an access token from an authorization server, puts it in a header on every call, and the server honors whoever presents it. The token behaves like cash. Whoever holds it can spend it, and the server cannot tell the original client from someone who copied the string out of a log, an environment variable, or a compromised laptop. MCP already limits the damage by requiring tokens to name the server they were issued for and by asking for short lifetimes, and a stolen token still works for as long as it lives. The fix everyone agrees on is to tie the credential to a private key that never leaves the client, so presenting it also means proving you hold the key. The disagreement is about where to put that lock, and each candidate picks a different layer.
On the token
DPoP puts the lock on the token itself and lives entirely inside OAuth. When the client asks for a token it shows the authorization server a public key, and the token comes back tied to that key. From then on every request carries a small signed note next to the token that says, in effect, “I hold the key this token was issued to, and I am sending this method to this URL right now.” The note signs the method and the URL and nothing else, so in an MCP call the tool name and its arguments go out unsigned. The server checks the note against the key in the token and rejects anything that does not match. Steal the token and you get a string that no longer works anywhere.
DPoP fits MCP because MCP authorization is already OAuth 2.1, and the profile asks the client to generate a key pair and sign one extra header on every call. It works for public clients, so a CLI on a laptop can use it without any certificate infrastructure, and it survives proxies and gateways because the proof rides inside the HTTP request, as long as the gateway does not rewrite the URL the client signed. The costs are real but small. The authorization server has to support it, and hardly any advertise support yet. The private key still has to live somewhere sensible. A key in the same process as the token still protects you from the common leaks, because a token copied out of a log leaves the key behind. It does nothing once someone owns the process. The mechanism itself has been an RFC since 2023 and already runs in production elsewhere; the MCP proposal, open since December, is settling the details for this protocol.
On the request
HTTP Message Signatures move the lock off the token and onto the message. The client signs the parts of the request it cares about, the method, the target, selected headers, and optionally a digest of the body, and the receiver verifies that signature against the sender’s public key, which in practice it fetches from a well-known URL on the sender’s domain. Nothing in that sentence mentions an authorization server or a token. The key is the identity, and a server can recognize a caller it never registered, though that tells it who is calling and nothing about what they may do.
That is why the approach is showing up first where there is no OAuth to speak of. The large edge networks already verify these signatures to tell a legitimate crawler from a spoofed user agent, under an IETF effort called Web Bot Auth, and newer proposals for agent protocols go further and sign every request so that bearer tokens disappear entirely. The signature format itself is a finished RFC, and everything built on it for bots and agents is still draft material at the IETF, which tells you where this sits on the maturity curve. The upside is that a signature can cover the body, so a tampered request fails, and it names the sender on every hop without a token exchange. The downside is that HTTP is messy, so any intermediary that rewrites a covered header breaks the signature and the canonicalization rules have sharp edges. The tooling is catching up though, with curl 8.22, released in early September, shipping experimental support for signing requests this way, which puts the primitive one command line flag away from anyone curious enough to point it at a server. For MCP this one is worth watching, and worth building on today only if you already live outside OAuth.
On the connection
Mutual TLS puts the lock on the channel. The client presents a certificate during the TLS handshake, the server verifies it against a CA it trusts, and from then on the server knows everything on the connection came from the holder of that certificate. OAuth has a profile that ties tokens to the certificate too, so a token stolen from one client fails over a connection opened with a different one. It is the oldest of the three, it carries a lot of regulated traffic today, and the crypto happens below the application, so the client does nothing per request.
Some teams have taken this a step further and use the certificate as the agent’s identity outright. SPIFFE gives every workload a short-lived certificate that encodes its name, and SPIRE hands those out based on where the process runs instead of a secret someone pasted in, which is why the big cloud providers are building their agent identity services on top of it. Inside one platform this is excellent, with no secrets to hand out, certificates that rotate on their own, and both sides of every connection authenticated. The trouble starts at the edges. TLS terminates at load balancers, CDNs, and gateways, and the binding stops there unless the proxy forwards the client certificate and the server takes the proxy’s word for it. Laptops and browsers make poor certificate holders. And a workload certificate tells you which process is calling while saying nothing about which of the ten agents sharing that process sent the request, or on whose behalf. Be warned that the SPIFFE rabbit hole is deep and pleasant, and it is easy to come out the other side holding a service mesh and no answer to the question you went in with.
Wrapping up
DPoP locks the token, HTTP Message Signatures lock the request, and mTLS locks the connection. DPoP and the mTLS token profile make a stolen token useless, signatures make the token unnecessary, and none of the three helps once the attacker is inside the agent, because whoever controls the agent can ask the key to sign anything. For MCP, DPoP lands first, since the protocol already runs on OAuth and the roadmap now lists it, while HTTP signatures and mTLS will keep showing up around it, at the edge and inside platforms. Whatever you pick, put the private key somewhere the agent process cannot leak it, because all three assume the key stays where the client put it and none of them can check.