Witness
Provides remote access to the MCP server via Cloudflare Quick Tunnels or Named Tunnels for secure external connections.
Integrates Ollama for generating local embeddings to power semantic search across notes.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Witnessfind all notes with tag 'ideas'"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Witness
Your AI companion for transforming chaos into order
Witness is an Obsidian plugin that turns your vault into an intelligent, AI-accessible knowledge base. It runs an MCP (Model Context Protocol) server directly inside Obsidian, allowing Claude Desktop and other AI assistants to read, write, and organize your notes on your behalf.
Philosophy: Chaos → Order
Witness is built around a simple organizational philosophy:
Chaos: Unprocessed information flowing in from the world (articles, videos, quick notes, transcripts)
Order: Structured knowledge you've refined and organized (topics, projects, synthesis)
The plugin helps you move information from chaos to order, with AI assistance to process, categorize, and synthesize your notes.
Related MCP server: obsidian-mcp
Features
Current (Phase 1 + 2 + 3) ✅
MCP Server: Runs inside Obsidian, no external dependencies
File Operations: Read, write, edit, and list files in your vault via AI
Full-Text Search: Search across all markdown files with optional filters
Semantic Search: Find documents by meaning using local Ollama embeddings + Orama vector store
Search Panel: Sidebar search with path and tag filtering via fuzzy autocomplete
Background Indexing: Automatic incremental indexing with idle-gated execution (waits for 2 minutes of inactivity), debounced saves, active file deferral, and status bar countdown timer
Command Execution: Execute any Obsidian command via AI
Claude Desktop Integration: Connect directly from Claude Desktop app
Remote Access: Cloudflare Quick Tunnel or Named Tunnel (permanent URL) for access from anywhere
Named Tunnel Support: Use your own domain with Cloudflare Named Tunnels for a permanent, stable URL
Primary Machine: Designate which machine runs the tunnel when syncing across multiple devices
Token Authentication: Protect your remote endpoint with a simple token
Chaos Triage: AI-assisted processing of unread chaos items with queue management and safe frontmatter updates
Chaos Queue Panel: Visual sidebar for browsing and triaging chaos items — card-based UI with hover actions, bulk edit mode, keyboard shortcuts, and file explorer context menu
LLM Re-ranking: Optional two-stage search — fast hybrid results shown instantly, then re-ranked by a local LLM for higher precision
Contextual Search: Toggle a mode where the search panel automatically shows related notes based on your cursor position, selection, or current paragraph — no typing needed
Page Preview: Cmd+hover on any search result to preview the note without leaving the panel
Privacy First: Everything runs locally, your tunnel, your data
16 MCP Tools Available:
read_file- Read file contents (with optional Dataview rendering)write_file- Create new files (create-only, errors on existing)list_files- Browse directoriesedit_file- Find and replace textsearch- Unified content search: hybrid (keyword + semantic), vector, or fulltext modes with tag/path filteringfind- Find files by name, path, tag, or frontmatter property with metadatamove_file- Move or rename filescopy_file- Copy files to new locationcreate_folder- Create folders (with mkdir -p support)delete- Delete files/folders (with trash support)execute_command- Run Obsidian commandsget_vault_context- Load your vault's context document (auto-renders Dataview)dataview_query- Execute Dataview queries, get structured vault data (requires Dataview plugin)get_next_chaos- Get next unprocessed chaos item for triage (single or list mode)mark_triage- Record triage decision (processed, deferred, acknowledged, next, reset)copy-obsidian-url- Copy the internal Obsidian URL for the current file
Coming Soon
Chat Interface: Connect via WhatsApp/Telegram for mobile access
Heartbeat Prompts: Daily/weekly prompts to keep your vault fresh
Chaos Monitoring: Get notified when unprocessed items pile up
Installation
Prerequisites
Obsidian 1.0.0 or higher
Node.js 20+ (for Claude Desktop connection)
Claude Desktop app (optional, for AI integration)
Ollama (optional, for semantic search)
Install via BRAT (Recommended)
The easiest way to install Witness is using the BRAT plugin:
Install BRAT from Obsidian's Community Plugins
Open BRAT settings and click "Add Beta Plugin"
Enter:
jawache/witnessClick "Add Plugin"
Enable Witness in Community Plugins
BRAT will automatically keep Witness updated when new releases are published.
Manual Installation
If you prefer to install manually:
Download the latest release
Go to Releases
Download
main.jsandmanifest.json
Install in your vault
# Create plugin folder mkdir -p /path/to/your/vault/.obsidian/plugins/witness/ # Copy files cp main.js manifest.json /path/to/your/vault/.obsidian/plugins/witness/Enable in Obsidian
Open Obsidian Settings → Community Plugins
Disable Safe Mode if prompted
Find "Witness" in the list and enable it
Build from Source
For developers who want to build from source:
Clone the repository
git clone https://github.com/jawache/witness.git cd witnessBuild the plugin
npm install npm run buildInstall in your vault
cp main.js manifest.json /path/to/your/vault/.obsidian/plugins/witness/
Connect to Claude Desktop
Configure Claude Desktop
Edit
~/.claude/claude_desktop_config.json(or%APPDATA%\Claude\claude_desktop_config.jsonon Windows):{ "mcpServers": { "witness": { "command": "npx", "args": [ "-y", "mcp-remote@latest", "http://localhost:3000/mcp", "--transport", "http-only", "--allow-http" ] } } }Restart Claude Desktop
Verify Connection
In Claude Desktop, you should see "witness" in the MCP servers list. Try asking:
"Can you list the files in my vault?"
Usage
Organizing Your Vault
For best results, organize your vault with these top-level folders:
vault/
├── chaos/
│ ├── external/ # Articles, videos, clippings
│ └── inbox/ # Quick capture notes
└── order/
├── knowledge/ # Organized information
├── heartbeat/ # Daily/weekly notes
├── projects/ # Active work
└── synthesis/ # Published outputThis structure isn't required, but Witness is designed to help you maintain this flow.
Settings
Open Obsidian Settings → Witness. Settings are organised into tabs:
General Tab
Enable MCP Server: Turn the server on/off
Port: HTTP server port (default: 3000)
Remote Access Tab
Enable Tunnel: Expose your MCP server via Cloudflare tunnel
Tunnel Type: Quick (random URL) or Named (permanent URL on your domain)
Require Authentication: Protect remote access with a token
Search Tab
Base URL: Ollama server address (default:
http://localhost:11434)Embedding Model: Which Ollama model to use for embeddings (see Supported Models)
Index Status: Shows the number of indexed documents and provides Build/Clear buttons
Minimum Content Length: Skip files shorter than this many characters (default: 50). Short files produce noisy, generic embeddings that match any query — filtering them significantly improves search quality. See Why Filter Short Documents? for details.
Folder Exclusions: Choose folders to exclude from indexing (e.g., attachments, templates). Uses a folder picker for easy selection.
Remote Access
Witness supports two types of Cloudflare tunnels to expose your vault remotely:
Option A: Quick Tunnel (Easy, Temporary)
A quick tunnel gives you a random URL that changes every time Obsidian restarts. Good for testing.
Go to Obsidian Settings → Witness
Toggle "Enable Tunnel"
Set Tunnel Type to "Quick Tunnel (ephemeral)"
Wait for the tunnel URL to appear
Enable "Require Authentication" and copy your MCP URL
The URL will look like: https://random-words.trycloudflare.com/mcp?token=xxx
Option B: Named Tunnel (Permanent URL)
A named tunnel gives you a permanent URL on your own domain. Requires a free Cloudflare account.
Step 1: Create the tunnel in Cloudflare
Sign up at Cloudflare Zero Trust
Go to Networks → Tunnels
Click Create a tunnel
Choose Cloudflared as the connector type
Name your tunnel (e.g., "witness")
On the "Install connector" page, copy the tunnel token (the long
eyJh...string)Skip the connector installation (Witness handles this automatically)
Add a Public Hostname:
Subdomain: e.g.,
witnessDomain: select your domain (e.g.,
example.com)Service Type:
HTTPURL:
localhost:3456(or whatever port you set in Witness settings)
Save the tunnel
Step 2: Configure Witness
Go to Obsidian Settings → Witness
Set the MCP Server Port to match your tunnel config (e.g.,
3456)Toggle "Enable Tunnel"
Set Tunnel Type to "Named Tunnel (permanent)"
Paste your Tunnel Token from Cloudflare
Set Tunnel URL to your public hostname (e.g.,
https://witness.example.com)Enable "Require Authentication" (recommended)
Click "Copy URL" to get your full MCP URL
Step 3: Connect Claude
Use the tunnel URL in your MCP client configuration:
{
"mcpServers": {
"witness": {
"command": "npx",
"args": [
"-y",
"mcp-remote@latest",
"https://witness.example.com/mcp?token=YOUR_TOKEN",
"--transport",
"http-only"
]
}
}
}This works with Claude Desktop, Claude.ai web, and Claude mobile.
Multiple Devices (Obsidian Sync)
If you sync your vault across multiple computers using Obsidian Sync, the Witness plugin settings sync too — including the tunnel token. Without precaution, every machine would try to start the tunnel, and Cloudflare would round-robin traffic between them unpredictably.
To prevent this, Witness has a Primary Machine feature:
Open Obsidian Settings → Witness on the machine you want to run the tunnel
Under Named Tunnel settings, click "Set as primary"
This saves the machine's hostname — only this machine will start the tunnel
On other machines, the tunnel is silently skipped on startup
To switch the primary to a different machine, open Witness settings on that machine and click "Set as primary". To clear the restriction entirely, click the ✕ button next to the primary hostname.
Mobile Devices
The tunnel and MCP server features are desktop-only. Obsidian mobile (iOS/Android) cannot run the HTTP server or cloudflared binary. To access your vault from a mobile device, connect to the tunnel URL from a client app (e.g., Claude mobile) — the vault is served by whichever desktop machine is running the tunnel.
Security Notes
The auth token is included in the URL query parameter. HTTPS encrypts this in transit, but be cautious about sharing URLs or logging them.
For additional security, the token can also be passed via
Authorization: Bearer xxxheader instead of the query parameter.The
cloudflaredbinary is automatically downloaded and stored in~/.witness/bin/.
Semantic Search
Witness provides semantic search powered by Ollama for local embeddings and Orama for the vector store. Everything runs locally — no cloud services, no API keys.
Prerequisites
Install Ollama: Download from ollama.com
Pull an embedding model:
ollama pull nomic-embed-text # Good default (768 dims, 2048 token context) ollama pull mxbai-embed-large # Higher quality (1024 dims, 512 token context)You can also pull models from the Witness settings page directly.
Build the index: Open Witness settings → Search tab → click "Build Index"
Search Modes
The search MCP tool (and the Search panel) supports three modes:
Hybrid (default): Combines QPS keyword matching with vector cosine similarity. Best for most queries — gets the precision of keywords with the recall of semantic understanding.
Vector: Pure semantic similarity. Finds conceptually related documents even when they don't share keywords. Good for exploratory queries like "notes about improving sleep quality".
Fulltext: Pure QPS (Quantum Proximity Scoring) keyword matching. Fast and precise when you know the exact terms. No embeddings needed. Scores by token proximity — "carbon intensity" as adjacent words ranks higher than scattered occurrences.
Supported Embedding Models
Model | Dimensions | Context | Prefixes | Notes |
| 768 | 2048 tokens | Both (mandatory) | Good default. Requires |
| 1024 | 512 tokens | Query only | Higher quality embeddings. Requires query prefix — handled automatically. |
| 384 | 256 tokens | None | Smallest and fastest. Short context window. |
| 1024 | 8192 tokens | None | Longest context — best for very long documents. |
| 1024 | 512 tokens | None | Good quality, no prefix needed. |
| 384 | 512 tokens | Query only | Compact model with decent quality. |
Task prefixes are special strings prepended to input text that tell the model whether it's processing a document for storage or a query for search. Witness handles this automatically via embedDocuments() and embedQuery() — you don't need to add prefixes manually. Using the wrong prefix (or no prefix when one is required) produces embeddings in the wrong vector space, making similarity scores meaningless.
Context Length and Truncation
Each embedding model has a maximum context window measured in tokens. Documents longer than this are truncated before embedding. Witness handles this automatically:
Dynamic resolution: On startup, Witness queries Ollama's
/api/showendpoint to get the model's actual architecture context lengthClient-side pre-truncation: As a safety net, text is truncated to
context_tokens × 2characters before sending to Ollama (the factor of 2 is a conservative chars-per-token estimate)Server-side truncation: Ollama's
truncate: trueparameter provides a second safety net
Important: The context length that matters is the model's architecture context length (e.g., nomic-bert.context_length: 2048), not the Modelfile num_ctx parameter (which may be 8192 but doesn't extend the embedding context). This distinction caught us out — nomic-embed-text reports num_ctx 8192 but can only embed 2048 tokens.
Documents with heavy JSON, HTML, URLs, or non-ASCII content tokenise less efficiently (as low as ~1.5 characters per token vs the typical ~4 for English prose). The conservative CHARS_PER_TOKEN = 2 accounts for this.
Why Filter Short Documents?
Very short documents (e.g., a file containing just a single word like "gold") produce generic embeddings that sit near the centre of the vector space. Because they lack distinctive content, they end up equidistant from everything — and cosine similarity scores them surprisingly high against any query.
The Minimum Content Length setting (default: 50 characters) filters these out at indexing time. This is the single most effective setting for improving search quality without changing your embedding model.
Signs you might want to increase this threshold:
Search results include stub pages, empty templates, or placeholder files
The same short documents appear in results for unrelated queries
Vector search returns noticeably worse results than fulltext
Index Persistence
The index is stored at .witness/index.orama in your vault as a single JSON file. It includes a schema version number — when the schema changes (e.g., when new fields are added), old indexes are automatically discarded and a full re-index is triggered on next use.
To force a complete re-index: Settings → Search → Clear Index → Build Index.
Example Commands
Once connected to Claude Desktop, you can ask:
"Show me all the files in my chaos/inbox folder"
"Read the contents of my daily note"
"Create a new note in order/knowledge about [topic]"
"List all markdown files in my vault"
Development
Building
npm run build # Production build
npm run dev # Development mode with watchTesting
# Build and install plugin in test vault
npm run test:install-plugin
# Start Obsidian with test vault
npm run test:start-obsidian
# Run integration tests (47 tests)
npm test
# Check server status
curl http://localhost:3000/healthLogs
MCP server logs are written to your vault's plugin folder:
.obsidian/plugins/witness/logs/mcp-YYYY-MM-DD.logThis makes it easy to:
Share logs for bug reports
Debug issues without Developer Console
Let AI assistants read logs directly
Additional log locations:
Obsidian console:
Cmd+Option+I→ Console tabClaude Desktop:
~/Library/Logs/Claude/mcp-server-witness.log
Troubleshooting
Plugin won't load
Check Obsidian console for errors
Verify files are in correct location:
.obsidian/plugins/witness/Try disabling and re-enabling the plugin
Claude Desktop won't connect
Check the MCP server is running:
curl http://localhost:3000/health # Should return: {"status":"ok","plugin":"witness"}Check Claude Desktop logs:
tail -f ~/Library/Logs/Claude/mcp-server-witness.logVerify Node.js version:
node --version # Should be 20.x or higher
MCP server drops connection (macOS sleep)
If the MCP server becomes unreachable after periods of inactivity, your Mac is likely sleeping and dropping network connections. Check your current power settings:
pmset -gThe key setting is networkoversleep — if it's 0, macOS drops all network connections during sleep, killing the MCP server for remote clients.
Fix: Enable network access during sleep
sudo pmset -a networkoversleep 1Other useful power settings for keeping the server reachable:
# Prevent system sleep on AC power
sudo pmset -c sleep 0
# Enable Wake on LAN (allows remote wake)
sudo pmset -c womp 1
# Disable Power Nap (can interfere with network stability)
sudo pmset -c powernap 0Quick fix: Keep awake temporarily
If you don't want to change system settings permanently, run caffeinate in a terminal:
# Prevent idle and system sleep (Ctrl+C to stop)
caffeinate -si
# Or run in the background
caffeinate -si &Key pmset settings
Setting | Value | Effect |
|
| Keep network alive during sleep |
|
| Wake on LAN enabled |
|
| Maintain TCP connections during sleep |
|
| Disable system sleep (AC power: |
|
| Disable Power Nap |
Port already in use
If port 3000 is taken:
Open Obsidian Settings → Witness
Change the port number (e.g., 3001)
Update your Claude Desktop config to match
Architecture
Witness runs an HTTP server inside Obsidian's Electron process:
Claude Desktop (MCP Client)
↓ stdio
mcp-remote bridge
↓ HTTP + SSE
Witness Plugin (MCP Server)
↓ Direct API
Obsidian VaultThis is different from other Obsidian MCP servers that run externally and connect via REST APIs. Witness has direct access to Obsidian's internal APIs for maximum reliability and performance.
Roadmap
Phase 1: MCP Server ✅
Basic plugin scaffold
HTTP server implementation
File operations (read, write, list, edit)
Claude Desktop integration
Full-text search
Command execution
Orientation document system
File-based logging
Integration test suite (47 tests)
Phase 2: Remote Access ✅
Cloudflare Quick Tunnel integration
Cloudflare Named Tunnel support (permanent URLs)
Primary machine designation for multi-device sync
Token authentication for remote access
WhatsApp/Telegram bot
Multi-user sessions
Phase 3: Semantic Search ✅
Local embeddings via Ollama (nomic-embed-text, mxbai-embed-large, and more)
Orama vector store with hybrid (BM25 + vector), vector-only, and fulltext modes
Model-specific task prefixes for optimal retrieval quality
Dynamic model info resolution via Ollama
/api/showClient-side pre-truncation for context length safety
Minimum content length filter for short document noise
Folder exclusions with folder picker UI
Search panel sidebar view
Tabbed settings UI with model pull and live indexing progress
Tested on 4,097-document vault
Dataview Integration ✅
dataview_queryMCP tool (markdown + JSON output)read_filerender parameter for resolving Dataview codeblocksget_vault_contextauto-renders Dataview queries8 integration tests
Chaos Triage ✅
get_next_chaostool (single + list mode, queue counts, priority sorting)mark_triagetool (processed, deferred, acknowledged, next, reset)Safe frontmatter updates via
processFrontMatterAPIAI guardrails: create-only
write_file, improvededit_fileerrors
Chaos Queue Panel ✅
Visual sidebar with card-based UI (title, path, smart snippets)
"Next Up" and "Queue" groups with collapsible sections
Hover-only action buttons (acknowledge, mark next, move to death, reset)
Bulk Edit mode with select all, bulk acknowledge, bulk move-to-death
10 keyboard commands (triage actions, sibling navigation, panel toggles)
Inline hotkey capture in settings with conflict detection
File explorer context menu for chaos files and folders
Post-action navigation (next sibling file after move-to-death)
Live vault event listeners (deleted/renamed files removed from panel)
Phase 4: Intelligence
Heartbeat scheduler (daily/weekly prompts)
Chaos monitoring (detect stale items)
Smart suggestions
Auto-categorization
Phase 5: Advanced Features
Graph analysis
Template system
Workflow automation
Contributing
Contributions are welcome! This project is in active early development.
Guidelines
Keep it simple and focused
Maintain zero dependencies on other plugins
Test with the included
test-vault/Follow the existing code style
License
MIT
Acknowledgments
Built on the Model Context Protocol by Anthropic
Inspired by the Zettelkasten and PARA methods
Thanks to the Obsidian community for the amazing platform
Support
Issues: GitHub Issues
Discussions: GitHub Discussions
Twitter: @jawache
"The best way to predict the future is to invent it." - Alan Kay
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/jawache/witness'
If you have feedback or need assistance with the MCP directory API, please join our Discord server