{"id":30898106,"url":"https://github.com/dashed/mcp-personal","last_synced_at":"2025-09-09T01:05:39.107Z","repository":{"id":300563904,"uuid":"1006005932","full_name":"dashed/mcp-personal","owner":"dashed","description":"Model Context Protocol (MCP) servers that I personally use.","archived":false,"fork":false,"pushed_at":"2025-08-09T09:34:00.000Z","size":670,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-09T11:35:24.505Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dashed.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-21T09:23:14.000Z","updated_at":"2025-08-09T09:34:03.000Z","dependencies_parsed_at":"2025-08-02T08:05:55.033Z","dependency_job_id":"81901bf6-4ce8-4cf7-8b65-94cffd1760c9","html_url":"https://github.com/dashed/mcp-personal","commit_stats":null,"previous_names":["dashed/mcp-personal"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dashed/mcp-personal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashed%2Fmcp-personal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashed%2Fmcp-personal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashed%2Fmcp-personal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashed%2Fmcp-personal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dashed","download_url":"https://codeload.github.com/dashed/mcp-personal/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashed%2Fmcp-personal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274231771,"owners_count":25245855,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-08T02:00:09.813Z","response_time":121,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-09-09T01:05:38.194Z","updated_at":"2025-09-09T01:05:39.077Z","avatar_url":"https://github.com/dashed.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MCP Personal - Collection of Personal MCP Servers\n\nA collection of [Model Context Protocol](https://modelcontextprotocol.io) (MCP) servers for various personal productivity tools and utilities.\n\n## Available MCP Servers\n\n### 1. File Search Server (`mcp_fd_server.py`)\nFuzzy file NAME search capabilities using `fd` and `fzf`:\n- **Fast file name search** using `fd` (searches file names/paths, NOT contents)\n- **Fuzzy filtering of file names** with `fzf` for intelligent name matching\n- **Pattern matching** with regex and glob support for file names\n- **Result limiting** with `limit` parameter to restrict number of matches\n- **Proper error handling** for fzf exit codes (distinguishes \"no matches\" from errors)\n- **Multiline mode** (advanced): can also search file contents when enabled\n- **Standalone CLI** for testing and direct usage\n- **Key point**: Primary purpose is finding files by NAME, not searching contents\n\n### 2. Fuzzy Search Server (`mcp_fuzzy_search.py`)\nAdvanced search with both file name and content capabilities using `ripgrep` and `fzf`:\n- **File name fuzzy search** - find files by partial/fuzzy names\n- **Content search** using `ripgrep` to search text within files\n- **Fuzzy filtering** of results using `fzf --filter`\n- **Proper error handling** for fzf exit codes (distinguishes \"no matches\" from errors)\n- **Two distinct modes**: \n  - `fuzzy_search_files`: Search file NAMES/paths\n  - `fuzzy_search_content`: Search file CONTENTS with path+content matching by default\n- **PDF and document search** (optional) - search through PDFs, Office docs, and archives using `ripgrep-all`\n- **PDF page extraction** (optional) - extract specific pages from PDFs using PyMuPDF with page label support\n- **PDF information tools** (optional) - get page labels, page count, and table of contents from PDF files:\n  - `get_pdf_page_labels`: Get all page labels from a PDF file\n  - `get_pdf_page_count`: Get the total number of pages in a PDF file\n  - `get_pdf_outline`: Extract table of contents/bookmarks from a PDF file\n- **Simplified interface** - just provide fuzzy search terms (NO regex support)\n- **Multiline record processing** for complex pattern matching\n- **Standalone CLI** for testing and direct usage\n\n### 3. SQLite Server (`mcp_sqlite_server.py`)\nSQLite database operations with configurable read/write permissions:\n- **Read-only by default** - Write operations disabled unless explicitly enabled\n- **Agent-friendly** - Clear tool descriptions and examples for easy AI agent usage\n- **In-memory database support** - Use `:memory:` for temporary databases\n- **Comprehensive operations** - Query, execute, list tables, describe schema, create tables\n- **Safety features** - Query validation, write operation restrictions, clear error messages\n- **Standalone CLI** for testing and direct usage\n\n## Prerequisites\n\n### General Requirements\n- Python 3.10 or higher\n- [uv](https://github.com/astral-sh/uv) (recommended) or pip\n\nTo install uv:\n```bash\n# macOS/Linux\ncurl -LsSf https://astral.sh/uv/install.sh | sh\n\n# Or using pip (if you already have Python)\npip install uv\n```\n\n### Note on Optional Features\nThe PDF search and extraction tools in the Fuzzy Search Server are **optional**. The server will work without these binaries installed - only the PDF-specific tools will be unavailable. This allows you to use the core fuzzy search functionality without requiring all dependencies.\n\n### File Search Server Requirements\nThe file search server requires the following command-line tools:\n\n#### macOS\n```bash\nbrew install fd fzf\n```\n\n#### Ubuntu/Debian\n```bash\nsudo apt install fd-find fzf\n# Note: On Debian/Ubuntu, fd is installed as 'fdfind'\n```\n\n#### Other Systems\n- [fd installation guide](https://github.com/sharkdp/fd#installation)\n- [fzf installation guide](https://github.com/junegunn/fzf#installation)\n\n### Fuzzy Search Server Requirements\nThe fuzzy search server requires:\n\n#### macOS\n```bash\nbrew install ripgrep fzf\n\n# For PDF search capabilities (optional)\nbrew install ripgrep-all pandoc\npip install PyMuPDF  # Or: uv pip install PyMuPDF\n```\n\n#### Ubuntu/Debian\n```bash\nsudo apt install ripgrep fzf\n\n# For PDF search capabilities (optional)\n# Install ripgrep-all\ncargo install ripgrep-all  # Requires Rust/cargo\n\n# Install PyMuPDF\npip install PyMuPDF  # Or: uv pip install PyMuPDF\n\n# Install pandoc\nsudo apt install pandoc\n```\n\n#### Other Systems\n- [ripgrep installation guide](https://github.com/BurntSushi/ripgrep#installation)\n- [fzf installation guide](https://github.com/junegunn/fzf#installation)\n- [ripgrep-all installation](https://github.com/phiresky/ripgrep-all#installation) (optional, for PDF search)\n- [pandoc installation](https://pandoc.org/installing.html) (optional, for PDF extraction)\n\n## Installation\n\n### Clone the Repository\n\n```bash\ngit clone https://github.com/yourusername/mcp-personal.git\ncd mcp-personal\n```\n\n### Configure MCP Servers\n\n#### Using Claude Code CLI\n\nThe easiest way to add MCP servers to Claude Code is using the CLI:\n\n```bash\n# Add published npm servers (recommended to use -s user for global access)\nclaude mcp add sequential-thinking -s user -- npx -y @modelcontextprotocol/server-sequential-thinking\n\n# Add custom Python servers from this repository\n# IMPORTANT: Use -s user for personal tools you want available across all projects\n# Without -s flag, servers are only available in current directory and are temporary\n\n# Easy method: Use $(pwd) when in the project directory\ncd /path/to/mcp-personal\nclaude mcp add file-search -s user -- $(pwd)/mcp_fd_server.py\nclaude mcp add fuzzy-search -s user -- $(pwd)/mcp_fuzzy_search.py\nclaude mcp add sqlite -s user -- $(pwd)/mcp_sqlite_server.py\n\n# Or use relative paths (also from project directory)\nclaude mcp add file-search -s user -- ./mcp_fd_server.py\nclaude mcp add fuzzy-search -s user -- ./mcp_fuzzy_search.py\nclaude mcp add sqlite -s user -- ./mcp_sqlite_server.py\n\n# Using absolute paths (works from anywhere)\nclaude mcp add file-search -s user -- /path/to/mcp-personal/mcp_fd_server.py\nclaude mcp add fuzzy-search -s user -- /path/to/mcp-personal/mcp_fuzzy_search.py\nclaude mcp add sqlite -s user -- /path/to/mcp-personal/mcp_sqlite_server.py\n\n# Add SQLite server with write permissions enabled\nclaude mcp add sqlite -s user -- /path/to/mcp-personal/mcp_sqlite_server.py --allow-writes\n\n# Or using environment variable\nclaude mcp add sqlite -s user -e MCP_SQLITE_ALLOW_WRITES=true -- /path/to/mcp-personal/mcp_sqlite_server.py\n\n# Add Python servers with Python interpreter explicitly\nclaude mcp add my-server -s user -- python /path/to/my_mcp_server.py\n\n# Add servers with arguments\nclaude mcp add my-server -s user -- python /path/to/server.py arg1 arg2\n\n# Add servers with environment variables\nclaude mcp add my-server -s user -e API_KEY=your_key -e DEBUG=true -- python /path/to/server.py\n\n# Scope options:\n# -s local (default): Temporary, only in current directory\n# -s project: Shared with team via .mcp.json file\n# -s user: Personal, available across all your projects (recommended)\n```\n\n**Note:** \n- The `--` separator is important before the command and its arguments\n- Environment variables use `-e KEY=value` syntax\n- Use `-s user` for personal servers available across all projects\n- Both relative and absolute paths work\n\n#### Manual Configuration (Claude Desktop)\n\nFor Claude Desktop, manually add servers to `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"file-search\": {\n      \"command\": \"/path/to/mcp-personal/mcp_fd_server.py\"\n    },\n    \"fuzzy-search\": {\n      \"command\": \"/path/to/mcp-personal/mcp_fuzzy_search.py\"\n    },\n    \"sqlite\": {\n      \"command\": \"/path/to/mcp-personal/mcp_sqlite_server.py\",\n      \"args\": [\"--allow-writes\"],\n      \"env\": {\n        \"MCP_SQLITE_ALLOW_WRITES\": \"true\"\n      }\n    }\n  }\n}\n```\n\n### Make Scripts Executable\n\n```bash\n# Make all Python scripts executable\nchmod +x *.py\n```\n\n### For Development\n\n```bash\n# Install with development dependencies\nuv sync --dev\n\n# Or use make\nmake setup\n```\n\n## Testing and Development\n\n### MCP Inspector\n\nThe **MCP Inspector** is an interactive developer tool for testing and debugging MCP servers. It provides a web-based interface that allows you to:\n\n- **Visually test your MCP servers** with an interactive UI\n- **Debug server implementations** by examining request/response flows\n- **Test tools, resources, and prompts** with different arguments\n- **Validate server behavior** before deployment\n\n#### Quick Testing\n\nTest any MCP server using the inspector:\n\n```bash\n# Test the file search server\nnpx @modelcontextprotocol/inspector ./mcp_fd_server.py\n\n# Test the fuzzy search server  \nnpx @modelcontextprotocol/inspector ./mcp_fuzzy_search.py\n\n# Test the SQLite server (read-only mode)\nnpx @modelcontextprotocol/inspector ./mcp_sqlite_server.py\n\n# Test the SQLite server with write permissions\nnpx @modelcontextprotocol/inspector ./mcp_sqlite_server.py -- --allow-writes\n```\n\nThis will:\n1. Start the MCP Inspector proxy server (default port 6277)\n2. Launch a web interface (default port 6274) \n3. Connect to your MCP server via stdio transport\n4. Open your browser to the inspector interface\n\n#### Using the Inspector\n\nOnce the inspector is running:\n\n1. **Navigate to the web interface** (usually http://localhost:6274)\n2. **Explore the tabs**:\n   - **Tools**: Test `search_files`, `filter_files`, `fuzzy_search_files`, `fuzzy_search_content`, `fuzzy_search_documents`, `extract_pdf_pages`\n   - **Resources**: View any exposed resources (if implemented)\n   - **Prompts**: Test any exposed prompts (if implemented)\n3. **Test different scenarios**:\n   - Try various search patterns and filters\n   - Test multiline functionality\n   - Experiment with different file paths and flags\n   - Test PDF search with `fuzzy_search_documents` (if binaries installed)\n   - Test PDF page extraction with `extract_pdf_pages` (if binaries installed)\n   - Validate error handling with invalid inputs\n\n#### Advanced Configuration\n\nYou can also use configuration files for complex setups:\n\n```bash\n# Using a config file\nnpx @modelcontextprotocol/inspector --config config.json\n\n# Passing environment variables\nnpx @modelcontextprotocol/inspector -e \"DEBUG=1\" ./mcp_fuzzy_search.py\n\n# Custom ports\nnpx @modelcontextprotocol/inspector --mcpp-port 3001 --mcpi-port 3002 ./mcp_fd_server.py\n```\n\nThe MCP Inspector is particularly valuable for:\n- **Rapid prototyping** - quickly test new functionality\n- **Debugging** - identify issues before integration with Claude\n- **Documentation** - understand exactly what your server exposes\n- **Validation** - ensure proper error handling and edge cases\n\n## Usage\n\n### File Search Server\n\n#### As an MCP Server\n\nOnce configured in Claude Desktop, you can use natural language to search for files by NAME:\n\n- \"Find all Python files in the src directory\" (searches file names ending in .py)\n- \"Search for files with 'config' in their name\" (fuzzy matches file names)\n- \"Find test files by name\" (searches for files with 'test' in the name)\n- \"Use fuzzy search to find 'mainpy'\" (finds main.py, main_py.txt, etc.)\n\n#### CLI Usage\n\nThe file search server also works as a standalone CLI tool:\n\n```bash\n# Search for files by name pattern\n./mcp_fd_server.py search \"\\.py$\" /path/to/search  # Find Python files by name\n./mcp_fd_server.py search \"\\.py$\" . --limit 10  # Limit to first 10 results\n\n# Search with additional fd flags\n./mcp_fd_server.py search \"\\.js$\" . --flags \"--hidden --no-ignore\"\n\n# Fuzzy filter file names/paths\n./mcp_fd_server.py filter \"main\" \"\\.py$\" /path/to/search  # Fuzzy search for 'main' in Python file names\n./mcp_fd_server.py filter \"test\" \"\" . --limit 20  # Find up to 20 test-related files\n\n# Get the best fuzzy match by name\n./mcp_fd_server.py filter \"app\" \"\" . --first  # Find file with name most similar to 'app'\n\n# Multiline mode - search file CONTENTS (not just names)\n./mcp_fd_server.py filter \"class function\" \"\" src --multiline  # Find files containing both terms\n./mcp_fd_server.py filter \"TODO\" \"\" . --multiline --limit 5  # Find first 5 files with TODOs\n```\n\n### Fuzzy Search Server\n\n#### As an MCP Server\n\nOnce configured in Claude Desktop, you can use natural language for advanced searching:\n\n- \"Search for TODO comments that mention 'implement'\"\n- \"Find all files with 'test' in the name using fuzzy search\"\n- \"Look for error handling code in Python files\"\n- \"Search for configuration files containing database settings\"\n- \"Find method definitions named 'update_ondemand_max_spend'\"\n- \"Search for async functions with error handling\"\n- \"Search for 'update' in test.py files only\" (works because default mode matches paths too!)\n- \"Search for 'async' in content only, ignore file paths\" (use content_only mode)\n- \"Search for 'vector' in PDF documents\" (requires ripgrep-all)\n- \"Find all references to 'machine learning' in PDFs and Word documents\"\n- \"Extract pages 5-10 from the user manual PDF\"\n- \"Get the table of contents from the research paper PDF\"\n- \"Show me the outline of chapters in the user manual\"\n\n#### CLI Usage\n\nThe fuzzy search server also works as a standalone CLI tool:\n\n```bash\n# Fuzzy search for file NAMES/PATHS\n./mcp_fuzzy_search.py search-files \"main\" /path/to/search  # Find files with 'main' in the name\n./mcp_fuzzy_search.py search-files \"test\" . --hidden --limit 10  # Find test files by name\n./mcp_fuzzy_search.py search-files \"config\" / --confirm-root  # Search from root (requires explicit confirmation)\n\n# Search file CONTENTS and filter with fzf (NO regex support)\n# Default: Matches on BOTH file paths AND content\n# Works with both directories and individual files\n./mcp_fuzzy_search.py search-content \"TODO implement\" .  # Find lines containing both terms\n./mcp_fuzzy_search.py search-content \"test.py: update\" .  # Find 'update' in test.py files\n./mcp_fuzzy_search.py search-content \"function\" specific_file.py  # Search within a single file\n./mcp_fuzzy_search.py search-content \"error handle\" src --rg-flags \"-i\"  # Case insensitive\n./mcp_fuzzy_search.py search-content \"config\" / --confirm-root  # Search from root (requires explicit confirmation)\n\n# Content-only mode: Match ONLY on content, ignore file paths\n./mcp_fuzzy_search.py search-content \"TODO implement\" . --content-only  # Pure content search\n./mcp_fuzzy_search.py search-content \"async await\" src --content-only  # Won't match file paths\n\n# Multiline mode - changes behavior:\n# search-files --multiline: Searches file CONTENTS instead of names\n./mcp_fuzzy_search.py search-files \"class constructor\" src --multiline  # Find files CONTAINING these terms\n\n# search-content --multiline: Treats whole files as searchable units\n./mcp_fuzzy_search.py search-content \"async await\" . --multiline  # Find files with both terms anywhere\n./mcp_fuzzy_search.py search-content \"try catch\" . --multiline --content-only  # Content-only + multiline\n\n# PDF and document search (requires optional binaries)\n./mcp_fuzzy_search.py search-documents \"machine learning\" .  # Search PDFs and docs\n./mcp_fuzzy_search.py search-documents \"invoice total\" invoices/ --file-types \"pdf\"  # PDFs only\n./mcp_fuzzy_search.py search-documents \"contract\" . --file-types \"pdf,docx\" --limit 5\n./mcp_fuzzy_search.py search-documents \"report\" / --confirm-root  # Search from root (requires explicit confirmation)\n\n# Extract specific pages from PDFs (using PyMuPDF)\n./mcp_fuzzy_search.py extract-pdf manual.pdf \"1,3,5-7\"  # Extract pages 1, 3, 5, 6, 7\n./mcp_fuzzy_search.py extract-pdf report.pdf \"v-vii,1,ToC\"  # Use page labels\n./mcp_fuzzy_search.py extract-pdf report.pdf \"10-20\" --format html  # Extract as HTML\n./mcp_fuzzy_search.py extract-pdf thesis.pdf \"100-105\" --preserve-layout  # Keep layout\n./mcp_fuzzy_search.py extract-pdf book.pdf \"1-50\" --fuzzy-hint \"neural network\"  # Filter by content\n./mcp_fuzzy_search.py extract-pdf book.pdf \"0,266-273\" --zero-based  # 0-based indices (pages 1, 267-274)\n./mcp_fuzzy_search.py extract-pdf book.pdf \"1-50\" --one-based  # 1-based indices (pages 1-50)\n\n# Get PDF information\n./mcp_fuzzy_search.py page-labels manual.pdf  # List all page labels\n./mcp_fuzzy_search.py page-labels manual.pdf --start 100 --limit 20  # Get labels for pages 100-119\n./mcp_fuzzy_search.py page-count manual.pdf  # Get total page count\n./mcp_fuzzy_search.py pdf-outline manual.pdf  # Get table of contents\n./mcp_fuzzy_search.py pdf-outline manual.pdf --max-depth 2  # Limit to 2 levels\n./mcp_fuzzy_search.py pdf-outline manual.pdf --fuzzy-filter \"chapter\"  # Filter by title\n./mcp_fuzzy_search.py pdf-outline manual.pdf --no-simple  # Detailed output with links\n```\n\n### SQLite Server\n\n#### As an MCP Server\n\nOnce configured in Claude Desktop, you can use natural language for database operations:\n\n- \"List all tables in the database\"\n- \"Show me the schema for the users table\"\n- \"Query the last 10 orders from the orders table\"\n- \"Count active users in the database\"\n- \"Update user status to inactive for users who haven't logged in for a year\" (requires write permissions)\n- \"Create a new table for storing session data\" (requires write permissions)\n\n#### CLI Usage\n\nThe SQLite server also works as a standalone CLI tool:\n\n```bash\n# Query database (read-only operations)\n./mcp_sqlite_server.py query \"SELECT * FROM users\" database.db\n./mcp_sqlite_server.py query \"SELECT COUNT(*) as total FROM orders WHERE status = 'active'\" sales.db\n\n# List all tables\n./mcp_sqlite_server.py list-tables database.db\n\n# Describe table schema\n./mcp_sqlite_server.py describe-table users database.db\n\n# Execute write operations (requires --allow-writes flag)\n./mcp_sqlite_server.py execute \"INSERT INTO users (name, email) VALUES ('John', 'john@example.com')\" database.db --allow-writes\n./mcp_sqlite_server.py execute \"UPDATE users SET active = 0 WHERE last_login \u003c date('now', '-1 year')\" database.db --allow-writes\n\n# Use in-memory database for testing\n./mcp_sqlite_server.py query \"SELECT sqlite_version()\" :memory:\n```\n\n## Multiline Search Mode\n\nBoth MCP servers support **multiline search mode** which changes the search behavior:\n\n### What is Multiline Mode?\n\n**Default behavior (multiline=false):**\n- **File Search Server**: Searches file NAMES/PATHS only\n- **Fuzzy Search Server**: Searches line-by-line within file contents\n\n**With multiline mode (multiline=true):**\n- **File Search Server**: Switches to searching file CONTENTS instead of names\n- **Fuzzy Search Server**: Treats entire file contents as single searchable units\n\n### When to Use Multiline Mode\n\nMultiline mode is for searching file CONTENTS (not names):\n- **Finding class definitions** with their methods: `\"class UserService authenticate\"` (fuzzy match in contents)\n- **Locating function implementations**: `\"async function await fetch\"` (all terms in one file)\n- **Searching for configuration blocks**: `\"database host port\"` (finds files containing all terms)\n- **Finding code structures** across lines: `\"try catch finally\"` (fuzzy matches across lines)\n- **Important**: This searches CONTENTS, not file names!\n\n### Multiline Examples\n\n#### File Search Server Multiline (Content Search)\n```bash\n# With --multiline, searches file CONTENTS instead of names\n# Find files CONTAINING these terms (not in file names)\n./mcp_fd_server.py filter \"class constructor method\" \"\" src --multiline\n\n# Find Python files CONTAINING specific patterns  \n./mcp_fd_server.py filter \"class def return\" \"\" . --multiline\n\n# Find files CONTAINING database configuration\n./mcp_fd_server.py filter \"database host password\" \"\" config --multiline\n```\n\n#### Fuzzy Search Server Multiline\n```bash\n# search-files with --multiline searches file CONTENTS (not names)\n./mcp_fuzzy_search.py search-files \"async function await\" src --multiline\n\n# search-content with --multiline treats files as single units\n./mcp_fuzzy_search.py search-content \"try catch finally\" . --multiline\n\n# Find files CONTAINING class definitions with specific methods\n./mcp_fuzzy_search.py search-content \"class constructor render\" src --multiline\n```\n\n### Performance Considerations\n\n- **File size**: Multiline mode reads entire files into memory; best for typical source code files\n- **Result size**: Multiline results include complete file contents, which may be truncated for display\n- **Pattern complexity**: Simple fuzzy patterns work well; complex queries may be slower\n\n### Tips for Multiline Queries\n\n1. **Use specific terms**: `\"class MyClass def method\"` is better than just `\"class def\"` (no regex!)\n2. **Combine structure and content**: `\"import React export default\"` finds React components\n3. **Mind the output**: Results show the entire matching file content\n4. **Test incrementally**: Start with simple patterns and refine\n\n## fzf Search Syntax Guide\n\nBoth MCP servers use **fzf's extended search syntax** for powerful fuzzy filtering. Understanding this syntax will help you construct precise queries.\n\n**IMPORTANT**: The `fuzzy_filter` parameter in `fuzzy_search_content` does NOT support regular expressions. It uses fzf's fuzzy matching syntax as described below. If you need regex-like patterns, use the position anchors and exact matching features of fzf syntax instead.\n\n### Basic Syntax\n\n| Pattern | Description | Example |\n|---------|-------------|---------|\n| `term` | Fuzzy match (default) | `config` matches \"configuration\" |\n| `term1 term2` | AND logic (all terms must match) | `main config` requires both terms |\n| `term1 \\| term2` | OR logic (any term can match) | `py$ \\| js$ \\| go$` matches files ending in any |\n\n### Exact Matching\n\n| Pattern | Description | Example |\n|---------|-------------|---------|\n| `'term` | Partial exact match | `'main` exactly matches \"main\" substring |\n| `'term'` | Exact boundary match | `'main.py'` matches exactly at word boundaries |\n\n### Position Anchors\n\n| Pattern | Description | Example |\n|---------|-------------|---------|\n| `^term` | Prefix match (starts with) | `^src` matches \"src/file.py\" |\n| `term$` | Suffix match (ends with) | `.json$` matches \"config.json\" |\n| `^term$` | Exact match (entire string) | `^README$` matches only \"README\" |\n\n### Negation (Exclusion)\n\n| Pattern | Description | Example |\n|---------|-------------|---------|\n| `!term` | Exclude fuzzy matches | `config !test` excludes test files |\n| `!'term` | Exclude exact matches | `!'backup'` excludes files with exact \"backup\" |\n| `!^term` | Exclude prefix matches | `!^.` excludes hidden files |\n| `!term$` | Exclude suffix matches | `!.tmp$` excludes temporary files |\n\n### Advanced Examples\n\n**Note**: These examples show how to achieve regex-like filtering WITHOUT using regular expressions, since `fuzzy_filter` does not support regex.\n\n```bash\n# Find Python configuration files, excluding tests\nconfig .py$ !test\n\n# Find main files in src directory with multiple extensions  \n^src/ main py$ | js$ | go$\n\n# Find exact package manager files\n'package.json' | 'yarn.lock' | 'Pipfile'\n\n# Find TODO comments in code files, excluding documentation\nTODO .py$ | .js$ | .go$ !README !docs/\n\n# Find function definitions, excluding test files\n'def ' .py$ !test !spec\n\n# Find configuration files with specific extensions, excluding backups\nconfig .json$ | .yaml$ | .toml$ !.bak$ !.old$\n```\n\n### Content Search Specific Patterns\n\nWhen using `fuzzy_search_content`, queries work on the format `file:line:content`:\n\n**Default Mode (matches file paths AND content):**\n```bash\n# Find implementation TODOs in specific file types\nTODO implement .py: | .js:  # Matches TODO in .py or .js files\n\n# Find error handling in specific files\nerror 'main.py:' | 'app.js:'  # Matches 'error' in main.py or app.js\n\n# Find updates in test files\ntest.py: update  # Matches 'update' in files named test.py\n\n# Find async functions with error handling\n'async def' error .py$  # Matches in Python files\n```\n\n**Content-Only Mode (ignores file paths):**\n```bash\n# With --content-only flag or content_only=true parameter\n# These will ONLY match the content, not file names:\n\n# Find TODO comments regardless of filename\nTODO implement  # Won't match files named 'TODO.txt'\n\n# Find async/await patterns\nasync await catch  # Pure content search\n\n# Find class definitions\n'class ' 'def __init__'  # Won't match 'class.py' filename\n```\n\n## ripgrep (rg) Flags Reference\n\nThe `fuzzy_search_content` tool accepts `rg_flags` for enhanced searching. Here are the most useful flags:\n\n### Case Sensitivity\n| Flag | Description | Example |\n|------|-------------|---------|\n| `-i, --ignore-case` | Case insensitive search | `rg -i \"todo\"` matches TODO, Todo, todo |\n| `-S, --smart-case` | Case insensitive if lowercase, sensitive if mixed | `rg -S \"Todo\"` is case sensitive |\n| `-s, --case-sensitive` | Force case sensitive (default) | `rg -s \"TODO\"` matches only TODO |\n\n### File Type Filtering\n| Flag | Description | Example |\n|------|-------------|---------| \n| `-t TYPE` | Only search specific file types | `-t py` searches Python files only |\n| `-T TYPE` | Exclude specific file types | `-T test` excludes test files |\n| `--type-list` | Show all supported file types | `rg --type-list` |\n\n### Context Lines\n| Flag | Description | Example |\n|------|-------------|---------| \n| `-A NUM` | Show NUM lines after match | `-A 3` shows 3 lines after |\n| `-B NUM` | Show NUM lines before match | `-B 2` shows 2 lines before |\n| `-C NUM` | Show NUM lines before and after | `-C 3` shows 3 lines both sides |\n\n### File Handling\n| Flag | Description | Example |\n|------|-------------|---------| \n| `--hidden` | Search hidden files/directories | `--hidden` includes .hidden files |\n| `--no-ignore` | Ignore .gitignore rules | `--no-ignore` searches ignored files |\n| `-u` | Reduce filtering (1-3 times) | `-uu` = `--no-ignore --hidden` |\n\n### Pattern Matching\n| Flag | Description | Example |\n|------|-------------|---------| \n| `-F` | Literal string search (no regex) | `-F` searches for exact text |\n| `-w` | Match whole words only | `-w` won't match partial words |\n| `-v` | Invert match (show non-matches) | `-v` shows lines without matches |\n| `-x` | Match entire lines only | `-x` matches exact line |\n\n### Advanced Features\n| Flag | Description | Example |\n|------|-------------|---------| \n| `-U` | Enable multiline matching | `-U` (note: use multiline parameter instead) |\n| `-P` | Use PCRE2 regex engine | `-P` for advanced regex features |\n| `-o` | Show only matching parts | `-o` shows just matching text |\n\n### Output Control\n| Flag | Description | Example |\n|------|-------------|---------| \n| `-c` | Count matches per file | `-c` shows count only |\n| `-l` | Show only filenames with matches | `-l` lists files with matches |\n| `--column` | Show column numbers | `--column` includes column info |\n\n### Practical Combinations\n\n```bash\n# Case-insensitive search with context in Python files\nrg_flags: \"-i -C 3 -t py\"\n\n# Search all files including hidden and ignored, with context\nrg_flags: \"-uu -C 2\"\n\n# Find exact function signatures in code files\nrg_flags: \"-F -w -t py -t js -t go\"\n\n# Search for TODOs with file types, case insensitive, show context\nrg_flags: \"-i -C 1 -t py -t js --no-ignore\"\n\n# Multi-line class definitions with context\nrg_flags: \"-U -C 3 -t py\"\n\n# Literal string search in all text files\nrg_flags: \"-F --no-ignore -t txt -t md -t rst\"\n```\n\n## MCP Tools Documentation\n\n### File Search Server Tools\n\n#### `search_files`\nFind files by NAME using fd with regex or glob patterns.\n\n**Purpose:** Search for files when you know exact patterns, extensions, or regex for file NAMES.\n\n**Parameters:**\n- `pattern` (required): Regex or glob pattern to match file names\n- `path` (optional): Directory to search in (defaults to current directory)\n- `limit` (optional): Maximum number of results to return (default: 0 = no limit)\n- `flags` (optional): Additional flags to pass to fd\n\n**Example:**\n```python\n{\n  \"pattern\": r\"\\.py$\",  # Find files with names ending in .py\n  \"path\": \"/home/user/projects\",\n  \"flags\": \"--hidden --no-ignore\"\n}\n```\n\n#### `filter_files`\nFuzzy search for files by NAME using fzf's fuzzy matching.\n\n**Purpose:** Find files when you only know partial or approximate file NAMES.\n\n**Parameters:**\n- `filter` (required): Fuzzy search string to match against file names/paths\n- `pattern` (optional): Initial pattern for fd to pre-filter\n- `path` (optional): Directory to search in\n- `first` (optional): Return only the best match\n- `limit` (optional): Maximum number of results to return (default: 0 = no limit)\n- `fd_flags` (optional): Extra flags for fd\n- `fzf_flags` (optional): Extra flags for fzf\n- `multiline` (optional): When true, searches file CONTENTS instead of names (default: false)\n\nNote: When both `first` and `limit` are provided, `first` takes precedence and returns only the best match.\n\n**Example (File Name Search):**\n```python\n{\n  \"filter\": \"test\",  # Fuzzy match 'test' in file names\n  \"pattern\": r\"\\.py$\",  # Only Python files\n  \"path\": \"./src\",\n  \"first\": true\n}\n```\n\n**Multiline Example (Content Search):**\n```python\n{\n  \"filter\": \"class function return\",  # Find files containing all these terms\n  \"pattern\": \"\",\n  \"path\": \"./src\",\n  \"multiline\": true  # Search CONTENTS, not names\n}\n```\n\n### Fuzzy Search Server Tools\n\n#### `fuzzy_search_files`\nSearch for file NAMES/PATHS using fuzzy matching.\n\n**Purpose:** Find files by NAME when you only know partial names (e.g., \"mainpy\" finds \"main.py\").\n\n**Parameters:**\n- `fuzzy_filter` (required): Fuzzy search string for file names/paths\n- `path` (optional): Directory to search in (defaults to current directory)\n- `hidden` (optional): Include hidden files (default: false)\n- `limit` (optional): Maximum results to return (default: 20)\n- `multiline` (optional): When true, searches file CONTENTS instead of names (default: false)\n- `confirm_root` (optional): Allow searching from root directory (/) (default: false)\n\n**Example (File Name Search):**\n```python\n{\n  \"fuzzy_filter\": \"main\",  # Finds main.py, main.js, domain.py, etc.\n  \"path\": \"/home/user/projects\",\n  \"hidden\": true,\n  \"limit\": 10\n}\n```\n\n**Multiline Example (Content Search):**\n```python\n{\n  \"fuzzy_filter\": \"import export\",  # Find files containing both terms\n  \"path\": \"./src\",\n  \"multiline\": true,  # Search CONTENTS, not names\n  \"limit\": 5\n}\n```\n\n#### `fuzzy_search_content`\nSearch file contents with fuzzy filtering, matching on BOTH file paths AND content by default.\n\n**Purpose:** Find specific text/code using fuzzy search that considers both where it is (path) and what it is (content). Works consistently with both directories and individual files.\n\n**Parameters:**\n- `fuzzy_filter` (required): Fuzzy search query for filtering (does NOT support regex - use fzf syntax)\n- `path` (optional): Directory/file to search in (defaults to current directory)\n  - **Enhanced file path support**: Can now search both directories and individual files\n  - Automatically includes filename in output when searching a single file for consistent results\n- `hidden` (optional): Search hidden files (default: false)\n- `limit` (optional): Maximum results to return (default: 20)\n- `rg_flags` (optional): Extra flags for ripgrep (see ripgrep flags reference)\n- `multiline` (optional): Enable multiline record processing (default: false)\n- `content_only` (optional): Match ONLY on content, ignore file paths (default: false)\n- `confirm_root` (optional): Allow searching from root directory (/) (default: false)\n\n**Matching Behavior:**\n- **Default (content_only=false)**: Matches on BOTH file paths AND content (skips line numbers)\n  - This is why `\"test.py: update\"` finds \"update\" in test.py files - it matches the path!\n  - Searching `\"src TODO\"` finds TODO comments in files under src/ directory\n  - Even just `\"update\"` will match files named \"update.py\" OR containing \"update\"\n- **With content_only=true**: Matches ONLY on content, ignoring file paths entirely\n  - Pure content search - `\"update\"` won't match \"update.py\" filename, only content\n\n**Example (Default - Path + Content):**\n```python\n{\n  \"fuzzy_filter\": \"test.py: TODO implement\",  # Find TODOs in test.py files\n  \"path\": \"./src\",\n  \"rg_flags\": \"-i\",\n  \"limit\": 15\n}\n```\n\n**Example (Single File Search):**\n```python\n{\n  \"fuzzy_filter\": \"function async\",  # Find async functions in a specific file\n  \"path\": \"./src/main.py\",  # Search within a single file\n  \"limit\": 10\n}\n```\n\n**Example (Content Only):**\n```python\n{\n  \"fuzzy_filter\": \"async await catch\",  # Find these terms in content only\n  \"path\": \"./src\",\n  \"content_only\": true,  # Ignore file paths in matching\n  \"limit\": 10\n}\n```\n\n#### `fuzzy_search_documents`\nSearch through PDFs and other document formats using ripgrep-all (requires optional binaries).\n\n**Purpose:** Search PDFs, Office documents, archives, and other binary formats that regular text search can't handle.\n\n**Parameters:**\n- `fuzzy_filter` (required): Fuzzy search query for document content\n- `path` (optional): Directory/file to search in (defaults to current directory)\n- `file_types` (optional): Comma-separated file types to search (e.g., \"pdf,docx,epub\")\n- `preview` (optional): Include preview context (default: true)\n- `limit` (optional): Maximum results to return (default: 20)\n- `confirm_root` (optional): Allow searching from root directory (/) (default: false)\n\n**Example:**\n```python\n{\n  \"fuzzy_filter\": \"machine learning algorithm\",\n  \"path\": \"./research\",\n  \"file_types\": \"pdf,epub\",\n  \"limit\": 10\n}\n```\n\n**Returns:**\n```python\n{\n  \"matches\": [\n    {\n      \"file\": \"/path/to/document.pdf\",\n      \"line\": 0,\n      \"content\": \"topology.\",  # Content without \"Page N: \" prefix\n      \"match_text\": \"topology\",\n      \"page\": 542,  # 1-based page number (from ripgrep-all)\n      \"page_index_0based\": 541,  # 0-based page index for programmatic access\n      \"page_label\": \"19\"  # Actual PDF page label (only for PDFs with PyMuPDF)\n    }\n  ]\n}\n```\n\n**Note:** For PDF files, the tool returns:\n- `page`: The 1-based page number from ripgrep-all (e.g., 542 means the 542nd page)\n- `page_index_0based`: The 0-based page index for programmatic access (e.g., 541 for page 542)\n- `page_label`: The actual page label as shown in PDF readers (e.g., \"vii\", \"ToC\", \"19\")\n\nThe content field no longer includes the \"Page N: \" prefix for cleaner output.\n\n#### `extract_pdf_pages`\nExtract specific pages from a PDF and convert to various formats using PyMuPDF.\n\n**Purpose:** Extract individual pages or page ranges from PDFs with support for page labels/aliases as they appear in PDF readers.\n\n**Parameters:**\n- `file` (required): Path to PDF file\n- `pages` (required): Comma-separated page specifications - supports:\n  - Page labels: \"v\", \"vii\", \"ToC\", \"Introduction\" (as shown in PDF readers)\n  - Page ranges: \"v-vii\", \"1-5\"\n  - Physical pages: \"1\", \"14\" (1-based if not found as label)\n  - Mixed: \"v,vii,1,5-8,ToC\"\n- `format` (optional): Output format - markdown, html, plain (default: markdown)\n- `preserve_layout` (optional): Try to preserve original layout (default: false)\n- `clean_html` (optional): Strip HTML styling tags like `\u003cspan style=\"...\"\u003e` (default: true)\n- `fuzzy_hint` (optional): Fuzzy search string to filter extracted pages by content\n- `zero_based` (optional): Interpret page numbers as 0-based indices (default: false)\n  - When true, all numbers are treated as direct 0-based page indices\n  - \"0\" = first page, \"266\" = 267th page, \"0-4\" = first 5 pages\n  - No page label lookup is performed when this is true\n  - Cannot be used together with `one_based`\n- `one_based` (optional): Interpret page numbers as 1-based indices (default: false)\n  - When true, all numbers are treated as direct 1-based page indices\n  - \"1\" = first page, \"267\" = 267th page, \"1-5\" = first 5 pages\n  - No page label lookup is performed when this is true\n  - Cannot be used together with `zero_based`\n\n**Example:**\n```python\n{\n  \"file\": \"research_paper.pdf\",\n  \"pages\": \"v-vii,1,5-10,ToC\",  # Mix of page labels and numbers\n  \"format\": \"markdown\",\n  \"clean_html\": true,\n  \"fuzzy_hint\": \"neural network\"  # Only include pages mentioning this\n}\n\n# Example with zero_based=true\n{\n  \"file\": \"research_paper.pdf\",\n  \"pages\": \"0,266-273\",  # Direct 0-based indices: page 1 and pages 267-274\n  \"zero_based\": true\n}\n\n# Example with one_based=true\n{\n  \"file\": \"research_paper.pdf\",\n  \"pages\": \"1,267-274\",  # Direct 1-based indices: pages 1, 267-274\n  \"one_based\": true\n}\n```\n\n#### `get_pdf_page_labels`\nGet all page labels from a PDF file.\n\n**Purpose:** Returns a mapping of page indices to their labels/aliases as shown in PDF readers, helpful for understanding available page labels before extraction.\n\n**Parameters:**\n- `file` (required): Path to PDF file\n- `start` (optional): 0-based start index for slicing results (default: 0)\n- `limit` (optional): Maximum number of labels to return (default: all pages)\n\n**Example:**\n```python\n{\n  \"file\": \"research_paper.pdf\"\n}\n\n# Returns something like:\n{\n  \"page_labels\": {\n    \"0\": \"Cover\",\n    \"1\": \"i\",\n    \"2\": \"ii\", \n    \"3\": \"iii\",\n    \"4\": \"iv\",\n    \"5\": \"v\",\n    \"6\": \"vi\",\n    \"7\": \"vii\",\n    \"8\": \"viii\",\n    \"9\": \"1\",\n    \"10\": \"2\",\n    \"11\": \"3\"\n  },\n  \"page_count\": 150\n}\n\n# Example with slicing:\n{\n  \"file\": \"research_paper.pdf\",\n  \"start\": 100,\n  \"limit\": 20\n}\n\n# Returns subset like:\n{\n  \"page_labels\": {\n    \"100\": \"87\",\n    \"101\": \"88\",\n    \"102\": \"89\",\n    \"103\": \"90\",\n    \"104\": \"91\"\n    # ... up to 20 entries\n  },\n  \"page_count\": 150\n}\n```\n\n#### `get_pdf_page_count`\nGet the total number of pages in a PDF file.\n\n**Purpose:** Returns the total page count, useful for understanding the document size before extraction.\n\n**Parameters:**\n- `file` (required): Path to PDF file\n\n**Example:**\n```python\n{\n  \"file\": \"research_paper.pdf\"\n}\n\n# Returns:\n{\n  \"page_count\": 150\n}\n```\n\n#### `get_pdf_outline`\nExtract the table of contents (outline/bookmarks) from a PDF file.\n\n**Purpose:** Returns the hierarchical outline structure with levels, titles, page numbers, and page labels, helpful for navigating complex PDFs and understanding document structure.\n\n**Parameters:**\n- `file` (required): Path to PDF file\n- `simple` (optional): Return basic info (default: true) or detailed info with link data (false)\n- `max_depth` (optional): Maximum depth to traverse in the outline hierarchy (default: unlimited)\n- `fuzzy_filter` (optional): Fuzzy search string to filter outline entries by title using fzf\n\n**Example:**\n```python\n{\n  \"file\": \"research_paper.pdf\"\n}\n\n# Returns (simple mode):\n{\n  \"outline\": [\n    [1, \"Introduction\", 1, \"i\"],\n    [1, \"Chapter 1: Background\", 5, \"1\"],\n    [2, \"1.1 History\", 6, \"2\"],\n    [2, \"1.2 Related Work\", 10, \"6\"],\n    [1, \"Chapter 2: Methods\", 15, \"11\"],\n    [2, \"2.1 Data Collection\", 16, \"12\"],\n    [3, \"2.1.1 Sources\", 17, \"13\"],\n    [2, \"2.2 Analysis\", 20, \"16\"]\n  ],\n  \"total_entries\": 8,\n  \"max_depth_found\": 3\n}\n\n# Example with filtering:\n{\n  \"file\": \"research_paper.pdf\",\n  \"fuzzy_filter\": \"chapter\"\n}\n\n# Returns:\n{\n  \"outline\": [\n    [1, \"Chapter 1: Background\", 5, \"1\"],\n    [1, \"Chapter 2: Methods\", 15, \"11\"]\n  ],\n  \"total_entries\": 8,\n  \"max_depth_found\": 3,\n  \"filtered_count\": 2\n}\n\n# Example with detailed output:\n{\n  \"file\": \"research_paper.pdf\",\n  \"simple\": false,\n  \"max_depth\": 2\n}\n\n# Returns:\n{\n  \"outline\": [\n    [1, \"Introduction\", 1, \"i\", {\n      \"page\": 1,\n      \"uri\": \"#page=1\u0026zoom=100,0,0\",\n      \"is_external\": false,\n      \"is_open\": true,\n      \"dest\": {\n        \"kind\": 1,\n        \"page\": 0,\n        \"uri\": \"#page=1\u0026zoom=100,0,0\"\n      }\n    }],\n    # ... more entries with link details\n  ],\n  \"total_entries\": 8,\n  \"max_depth_found\": 2\n}\n```\n\n**Outline Format:**\n- Simple mode returns: `[level, title, page, page_label]`\n  - `level`: Hierarchy level (1-based, 1 = top level)\n  - `title`: The bookmark/outline entry title\n  - `page`: Page number (1-based)\n  - `page_label`: Page label as shown in PDF readers (e.g., \"i\", \"ii\", \"1\", \"ToC\")\n- Detailed mode adds a 5th element with link information including destination details\n\n### SQLite Server Tools\n\n#### `query`\nExecute SELECT queries on the database.\n\n**Parameters:**\n- `query` (required): SELECT query to execute\n- `db_path` (optional): Path to SQLite database (defaults to configured db_path or ':memory:')\n\n**Example:**\n```python\n{\n  \"query\": \"SELECT * FROM users WHERE active = 1 ORDER BY created_at DESC LIMIT 10\",\n  \"db_path\": \"myapp.db\"\n}\n```\n\n#### `execute`\nExecute INSERT, UPDATE, or DELETE queries (requires write permissions).\n\n**Parameters:**\n- `query` (required): INSERT, UPDATE, or DELETE query to execute\n- `db_path` (optional): Path to SQLite database\n\n**Example:**\n```python\n{\n  \"query\": \"UPDATE users SET last_login = datetime('now') WHERE id = 123\",\n  \"db_path\": \"myapp.db\"\n}\n```\n\n#### `list_tables`\nList all tables in the database.\n\n**Parameters:**\n- `db_path` (optional): Path to SQLite database\n\n**Example:**\n```python\n{\n  \"db_path\": \"myapp.db\"\n}\n```\n\n#### `describe_table`\nGet detailed schema information for a specific table, including columns, types, constraints, and indexes.\n\n**Parameters:**\n- `table_name` (required): Name of the table to describe\n- `db_path` (optional): Path to SQLite database\n\n**Example:**\n```python\n{\n  \"table_name\": \"users\",\n  \"db_path\": \"myapp.db\"\n}\n```\n\n#### `create_table`\nCreate a new table with specified columns (requires write permissions).\n\n**Parameters:**\n- `table_name` (required): Name of the table to create\n- `columns` (required): List of column definitions\n- `db_path` (optional): Path to SQLite database\n\n**Column Definition:**\n- `name` (required): Column name\n- `type` (required): SQLite data type (TEXT, INTEGER, REAL, BLOB, etc.)\n- `constraints` (optional): Column constraints (PRIMARY KEY, NOT NULL, UNIQUE, etc.)\n\n**Example:**\n```python\n{\n  \"table_name\": \"sessions\",\n  \"columns\": [\n    {\n      \"name\": \"id\",\n      \"type\": \"TEXT\",\n      \"constraints\": \"PRIMARY KEY\"\n    },\n    {\n      \"name\": \"user_id\",\n      \"type\": \"INTEGER\",\n      \"constraints\": \"NOT NULL\"\n    },\n    {\n      \"name\": \"created_at\",\n      \"type\": \"TIMESTAMP\",\n      \"constraints\": \"DEFAULT CURRENT_TIMESTAMP\"\n    },\n    {\n      \"name\": \"expires_at\",\n      \"type\": \"TIMESTAMP\",\n      \"constraints\": \"NOT NULL\"\n    }\n  ],\n  \"db_path\": \"myapp.db\"\n}\n```\n\n## Development\n\n### Project Structure\n```\nmcp-personal/\n├── mcp_fd_server.py      # File search MCP server\n├── mcp_fuzzy_search.py   # Fuzzy content search MCP server\n├── mcp_sqlite_server.py  # SQLite database MCP server\n├── tests/                # Test suite\n│   ├── test_simple.py    # Direct function tests\n│   ├── test_fd_server.py # File search MCP integration tests\n│   ├── test_fuzzy_search.py # Fuzzy search tests\n│   ├── test_sqlite_server.py # SQLite server tests\n│   └── test_cli.py       # CLI interface tests\n├── pyproject.toml        # Project configuration\n├── Makefile              # Development commands\n├── CLAUDE.md             # Claude-specific instructions\n└── README.md             # This file\n```\n\n### Adding New MCP Servers\n\nTo add a new MCP server to this collection:\n\n1. Create a new Python file (e.g., `mcp_new_server.py`)\n2. Implement using FastMCP framework\n3. Add tests in the `tests/` directory\n4. Update this README with documentation\n5. Add configuration example for Claude Desktop\n\n### Running Tests\n\n```bash\n# Run all tests\nmake test\n\n# Run specific test categories\nmake test-simple  # Direct function tests\nmake test-cli     # CLI interface tests\nmake test-full    # Full MCP integration tests\n\n# Run with coverage\nmake test-cov\n```\n\n### Development Commands\n\n```bash\nmake help         # Show all available commands\nmake setup        # Install development dependencies\nmake test         # Run tests\nmake lint         # Run linting\nmake format       # Format code\nmake type-check   # Run type checking\nmake clean        # Clean generated files\n```\n\n### Contributing\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Make your changes\n4. Run tests (`make test`)\n5. Run linting (`make check`)\n6. Commit your changes\n7. Push to the branch (`git push origin feature/amazing-feature`)\n8. Open a Pull Request\n\n## Architecture\n\nAll MCP servers in this collection are built using:\n- **FastMCP**: High-level MCP server framework from the official Python SDK\n- **uv**: Fast Python package manager\n- **Self-contained scripts**: Each server uses `#!/usr/bin/env -S uv run --script` for easy deployment\n\n### File Search Server\nAdditionally uses:\n- **fd**: Modern file finder written in Rust\n- **fzf**: Command-line fuzzy finder\n\n### Fuzzy Search Server\nAdditionally uses:\n- **ripgrep**: Extremely fast search tool that respects gitignore\n- **fzf**: Command-line fuzzy finder (used in filter mode)\n\n## Security Considerations\n\n### General\n- All servers run with the permissions of the user executing them\n- Consider the security implications of each server's capabilities\n- Review server code before installation\n\n### Root Path Protection\n- **Built-in safety mechanism**: All search functions prevent accidental searches from root directory (/) by default\n- Searching from root without explicit confirmation returns an error message\n- To search from root directory, you must explicitly set `confirm_root=True` (MCP tools) or use `--confirm-root` flag (CLI)\n- This prevents unintended performance issues and excessive filesystem access\n- Cross-platform support: protects against both Unix root (/) and Windows drive roots (C:\\, etc.)\n\n### File Search Server\n- Has filesystem access based on user permissions\n- Be cautious when searching in sensitive directories\n- The `--no-ignore` flag will include files normally hidden by `.gitignore`\n\n### Fuzzy Search Server\n- Has filesystem read access based on user permissions\n- Can search file contents, including source code and configuration files\n- Respects `.gitignore` by default (use `--hidden` to include ignored files)\n- Be mindful when searching in repositories with sensitive data\n\n### SQLite Server\n- **Read-only by default** - Prevents accidental data modification\n- Write operations require explicit `--allow-writes` flag or environment variable\n- Has full database access based on file permissions\n- Can execute arbitrary SQL queries when write mode is enabled\n- Be extremely cautious with write permissions on production databases\n- Consider using separate read-only database users when possible\n\n## Troubleshooting\n\n### \"Cannot find the `fd` binary\"\n- Ensure fd is installed and in your PATH\n- On Debian/Ubuntu, fd might be installed as `fdfind`\n\n### \"Cannot find the `fzf` binary\"\n- Install fzf using your package manager\n- Ensure it's available in your PATH\n\n### \"Searching from root directory (/) is likely incorrect and could be very slow\"\n- This safety message appears when trying to search from the root directory without explicit confirmation\n- To search from root, add `confirm_root=True` parameter (MCP tools) or `--confirm-root` flag (CLI)\n- Consider using a more specific directory path instead for better performance\n- Example: `./mcp_fuzzy_search.py search-files \"config\" / --confirm-root`\n\n### Tests failing\n- Check that required binaries are installed for each server\n- Run `make check-deps` to verify binaries are available\n- Some tests require a Unix-like environment\n\n## License\n\nThis project is open source and available under the [MIT License](LICENSE).\n\n## Acknowledgments\n\n- [Model Context Protocol](https://modelcontextprotocol.io) - The protocol enabling AI-tool interactions\n- [FastMCP](https://github.com/jlowin/fastmcp) - The Python framework for building MCP servers\n- [uv](https://github.com/astral-sh/uv) - An extremely fast Python package installer and resolver\n\n### File Search Server\n- [fd](https://github.com/sharkdp/fd) - A simple, fast and user-friendly alternative to find\n- [fzf](https://github.com/junegunn/fzf) - A command-line fuzzy finder\n\n### Fuzzy Search Server\n- [ripgrep](https://github.com/BurntSushi/ripgrep) - Recursively search directories for text patterns\n- [fzf](https://github.com/junegunn/fzf) - A command-line fuzzy finder\n- [PyMuPDF](https://github.com/pymupdf/PyMuPDF) - Python bindings for MuPDF for PDF processing (optional)\n- [ripgrep-all](https://github.com/phiresky/ripgrep-all) - ripgrep, but also search in PDFs, E-Books, Office documents (optional)\n- [pandoc](https://pandoc.org/) - Universal markup converter (optional)\n\n### SQLite Server\n- [SQLite](https://www.sqlite.org/) - Self-contained, serverless, zero-configuration SQL database engine\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdashed%2Fmcp-personal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdashed%2Fmcp-personal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdashed%2Fmcp-personal/lists"}