DEV Community

Cover image for MCP + AWS AgentCore: Give Your AI Agent Real Tools in 60 Minutes
Jubin Soni
Jubin Soni Subscriber

Posted on

MCP + AWS AgentCore: Give Your AI Agent Real Tools in 60 Minutes

If you've been building with AI agents, you've probably hit the same wall I did: your agent needs to do things — query databases, call APIs, check systems — but wiring up each tool is a bespoke integration every time. The Model Context Protocol (MCP) solves this by giving agents a standard way to discover and invoke tools. Think of it as USB-C for AI tooling.

The problem? Most MCP tutorials stop at "run it locally with stdio." That's fine for solo dev work, but it falls apart the moment you need:

  • Multiple clients connecting to the same server
  • Auth, session isolation, and scaling
  • A deployment that doesn't die when your laptop sleeps

AWS Bedrock AgentCore Runtime changes the equation. You write an MCP server, hand it over, and AgentCore handles containerization, scaling, IAM auth, and session isolation — each user session runs in a dedicated microVM. No ECS clusters to configure. No load balancers to tune.

In this post, we'll build a practical MCP server from scratch, deploy it to AgentCore Runtime, and connect an AI agent to it. The whole thing takes about 30-60 minutes.


What We're Building

We'll create an MCP server that exposes infrastructure health tools — the kind of thing a DevOps agent would use to check system status, list recent deployments, and surface alerts. It's more interesting than a dice roller but simple enough to follow.

Here's the architecture:

architecture

Your agent connects via IAM auth → AgentCore discovers the tools → your server executes them → results stream back. You never manage servers, containers, or networking.


Prerequisites

Before we start, make sure you have:

  • Python 3.10+ and uv (or pip — but uv is faster)
  • AWS CLI configured with credentials that have Bedrock AgentCore permissions
  • Node.js 18+ (for the AgentCore CLI)
  • An AWS account with AgentCore access (there's a free tier)

Install the AgentCore tooling:

# AgentCore CLI
npm install -g @aws/agentcore

# AgentCore Python SDK
pip install bedrock-agentcore

# AgentCore Starter Toolkit (handles scaffolding + deployment)
pip install bedrock-agentcore-starter-toolkit
Enter fullscreen mode Exit fullscreen mode

Step 1: Build the MCP Server

Create your project structure:

mkdir infra-health-mcp && cd infra-health-mcp
uv init --bare
uv add mcp bedrock-agentcore
Enter fullscreen mode Exit fullscreen mode

Now create server.py. We'll use FastMCP, which gives us a decorator-based API for defining tools:

from mcp.server.fastmcp import FastMCP
from datetime import datetime, timedelta
import random

mcp = FastMCP("infra-health")


@mcp.tool()
def get_service_status(service_name: str) -> dict:
    """Check the health status of a deployed service.

    Args:
        service_name: Name of the service to check 
                      (e.g., 'api-gateway', 'auth-service', 'payments')
    """
    # In production, this would hit your monitoring API
    statuses = ["healthy", "healthy", "healthy", "degraded", "unhealthy"]
    uptime = round(random.uniform(95.0, 99.99), 2)

    return {
        "service": service_name,
        "status": random.choice(statuses),
        "uptime_percent": uptime,
        "last_checked": datetime.utcnow().isoformat(),
        "active_instances": random.randint(2, 10),
        "avg_latency_ms": round(random.uniform(12, 250), 1)
    }


@mcp.tool()
def list_recent_deployments(hours: int = 24) -> list[dict]:
    """List deployments that occurred in the last N hours.

    Args:
        hours: Number of hours to look back (default: 24)
    """
    services = ["api-gateway", "auth-service", "payments", 
                 "notification-svc", "user-profile"]
    deployers = ["ci-pipeline", "ci-pipeline", "hotfix-manual"]

    deployments = []
    for i in range(random.randint(1, 5)):
        deploy_time = datetime.utcnow() - timedelta(
            hours=random.randint(1, hours)
        )
        deployments.append({
            "service": random.choice(services),
            "version": f"v1.{random.randint(20,45)}.{random.randint(0,9)}",
            "deployed_at": deploy_time.isoformat(),
            "deployed_by": random.choice(deployers),
            "status": random.choice(["success", "success", "rolled_back"])
        })

    return sorted(deployments, key=lambda d: d["deployed_at"], reverse=True)


@mcp.tool()
def get_active_alerts(severity: str = "all") -> list[dict]:
    """Retrieve currently active infrastructure alerts.

    Args:
        severity: Filter by severity level - 
                  'critical', 'warning', 'info', or 'all'
    """
    alerts = [
        {
            "id": "ALT-1024",
            "severity": "warning",
            "message": "auth-service p99 latency above threshold (>500ms)",
            "triggered_at": (
                datetime.utcnow() - timedelta(minutes=23)
            ).isoformat(),
            "service": "auth-service"
        },
        {
            "id": "ALT-1025",
            "severity": "critical",
            "message": "payments service error rate at 2.3% (threshold: 1%)",
            "triggered_at": (
                datetime.utcnow() - timedelta(minutes=8)
            ).isoformat(),
            "service": "payments"
        },
        {
            "id": "ALT-1026",
            "severity": "info",
            "message": "Scheduled maintenance window in 4 hours",
            "triggered_at": (
                datetime.utcnow() - timedelta(hours=2)
            ).isoformat(),
            "service": "all"
        },
    ]

    if severity != "all":
        alerts = [a for a in alerts if a["severity"] == severity]

    return alerts


if __name__ == "__main__":
    mcp.run(transport="streamable-http")
Enter fullscreen mode Exit fullscreen mode

Key decisions here:

  • Each tool has a clear docstring with typed args — this is what the LLM sees when deciding which tool to call, so be descriptive
  • We're using streamable-http transport, which is what AgentCore Runtime expects
  • In production, you'd replace the mock data with calls to Datadog, CloudWatch, your deployment system, etc.

Step 2: Test Locally

Before deploying anything, make sure the server works:

# Start the server
uv run server.py
Enter fullscreen mode Exit fullscreen mode

In another terminal, test it with the MCP inspector or a quick curl:

# Using the MCP CLI inspector
npx @modelcontextprotocol/inspector http://localhost:8000/mcp
Enter fullscreen mode Exit fullscreen mode

You should see your three tools listed. Click through them, pass some args, verify the responses look right. Fix any issues now — it's much faster than debugging after deployment.


Step 3: Prepare for AgentCore Runtime

AgentCore Runtime needs your server wrapped with the BedrockAgentCoreApp. Update server.py by adding this at the top and modifying the entrypoint:

from bedrock_agentcore.runtime import BedrockAgentCoreApp

# ... (keep all your existing tool definitions) ...

# Replace the if __name__ block:
app = BedrockAgentCoreApp()

@app.entrypoint()
def handler(payload):
    return mcp.run(transport="streamable-http")

if __name__ == "__main__":
    app.run()
Enter fullscreen mode Exit fullscreen mode

Alternatively, use the AgentCore Starter Toolkit to scaffold the project structure automatically:

agentcore init --protocol mcp
Enter fullscreen mode Exit fullscreen mode

This generates the Dockerfile, IAM role config, and agentcore.json for you. Copy your server.py into the generated project and point the entrypoint to it.


Step 4: Deploy to AWS

This is the part that used to take hours of ECS/ECR/IAM wrangling. With the Starter Toolkit, it's two commands:

# Configure (generates IAM roles, ECR repo, build config)
agentcore configure

# Deploy (builds container via CodeBuild, pushes to ECR, 
# deploys to AgentCore Runtime)
agentcore deploy
Enter fullscreen mode Exit fullscreen mode

That's it. No Docker installed locally. No Terraform. CodeBuild handles the container image, and AgentCore Runtime manages the rest.

The output gives you a Runtime ARN — save this, you'll need it to connect your agent.


Step 5: Invoke Your Deployed Server

Test the deployed server using the AWS CLI:

aws bedrock-agent-runtime invoke-agent-runtime \
  --agent-runtime-arn "arn:aws:bedrock:us-east-1:123456789:agent-runtime/your-runtime-id" \
  --payload '{"jsonrpc":"2.0","method":"tools/list","id":1}' \
  --output text
Enter fullscreen mode Exit fullscreen mode

You should see your three tools returned. Now try calling one:

aws bedrock-agent-runtime invoke-agent-runtime \
  --agent-runtime-arn "arn:aws:bedrock:us-east-1:123456789:agent-runtime/your-runtime-id" \
  --payload '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"get_active_alerts","arguments":{"severity":"critical"}},"id":2}' \
  --output text
Enter fullscreen mode Exit fullscreen mode

Step 6: Connect an AI Agent

Now the fun part. Let's wire this up to a Strands agent that can use our infrastructure tools conversationally:

from strands import Agent
from strands.tools.mcp import MCPClient
from mcp.client.streamable_http import streamablehttp_client

# Connect to your deployed MCP server via IAM auth
mcp_client = MCPClient(
    lambda: streamablehttp_client(
        url="https://your-agentcore-endpoint/mcp",
        # IAM auth is handled automatically via your AWS credentials
    )
)

with mcp_client:
    agent = Agent(
        model="us.anthropic.claude-sonnet-4-20250514",
        tools=mcp_client.list_tools_sync(),
        system_prompt="""You are a DevOps assistant with access to 
        infrastructure health tools. When asked about system status, 
        check services, review recent deployments, and surface any 
        active alerts. Be concise and flag anything that needs 
        immediate attention."""
    )

    response = agent(
        "Give me a quick health check — any services having issues? "
        "And were there any recent deployments that might be related?"
    )
    print(response)
Enter fullscreen mode Exit fullscreen mode

The agent will automatically discover the tools, decide which ones to call, and synthesize the results into a coherent answer. You'll see it call get_active_alerts, then get_service_status for the flagged services, then list_recent_deployments to correlate — all without you writing any orchestration logic.


What AgentCore Gives You for Free

It's worth pausing to appreciate what you didn't have to build:

Concern Without AgentCore With AgentCore
Container infra ECR + ECS/EKS + ALB Handled
Session isolation Custom session management microVM per session
Auth OAuth setup, token management IAM SigV4 built in
Scaling Auto-scaling policies, metrics Automatic
Networking VPC, security groups, NAT Managed
Health checks Custom implementation Built in

You wrote a Python file with tool definitions. Everything else is infrastructure you didn't touch.


Production Considerations

Before going live with real data, a few things to think about:

Replace mock data with real integrations. The tool signatures stay the same — swap random.choice(statuses) with a call to your CloudWatch API, PagerDuty, or whatever you use.

Add error handling. MCP tools should return meaningful errors, not stack traces. Wrap your integrations in try/except and return structured error responses.

Think about tool granularity. Three focused tools is better than one "do everything" tool. The LLM needs clear, specific tool descriptions to make good decisions about what to call.

Stateful vs stateless. Our server is stateless (the default and recommended mode). If you need multi-turn interactions where the server asks the user for clarification mid-execution, look into AgentCore's stateful MCP support with elicitation and sampling.

Connect to AgentCore Gateway. If your agent needs tools from multiple MCP servers, the Gateway acts as a single entry point that discovers and routes to all of them. You can also use the Responses API with a Gateway ARN to get server-side tool execution — Bedrock handles the entire orchestration loop in a single API call.


Cleanup

When you're done experimenting:

agentcore destroy
Enter fullscreen mode Exit fullscreen mode

This tears down the Runtime, CodeBuild project, IAM roles, and ECR artifacts. You'll be prompted to confirm.


What's Next?

A few directions to take this further:

  • Add a Gateway to combine your MCP server with AWS's open-source MCP servers (S3, DynamoDB, CloudWatch, etc.) into a single agent toolkit
  • Try the AG-UI protocol alongside MCP — it standardizes how agents communicate with frontends, enabling streaming progress updates and interactive UIs

References:

GitHub logo strands-agents / sdk-python

A model-driven approach to building AI agents in just a few lines of code.

Strands Agents

A model-driven approach to building AI agents in just a few lines of code



GitHub commit activity
GitHub open issues
GitHub open pull requests
License
PyPI version
Python versions


Documentation
Samples
Python SDK
Tools
Agent Builder
MCP Server


Strands Agents is a simple yet powerful SDK that takes a model-driven approach to building and running AI agents. From simple conversational assistants to complex autonomous workflows, from local development to production deployment, Strands Agents scales with your needs.

Feature Overview

  • Lightweight & Flexible: Simple agent loop that just works and is fully customizable
  • Model Agnostic: Support for Amazon Bedrock, Anthropic, Gemini, LiteLLM, Llama, Ollama, OpenAI, Writer, and custom providers
  • Advanced Capabilities: Multi-agent systems, autonomous agents, and streaming support
  • Built-in MCP: Native support for Model Context Protocol (MCP) servers, enabling access to thousands of pre-built tools

Quick Start

# Install Strands Agents
pip install strands-agents strands-agents-tools
Enter fullscreen mode Exit fullscreen mode
from strands import Agent
from strands_tools import calculator
agent =
Enter fullscreen mode Exit fullscreen mode

Guidance for Deploying Model Context Protocol Servers on AWS

This Guidance demonstrates how to securely integrate Model Context Protocol (MCP) servers into AWS applications using containerized architecture.

favicon aws.amazon.com

Top comments (0)