MCP Personal
A collection of MCP servers for various personal productivity tools and utilities.
MCP Personal - Collection of Personal MCP Servers
A collection of Model Context Protocol (MCP) servers for various personal productivity tools and utilities.
Available MCP Servers
1. File Search Server (mcp_fd_server.py
)
Fuzzy file NAME search capabilities using fd
and fzf
:
- Fast file name search using
fd
(searches file names/paths, NOT contents) - Fuzzy filtering of file names with
fzf
for intelligent name matching - Pattern matching with regex and glob support for file names
- Result limiting with
limit
parameter to restrict number of matches - Proper error handling for fzf exit codes (distinguishes "no matches" from errors)
- Multiline mode (advanced): can also search file contents when enabled
- Standalone CLI for testing and direct usage
- Key point: Primary purpose is finding files by NAME, not searching contents
2. Fuzzy Search Server (mcp_fuzzy_search.py
)
Advanced search with both file name and content capabilities using ripgrep
and fzf
:
- File name fuzzy search - find files by partial/fuzzy names
- Content search using
ripgrep
to search text within files - Fuzzy filtering of results using
fzf --filter
- Proper error handling for fzf exit codes (distinguishes "no matches" from errors)
- Two distinct modes:
fuzzy_search_files
: Search file NAMES/pathsfuzzy_search_content
: Search file CONTENTS with path+content matching by default
- PDF and document search (optional) - search through PDFs, Office docs, and archives using
ripgrep-all
- PDF page extraction (optional) - extract specific pages from PDFs using PyMuPDF with page label support
- PDF information tools (optional) - get page labels, page count, and table of contents from PDF files:
get_pdf_page_labels
: Get all page labels from a PDF fileget_pdf_page_count
: Get the total number of pages in a PDF fileget_pdf_outline
: Extract table of contents/bookmarks from a PDF file
- Simplified interface - just provide fuzzy search terms (NO regex support)
- Multiline record processing for complex pattern matching
- Standalone CLI for testing and direct usage
3. SQLite Server (mcp_sqlite_server.py
)
SQLite database operations with configurable read/write permissions:
- Read-only by default - Write operations disabled unless explicitly enabled
- Agent-friendly - Clear tool descriptions and examples for easy AI agent usage
- In-memory database support - Use
:memory:
for temporary databases - Comprehensive operations - Query, execute, list tables, describe schema, create tables
- Safety features - Query validation, write operation restrictions, clear error messages
- Standalone CLI for testing and direct usage
Prerequisites
General Requirements
- Python 3.10 or higher
- uv (recommended) or pip
To install uv:
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Or using pip (if you already have Python)
pip install uv
Note on Optional Features
The 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.
File Search Server Requirements
The file search server requires the following command-line tools:
macOS
brew install fd fzf
Ubuntu/Debian
sudo apt install fd-find fzf
# Note: On Debian/Ubuntu, fd is installed as 'fdfind'
Other Systems
Fuzzy Search Server Requirements
The fuzzy search server requires:
macOS
brew install ripgrep fzf
# For PDF search capabilities (optional)
brew install ripgrep-all pandoc
pip install PyMuPDF # Or: uv pip install PyMuPDF
Ubuntu/Debian
sudo apt install ripgrep fzf
# For PDF search capabilities (optional)
# Install ripgrep-all
cargo install ripgrep-all # Requires Rust/cargo
# Install PyMuPDF
pip install PyMuPDF # Or: uv pip install PyMuPDF
# Install pandoc
sudo apt install pandoc
Other Systems
- ripgrep installation guide
- fzf installation guide
- ripgrep-all installation (optional, for PDF search)
- pandoc installation (optional, for PDF extraction)
Installation
Clone the Repository
git clone https://github.com/yourusername/mcp-personal.git
cd mcp-personal
Configure MCP Servers
Using Claude Code CLI
The easiest way to add MCP servers to Claude Code is using the CLI:
# Add published npm servers (recommended to use -s user for global access)
claude mcp add sequential-thinking -s user -- npx -y @modelcontextprotocol/server-sequential-thinking
# Add custom Python servers from this repository
# IMPORTANT: Use -s user for personal tools you want available across all projects
# Without -s flag, servers are only available in current directory and are temporary
# Easy method: Use $(pwd) when in the project directory
cd /path/to/mcp-personal
claude mcp add file-search -s user -- $(pwd)/mcp_fd_server.py
claude mcp add fuzzy-search -s user -- $(pwd)/mcp_fuzzy_search.py
claude mcp add sqlite -s user -- $(pwd)/mcp_sqlite_server.py
# Or use relative paths (also from project directory)
claude mcp add file-search -s user -- ./mcp_fd_server.py
claude mcp add fuzzy-search -s user -- ./mcp_fuzzy_search.py
claude mcp add sqlite -s user -- ./mcp_sqlite_server.py
# Using absolute paths (works from anywhere)
claude mcp add file-search -s user -- /path/to/mcp-personal/mcp_fd_server.py
claude mcp add fuzzy-search -s user -- /path/to/mcp-personal/mcp_fuzzy_search.py
claude mcp add sqlite -s user -- /path/to/mcp-personal/mcp_sqlite_server.py
# Add SQLite server with write permissions enabled
claude mcp add sqlite -s user -- /path/to/mcp-personal/mcp_sqlite_server.py --allow-writes
# Or using environment variable
claude mcp add sqlite -s user -e MCP_SQLITE_ALLOW_WRITES=true -- /path/to/mcp-personal/mcp_sqlite_server.py
# Add Python servers with Python interpreter explicitly
claude mcp add my-server -s user -- python /path/to/my_mcp_server.py
# Add servers with arguments
claude mcp add my-server -s user -- python /path/to/server.py arg1 arg2
# Add servers with environment variables
claude mcp add my-server -s user -e API_KEY=your_key -e DEBUG=true -- python /path/to/server.py
# Scope options:
# -s local (default): Temporary, only in current directory
# -s project: Shared with team via .mcp.json file
# -s user: Personal, available across all your projects (recommended)
Note:
- The
--
separator is important before the command and its arguments - Environment variables use
-e KEY=value
syntax - Use
-s user
for personal servers available across all projects - Both relative and absolute paths work
Manual Configuration (Claude Desktop)
For Claude Desktop, manually add servers to ~/Library/Application Support/Claude/claude_desktop_config.json
:
{
"mcpServers": {
"file-search": {
"command": "/path/to/mcp-personal/mcp_fd_server.py"
},
"fuzzy-search": {
"command": "/path/to/mcp-personal/mcp_fuzzy_search.py"
},
"sqlite": {
"command": "/path/to/mcp-personal/mcp_sqlite_server.py",
"args": ["--allow-writes"],
"env": {
"MCP_SQLITE_ALLOW_WRITES": "true"
}
}
}
}
Make Scripts Executable
# Make all Python scripts executable
chmod +x *.py
For Development
# Install with development dependencies
uv sync --dev
# Or use make
make setup
Testing and Development
MCP Inspector
The MCP Inspector is an interactive developer tool for testing and debugging MCP servers. It provides a web-based interface that allows you to:
- Visually test your MCP servers with an interactive UI
- Debug server implementations by examining request/response flows
- Test tools, resources, and prompts with different arguments
- Validate server behavior before deployment
Quick Testing
Test any MCP server using the inspector:
# Test the file search server
npx @modelcontextprotocol/inspector ./mcp_fd_server.py
# Test the fuzzy search server
npx @modelcontextprotocol/inspector ./mcp_fuzzy_search.py
# Test the SQLite server (read-only mode)
npx @modelcontextprotocol/inspector ./mcp_sqlite_server.py
# Test the SQLite server with write permissions
npx @modelcontextprotocol/inspector ./mcp_sqlite_server.py -- --allow-writes
This will:
- Start the MCP Inspector proxy server (default port 6277)
- Launch a web interface (default port 6274)
- Connect to your MCP server via stdio transport
- Open your browser to the inspector interface
Using the Inspector
Once the inspector is running:
- Navigate to the web interface (usually http://localhost:6274)
- Explore the tabs:
- Tools: Test
search_files
,filter_files
,fuzzy_search_files
,fuzzy_search_content
,fuzzy_search_documents
,extract_pdf_pages
- Resources: View any exposed resources (if implemented)
- Prompts: Test any exposed prompts (if implemented)
- Tools: Test
- Test different scenarios:
- Try various search patterns and filters
- Test multiline functionality
- Experiment with different file paths and flags
- Test PDF search with
fuzzy_search_documents
(if binaries installed) - Test PDF page extraction with
extract_pdf_pages
(if binaries installed) - Validate error handling with invalid inputs
Advanced Configuration
You can also use configuration files for complex setups:
# Using a config file
npx @modelcontextprotocol/inspector --config config.json
# Passing environment variables
npx @modelcontextprotocol/inspector -e "DEBUG=1" ./mcp_fuzzy_search.py
# Custom ports
npx @modelcontextprotocol/inspector --mcpp-port 3001 --mcpi-port 3002 ./mcp_fd_server.py
The MCP Inspector is particularly valuable for:
- Rapid prototyping - quickly test new functionality
- Debugging - identify issues before integration with Claude
- Documentation - understand exactly what your server exposes
- Validation - ensure proper error handling and edge cases
Usage
File Search Server
As an MCP Server
Once configured in Claude Desktop, you can use natural language to search for files by NAME:
- "Find all Python files in the src directory" (searches file names ending in .py)
- "Search for files with 'config' in their name" (fuzzy matches file names)
- "Find test files by name" (searches for files with 'test' in the name)
- "Use fuzzy search to find 'mainpy'" (finds main.py, main_py.txt, etc.)
CLI Usage
The file search server also works as a standalone CLI tool:
# Search for files by name pattern
./mcp_fd_server.py search "\.py$" /path/to/search # Find Python files by name
./mcp_fd_server.py search "\.py$" . --limit 10 # Limit to first 10 results
# Search with additional fd flags
./mcp_fd_server.py search "\.js$" . --flags "--hidden --no-ignore"
# Fuzzy filter file names/paths
./mcp_fd_server.py filter "main" "\.py$" /path/to/search # Fuzzy search for 'main' in Python file names
./mcp_fd_server.py filter "test" "" . --limit 20 # Find up to 20 test-related files
# Get the best fuzzy match by name
./mcp_fd_server.py filter "app" "" . --first # Find file with name most similar to 'app'
# Multiline mode - search file CONTENTS (not just names)
./mcp_fd_server.py filter "class function" "" src --multiline # Find files containing both terms
./mcp_fd_server.py filter "TODO" "" . --multiline --limit 5 # Find first 5 files with TODOs
Fuzzy Search Server
As an MCP Server
Once configured in Claude Desktop, you can use natural language for advanced searching:
- "Search for TODO comments that mention 'implement'"
- "Find all files with 'test' in the name using fuzzy search"
- "Look for error handling code in Python files"
- "Search for configuration files containing database settings"
- "Find method definitions named 'update_ondemand_max_spend'"
- "Search for async functions with error handling"
- "Search for 'update' in test.py files only" (works because default mode matches paths too!)
- "Search for 'async' in content only, ignore file paths" (use content_only mode)
- "Search for 'vector' in PDF documents" (requires ripgrep-all)
- "Find all references to 'machine learning' in PDFs and Word documents"
- "Extract pages 5-10 from the user manual PDF"
- "Get the table of contents from the research paper PDF"
- "Show me the outline of chapters in the user manual"
CLI Usage
The fuzzy search server also works as a standalone CLI tool:
# Fuzzy search for file NAMES/PATHS
./mcp_fuzzy_search.py search-files "main" /path/to/search # Find files with 'main' in the name
./mcp_fuzzy_search.py search-files "test" . --hidden --limit 10 # Find test files by name
./mcp_fuzzy_search.py search-files "config" / --confirm-root # Search from root (requires explicit confirmation)
# Search file CONTENTS and filter with fzf (NO regex support)
# Default: Matches on BOTH file paths AND content
# Works with both directories and individual files
./mcp_fuzzy_search.py search-content "TODO implement" . # Find lines containing both terms
./mcp_fuzzy_search.py search-content "test.py: update" . # Find 'update' in test.py files
./mcp_fuzzy_search.py search-content "function" specific_file.py # Search within a single file
./mcp_fuzzy_search.py search-content "error handle" src --rg-flags "-i" # Case insensitive
./mcp_fuzzy_search.py search-content "config" / --confirm-root # Search from root (requires explicit confirmation)
# Content-only mode: Match ONLY on content, ignore file paths
./mcp_fuzzy_search.py search-content "TODO implement" . --content-only # Pure content search
./mcp_fuzzy_search.py search-content "async await" src --content-only # Won't match file paths
# Multiline mode - changes behavior:
# search-files --multiline: Searches file CONTENTS instead of names
./mcp_fuzzy_search.py search-files "class constructor" src --multiline # Find files CONTAINING these terms
# search-content --multiline: Treats whole files as searchable units
./mcp_fuzzy_search.py search-content "async await" . --multiline # Find files with both terms anywhere
./mcp_fuzzy_search.py search-content "try catch" . --multiline --content-only # Content-only + multiline
# PDF and document search (requires optional binaries)
./mcp_fuzzy_search.py search-documents "machine learning" . # Search PDFs and docs
./mcp_fuzzy_search.py search-documents "invoice total" invoices/ --file-types "pdf" # PDFs only
./mcp_fuzzy_search.py search-documents "contract" . --file-types "pdf,docx" --limit 5
./mcp_fuzzy_search.py search-documents "report" / --confirm-root # Search from root (requires explicit confirmation)
# Extract specific pages from PDFs (using PyMuPDF)
./mcp_fuzzy_search.py extract-pdf manual.pdf "1,3,5-7" # Extract pages 1, 3, 5, 6, 7
./mcp_fuzzy_search.py extract-pdf report.pdf "v-vii,1,ToC" # Use page labels
./mcp_fuzzy_search.py extract-pdf report.pdf "10-20" --format html # Extract as HTML
./mcp_fuzzy_search.py extract-pdf thesis.pdf "100-105" --preserve-layout # Keep layout
./mcp_fuzzy_search.py extract-pdf book.pdf "1-50" --fuzzy-hint "neural network" # Filter by content
./mcp_fuzzy_search.py extract-pdf book.pdf "0,266-273" --zero-based # 0-based indices (pages 1, 267-274)
./mcp_fuzzy_search.py extract-pdf book.pdf "1-50" --one-based # 1-based indices (pages 1-50)
# Get PDF information
./mcp_fuzzy_search.py page-labels manual.pdf # List all page labels
./mcp_fuzzy_search.py page-labels manual.pdf --start 100 --limit 20 # Get labels for pages 100-119
./mcp_fuzzy_search.py page-count manual.pdf # Get total page count
./mcp_fuzzy_search.py pdf-outline manual.pdf # Get table of contents
./mcp_fuzzy_search.py pdf-outline manual.pdf --max-depth 2 # Limit to 2 levels
./mcp_fuzzy_search.py pdf-outline manual.pdf --fuzzy-filter "chapter" # Filter by title
./mcp_fuzzy_search.py pdf-outline manual.pdf --no-simple # Detailed output with links
SQLite Server
As an MCP Server
Once configured in Claude Desktop, you can use natural language for database operations:
- "List all tables in the database"
- "Show me the schema for the users table"
- "Query the last 10 orders from the orders table"
- "Count active users in the database"
- "Update user status to inactive for users who haven't logged in for a year" (requires write permissions)
- "Create a new table for storing session data" (requires write permissions)
CLI Usage
The SQLite server also works as a standalone CLI tool:
# Query database (read-only operations)
./mcp_sqlite_server.py query "SELECT * FROM users" database.db
./mcp_sqlite_server.py query "SELECT COUNT(*) as total FROM orders WHERE status = 'active'" sales.db
# List all tables
./mcp_sqlite_server.py list-tables database.db
# Describe table schema
./mcp_sqlite_server.py describe-table users database.db
# Execute write operations (requires --allow-writes flag)
./mcp_sqlite_server.py execute "INSERT INTO users (name, email) VALUES ('John', 'john@example.com')" database.db --allow-writes
./mcp_sqlite_server.py execute "UPDATE users SET active = 0 WHERE last_login < date('now', '-1 year')" database.db --allow-writes
# Use in-memory database for testing
./mcp_sqlite_server.py query "SELECT sqlite_version()" :memory:
Multiline Search Mode
Both MCP servers support multiline search mode which changes the search behavior:
What is Multiline Mode?
Default behavior (multiline=false):
- File Search Server: Searches file NAMES/PATHS only
- Fuzzy Search Server: Searches line-by-line within file contents
With multiline mode (multiline=true):
- File Search Server: Switches to searching file CONTENTS instead of names
- Fuzzy Search Server: Treats entire file contents as single searchable units
When to Use Multiline Mode
Multiline mode is for searching file CONTENTS (not names):
- Finding class definitions with their methods:
"class UserService authenticate"
(fuzzy match in contents) - Locating function implementations:
"async function await fetch"
(all terms in one file) - Searching for configuration blocks:
"database host port"
(finds files containing all terms) - Finding code structures across lines:
"try catch finally"
(fuzzy matches across lines) - Important: This searches CONTENTS, not file names!
Multiline Examples
File Search Server Multiline (Content Search)
# With --multiline, searches file CONTENTS instead of names
# Find files CONTAINING these terms (not in file names)
./mcp_fd_server.py filter "class constructor method" "" src --multiline
# Find Python files CONTAINING specific patterns
./mcp_fd_server.py filter "class def return" "" . --multiline
# Find files CONTAINING database configuration
./mcp_fd_server.py filter "database host password" "" config --multiline
Fuzzy Search Server Multiline
# search-files with --multiline searches file CONTENTS (not names)
./mcp_fuzzy_search.py search-files "async function await" src --multiline
# search-content with --multiline treats files as single units
./mcp_fuzzy_search.py search-content "try catch finally" . --multiline
# Find files CONTAINING class definitions with specific methods
./mcp_fuzzy_search.py search-content "class constructor render" src --multiline
Performance Considerations
- File size: Multiline mode reads entire files into memory; best for typical source code files
- Result size: Multiline results include complete file contents, which may be truncated for display
- Pattern complexity: Simple fuzzy patterns work well; complex queries may be slower
Tips for Multiline Queries
- Use specific terms:
"class MyClass def method"
is better than just"class def"
(no regex!) - Combine structure and content:
"import React export default"
finds React components - Mind the output: Results show the entire matching file content
- Test incrementally: Start with simple patterns and refine
fzf Search Syntax Guide
Both MCP servers use fzf's extended search syntax for powerful fuzzy filtering. Understanding this syntax will help you construct precise queries.
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.
Basic Syntax
Pattern | Description | Example |
---|---|---|
term | Fuzzy match (default) | config matches "configuration" |
term1 term2 | AND logic (all terms must match) | main config requires both terms |
term1 | term2 | OR logic (any term can match) | py$ | js$ | go$ matches files ending in any |
Exact Matching
Pattern | Description | Example |
---|---|---|
'term | Partial exact match | 'main exactly matches "main" substring |
'term' | Exact boundary match | 'main.py' matches exactly at word boundaries |
Position Anchors
Pattern | Description | Example |
---|---|---|
^term | Prefix match (starts with) | ^src matches "src/file.py" |
term$ | Suffix match (ends with) | .json$ matches "config.json" |
^term$ | Exact match (entire string) | ^README$ matches only "README" |
Negation (Exclusion)
Pattern | Description | Example |
---|---|---|
!term | Exclude fuzzy matches | config !test excludes test files |
!'term | Exclude exact matches | !'backup' excludes files with exact "backup" |
!^term | Exclude prefix matches | !^. excludes hidden files |
!term$ | Exclude suffix matches | !.tmp$ excludes temporary files |
Advanced Examples
Note: These examples show how to achieve regex-like filtering WITHOUT using regular expressions, since fuzzy_filter
does not support regex.
# Find Python configuration files, excluding tests
config .py$ !test
# Find main files in src directory with multiple extensions
^src/ main py$ | js$ | go$
# Find exact package manager files
'package.json' | 'yarn.lock' | 'Pipfile'
# Find TODO comments in code files, excluding documentation
TODO .py$ | .js$ | .go$ !README !docs/
# Find function definitions, excluding test files
'def ' .py$ !test !spec
# Find configuration files with specific extensions, excluding backups
config .json$ | .yaml$ | .toml$ !.bak$ !.old$
Content Search Specific Patterns
When using fuzzy_search_content
, queries work on the format file:line:content
:
Default Mode (matches file paths AND content):
# Find implementation TODOs in specific file types
TODO implement .py: | .js: # Matches TODO in .py or .js files
# Find error handling in specific files
error 'main.py:' | 'app.js:' # Matches 'error' in main.py or app.js
# Find updates in test files
test.py: update # Matches 'update' in files named test.py
# Find async functions with error handling
'async def' error .py$ # Matches in Python files
Content-Only Mode (ignores file paths):
# With --content-only flag or content_only=true parameter
# These will ONLY match the content, not file names:
# Find TODO comments regardless of filename
TODO implement # Won't match files named 'TODO.txt'
# Find async/await patterns
async await catch # Pure content search
# Find class definitions
'class ' 'def __init__' # Won't match 'class.py' filename
ripgrep (rg) Flags Reference
The fuzzy_search_content
tool accepts rg_flags
for enhanced searching. Here are the most useful flags:
Case Sensitivity
Flag | Description | Example |
---|---|---|
-i, --ignore-case | Case insensitive search | rg -i "todo" matches TODO, Todo, todo |
-S, --smart-case | Case insensitive if lowercase, sensitive if mixed | rg -S "Todo" is case sensitive |
-s, --case-sensitive | Force case sensitive (default) | rg -s "TODO" matches only TODO |
File Type Filtering
Flag | Description | Example |
---|---|---|
-t TYPE | Only search specific file types | -t py searches Python files only |
-T TYPE | Exclude specific file types | -T test excludes test files |
--type-list | Show all supported file types | rg --type-list |
Context Lines
Flag | Description | Example |
---|---|---|
-A NUM | Show NUM lines after match | -A 3 shows 3 lines after |
-B NUM | Show NUM lines before match | -B 2 shows 2 lines before |
-C NUM | Show NUM lines before and after | -C 3 shows 3 lines both sides |
File Handling
Flag | Description | Example |
---|---|---|
--hidden | Search hidden files/directories | --hidden includes .hidden files |
--no-ignore | Ignore .gitignore rules | --no-ignore searches ignored files |
-u | Reduce filtering (1-3 times) | -uu = --no-ignore --hidden |
Pattern Matching
Flag | Description | Example |
---|---|---|
-F | Literal string search (no regex) | -F searches for exact text |
-w | Match whole words only | -w won't match partial words |
-v | Invert match (show non-matches) | -v shows lines without matches |
-x | Match entire lines only | -x matches exact line |
Advanced Features
Flag | Description | Example |
---|---|---|
-U | Enable multiline matching | -U (note: use multiline parameter instead) |
-P | Use PCRE2 regex engine | -P for advanced regex features |
-o | Show only matching parts | -o shows just matching text |
Output Control
Flag | Description | Example |
---|---|---|
-c | Count matches per file | -c shows count only |
-l | Show only filenames with matches | -l lists files with matches |
--column | Show column numbers | --column includes column info |
Practical Combinations
# Case-insensitive search with context in Python files
rg_flags: "-i -C 3 -t py"
# Search all files including hidden and ignored, with context
rg_flags: "-uu -C 2"
# Find exact function signatures in code files
rg_flags: "-F -w -t py -t js -t go"
# Search for TODOs with file types, case insensitive, show context
rg_flags: "-i -C 1 -t py -t js --no-ignore"
# Multi-line class definitions with context
rg_flags: "-U -C 3 -t py"
# Literal string search in all text files
rg_flags: "-F --no-ignore -t txt -t md -t rst"
MCP Tools Documentation
File Search Server Tools
search_files
Find files by NAME using fd with regex or glob patterns.
Purpose: Search for files when you know exact patterns, extensions, or regex for file NAMES.
Parameters:
pattern
(required): Regex or glob pattern to match file namespath
(optional): Directory to search in (defaults to current directory)limit
(optional): Maximum number of results to return (default: 0 = no limit)flags
(optional): Additional flags to pass to fd
Example:
{
"pattern": r"\.py$", # Find files with names ending in .py
"path": "/home/user/projects",
"flags": "--hidden --no-ignore"
}
filter_files
Fuzzy search for files by NAME using fzf's fuzzy matching.
Purpose: Find files when you only know partial or approximate file NAMES.
Parameters:
filter
(required): Fuzzy search string to match against file names/pathspattern
(optional): Initial pattern for fd to pre-filterpath
(optional): Directory to search infirst
(optional): Return only the best matchlimit
(optional): Maximum number of results to return (default: 0 = no limit)fd_flags
(optional): Extra flags for fdfzf_flags
(optional): Extra flags for fzfmultiline
(optional): When true, searches file CONTENTS instead of names (default: false)
Note: When both first
and limit
are provided, first
takes precedence and returns only the best match.
Example (File Name Search):
{
"filter": "test", # Fuzzy match 'test' in file names
"pattern": r"\.py$", # Only Python files
"path": "./src",
"first": true
}
Multiline Example (Content Search):
{
"filter": "class function return", # Find files containing all these terms
"pattern": "",
"path": "./src",
"multiline": true # Search CONTENTS, not names
}
Fuzzy Search Server Tools
fuzzy_search_files
Search for file NAMES/PATHS using fuzzy matching.
Purpose: Find files by NAME when you only know partial names (e.g., "mainpy" finds "main.py").
Parameters:
fuzzy_filter
(required): Fuzzy search string for file names/pathspath
(optional): Directory to search in (defaults to current directory)hidden
(optional): Include hidden files (default: false)limit
(optional): Maximum results to return (default: 20)multiline
(optional): When true, searches file CONTENTS instead of names (default: false)confirm_root
(optional): Allow searching from root directory (/) (default: false)
Example (File Name Search):
{
"fuzzy_filter": "main", # Finds main.py, main.js, domain.py, etc.
"path": "/home/user/projects",
"hidden": true,
"limit": 10
}
Multiline Example (Content Search):
{
"fuzzy_filter": "import export", # Find files containing both terms
"path": "./src",
"multiline": true, # Search CONTENTS, not names
"limit": 5
}
fuzzy_search_content
Search file contents with fuzzy filtering, matching on BOTH file paths AND content by default.
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.
Parameters:
fuzzy_filter
(required): Fuzzy search query for filtering (does NOT support regex - use fzf syntax)path
(optional): Directory/file to search in (defaults to current directory)- Enhanced file path support: Can now search both directories and individual files
- Automatically includes filename in output when searching a single file for consistent results
hidden
(optional): Search hidden files (default: false)limit
(optional): Maximum results to return (default: 20)rg_flags
(optional): Extra flags for ripgrep (see ripgrep flags reference)multiline
(optional): Enable multiline record processing (default: false)content_only
(optional): Match ONLY on content, ignore file paths (default: false)confirm_root
(optional): Allow searching from root directory (/) (default: false)
Matching Behavior:
- Default (content_only=false): Matches on BOTH file paths AND content (skips line numbers)
- This is why
"test.py: update"
finds "update" in test.py files - it matches the path! - Searching
"src TODO"
finds TODO comments in files under src/ directory - Even just
"update"
will match files named "update.py" OR containing "update"
- This is why
- With content_only=true: Matches ONLY on content, ignoring file paths entirely
- Pure content search -
"update"
won't match "update.py" filename, only content
- Pure content search -
Example (Default - Path + Content):
{
"fuzzy_filter": "test.py: TODO implement", # Find TODOs in test.py files
"path": "./src",
"rg_flags": "-i",
"limit": 15
}
Example (Single File Search):
{
"fuzzy_filter": "function async", # Find async functions in a specific file
"path": "./src/main.py", # Search within a single file
"limit": 10
}
Example (Content Only):
{
"fuzzy_filter": "async await catch", # Find these terms in content only
"path": "./src",
"content_only": true, # Ignore file paths in matching
"limit": 10
}
fuzzy_search_documents
Search through PDFs and other document formats using ripgrep-all (requires optional binaries).
Purpose: Search PDFs, Office documents, archives, and other binary formats that regular text search can't handle.
Parameters:
fuzzy_filter
(required): Fuzzy search query for document contentpath
(optional): Directory/file to search in (defaults to current directory)file_types
(optional): Comma-separated file types to search (e.g., "pdf,docx,epub")preview
(optional): Include preview context (default: true)limit
(optional): Maximum results to return (default: 20)confirm_root
(optional): Allow searching from root directory (/) (default: false)
Example:
{
"fuzzy_filter": "machine learning algorithm",
"path": "./research",
"file_types": "pdf,epub",
"limit": 10
}
Returns:
{
"matches": [
{
"file": "/path/to/document.pdf",
"line": 0,
"content": "topology.", # Content without "Page N: " prefix
"match_text": "topology",
"page": 542, # 1-based page number (from ripgrep-all)
"page_index_0based": 541, # 0-based page index for programmatic access
"page_label": "19" # Actual PDF page label (only for PDFs with PyMuPDF)
}
]
}
Note: For PDF files, the tool returns:
page
: The 1-based page number from ripgrep-all (e.g., 542 means the 542nd page)page_index_0based
: The 0-based page index for programmatic access (e.g., 541 for page 542)page_label
: The actual page label as shown in PDF readers (e.g., "vii", "ToC", "19")
The content field no longer includes the "Page N: " prefix for cleaner output.
extract_pdf_pages
Extract specific pages from a PDF and convert to various formats using PyMuPDF.
Purpose: Extract individual pages or page ranges from PDFs with support for page labels/aliases as they appear in PDF readers.
Parameters:
file
(required): Path to PDF filepages
(required): Comma-separated page specifications - supports:- Page labels: "v", "vii", "ToC", "Introduction" (as shown in PDF readers)
- Page ranges: "v-vii", "1-5"
- Physical pages: "1", "14" (1-based if not found as label)
- Mixed: "v,vii,1,5-8,ToC"
format
(optional): Output format - markdown, html, plain (default: markdown)preserve_layout
(optional): Try to preserve original layout (default: false)clean_html
(optional): Strip HTML styling tags like<span style="...">
(default: true)fuzzy_hint
(optional): Fuzzy search string to filter extracted pages by contentzero_based
(optional): Interpret page numbers as 0-based indices (default: false)- When true, all numbers are treated as direct 0-based page indices
- "0" = first page, "266" = 267th page, "0-4" = first 5 pages
- No page label lookup is performed when this is true
- Cannot be used together with
one_based
one_based
(optional): Interpret page numbers as 1-based indices (default: false)- When true, all numbers are treated as direct 1-based page indices
- "1" = first page, "267" = 267th page, "1-5" = first 5 pages
- No page label lookup is performed when this is true
- Cannot be used together with
zero_based
Example:
{
"file": "research_paper.pdf",
"pages": "v-vii,1,5-10,ToC", # Mix of page labels and numbers
"format": "markdown",
"clean_html": true,
"fuzzy_hint": "neural network" # Only include pages mentioning this
}
# Example with zero_based=true
{
"file": "research_paper.pdf",
"pages": "0,266-273", # Direct 0-based indices: page 1 and pages 267-274
"zero_based": true
}
# Example with one_based=true
{
"file": "research_paper.pdf",
"pages": "1,267-274", # Direct 1-based indices: pages 1, 267-274
"one_based": true
}
get_pdf_page_labels
Get all page labels from a PDF file.
Purpose: Returns a mapping of page indices to their labels/aliases as shown in PDF readers, helpful for understanding available page labels before extraction.
Parameters:
file
(required): Path to PDF filestart
(optional): 0-based start index for slicing results (default: 0)limit
(optional): Maximum number of labels to return (default: all pages)
Example:
{
"file": "research_paper.pdf"
}
# Returns something like:
{
"page_labels": {
"0": "Cover",
"1": "i",
"2": "ii",
"3": "iii",
"4": "iv",
"5": "v",
"6": "vi",
"7": "vii",
"8": "viii",
"9": "1",
"10": "2",
"11": "3"
},
"page_count": 150
}
# Example with slicing:
{
"file": "research_paper.pdf",
"start": 100,
"limit": 20
}
# Returns subset like:
{
"page_labels": {
"100": "87",
"101": "88",
"102": "89",
"103": "90",
"104": "91"
# ... up to 20 entries
},
"page_count": 150
}
get_pdf_page_count
Get the total number of pages in a PDF file.
Purpose: Returns the total page count, useful for understanding the document size before extraction.
Parameters:
file
(required): Path to PDF file
Example:
{
"file": "research_paper.pdf"
}
# Returns:
{
"page_count": 150
}
get_pdf_outline
Extract the table of contents (outline/bookmarks) from a PDF file.
Purpose: Returns the hierarchical outline structure with levels, titles, page numbers, and page labels, helpful for navigating complex PDFs and understanding document structure.
Parameters:
file
(required): Path to PDF filesimple
(optional): Return basic info (default: true) or detailed info with link data (false)max_depth
(optional): Maximum depth to traverse in the outline hierarchy (default: unlimited)fuzzy_filter
(optional): Fuzzy search string to filter outline entries by title using fzf
Example:
{
"file": "research_paper.pdf"
}
# Returns (simple mode):
{
"outline": [
[1, "Introduction", 1, "i"],
[1, "Chapter 1: Background", 5, "1"],
[2, "1.1 History", 6, "2"],
[2, "1.2 Related Work", 10, "6"],
[1, "Chapter 2: Methods", 15, "11"],
[2, "2.1 Data Collection", 16, "12"],
[3, "2.1.1 Sources", 17, "13"],
[2, "2.2 Analysis", 20, "16"]
],
"total_entries": 8,
"max_depth_found": 3
}
# Example with filtering:
{
"file": "research_paper.pdf",
"fuzzy_filter": "chapter"
}
# Returns:
{
"outline": [
[1, "Chapter 1: Background", 5, "1"],
[1, "Chapter 2: Methods", 15, "11"]
],
"total_entries": 8,
"max_depth_found": 3,
"filtered_count": 2
}
# Example with detailed output:
{
"file": "research_paper.pdf",
"simple": false,
"max_depth": 2
}
# Returns:
{
"outline": [
[1, "Introduction", 1, "i", {
"page": 1,
"uri": "#page=1&zoom=100,0,0",
"is_external": false,
"is_open": true,
"dest": {
"kind": 1,
"page": 0,
"uri": "#page=1&zoom=100,0,0"
}
}],
# ... more entries with link details
],
"total_entries": 8,
"max_depth_found": 2
}
Outline Format:
- Simple mode returns:
[level, title, page, page_label]
level
: Hierarchy level (1-based, 1 = top level)title
: The bookmark/outline entry titlepage
: Page number (1-based)page_label
: Page label as shown in PDF readers (e.g., "i", "ii", "1", "ToC")
- Detailed mode adds a 5th element with link information including destination details
SQLite Server Tools
query
Execute SELECT queries on the database.
Parameters:
query
(required): SELECT query to executedb_path
(optional): Path to SQLite database (defaults to configured db_path or ':memory:')
Example:
{
"query": "SELECT * FROM users WHERE active = 1 ORDER BY created_at DESC LIMIT 10",
"db_path": "myapp.db"
}
execute
Execute INSERT, UPDATE, or DELETE queries (requires write permissions).
Parameters:
query
(required): INSERT, UPDATE, or DELETE query to executedb_path
(optional): Path to SQLite database
Example:
{
"query": "UPDATE users SET last_login = datetime('now') WHERE id = 123",
"db_path": "myapp.db"
}
list_tables
List all tables in the database.
Parameters:
db_path
(optional): Path to SQLite database
Example:
{
"db_path": "myapp.db"
}
describe_table
Get detailed schema information for a specific table, including columns, types, constraints, and indexes.
Parameters:
table_name
(required): Name of the table to describedb_path
(optional): Path to SQLite database
Example:
{
"table_name": "users",
"db_path": "myapp.db"
}
create_table
Create a new table with specified columns (requires write permissions).
Parameters:
table_name
(required): Name of the table to createcolumns
(required): List of column definitionsdb_path
(optional): Path to SQLite database
Column Definition:
name
(required): Column nametype
(required): SQLite data type (TEXT, INTEGER, REAL, BLOB, etc.)constraints
(optional): Column constraints (PRIMARY KEY, NOT NULL, UNIQUE, etc.)
Example:
{
"table_name": "sessions",
"columns": [
{
"name": "id",
"type": "TEXT",
"constraints": "PRIMARY KEY"
},
{
"name": "user_id",
"type": "INTEGER",
"constraints": "NOT NULL"
},
{
"name": "created_at",
"type": "TIMESTAMP",
"constraints": "DEFAULT CURRENT_TIMESTAMP"
},
{
"name": "expires_at",
"type": "TIMESTAMP",
"constraints": "NOT NULL"
}
],
"db_path": "myapp.db"
}
Development
Project Structure
mcp-personal/
├── mcp_fd_server.py # File search MCP server
├── mcp_fuzzy_search.py # Fuzzy content search MCP server
├── mcp_sqlite_server.py # SQLite database MCP server
├── tests/ # Test suite
│ ├── test_simple.py # Direct function tests
│ ├── test_fd_server.py # File search MCP integration tests
│ ├── test_fuzzy_search.py # Fuzzy search tests
│ ├── test_sqlite_server.py # SQLite server tests
│ └── test_cli.py # CLI interface tests
├── pyproject.toml # Project configuration
├── Makefile # Development commands
├── CLAUDE.md # Claude-specific instructions
└── README.md # This file
Adding New MCP Servers
To add a new MCP server to this collection:
- Create a new Python file (e.g.,
mcp_new_server.py
) - Implement using FastMCP framework
- Add tests in the
tests/
directory - Update this README with documentation
- Add configuration example for Claude Desktop
Running Tests
# Run all tests
make test
# Run specific test categories
make test-simple # Direct function tests
make test-cli # CLI interface tests
make test-full # Full MCP integration tests
# Run with coverage
make test-cov
Development Commands
make help # Show all available commands
make setup # Install development dependencies
make test # Run tests
make lint # Run linting
make format # Format code
make type-check # Run type checking
make clean # Clean generated files
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Make your changes
- Run tests (
make test
) - Run linting (
make check
) - Commit your changes
- Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Architecture
All MCP servers in this collection are built using:
- FastMCP: High-level MCP server framework from the official Python SDK
- uv: Fast Python package manager
- Self-contained scripts: Each server uses
#!/usr/bin/env -S uv run --script
for easy deployment
File Search Server
Additionally uses:
- fd: Modern file finder written in Rust
- fzf: Command-line fuzzy finder
Fuzzy Search Server
Additionally uses:
- ripgrep: Extremely fast search tool that respects gitignore
- fzf: Command-line fuzzy finder (used in filter mode)
Security Considerations
General
- All servers run with the permissions of the user executing them
- Consider the security implications of each server's capabilities
- Review server code before installation
Root Path Protection
- Built-in safety mechanism: All search functions prevent accidental searches from root directory (/) by default
- Searching from root without explicit confirmation returns an error message
- To search from root directory, you must explicitly set
confirm_root=True
(MCP tools) or use--confirm-root
flag (CLI) - This prevents unintended performance issues and excessive filesystem access
- Cross-platform support: protects against both Unix root (/) and Windows drive roots (C:, etc.)
File Search Server
- Has filesystem access based on user permissions
- Be cautious when searching in sensitive directories
- The
--no-ignore
flag will include files normally hidden by.gitignore
Fuzzy Search Server
- Has filesystem read access based on user permissions
- Can search file contents, including source code and configuration files
- Respects
.gitignore
by default (use--hidden
to include ignored files) - Be mindful when searching in repositories with sensitive data
SQLite Server
- Read-only by default - Prevents accidental data modification
- Write operations require explicit
--allow-writes
flag or environment variable - Has full database access based on file permissions
- Can execute arbitrary SQL queries when write mode is enabled
- Be extremely cautious with write permissions on production databases
- Consider using separate read-only database users when possible
Troubleshooting
"Cannot find the fd
binary"
- Ensure fd is installed and in your PATH
- On Debian/Ubuntu, fd might be installed as
fdfind
"Cannot find the fzf
binary"
- Install fzf using your package manager
- Ensure it's available in your PATH
"Searching from root directory (/) is likely incorrect and could be very slow"
- This safety message appears when trying to search from the root directory without explicit confirmation
- To search from root, add
confirm_root=True
parameter (MCP tools) or--confirm-root
flag (CLI) - Consider using a more specific directory path instead for better performance
- Example:
./mcp_fuzzy_search.py search-files "config" / --confirm-root
Tests failing
- Check that required binaries are installed for each server
- Run
make check-deps
to verify binaries are available - Some tests require a Unix-like environment
License
This project is open source and available under the MIT License.
Acknowledgments
- Model Context Protocol - The protocol enabling AI-tool interactions
- FastMCP - The Python framework for building MCP servers
- uv - An extremely fast Python package installer and resolver
File Search Server
Fuzzy Search Server
- ripgrep - Recursively search directories for text patterns
- fzf - A command-line fuzzy finder
- PyMuPDF - Python bindings for MuPDF for PDF processing (optional)
- ripgrep-all - ripgrep, but also search in PDFs, E-Books, Office documents (optional)
- pandoc - Universal markup converter (optional)
SQLite Server
- SQLite - Self-contained, serverless, zero-configuration SQL database engine
Related Servers
Leantime MCP Bridge
An MCP proxy bridge for the Leantime project management system, forwarding JSON-RPC messages with proper authentication.
macOS Notification MCP
Trigger macOS notifications, sounds, and text-to-speech from an AI assistant.
Valkey AI Tasks
A task management system for AI agents that uses Valkey as its persistence layer.
HireBase
Interact with the HireBase Job API to manage job listings and applications.
Feishu/Lark OpenAPI
Connects AI agents to the Feishu/Lark platform for automating tasks like document processing, conversation management, and calendar scheduling.
JIRA
Access and manage JIRA issues, projects, and users with optimized data payloads for AI context windows.
Notion
Integrates with Notion's API to manage personal todo list
MCP Custom Tools
A versatile server with tools for date/time, file management, system info, text processing, and web operations.
Dub.co Short Links (Unofficial)
An unofficial MCP server for creating and managing short links with Dub.co.
Canvas MCP
Interact with Canvas LMS and Gradescope using AI agents.