gregorizeidler/porto-alegre-mcp-server-llm-bus
If you are the rightful owner of porto-alegre-mcp-server-llm-bus and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
MCP server with intelligent LLM agent for Porto Alegre's public transportation system, providing natural language query support and route planning.
🚌 Porto Alegre MCP Server LLM Bus
MCP server with intelligent LLM agent for Porto Alegre's public transportation system. Answers natural language questions, plans routes, searches stops and routes through Claude Desktop or any MCP-compatible client.
What is this? An AI-powered transportation assistant that understands Portuguese queries like "Quero ir da UFRGS pro Aeroporto" and provides intelligent route planning using Porto Alegre's real bus data.
✨ Features
🧠 Intelligent LLM Agent
- 🗣️ Natural Language: Understands queries like "I want to go from UFRGS to the Airport with at most 1 transfer"
- 🤖 Smart Planning: Planner system that decides which tools to use to answer your questions
- 💭 Contextual Memory: Remembers previous conversations and user preferences
- 🔍 Intelligent Validation: Automatically validates results with fallbacks when APIs fail
🚌 Transportation Features
Core MCP Tools:
- 🚌 List all bus stops in Porto Alegre with full details
- 🛣️ Browse available bus routes with comprehensive information
- 📍 Get detailed route information (stops, schedule, path coordinates)
- 📄 Pagination support for large datasets
- ⚡ Redis caching for improved performance
- 🌐 HTTP streaming server with stateless architecture
Intelligent Agent Features:
- 🗺️ Proximity Search: Find stops near locations ("stops within 500m of Farroupilha Park")
- 🔄 Basic Route Planning: Plans routes with transfers and time estimates
- 🔍 Semantic Search: Natural language queries for stops and routes
- 🔤 Data Enhancement: Normalizes stop names, removes duplicates, adds location aliases
🏗️ Robust Architecture
- ⚡ Redis cache for optimized performance
- 🌐 HTTP streaming server with stateless architecture
- 📄 Automatic pagination for large datasets
- 🔄 Graceful degradation when APIs fail
🚀 Quick Start
Environment Variables
Create a .env
file:
REDIS_URL=redis://localhost:6379
OPENAI_API_KEY=sk-your-openai-api-key-here
Get your OpenAI API key at: https://platform.openai.com/api-keys
💡 Quick Setup? Check out for detailed step-by-step instructions!
Using Docker (Recommended)
docker-compose up -d
Development Commands
pnpm install # Install dependencies
pnpm build # Compile TypeScript
pnpm start # Start server
pnpm test # Run MCP Inspector
pnpm lint # Check code
pnpm format # Format code
pnpm check # Lint & format check
pnpm check:fix # Auto-fix issues
🔧 Claude Desktop Integration
Add to your claude_desktop_config.json
:
{
"mcpServers": {
"porto-alegre-mcp-server-llm-bus": {
"command": "npx",
"args": ["mcp-remote", "http://localhost:3000/mcp"]
}
}
}
🛠️ Available MCP Tools
Tool | Description | Parameters |
---|---|---|
stops-fetcher | List bus stops with pagination | cursor (string, optional) |
routes-fetcher | List all routes with pagination | cursor (string, optional) |
route-details-fetcher | Details of a specific route | routeId (string, required) |
🤖 Agent Endpoint
POST /agent/chat
Chat with the agent in natural language:
curl -X POST http://localhost:3000/agent/chat \
-H "Content-Type: application/json" \
-d '{
"message": "I want to go from UFRGS to the Airport with at most 1 transfer",
"sessionId": "user-123"
}'
Supported query examples:
-
Route Planning:
- "I want to go from UFRGS to the Airport with at most 1 transfer"
- "How do I get from Downtown to Shopping avoiding transfers?"
-
Semantic Search:
- "Find routes that go to Centro"
- "Search for stops near UFRGS"
-
Proximity Search:
- "Which stops within 500m of Farroupilha Park have routes to Downtown?"
- "Stops near Redenção that go to UFRGS"
-
Route Information:
- "What's the complete route of this line?"
- "Route schedules on Sundays"
💬 Real Usage Examples
Example 1: Route Planning
User: "Quero ir da UFRGS para o Aeroporto com no máximo 1 baldeação"
Agent Response:
Para ir da UFRGS ao Aeroporto com no máximo 1 baldeação, o agente irá:
1. Buscar paradas próximas à UFRGS
2. Encontrar rotas que conectam à região do Aeroporto
3. Calcular opções de viagem considerando transferências
4. Apresentar as melhores rotas com tempos estimados
O resultado incluirá:
- Opções de rotas com detalhes de paradas
- Tempos estimados de viagem
- Informações sobre transferências necessárias
- Distância de caminhada até as paradas
🔄 Query Processing Flow
Detailed Sequence: Route Planning Query
sequenceDiagram
participant U as User
participant C as Claude Desktop
participant A as Agent
participant N as NLP Processor
participant PS as ProximitySearch
participant RP as RoutePlanning
participant T as MCP Tools
participant API as PoA API
participant R as Redis
U->>+C: "Quero ir da UFRGS ao Aeroporto"
C->>+A: Process Query
A->>+N: Extract Intent & Entities
N->>N: Identify: origin="UFRGS", destination="Aeroporto"
N-->>-A: Parsed Data
A->>+T: Get stops data
T->>+R: Check Cache
alt Cache Hit
R-->>T: Cached Stops
else Cache Miss
T->>+API: Fetch Stops
API-->>-T: Stops Data
T->>R: Cache Data
end
T-->>-A: All Stops Data
A->>+PS: Find stops near UFRGS & Airport
PS-->>-A: Nearby stops for both locations
A->>+RP: Plan routes with transfers
RP->>RP: Calculate: transfers, time, walking distance
RP-->>-A: Ranked route options
A-->>-C: Formatted Response with Routes
C-->>-U: Route Options with Details
Note over U,R: Now uses ProximitySearchService<br/>and RoutePlanningService
Data Flow Architecture
graph LR
A[Raw Query] --> B[Intent Classification]
B --> C[Entity Extraction]
C --> D[Context Enrichment]
D --> E[Action Planning]
E --> F{Tool Selection}
F -->|Geographic| G[stops-fetcher]
F -->|Route Info| H[routes-fetcher]
F -->|Details| I[route-details-fetcher]
G --> J[Cache Layer]
H --> J
I --> J
J --> K[Response Validation]
K --> L[Memory Update]
L --> M[Response Generation]
style A fill:#4fc3f7,stroke:#0277bd,stroke-width:2px,color:#000
style M fill:#66bb6a,stroke:#2e7d32,stroke-width:3px,color:#fff
style J fill:#f06292,stroke:#c2185b,stroke-width:2px,color:#fff
style F fill:#9575cd,stroke:#512da8,stroke-width:2px,color:#fff
style E fill:#ffb74d,stroke:#f57c00,stroke-width:2px,color:#000
Example 2: Proximity Search
User: "Quais paradas até 300m do Parque Farroupilha que vão para o Centro?"
Agent Response:
O agente irá:
1. Buscar todas as paradas de ônibus disponíveis
2. Filtrar paradas próximas ao Parque Farroupilha (até 300m)
3. Verificar quais rotas dessas paradas conectam ao Centro
4. Apresentar resultados organizados por distância
O resultado incluirá:
- Lista de paradas próximas com localização
- Rotas disponíveis de cada parada
- Distância da parada até o parque
- Informações de tempo de viagem estimado
Example 3: Route Information
User: "Qual o trajeto completo da linha específica?"
Agent Response:
O agente irá:
1. Identificar a rota solicitada pelo usuário
2. Buscar informações detalhadas da rota
3. Obter sequência de paradas e coordenadas
4. Compilar informações de horários e características
O resultado incluirá:
- Pontos de origem e destino da rota
- Lista completa de paradas na sequência
- Coordenadas do trajeto
- Informações básicas da rota
🏗️ Agent Architecture
System Overview
graph TB
A[User Query] --> B[NLP Processor]
B --> C{Query Type?}
C -->|Route Planning| D[Route Planner]
C -->|Stop Search| E[Stop Finder]
C -->|Semantic Search| F[Semantic Search]
C -->|General Info| G[Info Retriever]
D --> H[MCP Tools Layer]
E --> H
F --> H
G --> H
H --> I[stops-fetcher]
H --> J[routes-fetcher]
H --> K[route-details-fetcher]
I --> L[PoA Transport API]
J --> L
K --> L
L --> M[Redis Cache]
M --> N[Basic Validation]
N --> O[Memory Update]
O --> P[Agent Response]
style A fill:#4fc3f7,stroke:#0277bd,stroke-width:3px,color:#000
style P fill:#66bb6a,stroke:#2e7d32,stroke-width:3px,color:#fff
style L fill:#ffb74d,stroke:#f57c00,stroke-width:2px,color:#000
style M fill:#f06292,stroke:#c2185b,stroke-width:2px,color:#fff
style C fill:#9575cd,stroke:#512da8,stroke-width:2px,color:#fff
style H fill:#81c784,stroke:#388e3c,stroke-width:2px,color:#000
Agent Processing Flow
flowchart TD
A[Incoming Message] --> B[NLP Processing]
B --> C[Extract Intent & Entities]
C --> D[Load Memory Context]
D --> E{Planning Loop}
E --> F[Planner Decision]
F --> G[Select MCP Tool]
G --> H[Execute Tool Call]
H --> I[Validate Response]
I --> J{Valid?}
J -->|No| K[Fallback Strategy]
J -->|Yes| L[Update Memory]
K --> F
L --> M{Goal Satisfied?}
M -->|No| F
M -->|Yes| N[Generate Response]
N --> O[Final Output]
style A fill:#4fc3f7,stroke:#0277bd,stroke-width:2px,color:#000
style E fill:#ffeb3b,stroke:#f57f17,stroke-width:2px,color:#000
style I fill:#ba68c8,stroke:#7b1fa2,stroke-width:2px,color:#fff
style M fill:#66bb6a,stroke:#2e7d32,stroke-width:2px,color:#fff
style O fill:#4caf50,stroke:#1b5e20,stroke-width:3px,color:#fff
style J fill:#ff7043,stroke:#d84315,stroke-width:2px,color:#fff
MCP Integration Flow
sequenceDiagram
participant C as Claude Desktop
participant M as MCP Server
participant A as Agent
participant P as PoA API
participant R as Redis
C->>+M: Tool Call Request
M->>+A: Process with LLM Agent
A->>A: NLP + Planning
loop Planning Steps (max 3)
A->>+M: MCP Tool Call
M->>+R: Check Cache
alt Cache Hit
R-->>-M: Cached Data
else Cache Miss
M->>+P: API Request
P-->>-M: Response Data
M->>R: Update Cache
end
M-->>-A: Tool Response
A->>A: Validate & Plan Next
end
A-->>-M: Final Response
M-->>-C: Structured Result
Note over C,R: Enhanced with proximity search,<br/>route planning, and semantic search
Components:
- NaturalLanguageProcessor: Extracts intents and entities from queries
- Planner: Decides which MCP tools to use based on the goal
- Memory: Basic conversation context and preferences
- Validator: Simple data validation with warnings
- ProximitySearchService: Finds stops near locations
- RoutePlanningService: Plans routes with transfers
- SemanticSearchService: Natural language search for stops/routes
- DataEnhancementService: Cleans and normalizes data
🔄 Planning Loop
The agent follows this pseudocode:
// planner decides next action (MCP tool) based on user's goal
while (!done && steps < 3) {
const plan = planner.decide(goal, memory, lastResult);
const result = callMCPTool(plan.tool, plan.args); // stops/routes/route-details
const ok = validator.check(result); // types, ranges, fields
if (!ok) { fallbackOrFix(); }
updateMemory(result);
done = planner.isSatisfied(result, goal);
}
🎯 Advanced Features
🔍 Intelligent Tool Routing
- Understands natural language requests
- Automatically chooses the right tools
- Routes queries to appropriate services (proximity, route planning, semantic search)
📊 Route Planning Features
- 🔄 Transfer optimization
- ⏱️ Estimated travel times
- 🚶 Walking distance calculations
- 📊 Route confidence scoring
🔍 Search & Discovery
- 📍 Proximity-based stop search
- 🔍 Semantic route and stop search
- 🏷️ Location aliases and landmarks
- 📝 Normalized data with fuzzy matching
🔤 Data Enhancement (Implemented)
- ✅ Normalizes stop names
- ✅ Removes duplicate stops
- ✅ Adds location aliases
- ✅ Maps landmarks ("stop near Redenção")
🛡️ Graceful Degradation
- Uses cache data when API fails
- Explains limitations to users
- Suggests alternatives when possible
🚨 Troubleshooting
Common Issues
"OpenAI API Key missing"
- Get your API key: https://platform.openai.com/api-keys
- Set environment variable or create
.env
file
"Redis connection failed"
- Make sure Redis is running:
docker-compose ps
- Restart:
docker-compose restart redis
"Port 3000 already in use"
- Stop other services or change port in docker-compose.yml
Need Help?
Check for detailed setup instructions.
📋 Key Features Overview
Claude Desktop Integration
- MCP server running in Claude Desktop with natural language queries
- Seamless integration with existing MCP workflow
- Real-time transportation assistance
Agent Conversation Flow
- Natural language processing of transportation queries
- Multi-step planning and execution
- Context-aware responses with memory
MCP Tools Integration
- Three core tools: stops-fetcher, routes-fetcher, route-details-fetcher
- Pagination support for large datasets
- Caching layer for optimized performance
API Response Format
- Structured JSON responses from agent endpoint
- Rich metadata including processing time and confidence scores
- Support for both conversational and structured data formats
🔧 Technical Implementation
Data Structures
Route Data Schema
erDiagram
Route {
string id
string code
string name
}
Stop {
string code
string terminal
string latitude
string longitude
array routes
}
RouteDetails {
string id
string code
string name
array coordinates
}
Route ||--o{ Stop : serves
Route ||--|| RouteDetails : details
Basic Memory Structure
interface Memory {
conversation: Array<{
role: "user" | "assistant";
content: string;
timestamp: Date;
}>;
lastResults: Array<{
tool: MCPTool;
args: Record<string, any>;
result: any;
}>;
userPreferences: {
maxTransfers?: number;
accessibilityNeeds?: boolean;
};
}
Performance Architecture
Cache Strategy
- Redis caching for API responses
- TTL-based cache invalidation
- Automatic fallback to API on cache miss
- Performance optimized for repeated queries
Response Time Targets
Operation | Target | Optimization Strategy |
---|---|---|
Route Planning | <3s | Multi-step caching, parallel API calls |
Stop Search | <1s | Indexed search, proximity filtering |
Route Details | <2s | Route-specific caching, batch requests |
Request Processing Flow
graph TB
A[Client Request] --> B[Process Request]
B --> C{Cache Available?}
C -->|Yes| D[Return Cached]
C -->|No| E[Call PoA API]
E --> F{API Success?}
F -->|Yes| G[Cache & Return]
F -->|No| H[Return Error]
style A fill:#4fc3f7,stroke:#0277bd,stroke-width:2px,color:#000
style G fill:#66bb6a,stroke:#2e7d32,stroke-width:2px,color:#fff
style H fill:#f44336,stroke:#c62828,stroke-width:2px,color:#fff
style C fill:#9575cd,stroke:#512da8,stroke-width:2px,color:#fff
style F fill:#ff9800,stroke:#f57c00,stroke-width:2px,color:#fff
Error Handling & Resilience
Error Handling Flow
flowchart TD
A[API Request] --> B{PoA API}
B -->|Success| C[Return Data]
B -->|Timeout/Error| D{Cache Available?}
D -->|Yes| E[Return Cached Data + Warning]
D -->|No| F[Return Graceful Error]
style A fill:#4fc3f7,stroke:#0277bd,stroke-width:2px,color:#000
style C fill:#66bb6a,stroke:#2e7d32,stroke-width:2px,color:#fff
style E fill:#ff9800,stroke:#f57c00,stroke-width:2px,color:#fff
style F fill:#f44336,stroke:#c62828,stroke-width:2px,color:#fff
style B fill:#9575cd,stroke:#512da8,stroke-width:2px,color:#fff
style D fill:#81c784,stroke:#388e3c,stroke-width:2px,color:#000
Simple Validation
graph LR
A[API Response] --> B[Basic Validation]
B --> C{Valid Data?}
C -->|Yes| D[Accept & Process]
C -->|No| E[Log Warning & Continue]
style A fill:#4fc3f7,stroke:#0277bd,stroke-width:2px,color:#000
style D fill:#66bb6a,stroke:#2e7d32,stroke-width:2px,color:#fff
style E fill:#ff9800,stroke:#f57c00,stroke-width:2px,color:#fff
style C fill:#9575cd,stroke:#512da8,stroke-width:2px,color:#fff
style B fill:#81c784,stroke:#388e3c,stroke-width:2px,color:#000
System Health
Basic Health Check
graph TB
A[Health Endpoint] --> B{System Check}
B --> C[Redis Status]
B --> D[Basic Connectivity]
C --> E{Connected?}
D --> F{API Reachable?}
E -->|Yes| G[✅ Healthy]
E -->|No| H[⚠️ Cache Issues]
F -->|Yes| G
F -->|No| I[⚠️ API Issues]
style A fill:#e3f2fd,stroke:#1976d2,stroke-width:3px,color:#000
style G fill:#4caf50,stroke:#2e7d32,stroke-width:2px,color:#fff
style H fill:#ff9800,stroke:#f57c00,stroke-width:2px,color:#fff
style I fill:#f44336,stroke:#c62828,stroke-width:2px,color:#fff
style B fill:#2196f3,stroke:#1565c0,stroke-width:2px,color:#fff
Basic Metrics
// Simple metrics tracking
interface BasicMetrics {
requestCount: number;
errorCount: number;
cacheHits: number;
cacheMisses: number;
lastResponse: Date;
}
Simple Architecture
- Stateless HTTP server
- Redis caching for API responses
- Basic error handling and fallbacks
API Contracts
Agent Chat Endpoint
// POST /agent/chat
interface ChatRequest {
message: string; // Natural language query
sessionId: string; // User session identifier
preferences?: { // Optional user preferences
maxTransfers: number;
walkingDistance: number;
accessibilityNeeds: boolean;
};
context?: { // Optional context
currentLocation?: Location;
previousSearches?: string[];
};
}
interface ChatResponse {
response: string; // Natural language response
confidence: number; // 0-1 confidence score
metadata: {
processingTime: number; // ms
toolsUsed: string[]; // MCP tools called
cacheHits: number; // Cache efficiency
fallbacksTriggered: boolean;
};
data?: { // Structured data if applicable
routes?: Route[];
stops?: Stop[];
alerts?: Alert[];
};
}
MCP Tool Responses
interface StopsResponse {
stops: Stop[];
pagination: {
cursor: string | null;
hasMore: boolean;
total: number;
};
metadata: {
source: 'cache' | 'api';
freshness: number; // minutes since fetch
};
}
🤝 Contributing
- Fork the repository
- Create your feature branch
- Run
pnpm check
before committing - Open a Pull Request