University Course Catalog MCP Server

University Course Catalog MCP Server

Provides LLM assistants with course search, prerequisite lookup, instructor information, and prerequisite graph tools backed by a SQLite database, enabling AI-powered academic advising.

Category
访问服务器

README

University Course Catalog MCP Server

A Model Context Protocol (MCP) server that exposes a university's course catalog to LLM assistants. It gives AI agents the ability to search courses, inspect prerequisites, build prerequisite dependency graphs, and look up instructors — backed by a local SQLite database and fully containerized with Docker.

This is the backend for an AI-powered academic advisor: a model can query the server in real time to help students plan schedules, understand course dependencies, and find the right instructor.


Features

  • MCP Tools — four validated, LLM-callable functions:
    • search_courses — keyword search across titles, descriptions and codes, optionally filtered by department code.
    • get_prerequisites — the direct prerequisites of a course.
    • lookup_instructor — instructor contact details by name.
    • get_prerequisite_graph — the full transitive prerequisite dependency graph (computed with NetworkX) as an adjacency list.
  • MCP Resources — contextual text bodies the model can load:
    • course_descriptions — a formatted list of every course and its description.
    • department_directory — the full department list with their codes.
  • MCP Prompt Templates:
    • course_comparison_template — a reusable template ({{course_code_1}}, {{course_code_2}}) that guides structured course comparisons.
  • Data integrity — every tool input/output is validated with Pydantic schemas; data access uses SQLAlchemy (an ORM, which prevents SQL injection).
  • Persistence — SQLite database stored in ./data/catalog.db, mounted as a volume.
  • Containerized — one command: docker compose up.

Project Structure

.
├── data/
│   ├── catalog.db            # Seeded SQLite database
│   └── seed_script/
│       └── seed.py           # Idempotent seeding script
├── src/
│   ├── __init__.py
│   ├── config.py             # Environment configuration
│   ├── database.py           # Engine + session helpers
│   ├── models.py             # SQLAlchemy ORM models
│   ├── schemas.py            # Pydantic validation contracts
│   ├── seed.py               # Shared seeding logic + seed data
│   ├── server.py             # MCP server: tools, resources, prompts
│   └── main.py               # Entry point (seeds + serves HTTP)
├── .env.example              # Documented environment variables
├── .gitignore
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── README.md

Quick Start with Docker (recommended)

Prerequisites: Docker with the Compose plugin.

# From the repository root
docker compose up --build

The service builds the image, maps port 8080, mounts ./data so the database persists, seeds the catalog on first start, and runs a health check.

To confirm the container is healthy:

docker compose ps

You should see mcp-server with a healthy status within about a minute.


Running Locally (without Docker)

Requires Python 3.11+.

# 1. Create and activate a virtual environment
python -m venv .venv
# Windows: .venv\Scripts\activate   |  macOS/Linux: source .venv/bin/activate

# 2. Install dependencies
pip install -r requirements.txt

# 3. (Optional) configure environment
# Copy .env.example to .env and adjust if needed.
# Default: DATABASE_URL=sqlite:///./data/catalog.db

# 4. Seed the database (idempotent — safe to run repeatedly)
python data/seed_script/seed.py

# 5. Start the server
python -m src.main

The server listens on http://localhost:8080.


Connecting an MCP Client

Point any MCP client at the Streamable HTTP endpoint:

http://localhost:8080/mcp

Example using the MCP Inspector:

npx @modelcontextprotocol/inspector
# URL: http://localhost:8080/mcp

You can also connect programmatically with the official mcp Python SDK:

import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

async def main():
    async with streamablehttp_client("http://localhost:8080/mcp") as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()
            result = await session.call_tool("get_prerequisites", {"course_code": "CS201"})
            print(result)

asyncio.run(main())

Tools

All tool inputs and outputs are validated with Pydantic. On unknown input the tools return a structured error, e.g. {"error": "Course not found"}.

search_courses

Searches the catalog by keyword (case-insensitive match against title, description and course code), optionally restricted to a department code.

Parameter Type Required Description
query string yes Keyword to search for.
department_code string no Restrict results to a department (e.g. CS).

Output (success):

[{ "course_code": "CS101", "title": "Introduction to Programming", "credits": 3 }]

Returns [] when nothing matches.

get_prerequisites

Returns the direct prerequisites of a course.

Parameter Type Required Description
course_code string yes E.g. CS201.

Output (success):

{
  "course_code": "CS201",
  "prerequisites": [
    { "course_code": "CS102", "title": "Data Structures and Algorithms" }
  ]
}

Empty list when the course has no prerequisites; {"error": "Course not found"} for an unknown code.

lookup_instructor

Finds an instructor by full or partial name.

Parameter Type Required Description
instructor_name string yes E.g. Grace Hopper.

Output (success):

{
  "name": "Dr. Grace Hopper",
  "email": "grace.hopper@university.edu",
  "department_name": "Computer Science"
}

{"error": "Instructor not found"} when no match exists.

get_prerequisite_graph

Returns the full prerequisite dependency graph for a course — the course itself plus every course in its transitive prerequisite chain — as an adjacency list. The graph is built with NetworkX (source is a prerequisite for target).

Parameter Type Required Description
course_code string yes E.g. CS401.

Output (success):

{
  "nodes": [{ "id": "CS401" }, { "id": "CS201" }, { "id": "CS102" }, { "id": "CS101" }],
  "edges": [
    { "source": "CS101", "target": "CS102" },
    { "source": "CS102", "target": "CS201" },
    { "source": "CS201", "target": "CS401" }
  ]
}

Resources

course_descriptions

catalog://course_descriptions — a single plain-text body listing every course:

[CS101] Introduction to Programming: A foundational course on programming principles...
[CS102] Data Structures and Algorithms: ...

department_directory

catalog://department_directory — a directory of all departments:

Computer Science (CS)
Mathematics (MATH)
Physics (PHYS)

Prompt Template

course_comparison_template

A reusable template that guides the model to produce a structured comparison of two courses:

Create a table comparing the following two courses: {{course_code_1}} and {{course_code_2}}. Include columns for Course Code, Title, Credits, Description, and Prerequisites. ...


Example Natural Language Queries

Once connected to an assistant, the model can answer questions like:

  • "Which courses are about machine learning?"
  • "What do I need to take before CS401, and is there a chain of prerequisites?"
  • "Does MATH101 have any prerequisites?"
  • "Who teaches Database Systems and what is their email?"
  • "Compare CS301 and CS401 side by side."
  • "List all courses offered by the Physics department."

The model resolves these by calling the tools above and reading the resources.


Database

SQLite file: ./data/catalog.db. Schema:

Table Columns
departments id (PK), name, code (UNIQUE)
instructors id (PK), name, email, office, department_id (FK)
courses id (PK), course_code (UNIQUE), title, description, credits, instructor_id (FK), department_id (FK)
prerequisites course_id (FK), prerequisite_id (FK) — many-to-many mapping

Seed data: 3 departments, 5 instructors, 10 courses (8 with prerequisites, including multi-level chains such as CS101 → CS102 → CS201 → CS401).

Re-seeding is automatic and idempotent — the server checks whether the catalog is empty before seeding, and the standalone script can be run anytime:

python data/seed_script/seed.py

Environment Variables

Variable Default Description
DATABASE_URL sqlite:///./data/catalog.db SQLite connection string (path inside container)
HOST 0.0.0.0 Interface the HTTP server binds to.
PORT 8080 Port the HTTP server listens on.
SERVER_NAME University Course Catalog MCP Server Name advertised during MCP initialize.

All variables are documented in .env.example.


Verification Checklist

  • [x] search_courses, get_prerequisites, lookup_instructor, get_prerequisite_graph tools
  • [x] course_descriptions, department_directory resources
  • [x] course_comparison_template prompt ({{course_code_1}}, {{course_code_2}})
  • [x] Pydantic-validated inputs/outputs and consistent {"error": ...} responses
  • [x] Seeded data/catalog.db with required schema
  • [x] Dockerfile, docker-compose.yml, .env.example, README.md

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选