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