Skip to content

MCP Integration

ck includes a built-in MCP (Model Context Protocol) server for seamless integration with AI coding assistants like Claude Desktop and Cursor.

What is MCP?

MCP (Model Context Protocol) is Anthropic’s standard for connecting AI assistants to external tools and data sources. ck’s MCP server gives AI agents powerful semantic code search capabilities.

Quick Start

Start MCP Server

bash
# Start the MCP server
ck --serve

The server listens on stdio and communicates via JSON-RPC 2.0.

Install in Claude Desktop

Using Claude Code CLI (Recommended):

bash
claude mcp add ck-search -s user -- ck --serve

# Restart Claude Code if needed
# Verify with:
claude mcp list

Manual Configuration:

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or equivalent:

json
{
  "mcpServers": {
    "ck": {
      "command": "ck",
      "args": ["--serve"],
      "cwd": "/path/to/your/codebase"
    }
  }
}

Tool Permissions:

When prompted by Claude Code, approve permissions for ck-search tools.

Available MCP Tools

Find code by meaning using embeddings.

Parameters:

  • query (string, required): Search query
  • path (string, optional): Directory to search (defaults to cwd)
  • page_size (integer, optional): Results per page (default: 25)
  • top_k (integer, optional): Maximum total results (default: 100)
  • snippet_length (integer, optional): Snippet size in characters (default: 200)
  • cursor (string, optional): Pagination cursor
  • threshold (number, optional): Minimum relevance score (0.0-1.0)

Example:

python
response = await client.call_tool("semantic_search", {
    "query": "authentication logic",
    "path": "/path/to/code",
    "page_size": 25,
    "top_k": 50,
    "threshold": 0.6
})

Traditional pattern matching (grep-style).

Parameters:

  • pattern (string, required): Regex pattern
  • path (string, optional): Directory to search
  • page_size (integer, optional): Results per page
  • case_insensitive (boolean, optional): Case-insensitive search
  • cursor (string, optional): Pagination cursor

Example:

python
response = await client.call_tool("regex_search", {
    "pattern": "TODO|FIXME",
    "path": "/path/to/code",
    "case_insensitive": true
})

Combined semantic and keyword search using Reciprocal Rank Fusion.

Parameters:

  • query (string, required): Search query
  • path (string, optional): Directory to search
  • page_size (integer, optional): Results per page
  • top_k (integer, optional): Maximum total results
  • threshold (number, optional): Minimum relevance score (RRF scale: ~0.01-0.05)

Hybrid Threshold Scale

Hybrid search uses Reciprocal Rank Fusion (RRF) scoring, producing values in the 0.01-0.05 range, not 0.0-1.0 like semantic search. Typical thresholds: 0.016-0.025. See Hybrid Search for details.

Example:

python
response = await client.call_tool("hybrid_search", {
    "query": "connection timeout",
    "path": "/path/to/code",
    "threshold": 0.02  # Note: RRF scale, not 0-1
})

index_status

Check indexing status and metadata.

Parameters:

  • path (string, optional): Directory to check

Returns:

  • Index statistics
  • Embedding model info
  • File counts
  • Last update time

reindex

Force rebuild of search index.

Parameters:

  • path (string, optional): Directory to reindex
  • model (string, optional): Embedding model to use

Example:

python
await client.call_tool("reindex", {
    "path": "/path/to/code",
    "model": "nomic-v1.5"
})

default_ckignore

Retrieve default .ckignore patterns used by ck.

Parameters: None

Returns:

  • String containing default .ckignore content

Use case: Useful for editor extensions and tools that need to display or work with ck’s default exclusion patterns without parsing the backend code.

Example:

python
patterns = await client.call_tool("default_ckignore", {})
# Returns multi-line string with default patterns:
# *.png
# *.jpg
# node_modules/
# ...

CLI Alternative

You can also get default patterns via CLI:

bash
ck --print-default-ckignore

health_check

Server status and diagnostics.

Returns:

  • Server version
  • Available models
  • System status

Response Format

All search tools return paginated results:

json
{
  "results": [
    {
      "file": "src/auth.rs",
      "line": 42,
      "content": "fn authenticate_user(token: &str) -> Result<User>",
      "score": 0.847
    }
  ],
  "pagination": {
    "total_results": 127,
    "returned_results": 25,
    "next_cursor": "abc123xyz",
    "has_more": true
  }
}

Pagination

Handle large result sets efficiently:

python
# First page
response = await client.call_tool("semantic_search", {
    "query": "authentication logic",
    "path": "/path/to/code",
    "page_size": 25
})

# Next page
if response["pagination"]["next_cursor"]:
    next_response = await client.call_tool("semantic_search", {
        "query": "authentication logic",
        "path": "/path/to/code",
        "cursor": response["pagination"]["next_cursor"]
    })

AI Agent Best Practices

Configure ck for AI Agents

For comprehensive guidance on configuring ck for AI coding assistants like Claude Code, see AI Agent Setup.

Query Formulation

python
# ✅ Good: Specific, actionable queries
await semantic_search("error handling patterns")
await semantic_search("user authentication logic")
await semantic_search("database connection pooling")

# ❌ Poor: Vague or overly broad
await semantic_search("code")
await semantic_search("functions")

Result Filtering

python
# Use threshold for quality control
results = await semantic_search(
    "caching",
    threshold=0.7  # Only high-confidence matches
)

# Limit results for performance
results = await semantic_search(
    "auth",
    top_k=10  # Top 10 results only
)

Combining Search Types

python
# Start with semantic for broad understanding
semantic_results = await semantic_search("authentication")

# Refine with hybrid for specific patterns
hybrid_results = await hybrid_search("jwt token")

# Use regex for exact strings
regex_results = await regex_search("Bearer .+")

Use Cases

Code Understanding

python
# Find entry points
await semantic_search("main entry point")

# Understand architecture
await semantic_search("dependency injection")

# Find configuration
await semantic_search("config loading")

Code Modification

python
# Find target code
results = await semantic_search("user authentication")

# Find related tests
test_results = await semantic_search("auth test")

# Find similar patterns for consistency
similar = await semantic_search("validation pattern")

Documentation Generation

python
# Find public APIs
api_results = await semantic_search("public api")

# Extract function signatures
functions = await hybrid_search("fn |function |def ")

# Generate docs from results
docs = generate_docs(api_results)

Security Analysis

python
# Find authentication code
auth = await semantic_search("authentication")

# Find input validation
validation = await semantic_search("input sanitization")

# Find secrets (with caution)
secrets = await regex_search("api_key|password|secret")

Performance Considerations

Index Management

python
# Check index before heavy operations
status = await index_status()
if not status["indexed"]:
    await reindex()

# Reindex after bulk changes
await git_pull()
await reindex()

Pagination Strategy

python
# For exploratory search: small pages
results = await semantic_search(query, page_size=10)

# For comprehensive search: larger pages
results = await semantic_search(query, page_size=50)

# Process incrementally to avoid memory issues
while has_more:
    page = await semantic_search(query, cursor=cursor)
    process(page["results"])
    cursor = page["pagination"]["next_cursor"]

Result Caching

python
# Cache search results for repeated queries
cache = {}
def cached_search(query):
    if query in cache:
        return cache[query]
    results = await semantic_search(query)
    cache[query] = results
    return results

Error Handling

python
try:
    results = await client.call_tool("semantic_search", {
        "query": "pattern",
        "path": "/path/to/code"
    })
except MCPError as e:
    if "index not found" in str(e):
        # Build index first
        await client.call_tool("reindex", {"path": "/path/to/code"})
        results = await client.call_tool("semantic_search", {
            "query": "pattern",
            "path": "/path/to/code"
        })
    else:
        raise

Troubleshooting

Server Not Responding

bash
# Check if ck is installed
which ck

# Test server manually
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | ck --serve

# Check logs (if available)
cat ~/.claude/logs/mcp.log

Tool Not Available

bash
# Verify installation
claude mcp list | grep ck

# Reinstall
claude mcp remove ck-search
claude mcp add ck-search -s user -- ck --serve

Slow Searches

python
# Reduce result count
results = await semantic_search(query, top_k=10)

# Increase threshold
results = await semantic_search(query, threshold=0.7)

# Use smaller snippets
results = await semantic_search(query, snippet_length=100)

Security Considerations

  • Local execution – All code analysis happens locally
  • No network calls – No data sent to external services
  • File access – MCP server has same permissions as user
  • Sandboxing – Consider running in containerized environment

Next Steps

Released under the MIT or Apache-2.0 License.