Authenticate an MCP Server with AWS IAM (SigV4)
When your agent runs in AWS, it can authenticate to an MCP server by signing each request with the credentials of the role it already has, so there is no token to issue and no secret to store.
- Method
- AWS IAM (SigV4)
- Platform
- AWS
- MCP Specification
- 2026-07-28
How it works
The agent signs every HTTP request with SigV4 and sends Authorization: AWS4-HMAC-SHA256 Credential=…, SignedHeaders=…, Signature=…. The AWS service in front of the MCP server — a Lambda function URL with AWS_IAM auth, API Gateway, or Bedrock AgentCore — recomputes the signature and evaluates IAM before your code runs. There is no token to mint, cache or rotate: the signature covers a SHA-256 of the request body, so every message is signed on its own. Behind a function URL the caller reaches your handler as an IAM ARN on the event.
- Best for
- Agents you write that run in AWS, calling a server behind Lambda, API Gateway, or AgentCore
- MCP spec
- Platform request signing rather than MCP authorization; the spec does not cover it
- Works with
- Your own agents. No MCP client signs SigV4; AWS ships a local proxy that does
- Effort
- An afternoon with AWS's transport, a day with the IAM policies
The exchange
Each step in the exchange, in order.
- Your agent task or Lambda role
- AWS function URL or AgentCore
- MCP server reads the caller ARN
-
No token is fetched. The signature is derived from role credentials already in the environment, so there is nothing to store and nothing to rotate, and the body hash means every message is signed separately.
Inside Your agent
Sign the canonical request SHA256 of the JSON-RPC body -
Your agent to AWS
POST /mcp Authorization: AWS4-HMAC-SHA256 … -
AWS verifies the signature and the IAM policy before your code runs. The caller arrives as an ARN in the request context rather than as a claim your handler has to validate.
Inside AWS
Recompute the signature, check IAM lambda:InvokeFunctionUrl + InvokeFunction -
AWS to MCP server
POST /mcp requestContext.authorizer.iam.userArn -
MCP server to AWS
200 OK tool result -
AWS to Your agent
200 OK tool result
Connect your agent
Pick your language and SDK.
When to use something else
Use this when
- The agent has an IAM role and the MCP server sits behind something that verifies SigV4 — a Lambda function URL, API Gateway, or AgentCore.
- You want no stored secret: the signature is computed per request from credentials already in the environment.
- Tool calls have to resolve to an IAM principal, which a function URL hands your code as an ARN on the event.
Use something else when
- The server is behind an Application Load Balancer or a raw EC2 endpoint. AWS names both as incompatible with IAM signing, because neither natively verifies SigV4 signatures.
- A person's chat client has to connect. No MCP client signs requests, so the answer is a local signing proxy or an OAuth front door.
- You need SigV4 and OAuth on one AgentCore Runtime: a runtime accepts either IAM SigV4 or JWT bearer inbound auth, not both at once.
This is platform request signing, not MCP authorization, and the specification does not describe it. Authorization is OPTIONAL there — "Implementations using an HTTP-based transport SHOULD conform to this specification" — so a signed request sits outside the OAuth profile rather than in conflict with it. That sentence is word-for-word identical in the 2025-11-25 revision and in 2026-07-28, the current protocol version. The cost is reach: it is the strongest option inside your own account and unavailable to everything else.
What lands on you next
SigV4 answers one question exactly: which IAM principal signed this request. The questions that follow are about callers with no IAM principal, and about what a principal may do once it is through the door.
-
Security wants to know which human was behind that role's tool call.
-
capability_invocationEach tool call emits an event carrying the authenticated subject, the capability, the outcome and the latency. An IAM role is one subject for every agent that assumes it, so the subject has to come from a user identity to be a person.
-
A partner's agent needs three of these tools. They have no AWS account.
-
mcp-cognito-oauth-inboundThe inbound method is a policy, not server code, so a route can authenticate against Amazon Cognito, ten other named providers, or any OIDC provider. Exactly one such policy per project.
-
Each API behind this server needs its own credential. Do the agents hold all of them?
-
mcp-token-exchange-inboundNo. The spec forbids passthrough with a MUST NOT. The inbound credential is stripped and an independent upstream credential is used per user or per gateway.
-
One agent's retry loop ate our Lambda concurrency for the afternoon.
-
rate-limit-inboundWith
rateLimitBy: "user"every tool call is counted against the authenticated subject rather than a shared egress IP, before the request reaches the function.
All of these attach to one MCP route's policies.inbound — the same policy engine on the way in and on the way out.
Common questions
Can Claude, ChatGPT or Cursor connect to an MCP server that requires SigV4?
Not directly. AWS says off-the-shelf MCP-compatible applications are unlikely to support its SigV4 transport, and that standard MCP clients do not know how to sign requests with AWS credentials. Its answer is mcp-proxy-for-aws: a local proxy, run as a command with uvx, that signs from your own AWS credentials for a client like Claude Desktop. It only helps a client that can launch a local command, so it does nothing for a hosted connector.
SigV4 vs OAuth for MCP — which should I use?
SigV4 when the caller is your own workload inside AWS, OAuth when the caller is a person or lives outside your account. AgentCore Runtime makes the choice explicit: a runtime accepts either IAM SigV4 or JWT bearer inbound auth, and not both simultaneously.
Does Bedrock AgentCore Gateway support SigV4 to any MCP server?
No, and this is the detail most write-ups miss. IAM outbound authorization requires that the target verify SigV4 itself. AWS lists AgentCore Gateway, AgentCore Runtime, API Gateway and Lambda function URLs as compatible, and states that services which do not natively verify signatures — Application Load Balancer or direct EC2 endpoints — are not. Use OAuth or an API key there.
Why do I get SignatureDoesNotMatch?
AWS recomputes the whole canonical request and compares. The signature covers the host header, every header you listed in SignedHeaders, and a SHA-256 of the body, and the credential scope pins the date, region and service. So the usual causes are the wrong signing service or region, a proxy that rewrites the body or a signed header, or temporary credentials sent without X-Amz-Security-Token. AWS advises against signing hop-by-hop headers for that reason.
What service name do I sign with?
The SigV4 signing name of whatever fronts the server, not the string "mcp". It is lambda for a Lambda function URL and bedrock-agentcore for AgentCore Runtime. The service name is one of the inputs to the signing key and part of the credential scope, so getting it wrong fails the signature comparison rather than the authorization check.
Is a Lambda function URL with AWS_IAM auth private?
It is authenticated, which is not the same thing. Lambda still generates a dedicated HTTPS endpoint at https://<url-id>.lambda-url.<region>.on.aws that any HTTP client can reach, and the only thing standing in front of it is IAM: since October 2025, invoking a new function URL requires both lambda:InvokeFunctionUrl and lambda:InvokeFunction. Treat the auth type as authentication, not as network isolation.
Can the MCP server tell who called it?
Yes. With the AWS_IAM auth type, Lambda populates requestContext.authorizer.iam on the event with userArn, callerId, principalOrgId and the caller's access key, so your handler reads the caller instead of validating a token.
Is there a token to cache or refresh?
There is no token. Because the body hash is part of the canonical request, each JSON-RPC message is signed on its own, and the signer reads whatever credentials the environment currently holds. That is the opposite trade from Google ID tokens, where caching the client rather than the token string is what keeps a long-lived process working.
One policy engine for APIs, AI, and MCP
Put your MCP servers behind a gateway that speaks every identity provider, filters tools per role, and logs every call.