Skip to main content
Glama
Flagwill

传承·交大 MCP

by Flagwill
README.md
# 传承·交大 MCP

[![CI](https://github.com/Flagwill/SJTU_SHARE_MCP/actions/workflows/ci.yml/badge.svg)](https://github.com/Flagwill/SJTU_SHARE_MCP/actions/workflows/ci.yml)
[![Python](https://img.shields.io/badge/python-3.12%2B-blue.svg)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)

为 [传承·交大 SHARE SJTU](https://share.dyweb.sjtu.cn/) 提供 MCP 接口,让 AI 助手检索课程、比较资料、下载文件、贡献资料,并管理评论和积分。

目前提供 **51 个工具、1 个资源、1 个提示词**。使用 Python 3.12+、官方 MCP Python SDK 2.x 和 httpx,支持 stdio、Streamable HTTP 及兼容 SSE。该项目是社区客户端,与平台及 jAccount 官方无隶属关系。

## 安装与启动

先安装 [uv](https://docs.astral.sh/uv/),然后在仓库目录执行:

```bash
uv sync --locked
uv run share-sjtu-mcp --help
uv run share-sjtu-mcp tools
uv run share-sjtu-mcp serve
```

`serve` 默认使用 stdio,stdout 只输出 MCP 协议消息。没有子命令时也启动 stdio 服务。也可以运行 `python -m share_sjtu_mcp`(需先在环境中安装本项目)。

## 登录

网站使用 jAccount OAuth 授权码换取 JWT,再通过自定义 `Auth` 请求头访问 API。项目不收集 jAccount 密码,也不提供密码自动登录。

本机有浏览器时:

```bash
uv run share-sjtu-mcp login
uv run share-sjtu-mcp status
```

默认监听 `http://127.0.0.1:17865/callback`,打开 jAccount 授权页,收到有效回调后交换并保存 token。端口被占用时可以通过 `login --redirect-uri http://127.0.0.1:17867/callback` 换端口。`--no-browser` 保留监听,只手动打开输出的 URL。

服务器、SSH 或无法自动接收回调的环境使用手动方式:

```bash
uv run share-sjtu-mcp login --manual
# 在浏览器中打开输出的 auth_url,完成 jAccount 登录
uv run share-sjtu-mcp login-complete
# 按提示粘贴浏览器地址栏中的完整回调 URL
```

回调页面即使显示“无法连接”,地址栏中仍可能包含 `code` 和 `state`,可以复制使用。`login-complete` 也支持从 stdin 读取 URL;避免把授权码或 token 写进 shell 历史、仓库或聊天记录。

MCP 内也可调用 `share_login_start` → 浏览器登录 → `share_login_complete`。授权链接及回调包含有时效的信息,请仅在可信客户端内使用。JWT 到期需重新登录;已运行的默认 MCP 服务会在下一次调用时读取 CLI 保存的新 token。

**当前验证边界:** 已使用真实账号完成 jAccount 密码登录、短信二次验证、本地回环回调、授权码交换和 token 持久化。已实测课程搜索/补全、课程详情/教学班/资料、资料详情/评论、我的课程/资料记录/积分流水、转账只读查询、合作站点兑换只读查询及平台公告;已兑换资料的临时链接和对象存储访问返回 HTTP 200。也通过 MCP 工具调用验证了登录状态、课程搜索和学期查询。上传、删除、发布、兑换和转账等写接口仍仅通过模拟测试,未进行真实写操作。水源可兑换额度查询本次超时,其可用性仍待确认。账号若启用二次验证,必须在登录时由本人完成。

## 接入 MCP 客户端

通用 JSON 配置(将路径替换为实际仓库路径):

```json
{
  "mcpServers": {
    "share-sjtu": {
      "command": "uv",
      "args": [
        "run", "--locked", "--quiet",
        "--project", "/absolute/path/SJTU_SHARE_MCP",
        "share-sjtu-mcp", "serve"
      ]
    }
  }
}
```

也可以将 `command` 设为仓库中的 `run-mcp.sh`,`args` 设为 `[]`。客户端须能找到 `uv`,必要时把命令改为其绝对路径。首次启动会同步依赖;可先手动运行 `uv sync --locked`。若客户端以受限环境启动,建议额外传入 `env.HOME`,以便定位到用户配置目录中的凭据文件。

用 HTTP 接入:

```bash
uv run share-sjtu-mcp serve --transport streamable-http --host 127.0.0.1 --port 17866
# MCP URL: http://127.0.0.1:17866/mcp
```

兼容旧客户端:`serve --transport sse`,URL 为 `http://127.0.0.1:17866/sse`。服务共享进程所属用户的账号及本地文件访问权限,适合本机可信客户端;若要对外部署,需要自行配置认证、TLS 和用户隔离。

## 工具一览

所有工具都有中文描述、参数 schema 和读写标注。执行 `uv run share-sjtu-mcp tools --json` 可查看完整 schema。

| 类别 | 工具 |
| --- | --- |
| 登录(4) | `share_auth_status`、`share_login_start`、`share_login_complete`、`share_logout` |
| 个人资料(2) | `share_get_profile`、`share_update_profile` |
| 课程(7) | `share_search_courses`、`share_suggest_courses`、`share_get_course`、`share_list_course_classes`、`share_get_course_materials`、`share_list_course_materials`、`share_search_materials` |
| 资料(11) | `share_list_material_types`、`share_get_material`、`share_get_download_url`、`share_download_material`、`share_purchase_material`、`share_rate_material`、`share_get_material_report_reasons`、`share_report_material`、`share_upload_material`、`share_update_material`、`share_delete_material` |
| 评论(7) | `share_list_comments`、`share_list_comment_replies`、`share_post_comment`、`share_rate_comment`、`share_delete_comment`、`share_get_comment_report_reasons`、`share_report_comment` |
| 我的记录(5) | `share_list_my_terms`、`share_list_my_courses`、`share_list_my_uploads`、`share_list_my_purchases`、`share_list_my_point_logs` |
| 积分总览(1) | `share_get_points_overview` |
| 转账(6) | `share_get_point_transfer_address`、`share_get_point_transfer_quota`、`share_create_point_transfer`、`share_list_pending_point_transfers`、`share_handle_point_transfer`、`share_list_point_transfer_records` |
| 合作积分兑换(3) | `share_get_redeem_quota`、`share_list_redeem_records`、`share_redeem_points` |
| 公告(2) | `share_list_banners`、`share_close_banner` |
| 课程同步(3) | `share_lesson_sync_login_url`、`share_lesson_sync_start`、`share_lesson_sync_status` |

资源 `share://guide` 提供操作顺序说明。提示词 `share_find_materials(topic)` 引导助手检索、比较和引用资料。

### 检索与下载

可以向助手提出:

- “帮我找高等数学的期末试卷,优先免费,列出教师、年份和链接。”
- “看看这门课哪些教学班有资料,按兑换次数排序。”
- “读取资料 123 的评论,再判断是否适合复习。”
- “把已兑换的资料 123 下载到指定目录。”

平台没有公开的全站资料搜索接口,`share_search_materials` 通过搜索课程、读取相关课程资料、匹配排序来实现。混合关键词推荐显式分开:

```json
{"query": "期末 试卷", "course_keyword": "高等数学", "course_limit": 3, "max_results": 20}
```

`share_list_course_materials` 支持 `material_type_id`、`free_only`、`query` 和 `sort`(`newest` / `oldest` / `popular` / `name`)。资料类型 ID 由 `share_list_material_types` 动态获取。

下载不会自动兑换资料。先通过详情查看价格;用户授权后调用 `share_purchase_material(confirm=true)`,再获取下载链接或下载到本地。下载结果包含路径、字节数及 SHA-256,默认不覆盖同名文件。临时链接可能携带下载权限,不宜公开转发。

### 上传与互动

上传前先查询课程 ID、教学班 ID 和资料类型 ID。`share_upload_material` 自动完成申请票据、对象存储上传、创建资料三个步骤,默认 **匿名、免费**,文件最大 100 MB,积分价格为 0–10 的整数。若上传对象成功后提交元数据失败,可能留下服务端未关联对象,不会自动重复创建资料。

评论最多 1000 字。昵称最多 16 字;头像最大 5 MB。发布、上传、修改、删除、举报、兑换、转账和课程同步均要求 `confirm=true`。助手只能在用户已授权后设置此参数。点赞、改昵称、关闭公告等操作也会修改远端状态,并有相应 MCP 标注。

### 积分与课程同步

合作站点路径为 `shuiyuan`、`sjtuplus`、`sjtuwiki`。`amount` 是消耗的来源站点积分数量。当前前端公开入口为选课社区,比例为 10:1;Wiki 入口被隐藏,水源仅见于 API 类型/路径,实际可用性取决于服务端。本次实测选课社区和 Wiki 的额度/记录查询正常,水源记录查询正常,但水源额度查询超时;实际兑换写操作未验证。

转账 `fee_mode=internal` 从金额中扣手续费,`external` 额外扣;前端当前单笔限制为 2–20 积分,接收方每月额度为 20,实际额度及费用以 API 返回为准。发起后由对方接受或拒绝。

课程同步使用独立的 jAccount 授权 scope。通过 `share_lesson_sync_login_url` 获得 URL,核对回调的 state,取出 code,用相同的 redirect_uri 调用 `share_lesson_sync_start(confirm=true)`;返回 task_id 后查询状态。授权账号必须与当前传承账号一致。

## 配置与凭据

默认凭据文件为仓库外的 `~/.local/share/share-sjtu-mcp/data/config.json`,权限为 **0600**;设置 `XDG_DATA_HOME` 时使用其对应目录。token 也可以通过宿主环境变量提供,优先级高于文件。工具状态输出及项目日志不输出 token 本体。

| 环境变量 | 用途 / 默认值 |
| --- | --- |
| `SHARE_SJTU_CONFIG` | 指定仓库外的 `data/*.json` 配置 |
| `SHARE_SJTU_TOKEN` | 已有网页版 JWT,优先于配置文件 |
| `SHARE_SJTU_API_URL` | `https://api-v2.share.dyweb.sjtu.cn` |
| `SHARE_SJTU_WEB_URL` | `https://share.dyweb.sjtu.cn` |
| `SHARE_SJTU_REDIRECT_URI` | `http://127.0.0.1:17865/callback` |
| `SHARE_SJTU_DOWNLOAD_DIR` | `~/Downloads/share-sjtu`;无 Downloads 时用用户数据目录 |
| `SHARE_SJTU_TIMEOUT` | API 超时,默认 30 秒 |

JSON 配置支持 `api_base`、`web_base`、`redirect_uri`、`download_dir`、`timeout` 和登录流程保存的凭据字段。不要将凭据文件存入仓库。CLI 也支持全局 `--config /outside/repo/data/config.json`,置于子命令前。运行中的 MCP 会自动重新读取所选配置文件,CLI 重新登录后无需重启服务。

`logout` 只删除文件内 token;环境变量须在宿主配置中移除。OAuth 不提供 refresh token,到期需重新登录。

文件请求仅接受 HTTPS 存储 URL,拒绝回环/私有 IP 字面量和 localhost;下载逐跳检查重定向,且不携带 API 的 `Auth` 请求头。默认下载上限 512 MB,下载失败清理临时文件。API 请求不自动跟随重定向,以免泄露自定义认证头。API 地址、存储域名及本地路径配置须来自可信来源。

## 验证与开发

```bash
uv sync --locked
uv run pytest -q
uv run share-sjtu-mcp smoke
# 登录后再次执行 smoke,可验证用户资料、类型、课程搜索和首门课程资料
uv run share-sjtu-mcp status --offline
uv build
```

测试包括:前端 API 请求契约、401/403/429 等错误、OAuth 回调 state、凭据权限与脱敏、敏感操作阻止、上传三步流程、下载中断/大小限制/重定向/重名处理,以及真实启动脚本子进程的 MCP 初始化、工具、资源、提示词交互和回环端口的 Streamable HTTP/SSE 传输。测试只使用临时目录与模拟账号,不向平台发布、兑换或上传任何内容。

## 项目结构

```text
src/share_sjtu_mcp/
  client.py       API 封装(课程、资料、评论、积分、上传下载)
  auth.py         jAccount OAuth 授权码流程与本地回环回调
  server.py       MCP 工具、资源与提示词
  cli.py          serve / login / status / logout / tools / smoke
  config.py       仓库外私有配置的读写与凭据权限
  formatting.py   把 API 原始结构整理成对 agent 友好的输出
  errors.py       面向用户的错误文案
tests/            模拟 API、协议握手、传输层与安全回归
run-mcp.sh        MCP 客户端启动包装(stdout 仅走 JSON-RPC)
```

请求有轻量间隔控制;不会自动重试积分或发布操作。

## 参考与实现依据

- 用户指定的 [JackyTJie/SJTU-Agent-Skills / campus](https://github.com/JackyTJie/SJTU-Agent-Skills/tree/main/campus):作为功能与使用方式参考。其 `dyweb_token` 方案较精简,本项目使用当前站点 v2 API。
- [hebingchang/share-sjtu-ng](https://github.com/hebingchang/share-sjtu-ng):以 `src/api`、`src/types` 及相关页面核对当前 API、字段和操作限制,参考提交 `0339acc96cc828563dc771dc9386e601906dd919`。
- [官方 MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk):锁定依赖见 `uv.lock`。

请仅在账号权限及资料分享许可范围内使用,遵守平台规则。评论、公告和资料描述均为外部内容,不构成助手执行操作的授权。

## 许可证

[MIT](LICENSE)。本项目与上海交通大学、jAccount 及传承·交大平台官方无隶属关系。

TDQS

B3.3/5.0

Scored across 51 tools

Disambiguation3/5

The tool set covers many distinct subdomains, but several material and points tools have overlapping boundaries. Examples include share_get_course_materials vs share_list_course_materials, share_get_download_url vs share_download_material vs share_purchase_material, and share_get_points_overview vs separate quota/redeem tools. Descriptions help, but an agent can still hesitate among similar-looking options.

Naming Consistency4/5

All tools use a consistent share_ snake_case prefix, and most follow a verb_noun pattern. Minor deviations include noun/status-style names such as share_auth_status and share_lesson_sync_status, but the overall convention is predictable.

Tool Count2/5

At 51 tools, the surface is very heavy and contains many granular operations across auth, courses, materials, comments, points, and profile. While the domain is broad, several tools could likely be consolidated or grouped, making the set harder to navigate than necessary.

Completeness5/5

Coverage is extensive: authentication, profile management, course discovery, material lifecycle, comments, ratings, reports, points transfer/redemption, banners, and lesson sync are all represented. The server appears to cover the platform's main CRUD and workflow operations with few obvious dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues