Skip to content

fix(mcp): search_code converts multi-word patterns to regex#304

Merged
DeusData merged 1 commit into
DeusData:mainfrom
jjoos:fix/search-code-multi-word
May 10, 2026
Merged

fix(mcp): search_code converts multi-word patterns to regex#304
DeusData merged 1 commit into
DeusData:mainfrom
jjoos:fix/search-code-multi-word

Conversation

@jjoos

@jjoos jjoos commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Problem

search_code returns 0 results when the pattern contains spaces (e.g. "slack webhook handler"). Single-word queries like "webhook" or "handler" work fine.

Root cause

handle_search_code writes the pattern to a temp file and passes it to grep -F -f (fixed-string mode). A multi-word pattern like "slack webhook handler" is treated as a literal substring — grep looks for that exact 22-character sequence on one line. This almost never matches real code.

Fix

Before invoking grep, if the pattern contains whitespace and use_regex is false:

  1. Split on whitespace runs
  2. Escape regex metacharacters in each word
  3. Join with .*slack.*webhook.*handler
  4. Flip to regex mode (grep -E)

This matches lines containing all words in order. Single-word patterns are unaffected (no spaces → no conversion).

Changes

  • src/mcp/mcp.c: 36 lines added in a new "Phase 0.5" block before grep invocation.
  • tests/test_mcp.c: New search_code_multi_word test verifying a two-word query finds a matching line.

Testing

  • New unit test: search_code_multi_word — searches for "HandleRequest error" in a fixture file containing func HandleRequest() error {. Verifies non-zero results.
  • Manual testing against indexed Ruby monolith confirmed multi-word queries now return relevant results.

When pattern contains spaces and is not already a regex, convert to a
regex with '.*' between words: "foo bar baz" → "foo.*bar.*baz".
This matches all terms in order on a line instead of requiring the
exact multi-word substring.

Metacharacters in user input are escaped so the conversion is safe
for arbitrary text.

Includes test: search_code_multi_word verifies that a two-word query
matches a line containing both words non-contiguously.
@DeusData DeusData added the bug Something isn't working label May 4, 2026
@DeusData
DeusData merged commit cc7ef34 into DeusData:main May 10, 2026
@DeusData

Copy link
Copy Markdown
Owner

Merged via rebase, thanks @jjoos. Diagnosis is clean and the conversion logic is well-scoped — gating on !use_regex && strchr(pattern, ' ') keeps single-word and explicit-regex paths untouched, the metacharacter list (\^$.|?*+()[]{}) covers ERE completely, and collapsing whitespace runs to a single .* keeps the regex tight on patterns with extra spaces.

Two small notes for future iteration (not blocking, just observations from review):

  • The plen * 3 + 1 worst-case bound is safe but slightly over-provisioned — actual upper bound is plen * 2 + 1 (each input char emits at most 2 output chars: either \X for an escaped metachar, .* for a whitespace run, or the literal). Harmless either way.
  • This fix removes the only path that previously let users search for a multi-word literal phrase. With use_regex=false they now always get fuzzy-in-order matching; with use_regex=true they have to escape themselves. In practice nobody was getting useful results from the old fixed-string-with-spaces behavior, so this is the right trade-off — but worth noting in case anyone hits it later.

Test coverage on the two-word path is the right place to start. Three+ words and metachar escaping are uncovered but the algorithm is straightforward enough that the targeted test plus build verification is sufficient.

@jjoos
jjoos deleted the fix/search-code-multi-word branch May 11, 2026 11:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants