bc_resource_mcp
Version:
MCP server for Baichuan resource
349 lines (348 loc) • 11.1 kB
JavaScript
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;
}
}
}