When Anthropic published the Model Context Protocol (MCP), I immediately started experimenting with deployment options on AWS:
First, I tried running MCP servers as AWS Lambda functions. A great solution in terms of simplicity and cost, but it also meant I had to manually manage session state across invocations.
Next, I deployed them as containers on Amazon ECS, which immediately solved session state management for me, but I had to pay for a running server, even when it sat idle.
Then Amazon Bedrock AgentCore was released, which turned out to be exactly the solution I was looking for: A serverless runtime, automatically handling session state, while only charging for the actual processing time of MCP requests - the best of both worlds. And, as a native AWS service, it supports IAM, which perfectly fits into my existing stack.
But when I tried to actually connect an agent to a server, I ran into a wall:
No matter which agent framework I used, they all expected OAuth. This meant setting up a separate Cognito stack just to connect an agent to its tools. But I'd like to use IAM credentials like I do for everything else on AWS.
This is why I built the MCP client for IAM, a drop-in replacement that can be used with any Python framework using the official MCP SDK's streamablehttp_client.
No Cognito setup, no token management, no custom signing code. This client automatically signs MCP requests with your agent's existing AWS credentials.
In this post, I'll show you how to use it with popular AI agent frameworks like LangChain, Strands Agents, LlamaIndex, and Microsoft's Agent Framework.
What You Need to Get Started
The MCP client for IAM is open source and part of the official MCP Proxy for AWS. You can find it on GitHub and PyPI.
If you already have an MCP server with IAM auth on AWS, all you need is to install the package in your client:
pip install mcp-proxy-for-aws
That's it. Now you can replace MCP's default streamablehttp_client with the following import:
from mcp_proxy_for_aws.client import aws_iam_streamablehttp_client
If you don't have an MCP server on AWS yet, stay tuned. I'll post working end-to-end examples for both AgentCore Runtime and AgentCore Gateway soon.
Integration Patterns
Different frameworks manage MCP connections differently. The client supports two integration patterns to work with the following approaches:
Pattern 1: Client Factory Integration
Use with: Frameworks that accept a factory function returning an MCP client, like the Strands Agents SDK and Microsoft's Agent Framework. The aws_iam_streamablehttp_client is passed as a factory to the framework, which then handles the connection lifecycle internally.
Example - Strands Agents:
from mcp_proxy_for_aws.client import aws_iam_streamablehttp_client
mcp_client_factory = lambda: aws_iam_streamablehttp_client(
endpoint=mcp_url, # The URL of the MCP server
aws_region=region, # The region of the MCP server
aws_service=service # The underlying AWS service, e.g. "bedrock-agentcore"
)
with MCPClient(mcp_client_factory) as mcp_client:
mcp_tools = mcp_client.list_tools_sync()
agent = Agent(tools=mcp_tools, ...)
Example - Microsoft's Agent Framework:
from mcp_proxy_for_aws.client import aws_iam_streamablehttp_client
mcp_client_factory = lambda: aws_iam_streamablehttp_client(
endpoint=mcp_url, # The URL of the MCP server
aws_region=region, # The region of the MCP server
aws_service=service # The underlying AWS service, e.g. "bedrock-agentcore"
)
mcp_tools = MCPStreamableHTTPTool(name="MCP Tools", url=mcp_url)
mcp_tools.get_mcp_client = mcp_client_factory
async with mcp_tools:
agent = ChatAgent(tools=[mcp_tools], ...)
Pattern 2: Direct MCP Session Integration
Use with: Frameworks that require direct access to the MCP sessions, like LangChain and LlamaIndex. The aws_iam_streamablehttp_client provides the authenticated transport streams, which are then used to create an MCP ClientSession.
Example - LangChain:
from mcp_proxy_for_aws.client import aws_iam_streamablehttp_client
mcp_client = aws_iam_streamablehttp_client(
endpoint=mcp_url, # The URL of the MCP server
aws_region=region, # The region of the MCP server
aws_service=service # The underlying AWS service, e.g. "bedrock-agentcore"
)
async with mcp_client as (read, write, session_id_callback):
async with ClientSession(read, write) as session:
mcp_tools = await load_mcp_tools(session)
agent = create_langchain_agent(tools=mcp_tools, ...)
Example - LlamaIndex:
from mcp_proxy_for_aws.client import aws_iam_streamablehttp_client
mcp_client = aws_iam_streamablehttp_client(
endpoint=mcp_url, # The URL of the MCP server
aws_region=region, # The region of the MCP server
aws_service=service # The underlying AWS service, e.g. "bedrock-agentcore"
)
async with mcp_client as (read, write, session_id_callback):
async with ClientSession(read, write) as session:
mcp_tools = await McpToolSpec(client=session).to_tool_list_async()
agent = ReActAgent(tools=mcp_tools, ...)
Running Examples
Explore complete working examples for different frameworks in the GitHub repository.
Benefits of Using this Client
Simple local development:
Use your AWS CLI credentials directly. No Cognito setup, no token management, no separate auth infrastructure.
Standard AWS patterns:
Cross-account access via IAM role assumption works the same way it does for every other AWS service.
IAM-based access control:
Control which agents can connect to which MCP servers using IAM policies. No changes to server code required.
Universal compatibility across AWS:
The MCP client for IAM works with AgentCore Gateway, AgentCore Runtime, and any other AWS service exposing MCP over HTTPS with IAM authentication.
Next Steps
Check out the complete examples on GitHub for working code with a selection of frameworks.
Further resources:
Coming soon:
- An end-to-end tutorial: How to build and deploy MCP servers on AgentCore Runtime
- An end-to-end tutorial: How to turn existing APIs into MCP servers using AgentCore Gateway
What MCP servers are you planning to build? I'd love to hear about your use cases in the comments!
Top comments (4)
Wow, what an adventure! 😄 I love how you went from Lambda “fun-size deployments” to ECS “always-on-but-feels-like Netflix for servers” and finally landed in the Bedrock AgentCore sweet spot—serverless glory! Your journey reads like a mini AWS odyssey, and honestly, I felt the pain of session state management right alongside you.
I especially appreciate how you tackled the OAuth wall. I’ve hit that headache before—having to spin up Cognito just to let my agent say “hello” feels… dramatic. Your IAM-based client is such a sleek solution: plug-and-play, no extra tokens, no custom signing gymnastics. Pure elegance.
One thought I had—have you considered adding optional support for AWS STS (Security Token Service) session tokens? I know IAM roles are great for long-lived credentials, but some setups might prefer short-lived STS sessions for added security, especially if agents are deployed across multiple accounts. It could make the client even more versatile in enterprise environments.
I’m excited to see your end-to-end tutorials! I might even try converting a few internal APIs into MCP servers myself—finally, my rogue Python scripts might get some structure.
Thanks for sharing this; it’s a genuinely fun and practical dive into AWS + MCP that actually makes me want to experiment!
Thanks for the great feedback! And thanks for the idea with STS, I'll definitely need to think about that.
This is incredibly insightful! As someone currently building AI-driven SaaS systems and experimenting heavily with MCP-based workflows, the IAM-authenticated approach really caught my attention.
Most of my recent projects involve integrating AI agents into production-ready environments, and the OAuth overhead has definitely slowed things down — especially when trying to prototype fast for hackathons or ship features for my SaaS products. Seeing a clean IAM-based solution feels like a huge unlock for developers like me who already rely on AWS in almost every project.
Excited to try this out with LangChain and LlamaIndex in one of my upcoming AI automation tools. Thanks for sharing such practical, dev-friendly patterns!
Cool, I'm glad it's useful. Let me know how it works out!