University Course Catalog MCP Server
README.md
# University Course Catalog MCP Server
A production-grade [Model Context Protocol](https://modelcontextprotocol.io/) server that exposes a university course catalog through structured tools, resources, and prompt templates. Built with Python 3.12, FastAPI, SQLAlchemy 2.x, and the official MCP SDK.
## Project Overview
This MCP server provides intelligent access to a university course catalog with the following capabilities:
- **Full-text course search** with optional department filtering
- **Prerequisite dependency tracking** with cycle prevention
- **Instructor lookups** with contact information and department associations
- **Prerequisite graph analysis** for understanding course dependencies
- **Course catalog resource** with complete course descriptions
- **Department directory resource** for department information
- **Course comparison prompt template** for structured LLM analysis
The server is designed to work seamlessly with Claude, ChatGPT, and other LLM clients through the MCP protocol.
## Architecture
### Design Principles
- **Clean Separation of Concerns**: Service layer abstraction decouples MCP tools from database operations
- **Production Quality**: Full logging, error handling, type hints, and docstrings throughout
- **Scalability**: SessionLocal factory pattern for thread-safe database access
- **Maintainability**: Centralized configuration, structured schemas, and comprehensive tests
### Layer Structure
```
MCP Tools/Resources/Prompts (src/tools, src/resources, src/prompts)
↓
Pydantic Schemas (src/schemas) - Input/output validation
↓
Service Layer (src/services) - Business logic, database queries
↓
SQLAlchemy ORM (src/models) - Database mapping
↓
SQLite Database (data/catalog.db)
```
### Data Flow
1. **MCP Client** sends request with validated input
2. **Tool/Resource Handler** validates input via Pydantic schema
3. **Service Layer** queries database using SQLAlchemy 2.x with select()
4. **ORM** marshals database results to Python objects
5. **Response** returned as typed Pydantic model for JSON serialization
## Folder Structure
```
university-mcp-server/
├── src/
│ ├── config.py # Environment configuration (Pydantic BaseSettings)
│ ├── database.py # SQLAlchemy engine and SessionLocal
│ ├── mcp_app.py # Shared FastMCP instance
│ ├── server.py # FastAPI application with MCP transport mounting
│ ├── models/ # SQLAlchemy ORM models
│ │ ├── course.py
│ │ ├── department.py
│ │ ├── instructor.py
│ │ └── prerequisite.py
│ ├── schemas/ # Pydantic validation schemas
│ │ └── course.py
│ ├── services/ # Business logic and database queries
│ │ ├── course_service.py
│ │ ├── department_service.py
│ │ ├── graph_service.py
│ │ └── instructor_service.py
│ ├── tools/ # MCP tools (registered via @mcp.tool)
│ │ ├── search_courses.py
│ │ ├── get_prerequisites.py
│ │ ├── lookup_instructor.py
│ │ └── get_prerequisite_graph.py
│ ├── resources/ # MCP resources (registered via @mcp.resource)
│ │ ├── course_descriptions.py
│ │ └── department_directory.py
│ └── prompts/ # MCP prompts (registered via @mcp.prompt)
│ └── course_comparison.py
├── data/
│ ├── seed.py # Database seeding script
│ └── catalog.db # SQLite database (created at runtime)
├── tests/ # Pytest test suite
│ ├── conftest.py # Fixtures and test configuration
│ ├── test_mcp_app.py
│ ├── test_endpoints.py
│ ├── test_tools.py
│ ├── test_resources.py
│ └── test_prompts.py
├── Dockerfile # Container image definition
├── docker-compose.yml # Multi-container orchestration
├── .env.example # Environment variable template
├── requirements.txt # Python dependencies
├── pytest.ini # Pytest configuration
└── README.md # This file
```
## Installation
### Prerequisites
- Python 3.12+
- pip or conda package manager
- Docker and Docker Compose (optional, for containerized deployment)
### Local Setup
1. **Clone the repository**
```bash
cd university-mcp-server
```
2. **Create and activate virtual environment**
```bash
# Windows
python -m venv venv
.\venv\Scripts\Activate.ps1
# macOS/Linux
python3 -m venv venv
source venv/bin/activate
```
3. **Install dependencies**
```bash
pip install -r requirements.txt
```
4. **Initialize database**
```bash
# Windows
.\venv\Scripts\python.exe data/seed.py
# macOS/Linux
python data/seed.py
```
5. **Configure environment (optional)**
```bash
# Copy template and customize if needed
cp .env.example .env
```
### Docker Setup
1. **Build and start with Docker Compose**
```bash
docker-compose up --build
```
The container bootstraps the SQLite schema and seed data on startup, so a fresh checkout works without a prebuilt database file.
2. **Verify server is running**
```bash
curl http://localhost:8080/health
# Response: {"status": "healthy"}
```
3. **Stop the service**
```bash
docker-compose down
```
## Environment Variables
Configure via `.env` file (see `.env.example`):
| Variable | Default | Description |
|----------|---------|-------------|
| `DATABASE_URL` | `sqlite:///./data/catalog.db` | SQLAlchemy database connection string; supports sqlite, PostgreSQL, MySQL |
| `HOST` | `0.0.0.0` | Server binding address; use `127.0.0.1` for localhost-only |
| `PORT` | `8080` | Server port number (1-65535) |
### Docker Environment
Docker Compose automatically sets all environment variables. Override in `docker-compose.yml`:
```yaml
environment:
DATABASE_URL: sqlite:///./data/catalog.db
HOST: 0.0.0.0
PORT: 8080
```
## Running Locally
### Start the server
```bash
# Windows
.\venv\Scripts\python.exe -m src.server
# macOS/Linux
python -m src.server
```
Server will start on `http://0.0.0.0:8080` with logging output.
### Health check
```bash
curl http://localhost:8080/health
```
Expected response:
```json
{"status": "healthy"}
```
### Access MCP endpoints
- **HTTP (Streamable)**: `http://localhost:8080/mcp`
- **SSE (Server-Sent Events)**: `http://localhost:8080/sse`
- **SSE message endpoint**: `http://localhost:8080/sse/messages/`
## Docker Notes
- The image runs `create_db.py` and `data/seed.py` on startup before launching the API.
- The build excludes the local virtual environment and cache directories with `.dockerignore`.
- The container exposes port `8080` and uses the same `DATABASE_URL`, `HOST`, and `PORT` settings as local runs.
## Testing
Run the full pytest suite:
```bash
# All tests
pytest
# Verbose output
pytest -v
# Specific test file
pytest tests/test_tools.py
# Specific test class
pytest tests/test_tools.py::TestSearchCoursesTool
# With coverage
pip install pytest-cov
pytest --cov=src --cov-report=html
```
### Test Structure
- **test_mcp_app.py**: Startup smoke tests for FastAPI app composition and MCP registration (2 tests)
- **test_endpoints.py**: Health endpoint validation (3 tests)
- **test_tools.py**: MCP tool functionality (18 tests)
- search_courses: keyword search, filtering, no results, case insensitivity
- get_prerequisites: with/without prerequisites, error handling
- lookup_instructor: success, not found, whitespace handling
- get_prerequisite_graph: graph generation, structure validation
- **test_resources.py**: MCP resource generation (12 tests)
- course_descriptions: format, field inclusion, multiple courses
- department_directory: format, codes, alphabetical ordering
- **test_prompts.py**: Prompt template rendering (10 tests)
**Coverage**: 45 test cases covering app wiring, success paths, and failure paths.
## Available MCP Tools
### 1. search_courses
Search the university course catalog by keyword with optional department filtering.
**Input Schema**
```json
{
"query": "string (required, non-empty)",
"department_code": "string (optional, e.g., 'CS', 'AI')"
}
```
**Output Schema**
```json
{
"root": [
{
"course_code": "CS101",
"title": "Introduction to Computer Science",
"credits": 3
}
]
}
```
**Example Queries**
- "Find all programming courses"
- "Search for data science courses in the DS department"
- "What computer science courses are available?"
### 2. get_prerequisites
Retrieve all direct prerequisite courses for a given course code.
**Input Schema**
```json
{
"course_code": "string (required, e.g., 'CS201')"
}
```
**Output Schema**
```json
{
"course_code": "CS201",
"prerequisites": [
{
"course_code": "CS101",
"title": "Introduction to Computer Science"
}
]
}
```
**Example Queries**
- "What are the prerequisites for CS201?"
- "Can I take AI101 without any prerequisites?"
- "What courses do I need to complete before taking CS301?"
### 3. lookup_instructor
Find instructor contact information and department assignment.
**Input Schema**
```json
{
"instructor_name": "string (required, e.g., 'Dr. Alice Smith')"
}
```
**Output Schema**
```json
{
"name": "Dr. Alice Smith",
"email": "alice@university.edu",
"department_name": "Computer Science"
}
```
**Example Queries**
- "How can I contact Dr. Alice Smith?"
- "What department is Dr. Bob Johnson in?"
- "Find the email for Dr. Carol White"
### 4. get_prerequisite_graph
Build a complete prerequisite dependency graph for a course, showing all direct and transitive prerequisites.
**Input Schema**
```json
{
"course_code": "string (required, e.g., 'CS301')"
}
```
**Output Schema**
```json
{
"nodes": [
{"id": "CS101"},
{"id": "CS201"},
{"id": "CS301"}
],
"edges": [
{"source": "CS101", "target": "CS201"},
{"source": "CS201", "target": "CS301"}
]
}
```
**Example Queries**
- "Show me the prerequisite chain for CS301"
- "What's the full dependency graph for AI301?"
- "Create a graph of all prerequisites needed for DS301"
## Available MCP Resources
### course_descriptions
A comprehensive text resource listing all university courses with complete descriptions.
**URI**: `resource://course_descriptions`
**Format**
```
[CODE] Title
Credits: N
Description: ...
------------------------------------
```
**Example Response**
```
[CS101] Introduction to Computer Science
Credits: 3
Description: Fundamentals of programming and computational thinking
------------------------------------
[CS201] Data Structures and Algorithms
Credits: 4
Description: Advanced programming concepts and algorithm design
------------------------------------
```
### department_directory
A formatted text resource containing all university departments.
**URI**: `resource://department_directory`
**Format**
```
Name (Code)
Name (Code)
...
```
**Example Response**
```
Artificial Intelligence (AI)
Computer Science (CS)
Data Science (DS)
```
## Prompt Template
### course_comparison_template
A reusable prompt template for comparing two courses, useful for generating structured LLM analysis.
**Parameters**
- `course_code_1`: First course code (e.g., "CS101")
- `course_code_2`: Second course code (e.g., "CS201")
**Generated Prompt**
The template instructs the LLM to create a comparison table with:
- Course titles
- Credit hours
- Course descriptions
- Instructors
- Departments
- Prerequisites
- Recommendations for student types
**Example Usage**
```
Compare CS101 vs CS201 to understand which course would be better for a beginner programmer
```
## Example Natural Language Queries
### Course Discovery
- "What programming courses are available in the CS department?"
- "Find all courses about machine learning"
- "Show me the data science curriculum"
- "What courses can I take without prerequisites?"
### Prerequisite Planning
- "What do I need to take CS301?"
- "Show me the full prerequisite chain for AI301"
- "Can I take DS201 if I've completed CS101?"
- "Map out all the required courses for the AI track"
### Instructor Information
- "Who teaches CS201?"
- "How do I contact Dr. Alice Smith?"
- "What courses are taught by the Data Science department?"
- "Find all instructors in the Computer Science department"
### Course Comparison
- "Compare CS101 and CS201 to decide which to take"
- "What's the difference between AI101 and DS101?"
- "Should I take the AI course or the DS course?"
### Curriculum Planning
- "Create a 2-semester course plan for CS major"
- "What's the recommended order to take CS courses?"
- "Show me all prerequisites needed to take the advanced AI courses"
## Technology Stack
### Core Framework
- **FastAPI 0.139.0** - Async web framework for Python
- **Uvicorn** - ASGI server for FastAPI
### Database & ORM
- **SQLAlchemy 2.x** - Modern Python ORM with select() queries
- **SQLite** - Lightweight embedded database (default; easily swappable)
### MCP & LLM Integration
- **mcp 1.28.1** - Official Model Context Protocol SDK
- **Pydantic v2** - Data validation and serialization
### Utilities
- **httpx** - HTTP client for health checks
- **NetworkX 3.x** - Graph algorithms for prerequisite dependency analysis
### Development & Testing
- **pytest** - Testing framework
- **Docker & Docker Compose** - Containerization and orchestration
### Python Version
- **Python 3.12** - Latest stable Python version with improved performance
## Future Improvements
### Phase 2: Enhanced Features
- [ ] Course enrollment management (add/drop functionality)
- [ ] Student transcript tracking
- [ ] GPA calculation and academic standing
- [ ] Course schedule/timetable queries
- [ ] Room and building location resources
- [ ] Instructor office hours and availability
### Phase 3: Advanced Analytics
- [ ] Course recommendation engine based on student history
- [ ] Prerequisite conflict detection and resolution suggestions
- [ ] Workload analysis (credits per semester)
- [ ] Course difficulty ratings and student feedback
- [ ] Prerequisite weakness identification
### Phase 4: Integration & Deployment
- [ ] PostgreSQL support for production environments
- [ ] Authentication and authorization (OAuth2)
- [ ] Rate limiting and API key management
- [ ] WebSocket support for real-time updates
- [ ] Kubernetes deployment manifests
- [ ] AWS/Azure cloud deployment guides
### Phase 5: UX Improvements
- [ ] Multi-language support (Spanish, Chinese, etc.)
- [ ] Accessibility enhancements (screen reader optimization)
- [ ] Interactive prerequisite tree visualization
- [ ] Course planning calendar with drag-and-drop
- [ ] Mobile-friendly response formatting
## License
This project is provided as-is for educational and demonstration purposes. Modify and distribute freely with attribution.
---
**Questions or Issues?**
For bugs, feature requests, or questions, refer to the project documentation or contact the development team.
**Happy course planning! 🎓**
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues