
Connect Any MCP Client to Your Bedrock AgentCore Runtime hosted MCP Server
MCP servers hosted on Bedrock AgentCore Runtime require AWS IAM SigV4 signing, but MCP clients like Kiro IDE, Claude Desktop, Cursor, and Cline don't support it natively. This tutorial walks through setting up mcp-proxy-for-aws — a lightweight local bridge that handles SigV4 automatically. Covers three install options (pip, uvx, Docker), client-specific JSON configs and proxy tuning parameters.
You've deployed your MCP server to Amazon Bedrock AgentCore . It's running, it's scalable, and it's secured behind AWS IAM SigV4 authentication . Now you open Kiro IDE, point it at the endpoint, and... nothing. The client doesn't speak SigV4.
This is the "last mile" problem of managed MCP hosting. Model Context Protocol (MCP) clients communicate over stdio or plain HTTP. AgentCore Runtime endpoints demand signed requests. It's like having a perfectly good highway with a toll booth that only accepts a currency your car doesn't carry.
In this tutorial, you'll set up
mcp-proxy-for-aws — a lightweight local bridge that handles SigV4 signing transparently — and connect five popular MCP clients to your AgentCore-hosted server. By the end, you'll have Kiro IDE, Claude Desktop, Cursor, Cline, or any stdio-based client talking to your managed endpoint.Here's what we'll walk through:
- Build the embedded endpoint URL from your AgentCore Runtime ARN
- Install mcp-proxy-for-aws via pip, uvx, or Docker
- Configure your MCP client with the proxy and endpoint URL
- Tune and troubleshoot — optional parameters, programmatic Python access, and common fixes
Prerequisites
Before you start, make sure you have:
- Python 3.10+ installed
- AWS credentials configured via
aws configure, environment variables, or IAM Identity Center (aws sso login)
- An MCP server deployed to AgentCore — you'll need the Runtime ARN (if you haven't deployed one yet, follow the Deploy MCP servers in AgentCore Runtime guide first)
How AgentCore hosts MCP servers
Before diving into the client-side setup, it helps to understand what's happening on the server side. When you deploy an MCP server to AgentCore Runtime , the platform expects your server container to be available at
0.0.0.0:8000/mcp — the default path supported by most official MCP server SDKs. AgentCore supports both stateless and stateful streamable-HTTP MCP servers. Stateless mode ( stateless_http=True ) is the default and works for most use cases. Stateful mode enables multi-turn interactions like elicitation and sampling.The deployment workflow looks like this: you write a standard MCP server using the MCP Python SDK , test it locally, then deploy it with the AgentCore CLI (
agentcore deploy ). After deployment, you get a Runtime ARN — that's the piece you need for this tutorial.Python
from mcp.server.fastmcp import FastMCPmcp = FastMCP(host="0.0.0.0", stateless_http=True)@mcp.tool()def add_numbers(a: int, b: int) -> int:"""Add two numbers together"""return a + b@mcp.tool()def greet_user(name: str) -> str:"""Greet a user by name"""return f"Hello, {name}! Nice to meet you."if __name__ == "__main__":mcp.run(transport="streamable-http")
The
@mcp.tool() decorator turns plain Python functions into MCP tools. AgentCore handles the rest — packaging, scaling, endpoint management, and session routing. Think of it as the "Fargate for MCP servers": you hand it your code, and it handles the infrastructure.For the full walkthrough — including local testing, Cognito authentication setup, and the
agentcore deploy command — see Deploy MCP servers in AgentCore Runtime and the tutorial sample on GitHub .With your server deployed and a Runtime ARN in hand, let's connect a client to it.
How the proxy works
Think of
mcp-proxy-for-aws as a translator sitting between your MCP client and AgentCore. Your client speaks stdio. AgentCore speaks HTTPS with SigV4 signatures. The proxy speaks both.Plain text
┌──────────────────┐ stdio ┌─────────────────────┐ HTTPS + SigV4 ┌──────────────────────┐│ MCP Client │ ◄───────────────► │ mcp-proxy-for-aws │ ◄──────────────────► │ AgentCore Runtime ││ (Kiro, Claude, │ │ (local bridge) │ │ (your MCP server) ││ Cursor, Cline) │ └─────────────────────┘ └──────────────────────┘└──────────────────┘
It runs locally as a lightweight, client-side bridge — exactly the stdio interface your MCP client expects. Under the hood, it forwards every request to the AgentCore endpoint, automatically signs it with SigV4 using your local AWS credentials (from the AWS CLI, environment variables, or IAM roles), and passes the response back. Dynamic tool discovery, request routing, and error handling are all built in. You configure it once and forget about it.
- As a proxy — the stdio bridge described above, for connecting MCP clients like Kiro, Claude Desktop, and Cursor
- As a library — a Python import for programmatically connecting agent frameworks (Strands, LangChain, LlamaIndex) to IAM-secured MCP servers without the stdio layer
Step 1: Build the embedded endpoint URL from your Runtime ARN
Every AgentCore Runtime has an ARN like this:
Plain text
arn:aws:bedrock-agentcore:<REGION>:<ACCOUNT_ID>:runtime/<RUNTIME_NAME>
To call your MCP server, you need an embedded endpoint URL — a full HTTPS URL with the ARN URL-encoded and embedded in the path. You could do the encoding by hand, but it's error-prone — colons become
%3A , slashes become %2F , and one missed character means a cryptic 403. This script handles it for you:Python
#!/usr/bin/env python3"""Generate the AgentCore MCP endpoint URL from a Runtime ARN."""import sysfrom urllib.parse import quotedef build_endpoint_url(arn: str) -> str:"""URL-encode the ARN and construct the AgentCore endpoint URL."""arn = arn.strip()parts = arn.split(":")if len(parts) < 6 or not arn.startswith("arn:aws:bedrock-agentcore:"):raise ValueError(f"Invalid AgentCore Runtime ARN: {arn}")region = parts[3]encoded_arn = quote(arn, safe="")return (f"https://bedrock-agentcore.{region}.amazonaws.com"f"/runtimes/{encoded_arn}/invocations?qualifier=DEFAULT")if __name__ == "__main__":if len(sys.argv) != 2:print("Usage: python build_endpoint_url.py <RUNTIME_ARN>")sys.exit(1)url = build_endpoint_url(sys.argv[1])print(f"\nEndpoint URL:\n {url}")
Save it as
build_endpoint_url.py and run with your AgentCore Runtime ARN. Example:
Bash
python build_endpoint_url.py "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/myMCPServer-abc123"
You'll get output like:
Plain text
Endpoint URL:https://bedrock-agentcore.us-east-1.amazonaws.com/runtimes/arn%3Aaws%3Abedrock-agentcore%3Aus-east-1%3A123456789012%3Aruntime%2FmyMCPServer-abc123/invocations?qualifier=DEFAULT
Copy that embedded endpoint URL — you'll plug it into every client config in Step 3.
Step 2: Install mcp-proxy-for-aws
With your embedded endpoint URL ready, you need the proxy itself. There are three installation options — each with different trade-offs around setup effort, portability, and environment isolation. Pick whichever fits your workflow.
Option A: pip install
This is the most straightforward approach. Create a virtual environment to keep the proxy and its dependencies isolated from your system Python:
Bash
python -m venv .venvsource .venv/bin/activate # macOS/Linux# .venv\Scripts\activate # Windowspip install mcp-proxy-for-aws
Verify the installation succeeded:
Bash
mcp-proxy-for-aws --help
You should see the proxy's usage output listing all available parameters. If you get a
command not found error, make sure your virtualenv is activated.Now grab the absolute path to the binary — you'll need this for your client config:
Bash
which mcp-proxy-for-aws# Example output: /Users/you/project/.venv/bin/mcp-proxy-for-aws
This is important. MCP clients don't activate your virtualenv — they just run whatever command you give them. If you use a bare
mcp-proxy-for-aws without the full path, the client will fail with an ENOENT error because it can't find the binary. Think of it like giving someone directions to your house but leaving out the street name.When to choose this option: You want a stable, pinned version of the proxy. You're comfortable managing a virtualenv. You want the fastest startup time (no download on each run).
Option B: Use uvx (no install needed)
If you have uv installed,
uvx will download and run the proxy on the fly — no virtualenv, no pip install, no path issues:Bash
uvx mcp-proxy-for-aws@latest --help
The first run may take tens of seconds as
uvx downloads and caches the package and its dependencies. Subsequent runs start in seconds since everything is cached locally.You don't need to note any binary path with this approach. In your client config, you'll set
"command": "uvx" and pass "mcp-proxy-for-aws@latest" as the first argument. The client configs in Step 3 show exactly how.When to choose this option: You want zero setup. You don't want to manage virtualenvs. You're fine with
uvx handling dependency caching. You want the proxy to auto-update to the latest version on each run.Option C: Use Docker
If you prefer containers or need to run the proxy in an environment where installing Python packages isn't practical, pre-built images are published to the public AWS ECR registry:
Bash
docker pull public.ecr.aws/mcp-proxy-for-aws/mcp-proxy-for-aws:latest
You can also pin to a specific version:
Bash
docker pull public.ecr.aws/mcp-proxy-for-aws/mcp-proxy-for-aws:1.1.6
To verify the image works:
Bash
docker run --rm public.ecr.aws/mcp-proxy-for-aws/mcp-proxy-for-aws:latest --help
When using Docker in your MCP client config, you'll set
"command": "docker" and pass the run arguments including a volume mount for your AWS credentials. See the Docker setup examples in the README for full client configs.When to choose this option: You want full environment isolation. You're running in a CI/CD pipeline or a machine where you can't install Python packages. You want reproducible builds with pinned image versions.
Quick comparison
| pip install | uvx | Docker |
|---|---|---|---|
Setup effort | Create venv, pip install | Install uv once | Pull image |
Startup speed | Fastest (local binary) | Fast after first run | Moderate (container overhead) |
Auto-updates | No (pin with pip install mcp-proxy-for-aws==x.y.z ) | Yes ( @latest ) | No (pin with image tag) |
Path management | Need absolute path in config | No path needed | No path needed |
Environment isolation | Virtualenv | uvx cache | Full container |
Step 3: Configure your MCP client
Now for the part that ties everything together. Every MCP client uses a JSON config file to define which MCP servers it can talk to. The structure is the same across all clients — what changes is where the config file lives.
Understanding the config structure
Here's what each field in the config means:
JSON
{"mcpServers": {"agentcore-mcp-remote": { // A name you choose — shows up in the client's server list"command": "...", // The binary to run (absolute path, "uvx", or "docker")"args": ["<EMBEDDED_ENDPOINT_URL>", // The embedded endpoint URL from Step 1"--service", "bedrock-agentcore", // Tells the proxy which AWS service to sign for"--region", "<REGION>" // Your AWS region (e.g., "us-east-1")]}}}
The
--service bedrock-agentcore flag is critical. The proxy tries to auto-detect the service from the URL, but for AgentCore endpoints you should always set it explicitly — without it, SigV4 signing may target the wrong service and you'll get cryptic 403 errors.Placeholder reference
Replace these placeholders in whichever config you use:
Placeholder | Replace with | Example |
|---|---|---|
<EMBEDDED_ENDPOINT_URL> | The embedded endpoint URL you generated in Step 1 | https://bedrock-agentcore.us-east-1.amazonaws.com/runtimes/arn%3A.../invocations?qualifier=DEFAULT |
<REGION> | Your AWS region | us-east-1 |
/absolute/path/to/.venv/bin/mcp-proxy-for-aws | Output of which mcp-proxy-for-aws | /Users/you/project/.venv/bin/mcp-proxy-for-aws |
Each client below shows both the absolute path approach (Option A from Step 2) and the uvx approach (Option B). If you chose Docker (Option C), see the Docker setup examples in the README.
Kiro IDE
Config file:
.kiro/settings/mcp.json in your workspace root.This is a workspace-level config — it applies only to this project. If you want the server available across all projects, use the Kiro CLI config instead (see below). Kiro automatically detects changes to this file and reconnects MCP servers without a restart.
Using absolute path:
JSON
{"mcpServers": {"agentcore-mcp-remote": {"command": "/absolute/path/to/.venv/bin/mcp-proxy-for-aws","args": ["<EMBEDDED_ENDPOINT_URL>","--service", "bedrock-agentcore","--region", "<REGION>"]}}}
Using uvx:
JSON
{"mcpServers": {"agentcore-mcp-remote": {"command": "uvx","args": ["mcp-proxy-for-aws@latest","<EMBEDDED_ENDPOINT_URL>","--service", "bedrock-agentcore","--region", "<REGION>"]}}}
Kiro CLI
Config file:
~/.kiro/settings/mcp.json (user-level).This is a global config — the server is available across all your projects. Useful if you connect to the same AgentCore endpoint from multiple workspaces.
Using absolute path:
JSON
{"mcpServers": {"agentcore-mcp-remote": {"command": "/absolute/path/to/.venv/bin/mcp-proxy-for-aws","args": ["<EMBEDDED_ENDPOINT_URL>","--service", "bedrock-agentcore","--region", "<REGION>"]}}}
Using uvx:
JSON
{"mcpServers": {"agentcore-mcp-remote": {"command": "uvx","args": ["mcp-proxy-for-aws@latest","<EMBEDDED_ENDPOINT_URL>","--service", "bedrock-agentcore","--region", "<REGION>"]}}}
Claude Desktop
Config file:
~/Library/Application Support/Claude/claude_desktop_config.json (macOS). On Windows, it's at %APPDATA%\Claude\claude_desktop_config.json .If the file doesn't exist yet, create it. If it already has other MCP servers configured, add the
"agentcore-mcp-remote" entry inside the existing "mcpServers" object — don't overwrite the whole file.Using absolute path:
JSON
{"mcpServers": {"agentcore-mcp-remote": {"command": "/absolute/path/to/.venv/bin/mcp-proxy-for-aws","args": ["<EMBEDDED_ENDPOINT_URL>","--service", "bedrock-agentcore","--region", "<REGION>"]}}}
Using uvx:
JSON
{"mcpServers": {"agentcore-mcp-remote": {"command": "uvx","args": ["mcp-proxy-for-aws@latest","<EMBEDDED_ENDPOINT_URL>","--service", "bedrock-agentcore","--region", "<REGION>"]}}}
After saving, restart Claude Desktop for the changes to take effect.
Cursor
Config file:
.cursor/mcp.json in your project root.Like Kiro, this is a project-level config. Cursor picks up changes automatically — no restart needed.
Using absolute path:
JSON
{"mcpServers": {"agentcore-mcp-remote": {"command": "/absolute/path/to/.venv/bin/mcp-proxy-for-aws","args": ["<EMBEDDED_ENDPOINT_URL>","--service", "bedrock-agentcore","--region", "<REGION>"]}}}
Using uvx:
JSON
{"mcpServers": {"agentcore-mcp-remote": {"command": "uvx","args": ["mcp-proxy-for-aws@latest","<EMBEDDED_ENDPOINT_URL>","--service", "bedrock-agentcore","--region", "<REGION>"]}}}
Cline (VS Code Extension)
Config file:
cline_mcp_settings.json , or add via Cline's MCP server settings UI (gear icon → MCP Servers).The UI approach is easier if you're not sure where the config file lives — Cline will write it for you.
Using absolute path:
JSON
{"mcpServers": {"agentcore-mcp-remote": {"command": "/absolute/path/to/.venv/bin/mcp-proxy-for-aws","args": ["<EMBEDDED_ENDPOINT_URL>","--service", "bedrock-agentcore","--region", "<REGION>"]}}}
Using uvx:
JSON
{"mcpServers": {"agentcore-mcp-remote": {"command": "uvx","args": ["mcp-proxy-for-aws@latest","<EMBEDDED_ENDPOINT_URL>","--service", "bedrock-agentcore","--region", "<REGION>"]}}}
One gotcha with Cline: don't use the
--log-level argument. Cline monitors stderr for the word "error" (case-insensitive) and will flag normal log messages as failures. It's a known quirk.Verifying the connection
After saving your config, your MCP client should detect the new server and connect automatically (Claude Desktop requires a restart). You'll know it's working when you can see the tools from your AgentCore-hosted MCP server listed in the client's tool panel.
If the server doesn't appear or shows an error, check the Troubleshooting section below. The most common issues are an incorrect binary path (ENOENT), missing
--service flag, or expired AWS credentials.Quick reference: config file locations
Client | Config file path | Scope |
|---|---|---|
Kiro IDE | .kiro/settings/mcp.json | Workspace |
Kiro CLI | ~/.kiro/settings/mcp.json | Global (all projects) |
Claude Desktop (macOS) | ~/Library/Application Support/Claude/claude_desktop_config.json | Global |
Claude Desktop (Windows) | %APPDATA%\Claude\claude_desktop_config.json | Global |
Cursor | .cursor/mcp.json | Project |
Cline | cline_mcp_settings.json (or via UI) | Varies |
Troubleshooting
Even with a straightforward setup, a few issues come up regularly. Here's what to check.
ENOENT error
The MCP client can't find the
mcp-proxy-for-aws binary. This almost always means you used a bare command name instead of the full path.Fix: Run
which mcp-proxy-for-aws and use that absolute path in your config's "command" field. Or switch to the uvx approach, which doesn't have this problem.Authentication errors
The proxy tries to auto-detect the service from the URL, but sometimes this fails. Work through these in order:
- Verify
--serviceis explicitly set tobedrock-agentcorein your args — without it, SigV4 signing targets the wrong service and the request is rejected
- Confirm your credentials are valid:
aws sts get-caller-identity
- For IAM Identity Center (SSO) users, run
aws sso loginbefore starting the client
- For long-running sessions, consider using an AWS profile via
--profileor IAM Identity Center credentials
- The proxy auto-refreshes credentials on auth failure — re-authenticate and retry without restarting
Client hangs on tool calls
Some tools take a while, especially if they're hitting external APIs or processing large datasets. Use
--tool-timeout to set a maximum duration per tool call. When the timeout is exceeded, the proxy returns a graceful error to the agent instead of hanging indefinitely:JSON
"args": ["<EMBEDDED_ENDPOINT_URL>", "--tool-timeout", "60"]
Credential expiry during long sessions
The proxy detects auth failures and picks up refreshed credentials automatically on the next request. Just run
aws sso login (or refresh your credentials however you normally do) and retry. No client restart needed.Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article