A unified Model Context Protocol (MCP) server providing access to ScottyLabs's Projects for CMU Students services through FastMCP. This server combines multiple CMU-related services into a single, composable MCP interface.
This project provides MCP tools for:
- CMU Dining (Eats): Query dining locations, hours, menus, and real-time availability
 - CMU Maps: Search buildings, get directions, and calculate distances on campus
 
Built with FastMCP, this server uses a modular architecture that allows mounting multiple sub-services with namespace prefixes.
- Get all dining locations with details (cuisine, hours, location)
 - Search locations by name
 - Find locations currently open
 - Check locations open at specific times
 - Query locations by cuisine type
 - Get detailed hours and specials for specific locations
 - Real-time open/closed status
 - Online ordering availability indicators
 
- Search buildings and locations by name
 - Get paths between two locations
 - Calculate distances between locations
 - List possible location matches for queries
 
# Install dependencies
uv sync
# Activate virtual environment
source .venv/bin/activate# Install dependencies
poetry install
# Activate virtual environment
poetry shell# Build the Docker image
docker build -t mcp-server .
# Run the container
docker run -p 8000:8000 mcp-server
# Or use docker-compose (if you create a docker-compose.yml)
docker-compose upThe server runs on HTTP transport by default on 0.0.0.0:8001:
# Run as module
python -m mcp_server
# Or run directly
python src/mcp_server/__init__.pyEach service can also be run independently:
# Run only the dining service
python src/mcp_server/services/eats/app.py
# Run only the maps service
python src/mcp_server/services/maps/app.pyget_all_dining_locations(): List all CMU dining locationssearch_dining_locations(name_query): Search by nameget_locations_open_now(): Find currently open locationsget_locations_open_at_time(day, hour, minute): Check availability at specific timeget_location_hours(location_name): Get detailed info for a locationget_locations_by_cuisine(cuisine_query): Find locations by cuisine type
search_buildings(query): Search for buildings/locationsget_path(start_id, end_id): Get path between two locationslist_possible_locations(query): List location name matchesdistance_between(start_id, end_id): Calculate distance in meters
- Dining API: 
https://dining.apis.scottylabs.org - Maps API: 
https://rust.api.maps.scottylabs.org 
Endpoints are configured in:
src/mcp_server/services/eats/constants.pysrc/mcp_server/services/maps/app.py
The main server configuration is in src/mcp_server/__init__.py:
- Host: 
0.0.0.0 - Port: 
8000 - Transport: 
http(streamable HTTP transport) 
CORS (Cross-Origin Resource Sharing) is enabled by default in src/mcp_server/core/app.py:
- Allow Origins: 
*(all origins - adjust for production) - Allow Methods: All HTTP methods including OPTIONS
 - Allow Headers: All headers
 - Allow Credentials: Enabled
 
This configuration enables the server to handle OPTIONS preflight requests and accept requests from any origin. For production deployments, consider restricting allow_origins to specific domains.
The project uses a compositional architecture:
- Base App (
core/app.py): Defines the main FastMCP instance - Services (
services/): Individual MCP services with their own tools - Main Composition (
main.py): Mounts services with prefixes to avoid conflicts 
This allows:
- Independent development and testing of services
 - Namespace isolation via prefixes
 - Easy addition of new services
 - Running services independently or combined
 
- Create a new directory under 
src/mcp_server/services/ - Implement your service with FastMCP tools
 - Mount it in 
src/mcp_server/main.py: 
from mcp_server.services.your_service.app import mcp as your_mcp
main_mcp.mount(your_mcp, prefix="your_service")Core dependencies:
fastmcp>=2.12.3: MCP frameworkaiohttp>=3.12.15: Async HTTP clienthttpx: HTTP client for async requestspydantic: Data validation and models
concept_id: Unique identifiername: Location nameshort_description: Brief descriptiondescription: Full descriptionlocation: Physical location on campusaccepts_online_orders: Online ordering availabilityurl: Location websitemenu_url: Menu linkcurrent_status: Open/closed status
day: Day of week (0=Sunday, 6=Saturday)start_hour: Opening hour (24-hour format)start_minute: Opening minuteend_hour: Closing hourend_minute: Closing minute
All dining tools return formatted Markdown with:
- Status indicators (=� open, =4 closed)
 - Online ordering indicators (=�)
 - Grouped by cuisine type
 - 12-hour time format
 - Consecutive day grouping for hours
 
AI Team at ScottyLabs
Current version: 0.1.0