黑曜石保险库服务器
MCP/REST服务器,用于黑曜石金库管理,具有语义搜索、知识图和结构化数据功能。
特性
核心能力
- 金库摄入:将黑曜石保管库上传为ZIP文件,并保留完整的元数据
- Wiki链接支持:完全解析
[[wiki-links]]带有别名、嵌入、标头和块引用 - 语义搜索:使用pgvector和OpenAI嵌入的基于向量的搜索
- 全文检索:PostgreSQL全文搜索,突出显示
- 知识图谱:通过Apache AGE进行文档连接(Cypher查询)
- 多用户:具有用户隔离的JWT身份验证
结构化数据
- 表格:带有类型列(文本、数字、布尔值、日期、JSON、数组、引用)的用户定义表
- CRUD行:具有过滤和分页功能的完整创建、读取、更新、删除操作
- 关系:支持CASCADE删除的表之间的外键
- CSV导入/导出:具有自动类型推理的批量数据操作
- 文档表链接:文档可以使用以下方式引用表格
[[table:TableName]]语法 - 查询语言:与数据视图兼容的查询(
TABLE,WHERE,SORT,LIMIT)
建筑
- 六边形架构:域、应用程序和基础架构层的清晰分离
- 双接口:用于AI代理集成的REST API和MCP(模型上下文协议)
graph TB
subgraph "Clients"
REST[REST API Clients]
MCP[MCP/AI Agents]
end
subgraph "API Layer"
FastAPI[FastAPI Routes]
MCPTools[MCP Tools]
end
subgraph "Application Layer"
UC[Use Cases]
DTO[DTOs]
end
subgraph "Domain Layer"
E[Entities]
VO[Value Objects]
DS[Domain Services]
end
subgraph "Infrastructure"
PG[(PostgreSQL)]
PGV[(pgvector)]
AGE[(Apache AGE)]
OAI[OpenAI API]
end
REST --> FastAPI
MCP --> MCPTools
FastAPI --> UC
MCPTools --> UC
UC --> E
UC --> DS
DS --> VO
UC --> PG
UC --> PGV
UC --> AGE
UC --> OAI需求
- Python 3.12+
- PostgreSQL 16,带有pgvector和Apache AGE扩展
- OpenAI API密钥(用于语义搜索)
快速开始
1.克隆和安装
cd obsidian_vault_server
# Install dependencies (using uv)
just install-dev
# Or manually
uv sync --dev2.启动基础设施
# Start PostgreSQL with pgvector + Apache AGE
just infra-up
# Or with docker-compose
docker-compose up -d3.配置环境
创建一个 .env 文件:
DATABASE_URL=postgresql+asyncpg://obsidian:obsidian@localhost:5433/obsidian
OPENAI_API_KEY=your-openai-api-key
JWT_SECRET=your-secret-key-min-32-chars
JWT_ISSUER=obsidian-vault-server
MAX_UPLOAD_SIZE_MB=100
ENVIRONMENT=development
CORS_ORIGINS=http://localhost:3000,http://localhost:5173
RATE_LIMIT_ENABLED=true4.运行迁移
just migrate
# Or manually
uv run alembic upgrade head5.启动开发服务器
just dev
# Or manually
uv run uvicorn app.main:app --reload --port 8001服务器将在以下时间可用 http://localhost:8001.
API终点
API版本
- API标准基本路径:
/v1 - 向后兼容性:现有的未版本化端点目前仍然可用。
- 兼容性策略:
- 可以添加新的非中断功能 /v1. - 重大更改需要新版本(例如, /v2). - 未指定的路由被认为是兼容性别名,在未来的主要版本中可能会被弃用。
认证
| 方法 | 端点 | 描述 |
|---|---|---|
| 职位 | /auth/register | 注册新用户 |
| 职位 | /auth/login | 登录并获取JWT代币 |
| 职位 | /auth/refresh | 刷新访问令牌 |
| 得到 | /auth/me | 获取当前用户配置文件 |
拱顶
| 方法 | 端点 | 描述 |
|---|---|---|
| 得到 | /vaults | 列出所有保险库 |
| 职位 | /vaults | 创建vault |
| 得到 | /vaults/{slug} | 获取保险库 |
| 删除 | /vaults/{slug} | 删除vault |
| 职位 | /vaults/{slug}/ingest | 上传ZIP |
| 得到 | /vaults/{slug}/export | 下载ZIP |
文件
| 方法 | 端点 | 描述 |
|---|---|---|
| 得到 | /vaults/{slug}/documents | 列出文件 |
| 职位 | /vaults/{slug}/documents | 创建文档 |
| 得到 | /vaults/{slug}/documents/{id} | 获取文档 |
| 补丁 | /vaults/{slug}/documents/{id} | 更新文档 |
| 删除 | /vaults/{slug}/documents/{id} | 删除文档 |
链接
| 方法 | 端点 | 描述 |
|---|---|---|
| 得到 | /vaults/{slug}/documents/{id}/links/outgoing | 获取外发链接 |
| 得到 | /vaults/{slug}/documents/{id}/links/incoming | 获取反向链接 |
搜索
| 方法 | 端点 | 描述 |
|---|---|---|
| 职位 | /vaults/{slug}/search/semantic | 语义搜索(需要嵌入) |
| 得到 | /vaults/{slug}/search/fulltext | 全文搜索 |
图
| 方法 | 端点 | 描述 |
|---|---|---|
| 得到 | /vaults/{slug}/graph/connections/{id} | 获取文档连接 |
| 得到 | /vaults/{slug}/graph/hubs | 获取连接最多的文档 |
| 得到 | /vaults/{slug}/graph/orphans | 获取没有连接的文档 |
| 得到 | /vaults/{slug}/graph/path | 获取文档之间的最短路径 |
表(结构化数据)
| 方法 | 端点 | 描述 |
|---|---|---|
| 得到 | /vaults/{slug}/tables | 列出所有表格 |
| 职位 | /vaults/{slug}/tables | 使用架构创建表 |
| 得到 | /vaults/{slug}/tables/{table} | 获取表架构 |
| 补丁 | /vaults/{slug}/tables/{table} | 更新表格 |
| 删除 | /vaults/{slug}/tables/{table} | 删除表(级联行) |
表格行
| 方法 | 端点 | 描述 |
|---|---|---|
| 得到 | /vaults/{slug}/tables/{table}/rows | 列出行(带筛选器) |
| 职位 | /vaults/{slug}/tables/{table}/rows | 创建行 |
| 得到 | /vaults/{slug}/tables/{table}/rows/{id} | 获取行 |
| 补丁 | /vaults/{slug}/tables/{table}/rows/{id} | 更新行 |
| 删除 | /vaults/{slug}/tables/{table}/rows/{id} | 删除行 |
CSV导入/导出
| 方法 | 端点 | 描述 |
|---|---|---|
| 职位 | /vaults/{slug}/tables/import/csv | 将CSV导入为新表 |
| 职位 | /vaults/{slug}/tables/{table}/import/csv | 将CSV附加到表中 |
| 得到 | /vaults/{slug}/tables/{table}/export/csv | 将表格导出为CSV |
文档表查询
| 方法 | 端点 | 描述 |
|---|---|---|
| 得到 | /vaults/{slug}/documents/{id}/tables | 获取文档引用的表 |
| 得到 | /vaults/{slug}/tables/{table}/documents | 获取文档引用表 |
| 职位 | /vaults/{slug}/documents/{id}/query | 执行数据视图样式查询 |
行筛选查询参数
?filter[column]=value # Equality
?filter[column][gt]=value # Greater than
?filter[column][lt]=value # Less than
?filter[column][like]=pattern # LIKE match
?sort=column&order=asc|desc # Sorting
?limit=50&offset=0 # Pagination
?q=search_term # Full-text search数据视图查询语法
TABLE name, email FROM Contacts WHERE status = 'active' SORT name ASC LIMIT 10支持条款:
TABLE col1, col2 FROM table_name-选择列WHERE column = value-过滤器(=,!=,>,\|MCP Protocol| Tools
Tools --> Docs Tools --> Search Tools --> Graph Tools --> Tables
### 文档工具
|工具|说明|
|------|-------------|
| `list_vaults` |列出当前用户的所有保管库|
| `list_documents` |列出vault中的文档并进行分页|
| `get_document` |按路径或ID获取文档内容|
| `get_backlinks` |获取文档的传入链接|
### 搜索工具
|工具|说明|
|------|-------------|
| `search_documents` |跨文档的语义或全文搜索|
### 图形工具
|工具|说明|
|------|-------------|
| `get_connections` |在N个跃点内获取已连接的文档|
### 结构化数据工具
|工具|说明|
|------|-------------|
| `list_tables` |列出vault中的所有表|
| `get_table` |获取表架构和列定义|
| `list_table_rows` |列出具有过滤、排序和分页功能的行|
| `get_table_row` |按ID获取特定行|
| `query_table` |执行数据视图样式查询|
### MCP配置
添加到MCP客户端配置中:
{ "mcpServers": { "obsidian-vault": { "command": "uv", "args": ["run", "python", "-m", "app.mcp_server"], "env": { "DATABASE_URL": "postgresql+asyncpg://...", "JWT_SECRET": "your-secret" } } } }
## 发展
Run tests
just test
Run tests with coverage
just test-cov
Run linting
just lint
Run type checking
just typecheck
Format code
just format
## 建筑
项目如下 **六边形建筑** (端口和适配器):
app/ ├── domain/ # Pure Python - no external dependencies │ ├── entities/ # Business objects (Vault, Document, Tag, etc.) │ ├── value_objects/# Immutable values (WikiLink, Frontmatter, etc.) │ ├── services/ # Domain logic (LinkResolver, TagParser, etc.) │ └── exceptions.py # Domain exceptions │ ├── application/ # Use cases and ports │ ├── interfaces/ # Port definitions (repositories, providers) │ ├── use_cases/ # Application logic │ └── dto/ # Data transfer objects │ ├── infrastructure/ # External adapters │ ├── database/ # PostgreSQL repositories │ ├── pgvector/ # Vector search adapter │ ├── age/ # Apache AGE graph adapter │ └── embedding/ # OpenAI embedding adapter │ └── api/ # HTTP interface ├── routes/ # FastAPI endpoints └── schemas/ # Request/response models
## 数据库模式
erDiagram users ||--o{ vaults : owns vaults ||--o{ documents : contains vaults ||--o{ folders : contains vaults ||--o{ tags : contains vaults ||--o{ data_tables : contains documents ||--o{ document_links : has documents ||--o{ document_tags : has documents ||--o{ embedding_chunks : has documents ||--o{ document_table_links : references data_tables ||--o{ table_rows : contains data_tables ||--o{ table_relationships : has data_tables ||--o{ document_table_links : referenced_by
users { uuid id PK string email UK string password_hash string display_name boolean is_active }
vaults { uuid id PK uuid user_id FK string name string slug UK int document_count }
documents { uuid id PK uuid vault_id FK uuid folder_id FK string title string path text content jsonb frontmatter }
data_tables { uuid id PK uuid vault_id FK string name string slug jsonb schema int row_count }
table_rows { uuid id PK uuid table_id FK uuid vault_id FK jsonb data }
### 核心表
- `users` -具有JWT身份验证的用户帐户
- `vaults` -黑曜石拱顶(每位用户)
- `documents` -带元数据的Markdown文档
- `folders` -文件夹层次结构
- `document_links` -文档之间的Wiki链接
- `tags` -分层标签
- `document_tags` -文档标签关联
### 结构化数据表
- `data_tables` -JSONB模式的表定义
- `table_rows` -JSONB存储的行数据(GIN索引)
- `table_relationships` -表之间的外键定义
- `document_table_links` -从文档到表/行的链接
### 扩展
- `embedding_chunks` -用于语义搜索的pgvector嵌入
- `obsidian_graph` -用于关系查询的Apache AGE图
## 测试
该项目具有全面的测试覆盖范围:
|测试套件|描述|
|------------|-------------|
|单元测试(域)|实体验证、值对象、域服务|
|单元测试(应用程序)|用例、DTO、业务逻辑|
|单元测试(基础设施)|存储库、适配器、MCP工具|
|BDD场景|使用Gherkin语法的特征驱动测试|
|API测试| REST端点集成测试|
|集成测试|全栈数据库|
**总计:433次测试**
Run all tests
just test
Run with coverage
just test-cov
Run specific test suite
uv run pytest tests/unit -v uv run pytest tests/api -v uv run pytest tests/bdd -v
## 许可证
麻省理工学院