```
feat(mcp-bridge): 实现MCP服务器功能增强和日志系统 - 添加日志缓冲区和封装日志函数,支持多种日志类型(info, success, warn, error, mcp) - 实现MCP服务器启动/停止功能,支持端口配置和状态管理 - 添加配置文件管理(auto-start, last-port),支持持久化设置 - 实现完整的工具API接口(get_selected_node, set_node_name, save_scene等) - 统一处理MCP调用逻辑,便于日志记录和错误处理 - 更新面板界面,添加端口输入、自动启动开关、日志查看等功能 - 优化错误处理和响应格式,符合MCP标准规范 ```
This commit is contained in:
624
main.js
624
main.js
@@ -3,6 +3,29 @@
|
||||
const http = require("http");
|
||||
const path = require("path");
|
||||
|
||||
let logBuffer = []; // 存储所有日志
|
||||
let mcpServer = null;
|
||||
let serverConfig = {
|
||||
port: 3456,
|
||||
active: false,
|
||||
};
|
||||
|
||||
// 封装日志函数,同时发送给面板和编辑器控制台
|
||||
function addLog(type, message) {
|
||||
const logEntry = {
|
||||
time: new Date().toLocaleTimeString(),
|
||||
type: type,
|
||||
content: message,
|
||||
};
|
||||
logBuffer.push(logEntry);
|
||||
Editor.Ipc.sendToPanel("mcp-bridge", "mcp-bridge:on-log", logEntry);
|
||||
// 【修改】移除 Editor.log,保持编辑器控制台干净
|
||||
// 仅在非常严重的系统错误时才输出到编辑器
|
||||
if (type === "error") {
|
||||
Editor.error(`[MCP] ${message}`); // 如果你完全不想在编辑器看,可以注释掉
|
||||
}
|
||||
}
|
||||
|
||||
const getNewSceneTemplate = () => {
|
||||
// 尝试获取 UUID 生成函数
|
||||
let newId = "";
|
||||
@@ -43,31 +66,320 @@ const getNewSceneTemplate = () => {
|
||||
module.exports = {
|
||||
"scene-script": "scene-script.js",
|
||||
load() {
|
||||
// 插件加载时启动一个微型服务器供 MCP 使用 (默认端口 3000)
|
||||
this.startMcpServer();
|
||||
addLog("info", "MCP Bridge Plugin Loaded");
|
||||
// 读取配置
|
||||
let profile = this.getProfile();
|
||||
serverConfig.port = profile.get("last-port") || 3456;
|
||||
let autoStart = profile.get("auto-start");
|
||||
|
||||
if (autoStart) {
|
||||
addLog("info", "Auto-start is enabled. Initializing server...");
|
||||
// 延迟一点启动,确保编辑器环境完全就绪
|
||||
setTimeout(() => {
|
||||
this.startServer(serverConfig.port);
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
// 获取配置文件的辅助函数
|
||||
getProfile() {
|
||||
// 'local' 表示存储在项目本地(local/mcp-bridge.json)
|
||||
return Editor.Profile.load("profile://local/mcp-bridge.json", "mcp-bridge");
|
||||
},
|
||||
|
||||
unload() {
|
||||
if (this.server) this.server.close();
|
||||
this.stopServer();
|
||||
},
|
||||
startServer(port) {
|
||||
if (mcpServer) this.stopServer();
|
||||
|
||||
try {
|
||||
mcpServer = http.createServer((req, res) => {
|
||||
// 设置 CORS 方便调试
|
||||
res.setHeader("Access-Control-Allow-Origin", "*");
|
||||
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
|
||||
if (req.method === "OPTIONS") {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
let body = "";
|
||||
req.on("data", (chunk) => {
|
||||
body += chunk;
|
||||
});
|
||||
req.on("end", () => {
|
||||
try {
|
||||
// 简单的路由处理
|
||||
if (req.url === "/list-tools" && req.method === "GET") {
|
||||
// 1. 返回工具定义 (符合 MCP 规范)
|
||||
const tools = [
|
||||
{
|
||||
name: "get_selected_node",
|
||||
description: "获取当前编辑器中选中的节点 ID",
|
||||
inputSchema: { type: "object", properties: {} },
|
||||
},
|
||||
{
|
||||
name: "set_node_name",
|
||||
description: "修改指定节点的名称",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: { type: "string", description: "节点的 UUID" },
|
||||
newName: { type: "string", description: "新的节点名称" },
|
||||
},
|
||||
required: ["id", "newName"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "save_scene",
|
||||
description: "保存当前场景的修改",
|
||||
inputSchema: { type: "object", properties: {} },
|
||||
},
|
||||
{
|
||||
name: "get_scene_hierarchy",
|
||||
description: "获取当前场景的完整节点树结构(包括 UUID、名称和层级关系)",
|
||||
inputSchema: { type: "object", properties: {} },
|
||||
},
|
||||
{
|
||||
name: "update_node_transform",
|
||||
description: "修改节点的坐标、缩放或颜色",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: { type: "string", description: "节点 UUID" },
|
||||
x: { type: "number" },
|
||||
y: { type: "number" },
|
||||
scaleX: { type: "number" },
|
||||
scaleY: { type: "number" },
|
||||
color: { type: "string", description: "HEX 颜色代码如 #FF0000" },
|
||||
},
|
||||
required: ["id"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create_scene",
|
||||
description: "在 assets 目录下创建一个新的场景文件",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
sceneName: { type: "string", description: "场景名称" },
|
||||
},
|
||||
required: ["sceneName"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create_prefab",
|
||||
description: "将场景中的某个节点保存为预制体资源",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
nodeId: { type: "string", description: "节点 UUID" },
|
||||
prefabName: { type: "string", description: "预制体名称" },
|
||||
},
|
||||
required: ["nodeId", "prefabName"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "open_scene",
|
||||
description: "在编辑器中打开指定的场景文件",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
url: {
|
||||
type: "string",
|
||||
description: "场景资源路径,如 db://assets/NewScene.fire",
|
||||
},
|
||||
},
|
||||
required: ["url"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create_node",
|
||||
description: "在当前场景中创建一个新节点",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
name: { type: "string", description: "节点名称" },
|
||||
parentId: {
|
||||
type: "string",
|
||||
description: "父节点 UUID (可选,不传则挂在场景根部)",
|
||||
},
|
||||
type: {
|
||||
type: "string",
|
||||
enum: ["empty", "sprite", "label"],
|
||||
description: "节点预设类型",
|
||||
},
|
||||
},
|
||||
required: ["name"],
|
||||
},
|
||||
},
|
||||
];
|
||||
return res.end(JSON.stringify({ tools }));
|
||||
}
|
||||
if (req.url === "/call-tool" && req.method === "POST") {
|
||||
try {
|
||||
const { name, arguments: args } = JSON.parse(body);
|
||||
|
||||
addLog("mcp", `REQ -> [${name}] ${JSON.stringify(args)}`);
|
||||
|
||||
this.handleMcpCall(name, args, (err, result) => {
|
||||
// 3. 构建 MCP 标准响应格式
|
||||
const response = {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: err
|
||||
? `Error: ${err}`
|
||||
: typeof result === "object"
|
||||
? JSON.stringify(result, null, 2)
|
||||
: result,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// 4. 记录返回日志
|
||||
if (err) {
|
||||
addLog("error", `RES <- [${name}] Failed: ${err}`);
|
||||
} else {
|
||||
// 日志里只显示简短的返回值,防止长 JSON(如 hierarchy)刷屏
|
||||
const logRes = typeof result === "object" ? "[Object Data]" : result;
|
||||
addLog("success", `RES <- [${name}] Success: ${logRes}`);
|
||||
}
|
||||
res.end(JSON.stringify(response));
|
||||
});
|
||||
} catch (e) {
|
||||
addLog("error", `Parse Error: ${e.message}`);
|
||||
res.end(JSON.stringify({ content: [{ type: "text", text: `Error: ${e.message}` }] }));
|
||||
}
|
||||
} else {
|
||||
res.statusCode = 404;
|
||||
res.end(JSON.stringify({ error: "Not Found" }));
|
||||
}
|
||||
} catch (e) {
|
||||
res.statusCode = 500;
|
||||
res.end(JSON.stringify({ error: e.message }));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
mcpServer.listen(port, () => {
|
||||
serverConfig.active = true;
|
||||
addLog("success", `Server started on port ${port}`);
|
||||
Editor.Ipc.sendToPanel("mcp-bridge", "mcp-bridge:state-changed", serverConfig);
|
||||
});
|
||||
|
||||
mcpServer.on("error", (err) => {
|
||||
addLog("error", `Server Error: ${err.message}`);
|
||||
this.stopServer();
|
||||
});
|
||||
// 启动成功后顺便存一下端口
|
||||
this.getProfile().set("last-port", port);
|
||||
this.getProfile().save();
|
||||
} catch (e) {
|
||||
addLog("error", `Failed to start server: ${e.message}`);
|
||||
}
|
||||
},
|
||||
|
||||
stopServer() {
|
||||
if (mcpServer) {
|
||||
mcpServer.close();
|
||||
mcpServer = null;
|
||||
serverConfig.active = false;
|
||||
addLog("warn", "MCP Server stopped");
|
||||
Editor.Ipc.sendToPanel("mcp-bridge", "mcp-bridge:state-changed", serverConfig);
|
||||
}
|
||||
},
|
||||
|
||||
// 统一处理逻辑,方便日志记录
|
||||
handleMcpCall(name, args, callback) {
|
||||
switch (name) {
|
||||
case "get_selected_node":
|
||||
const ids = Editor.Selection.curSelection("node");
|
||||
callback(null, ids);
|
||||
break;
|
||||
|
||||
case "set_node_name":
|
||||
Editor.Scene.callSceneScript(
|
||||
"mcp-bridge",
|
||||
"set-property",
|
||||
{
|
||||
id: args.id,
|
||||
path: "name",
|
||||
value: args.newName,
|
||||
},
|
||||
callback,
|
||||
);
|
||||
break;
|
||||
|
||||
case "save_scene":
|
||||
Editor.Ipc.sendToMain("scene:save-scene");
|
||||
callback(null, "Scene saved successfully");
|
||||
break;
|
||||
|
||||
case "get_scene_hierarchy":
|
||||
Editor.Scene.callSceneScript("mcp-bridge", "get-hierarchy", callback);
|
||||
break;
|
||||
|
||||
case "update_node_transform":
|
||||
Editor.Scene.callSceneScript("mcp-bridge", "update-node-transform", args, callback);
|
||||
break;
|
||||
|
||||
case "create_scene":
|
||||
const sceneUrl = `db://assets/${args.sceneName}.fire`;
|
||||
if (Editor.assetdb.exists(sceneUrl)) {
|
||||
return callback("Scene already exists");
|
||||
}
|
||||
Editor.assetdb.create(sceneUrl, getNewSceneTemplate(), (err) => {
|
||||
callback(err, err ? null : `Standard Scene created at ${sceneUrl}`);
|
||||
});
|
||||
break;
|
||||
|
||||
case "create_prefab":
|
||||
const prefabUrl = `db://assets/${args.prefabName}.prefab`;
|
||||
Editor.Ipc.sendToMain("scene:create-prefab", args.nodeId, prefabUrl);
|
||||
callback(null, `Command sent: Creating prefab '${args.prefabName}'`);
|
||||
break;
|
||||
|
||||
case "open_scene":
|
||||
const openUuid = Editor.assetdb.urlToUuid(args.url);
|
||||
if (openUuid) {
|
||||
Editor.Ipc.sendToMain("scene:open-by-uuid", openUuid);
|
||||
callback(null, `Success: Opening scene ${args.url}`);
|
||||
} else {
|
||||
callback(`Could not find asset with URL ${args.url}`);
|
||||
}
|
||||
break;
|
||||
|
||||
case "create_node":
|
||||
Editor.Scene.callSceneScript("mcp-bridge", "create-node", args, callback);
|
||||
break;
|
||||
|
||||
default:
|
||||
callback(`Unknown tool: ${name}`);
|
||||
break;
|
||||
}
|
||||
},
|
||||
// 暴露给 MCP 或面板的 API 封装
|
||||
messages: {
|
||||
"open-test-panel"() {
|
||||
Editor.Panel.open("mcp-bridge");
|
||||
},
|
||||
|
||||
// 获取当前选中节点信息
|
||||
"get-selected-info"(event) {
|
||||
let selection = Editor.Selection.curSelection("node");
|
||||
if (event) event.reply(null, selection);
|
||||
return selection;
|
||||
"get-server-state"(event) {
|
||||
event.reply(null, { config: serverConfig, logs: logBuffer });
|
||||
},
|
||||
"toggle-server"(event, port) {
|
||||
if (serverConfig.active) this.stopServer();
|
||||
else this.startServer(port);
|
||||
},
|
||||
"clear-logs"() {
|
||||
logBuffer = [];
|
||||
addLog("info", "Logs cleared");
|
||||
},
|
||||
|
||||
// 修改场景中的节点(需要通过 scene-script)
|
||||
"set-node-property"(event, args) {
|
||||
Editor.log("Calling scene script with:", args); // 打印日志确认 main 进程收到了面板的消息
|
||||
|
||||
addLog("mcp", `Creating node: ${args.name} (${args.type})`);
|
||||
// 确保第一个参数 'mcp-bridge' 和 package.json 的 name 一致
|
||||
Editor.Scene.callSceneScript("mcp-bridge", "set-property", args, (err, result) => {
|
||||
if (err) {
|
||||
@@ -78,279 +390,27 @@ module.exports = {
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
// 简易 MCP 桥接服务器
|
||||
startMcpServer() {
|
||||
this.server = http.createServer((req, res) => {
|
||||
// 设置 CORS 方便调试
|
||||
res.setHeader("Access-Control-Allow-Origin", "*");
|
||||
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
|
||||
if (req.method === "OPTIONS") {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
let body = "";
|
||||
req.on("data", (chunk) => {
|
||||
body += chunk;
|
||||
"create-node"(event, args) {
|
||||
addLog("mcp", `Creating node: ${args.name} (${args.type})`);
|
||||
Editor.Scene.callSceneScript("mcp-bridge", "create-node", args, (err, result) => {
|
||||
if (err) addLog("error", `CreateNode Failed: ${err}`);
|
||||
else addLog("success", `Node Created: ${result}`);
|
||||
event.reply(err, result);
|
||||
});
|
||||
req.on("end", () => {
|
||||
try {
|
||||
// 简单的路由处理
|
||||
if (req.url === "/list-tools" && req.method === "GET") {
|
||||
// 1. 返回工具定义 (符合 MCP 规范)
|
||||
const tools = [
|
||||
{
|
||||
name: "get_selected_node",
|
||||
description: "获取当前编辑器中选中的节点 ID",
|
||||
inputSchema: { type: "object", properties: {} },
|
||||
},
|
||||
{
|
||||
name: "set_node_name",
|
||||
description: "修改指定节点的名称",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: { type: "string", description: "节点的 UUID" },
|
||||
newName: { type: "string", description: "新的节点名称" },
|
||||
},
|
||||
required: ["id", "newName"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "save_scene",
|
||||
description: "保存当前场景的修改",
|
||||
inputSchema: { type: "object", properties: {} },
|
||||
},
|
||||
{
|
||||
name: "get_scene_hierarchy",
|
||||
description: "获取当前场景的完整节点树结构(包括 UUID、名称和层级关系)",
|
||||
inputSchema: { type: "object", properties: {} },
|
||||
},
|
||||
{
|
||||
name: "update_node_transform",
|
||||
description: "修改节点的坐标、缩放或颜色",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: { type: "string", description: "节点 UUID" },
|
||||
x: { type: "number" },
|
||||
y: { type: "number" },
|
||||
scaleX: { type: "number" },
|
||||
scaleY: { type: "number" },
|
||||
color: { type: "string", description: "HEX 颜色代码如 #FF0000" },
|
||||
},
|
||||
required: ["id"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create_scene",
|
||||
description: "在 assets 目录下创建一个新的场景文件",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
sceneName: { type: "string", description: "场景名称" },
|
||||
},
|
||||
required: ["sceneName"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create_prefab",
|
||||
description: "将场景中的某个节点保存为预制体资源",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
nodeId: { type: "string", description: "节点 UUID" },
|
||||
prefabName: { type: "string", description: "预制体名称" },
|
||||
},
|
||||
required: ["nodeId", "prefabName"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "open_scene",
|
||||
description: "在编辑器中打开指定的场景文件",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
url: {
|
||||
type: "string",
|
||||
description: "场景资源路径,如 db://assets/NewScene.fire",
|
||||
},
|
||||
},
|
||||
required: ["url"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create_node",
|
||||
description: "在当前场景中创建一个新节点",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
name: { type: "string", description: "节点名称" },
|
||||
parentId: {
|
||||
type: "string",
|
||||
description: "父节点 UUID (可选,不传则挂在场景根部)",
|
||||
},
|
||||
type: {
|
||||
type: "string",
|
||||
enum: ["empty", "sprite", "label"],
|
||||
description: "节点预设类型",
|
||||
},
|
||||
},
|
||||
required: ["name"],
|
||||
},
|
||||
},
|
||||
];
|
||||
return res.end(JSON.stringify({ tools }));
|
||||
}
|
||||
if (req.url === "/call-tool" && req.method === "POST") {
|
||||
// 2. 执行工具逻辑
|
||||
const { name, arguments: args } = JSON.parse(body);
|
||||
|
||||
if (name === "get_selected_node") {
|
||||
let ids = Editor.Selection.curSelection("node");
|
||||
res.end(JSON.stringify({ content: [{ type: "text", text: JSON.stringify(ids) }] }));
|
||||
} else if (name === "set_node_name") {
|
||||
Editor.Scene.callSceneScript(
|
||||
"mcp-bridge",
|
||||
"set-property",
|
||||
{
|
||||
id: args.id,
|
||||
path: "name",
|
||||
value: args.newName,
|
||||
},
|
||||
(err, result) => {
|
||||
res.end(
|
||||
JSON.stringify({
|
||||
content: [
|
||||
{ type: "text", text: err ? `Error: ${err}` : `Success: ${result}` },
|
||||
],
|
||||
}),
|
||||
);
|
||||
},
|
||||
);
|
||||
} else if (name === "save_scene") {
|
||||
// 触发编辑器保存指令
|
||||
Editor.Ipc.sendToMain("scene:save-scene");
|
||||
res.end(JSON.stringify({ content: [{ type: "text", text: "Scene saved successfully" }] }));
|
||||
} else if (name === "get_scene_hierarchy") {
|
||||
Editor.Scene.callSceneScript("mcp-bridge", "get-hierarchy", (err, hierarchy) => {
|
||||
if (err) {
|
||||
res.end(
|
||||
JSON.stringify({
|
||||
content: [
|
||||
{ type: "text", text: "Error fetching hierarchy: " + err.message },
|
||||
],
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
res.end(
|
||||
JSON.stringify({
|
||||
content: [{ type: "text", text: JSON.stringify(hierarchy, null, 2) }],
|
||||
}),
|
||||
);
|
||||
}
|
||||
});
|
||||
} else if (name === "update_node_transform") {
|
||||
Editor.Scene.callSceneScript("mcp-bridge", "update-node-transform", args, (err, result) => {
|
||||
res.end(
|
||||
JSON.stringify({
|
||||
content: [{ type: "text", text: err ? `Error: ${err}` : result }],
|
||||
}),
|
||||
);
|
||||
});
|
||||
} else if (name === "create_scene") {
|
||||
const url = `db://assets/${args.sceneName}.fire`;
|
||||
if (Editor.assetdb.exists(url)) {
|
||||
return res.end(
|
||||
JSON.stringify({
|
||||
content: [{ type: "text", text: "Error: Scene already exists" }],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// 生成标准场景内容
|
||||
const sceneJson = getNewSceneTemplate();
|
||||
|
||||
Editor.assetdb.create(url, sceneJson, (err, results) => {
|
||||
if (err) {
|
||||
res.end(
|
||||
JSON.stringify({
|
||||
content: [{ type: "text", text: "Error creating scene: " + err }],
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
res.end(
|
||||
JSON.stringify({
|
||||
content: [{ type: "text", text: `Standard Scene created at ${url}` }],
|
||||
}),
|
||||
);
|
||||
}
|
||||
});
|
||||
} else if (name === "create_prefab") {
|
||||
const url = `db://assets/${args.prefabName}.prefab`;
|
||||
// 2.4.x 创建预制体的 IPC 消息
|
||||
Editor.Ipc.sendToMain("scene:create-prefab", args.nodeId, url);
|
||||
res.end(
|
||||
JSON.stringify({
|
||||
content: [
|
||||
{ type: "text", text: `Command sent: Creating prefab '${args.prefabName}'` },
|
||||
],
|
||||
}),
|
||||
);
|
||||
} else if (name === "open_scene") {
|
||||
const url = args.url;
|
||||
// 1. 将 db:// 路径转换为 UUID
|
||||
const uuid = Editor.assetdb.urlToUuid(url);
|
||||
|
||||
if (uuid) {
|
||||
// 2. 发送核心 IPC 消息给主进程
|
||||
// scene:open-by-uuid 是编辑器内置的场景打开逻辑
|
||||
Editor.Ipc.sendToMain("scene:open-by-uuid", uuid);
|
||||
|
||||
res.end(
|
||||
JSON.stringify({
|
||||
content: [
|
||||
{ type: "text", text: `Success: Opening scene ${url} (UUID: ${uuid})` },
|
||||
],
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
res.end(
|
||||
JSON.stringify({
|
||||
content: [
|
||||
{ type: "text", text: `Error: Could not find asset with URL ${url}` },
|
||||
],
|
||||
}),
|
||||
);
|
||||
}
|
||||
} else if (name === "create_node") {
|
||||
// 转发给场景脚本处理
|
||||
Editor.Scene.callSceneScript("mcp-bridge", "create-node", args, (err, result) => {
|
||||
res.end(
|
||||
JSON.stringify({
|
||||
content: [
|
||||
{ type: "text", text: err ? `Error: ${err}` : `Node created: ${result}` },
|
||||
],
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
res.statusCode = 404;
|
||||
res.end(JSON.stringify({ error: "Not Found" }));
|
||||
}
|
||||
} catch (e) {
|
||||
res.statusCode = 500;
|
||||
res.end(JSON.stringify({ error: e.message }));
|
||||
}
|
||||
},
|
||||
"get-server-state"(event) {
|
||||
let profile = this.getProfile();
|
||||
event.reply(null, {
|
||||
config: serverConfig,
|
||||
logs: logBuffer,
|
||||
autoStart: profile.get("auto-start"), // 返回自动启动状态
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
this.server.listen(3456);
|
||||
Editor.log("MCP Server standard interface listening on http://localhost:3456");
|
||||
"set-auto-start"(event, value) {
|
||||
this.getProfile().set("auto-start", value);
|
||||
this.getProfile().save();
|
||||
addLog("info", `Auto-start set to: ${value}`);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user