[semantic]
Searches for a literal string or regex pattern (non-semantic) over the documents the workspace has loaded - source files plus any additional files and analyzer config a project declares - as the compiler last ingested them - the file watcher keeps that in step with disk, and sync/reload force it, so results track saved files rather than an unsaved editor buffer. Files no loaded project references are out of scope: for those, add scout as its own MCP server and use its find tool. Requires a completed workspace load.
Plain text still matters for comments, config-like code, string literals, and broad repo reconnaissance.
It gives the model an intentional text-search path inside the same loaded-root workflow, instead of mixing semantic and shell evidence casually.
Try it locally in the Glider playground
| Name | Type | Required | Description |
|---|---|---|---|
| query | string | No | Search query (literal string by default). Preferred argument name. |
| pattern | string | No | Backward-compatible alias for query. |
| useRegex | boolean | No | Treat pattern as a regex (.NET dialect). Default is false. |
| caseSensitive | boolean | No | Case-sensitive match. Default is false. |
| scope | json | No | Optional search scope. |
| skip | number | No | Pagination offset. Default is 0. |
| take | number | No | Pagination size. Default is 200. |
| maxLineTextChars | number | No | Max characters for lineText. Use 0 for unlimited. Default is 200. |
| pathStyle | string | No | Path style: 'absolute' (default) or 'relative' (to solution root). |
Find TODO comments
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_text",
"arguments": {
"query": "TODO"
}
}
}{
"success": true,
"data": {
"coverage": "loadedDocuments",
"pattern": "TODO",
"useRegex": false,
"caseSensitive": false,
"scopeUsed": {
"mode": "solution"
},
"matchCount": 2,
"projectsSearched": 2,
"totalProjectsInWorkspace": 2,
"documentsMatchedScope": 120,
"documentsSearched": 120,
"documentsWithMatches": 1,
"documentsUnreadable": 0,
"totalDocumentsInWorkspace": 120,
"paging": {
"skip": 0,
"take": 200,
"returned": 2,
"total": 2
},
"matches": [
{
"filePath": "/path/to/Program.cs",
"lineNumber": 12,
"column": 1,
"lineText": "// TODO: refactor this",
"projectName": "MyProject"
}
],
"hints": {
"nextSteps": [
"Use get_symbol_at_position if the match is an identifier and you want a symbolKey",
"Use search_symbols for semantic discovery once you know a symbol name"
],
"scopeNote": null,
"noMatchNote": null,
"unreadableNote": null
}
},
"meta": {
"durationMs": 123,
"cancelled": false,
"timedOut": false,
"timeoutMs": 1200000
},
"error": null
}Returns matching text occurrences with paging. data.coverage always reports 'loadedDocuments' - a standing statement of scope, not a backend discriminator. Before reading a zero-hit result as proof the code is absent, check how much was actually searched: compare documentsSearched with documentsMatchedScope, and check documentsUnreadable. A scope that matched no documents is reported in hints.scopeNote, and an unreadable-document count in hints.unreadableNote. A zero-hit search fills hints.noMatchNote, which names how many documents were searched and which file kinds that scope excludes. Text outside the loaded workspace is not covered at all - use scout's find for that.