Introduction
You have built an AI agent that works beautifully on your laptop. It calls tools, reasons through problems,
and returns exactly the answer your users need. There is just one problem: it lives on
localhost.
Moving from a local prototype to a production-grade, multi-tenant cloud service usually means weeks of infrastructure work — containers, load balancers, session isolation, authentication, observability. Amazon Bedrock AgentCore Runtime collapses that effort into a handful of commands while the Model Context Protocol (MCP) gives your agent a standard interface that any MCP-compatible client can discover and invoke.
In this post you will take a Python agent running in your IDE, transform it into an MCP server, and deploy it to AgentCore Runtime — with working code at every step.
What Is Amazon Bedrock AgentCore Runtime?
Amazon Bedrock AgentCore Runtime is a serverless hosting environment purpose-built for AI agents. It provides several capabilities that are hard to replicate on your own:
- Framework-agnostic — Works with Strands Agents, LangGraph, CrewAI, or any custom Python agent.
- Model flexibility — Use any LLM — Amazon Bedrock models, Anthropic Claude, Google Gemini, or OpenAI.
- Session isolation — Each user session runs in a dedicated microVM with isolated CPU, memory, and filesystem.
- Protocol support — Native support for Model Context Protocol (MCP) and Agent-to-Agent (A2A) communication.
- Extended execution — Synchronous requests get a 15-minute timeout; asynchronous sessions can run for up to 8 hours.
- Consumption-based pricing — You pay only for the compute your agent actually uses.
What Is MCP and Why Does It Matter?
The Model Context Protocol (MCP) is an open standard that defines how AI agents discover and invoke tools over HTTP. Think of it as a contract: an MCP server exposes tools with typed inputs and outputs, and any MCP client can discover those tools at runtime and call them without custom integration code.
- Stateless streamable-HTTP — AgentCore requires stateless servers. The platform automatically injects a
Mcp-Session-Idheader for session continuity. - Tool discovery — Clients call
list_tools()to discover every tool the server exposes. - Standard path — The server listens on
0.0.0.0:8000/mcp. - Interoperability — Any MCP client — Claude Code, Cursor, Kiro, Amazon Q CLI — can connect with zero custom wiring.
Architecture Overview
The diagram below shows the end-to-end flow — from your local IDE to a fully deployed MCP server on AgentCore Runtime.
LOCAL IDE TRANSFORMATION AGENTCORE RUNTIME INVOCATION
───────── ────────────── ───────────────── ──────────
┌─────────────────────┐ ┌──────────────────────┐ ┌──────────────────────────┐ ┌─────────────────────┐
│ MCP Server Code │ │ Install AgentCore │ │ agentcore configure │ │ Claude Code / │
│ my_mcp_server.py │ │ MCP Server in IDE │ │ --protocol MCP │ │ Cursor / Kiro │
│ │ │ │ │ │ │ │ │ │ │ │
│ ▼ │ │ ▼ │ │ ▼ │ │ ▼ │
│ Local Test │─────▶│ Transform Agent │─────▶│ agentcore launch │ │ ┌───────────────┐ │
│ localhost:8000/mcp │ │ + BedrockAgentCore │ │ Build + ECR + Deploy │ │ │ Agent Runtime │ │
│ │ │ App wrapper │ │ │ │ │ │ ARN │◀─┤
└─────────────────────┘ └──────────────────────┘ │ ▼ │ │ │ MicroVM │ │
│ ┌────────────────────┐ │ │ │ Isolation │ │
│ │ Agent Runtime ARN │ │ │ └───────────────┘ │
│ │ MicroVM Isolation │──┼─────▶│ Remote MCP Client │
│ │ Session Mgmt │ │ │ Python Script │
│ └────────────────────┘ │ │ MCP Inspector │
└──────────────────────────┘ └─────────────────────┘
Prerequisites
Before you start, make sure you have the following:
- An AWS account with Amazon Bedrock AgentCore permissions
- AWS CLI installed and configured
- Python 3.10+ (3.13 recommended)
- uv package manager (optional but recommended)
- An MCP client: Claude Code, Cursor, Kiro, or Amazon Q CLI
Install the core packages:
pip install mcp
pip install bedrock-agentcore
pip install bedrock-agentcore-starter-toolkit
Step 1: Build Your Local MCP Server
Start by creating a simple MCP server with a few tools. Create my_mcp_server.py:
# my_mcp_server.py
from mcp.server.fastmcp import FastMCP
from starlette.responses import JSONResponse
mcp = FastMCP(host="0.0.0.0", stateless_http=True)
@mcp.tool()
def summarise_architecture(service_name: str) -> str:
"""Summarise the high-level architecture of an AWS service."""
return (
f"The {service_name} architecture typically includes "
f"a control plane for management operations and a data plane "
f"for runtime request handling, with IAM for access control."
)
@mcp.tool()
def estimate_monthly_cost(
service: str, requests_per_month: int, avg_duration_ms: int
) -> str:
"""Estimate monthly cost for a serverless AWS service."""
cost_per_request = 0.0000002
cost_per_gb_second = 0.0000166667
memory_gb = 0.5
duration_seconds = avg_duration_ms / 1000
compute_cost = requests_per_month * duration_seconds * memory_gb * cost_per_gb_second
request_cost = requests_per_month * cost_per_request
total = compute_cost + request_cost
return f"Estimated monthly cost for {service}: ${total:,.2f}"
@mcp.tool()
def generate_iam_policy(actions: list[str], resource_arn: str) -> dict:
"""Generate a least-privilege IAM policy document."""
return {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": actions,
"Resource": resource_arn,
}
],
}
if __name__ == "__main__":
mcp.run(transport="streamable-http")
Test Locally
Start the server:
python my_mcp_server.py
From a separate terminal, run a test client:
# my_mcp_client.py
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def main():
mcp_url = "http://localhost:8000/mcp"
async with streamablehttp_client(
mcp_url, headers={}, timeout=120, terminate_on_close=False
) as (read_stream, write_stream, _):
async with ClientSession(read_stream, write_stream) as session:
await session.initialize()
tools = await session.list_tools()
print("Available tools:")
for tool in tools.tools:
print(f" - {tool.name}: {tool.description}")
result = await session.call_tool(
"estimate_monthly_cost",
{
"service": "AWS Lambda",
"requests_per_month": 1_000_000,
"avg_duration_ms": 200,
},
)
print(f"\nResult: {result.content[0].text}")
asyncio.run(main())
Step 2: Install the AgentCore MCP Server in Your IDE
Add the following to your MCP client configuration:
Claude Code (~/.claude/mcp.json)
{
"mcpServers": {
"bedrock-agentcore-mcp-server": {
"command": "uvx",
"args": [
"awslabs.amazon-bedrock-agentcore-mcp-server@latest"
],
"env": {
"FASTMCP_LOG_LEVEL": "ERROR"
}
}
}
}
Step 3: Transform Your Agent for AgentCore
If you are deploying an MCP server, the transformation is minimal — your FastMCP server already meets the protocol contract. However, for a general agent, wrap it with the AgentCore SDK:
1. Add the AgentCore import
from bedrock_agentcore.runtime import BedrockAgentCoreApp
2. Initialise the application
app = BedrockAgentCoreApp()
3. Decorate your entrypoint
@app.entrypoint
def handler(event, context):
user_prompt = event.get("prompt", "")
response = my_agent.run(user_prompt)
return {"result": response}
4. Add the runner
if __name__ == "__main__":
app.run()
Step 4: Deploy to AgentCore Runtime
Configure the deployment
agentcore configure -e my_mcp_server.py --protocol MCP
Launch
agentcore launch
Behind the scenes, this command:
- Builds an ARM64 Docker container with your server code
- Pushes the container image to Amazon ECR
- Creates an AgentCore Runtime resource
- Deploys your MCP server into an isolated microVM environment
On success, you receive an Agent Runtime ARN:
arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/my_mcp_server-abc123
Step 5: Invoke and Test Your Deployed MCP Server
# my_mcp_client_remote.py
import asyncio
import os
import sys
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def main():
agent_arn = os.getenv("AGENT_ARN")
bearer_token = os.getenv("BEARER_TOKEN")
encoded_arn = agent_arn.replace(":", "%3A").replace("/", "%2F")
mcp_url = (
f"https://bedrock-agentcore.us-west-2.amazonaws.com"
f"/runtimes/{encoded_arn}/invocations?qualifier=DEFAULT"
)
headers = {
"authorization": f"Bearer {bearer_token}",
"Content-Type": "application/json",
}
async with streamablehttp_client(
mcp_url, headers, timeout=120, terminate_on_close=False
) as (read_stream, write_stream, _):
async with ClientSession(read_stream, write_stream) as session:
await session.initialize()
tools = await session.list_tools()
print("Deployed tools:")
for tool in tools.tools:
print(f" - {tool.name}: {tool.description}")
result = await session.call_tool(
"generate_iam_policy",
{
"actions": ["s3:GetObject", "s3:PutObject"],
"resource_arn": "arn:aws:s3:::my-bucket/*",
},
)
print(f"\nGenerated policy:\n{result.content[0].text}")
asyncio.run(main())
What's Next?
- AgentCore Gateway — Connect your agent to external APIs with automatic tool discovery and OAuth.
- AgentCore Memory — Add persistent conversation context across sessions.
- AgentCore Identity — Integrate with Okta, Microsoft Entra ID, or Amazon Cognito.
- Agent-to-Agent (A2A) — Multi-agent collaboration using the A2A protocol.
- Observability — Built-in tracing via CloudWatch Transaction Search.
References
- Host agent or tools with Amazon Bedrock AgentCore Runtime — AWS Documentation
- Deploy MCP servers in AgentCore Runtime — AWS Documentation
- MCP protocol contract — AWS Documentation
- Amazon Bedrock AgentCore MCP Server: Vibe coding with your coding assistant — AWS Documentation
- Get started with AgentCore Runtime direct code deployment — AWS Documentation
- AgentCore MCP Server Tutorial — GitHub (awslabs)
- AWS Bedrock AgentCore MCP Server — Open Source MCP Servers for AWS
- Build long-running MCP servers on Amazon Bedrock AgentCore — AWS ML Blog
- MCP Specification: Transports — Model Context Protocol
- Amazon Bedrock AgentCore Python SDK — GitHub
- Amazon Bedrock AgentCore Starter Toolkit — GitHub