Skip to content

MCP Tools

Reflex’s MCP server (rfx mcp) exposes 17 tools through the Model Context Protocol. These tools let AI assistants search code, analyze dependencies, and understand your codebase.

The server speaks MCP protocol version 2025-11-25 over stdio and uses its working directory as the project root. On initialize it also returns an instructions string telling the agent to prefer Reflex tools over grep and listing the exact argument names.

Terminal window
# Current project only (default "local" scope)
claude mcp add reflex -- rfx mcp
# Share with your team via a checked-in .mcp.json
claude mcp add --scope project reflex -- rfx mcp

Or add it to .mcp.json in your project root yourself:

{
"mcpServers": {
"reflex": {
"type": "stdio",
"command": "rfx",
"args": ["mcp"]
}
}
}

Other MCP clients use the same command / args. Launch the server from your project directory (the one containing .reflex/).

Five whole-graph analysis tools (find_circular, find_islands, find_unused, analyze_summary, get_transitive_deps) can be removed from the tool list to save context. Add this to ~/.reflex/config.toml:

[mcp]
enable_structural_tools = false # default: true
  • The search argument is always pattern, the language filter is lang, and the result cap is limit.
  • Common wrong names are accepted and mapped, with a warnings entry in the response: query, symbol, text, search → pattern; max_results → limit; path → file (only on tools that have no real path parameter).
  • Any other unknown argument is rejected with a JSON-RPC -32602 error that lists the valid names.
  • Numeric strings ("40") are accepted for integer parameters.

Every search response carries status ("fresh" or "stale") and can_trust_results. A stale response still contains real matches, but it may be incomplete. It includes a warning with the changed paths (files_modified, files_added, files_deleted) and action_required: "index_project". Freshness is judged by file content, not by commit, so an uncommitted edit makes the index stale and committing already-indexed content does not.

All search tools accept these filters. search_ast and find_references take only some of them, as noted below.

ParameterTypeDescription
langstringrust, typescript, javascript, go, java, php, kotlin, python, c, cpp, csharp, ruby, vue, svelte, zig, or text / lock / generated for the non-code tiers
filestringFilter by file path substring
globstring[]Include files matching patterns (gitignore rules: a pattern containing / is anchored at the index root, a bare name matches at any depth, * does not cross /)
excludestring[]Exclude files matching patterns (same rules)
forceboolBypass broad-query detection
dependenciesboolInclude static imports in results
ignore_caseboolMatch regardless of case, like rg -i
include_locksboolAlso search lock files (Cargo.lock, package-lock.json, *.lock, go.sum)
include_generatedboolAlso search generated files (*.pb.go, *.min.js, *.min.css, *.map, *_generated.*)

Coverage matches ripgrep’s defaults: every non-binary file that isn’t gitignored and isn’t under a dot-directory. Lock and generated files are indexed, but left out unless you ask for them. A zero-result response carries excluded_reason (hidden, not_indexed, lock_or_generated, or whole_identifier) and a hint naming the cause.

Full-text search. Matches whole identifiers by default (verify_csrf does not match verify_csrf_form_field). Pass contains: true for substring matching. A pattern containing brackets ((), [], <>) is escaped and run as a regex, with a note in warnings.

ParameterTypeRequiredDescription
patternstringyesText to find
containsboolnoSubstring matching, like grep -F
symbolsboolnoSymbol definitions only
kindstringnoSymbol kind filter (function, class, struct, …)
exactboolnoCase-sensitive exact-identifier match
expandboolnoShow full symbol body
modelist | countnocount returns only {count, pattern}
limitintnoResults per page (default: 200, max: 500)
offsetintnoPagination offset
pathsboolnoReturn only unique file paths
preview_lengthintnoMax characters per preview line (default: 180)

Plus the common filters.

Results are columnar: each row lines up with columns.

{
"status": "fresh",
"can_trust_results": true,
"columns": ["path", "language", "start_line", "end_line", "preview", "kind", "symbol"],
"rows": [
["src/cli/ask.rs", "rust", 9, 426, "pub(super) fn handle_ask(\n question: Option<String>,\n …", "Function", "handle_ask"]
],
"pagination": { "count": 1, "has_more": false, "limit": 2, "offset": 0, "total": 1, "total_is_exact": true },
"returned_count": 1,
"total_count": 1,
"total_is_exact": true,
"has_more": false,
"ai_instruction": "Found 1 precise result. Respond concisely: '[symbol] at [path]:[line]'."
}

With paths: true the response is {status, can_trust_results, paths, total_files} instead. Set the environment variable REFLEX_MCP_COLUMNAR=0 to get the file-grouped results[] shape used by rfx query --json, or REFLEX_MCP_TIMING=1 to add per-phase timings.

A list-mode search stops verifying once the page is full, so total is a number only when total_is_exact is true. Otherwise it’s null and approx_total holds an estimate. Use mode: "count" for an exact number.

Regular-expression search with the same coverage as search_code. Regexes with a literal of 3+ characters (including (?i) patterns) still use the trigram index.

ParameterTypeRequiredDescription
patternstringyesRegex pattern
modelist | countnocount returns only {count, pattern}
limitintnoResults per page (default: 200, max: 500)
offsetintnoPagination offset
pathsboolnoReturn only unique file paths

Plus the common filters. ignore_case: true prepends (?i).

Structure-aware search with Tree-sitter S-expression patterns. It’s slow, because it bypasses the trigram index and parses every candidate file, so pass glob to limit scope.

ParameterTypeRequiredDescription
patternstringyesTree-sitter S-expression, e.g. (function_item) @fn
langstringyesrust, typescript, javascript, python, go, java, c, cpp, csharp, php, ruby, kotlin, zig
globstring[]noInclude patterns (strongly recommended)
excludestring[]noExclude patterns
filestringnoFile path substring
limitintnoMax results
offsetintnoPagination offset
pathsboolnoReturn only unique file paths
forceboolnoBypass broad-query detection
dependenciesboolnoInclude static imports

A symbol’s definition plus every usage, in one call. By default it skips matches inside string literals and comments, and it only searches code files (not docs or config).

ParameterTypeRequiredDescription
patternstringyesSymbol name, e.g. CacheManager
containsboolnoSubstring matching
ignore_caseboolnoCase-insensitive matching
include_stringsboolnoInclude matches in strings and comments (default: false)
kindstringnoFilter the definition lookup by kind
langstringnoFilter by language
globstring[]noInclude patterns
excludestring[]noExclude patterns
modelist | countnocount returns only {count, pattern}
limitintnoReferences per page (default: 200, max: 500)
offsetintnoPagination offset
forceboolnoBypass broad-query detection
{
"status": "fresh",
"definition": {
"kind": "Function", "path": "src/cli/ask.rs", "symbol": "handle_ask",
"span": { "start_line": 9, "end_line": 426 },
"preview": "pub(super) fn handle_ask(\n question: Option<String>,\n …"
},
"references": [
{ "line": 9, "path": "src/cli/ask.rs", "preview": "pub(super) fn handle_ask(" },
{ "line": 1258, "path": "src/cli/mod.rs", "preview": " }) => ask::handle_ask(" }
],
"total_references": 2,
"returned_count": 2,
"filtered_out": 0,
"pagination": { "count": 2, "has_more": false, "limit": 3, "offset": 0, "total": 2, "total_is_exact": true }
}

total_references and pagination.total are raw totals before string/comment filtering. filtered_out is how many of them were dropped.

Every place a pattern occurs, as {path, line} pairs with no previews and no limit. It’s the cheapest way to enumerate hits.

ParameterTypeRequiredDescription
patternstringyesText to find
containsboolnoSubstring matching

Plus the common filters.

{"locations":[{"line":9,"path":"src/cli/ask.rs"},{"line":1258,"path":"src/cli/mod.rs"}],"status":"fresh","total_locations":2}

Total occurrences and file count, without loading content.

ParameterTypeRequiredDescription
patternstringyesText to find
containsboolnoSubstring matching
symbolsboolnoCount definitions only
kindstringnoSymbol kind filter

Plus the common filters.

{"files":2,"pattern":"handle_ask","status":"fresh","total":2}

Build or update the index. Incremental by default. Returns index statistics (total_files, files_by_language, lines_by_language, index_size_bytes, corpus_bytes, trigram_index_bytes, last_updated, plus changed-file counts).

ParameterTypeRequiredDescription
forceboolnoForce a full rebuild
languagesstring[]noLanguages to include (empty = all)

Check whether the index is fresh, stale, or missing, without running a search. Call it at session start, after git operations, and after editing files. No parameters.

{
"status": "fresh",
"can_trust_results": true,
"details": {
"checked_by": "git",
"current_branch": "HEAD",
"current_commit": "436f836…",
"indexed_branch": "HEAD",
"indexed_commit": "436f836…",
"indexed_at": 1790189114
}
}

When stale, the response adds reason, action_required ("index_project"), files_modified, files_added, files_deleted (capped at 100 each, with truncated set if cut short), and changed_count.

Path matching is fuzzy: exact paths, fragments, or bare filenames all work. Only static imports are considered.

Every import of a single file.

ParameterTypeRequiredDescription
pathstringyesFile path
[{"line":1,"path":"src/cache.rs"},{"line":2,"path":"anyhow","symbols":["Context","Result"]}]

Every file that imports the given file. Returns an array of paths.

ParameterTypeRequiredDescription
pathstringyesFile path

Walk the dependency tree of a file. Returns [{path, depth}]. Structural tool.

ParameterTypeRequiredDescription
pathstringyesFile path
depthintnoMax traversal depth (default: 3)

Paginated analysis tools return {pagination, results} with a default page size of 200.

Files ranked by how many other files import them. Returns [{path, import_count}].

ParameterTypeRequiredDescription
min_dependentsintnoMinimum dependents to include (default: 2)
sortasc | descnoSort order (default: desc)
limitintnoPage size (default: 200)
offsetintnoPagination offset

Circular dependency chains. Returns [{paths: ["a.rs", "b.rs", "a.rs"]}], longest first by default. Structural tool.

ParameterTypeRequiredDescription
sortasc | descnoSort by cycle length (default: desc)
limitintnoPage size (default: 200)
offsetintnoPagination offset

Files that no other file imports. Entry points such as main.rs show up here by design. Structural tool.

ParameterTypeRequiredDescription
limitintnoPage size (default: 200)
offsetintnoPagination offset

Disconnected components of the import graph. Returns [{island_id, size, paths}], largest first by default. Structural tool.

ParameterTypeRequiredDescription
min_island_sizeintnoMinimum files per island (default: 2)
max_island_sizeintnoMaximum files per island (default: 500 or 50% of files)
sortasc | descnoSort by size (default: desc)
limitintnoPage size (default: 200)
offsetintnoPagination offset

Aggregate counts, to decide which analysis to drill into. Structural tool.

ParameterTypeRequiredDescription
min_dependentsintnoHotspot threshold (default: 2)
{"circular_dependencies":1,"hotspots":68,"islands":187,"min_dependents":2,"unused_files":24}

Collect codebase orientation: project structure, frameworks, entry points, and file statistics. With no parameters, all context types are gathered. Returns prose, not JSON.

ParameterTypeRequiredDescription
structureboolnoShow directory structure
file_typesboolnoShow file type distribution
project_typeboolnoDetect project type (CLI, library, webapp, monorepo)
frameworkboolnoDetect frameworks and conventions
entry_pointsboolnoShow entry point files
test_layoutboolnoShow test organization pattern
config_filesboolnoList important configuration files
depthintnoTree depth for structure (default: 2)
pathstringnoFocus on a specific directory path