On this page
Authenticate an MCP server with AWS IAM (SigV4)
When your agent runs in AWS, it signs each request to the MCP server 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. Nothing mints a token: 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
- Specification
- Platform request signing rather than MCP authorization; the specification doesn't 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
- Your agent task or Lambda role
- AWS function URL or AgentCore
- MCP server reads the caller ARN
-
Nothing fetches a token. The signer derives the signature from role credentials already in the environment, so there is nothing to store and nothing to rotate.
Inside Your agent
Sign the canonical request SHA256 of the JSON-RPC body -
Your agent to AWS
POST /mcp (carries the credential) 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 must 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 your options are 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", word for word unchanged from the 2025-11-25 revision — so a signed request sits outside the OAuth profile rather than in conflict with it. The cost is reach: it works inside your own AWS account and nowhere else.
SigV4 answers one question: which IAM principal signed this request. The questions that follow are about callers with no IAM principal, and about what a principal can do once it is through the door.
- Step 1.
Add the second door
SigV4 stays exactly as it is for your own AWS workloads. The gateway is a second route, for the callers with no IAM principal to sign with — a browser, a chat client, someone else's agent.
"url": "https://
api. example. com/ mcp" - Step 2.
Add the policies
A list on the route, and the options that go with it. The gateway authenticates the caller its own way, then presents the upstream credential your server already expects.
"inbound": [ "mcp-cognito-oauth-inbound", "rate-limit-inbound", "mcp-token-exchange-inbound" ]
- Step 3.
Deploy
Nothing about your IAM policy, your function URL, or your signed workload path changes. The new route runs beside it.
zuplo deploy
-
Security wants to know which human was behind that role's tool call.
-
capability_invocationA shared role can't say — one ARN covers every agent that assumes it. On the gateway route, each tool call is logged against the authenticated subject, and a subject can be a person.
-
A partner's agent needs three of these tools. They have no AWS account.
-
mcp-cognito-oauth-inboundThey don't need one. The gateway route signs them in against Amazon Cognito — or ten other named providers, or any OIDC one — while your IAM path stays exactly as it is. One MCP OAuth policy per project.
-
Each API behind this server needs its own credential. Do the agents hold all of them?
-
mcp-token-exchange-inboundNo — the gateway holds them. Inbound credentials are stripped, and an independent upstream credential goes out instead, per user or shared gateway-wide. Passthrough is what the specification forbids with a MUST NOT.
-
One agent's retry loop ate our Lambda concurrency for the afternoon.
-
rate-limit-inboundCap it before it reaches the function: every tool call counts against the authenticated subject, not a shared egress IP, so one agent's loop burns its own budget and leaves the concurrency pool alone.
All of these attach to one MCP route's policies.inbound — the same policy engine on the way in and on the way out. Your MCP server keeps
the code and the authentication it has today.
Common questions
Can Claude, ChatGPT, or Cursor connect to an MCP server that requires SigV4?
Not directly. AWS says standard MCP clients don't know how to sign requests with AWS credentials, and that off-the-shelf MCP-compatible applications are unlikely to support its SigV4 transport. 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. That helps only a client that can launch a local command, so it does nothing for a hosted connector.
SigV4 or OAuth for MCP — which one do 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 at once.
Does Bedrock AgentCore Gateway support SigV4 to any MCP server?
No. 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 don't 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; the credential scope pins the date, the Region, and the 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 generates a dedicated HTTPS endpoint at https://URL_ID.lambda-url.REGION.on.aws that any HTTP client can reach, and the only thing 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. The body hash is part of the canonical request, so each JSON-RPC message is signed on its own from whatever credentials the environment 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.