# tabula8rasa/obsidian_mcp_rag_server architecture

> Architecture diagram of the GitHub repository tabula8rasa/obsidian_mcp_rag_server, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/tabula8rasa/obsidian_mcp_rag_server
- Repository: https://github.com/tabula8rasa/obsidian_mcp_rag_server

## Overview

This repository provides semantic search over an Obsidian Vault: committed Markdown is loaded, chunked, embedded, and indexed in Qdrant; queries reach the RAG API directly or through an MCP tool and return ranked note fragments. Git-aware sync and full reindex are separate indexing modes. The graph also shows API startup, state, and documented optional monitoring. Source excerpts establish the principal API and MCP calls; unsampled indexing, storage, and monitoring wiring is limited to README-supported relationships.

Main entry points: [`rag-api/app/api/routes.py`](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/api/routes.py) (RAG endpoints), [`rag-api/app/services/vault_sync.py`](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/services/vault_sync.py) (Git-aware sync), [`rag-api/app/infrastructure/qdrant_store.py`](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/infrastructure/qdrant_store.py) (Vector store access), [`rag-api/app/services/vault_loader.py`](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/services/vault_loader.py) (Vault loader)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_indexing["Vault indexing"]
  node_sync["Git-aware sync<br/>[vault_sync.py]"]
  node_loader["Vault loader<br/>[vault_loader.py]"]
  node_chunker["Markdown chunker"]
  node_filtering["Path filtering<br/>[indexing.py]"]
  node_chunk["Note chunk<br/>[chunk.py]"]
  node_embed["Embedding model<br/>[embedding_model.py]"]
end

subgraph group_retrieval["Search API"]
  node_rag_routes["RAG endpoints<br/>[routes.py]"]
  node_rag_main["API startup<br/>[main.py]"]
  node_schemas["Search schemas<br/>[schemas.py]"]
end

subgraph group_mcp["MCP access"]
  node_mcp_main["MCP process<br/>[main.py]"]
  node_mcp_server["MCP composition<br/>[server.py]"]
  node_search_tool["search_vault tool<br/>[vault_search.py]"]
  node_rag_client["RAG API client<br/>[rag_api.py]"]
end

subgraph group_state["Index state"]
  node_qdrant_store["Vector store access<br/>[qdrant_store.py]"]
  node_qdrant[("Qdrant")]
  node_sync_state["Commit state<br/>[vault_sync.py]"]
end

subgraph group_monitoring["Monitoring"]
  node_prometheus["Prometheus<br/>[prometheus.yml]"]
  node_grafana["Grafana dashboards"]
  node_alloy["Alloy collector<br/>[config.alloy]"]
  node_loki[("Loki<br/>[loki-config.yml]")]
end

node_vault["Obsidian Vault"]
node_git[("Vault Git")]
node_api_user(("API caller"))
node_mcp_user(("MCP client"))

node_api_user -->|"calls"| node_rag_routes
node_rag_routes -->|"validates"| node_schemas
node_rag_routes -->|"runs sync"| node_sync
node_rag_routes -->|"searches"| node_qdrant_store
node_rag_main -->|"loads model"| node_embed
node_rag_main -->|"ensures collection"| node_qdrant_store
node_sync -->|"reads commits"| node_git
node_sync -->|"filters paths"| node_filtering
node_sync -->|"loads notes"| node_loader
node_loader -->|"reads Markdown"| node_vault
node_loader -->|"chunks notes"| node_chunker
node_loader -->|"creates chunks"| node_chunk
node_sync -->|"updates index"| node_qdrant_store
node_sync -->|"records commit"| node_sync_state
node_qdrant_store -->|"embeds text"| node_embed
node_qdrant_store -->|"reads and writes"| node_qdrant
node_mcp_user -->|"connects"| node_mcp_main
node_mcp_main -->|"creates"| node_mcp_server
node_mcp_server -->|"registers tool"| node_search_tool
node_search_tool -->|"delegates search"| node_rag_client
node_rag_client -->|"POSTs search"| node_rag_routes
node_rag_routes -->|"returns results"| node_api_user
node_search_tool -->|"returns fragments"| node_mcp_user
node_rag_routes -.->|"exposes metrics"| node_prometheus
node_mcp_server -.->|"exposes metrics"| node_prometheus
node_prometheus -.->|"feeds dashboards"| node_grafana
node_alloy -.->|"ships logs"| node_loki

click node_rag_routes "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/api/routes.py"
click node_rag_main "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/main.py"
click node_schemas "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/api/schemas.py"
click node_sync "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/services/vault_sync.py"
click node_loader "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/services/vault_loader.py"
click node_chunker "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/services/markdown_chunker.py"
click node_filtering "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/core/indexing.py"
click node_chunk "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/domain/chunk.py"
click node_embed "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/infrastructure/embedding_model.py"
click node_qdrant_store "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/infrastructure/qdrant_store.py"
click node_sync_state "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/services/vault_sync.py"
click node_mcp_main "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/mcp-server/app/main.py"
click node_mcp_server "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/mcp-server/app/server.py"
click node_search_tool "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/mcp-server/app/tools/vault_search.py"
click node_rag_client "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/mcp-server/app/clients/rag_api.py"
click node_prometheus "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/observability/prometheus/prometheus.yml"
click node_grafana "https://github.com/tabula8rasa/obsidian_mcp_rag_server/tree/main/observability/grafana/dashboards"
click node_alloy "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/observability/alloy/config.alloy"
click node_loki "https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/observability/loki/loki-config.yml"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_sync,node_loader,node_chunker,node_filtering,node_chunk,node_embed,node_mcp_user toneBlue
class node_rag_routes,node_rag_main,node_schemas,node_git toneAmber
class node_mcp_main,node_mcp_server,node_search_tool,node_rag_client,node_api_user toneMint
class node_qdrant_store,node_qdrant,node_sync_state toneRose
class node_prometheus,node_grafana,node_alloy,node_loki,node_vault toneIndigo
```

## Components

### Vault indexing

- [Git-aware sync](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/services/vault_sync.py): `rag-api/app/services/vault_sync.py`
- [Vault loader](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/services/vault_loader.py): `rag-api/app/services/vault_loader.py`
- [Markdown chunker](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/services/markdown_chunker.py): `rag-api/app/services/markdown_chunker.py`
- [Path filtering](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/core/indexing.py): `rag-api/app/core/indexing.py`
- [Note chunk](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/domain/chunk.py): `rag-api/app/domain/chunk.py`
- [Embedding model](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/infrastructure/embedding_model.py): `rag-api/app/infrastructure/embedding_model.py`

### Search API

- [RAG endpoints](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/api/routes.py): `rag-api/app/api/routes.py`
- [API startup](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/main.py): `rag-api/app/main.py`
- [Search schemas](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/api/schemas.py): `rag-api/app/api/schemas.py`

### MCP access

- [MCP process](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/mcp-server/app/main.py): `mcp-server/app/main.py`
- [MCP composition](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/mcp-server/app/server.py): `mcp-server/app/server.py`
- [search_vault tool](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/mcp-server/app/tools/vault_search.py): `mcp-server/app/tools/vault_search.py`
- [RAG API client](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/mcp-server/app/clients/rag_api.py): `mcp-server/app/clients/rag_api.py`

### Index state

- [Vector store access](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/infrastructure/qdrant_store.py): `rag-api/app/infrastructure/qdrant_store.py`
- **Qdrant**
- [Commit state](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/rag-api/app/services/vault_sync.py): `rag-api/app/services/vault_sync.py`

### Monitoring

- [Prometheus](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/observability/prometheus/prometheus.yml): `observability/prometheus/prometheus.yml`
- [Grafana dashboards](https://github.com/tabula8rasa/obsidian_mcp_rag_server/tree/main/observability/grafana/dashboards): `observability/grafana/dashboards`
- [Alloy collector](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/observability/alloy/config.alloy): `observability/alloy/config.alloy`
- [Loki](https://github.com/tabula8rasa/obsidian_mcp_rag_server/blob/main/observability/loki/loki-config.yml): `observability/loki/loki-config.yml`

### Other components

- **Obsidian Vault**
- **Vault Git**
- **API caller**
- **MCP client**

## Connections

- API caller → RAG endpoints: calls
- RAG endpoints → Search schemas: validates
- RAG endpoints → Git-aware sync: runs sync
- RAG endpoints → Vector store access: searches
- API startup → Embedding model: loads model
- API startup → Vector store access: ensures collection
- Git-aware sync → Vault Git: reads commits
- Git-aware sync → Path filtering: filters paths
- Git-aware sync → Vault loader: loads notes
- Vault loader → Obsidian Vault: reads Markdown
- Vault loader → Markdown chunker: chunks notes
- Vault loader → Note chunk: creates chunks
- Git-aware sync → Vector store access: updates index
- Git-aware sync → Commit state: records commit
- Vector store access → Embedding model: embeds text
- Vector store access → Qdrant: reads and writes
- MCP client → MCP process: connects
- MCP process → MCP composition: creates
- MCP composition → search_vault tool: registers tool
- search_vault tool → RAG API client: delegates search
- RAG API client → RAG endpoints: POSTs search
- RAG endpoints → API caller: returns results
- search_vault tool → MCP client: returns fragments
- RAG endpoints → Prometheus: exposes metrics
- MCP composition → Prometheus: exposes metrics
- Prometheus → Grafana dashboards: feeds dashboards
- Alloy collector → Loki: ships logs
