Querying DynamoDB with Natural Language Using MCP
DynamoDB is great, but writing queries can be painful. Wouldn’t it be nice if you could ask, "Show me all active users in my table" and get a structured response? That’s exactly what Model Context Protocol (MCP) enables. So, is Model Context Protocol an edible? Definitely no! MCP is a protocol for interacting with external data sources using natural language. Instead of manually constructing API requests, you describe what you need, and MCP does the heavy lifting. Think of it as a structured way for LLMs to query APIs, databases, and external services like GitHub, you can take a look at some popular servers here. From my perspective, we are witnessing a new revolution in protocols, as we have with WSDL and webservices, so we need to pay attention to them. How does this tick? I built a DynamoDB MCP Agent using mcp-server-aws and Agno MCP Tools. The idea is simple: User enters a natural language query like "Find all orders with status = 'pending'". The agent uses MCP to translate this into a DynamoDB query. Then, using Streamlit UI, results are returned in a structured format, making it easy to use. Breaking Down the Code xD Lifting the server MCP needs a backend server to handle requests. We use mcp-server-aws, which allows the agent to communicate with AWS services like DynamoDB. We define the server parameters so the MCP client can connect to it: server_params = StdioServerParameters( command="npx", args=["-y", "@modelcontextprotocol/server-aws"], ) command="npx" → Runs the MCP server using Node.js. args=["-y", "@modelcontextprotocol/server-aws"] → Installs and runs the AWS MCP server, which interfaces with DynamoDB. This server acts as a bridge between the agent and DynamoDB, allowing the agent to process natural language queries. MCP says: Oh hey Agno, let's connect... Agno provides an abstraction for building agents with tools like MCP, the Agno team rocks on being up-to-date async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: mcp_tools = MCPTools(session=session) await mcp_tools.initialize() stdio_client(server_params) → Starts the MCP server and establishes a connection. ClientSession(read, write) → Creates an MCP session, allowing requests to be sent and responses received. MCPTools(session=session) → Loads MCP tools, so we can make DynamoDB queries. Agent it's time to wake up Once MCP is set up, we create an agent to process natural language queries hehe agent = Agent( tools=[mcp_tools], instructions=dedent("""\ You are a DynamoDB assistant. Help users query their database. - Convert natural language to structured DynamoDB queries. - Return results in a readable format. - Provide useful insights when possible. """), markdown=True, show_tool_calls=True, ) tools=[mcp_tools]→ The agent is equipped with MCP tools to interact with DynamoDB. instructions → Defines the role of the agent (converting NL queries to DynamoDB operations). markdown=True → Ensures responses are formatted nicely. show_tool_calls=True → Shows internal query execution details. You can see agno documentation to go deeply on it ✨have a squiz in full code here✨

DynamoDB is great, but writing queries can be painful. Wouldn’t it be nice if you could ask, "Show me all active users in my table" and get a structured response? That’s exactly what Model Context Protocol (MCP) enables.
So, is Model Context Protocol an edible?
Definitely no!
MCP is a protocol for interacting with external data sources using natural language. Instead of manually constructing API requests, you describe what you need, and MCP does the heavy lifting. Think of it as a structured way for LLMs to query APIs, databases, and external services like GitHub, you can take a look at some popular servers here.
From my perspective, we are witnessing a new revolution in protocols, as we have with WSDL and webservices, so we need to pay attention to them.
How does this tick?
I built a DynamoDB MCP Agent using mcp-server-aws and Agno MCP Tools. The idea is simple:
User enters a natural language query like "Find all orders with status = 'pending'".
The agent uses MCP to translate this into a DynamoDB query. Then, using Streamlit UI, results are returned in a structured format, making it easy to use.
Breaking Down the Code xD
Lifting the server
MCP needs a backend server to handle requests. We use mcp-server-aws, which allows the agent to communicate with AWS services like DynamoDB.
We define the server parameters so the MCP client can connect to it:
server_params = StdioServerParameters(
command="npx",
args=["-y", "@modelcontextprotocol/server-aws"],
)
-
command="npx"
→ Runs the MCP server using Node.js. -
args=["-y", "@modelcontextprotocol/server-aws"]
→ Installs and runs the AWS MCP server, which interfaces with DynamoDB.
This server acts as a bridge between the agent and DynamoDB, allowing the agent to process natural language queries.
MCP says: Oh hey Agno, let's connect...
Agno provides an abstraction for building agents with tools like MCP, the Agno team rocks on being up-to-date
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
mcp_tools = MCPTools(session=session)
await mcp_tools.initialize()
-
stdio_client(server_params)
→ Starts the MCP server and establishes a connection. -
ClientSession(read, write)
→ Creates an MCP session, allowing requests to be sent and responses received. -
MCPTools(session=session)
→ Loads MCP tools, so we can make DynamoDB queries.
Agent it's time to wake up
Once MCP is set up, we create an agent to process natural language queries hehe
agent = Agent(
tools=[mcp_tools],
instructions=dedent("""\
You are a DynamoDB assistant. Help users query their database.
- Convert natural language to structured DynamoDB queries.
- Return results in a readable format.
- Provide useful insights when possible.
"""),
markdown=True,
show_tool_calls=True,
)
tools=[mcp_tools]
→ The agent is equipped with MCP tools to interact with DynamoDB.
instructions
→ Defines the role of the agent (converting NL queries to DynamoDB operations).
markdown
=True → Ensures responses are formatted nicely.
show_tool_calls
=True → Shows internal query execution details.
You can see agno documentation to go deeply on it