{
  "markdown": "# cowork-semantic-search\n\n[![GitHub stars](https://img.shields.io/github/stars/ZhuBit/cowork-semantic-search?style=social)](https://github.com/ZhuBit/cowork-semantic-search/stargazers)\n[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/downloads/)\n[![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-green)](LICENSE)\n[![MCP Compatible](https://img.shields.io/badge/MCP-compatible-purple)](https://modelcontextprotocol.io)\n\n> If you find this useful, consider giving it a ⭐ — it helps others discover the project.\n\n**Local semantic search for your documents. No API keys. No cloud. Works with any MCP client.**\n\n![demo](assets/image.png)\n\n---\n\n## Why\n\nAI coding tools are powerful, but they have blind spots when it comes to your local files:\n\n- **Frozen knowledge** -- training data has a cutoff. Your latest reports, notes, and contracts don't exist in the model's world.\n- **Context window limits** -- you can't paste 500 documents into a prompt.\n- **No cross-file search** -- your AI tool can read one file at a time, but can't search across your entire document library for the relevant pieces.\n\nThis plugin bridges that gap. It indexes your local documents into a small, fast vector database. When you ask a question, it retrieves only the relevant pieces -- so your AI tool can answer with your actual data.\n\n```\nYour documents --> chunked --> embedded --> local vector DB\n                                                 |\n         Your question --> embedded --> similarity search --> relevant chunks --> AI answers\n```\n\n## Features\n\n- **Fully offline** -- one-time model download (~120MB), then no network calls. No data leaves your machine.\n- **Incremental indexing** -- SHA-256 content hashing. Only changed files get reprocessed. Re-indexing 1000 files where 3 changed takes seconds.\n- **Multilingual** -- handles 50+ languages natively. Search in one language, find results in another.\n- **Hybrid search** -- combines semantic similarity with full-text keyword search via Reciprocal Rank Fusion. Catches what pure vector search misses.\n- **Multiple formats** -- txt, md, pdf, docx, pptx, csv out of the box.\n- **Any MCP client** -- works with Claude Code, Cursor, Windsurf, Cline, and any other MCP-compatible tool.\n- **Zero infrastructure** -- LanceDB stores everything as local files. No server, no Docker, no database to manage.\n\n## Supported Formats\n\n| Format | Extension | Details |\n|--------|-----------|---------|\n| Plain text | `.txt` | UTF-8 with fallback |\n| Markdown | `.md` | Raw text preserved |\n| PDF | `.pdf` | Page-level extraction with metadata |\n| Word | `.docx` | Full paragraph extraction |\n| PowerPoint | `.pptx` | Slide-level extraction with metadata |\n| CSV | `.csv` | Row-based text extraction |\n\n## Quick Start\n\n### 1. Install\n\n```bash\ngit clone https://github.com/ZhuBit/cowork-semantic-search.git\ncd cowork-semantic-search\npython3 -m venv .venv && source .venv/bin/activate\npip install -e \".[all]\"\n```\n\n### 2. Configure your MCP client\n\nAdd the server to your MCP client's config. Replace paths with your own.\n\n<details>\n<summary><strong>Claude Code</strong> -- <code>.mcp.json</code> in your project root</summary>\n\n```json\n{\n  \"mcpServers\": {\n    \"semantic-search\": {\n      \"command\": \"/absolute/path/to/.venv/bin/python\",\n      \"args\": [\"-m\", \"server.main\"],\n      \"cwd\": \"/absolute/path/to/cowork-semantic-search\",\n      \"env\": {\n        \"PYTHONPATH\": \"/absolute/path/to/cowork-semantic-search\"\n      }\n    }\n  }\n}\n```\n</details>\n\n<details>\n<summary><strong>Cursor</strong> -- <code>.cursor/mcp.json</code> in your project root or <code>~/.cursor/mcp.json</code> globally</summary>\n\n```json\n{\n  \"mcpServers\": {\n    \"semantic-search\": {\n      \"command\": \"/absolute/path/to/.venv/bin/python\",\n      \"args\": [\"-m\", \"server.main\"],\n      \"env\": {\n        \"PYTHONPATH\": \"/absolute/path/to/cowork-semantic-search\"\n      }\n    }\n  }\n}\n```\n</details>\n\n<details>\n<summary><strong>Windsurf</strong> -- <code>~/.codeium/windsurf/mcp_config.json</code></summary>\n\n```json\n{\n  \"mcpServers\": {\n    \"semantic-search\": {\n      \"command\": \"/absolute/path/to/.venv/bin/python\",\n      \"args\": [\"-m\", \"server.main\"],\n      \"env\": {\n        \"PYTHONPATH\": \"/absolute/path/to/cowork-semantic-search\"\n      }\n    }\n  }\n}\n```\n</details>\n\n<details>\n<summary><strong>Cline</strong> -- MCP Servers settings in the Cline VS Code extension</summary>\n\nOpen Cline > MCP Servers icon > Configure > Advanced MCP Settings, then add:\n\n```json\n{\n  \"mcpServers\": {\n    \"semantic-search\": {\n      \"command\": \"/absolute/path/to/.venv/bin/python\",\n      \"args\": [\"-m\", \"server.main\"],\n      \"env\": {\n        \"PYTHONPATH\": \"/absolute/path/to/cowork-semantic-search\"\n      }\n    }\n  }\n}\n```\n</details>\n\n### 3. Restart your MCP client and go\n\n> \"Index all documents in ~/Documents/projects\"\n\n> \"Search for 'quarterly revenue report'\"\n\nFirst run downloads the embedding model (~120MB), then everything runs offline.\n\n## Example: Search Your Obsidian Vault\n\nIf you keep notes in Obsidian (or any folder of markdown files), this plugin turns your AI tool into a search engine for your knowledge base.\n\n```\nYou: \"Index my vault at ~/Documents/ObsidianVault\"\nAI:  Indexed 847 files -> 3,291 chunks in 42s\n\nYou: \"What did I write about API rate limiting?\"\nAI:  Found 6 relevant chunks across 3 files:\n       - notes/backend/rate-limiting-strategies.md\n       - projects/acme-api/design-decisions.md\n       - daily/2025-11-03.md\n       ...\n\nYou: \"Find anything about the client meeting last November, use hybrid search\"\nAI:  Found 4 results using hybrid search (vector + keyword):\n       - meetings/2025-11-12-acme-kickoff.md\n       - daily/2025-11-12.md\n       ...\n```\n\nWorks the same with PDFs, Word docs, PowerPoints, and CSVs -- just point it at a folder.\n\n## Tools\n\n| Tool | Description |\n|------|-------------|\n| `index_folder` | Index or re-index all documents in a folder. Incremental -- skips unchanged files. |\n| `semantic_search` | Search indexed documents using natural language. Supports `vector` and `hybrid` modes. |\n| `get_index_status` | Show total chunks, file count, and list of indexed files. |\n| `reindex_file` | Force re-index a single file, bypassing the hash cache. |\n\n## How It Works\n\n1. **Parse** -- extract text from each document, preserving structure (pages, slides)\n2. **Chunk** -- split into ~400 character overlapping pieces for precise retrieval\n3. **Embed** -- convert each chunk into a 384-dimensional vector using `paraphrase-multilingual-MiniLM-L12-v2`\n4. **Store** -- save chunks + vectors in a LanceDB database (a local file, no server needed)\n5. **Search** -- embed your query, find nearest chunks by cosine similarity, optionally combine with full-text keyword search via RRF\n\n## Advanced Usage\n\n<details>\n<summary><strong>Use as a Python library</strong></summary>\n\n```python\nfrom server.indexer import index_folder\nfrom server.search import semantic_search\n\n# Index a folder\nresult = index_folder(\"/path/to/docs\")\nprint(f\"{result['files_indexed']} files -> {result['total_chunks']} chunks\")\n\n# Search\nresults = semantic_search(\"project deadline\", mode=\"hybrid\")\nfor r in results[\"results\"]:\n    print(f\"  {r['file_name']}: {r['text'][:100]}...\")\n```\n</details>\n\n## Architecture\n\n```\nserver/\n  main.py       # MCP server + tool definitions\n  parsers.py    # Per-format text extraction\n  chunker.py    # Text splitting with metadata\n  indexer.py    # Discovery, hashing, embedding pipeline\n  store.py      # LanceDB vector store + FTS + hybrid search\n  search.py     # Query embedding + search orchestration\n```\n\n| Component | Choice | Why |\n|-----------|--------|-----|\n| MCP framework | FastMCP | Clean tool definitions, async support |\n| Embeddings | sentence-transformers | Offline, multilingual, fast |\n| Vector DB | LanceDB | Serverless, embedded, FTS built-in |\n| Chunking | langchain-text-splitters | Battle-tested recursive splitting |\n| PDF | PyMuPDF | Fast, accurate extraction |\n| DOCX | python-docx | Lightweight, no system deps |\n| PPTX | python-pptx | Slide-level extraction |\n\n## Development\n\n```bash\nsource .venv/bin/activate\npytest tests/ -v\n```\n\n56 tests covering parsers, chunking, indexing, search, and MCP tool integration.\n\nContributions welcome -- open an issue or submit a PR.\n\n## Roadmap\n\n- ONNX runtime for faster embeddings (drop PyTorch dependency)\n- Configurable chunk size and overlap via tool params\n- Multi-folder named indexes\n- Metadata filtering (date ranges, tags, custom fields)\n- Watch mode (auto-reindex on file changes)\n\n## Support\n\nIf this is useful to you, consider giving it a ⭐ — it helps others find the project.\n\n## License\n\nAGPL-3.0 -- free to use, modify, and self-host. If you offer this as a network service, you must share your source code. See [LICENSE](LICENSE) for details.\n",
  "bytes": 8819,
  "sha": "5922a6455c12e99d69d836e661c449e979d543a5574d36a52558ab5c755b3a07",
  "repo_slug": "zhubit/cowork-semantic-search",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_zhubit_cowork_semantic_search_semanticse_4a25332d/readme"
}