Files
Project-Caffeine/projects/arabica/sprint1/dist/app.js
2026-03-02 13:39:06 +08:00

143 lines
6.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use strict";
/**
* Project Caffeine
* Copyright (c) 2025-2026 Gitconomy Research
*
* SPDX-License-Identifier: MIT
*
* Contributors:
* - 郭晧 <guohao@gitconomy.org> (Initial Author)
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
const zod_1 = require("zod");
const promptService_1 = require("./services/promptService");
const resourceService_1 = require("./services/resourceService");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
// ==========================================
// 1. 初始化 MCP Server
// ==========================================
const mcpServer = new mcp_js_1.McpServer({
name: "Project-Caffeine-Prompt-Strategy",
version: "1.2.0"
});
// ==========================================
// 2. 注册 Tools (工具) - 赋予大模型主动执行的能力
// ==========================================
// 工具 15 Whys 提示词策略生成
mcpServer.tool("generate_5_whys", "使用 5 Whys 模板对用户查询进行深度分解,生成增强的提示词策略", { query: zod_1.z.string().describe("需要分析的查询主题") }, async ({ query }) => {
console.error(`[Project Caffeine] 大模型调用工具: 正在生成 5 Whys 策略 -> ${query}`);
const enhancedPrompt = (0, promptService_1.generate5Whys)(query);
return {
content: [{ type: "text", text: JSON.stringify(enhancedPrompt, null, 2) }]
};
});
// 工具 2扫描本地知识库目录
mcpServer.tool("list_local_notes", "获取本地 Obsidian 知识库中的所有 Markdown 笔记列表,用于了解当前有哪些可用的本地上下文资料。", {}, async () => {
console.error(`[Project Caffeine] 大模型调用工具: 正在扫描本地笔记列表...`);
const notes = await (0, resourceService_1.listObsidianNotes)();
return {
content: [{
type: "text",
text: notes.length > 0 ? `找到了以下笔记:\n${notes.join('\n')}` : "未找到笔记。"
}]
};
});
// 工具 3阅读指定的单篇笔记内容
mcpServer.tool("read_local_note", "读取本地 Obsidian 知识库中指定笔记的完整内容,作为深度分析的上下文参考。", { filename: zod_1.z.string().describe("需要读取的笔记文件名,必须包含 .md 后缀") }, async ({ filename }) => {
console.error(`[Project Caffeine] 大模型调用工具: 正在深度阅读笔记 -> ${filename}`);
try {
const content = await (0, resourceService_1.readObsidianNote)(filename);
return { content: [{ type: "text", text: content }] };
}
catch (error) {
return {
content: [{ type: "text", text: `读取失败: ${error.message}` }],
isError: true // 明确告知大模型此操作抛出了错误
};
}
});
// ==========================================
// 3. 注册 Resources (资源) - 暴露给客户端供用户手动勾选的静态数据
// ==========================================
// 资源 1知识库目录索引
mcpServer.resource("obsidian-index", // 客户端显示的资源 Name/ID
"obsidian://vault/index", // 唯一的 URI 标识
{
description: "本地知识库的目录索引,包含所有 Markdown 笔记的列表"
}, async (uri) => {
console.error(`[Project Caffeine] 客户端请求静态资源: ${uri.href}`);
const notes = await (0, resourceService_1.listObsidianNotes)();
const textContent = notes.length > 0
? `当前知识库包含以下文件:\n${notes.join('\n')}`
: "当前知识库为空。";
return {
contents: [{
uri: uri.href,
mimeType: "text/plain",
text: textContent
}]
};
});
// ==========================================
// 4. 启动底层 Stdio 传输层
// ==========================================
async function start() {
console.error("[Project Caffeine] 正在启动 TS 版 MCP Server (含 Tools 与 Resources)...");
const transport = new stdio_js_1.StdioServerTransport();
await mcpServer.connect(transport);
console.error("[Project Caffeine] MCP Server 已就绪,等待 Cherry Studio 交互。");
}
// 捕获致命错误并安全退出
start().catch((err) => {
console.error("服务器启动失败:", err);
process.exit(1);
});
// ==========================================
// 💡 5. 日志持久化拦截器 (Linux)
// ==========================================
const logFilePath = path.resolve(__dirname, '../server.log');
const originalConsoleError = console.error;
console.error = (...args) => {
// 1. 在后台输出
originalConsoleError(...args);
// 2. 同时把日志追加写入到项目根目录的 server.log 文件中
const logMessage = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ');
fs.appendFileSync(logFilePath, `[${new Date().toISOString()}] ${logMessage}\n`);
};
//# sourceMappingURL=app.js.map