Skip to main content
Glama
little2512
by little2512
server-basic.js10.4 kB
#!/usr/bin/env node import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, ListResourcesRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; import fs from 'fs-extra'; import path from 'path'; import mammoth from 'mammoth'; const server = new Server( { name: "word-doc-reader", version: "1.0.0", }, { capabilities: { tools: {}, resources: {}, }, } ); // 内存存储用于保存读取的文档内容 const documentMemory = new Map(); const uiComponentMemory = new Map(); // 工具定义 server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "read_word_document", description: "读取Word文档内容并存储到内存中", inputSchema: { type: "object", properties: { filePath: { type: "string", description: "Word文档的文件路径" }, memoryKey: { type: "string", description: "用于存储的内存键名,便于后续检索", default: "default" }, documentType: { type: "string", description: "文档类型,如 'ui-component', 'api-doc', 'common-doc'", enum: ["ui-component", "api-doc", "common-doc", "other"], default: "common-doc" } }, required: ["filePath"] } }, { name: "list_stored_documents", description: "列出所有已存储到内存的文档", inputSchema: { type: "object", properties: { documentType: { type: "string", description: "筛选特定类型的文档", enum: ["ui-component", "api-doc", "common-doc", "other"] } } } }, { name: "get_stored_document", description: "获取已存储的文档内容", inputSchema: { type: "object", properties: { memoryKey: { type: "string", description: "要获取的文档内存键名" } }, required: ["memoryKey"] } }, { name: "search_in_documents", description: "在已存储的文档中搜索内容", inputSchema: { type: "object", properties: { query: { type: "string", description: "搜索关键词" }, documentType: { type: "string", description: "限制搜索的文档类型", enum: ["ui-component", "api-doc", "common-doc", "other"] } }, required: ["query"] } }, { name: "clear_memory", description: "清除指定的内存内容", inputSchema: { type: "object", properties: { memoryKey: { type: "string", description: "要清除的内存键名,如果不提供则清除所有" } } } } ] }; }); // 工具执行 server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case "read_word_document": { const { filePath, memoryKey = "default", documentType = "common-doc" } = args; if (!fs.existsSync(filePath)) { throw new Error(`文件不存在: ${filePath}`); } const fileExt = path.extname(filePath).toLowerCase(); if (fileExt !== '.docx' && fileExt !== '.doc') { throw new Error(`不支持的文件格式: ${fileExt}。仅支持 .docx 和 .doc 文件`); } const result = await mammoth.extractRawText({ path: filePath }); const documentData = { content: result.value, filePath, documentType, timestamp: new Date().toISOString(), memoryKey }; // 根据文档类型存储到不同的内存区域 if (documentType === 'ui-component') { uiComponentMemory.set(memoryKey, documentData); } else { documentMemory.set(memoryKey, documentData); } return { content: [ { type: "text", text: `成功读取并存储Word文档:\n文件路径: ${filePath}\n文档类型: ${documentType}\n内存键: ${memoryKey}\n内容长度: ${result.value.length} 字符\n\n文档内容预览:\n${result.value.substring(0, 500)}...` } ] }; } case "list_stored_documents": { const { documentType } = args; let docs = []; if (!documentType || documentType === "ui-component") { for (const [key, doc] of uiComponentMemory.entries()) { docs.push({ ...doc, memoryKey: key, storage: "ui-component" }); } } if (!documentType || documentType !== "ui-component") { for (const [key, doc] of documentMemory.entries()) { if (!documentType || doc.documentType === documentType) { docs.push({ ...doc, memoryKey: key, storage: "document" }); } } } const docList = docs.map(doc => `- 内存键: ${doc.memoryKey}\n 文件路径: ${doc.filePath}\n 文档类型: ${doc.documentType}\n 存储时间: ${doc.timestamp}\n 内容长度: ${doc.content.length} 字符` ).join('\n\n'); return { content: [ { type: "text", text: `已存储的文档 (${docs.length} 个):\n\n${docList || "暂无存储的文档"}` } ] }; } case "get_stored_document": { const { memoryKey } = args; let doc = uiComponentMemory.get(memoryKey) || documentMemory.get(memoryKey); if (!doc) { throw new Error(`未找到内存键为 "${memoryKey}" 的文档`); } return { content: [ { type: "text", text: `文档内容 (内存键: ${memoryKey}):\n\n${doc.content}` } ] }; } case "search_in_documents": { const { query, documentType } = args; const queryLower = query.toLowerCase(); const results = []; // 搜索UI组件文档 if (!documentType || documentType === "ui-component") { for (const [key, doc] of uiComponentMemory.entries()) { const contentLower = doc.content.toLowerCase(); if (contentLower.includes(queryLower)) { results.push({ memoryKey: key, filePath: doc.filePath, documentType: doc.documentType, matches: extractMatches(doc.content, query) }); } } } // 搜索其他文档 if (!documentType || documentType !== "ui-component") { for (const [key, doc] of documentMemory.entries()) { if (!documentType || doc.documentType === documentType) { const contentLower = doc.content.toLowerCase(); if (contentLower.includes(queryLower)) { results.push({ memoryKey: key, filePath: doc.filePath, documentType: doc.documentType, matches: extractMatches(doc.content, query) }); } } } } const resultsText = results.map(result => `- 内存键: ${result.memoryKey}\n 文件: ${result.filePath}\n 类型: ${result.documentType}\n 匹配内容: ${result.matches.slice(0, 3).join('; ')}...` ).join('\n\n'); return { content: [ { type: "text", text: `搜索结果 "${query}" (找到 ${results.length} 个匹配):\n\n${resultsText || "未找到匹配的内容"}` } ] }; } case "clear_memory": { const { memoryKey } = args; if (memoryKey) { const removedFromUI = uiComponentMemory.delete(memoryKey); const removedFromDoc = documentMemory.delete(memoryKey); if (removedFromUI || removedFromDoc) { return { content: [ { type: "text", text: `已清除内存键 "${memoryKey}" 的内容` } ] }; } else { throw new Error(`未找到内存键 "${memoryKey}" 的内容`); } } else { // 清除所有内存 const count = uiComponentMemory.size + documentMemory.size; uiComponentMemory.clear(); documentMemory.clear(); return { content: [ { type: "text", text: `已清除所有内存内容 (共 ${count} 个文档)` } ] }; } } default: throw new Error(`未知工具: ${name}`); } } catch (error) { return { content: [ { type: "text", text: `错误: ${error.message}` } ], isError: true }; } }); // 辅助函数:提取匹配的内容片段 function extractMatches(content, query, maxMatches = 5) { const lines = content.split('\n'); const matches = []; const queryLower = query.toLowerCase(); for (let i = 0; i < lines.length && matches.length < maxMatches; i++) { if (lines[i].toLowerCase().includes(queryLower)) { const context = lines[i].trim(); if (context.length > 0) { matches.push(context.substring(0, 100)); } } } return matches.length > 0 ? matches : [`包含关键词 "${query}"`]; } // 启动服务器 async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("Word Document Reader MCP server running on stdio"); } main().catch((error) => { console.error("服务器启动失败:", error); process.exit(1); });

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/little2512/word-doc-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server