图书馆员MCP服务器
Knowledge at your fingertips
概述
图书管理员是一个模型上下文协议(MCP)服务器,它提供了一个API,用于列出、搜索和检索以结构化方式存储的降价文件。它作为大型语言模型(LLM)的知识库,根据需要为他们提供所需的信息。
Librarian不提供任何写入操作,它是一种只读服务,旨在通过MCP框架高效地将文档内容传递给LLM。
特性
- 结构化文档组织:文件按章节组织(例如。,
daisyui/components/button.md) - 基于标签的过滤:按frontmatter中定义的标签筛选文档
- 分层标记继承:标签继承自父目录
- 灵活的搜索功能:
- 简单字符串搜索(不区分大小写) - 带有可自定义标志的正则表达式搜索
- 高效的文档检索:按路径快速访问特定文档
- 标签发现:列出所有可用标签,包括使用计数和可选文件路径
- MCP集成:与模型上下文协议无缝集成
项目结构
图书馆员MCP服务器由模块化组件组成:
- src/lib/config.ts:配置的类型定义和加载器
- src/lib/load.ts:文档加载和处理功能
- src/lib/librarian.ts:使用模式实现核心库管理员
- src/lib/util.ts:纯文本响应的格式化实用程序
- src/lib/server.ts:MCP服务器实现
- src/bin.ts:CLI入口点
- src/index.ts:图书馆入口点
这种模块化设计允许轻松扩展和维护,并明确分离关注点。
安装
先决条件
- Node.js(v14或更高版本)
- npm或pnpm
安装步骤
# Clone the repository
git clone https://github.com/yourusername/mcp-server-librarian.git
cd mcp-server-librarian
# Install dependencies
pnpm install
# Build the project
pnpm build配置
文档文件夹路径可以使用以下方法配置(按优先级顺序):
命令行参数
node dist/bin.js --docs-root /path/to/your/docs环境变量
LIBRARIAN_DOCS_ROOT=/path/to/your/docs node dist/bin.js文档结构
组织
文档按章节组织,遵循层次结构:
/
├── daisyui/
│ ├── index.md # DaisyUI section info with tags
│ └── components/
│ ├── index.md # Components section info with tags
│ ├── button.md # Document with specific tags
│ └── card.md # Another document with specific tags
└── tailwind4/
├── index.md # Tailwind section info with tags
└── getting-started.md # Document with specific tags前台
每个markdown文档都可以包含frontmatter和 tags 字段:
---
tags: ["frontend", "ui", "button"]
---
# Button Component
This document describes the button component...标签继承
标签通过文件夹层次结构继承:
- 文档继承了来自的所有标签
index.md父目录中的文件 - 标签从最通用(根)合并到最具体(文档)
例如,如果我们有:
/daisyui/index.md带有标签:["ui"]/daisyui/components/index.md带有标签:["components"]/daisyui/components/button.md带有标签:["interactive", "form"]
然后 /daisyui/components/button.md 将有效地拥有所有标签: ["documentation", "ui", "components", "interactive", "form"]
文件夹描述
您可以通过创建 index.md 该文件夹中的文件。此文件可以包含frontmatter(带标签)和描述该部分目的的内容。
api参考
图书馆员MCP服务器提供以下工具:
getDocuments
按路径检索多个文档。
参数:
filepaths:要检索的文件路径数组
答复:
**/path/to/document1.md**
- tags: tag1, tag2, tag3
======
Document 1 content
======
**/path/to/document2.md**
- tags: tag1, tag4, tag5
======
Document 2 content
======getDocument
按路径检索特定文档。
参数:
filepath:文档的路径
答复:
**/path/to/document.md**
- tags: tag1, tag2, tag3
======
Document content
======list文档
列出所有文档,并可选择按目录和标签进行筛选。
参数:
directory(可选):列出文档的目录路径(默认:“/”)tags(可选):要筛选的标记数组(默认值:\[\])includeContents(可选):是否在结果中包含文档内容(默认:false)depth(可选):要遍历的最大目录深度(-1表示无限,默认值:-1)
答复: (当 includeContents 是假的)
- /path/to/document1.md
- tags: tag1, tag2, tag3
- /path/to/document2.md
- tags: tag1, tag4, tag5
...答复: (当 includeContents 是真的)
**/path/to/document1.md**
- tags: tag1, tag2, tag3
======
Document 1 content
======
**/path/to/document2.md**
- tags: tag1, tag4, tag5
======
Document 2 content
======搜索文档
使用字符串或正则表达式模式搜索文档内容。
参数:
query:搜索查询(字符串或正则表达式模式)mode(可选):搜索模式(“string”或“regex”,默认:“string”)caseSensitive(可选):搜索是否应区分大小写(默认值:false)directory(可选):要搜索的目录路径(默认值:“/”)tags(可选):要筛选的标记数组(默认值:\[\])includeContents(可选):是否在结果中包含文档内容(默认:false)depth(可选):要遍历的最大目录深度(-1表示无限,默认值:-1)
答复: (当 includeContents 是假的)
- /path/to/document1.md
- tags: tag1, tag2, tag3
- /path/to/document2.md
- tags: tag1, tag4, tag5
...答复: (当 includeContents 是真的)
**/path/to/document1.md**
- tags: tag1, tag2, tag3
======
Document 1 content
======
**/path/to/document2.md**
- tags: tag1, tag4, tag5
======
Document 2 content
======列表标签
列出所有带有计数和可选文件路径的标签。
参数:
directory(可选):列出标签的目录路径(默认:“/”)includeFilepaths(可选):是否在结果中包含文件路径(默认值:false)depth(可选):要遍历的最大目录深度(-1表示无限,默认值:-1)
答复: (当 includeFilepaths 是假的)
- tag1 (5)
- tag2 (3)
- tag3 (2)
...答复: (当 includeFilepaths 是真的)
- tag1 (5)
- /path/to/document1.md
- /path/to/document2.md
- ...
- tag2 (3)
- /path/to/document3.md
- ...使用示例
启动服务器
# Start with default configuration
node dist/bin.js
# Start with custom docs directory
node dist/bin.js --docs-root ./my-documentation
# Start with environment variable
LIBRARIAN_DOCS_ROOT=./my-documentation node dist/bin.js查询示例
列出文档
// List all documents
const allDocs = await mcp.useTool("librarian", "listDocuments", {});
// List documents in a specific directory
const uiDocs = await mcp.useTool("librarian", "listDocuments", {
directory: "/daisyui/components",
});
// List documents with specific tags
const buttonDocs = await mcp.useTool("librarian", "listDocuments", {
tags: ["button", "interactive"],
});
// List documents with depth limit
const topLevelDocs = await mcp.useTool("librarian", "listDocuments", {
directory: "/daisyui",
depth: 1, // Only include direct children, not nested subdirectories
});搜索文档
// Simple string search
const results = await mcp.useTool("librarian", "searchDocuments", {
query: "button styling",
});
// Regex search
const regexResults = await mcp.useTool("librarian", "searchDocuments", {
query: "\\bbutton\\b.*\\bstyle\\b",
mode: "regex",
caseSensitive: true,
includeContents: true,
});
// Search with tag filtering
const filteredResults = await mcp.useTool("librarian", "searchDocuments", {
query: "installation",
tags: ["tutorial"],
directory: "/tailwind4",
});
// Search with depth limit
const topLevelResults = await mcp.useTool("librarian", "searchDocuments", {
query: "component",
directory: "/daisyui",
depth: 1, // Only search in direct children, not nested subdirectories
});检索文档
// Get a specific document
const document = await mcp.useTool("librarian", "getDocument", {
filepath: "/daisyui/components/button.md",
});检索多个文档
// Get multiple specific documents
const documents = await mcp.useTool("librarian", "getDocuments", {
filepaths: ["/daisyui/components/button.md", "/daisyui/components/card.md"],
});列表标签
// List all tags
const allTags = await mcp.useTool("librarian", "listTags", {});
// List tags in a specific directory
const tailwindTags = await mcp.useTool("librarian", "listTags", {
directory: "/tailwind",
});
// List tags with filepaths
const tagsWithFiles = await mcp.useTool("librarian", "listTags", {
includeFilepaths: true,
});
// List tags with depth limit
const topLevelTags = await mcp.useTool("librarian", "listTags", {
directory: "/daisyui",
depth: 1, // Only include tags from direct children, not nested subdirectories
});与LLM集成
Librarian旨在通过模型上下文协议与LLM无缝协作。以下是法学硕士如何使用图书馆员:
- 标签发现LLM可以列出可用的标签来理解知识分类
- 文档发现:法学硕士可以列出可用的文件,以了解可用的知识
- 搜索:当LLM需要特定信息时,它可以在文档中搜索
- 检索:一旦LLM识别出相关文档,它就可以检索其全部内容
- 上下文构建:LLM可以使用检索到的内容来构建生成响应的上下文
错误处理
图书管理员使用标准的MCP错误响应,并附上适当的错误代码和消息:
INVALID_ARGUMENT:当提供的参数无效时NOT_FOUND:当请求的文档或目录不存在时INTERNAL:用于意外的服务器错误
每个错误响应包括:
- 错误代码
- 描述性信息
- 调试的可选详细信息
故障排除
常见问题
找不到文档
如果你得到 NOT_FOUND 错误:
- 检查文档路径是否正确
- 确认
--docs-root指向正确的目录 - 确保文件权限允许服务器读取文件
搜索未返回任何结果
如果搜索未返回预期结果:
- 检查查询语法是否正确(尤其是正则表达式搜索)
- 验证文档是否包含预期内容
- 尝试拓宽搜索词或使用更简单的模式
标签筛选不起作用
如果标签筛选未按预期工作:
- 验证标签在frontmatter中的定义是否正确
- 检查继承层次结构,了解哪些标签适用于哪些文档
- 确保标签名称完全匹配(标签区分大小写)
许可证
此项目根据MIT许可证获得许可-有关详细信息,请参阅许可证文件。
贡献
欢迎投稿!请随时提交拉取请求。
90%的氛围编码。这个代码质量不是我的。我可以更慢地编写更好的代码:)
