Skip to main content
Glama
README.md
# iGuat-MCP

面向 **i桂航** 校园数据的只读 MCP(Model Context Protocol)服务。项目基于 Python、FastMCP 与 Streamable HTTP,将课表、班级和校区查询封装为可供 AI 客户端调用的标准工具。

> 本项目只提供查询能力,不会修改微信小程序或上游教务数据。

## 功能

- 获取完整学期列表、当前学期与下一学期
- 按专业、年级和班级关键字检索班级
- 查询指定班级、学期和周次的课表
- 查询指定人员的课表,并在返回前移除身份字段
- 根据专业信息推断所在校区
- 内置 TTL 课表缓存、并发限制与健康检查
- 使用 Bearer API Key 保护 MCP 与管理员接口
- 支持通过管理员接口热更新上游 token
- 支持 Docker、环境变量及 Docker Secrets 部署

## MCP 工具

| 工具 | 说明 |
| --- | --- |
| `get_xnxq` | 获取完整学期列表,包含当前及下一学期 |
| `get_current_term` | 获取当前学期 |
| `search_classes` | 按条件检索班级 |
| `get_class_schedule` | 获取指定班级、学期和周次的课表 |
| `get_ta_schedule` | 按姓名或学号查询课表,响应会移除身份字段 |
| `infer_major_campus` | 根据专业信息推断校区 |

## 技术栈

- Python 3.11+
- MCP / FastMCP
- HTTPX
- Uvicorn
- Pytest
- Docker

## 快速开始

### 本地运行

```bash
git clone https://github.com/Strayed2SE/iGuat-MCP.git
cd iGuat-MCP

python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install -e ".[test]"

cp .env.example .env
# 按下方说明配置环境变量后启动
python server.py
```

服务默认监听 `0.0.0.0:8000`:

- MCP:`http://127.0.0.1:8000/mcp`
- 健康检查:`http://127.0.0.1:8000/healthz`

MCP 客户端请求头:

```text
Authorization: Bearer <MCP_PUBLIC_API_KEY>
```

### Docker

```bash
docker build -t iguat-mcp .
docker run --rm -p 8000:8000 --env-file .env iguat-mcp
```

生产环境建议使用 `NAME_FILE` 形式从 Docker Secrets 或只读文件加载敏感配置:

```bash
docker run --rm -p 8000:8000 \
  -e IGUAT_USER_TOKEN_FILE=/run/secrets/iguat_token \
  -e IGUAT_MAIN_SIGN_KEY_FILE=/run/secrets/main_sign_key \
  -e MCP_PUBLIC_API_KEY_FILE=/run/secrets/public_key \
  -e MCP_ADMIN_API_KEY_FILE=/run/secrets/admin_key \
  --mount type=bind,src=/secure/secrets,dst=/run/secrets,ro \
  iguat-mcp
```

## 配置

复制 `.env.example`,按需设置:

| 变量 | 用途 |
| --- | --- |
| `IGUAT_USER_TOKEN` | 上游查询 token |
| `IGUAT_MAIN_SIGN_KEY` | 主接口签名密钥 |
| `IGUAT_CLASS_SIGN_KEY` | 班级接口签名密钥 |
| `IGUAT_CSM_SIGN_KEY` | CSM 接口签名密钥 |
| `IGUAT_ALUMNI_SIGN_KEY` | 校友接口签名密钥 |
| `IGUAT_SITE_SIGN_KEY` | 站点接口签名密钥 |
| `MCP_PUBLIC_API_KEY` | MCP 客户端访问密钥 |
| `MCP_ADMIN_API_KEY` | 管理接口访问密钥 |
| `MCP_HOST` / `MCP_PORT` | 服务监听地址与端口 |
| `MCP_CACHE_TTL` | 课表缓存秒数,设为 `0` 可关闭缓存 |
| `MCP_MAX_CONCURRENCY` | 最大并发数 |
| `MCP_MAX_MAJOR_CLASSES` | 专业班级查询上限 |
| `IGUAT_TRUST_ENV` | 是否读取系统代理和证书环境变量 |

## 更新上游 Token

当上游 token 失效时,管理员可在不重启服务的情况下更新内存中的 token:

```bash
curl -X PUT http://127.0.0.1:8000/admin/token \
  -H "Authorization: Bearer <MCP_ADMIN_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"token":"<NEW_TOKEN>"}'
```

## 测试

```bash
pip install -e ".[test]"
pytest -q
```

## 安全说明

- 不要把真实 token、签名密钥、API Key 或 `.env` 提交到仓库。
- 服务不会把 token、签名或个人身份字段返回给 MCP 客户端。
- 默认不读取系统代理环境;部署环境确有需要时再设置 `IGUAT_TRUST_ENV=1`。

## 关联项目

- [桂航百科查询系统](https://github.com/Strayed2SE/%E6%A1%82%E8%88%AA%E7%99%BE%E7%A7%91%E6%9F%A5%E8%AF%A2%E7%B3%BB%E7%BB%9F):集成本 MCP 服务的校园知识库与智能问答系统。