Show HN: AI-powered web service combining FastAPI, Pydantic-AI, and MCP servers
2 hours ago
1
A robust, scalable AI-powered web service combining FastAPI, Pydantic-AI, and MCP servers
This project demonstrates how to build a production-ready AI-powered web service by combining three cutting-edge, open-source technologies:
FastAPI for high-performance asynchronous APIs
Pydantic-AI for type-safe, schema-driven agent construction
Model Context Protocol (MCP) servers as plug-and-play tools
A quick glance at the UI: type a question, choose sources (Hacker News and/or Web Search), then get ranked trend cards with scores, links, and an AI-written summary—so you can quickly see what's trending about any topic or technology.
Advanced data modeling patterns with Pydantic
Multi-agent AI systems with A2A communication
MCP server integration for extensible AI tools
Production-ready FastAPI deployment patterns
Docker containerization for AI services
Type-safe AI agent development
flowchart TD
subgraph UI["🌐 Web UI + Docs"]
U["👤 User"] -->|HTTP| FA["🚀 FastAPI<br/>(app/main.py)"]
end
subgraph CORE["🎯 Orchestration"]
dummy[" "]:::hidden
FA --> AM["AgentManager"]
AM --> GA["🤖 GeneralAgent<br/>Classifier / Chat"]
AM --> EA["🤖 EntryAgent<br/>Tech Radar"]
AM --> SA["🤖 SpecialistAgent<br/>Repo Intel"]
GA -->|handoff| EA
EA <--> A2A["A2A Protocol"]
SA <--> A2A
end
subgraph TOOLS["🔌 Tooling"]
EA --> BS["🔍 Brave Search MCP<br/>(active)"]
EA --> HN["📰 Hacker News MCP<br/>(active)"]
SA --> GH["🐙 GitHub MCP<br/>(optional)"]
EA --> FS["📁 Filesystem MCP<br/>(optional)"]
SA --> FS
end
classDef agent fill:#ffffff,color:#111827,stroke:#60a5fa,stroke-width:2px,rx:10,ry:10
classDef svc fill:#f8fafc,color:#111827,stroke:#0288d1,stroke-width:2px,rx:10,ry:10
classDef toolActive fill:#ffffff,color:#111827,stroke:#16a34a,stroke-width:2px,rx:10,ry:10
classDef toolDisabled fill:#ffffff,color:#111827,stroke:#f59e0b,stroke-width:2px,rx:10,ry:10
classDef hidden fill:transparent,stroke:transparent
class EA,GA,SA agent
class FA,AM,A2A svc
class BS,HN toolActive
class GH toolDisabled
Loading
🚀 Quick Start (Docker - Recommended)
Docker and Docker Compose
OpenAI API key (required)
GitHub token (optional, for enhanced GitHub features)
git clone <your-repo-url>cd Tech_Trends_Agent
# Copy environment template
cp env.example .env
# Edit .env with your API keys
vi .env # or your preferred editor
Required environment variables:
OPENAI_API_KEY=your_openai_api_key_hereGITHUB_TOKEN=your_github_token_here# Optional but recommendedBRAVE_API_KEY=your_brave_api_key
# Start with Docker (recommended)
./docker-start.sh
# Or manually with docker-compose
docker-compose up --build -d
POST /api/v1/combined-analysisContent-Type: application/json
{
"query": "Python web frameworks 2024",
"auto_detect_repos": true,
"max_repos": 5,
"trend_limit": 15
}
🧠 Unified Assistant (Intent Routing)
POST /api/v1/assistantContent-Type: application/json
{
"input": "Where is Athens?",
"limit": 10,
"include_hn": true,
"include_brave": true
}
Response when routed to chat:
{
"route": "chat",
"data": { "response": "...", "message_type": "general", "timestamp": "..." },
"timestamp": "..."
}
Response when routed to trends:
{
"route": "trends",
"data": { "query": "...", "trends": [...], "summary": "...", "analysis_timestamp": "..." },
"timestamp": "..."
}
Other helpful endpoints:
GET /api/v1/agents/status
GET /api/v1/mcp/status
GET /api/v1/files
GET /api/v1/history, GET /api/v1/history/{id}
GET /health - Application health check
GET /api/v1/agents/status - Agent status information
GET /api/v1/mcp/status - MCP server status
Analyzes technology trends using Brave Search and Hacker News
Identifies emerging technologies and frameworks
Detects GitHub repositories mentioned in trends
Delegates repository analysis to Specialist Agent
Specialist Agent (Repo Intel)
Performs detailed GitHub repository analysis
Provides repository health metrics and insights
Correlates repository data with technology trends
Generates competitive analysis and recommendations
Agents communicate through Pydantic-AI's Agent-to-Agent (A2A) protocol:
Type-safe message passing
Correlation tracking
Error handling and retries
Model Context Protocol (MCP) servers provide standardized interfaces for AI tools:
Pluggable Architecture: Easy to add new capabilities
Type Safety: Schema-driven tool definitions
Scalability: Distributed tool execution
Security: Sandboxed tool execution
Top stories and trending content via MCP tools
Filtered by relevance and recency
Status: ✅ Active (see hackernews-mcp-custom)
Brave Search MCP (Active)
Brave Search API integration via MCP server
Structured results with relevance and quality scoring
Status: ✅ Active (see brave-search-mcp-custom)
GitHub MCP (Disabled by default)
Repository search and details
Status: ❌ Disabled by default; enable in docker-compose.yml and provide GITHUB_TOKEN
Filesystem MCP (Disabled)
Secure file operations
Read-only data access
Status: ❌ Disabled (local file listing is exposed via /api/v1/files instead)
Quick Start (Recommended)
# Start Tech Tracker with one command
./docker-start.sh
# Stop Tech Tracker
./docker-stop.sh
# Build and start
docker-compose up --build -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down
# Build production image
docker build -t tech-tracker:latest .# Run with production settings
docker run -d \
--name tech-tracker \
-p 8000:8000 \
-e OPENAI_API_KEY="your_key" \
-e ENVIRONMENT="production" \
tech-tracker:latest
Current Tooling Status (from code and compose)
Brave Search MCP: ✅ active on port 3001
Hacker News MCP: ✅ active on port 3003
GitHub MCP: ❌ disabled by default (uncomment in compose to enable)
Filesystem MCP: ❌ disabled by default
# Install development dependencies
pip install -e ".[dev]"# Run tests
pytest
# Run tests with coverage
pytest --cov=app --cov-report=html
# Type checking
mypy app/
Basic commands to format, lint, and scan the codebase:
Black (format)
Format repo: black .
Check only: black --check .
Ruff (lint + fixes)
Lint: ruff check .
Autofix: ruff check . --fix
Bandit (security scan)
Scan app code: bandit -r app
Output to file: bandit -r app -f txt -o bandit-report.txt
This project is licensed under the MIT License - see the LICENSE file for details.
This project was created as a demonstration for a PyCon tutorial:
"Building Robust AI Web Services with FastAPI, Pydantic-AI, and MCP Servers"
In this 60-minute tutorial, learn how to build a production-ready AI-powered web service that combines high-performance APIs, type-safe agent construction, and pluggable tool integration.
🔢 Understanding the Scoring System
The application uses dynamic scoring based on real data from active sources:
Web Search Results (1-100 Scale) - Active Scoring
Based on: Search relevance, domain authority, content match
Algorithm: Enhanced relevance calculation with quality bonuses
Location: app/agents/entry_agent.py:1614-1680
Factors: Title matches (25-35pts), URL matches (15pts), Quality domains (+25pts)
Hacker News Stories (1-100 Scale) - Live Weighted Scoring
Based on: HN points (50%) + Relevance (40%) + Recency (10%)
Algorithm: Weighted combination of multiple factors
Location: app/agents/entry_agent.py:1130-1164
Filters: Stories must be recent (within 60 days) and relevant
Repository Health (0.0-1.0 Scale) - Calculated from GitHub API
Based on: Stars (30%), Forks (20%), Activity (30%), Diversity (20%)
Algorithm: Normalized weighted scoring
Location: app/agents/specialist_agent.py:328-360
Real-time data from GitHub API (when available)
✅ Active Sources: Hacker News MCP, Brave Search MCP
⚠️ Fallback Mode: GitHub API (direct calls when MCP unavailable)
❌ Disabled: Filesystem MCP
Health Check: Visit /health endpoint to see real-time status
📊 Detailed System Architecture
Complete Request Flow (Assistant Route)
sequenceDiagram
participant U as User
participant UI as Frontend UI
participant FA as FastAPI Server
participant AM as Agent Manager
participant EA as Entry Agent<br/>(Tech Radar)
participant SA as Specialist Agent<br/>(Repo Intel)
participant A2A as A2A Protocol
participant BS as Brave Search MCP
participant HN as Hacker News MCP
participant GH as GitHub MCP (opt)
Note over U,GH: Complete Tech Trends Analysis Flow
U->>UI: Enter query "Docker development tools"
UI->>FA: POST /api/v1/assistant
FA->>AM: route_user_intent()
AM->>GA: process_request(message)
alt TECH
GA-->>AM: handoff payload
AM->>EA: process_request(query_data)
else GENERAL
GA-->>AM: direct answer
AM-->>FA: AssistantRouteResponse(route="chat")
FA-->>UI: Render chat
end
Note over EA,GH: Entry Agent Processing
EA->>EA: Classify query as tech-related
EA->>BS: Brave Search MCP call
BS-->>EA: Web search results (structured JSON)
EA->>HN: search_stories via MCP
HN-->>EA: HN stories (filtered and scored)
EA->>EA: Generate AI analysis summary
EA->>EA: Extract GitHub repositories
EA->>EA: Calculate confidence score
alt If repositories detected
EA->>A2A: delegate_to_specialist()
A2A->>SA: send_message(repo_analysis_request)
Note over SA,GH: Specialist Agent Processing
SA->>GH: get_repository/search (if enabled)
GH-->>SA: repo data
SA->>SA: Generate correlation analysis
SA->>SA: Calculate repo health scores
SA->>A2A: send_message(repo_analysis_response)
A2A-->>EA: Repository intelligence results
end
EA-->>AM: Complete trends analysis
AM-->>FA: Formatted response
FA-->>UI: TechTrendsResponse JSON
UI->>UI: renderMarkdown(summary)
UI->>UI: Display trend cards
UI-->>U: Results
Note over U,GH: General Chat Flow (Alternative)
U->>UI: "Where is Athens?"
UI->>FA: POST /api/v1/chat
FA->>EA: process_general_chat()
EA->>EA: Classify as general (non-tech)
EA->>EA: Generate direct AI response
EA-->>FA: General chat response
FA-->>UI: GeneralChatResponse
UI->>UI: renderMarkdown() for AI response
UI-->>U: Formatted chat response
Note over U,GH: Health Check & Status
UI->>FA: GET /health
FA->>AM: health_check()
AM->>HN: health_check() - ✅ Active
AM->>A2A: health_check()
AM-->>FA: System health status
FA-->>UI: HealthResponse
UI->>UI: Update status indicators
Loading
System Architecture & Data Flow
flowchart TD
%% User Interface Layer
U[👤 User] --> UI[🌐 Frontend UI<br/>Vanilla JS SPA]
UI --> |HTTP Requests| FA[🚀 FastAPI Server<br/>Port 8000]
%% API Layer
FA --> |Dependency Injection| AM[🎯 Agent Manager<br/>Orchestration Hub]
%% Agent Layer
AM --> EA[🤖 Entry Agent<br/>Tech Radar<br/>Pydantic AI]
AM --> SA[🤖 Specialist Agent<br/>Repo Intel<br/>Pydantic AI]
%% A2A Communication
EA <--> |Agent-to-Agent<br/>Messages| A2A[📡 A2A Protocol]
SA <--> A2A
%% Data Sources Layer
EA --> |MCP Active ✅| BS[🔍 Brave Search MCP]
EA --> |MCP Active ✅| HN[📰 Hacker News MCP]
SA --> |MCP opt ❌| GH[🐙 GitHub MCP]
AM --> |Local Files| FD[📁 Local Data Access<br/>JSON Files]
%% External APIs
BS --> |MCP Protocol| BE[🌐 Brave Search API]
HN --> |MCP Protocol| HE[📡 Hacker News API]
GH --> |REST API| GE[🐱 GitHub REST API]
%% Processing Flow
subgraph "🎨 Frontend Processing"
UI --> MD[📝 Markdown Renderer<br/>marked.js + Prism.js]
UI --> SC[⭐ Score Display<br/>Dynamic Scoring]
UI --> TC[🗂️ Trend Cards<br/>Interactive UI]
end
subgraph "🧠 AI Processing"
EA --> |System Prompt| EP[💭 Tech Analysis<br/>OpenAI GPT]
SA --> |System Prompt| SP[💭 Repo Intelligence<br/>OpenAI GPT]
EP --> |Generates| AS[📋 Analysis Summary<br/>Markdown Format]
SP --> |Generates| RI[📊 Repo Insights<br/>Correlation Scores]
end
subgraph "📊 Scoring System"
BS --> |Relevance + Quality| S1[⭐ Web Score<br/>1-100 Scale]
HN --> |HN Points + Recency| S2[⭐ HN Score<br/>Weighted Algorithm]
GH --> |Stars/Forks/Activity| S3[⭐ Repo Health<br/>0.0-1.0 Scale]
end
subgraph "🔧 Configuration"
CF[⚙️ Config Files<br/>.env<br/>settings.py]
CF --> AM
CF --> EA
CF --> SA
end
%% Status Indicators
HN -.-> |Status: Active ✅| ST1[Functional MCP]
BS -.-> |Status: Active ✅| ST2[Full MCP Server]
GH -.-> |Status: Fallback ⚠️| ST3[Demo Mode]
%% Styling
classDef userLayer fill:#e1f5fe,stroke:#01579b,stroke-width:2px,color:#000
classDef apiLayer fill:#f3e5f5,stroke:#4a148c,stroke-width:2px,color:#000
classDef agentLayer fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px,color:#000
classDef activeLayer fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#000
classDef fallbackLayer fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#000
classDef externalLayer fill:#fce4ec,stroke:#880e4f,stroke-width:2px,color:#000
classDef dataLayer fill:#f1f8e9,stroke:#33691e,stroke-width:2px,color:#000
class U,UI userLayer
class FA,AM apiLayer
class EA,SA,A2A agentLayer
class BS,ST1 activeLayer
class HN activeLayer
class GH,ST3 fallbackLayer
class BE,HE,GE externalLayer
class FD,CF,MD,SC,TC,EP,SP,AS,RI,S1,S2,S3 dataLayer
Loading
Key Architecture Components
🎯 Agent Manager (AgentManager)
Purpose: Central orchestration hub for all agents and services
Location: app/services/agent_manager.py
Responsibilities:
Initialize and manage agent lifecycle
Route requests to appropriate agents
Coordinate A2A communication
Manage MCP client connections
Health monitoring and error handling
🤖 Entry Agent (EntryAgent)
Purpose: Tech trend analysis and general AI assistance
Location: app/agents/entry_agent.py
Capabilities:
Brave Search MCP integration for web trends
Hacker News story fetching and analysis
GitHub repository detection from trends
General chat for non-tech queries
A2A delegation to Specialist Agent
🤖 Specialist Agent (SpecialistAgent)
Purpose: GitHub repository intelligence and analysis
What it is: A FastAPI service with a small web UI that analyzes tech trends and (optionally) related GitHub repositories using Pydantic-AI agents and MCP servers.
How it works:
Entry Agent: Searches the web via Brave Search MCP and filters recent Hacker News stories via the Hacker News MCP, then summarizes results and extracts mentioned repos.
Specialist Agent: Analyzes detected repositories. If the GitHub MCP server is enabled, it fetches repo data/metrics and produces correlation insights and recommendations.
Deployment: Docker Compose starts the app plus Brave Search and Hacker News MCP servers; GitHub/Filesystem MCP are disabled by default but can be enabled.
Extras: @filename.json syntax to inject local JSON into queries, structured logging, and a simple SPA for running analyses and viewing results.