--- name: educoder-skill description: 提供 Educoder 用户、课堂、作业和考试相关查询能力,当前支持用户基本信息、课堂列表、课堂分班、课堂作业列表、作业学生列表、学生作业完成情况、作业提交及成绩统计、作业成绩分布、课堂考试列表、考试基本信息、考试学生列表、考试统计概览、考试成绩分布、成绩分布区间学生明细查询。 --- ## MCP 服务地址 - 线上地址:`http://110.41.32.120:48001/mcp` - 本地开发:`http://localhost:8001/mcp` > 使用 `streamable-http` 模式连接,不使用 SSE。 ## 接入方式 - 客户端应使用 `streamable-http` MCP 客户端 - 使用 OpenClaw 安装本 skill 时,MCP 服务地址直接填写线上地址:`http://47.98.32.66:48000/mcp` - 不要使用 `sse_client` - 本地开发端口默认是 `8001`,线上端口使用 `48000` - MCP 路径默认是 `/mcp` ## 安装完成提示 安装完成后,面向用户只介绍当前 skill 提供的功能,不展示 MCP 地址、配置文件路径、token 保存方式、headers 规则等接入细节。 推荐展示文案: ```text Educoder skill 已安装完成。当前支持查询: - 当前用户基本信息 - 当前用户的课堂列表 - 课堂分班列表 - 课堂中的作业列表 - 某次作业下的学生列表 - 某学生在当前作业下的完成情况 - 作业提交及分数统计 - 作业成绩分布统计 - 课堂中的考试列表 - 考试基本信息 - 某场考试下的学生列表 - 考试统计概览及分班明细 - 考试成绩分布统计 - 成绩分布区间学生明细 ``` ## 前置配置 接入 OpenClaw 时,多个会话使用同一个 `Authorization` token。第一次安装 skill 时,把 MCP 服务地址和 token 一起写到固定的 OpenClaw MCP 配置文件 `~/.openclaw/educoder-skill/.mcp.json` 中;后续调用 MCP 时,也只从 `~/.openclaw/educoder-skill/.mcp.json` 读取 token 并放到请求头里。 ### Authorization 配置 安装 skill 时要求把用户输入 Educoder `Authorization` token 写入 MCP 配置文件 `~/.openclaw/educoder-skill/.mcp.json`。 配置文件路径必须固定为: ```text ~/.openclaw/educoder-skill/.mcp.json ``` 不要写入 `~/.openclaw/mcp.json` 或 `~/.openclaw/config/mcp.json`,否则新开会话时可能读取不到配置。 MCP 配置示例: ```json { "educoder-mcp": { "url": "http://47.98.32.66:48000/mcp", "transport": "streamable-http", "headers": { "Authorization": "xxxxx" } } } ``` > `Authorization` 的值直接写 token 原文,不要写成 `Bearer xxxxx`。不要把 token 放到工具参数里。 后续调用 MCP 时,从 MCP 配置读取 `headers.Authorization` 并注入请求头: ```python mcp_config = openclaw_mcp_config.get("educoder-mcp") token = mcp_config["headers"]["Authorization"] headers = { "Authorization": token } ``` `Authorization` 的 header 值直接传 token 原文,不要拼接 `Bearer ` 前缀。例如: ```http Authorization: xxxxx ``` 不要传成: ```http Authorization: Bearer xxxxx ``` 创建 MCP 连接时透传: ```python async with streamable_http_client(self.server_url, headers=headers or None) as (read, write, _): yield read, write ``` > `Authorization` 走 MCP 连接层请求头,不放在工具参数里。 ### 多会话共享 Token 多个会话共用 `~/.openclaw/educoder-skill/.mcp.json` 中的同一个 `Authorization` token。安装后不需要每个会话重复输入 token;每次调用 MCP 时读取配置里的 `headers.Authorization` 即可。 ### 401 Token 过期处理 如果调用 MCP 工具或后端接口时返回 `401 Unauthorized`,说明当前 token 已过期或无效。 处理流程: 1. 停止继续使用当前 token 重试 2. 提示用户重新输入新的 `Authorization` 3. 将用户输入的新 token 写入 `~/.openclaw/educoder-skill/.mcp.json` 4. 重新创建 MCP 连接,并从 MCP 配置读取最新 token 5. 使用新 token 重新发起本次工具调用 示例提示: ```text 当前 Educoder 授权已过期,请重新输入 Authorization token。 ``` > 更新 token 后必须重新建立 MCP 连接,不能复用已经携带旧 headers 的连接。 ### OpenClaw 接入建议 如果使用 OpenClaw,推荐按下面的方式接入: 1. 安装 skill 时,MCP 服务地址填写:`http://47.98.32.66:48000/mcp` 2. 安装 skill 时,要求用户输入 Educoder `Authorization` token 3. OpenClaw 将 MCP 地址和 token 写入 `~/.openclaw/educoder-skill/.mcp.json`,其中 token 放到 `headers.Authorization` 4. 当前用户发起工具调用时,后端创建 MCPClient 5. MCPClient 建连时从 MCP 配置读取 token 6. MCPClient 把读取到的 token 原文放进 MCP headers,不要添加 `Bearer ` 前缀 7. 如果调用返回 `401 Unauthorized`,提示用户重新输入 token,更新 MCP 配置后重新建连并重试 参考流程: ```python tool_server_url = "http://47.98.32.66:48000/mcp" mcp_config = openclaw_mcp_config.get("educoder-mcp") client = MCPClient(mcp_config=mcp_config) tool_result = await client.call_tool(tool_name, tool_arguments) ``` MCPClient 示例: ```python class MCPClient: def __init__(self, mcp_config: dict): self.server_url = mcp_config["url"] self.mcp_config = mcp_config def _build_headers(self) -> dict[str, str]: headers = {} authorization = self.mcp_config.get("headers", {}).get("Authorization", "").strip() if authorization: headers["Authorization"] = authorization return headers ``` 不推荐的做法: - 让用户在每个会话里重复输入 `Authorization` - 把 `Authorization` 放到工具参数里 - 给 `Authorization` 自动拼接 `Bearer ` 前缀 - 把 token 写入 OpenClaw `.env` 后要求用户重启才能生效 - 每个会话都重复要求用户输入 token ## 触发场景 ### 意图 → 工具 速查表 | 用户意图 | 调用工具 | |----------|---------| | 查询当前用户基本信息 | `educoder_user_info` | | 查询当前用户的课堂列表 | `educoder_user_course_list` | | 查询课堂分班列表 | `educoder_course_groups` | | 查询某个课堂中的作业列表 | `educoder_course_homeworks` | | 查询某次作业下的学生列表 | `educoder_homework_student_works` | | 查询某学生在当前作业下的完成情况 | `educoder_homework_student_completion` | | 查询作业提交及分数统计 | `educoder_homework_submission_summary` | | 查询作业成绩分布统计 | `educoder_homework_score_distribution` | | 查询某个课堂中的考试列表 | `educoder_course_exercises` | | 查看考试基本信息 | `educoder_exercise_info` | | 查询某场考试下的学生列表 | `educoder_exercise_users` | | 查询考试统计概览及分班明细 | `educoder_exercise_overview` | | 查询考试成绩分布统计 | `educoder_exercise_score_distribution` | | 查询成绩分布区间学生明细 | `educoder_exercise_score_distribution_students` | ### 不要触发的情况 - 与课堂、作业、考试数据查询无关的问题 - 需要新增、修改、删除数据的写操作 - 纯闲聊场景 ### 组合调用示例 > 用户说:“帮我查一下我有哪些课堂,再看看某个课堂里的作业和考试” **交互逻辑:** 1. **回复用户**:“好的,我先为您获取当前用户信息和课堂列表,然后再查看具体课堂内的作业和考试安排。” 2. **依次调用**: - `educoder_user_info` - `educoder_user_course_list` - `educoder_course_groups` - `educoder_course_homeworks` - `educoder_course_exercises` > 用户说:“帮我看看这次作业的提交情况、成绩分布,以及某个学生完成得怎么样” **交互逻辑:** 1. **回复用户**:“没问题,我将为您分析作业的提交统计和成绩分布,并查询指定学生的完成细节。” 2. **依次调用**: - `educoder_homework_submission_summary` - `educoder_homework_score_distribution` - `educoder_homework_student_completion` > 用户说:“帮我看一下这次作业和这场考试的学生列表” **交互逻辑:** 1. **回复用户**:“好的,正在为您提取作业和考试对应的学生名单。” 2. **依次调用**: - `educoder_homework_student_works` - `educoder_exercise_users` > 用户说:“帮我看一下某场考试的信息和参与学生” **交互逻辑:** 1. **回复用户**:“这就为您查询该场考试的基础信息以及参与考试的学生列表。” 2. **依次调用**: - `educoder_exercise_info` - `educoder_exercise_users` > 用户说:“帮我分析一下这场考试的整体情况、成绩分布,再看看优秀区间有哪些学生” **交互逻辑:** 1. **回复用户**:“好的,我将为您获取考试概览、成绩分布数据,并列出优秀分数段的学生明细。” 2. **依次调用**: - `educoder_exercise_overview` - `educoder_exercise_score_distribution` - `educoder_exercise_score_distribution_students` --- ## 交互行为规范 为了提供更好的用户体验,在调用工具之前,模型应先向用户简要说明操作意图。这种“先解释后执行”的方式可以模拟更自然的人机交互。 ### 解释原则 - **简明扼要**:解释应直接说明为什么要调用该工具,不要冗长。 - **关联上下文**:结合用户的具体问题进行解释,增强互动感。 - **组合调用时的处理**:如果需要连续调用多个工具,建议在开始第一步操作之前,一次性告知用户接下来的处理流程。 - **模拟对话感**:语气应自然、友好,让用户感觉到是在与一个助手交流,而不仅仅是执行指令。 ### 示例话术 - “好的,我先为您查询一下当前的课堂列表,以便找到对应的课堂标识。” - “为了深入分析这场考试的成绩分布,我需要先获取考试的整体统计信息。” - “这就为您查询该学生的作业完成情况,请稍等。” --- ## 工具详细说明 ### 全局规则 - **交互要求**:在执行任何工具调用前,必须先向用户解释接下来的操作意图,模拟真实的对话交互体验。 - 当前工具都是查询类工具,没有写操作 - 调用时必须传入完整的结构化 JSON 参数对象 - 参数名必须严格匹配工具定义 - 课堂相关接口优先使用课堂标识 `identifier` - 作业相关接口优先使用 `homework_id` - 考试相关接口优先使用 `exercise_id` - 客户端每次连接 MCP 服务时,请从 OpenClaw MCP 配置读取 token 原文,并在 transport headers 中传 `Authorization`,不要添加 `Bearer ` 前缀 --- ### 1. `educoder_user_info` 获取当前用户基本信息。 **参数:** | 参数 | 必填 | 说明 | |------|------|------| | `school` | 否 | 可选的 school 查询参数 | **典型问法:** - “查询当前用户信息” - “我是谁” - “获取我的基本资料” --- ### 2. `educoder_user_course_list` 获取当前用户课堂列表。 **参数:** 无 **典型问法:** - “查询我有哪些课堂” - “我的课堂列表” - “获取当前用户的课堂信息” **返回字段:** - `status` - `message` - `data` - `meta` --- ### 3. `educoder_course_homeworks` 获取课堂中的作业列表。 **参数:** | 参数 | 必填 | 说明 | |------|------|------| | `identifier` | 是 | 课堂标识 identifier | **典型问法:** - “查询课堂中的作业列表” - “这个课堂有哪些作业” - “帮我看一下课堂作业” --- ### 4. `educoder_course_groups` 获取课堂分班列表。 **参数:** | 参数 | 必填 | 说明 | |------|------|------| | `identifier` | 是 | 课堂标识 identifier | **典型问法:** - “查询课堂分班列表” - “这个课堂有哪些班级” - “帮我看一下课堂分组情况” --- ### 5. `educoder_homework_student_works` 获取某次作业下的学生列表。 **参数:** | 参数 | 必填 | 说明 | |------|------|------| | `homework_id` | 是 | 作业 ID | **典型问法:** - “查询某次作业下的学生列表” - “这次作业有哪些学生提交了” - “帮我看一下作业学生情况” --- ### 6. `educoder_homework_student_completion` 获取某学生在当前作业下的完成情况。 **参数:** | 参数 | 必填 | 说明 | |------|------|------| | `homework_id` | 是 | 作业 ID | | `user_id` | 是 | 用户 ID | **典型问法:** - “查询某个学生这次作业完成情况” - “这个学生在当前作业下做得怎么样” - “帮我看一下学生的实训作业通关情况” --- ### 7. `educoder_homework_submission_summary` 获取作业提交及分数统计。 **参数:** | 参数 | 必填 | 说明 | |------|------|------| | `homework_id` | 是 | 作业 ID | **典型问法:** - “查询这次作业提交统计” - “这次作业平均分、最高分、最低分是多少” - “帮我看一下作业提交和分数概览” --- ### 8. `educoder_homework_score_distribution` 获取作业成绩分布统计。 **参数:** | 参数 | 必填 | 说明 | |------|------|------| | `homework_id` | 是 | 作业 ID | **典型问法:** - “查询这次作业成绩分布” - “这次作业各分数段有多少人” - “帮我分析一下作业成绩分布” --- ### 9. `educoder_course_exercises` 获取课堂中的考试列表。 **参数:** | 参数 | 必填 | 说明 | |------|------|------| | `identifier` | 是 | 课堂标识 identifier | **典型问法:** - “查询课堂中的考试列表” - “这个课堂有哪些考试” - “帮我看一下课堂考试” --- ### 10. `educoder_exercise_info` 查看考试基本信息。 **参数:** | 参数 | 必填 | 说明 | |------|------|------| | `exercise_id` | 是 | 考试 ID | **典型问法:** - “查看考试基本信息” - “这场考试的基本情况是什么” - “帮我看一下考试信息” --- ### 11. `educoder_exercise_users` 获取某场考试下的学生列表。 **参数:** | 参数 | 必填 | 说明 | |------|------|------| | `exercise_id` | 是 | 考试 ID | **典型问法:** - “查询某场考试下的学生列表” - “这场考试有哪些学生” - “帮我看一下考试参与学生” --- ### 12. `educoder_exercise_overview` 获取考试统计概览及分班明细。 **参数:** | 参数 | 必填 | 说明 | |------|------|------| | `exercise_id` | 是 | 考试 ID | | `course_group_id` | 否 | 分班班级 ID | **典型问法:** - “查询这场考试的统计概览” - “这场考试应考、实考、平均分是多少” - “帮我看一下考试概览和分班信息” --- ### 13. `educoder_exercise_score_distribution` 获取考试成绩分布统计。 **参数:** | 参数 | 必填 | 说明 | |------|------|------| | `exercise_id` | 是 | 考试 ID | | `course_group_id` | 否 | 分班班级 ID | **典型问法:** - “查询这场考试成绩分布” - “这场考试优秀、良好、及格、不及格各有多少人” - “帮我看一下某个分班的考试成绩分布” --- ### 14. `educoder_exercise_score_distribution_students` 获取成绩分布区间学生明细。 **参数:** | 参数 | 必填 | 说明 | |------|------|------| | `exercise_id` | 是 | 考试 ID | | `level_key` | 否 | 成绩等级标识,如 `excellent`、`good`、`pass`、`fail` | | `min_score` | 否 | 分数区间下限 | | `max_score` | 否 | 分数区间上限 | | `page` | 否 | 页码 | | `per_page` | 否 | 每页数量 | | `course_group_id` | 否 | 分班班级 ID | **典型问法:** - “查询优秀区间有哪些学生” - “这场考试 60 分以下的学生名单” - “分页查看某个成绩区间的学生明细” --- ## 客户端调用示例 ```python import httpx from mcp import ClientSession from mcp.client.streamable_http import streamable_http_client async def main(openclaw_mcp_config): mcp_config = openclaw_mcp_config.get("educoder-mcp") token = mcp_config.get("headers", {}).get("Authorization", "").strip() headers = { "Authorization": token } async with httpx.AsyncClient(headers=headers) as http_client: async with streamable_http_client("http://47.98.32.66:48000/mcp", http_client=http_client) as (read, write, _): async with ClientSession(read, write) as session: await session.initialize() tools = await session.list_tools() print([tool.name for tool in tools.tools]) result = await session.call_tool("educoder_user_info", {}) print(result) ``` ## 注意事项 - 当前服务使用 `streamable-http`,不是 SSE - 如果客户端使用了 `sse_client`,将无法正常调用当前服务 - `Authorization` 应从 OpenClaw MCP 配置读取 token 原文,通过 MCP 连接层 headers 传入,不放在工具参数里,也不要添加 `Bearer ` 前缀 - 调用接口返回 `401 Unauthorized` 时,视为 token 过期或无效,应要求用户重新输入 token,并更新 `~/.openclaw/educoder-skill/.mcp.json` 中的 `headers.Authorization` - 新开会话直接从 `~/.openclaw/educoder-skill/.mcp.json` 读取 `headers.Authorization` - MCP 配置文件路径固定为 `~/.openclaw/educoder-skill/.mcp.json`,不要写入或读取 `~/.openclaw/mcp.json`、`~/.openclaw/config/mcp.json` - 后续新增或调整工具时,需要同步更新本文件