fix: mcp serve

This commit is contained in:
hypercross 2026-03-18 15:00:13 +08:00
parent 5389345a00
commit e5ce8c20b5
2 changed files with 78 additions and 16 deletions

View File

@ -24,7 +24,7 @@ import {
readResource,
type DocResource
} from '../resources/docs.js';
import { serveCommand } from './serve.js';
import { createContentServer, type ContentServer } from './serve.js';
/**
* MCP
@ -69,12 +69,8 @@ async function mcpServeAction(host: string, options: MCPOptions) {
process.chdir(cwd);
console.error(`MCP 服务器工作目录:${cwd}`);
// 启动 serve 服务器(在后台运行)
console.error('启动预览服务器...');
serveCommand(cwd, { port: '3000' });
// 等待服务器启动
await new Promise(resolve => setTimeout(resolve, 1000));
// 启动内容服务器(预览服务器)
const contentServer: ContentServer = createContentServer(cwd, 3000);
// 动态导入 MCP SDK
const { Server } = await import('@modelcontextprotocol/sdk/server/index.js');
@ -328,7 +324,7 @@ async function mcpServeAction(host: string, options: MCPOptions) {
}
case 'deck_card_crud': {
const params = args as unknown as CardCrudParams;
let params = args as unknown as CardCrudParams;
if (!params.csv_file || !params.action) {
return {
@ -337,6 +333,15 @@ async function mcpServeAction(host: string, options: MCPOptions) {
};
}
// 解析 cards 参数(可能是 JSON 字符串)
if (params.cards && typeof params.cards === 'string') {
try {
params.cards = JSON.parse(params.cards);
} catch (e) {
// 如果不是 JSON保持原样
}
}
const result = cardCrud(params);
return {
@ -465,6 +470,19 @@ async function mcpServeAction(host: string, options: MCPOptions) {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('TTRPG 卡牌生成 MCP 服务器已启动stdio');
// 监听进程退出事件,关闭服务器
process.on('SIGINT', () => {
console.error('\n正在关闭服务器...');
contentServer.close();
process.exit(0);
});
process.on('SIGTERM', () => {
console.error('\n正在关闭服务器...');
contentServer.close();
process.exit(0);
});
} else {
// TODO: 支持 HTTP 传输
console.error('HTTP 传输模式尚未实现,请使用 stdio 模式');

View File

@ -47,7 +47,7 @@ function getMimeType(filePath: string): string {
/**
* .md
*/
function scanDirectory(dir: string): ContentIndex {
export function scanDirectory(dir: string): ContentIndex {
const index: ContentIndex = {};
function scan(currentPath: string, relativePath: string) {
@ -176,10 +176,35 @@ function createRequestHandler(
}
/**
*
*
*/
export const serveCommand: ServeCommandHandler = async (dir, options) => {
const contentDir = resolve(dir);
export interface ContentServer {
/**
* HTTP
*/
server: Server;
/**
*
*/
watcher: ReturnType<typeof watch>;
/**
*
*/
index: ContentIndex;
/**
*
*/
close(): void;
}
/**
*
*/
export function createContentServer(
contentDir: string,
port: number,
distPath: string = distDir,
): ContentServer {
let contentIndex: ContentIndex = {};
// 扫描内容目录生成索引
@ -231,19 +256,38 @@ export const serveCommand: ServeCommandHandler = async (dir, options) => {
// 创建请求处理器
const handleRequest = createRequestHandler(
contentDir,
distDir,
distPath,
() => contentIndex,
);
// 创建 HTTP 服务器
const server = createServer(handleRequest);
const port = parseInt(options.port, 10);
server.listen(port, () => {
console.log(`\n开发服务器已启动http://localhost:${port}`);
console.log(`内容目录:${contentDir}`);
console.log(`静态资源目录:${distDir}`);
console.log(`静态资源目录:${distPath}`);
console.log(`索引文件http://localhost:${port}/__CONTENT_INDEX.json\n`);
});
return {
server,
watcher,
index: contentIndex,
close() {
console.log("关闭内容服务器...");
server.close();
watcher.close();
},
};
}
/**
*
*/
export const serveCommand: ServeCommandHandler = async (dir, options) => {
const contentDir = resolve(dir);
const port = parseInt(options.port, 10);
createContentServer(contentDir, port);
};