Skip to content

ariosramirez/mcp-pycon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

18 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ MCP PyCon Demo: Bridging LLMs and Real-World APIs

Python 3.12+ FastAPI FastMCP AWS

A complete demonstration of the Model Context Protocol (MCP) showcasing how to securely bridge Large Language Models with real-world APIs.

🎯 The Challenge

When integrating LLMs with internal APIs, you face three critical problems:

  1. πŸŒ‰ The Language Barrier: LLMs speak natural language, APIs speak HTTP+JSON
  2. πŸ”’ The Security Dilemma: How to give LLMs API access without exposing credentials
  3. πŸŽͺ The Orchestration Burden: Where does the business logic live?

This demo solves all three elegantly using MCP.

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Usuario   │─────▢│      LLM    │─────▢│ MCP Server  │─────▢│  Task API   β”‚
β”‚  (EspaΓ±ol)  │◀─────│  (Reasoning)│◀─────│  (Bridge)   │◀─────│  (FastAPI)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚                      β”‚                    β”‚
                     Natural Language      API Key (Secure)      Stores in S3
                     Understanding         Translation Layer     JSON Files

Components

  • Task API (FastAPI): RESTful API for managing users, calls, and tasks
  • MCP Server (FastMCP): Secure bridge exposing API as LLM tools with modern Python decorators
  • Demo Client (Streamlit): Interactive web app showcasing the integration
  • S3 Storage: Simple, persistent data layer (LocalStack for local dev)

✨ Features

  • βœ… FastMCP Framework: Decorator-based MCP server with automatic schema generation
  • βœ… Secure Credential Isolation: API keys never exposed to LLM
  • βœ… Natural Language Interface: Spanish/English commands β†’ API calls
  • βœ… Multi-step Orchestration: Complex workflows handled intelligently
  • βœ… Complete CRUD Operations: Users, scheduled calls, and tasks
  • βœ… Production-Ready: FastAPI + AWS App Runner + S3
  • βœ… Interactive Demo: Streamlit web app with visual scenarios
  • βœ… MCP Inspector: Debug and test tools interactively
  • βœ… Docker Support: Full containerized deployment

πŸš€ Quick Start

Prerequisites

  • Python 3.12+
  • Docker & Docker Compose (for containerized setup)
  • GitHub API Key (for LLM features)
  • More details

Option 1: Docker Compose (Recommended)

# Clone repository
git clone https://github.com/ariosramirez/mcp-pycon.git
cd mcp-pycon

# Set GitHub API key for LLM features
export GITHUB_API_KEY=your-github-token-here

# Start all services
docker compose up -d

# View logs
docker compose logs -f

Services available at:

Option 2: Local Development

# Install dependencies
uv sync
# OR
pip install -e .

# Configure environment
cp .env.example .env
# Edit .env with your credentials:
# - TASK_API_KEY
# - GITHUB_API_KEY
# - AWS configuration (for LocalStack: AWS_ENDPOINT_URL=http://localhost:4566)

Start services in separate terminals:

# Terminal 1: Start Task API (with LocalStack)
cd task_api
docker compose up -d
# OR run directly
python -m task_api.main

# Terminal 2: Start MCP Server
python -m mcp_server.server

# Terminal 3: Start Streamlit Demo
streamlit run demo_client/streamlit_app.py

πŸ” MCP Inspector

Test and debug MCP tools interactively:

# Make sure Task API is running
npx @modelcontextprotocol/inspector fastmcp run mcp_server/server.py:mcp

Open http://localhost:5173 to:

  • View all available tools with schemas
  • Test tool calls with custom parameters
  • Inspect request/response payloads
  • Debug in real-time

Example: Test register_user tool

{
  "name": "Test User",
  "email": "test@example.com",
  "company": "Test Corp"
}

🎬 Demo Scenarios

The Streamlit demo showcases three scenarios demonstrating MCP's capabilities:

Scenario 1: Register & Schedule

"Por favor, registra a nuestro nuevo cliente 'Azollon International' con el contacto MarΓ­a GarcΓ­a (maria@test-azollon.com) y agΓ©ndale una llamada de onboarding para este viernes a las 10am."

Demonstrates: Multi-step orchestration, secure API calls

Scenario 2: Query & Update

"MuΓ©strame todas las llamadas pendientes y marca la primera como completada."

Demonstrates: Data retrieval, intelligent processing, updates

Scenario 3: Complex Workflow

"Crea una tarea de seguimiento para todos los clientes que tienen llamadas programadas esta semana."

Demonstrates: Complex reasoning, data aggregation, orchestration

πŸš€ Why FastMCP?

FastMCP reduces boilerplate by 60% compared to traditional MCP SDK:

Traditional MCP SDK:

@app.list_tools()
async def list_tools() -> list[Tool]:
    return [Tool(name="...", inputSchema={...})]  # Manual JSON schema

@app.call_tool()
async def call_tool(name: str, arguments: Any):
    if name == "register_user":  # Manual routing
        return [TextContent(type="text", text="...")]

FastMCP:

@mcp.tool
async def register_user(
    name: Annotated[str, "Full name of the user"],
    email: Annotated[str, "Email address"],
) -> str:
    """Register a new user."""
    return "βœ… User registered!"  # Auto-wrapped!

Benefits:

  • Automatic schema generation from type hints
  • Built-in parameter validation (Pydantic)
  • Type-safe with modern Python features
  • Cleaner error handling with ToolError

πŸ“š API Overview

Users

  • POST /users - Register user
  • GET /users - List all users
  • GET /users/{user_id} - Get user details

Scheduled Calls

  • POST /calls - Schedule call
  • GET /calls - List calls (filterable by user_id, status_filter)
  • PATCH /calls/{call_id}/status - Update status

Tasks

  • POST /tasks - Create task
  • GET /tasks - List tasks (filterable by user_id, status_filter)
  • PATCH /tasks/{task_id}/status - Update status

Authentication

All endpoints require X-API-Key header (except /health):

curl -X POST http://localhost:8000/users \
  -H "X-API-Key: demo-secret-key-change-in-production" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "MarΓ­a GarcΓ­a",
    "email": "maria@test-azollon.com",
    "company": "Azollon International"
  }'

Default key: demo-secret-key-change-in-production

πŸ§ͺ Testing

Quick Health Check

curl http://localhost:8000/health

Test with Python

import httpx

client = httpx.Client(
    base_url="http://localhost:8000",
    headers={"X-API-Key": "demo-secret-key-change-in-production"}
)

# Create user
response = client.post("/users", json={
    "name": "MarΓ­a GarcΓ­a",
    "email": "maria@test-azollon.com",
    "company": "Azollon International"
})
user = response.json()

# Schedule call
response = client.post("/calls", json={
    "user_id": user['id'],
    "title": "Onboarding Call",
    "scheduled_for": "2025-10-20T10:00:00Z",
    "duration_minutes": 30
})

πŸ”’ Security Best Practices

  1. API Key Isolation: Keys live ONLY in MCP Server environment, never exposed to LLM
  2. AWS Secrets Manager: Use for production credential management
  3. HTTPS/TLS: Always enable in production
  4. Key Rotation: Implement regular rotation policy
  5. Access Logging: Monitor all API calls and tool uses
  6. Least Privilege: Grant minimal S3 permissions

πŸ› οΈ Project Structure

mcp-pycon-demo/
β”œβ”€β”€ task_api/              # FastAPI application
β”‚   β”œβ”€β”€ main.py           # API endpoints
β”‚   β”œβ”€β”€ models.py         # Pydantic models
β”‚   β”œβ”€β”€ storage.py        # S3 storage layer
β”‚   β”œβ”€β”€ Dockerfile        # Container image
β”‚   └── README.md         # API documentation
β”œβ”€β”€ mcp_server/           # MCP Server
β”‚   β”œβ”€β”€ server.py         # FastMCP implementation
β”‚   └── README.md         # MCP server documentation
β”œβ”€β”€ demo_client/          # Streamlit Demo
β”‚   β”œβ”€β”€ streamlit_app.py  # Web UI
β”‚   β”œβ”€β”€ langgraph_agent.py # LLM agent with LangGraph
β”‚   └── azure_chat_wrapper.py # GitHub Models integration
β”œβ”€β”€ docker-compose.yml    # Container orchestration
β”œβ”€β”€ pyproject.toml        # Project metadata
└── README.md            # This file

βž• Adding New Tools

1. Add API Endpoint

In task_api/main.py:

@app.post("/your-endpoint")
async def your_endpoint(
    data: YourModel,
    api_key: str = Header(..., alias="X-API-Key")
):
    verify_api_key(api_key)
    return {"result": "success"}

2. Add MCP Tool

In mcp_server/server.py:

from typing import Annotated, Literal
from fastmcp.exceptions import ToolError
from pydantic import Field

@mcp.tool
async def your_new_tool(
    param: Annotated[str, "Parameter description"],
    count: Annotated[int, Field(ge=1, le=100)] = 10,
    status: Annotated[Literal["active", "inactive"] | None, "Filter"] = None
) -> str:
    """Tool description for LLM."""
    client = get_http_client()

    try:
        response = await client.post("/your-endpoint", json={"param": param})
        response.raise_for_status()
        return f"βœ… Success: {response.json()}"
    except httpx.HTTPStatusError as e:
        raise ToolError(f"Failed: {e.response.json().get('message')}")

FastMCP handles schema generation, validation, and error formatting automatically!

🐳 Docker Commands

# Start all services
docker compose up -d

# View logs (all)
docker compose logs -f

# View logs (specific service)
docker compose logs -f task-api

# Rebuild and restart
docker compose up -d --build

# Stop all services
docker compose down

# Stop and remove volumes
docker compose down -v

πŸ’‘ Use Cases

This architecture is ideal for:

  • Internal Tool Integration: Connect LLMs to company APIs securely
  • Multi-Service Orchestration: Coordinate multiple microservices
  • Agent Architectures: Build autonomous AI agents
  • Enterprise AI: Production-grade LLM applications
  • API Democratization: Natural language access to APIs

πŸ“– Resources

🎯 Challenge for Attendees

Want to extend the demo? Try the PyCon Challenge:

CHALLENGE.md - Step-by-step guide to add:

  • πŸ“Š Client Summary Tool (data aggregation)
  • πŸ“ User Info Prompt (template generation)
  • Complete with code, testing instructions, and troubleshooting

Time: 30-40 minutes | Difficulty: Intermediate

πŸ“ Documentation

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

πŸ“ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

  • Built for PyCon presentation
  • Powered by FastMCP framework
  • Anthropic's Model Context Protocol
  • FastAPI for the web framework
  • AWS for serverless infrastructure
  • GitHub Models for LLM access

Β‘Construyamos el futuro de la IA juntos! πŸš€

About

Tu Primer MCP: Creando Servidores de IA con Python y MCP CLI

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors