Skip to main content
Glama
gayatrianne

langgraph-mcp-aws-dynamodb-agent

by gayatrianne
README.md
# LangGraph MCP AWS DynamoDB CRM Agent
### Galaxy Telecom — Standardised AI Tool Integration via Model Context Protocol

A production-grade AI agent demonstrating MCP (Model Context Protocol) integration
with AWS DynamoDB — connecting a LangGraph agent to live CRM data via a standardised
tool protocol rather than bespoke custom integrations.

šŸ“„ **[Portfolio Document (PDF)](Galaxy_Telecom_MCP_CRM_Agent.pdf)** — full write-up with architecture, AWS DynamoDB setup, and sample interactions

---

## Overview

Traditional AI agents that need CRM data require hardcoded integrations — custom
code for every external system, tightly coupled to the agent logic. This project
demonstrates a better approach: the agent connects to a Python MCP server at runtime,
discovers available tools dynamically, and calls them to retrieve live customer account
and ticket data from AWS DynamoDB — with zero hardcoded integration logic in the agent.

---

## What is MCP?

MCP (Model Context Protocol) is an open standard introduced by Anthropic that defines
how AI agents connect to external tools and data sources. It is to AI agents what
REST APIs are to web services — a universal contract enabling interoperability without
bespoke adapters for every integration.

The key capability is **runtime tool discovery**. The agent does not know which tools
exist at startup. It connects to the MCP server and asks "what can you do?" The server
responds with tool names, descriptions, and input schemas. The agent then decides which
tools to call based on the customer query.

---

## Architecture

```
Customer CLI Input
        │
        ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│   LangGraph Agent   │  ← ReAct pattern, Claude Haiku (Anthropic API)
│   (crm_agent.py)    │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
           │ MCP protocol — stdio transport
           │ Runtime tool discovery via get_tools()
           ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│    MCP Server       │  ← FastMCP, Python
│    (server.py)      │
│                     │
│  get_customer_      │  ← queries CustomerAccounts table
│  account()          │
│                     │
│  get_open_          │  ← queries SupportTickets table
│  tickets()          │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
           │ boto3
           ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│   AWS DynamoDB      │  ← eu-west-1
│                     │
│ GalaxyTelecom_      │
│ CustomerAccounts    │
│                     │
│ GalaxyTelecom_      │
│ SupportTickets      │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
```

---

## MCP Tool Definition

Tools are registered on the MCP server using the `@server.tool()` decorator.
The agent has no knowledge of these functions — it receives their definitions
dynamically via the protocol at runtime.

```python
@server.tool()
def get_customer_account(customer_id: str) -> str:
    """
    Retrieve a Galaxy Telecom customer account from DynamoDB.
    Returns account details including plan, status, and balance due.
    """
    ...

@server.tool()
def get_open_tickets(customer_id: str) -> str:
    """
    Retrieve all open support tickets for a Galaxy Telecom customer.
    Returns a list of tickets with issue type, description, status and priority.
    """
    ...
```

Replacing DynamoDB with Salesforce or Dynamics requires only a new MCP server
implementation. The agent code remains completely unchanged — demonstrating the
portability benefit of the protocol.

---

## AWS DynamoDB Tables

**GalaxyTelecom_CustomerAccounts**
- Partition key: `customer_id`
- Stores: name, email, plan, monthly charge, account status, balance due, member since

**GalaxyTelecom_SupportTickets**
- Partition key: `customer_id`, Sort key: `ticket_id`
- Stores: issue type, description, status, date raised, assigned team, priority
- Compound key enables fetching all tickets for a customer in one query

---

## Sample Interactions

**Overdue account with open tickets (C001)**
```
Customer ID : C001
Message     : Hi, I wanted to check on my account and see if there are any issues.

[MCP] Tools discovered: ['get_customer_account', 'get_open_tickets']

Response: Hi John, I can see your account is overdue with a balance of £47.50.
You have 2 open tickets — a billing query (T001, medium priority) and
broadband dropouts (T002, high priority, in progress with Technical Support)...
```

**Active account, existing technical ticket (C002)**
```
Customer ID : C002
Message     : I have been having some signal issues at home, can you help?

Response: Hello Sarah! I can see you're on our EliteMax plan with no balance due.
You've already raised ticket T003 regarding weak 5G signal — an engineer
visit has been requested, marked medium priority...
```

**Invalid customer ID — graceful error handling**
```
Customer ID : 99
Message     : I have been having some signal issues at home, can you help?

Response: I'm unable to locate a Galaxy Telecom account associated with
Customer ID 99. The ID may have been entered incorrectly...
```

---

## Tech Stack

| Component | Technology |
|---|---|
| Agent orchestration | LangGraph (ReAct pattern) |
| LLM framework | LangChain |
| LLM provider | Anthropic Claude Haiku API |
| MCP protocol | Model Context Protocol (FastMCP) |
| MCP adapter | langchain-mcp-adapters |
| CRM data store | AWS DynamoDB (eu-west-1) |
| AWS SDK | boto3 |
| Language | Python 3.11+ |

---

## Project Structure

```
langgraph-mcp-aws-dynamodb-agent/
ā”œā”€ā”€ agent/
│   ā”œā”€ā”€ __init__.py
│   └── crm_agent.py        # LangGraph ReAct agent — connects to MCP server
ā”œā”€ā”€ dynamo/
│   ā”œā”€ā”€ __init__.py
│   └── seed_data.py        # Creates DynamoDB tables and seeds mock CRM data
ā”œā”€ā”€ mcp_server/
│   ā”œā”€ā”€ __init__.py
│   └── server.py           # MCP server — exposes CRM tools backed by DynamoDB
ā”œā”€ā”€ main.py                 # Interactive CLI entry point
ā”œā”€ā”€ requirements.txt
ā”œā”€ā”€ .env.example            # Environment variable template
└── .gitignore
```

---

## Setup and Installation

### Prerequisites
- Python 3.11+
- Anthropic API key
- AWS account with CLI configured (`aws configure`)
- IAM user with DynamoDB read/write permissions

### Installation

```bash
# Clone the repository
git clone https://github.com/gayatrianne/langgraph-mcp-aws-dynamodb-agent.git
cd langgraph-mcp-aws-dynamodb-agent

# Create and activate virtual environment
python -m venv venv
venv\Scripts\activate        # Windows
source venv/bin/activate     # macOS/Linux

# Install dependencies
pip install -r requirements.txt

# Configure environment variables
cp .env.example .env
# Edit .env and add your Anthropic API key
```

### Environment Variables

```env
# Anthropic
ANTHROPIC_API_KEY=your_key_here

# AWS — credentials come from AWS CLI profile (aws configure)
AWS_REGION=eu-west-1

# DynamoDB table names
CUSTOMER_TABLE=GalaxyTelecom_CustomerAccounts
TICKETS_TABLE=GalaxyTelecom_SupportTickets

# LLM Configuration
CLAUDE_MODEL=claude-haiku-4-5-20251001
CLAUDE_TEMPERATURE=0.3
```

### Seed DynamoDB Tables

Run once before starting the agent:

```bash
python dynamo/seed_data.py
```

This creates both DynamoDB tables in eu-west-1 and seeds them with mock
Galaxy Telecom customer records and support tickets.

### Run

```bash
python main.py
```

Enter a customer ID (C001, C002, C003, C004) and a support message.
The agent will discover MCP tools, query DynamoDB, and return a
personalised response grounded in live CRM data.

---

## Key Design Decisions

**Runtime tool discovery via MCP**
The agent calls `await client.get_tools()` at runtime — it does not know
which tools exist until it asks the MCP server. This is the core protocol
benefit: the agent is decoupled from the implementation.

**Graceful error handling**
Invalid customer IDs return a structured error JSON from the MCP server.
The agent interprets this naturally and responds helpfully without
exposing technical details to the customer.

**MCP portability**
Replacing DynamoDB with Salesforce, Dynamics, or any other CRM requires
only a new MCP server implementation. The LangGraph agent code in
`crm_agent.py` remains completely unchanged — the agent is decoupled
from the data source by the protocol layer.

**AWS DynamoDB data model**
CustomerAccounts uses a single partition key (customer_id). SupportTickets
uses a compound key (customer_id + ticket_id) — enabling a single query
to return all tickets for a customer, mirroring real CRM data access patterns.

---

## Skills Demonstrated

- Model Context Protocol (MCP) — standardised AI tool integration
- Runtime tool discovery — agent discovers tools dynamically, no hardcoding
- LangGraph agent orchestration — ReAct pattern with external tool calling
- AWS DynamoDB — NoSQL CRM data store with partition and sort keys
- boto3 — AWS SDK for Python
- FastMCP — Python MCP server framework
- Graceful error handling — structured MCP error responses
- Externalised configuration — model and region via environment variables

---

## Author

**Gayatri Anne**
AI & Cloud Architect | 18+ Years Enterprise IT

I build AI-powered automation systems that eliminate manual work from
business processes, combining agentic workflows, large language models
and cloud integration to deliver production-ready solutions.

Certifications: Azure Solutions Architect Expert | Azure AI Engineer
Associate | Python PCAP | TOGAF Foundation

GitHub: [gayatrianne](https://github.com/gayatrianne)

Maintenance

ActivityMaintained
ResponsivenessNo issues