API и MCP серверы для интеллектуальной работы с Obsidian vault'ами через RAG (Retrieval-Augmented Generation).
Этот подмодуль предоставляет три основных компонента:
- FastAPI REST API — HTTP endpoints для загрузки vault'ов и запросов к агенту
- MCP Server (stdio) — для интеграции с Claude Desktop и другими MCP клиентами
- MCP Server (HTTP) — HTTP версия MCP сервера для кастомных интеграций
- LangGraph Agent — интеллектуальный агент с рекурсивным расширением контекста
obsidian-rag-api/
├── src/obsidian_rag_api/
│ ├── __init__.py
│ ├── config.py # Конфигурация из переменных окружения
│ ├── vault_manager.py # Управление множественными vault'ами
│ ├── llm.py # Утилиты для работы с LLM
│ ├── server.py # MCP Server (stdio transport)
│ ├── server_http.py # MCP Server (HTTP transport)
│ ├── agent.py # LangGraph агент
│ └── api.py # FastAPI REST endpoints
└── pyproject.toml
Централизованная конфигурация через Pydantic Settings:
OPENAI_API_KEY— ключ для OpenAI APIOPENAI_BASE_URL— опциональный base URL (для совместимых API)OPENAI_MODEL— основная модель (по умолчанию: gpt-4o-mini)OPENAI_CHEAP_MODEL— модель для проверок релевантностиMAX_RECURSION_DEPTH— макс. глубина расширения контекста (по умолчанию: 3)SEARCH_TOP_K— количество результатов поиска (по умолчанию: 5)EMBEDDINGS_MODEL— модель для embeddings (по умолчанию: openai/text-embedding-3-large)NEO4J_URI,NEO4J_USER,NEO4J_PASSWORD— подключение к Neo4jQDRANT_HOST,QDRANT_PORT— подключение к Qdrant
Управление множественными Obsidian vault'ами:
- UUID-based isolation — каждый vault получает уникальный ID
- In-memory storage — vault'ы хранятся в памяти (теряются при перезапуске)
- ObsidianRetriever integration — создает инстанс ObsidianRetriever для каждого vault
Основные методы:
vault_manager = VaultManager()
# Создать новый vault
vault_id = vault_manager.create_vault(retriever: ObsidianRetriever)
# Получить retriever по ID
retriever = vault_manager.get_vault(vault_id: str)
# Список всех vault ID
vault_ids = vault_manager.list_vaults()LangGraph агент с умным RAG и рекурсивным расширением контекста.
START → reformulate → search → check_context ⟷ extend_context → generate_answer → END
class AgentState(TypedDict):
original_query: str # Исходный запрос
vault_id: str # UUID vault'а
reformulated_query: str # Переформулированный запрос
search_results: list[dict] # Результаты поиска
knowledge_base: list[Note] # Накопленные заметки
explored_notes: set[str] # Уже изученные заметки
current_depth: int # Текущая глубина рекурсии
final_answer: str # Итоговый ответ- reformulate — переформулирует запрос для лучшего поиска
- search — семантический поиск в Qdrant
- check_context — проверяет достаточность информации для ответа
- extend_context — параллельно проверяет связанные заметки через LLM
- generate_answer — генерирует финальный ответ
# Создать и скомпилировать граф
graph = create_agent_graph()
# Запустить агент
result = await graph.ainvoke({
"original_query": "Что такое квантовая механика?",
"vault_id": "550e8400-e29b-41d4-a716-446655440000"
})FastAPI REST API с endpoint'ами для работы с vault'ами и агентом.
Загружает ZIP-архив с Obsidian vault.
Request (multipart/form-data):
file— ZIP файлinclude_paths(optional) — пути для включения (через запятую)exclude_paths(optional) — пути для исключенияchunk_size(optional) — размер чанков (по умолчанию: 500)
Response:
{
"vault_id": "550e8400-e29b-41d4-a716-446655440000",
"message": "Vault uploaded successfully",
"status": "success"
}То же самое, но с прогрессом через Server-Sent Events.
SSE события:
{"stage": "extracting", "progress": 15, "message": "...", "elapsed": "2s", "eta": "11s"}
{"stage": "parsing", "progress": 50, "message": "..."}
{"stage": "processing", "progress": 65, "message": "..."}
{"stage": "storing", "progress": 82, "message": "..."}
{"stage": "linking", "progress": 100, "message": "..."}
{"stage": "complete", "vault_id": "...", "notes_count": 42}Возвращает список всех vault ID.
Response:
{
"vaults": ["550e8400-...", "660e9511-..."],
"count": 2
}Запрос к агенту.
Request:
{
"query": "Расскажи про машинное обучение",
"vault_id": "550e8400-e29b-41d4-a716-446655440000",
"thread_id": "optional-session-id"
}Response:
{
"query": "Расскажи про машинное обучение",
"reformulated_query": "machine learning algorithms neural networks",
"answer": "На основе ваших заметок...",
"notes_used": 5,
"max_depth_reached": 2,
"thread_id": "abc123",
"vault_id": "550e8400-e29b-41d4-a716-446655440000"
}Стриминг прогресса агента через SSE.
Request: тот же, что и /agent
SSE события:
{"stage": "reformulating", "message": "Reformulating query..."}
{"stage": "searching", "message": "Found 5 relevant notes"}
{"stage": "extending", "message": "Checking 3 related notes..."}
{"stage": "generating", "message": "Generating final answer..."}
{"stage": "complete", "answer": "...", "notes_used": 8}MCP Server с stdio транспортом для интеграции с Claude Desktop.
| Tool | Описание | Параметры |
|---|---|---|
read_note |
Читает заметку по ID | vault_id, note_id |
search |
Семантический поиск | vault_id, query, top_k |
extend_context_using_nearest |
Расширяет контекст | vault_id, note_id, query |
python -m obsidian_rag_api.serverИли через главный entry point:
python main.py mcpMCP Server с HTTP транспортом (SSE) на порту 8001.
GET /sse— SSE endpoint для MCP протоколаPOST /messages— отправка сообщений серверу
python -m obsidian_rag_api.server_httpИли:
python main.py mcp --httpУтилиты для работы с LLM:
from obsidian_rag_api.llm import get_chat_model, get_cheap_chat_model
# Основная модель
llm = get_chat_model()
# Дешевая модель для проверок
cheap_llm = get_cheap_chat_model()
# Использование
response = llm.invoke("Your prompt here")# Как часть workspace
cd /path/to/obsidian-rag-mcp
uv sync
# Standalone (если опубликован в PyPI)
uv add obsidian-rag-apifrom obsidian_rag_api.vault_manager import VaultManager
from obsidian_rag_api.agent import create_agent_graph
from obsidian_retriever import ObsidianRetriever
# 1. Создать retriever
retriever = ObsidianRetriever(
neo4j_uri="bolt://localhost:7687",
neo4j_user="neo4j",
neo4j_password="password",
qdrant_host="localhost",
qdrant_port=6333,
collection_name="my_vault"
)
# 2. Зарегистрировать vault
vault_manager = VaultManager()
vault_id = vault_manager.create_vault(retriever)
# 3. Использовать агент
graph = create_agent_graph()
result = await graph.ainvoke({
"original_query": "Что такое квантовая механика?",
"vault_id": vault_id
})
print(result["final_answer"])fastapi>=0.124.4
langchain>=1.1.3
langchain-openai>=1.1.3
langgraph>=1.0.5
mcp>=1.24.0
neomodel>=6.0.0
qdrant-client>=1.16.2
sentence-transformers>=5.2.0
uvicorn>=0.38.0
pydantic>=2.12.5
python-dotenv>=1.2.1Создайте .env файл:
# OpenAI
OPENAI_API_KEY=sk-your-key-here
OPENAI_MODEL=gpt-4o-mini
OPENAI_CHEAP_MODEL=gpt-4o-mini
# Agent
MAX_RECURSION_DEPTH=3
SEARCH_TOP_K=5
# Neo4j
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=your-password
# Qdrant
QDRANT_HOST=localhost
QDRANT_PORT=6333
# Embeddings
EMBEDDINGS_MODEL=openai/text-embedding-3-largepython main.py allЭто запустит:
- Agent API на порту 8000
- MCP HTTP на порту 8001
python main.py agentpython main.py mcppython main.py mcp --httpДобавьте в claude_desktop_config.json:
{
"mcpServers": {
"obsidian-rag": {
"command": "docker",
"args": [
"compose", "exec", "-T", "obsidian-rag",
"uv", "run", "python", "main.py", "mcp"
]
}
}
}uv run pytestuv run ruff format .
uv run ruff check --fix .MIT