UNPKG

bc_resource_mcp

Version:

MCP server for Baichuan resource

349 lines (348 loc) 11.1 kB
import { Logger } from "../utils/logger.js"; import { MissingRequiredArgumentError } from "../utils/errors.js"; export const TOOL_DICTIONARY = "bc_dictionary"; export const TOOL_LIST_BOOKS = "bc_list_books"; export const TOOL_LIST_CHAPTERS = "bc_list_chapters"; export const TOOL_FETCH_RESOURCE = "bc_fetch_resource"; export class DictionaryToolHandler { name; constructor() { this.name = TOOL_DICTIONARY; } getToolDescription() { return { name: this.name, description: "Looks up the code for the field in the dictionary.", inputSchema: { type: "object", properties: { subject: { type: "string", description: "The subject to look up.", }, grade: { type: "string", description: "The grade to look up.", }, volume: { type: "string", description: "The volume to look up.", }, press: { type: "string", description: "The press to look up.", }, }, required: [], }, }; } runTool(args) { return new Promise((resolve, reject) => { const subject = args.subject; const grade = args.grade; const volume = args.volume; const press = args.press; let result = {}; if (subject) { result = { ...result, subject: this.convertSubjectToCode(subject), }; } if (grade) { result = { ...result, grade: this.convertGradeToCode(grade), }; } if (volume) { result = { ...result, volume: this.convertVolumeToCode(volume), }; } if (press) { result = { ...result, press: this.convertPressToCode(press), }; } resolve([ { type: "text", text: JSON.stringify(result, null, 2), }, ]); }); } convertGradeToCode(grade) { const gradeMapping = { 一年级: 1, 二年级: 2, 三年级: 3, 四年级: 4, 五年级: 5, 六年级: 6, 七年级: 7, 八年级: 8, 九年级: 9, }; return gradeMapping[grade]; } convertVolumeToCode(volume) { const volumeMapping = { 上册: 1, 下册: 2, }; return volumeMapping[volume]; } convertSubjectToCode(subject) { const subjectMapping = { 语文: "01", 数学: "02", 英语: "03", 道德: "04", 历史: "05", 物理: "06", 生物: "07", 化学: "08", 地理: "09", }; return subjectMapping[subject]; } convertPressToCode(press) { const pressMapping = { 统编版: 0, 人教版: 1, 苏教版: 2, 人教版PEP: 3, 沪教版: 4, 沪科版: 5, 沪粤版: 6, 北师版: 7, 外研版: 8, 湘少版: 9, "外研版(三起点)": 10, 译林版: 11, 冀教版: 12, 教科版: 13, 鲁教版: 14, 青岛版: 15, 华师版: 16, 浙教版: 17, 星球版: 18, 济南版: 19, "统编版(2024新版)": 21, "人教版(2024新版)": 22, "人教PEP(2024新版)": 23, "湘教版(2024新版)": 24, "青岛版(2024新版)": 25, "北师版(2024新版)": 26, "冀教版(2024新版)": 27, "沪粤版(2024新版)": 28, "科粤版(2024新版)": 29, "鲁教版(2024新版·六三制)": 30, "湘少版(2024新版)": 31, "外研版(2024新版)": 32, "外研版(三起点,2024新版)": 33, "华师版(2024新版)": 34, "沪科版(2024新版)": 35, "教科版(2024新版)": 36, "济南版(2024新版)": 37, "冀少版(2024新版)": 38, "星球版(2024新版)": 39, "中图版(2024新版)": 40, "译林版(2024新版)": 41, "浙教版(2024新版)": 42, "鲁教版(2024新版)": 43, "青岛版(2024新版·63制)": 44, 湘教版: 51, 科普版: 52, 仁爱版: 53, 冀少版: 54, 中图版: 55, 人文版: 56, 课标版: 57, 人教精通版: 58, 人教新起点: 59, 川教版: 60, 鲁科版: 61, EEC版: 62, 辽师版: 63, 湘鲁版: 64, 开心版: 65, 陕旅版: 66, 北京版: 67, 剑桥版: 68, 广州版: 69, 沪教牛津版: 70, 重庆版: 71, "北师大版(一起点)": 72, "冀教版(3起点)": 73, "北京版(2024新版)": 74, "川教版(2024新版)": 75, "闽教版(2024新版)": 76, "陕旅版(2024新版)": 77, "科普版(2024新版)": 78, "鲁科版(2024新版)": 79, "人教精通版(2024新版)": 80, "湘鲁版(2024新版)": 81, "重大版(2024新版)": 82, "沪教版(2024新版)": 83, "仁爱版(2024新版)": 84, "冀教版(2024新版)": 85, "人教大同版(2024新版)": 86, "EEC版(2024新版)": 87, "辽师版(2024新版)": 88, "清华大学版(2024新版)": 89, "沪外教版(2024新版)": 90, 人教A版: 91, "鲁教版(2024新版·五四制)": 92, "牛津版(2024新版)": 93, 人教B版: 94, "剑桥版(2024新版)": 95, 闽教版: 96, 清华大学版: 97, }; return pressMapping[press]; } } export class ListBooksToolHandler { name; apiServer; constructor(apiServer) { this.name = TOOL_LIST_BOOKS; this.apiServer = apiServer; } getToolDescription() { return { name: this.name, description: "Lists all the books in the remote server.", inputSchema: { type: "object", properties: { subject: { type: "string", description: "The subject of the book.", }, grade: { type: "number", description: "The grade of the book.", }, volume: { type: "number", description: "The volume of the book.", }, press: { type: "string", description: "The press of the book.", }, }, required: [], }, }; } async runTool(args) { const params = { subject: args.subject, grade: args.grade, volume: args.volume, press: args.press, }; let books = await this.apiServer.listBooks(params); console.error("--------------------"); console.error(JSON.stringify(books, null, 2)); console.error("--------------------"); return [ { type: "text", text: JSON.stringify(books, null, 2), }, ]; } } export class ListChaptersToolHandler { name; apiServer; constructor(apiServer) { this.name = TOOL_LIST_CHAPTERS; this.apiServer = apiServer; } getToolDescription() { return { name: this.name, description: "Lists all the chapters of the book in the remote server.", inputSchema: { type: "object", properties: { bookId: { type: "string", description: "The book ID of the book.", }, }, required: ["bookId"], }, }; } async runTool(args) { if (!args.bookId) { throw new Error("bookId is required"); } const params = { bookId: args.bookId }; let chapters = (await this.apiServer.listChapters(params)).result; console.error("--------------------"); console.error(JSON.stringify(chapters, null, 2)); console.error("--------------------"); return [ { type: "text", text: JSON.stringify(chapters, null, 2), }, ]; } } export class FetchResourceToolHandler { name; apiServer; constructor(apiServer) { this.name = TOOL_FETCH_RESOURCE; this.apiServer = apiServer; } getToolDescription() { return { name: this.name, description: "Fetches the resource of the chapter in the remote server.", inputSchema: { type: "object", properties: { id: { type: "string", description: "The ID of the resource.", }, }, required: ["id"], }, }; } async runTool(args) { if (!args.id) { Logger.error("缺少必要参数: id"); throw new MissingRequiredArgumentError("id"); } try { const resource = (await this.apiServer.fetchResource(args.id)).result; Logger.debug("获取资源成功", resource); return [ { type: "text", text: JSON.stringify(resource, null, 2), }, ]; } catch (error) { Logger.error("获取资源失败", error); throw error; } } }