I've tried the AWS MCP Server
A journey through the evolution of AI-Infrastructure integration
👋 Hi, I’m @hpfpv ☁️ I’m a Cloud Infrastructure Architect | 8x AWS Certified 🚀 I build secure, scalable, and automated solutions on AWS using Terraform, CloudFormation, and CI/CD 📚 Always exploring hybrid cloud, serverless, and AI-driven architectures
Hi guys!
So years ago, GenAI was emerging and I gave a presentation about how to apply Generative AI to everyday business processes. The goal was simple: showcase what was possible with services like Amazon Bedrock and demonstrate how AI could transform how we work.
One scenario stuck with people:
Mr. Nobody wants to talk to his AWS resources.
He speaks; a bot listens; it pulls context from the environment and, when asked, takes action.
Back then, that was more vision than product. Amazon Q was still young and couldn’t reach into the console the way we wanted. If you needed an assistant for AWS infrastructure, you had to build your own.
Fast-forward to today: Amazon Q can now provide details about your resources right inside the console. The thing that felt “impossible” turned into a menu option. So why bother building your own at all?
Because the path from proof-of-concept to production reality teaches you when to build, when to buy, and how the underlying architecture is changing.
Goals & Constraints
For this scenario, my goals were simple:
Make an application that will work simpler with AI
Boost day-to-day productivity
Plug in enterprise context (AWS resources across multiple accounts)
Keep the overall infrastructure fast and cheap enough to matter
At that time, building a custom solution was the only way to explore this possibility. I knew I needed:
An LLM to understand natural language requests (Claude with Amazon Bedrock)
Custom tools to interact with AWS services/resources
An agent to orchestrate everything together
The plan on paper looked clean:
User → Agent → Custom Tools → AWS APIs → Answer/Action
I followed the standard pattern for AI agents at the time (at least to my knowledge then). I built custom Python functions to serve as tools for the agent:
def search_ec2_instances_by_tag(tag_key):
"""Custom tool to search EC2 instances by tag"""
ec2 = boto3.client('ec2')
response = ec2.describe_instances(
Filters=[{'Name': f'tag:{tag_key}', 'Values': ['*']}]
)
# Process and return results...
def start_ec2_instance(instance_id):
"""Custom tool to start an EC2 instance"""
ec2 = boto3.client('ec2')
response = ec2.start_instances(InstanceIds=[instance_id])
# Handle response...
Each tool required careful implementation, error handling, and testing. The LangChain integration looked like this:
tools = [
Tool(
name="search_ec2_instances_by_tag",
func=search_ec2_instances_by_tag,
description="Lists EC2 instances by tag key"
),
Tool(
name="start_ec2_instance",
func=start_ec2_instance,
description="Starts an EC2 instance"
)
# ... more custom tools
]
agent = initialize_agent(
tools,
llm,
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
memory=memory,
verbose=True
)
The tradeoffs
This approach worked but it came with significant challenges:
Every new AWS action was another tool to build, test, and document.
The wrappers had to keep up with AWS API changes.
Capability matched my free time, not business demand.
I was basically shipping a tiny, bespoke AWS CLI.
Great for a talk and demos. Less great for production and scale.
From Custom Tools to MCP
While Q matured inside the console, the Model Context Protocol (MCP) landed with a different promise: standardize how AI apps talk to tools and data. No more bespoke plumbing for every integration. Just a protocol and servers that expose capabilities in a consistent way.
AWS Labs shipped two official MCP servers I cared about:
aws-api: access to AWS operations
aws-docs: fast, contextual access to AWS documentation
The architecture simplified overnight:

My code shrank while the surface area grew.
class SimpleAgent:
"""Simplified agent that directly uses Bedrock and MCP servers."""
def __init__(self, app_config, mcp_client, aws_session=None):
self.app_config = app_config
self.mcp_client = mcp_client
self.aws_session = aws_session or boto3.Session()
self.bedrock_client = None
self.conversation_history = []
self._initialized = False
self._last_tool_calls = []
async def _analyze_intent(self, user_message: str) -> Dict[str, Any]:
"""Analyze user intent and determine what tools to use."""
...
# Get available tools
available_tools = self.mcp_client.get_available_tools()
tools_description = self._format_tools_for_prompt(available_tools)
# Create intent analysis prompt with improved context awareness
...
What changed for me
Fewer moving parts. I dropped a lot of LangChain-specific orchestration and custom wrappers.
First-class AWS. Instead of my custom EC2 functions, I now have access to the full AWS CLI through the
aws-apiserverBuilt-in documentation. The
aws-docsserver provides something I never implemented in my custom solution: intelligent documentation access.
When Custom Still Wins
Q is excellent when you live inside the console. But custom assistants still win when you need:
Cross-tool workflows. AWS + Jira + GitHub + PagerDuty in one thread.
Multi-cloud or on-prem bridges. Q won’t run your GCP/Azure/VMware playbooks.
Custom guardrails. Your change windows, naming rules, org policy, and hand-offs.
Deep domain context. Proprietary docs, acronyms, runbooks, and tribal knowledge.
In other words: when your workflow isn’t just “ask AWS something,” custom still pays off.
Key Takeaways
Building this custom AWS assistant taught me several lessons that I think will remain relevant for a long time (I know, AI is moving fast…):
Standards > Snowflakes. MCP changed the shape of the problem. I write less glue and deliver more capability.
Build → Buy → Blend. Building teaches you enough to know what to buy later and eventually what to keep custom.
Reduce learning debt. The value of the proof-of-concept wasn’t the code; it was the intuition about where agents help and where they get in the way.
Conclusion
More than the result, the lesson was understanding how the GenAI technology stack keeps evolving. Whether you're using Amazon Q (or similar), building custom solutions, or exploring MCP servers, understanding these architectural patterns helps you make better decisions about when to build, when to buy, and when to migrate.
The Model Context Protocol represents the current state of this evolution: standardized ways to integrate AI with external systems that remain valuable even as managed services continue expanding their capabilities.
The complete implementation, including both the custom tool approach and the MCP-based solution, is available in my GitHub repository.

