使用说明
AI运维中心
一个MCP服务器,为AI助手在您的机器上提供安全的沙盒手 --笔记、任务、网页和个人文档语料库上的混合搜索(FTS5+嵌入)。使用TypeScript、SQLite和安全第一的设计构建。
MCP(模型上下文协议) 是允许像Claude Desktop这样的AI客户端调用外部工具的开放标准。此服务器实现它 一个代码库中的两次:通过stdio用于本地客户端,通过HTTP用于远程访问。
它在实践中是什么样子的
一旦连接到Claude Desktop,这样的对话就可以正常工作了:
你: 找到我关于Postgres迁移的笔记,并添加一个任务,以便在周五之前完成。
克劳德: →
rag_search("postgres migration")--语料库中的3个匹配块 →task_create("Finish Postgres migration", due: "2026-07-31")“找到了您的迁移说明——剩下的步骤是索引重建。为周五创建的任务。”
每一步都发生在您配置的沙箱中:Claude只能触摸您允许的notes目录,只能从您允许的主机获取,并且只能通过下面的工具。
工具
| 工具 | 它做什么 |
|---|---|
rag_search |
搜索语料库-- keyword (FTS5), vector (嵌入),或 hybrid (两者均与往复式秩融合融合) |
rag_add_document |
添加或更新文档:自动分块、FTS索引、配置矢量搜索时嵌入 |
rag_stats |
语料库统计:文档、块、嵌入、后端可用性 |
file_read / file_write / file_list |
笔记访问——沙盒化 NOTES_DIR,仅允许扩展 |
web_fetch |
从以下位置获取页面 仅限分配主机,剥去干净的文字(欢呼) |
task_create / task_list / task_complete |
任务存储为简单的、可人工编辑的标记 |
混合搜索 在以下情况下为默认值 OPENAI_API_KEY 设置:FTS5和余弦相似性结果与 互逆排名融合 --基于秩的融合,不需要在bm25和余弦尺度之间进行分数归一化。如果向量后端在查询过程中失败,混合引擎将优雅地降级为关键字结果。
安全模型
LLM的本地工具访问是一个安全问题,而不是其他问题。这里有趣的工程:
- 在经典旁路中幸存下来的路径沙盒。 每一条路都注定要失败
NOTES_DIR;绝对路径,../遍历和兄弟前缀旁路(notesvsnotes-evil--最天真的虫子startsWith支票已被拒绝。扩展满列表在读和写时都是强制的。 - 默认情况下,Web获取被拒绝。
web_fetch拒绝任何不在的主机WEB_ALLOWED_HOSTS.允许主机的子域通过;长相相似(example.com.evil.com)不要。仅限HTTP(S)。 - 协议通道保持干净。 所有日志记录都会进入stderr——在stdio MCP服务器上,stdout属于JSON-RPC,只有一个杂散
console.log腐蚀了溪流。 - 键入故障路径。 持久层返回 从来没有
Result类型而不是投掷;输入通过以下方式进行验证 zod.
所有这一切都被 45个单元测试 正是针对这些属性——遍历尝试、前缀绕过、相似域、协议过滤、秩融合和注册表调度——在节点20和22上的CI中运行。
建筑学
两种运输方式都消耗一个 ToolRegistry --工具定义和调度的单一真实来源,因此stdio和HTTP表面永远不会分开。
flowchart LR
CD[Claude Desktop] -- "stdio (JSON-RPC)" --> REG[ToolRegistry<br/>definitions + dispatch]
RC[Remote client] -- "HTTP :3333" --> REG
REG --> FS["FileService<br/>sandboxed notes"]
REG --> WS["WebService<br/>allowlisted fetch"]
REG --> TS["TaskService<br/>markdown store"]
REG --> RAG["RAGService<br/>keyword | vector | hybrid"]
RAG -- "FTS5 (bm25)" --> POOL["ConnectionPool"]
RAG -- "embeddings + cosine" --> VEC["VectorRAGService"]
VEC --> POOL
RAG -- "RRF fusion" --> RAG
POOL --> DB[("SQLite<br/>docs + chunks<br/>chunks_fts + chunk_vecs")]
src/
server.ts MCP entrypoint (SDK 1.x): wires services into the registry
tools/
registry.ts single source of truth: tool schemas + dispatch
transports/
http-transport.ts thin HTTP facade over the registry: /health, /tools, /call, /status
connectors/
file-service.ts sandboxed file access
web-service.ts allowlisted web fetching + HTML cleaning
task-service.ts markdown-backed task store
rag/
rag-service.ts search facade: keyword / vector / hybrid modes
fusion.ts Reciprocal Rank Fusion (pure, unit-tested)
sqlite-client.ts SQLite persistence: FTS5, chunking, migrations (neverthrow API)
vector-rag-service.ts vector search with OpenAI embeddings
embedding-service.ts embedding generation (text-embedding-3-small)
db/
connection-pool.ts SQLite connection pooling
快速开始
git clone https://github.com/Galiusbro/ai-ops-hub.git && cd ai-ops-hub
npm install
cp .env.example .env # adjust paths and allowlist
npm run build
npm start # stdio only (for Claude Desktop)
npm run start:http # stdio + HTTP facade on :3333
HTTP外观是可选的(--http 旗帜或 HTTP_ENABLED=1)以便MCP客户端可以生成多个服务器实例而不会发生端口冲突。
连接到克劳德桌面
{
"mcpServers": {
"ai-ops-hub": {
"command": "node",
"args": ["/absolute/path/to/dist/server.js"],
"env": {
"NOTES_DIR": "/path/to/your/notes",
"RAG_DB_PATH": "/path/to/your/rag.db"
}
}
}
}
或者通过HTTP与它对话
curl http://localhost:3333/health
curl http://localhost:3333/tools
curl -X POST http://localhost:3333/call \
-H "Content-Type: application/json" \
-d '{"name":"rag_search","arguments":{"query":"postgres migration"}}'
配置
| 变量 | 默认值 | 用途 |
|---|---|---|
NOTES_DIR |
./notes |
文件工具沙盒所在的目录 |
TASKS_FILE |
./tasks.md |
任务工具后面的Markdown文件 |
RAG_DB_PATH |
./data/rag.db |
语料库的SQLite数据库 |
WEB_ALLOWED_HOSTS |
example.com,developer.mozilla.org |
逗号分隔的列表 web_fetch |
HTTP_PORT |
3333 |
HTTP传输端口 |
OPENAI_API_KEY |
-- | 启用矢量+混合搜索(嵌入) |
发展
npm run dev # run from source (tsx)
npm test # vitest unit suite
npm run type-check # tsc --noEmit
npm run lint
路线图
- [x] 基于stdio+HTTP的MCP服务器
- [x] 沙盒文件/网络/任务工具
- [x] 带触发器同步索引的SQLite FTS5语料库
- [x] 安全关键路径+CI的单元测试
- [x] 两个传输之间的共享工具注册表
- [x] 向量搜索:混合模式与互序融合
- [x]
@modelcontextprotocol/sdk1.x - []来自SDK的可流式HTTP传输(替换自定义REST外观)
- []审核日志记录
- []本地嵌入后端作为OpenAI的替代方案
为什么存在
我构建这个是为了从内部理解MCP——协议、传输,以及将LLM安全访问权交给真实机器实际需要什么。它发展成为一个可用的本地第一助理后端:FTS5语料库、沙盒和测试套件是我在生产中重用的部分。
