diff --git a/.claude/skills/ide-index-mcp/SKILL.md b/.claude/skills/ide-index-mcp/SKILL.md new file mode 100644 index 0000000000..da91b8d9b7 --- /dev/null +++ b/.claude/skills/ide-index-mcp/SKILL.md @@ -0,0 +1,136 @@ +--- +name: ide-index-mcp +description: > + Guide for using JetBrains IDE Index MCP tools for code navigation, refactoring, and analysis. + TRIGGER: When ANY of these MCP tools are available in the current session: ide_find_references, + ide_find_definition, ide_find_class, ide_find_file, ide_search_text, ide_diagnostics, + ide_index_status, ide_sync_files, ide_refactor_rename, ide_move_file, ide_type_hierarchy, + ide_call_hierarchy, ide_find_implementations, ide_find_symbol, ide_find_super_methods, + ide_file_structure, ide_refactor_safe_delete, ide_reformat_code, ide_build_project, + ide_read_file, ide_get_active_file, ide_open_file. + Use when performing code navigation (find usages, go to definition, find class), + code analysis (diagnostics, type hierarchy, call hierarchy), + refactoring (rename, move, safe delete, reformat), + or searching code (text search, symbol search, file search). + Prefer IDE tools over grep/find/sed for ALL semantic code operations. +--- + +# IDE Index MCP - Agent Guide + +The IDE Index MCP server exposes JetBrains IDE indexing and refactoring capabilities. These tools provide **semantic** code understanding superior to text-based search/replace. + +## Core Rule + +**Always prefer IDE MCP tools over built-in tools (grep, find, sed, read) for semantic code operations.** IDE tools understand code structure, types, inheritance, and references. Built-in tools only see text. + +## When to Use IDE Tools vs Built-In Tools + +| Task | Use IDE Tool | Use Built-In Tool | +|------|-------------|-------------------| +| Find all usages of a method/class/variable | `ide_find_references` | Never - grep misses renamed imports, aliases, overrides | +| Go to a symbol's definition | `ide_find_definition` | Never - grep can't resolve through imports/generics | +| Find a class by name | `ide_find_class` | Only if IDE unavailable | +| Find a file by name | `ide_find_file` | `Glob` is fine for simple patterns | +| Search for a word in code | `ide_search_text` | `Grep` is fine for regex patterns (IDE tool is exact-word only) | +| Rename a symbol across project | `ide_refactor_rename` | Never - sed/replace breaks code | +| Move a file to another directory | `ide_move_file` | Never - mv/git mv bypasses IDE move semantics | +| Check for errors in a file | `ide_diagnostics` | Never - no equivalent | +| Understand class hierarchy | `ide_type_hierarchy` | Never - no equivalent | +| Find who calls a method | `ide_call_hierarchy` | Never - grep misses indirect calls | +| Find interface implementations | `ide_find_implementations` | Never - grep can't resolve type relationships | +| Delete a symbol safely | `ide_refactor_safe_delete` | Never - manual deletion misses usages | +| Find what a method overrides | `ide_find_super_methods` | Never - no equivalent | +| Read file content | Built-in Read tool | `ide_read_file` only for library/jar sources | +| Find text with regex | `Grep` | IDE search_text doesn't support regex | + +## Pre-Flight Check + +Before using any IDE tool that requires smart mode, check IDE readiness: + +``` +ide_index_status -> if isDumbMode: true, wait a few seconds and retry +``` + +Most tools require smart mode (IDE finished indexing). Tools that work in dumb mode: `ide_index_status`, `ide_sync_files`, `ide_reformat_code`, `ide_open_file`, `ide_get_active_file`. + +## File Sync Rule + +If you created or modified files outside the IDE (via Write/Edit tools) and an IDE search tool returns incomplete/missing results, call `ide_sync_files` first, then retry. + +```json +{ "paths": ["src/new_file.java", "src/modified_file.java"] } +``` + +Omit `paths` to sync the entire project. + +## Parameter Rules + +1. **Line and column are 1-based** (first line = 1, first column = 1) +2. **Project file paths are relative** to project root (e.g., `src/main/java/App.java`, NOT absolute paths). If an IDE tool returns a dependency/library file, keep the returned absolute path or `jar://` URL unchanged when passing it back to read-only navigation tools or `ide_read_file` +3. **Column must point to the symbol name**, not whitespace or punctuation. For `public void myMethod()`, column should land on `m` of `myMethod`. For dotted expressions like `json.dumps()` or `os.path.join()`, put the column on the member token (`dumps`, `join`) when you want the member definition rather than the module/package. +4. **project_path is only needed** for multi-project workspaces. Omit for single-project setups. When needed, use the absolute path to the project root. +5. **Use built-in search scope intentionally**: `ide_find_references`, `ide_find_implementations`, `ide_type_hierarchy`, `ide_call_hierarchy`, `ide_find_class`, `ide_find_file`, and `ide_find_symbol` accept `scope`. Use `project_files` for the default project-only view, `project_and_libraries` when dependency code matters, `project_production_files` to stay out of tests, and `project_test_files` when you want test-only results. + +## Tool Selection by Task + +### "I need to understand how X is used" +1. `ide_find_references` - all call sites, field accesses, imports +2. `ide_call_hierarchy` with `direction: "callers"` - full call chain upward + +### "I need to understand what X is" +1. `ide_find_definition` - jump to source +2. `ide_type_hierarchy` - inheritance chain +3. `ide_find_super_methods` - what interface/base method it implements + +### "I need to find a class/file/symbol" +1. `ide_find_class` - classes by name (CamelCase: `USvc` finds `UserService`) +2. `ide_find_file` - files by name +3. `ide_search_text` - exact word occurrences across project + +### "I need to refactor" +1. `ide_refactor_rename` - rename symbol + all references atomically +2. `ide_move_file` - move file and let the IDE apply semantic updates when that language/backend supports them +3. `ide_refactor_safe_delete` - delete with usage checking (Java/Kotlin only) +4. `ide_reformat_code` - apply project code style (disabled by default) + +### "I need to check for problems" +1. `ide_diagnostics` - compiler errors, warnings, quick fixes + +### "I need to find implementations of an interface" +1. `ide_find_implementations` - cursor on interface/abstract class/method + +### "I need to trace call chains" +1. `ide_call_hierarchy` with `direction: "callers"` - who calls this? +2. `ide_call_hierarchy` with `direction: "callees"` - what does this call? + +## Common Mistakes to Avoid + +1. **Using grep instead of `ide_find_references`**: Grep finds text, not semantic usages. Misses aliased imports, includes false positives from comments/strings. + +2. **Using sed/replace instead of `ide_refactor_rename`**: Text replacement breaks code. IDE rename updates all references, getters/setters, overrides, test classes, imports. + +3. **Using mv/git mv instead of `ide_move_file`**: File system moves bypass IDE move semantics. `ide_move_file` can preserve IDE-managed package/namespace/reference updates when the active language backend supports them. + +4. **Forgetting to check index status**: If IDE is indexing (dumb mode), most tools error. Check `ide_index_status` first if a tool fails unexpectedly. + +5. **Using 0-based line/column**: All IDE tools use **1-based**. Line 5 in file = `line: 5`. + +6. **Passing absolute project file paths**: Use relative paths for project files. `src/main/App.java`, not `/Users/me/project/src/main/App.java`. + +7. **Rewriting plugin-returned library paths**: If a search or read tool returns an absolute path or `jar://` URL for a dependency/library file, pass that path back unchanged to read-only navigation tools or `ide_read_file`. + +8. **Not syncing after external file changes**: After creating files via Write tool, call `ide_sync_files` before searching. + +9. **Using `ide_search_text` for regex**: This tool is exact-word only (uses word index). Use `Grep` for regex. + +10. **Using `ide_find_class` for methods/functions**: It searches classes only. Use `ide_search_text` for a quick word lookup. + +## Disabled-by-Default Tools + +These tools exist but are disabled by default. If you get "tool not found", they need to be enabled in IDE settings (Settings > Tools > Index MCP Server): + +`ide_build_project`, `ide_file_structure`, `ide_find_symbol`, `ide_read_file`, `ide_get_active_file`, `ide_open_file`, `ide_reformat_code` + +## Detailed Tool Parameters + +For complete parameter reference with types, defaults, and return formats, see [tools-reference.md](references/tools-reference.md). diff --git a/.claude/skills/ide-index-mcp/references/tools-reference.md b/.claude/skills/ide-index-mcp/references/tools-reference.md new file mode 100644 index 0000000000..d05f16b2f0 --- /dev/null +++ b/.claude/skills/ide-index-mcp/references/tools-reference.md @@ -0,0 +1,376 @@ +# IDE Index MCP - Tools Reference + +Complete parameter reference for all IDE MCP tools. All tools use JSON-RPC via MCP protocol. + +## Common Parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| `project_path` | string, optional | Absolute path to project root. Required for multi-project workspaces. Omit for single-project setups. | +| `file` | string | For project files, path relative to project root (e.g., `src/main/App.java`). `ide_read_file` and some read-only position-based navigation tools also accept dependency/library paths returned by the plugin as absolute paths or `jar://` URLs; check each tool section because support is tool-specific. | +| `line` | integer | **1-based** line number | +| `column` | integer | **1-based** column number. Place on the symbol name, not whitespace. For dotted expressions like `json.dumps()` or `os.path.join()`, point to the member token (`dumps`, `join`) when targeting the member definition. | +| `language` | string | Language of the symbol (e.g., `"Java"`). Required when using `symbol`. | +| `symbol` | string | Fully qualified symbol reference. Format: `com.example.ClassName`, `com.example.ClassName#memberName`. | + +**Symbol reference:** Some tools accept `language` + `symbol` as an alternative to `file` + `line` + `column`. The two groups are **mutually exclusive**. Currently supported for Java only. Unsupported languages are rejected explicitly; use `file` + `line` + `column` for other languages. + +## Response Format + +All tools return: `{ "content": [{"type": "text", "text": ""}], "isError": false|true }` + +Parse the `text` field as JSON for structured data. + +--- + +## Navigation Tools + +### ide_find_references +Find all usages of a symbol (semantic, not text search). + +**Target (mutually exclusive):** `file`+`line`+`column` OR `language`+`symbol` + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | string | conditional | Project-relative file path, or a dependency/library absolute path or `jar://` URL previously returned by the plugin. Required for position-based lookup. | +| `line` | integer | conditional | 1-based line. Required for position-based lookup. | +| `column` | integer | conditional | 1-based column. Required for position-based lookup. | +| `language` | string | conditional | Symbol language (e.g., `"Java"`). Required for symbol-based lookup. | +| `symbol` | string | conditional | Fully qualified symbol reference. Required for symbol-based lookup. | +| `scope` | enum | no | One of `project_files` (default), `project_and_libraries`, `project_production_files`, `project_test_files` | +| `maxResults` | integer | no | Deprecated alias for `pageSize`. Default 100, max 500 | +| `cursor` | string | no | Pagination cursor from a previous response. When provided, search parameters are ignored; `project_path` and `pageSize` may still be provided. | +| `pageSize` | integer | no | Results per page. Default 100, max 500 | +| `project_path` | string | no | Project root path | + +**Returns**: `{ usages: [{ file, line, column, context, type, astPath }], totalCount, truncated, nextCursor?, hasMore, totalCollected, offset, pageSize, stale }` +**Pagination note**: `truncated` mirrors `hasMore`; when `hasMore` is `true`, pass `nextCursor` to fetch the next page. +**type values**: `METHOD_CALL`, `FIELD_ACCESS`, `IMPORT`, `PARAMETER`, `VARIABLE`, `REFERENCE` + +### ide_find_definition +Go to where a symbol is defined. + +**Target (mutually exclusive):** `file`+`line`+`column` OR `language`+`symbol` + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | string | conditional | Project-relative file path, or a dependency/library absolute path or `jar://` URL previously returned by the plugin. Required for position-based lookup. | +| `line` | integer | conditional | 1-based line. Required for position-based lookup. | +| `column` | integer | conditional | 1-based column. Required for position-based lookup. | +| `language` | string | conditional | Symbol language (e.g., `"Java"`). Required for symbol-based lookup. | +| `symbol` | string | conditional | Fully qualified symbol reference. Required for symbol-based lookup. | +| `fullElementPreview` | boolean | no | Return full element code (default false) | +| `maxPreviewLines` | integer | no | Max lines for full preview (default 50, max 500) | +| `project_path` | string | no | Project root path | + +**Returns**: `{ file, line, column, preview, symbolName, astPath }` +Handles: packages, compiled classes, library sources (jar: URLs). + +### ide_find_class +Search for classes/interfaces by name using IDE's class index. Equivalent to Ctrl+N / Cmd+O. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `query` | string | yes | Class name pattern | +| `scope` | enum | no | One of `project_files` (default), `project_and_libraries`, `project_production_files`, `project_test_files` | +| `language` | string | no | Filter: "Java", "Kotlin", "Python", etc. | +| `matchMode` | enum | no | `substring` (default), `prefix`, `exact` | +| `limit` | integer | no | Deprecated alias for `pageSize`. Default 25, max 500 | +| `cursor` | string | no | Pagination cursor from a previous response. When provided, search parameters are ignored; `project_path` and `pageSize` may still be provided. | +| `pageSize` | integer | no | Results per page. Default 25, max 500 | +| `project_path` | string | no | Project root path | + +**Returns**: `{ classes: [{name, qualifiedName, file, line, kind, language}], totalCount, query }` +**Path note**: Project results use relative paths. Dependency/library results may use absolute paths or `jar://` URLs. +**Matching**: CamelCase (`USvc` -> `UserService`), substring, wildcard (`User*Impl`). + +### ide_find_file +Search for files by name using IDE's file index. Equivalent to Ctrl+Shift+N / Cmd+Shift+O. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `query` | string | yes | File name pattern | +| `scope` | enum | no | One of `project_files` (default), `project_and_libraries`, `project_production_files`, `project_test_files` | +| `limit` | integer | no | Deprecated alias for `pageSize`. Default 25, max 500 | +| `cursor` | string | no | Pagination cursor from a previous response. When provided, search parameters are ignored; `project_path` and `pageSize` may still be provided. | +| `pageSize` | integer | no | Results per page. Default 25, max 500 | +| `project_path` | string | no | Project root path | + +**Returns**: `{ files: [{name, path, directory}], totalCount, query }` +**Path note**: Project results use relative paths. Dependency/library results may use absolute paths or `jar://` URLs. + +### ide_search_text +Search for exact words using IDE's pre-built word index. O(1) lookups, not file scanning. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `query` | string | yes | Exact word (NOT regex/pattern) | +| `context` | enum | no | `all` (default), `code`, `comments`, `strings` | +| `caseSensitive` | boolean | no | Default true | +| `limit` | integer | no | Default 100, max 500 | +| `project_path` | string | no | Project root path | + +**Returns**: `{ matches: [{file, line, column, context}], totalCount, query }` + +### ide_find_implementations +Find implementations of interfaces, abstract classes, or abstract methods. + +**Target (mutually exclusive):** `file`+`line`+`column` OR `language`+`symbol` + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | string | conditional | Project-relative file path, or a dependency/library absolute path or `jar://` URL previously returned by the plugin. Required for position-based lookup. | +| `line` | integer | conditional | 1-based line. Required for position-based lookup. | +| `column` | integer | conditional | 1-based column. Required for position-based lookup. | +| `language` | string | conditional | Symbol language (e.g., `"Java"`). Required for symbol-based lookup. | +| `symbol` | string | conditional | Fully qualified symbol reference. Required for symbol-based lookup. | +| `scope` | enum | no | One of `project_files` (default), `project_and_libraries`, `project_production_files`, `project_test_files` | +| `cursor` | string | no | Pagination cursor from a previous response. When provided, search parameters are ignored; `project_path` and `pageSize` may still be provided. | +| `pageSize` | integer | no | Results per page. Default 100, max 500 | +| `project_path` | string | no | Project root path | + +**Returns**: `{ implementations: [{name, file, line, column, kind, language}], totalCount, nextCursor?, hasMore, totalCollected, offset, pageSize, stale }` +**Languages**: Java, Kotlin, Python, JS/TS, PHP, Rust (not Go). + +### ide_find_symbol (disabled by default) +Search for any code symbol (classes, methods, fields, functions) by name. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `query` | string | yes | Symbol name pattern. Matching follows IntelliJ's Go to Symbol popup, including qualified queries like `BasicSolver.run`. | +| `scope` | enum | no | One of `project_files` (default), `project_and_libraries`, `project_production_files`, `project_test_files` | +| `language` | string | no | Filter by language | +| `limit` | integer | no | Deprecated alias for `pageSize`. Default 25, max 500 | +| `cursor` | string | no | Pagination cursor from a previous response. When provided, search parameters are ignored; `project_path` and `pageSize` may still be provided. | +| `pageSize` | integer | no | Results per page. Default 25, max 500 | +| `project_path` | string | no | Project root path | + +**Returns**: `{ symbols: [{name, qualifiedName, file, line, kind, language}], totalCount, query }` +**Languages**: Java, Kotlin, Python, JS/TS, Go, PHP, Rust, plus other IDE-supplied symbol contributors where available. +**Path note**: Project results use relative paths. Dependency/library results may use absolute paths or `jar://` URLs. + +### ide_find_super_methods +Find parent methods that a given method overrides or implements. + +**Target (mutually exclusive):** `file`+`line`+`column` OR `language`+`symbol` + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | string | conditional | Project-relative file path, or a dependency/library absolute path or `jar://` URL previously returned by the plugin. Required for position-based lookup. | +| `line` | integer | conditional | 1-based line. Required for position-based lookup. | +| `column` | integer | conditional | 1-based column (anywhere in method body works). Required for position-based lookup. | +| `language` | string | conditional | Symbol language (e.g., `"Java"`). Required for symbol-based lookup. | +| `symbol` | string | conditional | Fully qualified symbol reference. Required for symbol-based lookup. | +| `project_path` | string | no | Project root path | + +**Returns**: `{ method: {name, class, file, line}, hierarchy: [{name, class, file, line, isInterface}], totalCount }` +**Languages**: Java, Kotlin, Python, JS/TS, PHP (NOT Go, Rust). + +### ide_type_hierarchy +Get complete type inheritance hierarchy (supertypes and subtypes). + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `className` | string | no | FQN (preferred, faster). E.g., `com.example.MyClass` | +| `file` | string | no | Alternative: project-relative file path. Unlike other read-only navigation tools, `ide_type_hierarchy` file mode does not resolve dependency/library absolute paths or `jar://` URLs. | +| `line` | integer | no | Required with file | +| `column` | integer | no | Required with file | +| `scope` | enum | no | One of `project_files` (default), `project_and_libraries`, `project_production_files`, `project_test_files` | +| `project_path` | string | no | Project root path | + +**Provide either** `className` **or** `file`+`line`+`column`. +**Returns**: `{ element: {name, file, kind, language, supertypes?}, supertypes: [{name, file, kind, language, supertypes?}], subtypes: [{name, file, kind, language, supertypes?}] }` +**Languages**: Java, Kotlin, Python, JS/TS, PHP, Rust. + +### ide_call_hierarchy +Build call tree showing who calls a method or what a method calls. + +**Target (mutually exclusive):** `file`+`line`+`column` OR `language`+`symbol` + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | string | conditional | Project-relative file path, or a dependency/library absolute path or `jar://` URL previously returned by the plugin. Required for position-based lookup. | +| `line` | integer | conditional | 1-based line. Required for position-based lookup. | +| `column` | integer | conditional | 1-based column. Required for position-based lookup. | +| `language` | string | conditional | Symbol language (e.g., `"Java"`). Required for symbol-based lookup. | +| `symbol` | string | conditional | Fully qualified symbol reference. Required for symbol-based lookup. | +| `direction` | enum | yes | `callers` or `callees` | +| `depth` | integer | no | Recursion depth (default 3, max 5) | +| `scope` | enum | no | One of `project_files` (default), `project_and_libraries`, `project_production_files`, `project_test_files` | +| `project_path` | string | no | Project root path | + +**Returns**: `{ element: {name, file, line, column, language}, calls: [{name, file, line, column, language, children: [...]}] }` + +### ide_file_structure (disabled by default) +Get hierarchical file structure like IDE's Structure panel. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | string | yes | Relative file path | +| `project_path` | string | no | Project root path | + +**Returns**: `{ file, language, structure }` (formatted tree with types, modifiers, signatures, line numbers) +**Languages**: Java, Kotlin, Python, JS/TS, Markdown. + +### ide_read_file (disabled by default) +Read file content by path or qualified name, including library/jar sources. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | string | no | File path (relative, absolute, or jar:// URL) | +| `qualifiedName` | string | no | Java/PHP FQN (e.g., `java.util.ArrayList`) | +| `startLine` | integer | no | 1-based start line | +| `endLine` | integer | no | 1-based end line | +| `project_path` | string | no | Project root path | + +**Provide either** `file` **or** `qualifiedName`. +**Returns**: `{ file, content, language, lineCount, startLine?, endLine?, isLibraryFile }` + +--- + +## Intelligence Tools + +### ide_diagnostics +Analyze a file for errors, warnings, and available quick fixes/intentions. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | string | yes | Relative file path | +| `line` | integer | no | For intention lookup (default 1) | +| `column` | integer | no | For intention lookup (default 1) | +| `startLine` | integer | no | Filter problems to range | +| `endLine` | integer | no | Filter problems to range | +| `project_path` | string | no | Project root path | + +**Returns**: `{ problems: [{message, severity, line, column, source}], intentions: [{name, description, familyName}], problemCount, intentionCount, analysisFresh, analysisTimedOut, analysisMessage }` +**Notes**: Open files use fresh daemon highlights. Closed files use public batch analysis, so `WEAK_WARNING` results and quick-fix intentions may be less complete unless the file is already open in an editor. +**Severity levels**: `ERROR`, `WARNING`, `WEAK_WARNING` + +--- + +## Refactoring Tools + +### ide_refactor_rename +Rename a symbol and update ALL references (semantic rename, not find-replace). Works across ALL languages. + +**Target (mutually exclusive):** `file`+`line`+`column` OR `language`+`symbol` + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | string | conditional | Relative file path. Required for position-based lookup. | +| `line` | integer | conditional | 1-based line. Required for position-based lookup. | +| `column` | integer | conditional | 1-based column. Required for position-based lookup. | +| `language` | string | conditional | Symbol language (e.g., `"Java"`). Required for symbol-based lookup. | +| `symbol` | string | conditional | Fully qualified symbol reference. Required for symbol-based lookup. | +| `newName` | string | yes | New name for the symbol | +| `overrideStrategy` | enum | no | `rename_base` (default), `rename_only_current`, `ask` | +| `project_path` | string | no | Project root path | + +**Returns**: `{ success, affectedFiles: [paths], changesCount, message }` +**Auto-renames**: getters/setters, overriding methods, constructor params <-> fields, test classes. +**Supports IDE undo** (Ctrl+Z). + +### ide_move_file +Move a file to a new directory. Applies language-aware reference, import, and package/namespace updates only when the IDE provides a semantic move backend for that file type. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | string | yes | Relative path of file to move | +| `destination` | string | yes | Target directory (relative to project root, created if needed) | +| `project_path` | string | no | Project root path | + +**Returns**: `{ success, affectedFiles: [paths], changesCount, message }` +**Supports IDE undo** (Ctrl+Z). + +### ide_refactor_safe_delete (Java/Kotlin only) +Delete a symbol or file, checking for usages first. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | string | yes | Relative file path | +| `line` | integer | no | Required for target_type="symbol" | +| `column` | integer | no | Required for target_type="symbol" | +| `target_type` | enum | no | `symbol` (default) or `file` | +| `force` | boolean | no | Force delete even with usages (default false) | +| `project_path` | string | no | Project root path | + +**Returns (success)**: `{ success, affectedFiles, changesCount, message }` +**Returns (blocked)**: `{ canDelete: false, elementName, usageCount, blockingUsages: [...], message }` +**Only available in**: IntelliJ IDEA, Android Studio (requires Java plugin). + +### ide_reformat_code (disabled by default) +Reformat code per project style (.editorconfig, IDE settings). Equivalent to Ctrl+Alt+L / Cmd+Opt+L. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | string | yes | Relative file path | +| `startLine` | integer | no | 1-based start (requires endLine) | +| `endLine` | integer | no | 1-based end (requires startLine) | +| `optimizeImports` | boolean | no | Default true | +| `rearrangeCode` | boolean | no | Default true | +| `project_path` | string | no | Project root path | + +**Returns**: `{ success, affectedFiles, changesCount, message }` + +--- + +## Project Tools + +### ide_index_status +Check if IDE is ready for code intelligence operations. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `project_path` | string | no | Project root path | + +**Returns**: `{ isDumbMode, isIndexing, indexingProgress? }` +When `isDumbMode: true`, most tools will fail. Wait and retry. + +### ide_sync_files +Force sync IDE's virtual file system with external file changes. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `paths` | string[] | no | Relative paths to sync (empty = sync entire project) | +| `project_path` | string | no | Project root path | + +**Returns**: `{ syncedPaths, syncedAll, message }` +Call this when files were created/modified outside the IDE and search tools miss them. + +### ide_build_project (disabled by default) +Build project using IDE's build system (JPS, Gradle, Maven). + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `project_path` | string | no | For workspace sub-projects | +| `rebuild` | boolean | no | Full rebuild (default false = incremental) | +| `includeRawOutput` | boolean | no | Include raw build log (default false) | +| `timeoutSeconds` | integer | no | Build timeout (no timeout if omitted) | + +**Returns**: `{ success, aborted, errors?, warnings?, buildMessages: [{message, file, line, column, severity}], truncated, rawOutput?, durationMs }` +Note: `errors`/`warnings` are `null` when no messages were captured (not 0). + +--- + +## Editor Tools + +### ide_get_active_file (disabled by default) +Get currently active file(s) in editor with cursor position and selection. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `project_path` | string | no | Project root path | + +**Returns**: `{ activeFiles: [{file, line, column, selectedText, language}] }` + +### ide_open_file (disabled by default) +Open a file in the editor with optional navigation. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | string | yes | Relative or absolute path | +| `line` | integer | no | 1-based line to navigate to | +| `column` | integer | no | 1-based column (requires line) | +| `project_path` | string | no | Project root path | + +**Returns**: `{ file, opened, message }` diff --git a/.claude/skills/jetbrains-debugger/SKILL.md b/.claude/skills/jetbrains-debugger/SKILL.md new file mode 100644 index 0000000000..1fd760158b --- /dev/null +++ b/.claude/skills/jetbrains-debugger/SKILL.md @@ -0,0 +1,169 @@ +--- +name: jetbrains-debugger +description: >- + Guide for using JetBrains IDE Debugger MCP tools to programmatically debug applications. + TRIGGER when ANY of these MCP tools are available: list_run_configurations, execute_run_configuration, + start_debug_session, stop_debug_session, get_debug_session_status, list_debug_sessions, + set_breakpoint, remove_breakpoint, list_breakpoints, resume_execution, pause_execution, + step_over, step_into, step_out, run_to_line, wait_for_pause, get_stack_trace, select_stack_frame, + list_threads, get_variables, set_variable, get_source_context, evaluate_expression. + Use when debugging any application, investigating bugs, tracing execution flow, inspecting + runtime state, or when the user says "debug", "breakpoint", "step through", "inspect variable", + "why is this returning X", "trace execution", or similar debugging-related requests. + PREFER the debugger over reading code and guessing when runtime behavior is unclear. +--- + +# JetBrains Debugger MCP + +Use these tools to **actually debug** applications in a JetBrains IDE rather than guessing from static code. + +**Complete parameter reference:** See [references/tool-reference.md](references/tool-reference.md) for all tool parameters, types, defaults, and return schemas. + +## When to Use the Debugger + +**USE the debugger when:** +- A bug involves runtime state (wrong values, unexpected nulls, incorrect flow) +- Reading code alone doesn't explain the behavior +- The user asks "why does X happen" or "what value does Y have" +- A test fails and the cause isn't obvious from the assertion message +- You need to verify a hypothesis about execution flow +- The user explicitly asks to debug + +**DON'T use the debugger when:** +- The bug is a clear syntax error, typo, or missing import +- The fix is obvious from reading the code (e.g., off-by-one, wrong operator) +- There's no run configuration available to debug + +## Core Workflow + +### Standard Debugging Sequence + +``` +1. list_run_configurations -- Find a config with can_debug: true +2. set_breakpoint -- Set breakpoint(s) BEFORE starting +3. start_debug_session -- Launch the debugger +4. wait_for_pause(timeout=60) -- Block until breakpoint hit (returns full status) +5. evaluate_expression -- Test hypotheses about values +6. step_over / step_into / step_out -- Navigate through code +7. wait_for_pause(timeout=10) -- Wait for step to complete, get state +8. resume_execution -- Continue to next breakpoint +9. wait_for_pause(timeout=60) -- Block until next breakpoint hit +10. stop_debug_session -- Clean up when done +``` + +### Critical Rules + +1. **Set breakpoints BEFORE starting the session.** Breakpoints can be set without an active session. Setting them first ensures the program pauses where you need it. + +2. **After `resume_execution` or any step command, use `wait_for_pause` to block until the session pauses.** It returns the full session status (variables, stack, source, location) when the pause occurs — no polling needed. Step/resume commands return immediately with `newState: "running"` and do NOT wait for the program to pause. + +3. **Use `get_debug_session_status` to re-inspect state without waiting.** It returns variables, stack trace, source context, and current location in ONE call. Do NOT call `get_variables`, `get_stack_trace`, and `get_source_context` separately unless you need specific parameters (e.g., a different frame index or more context lines). + +4. **Line numbers are 1-based.** When setting breakpoints or using `run_to_line`, use the line numbers as they appear in the editor (starting from 1). + +5. **File paths must be absolute.** For `set_breakpoint`, `run_to_line`, and `get_source_context`, always use absolute file paths (e.g., `/Users/dev/project/src/Main.java`). + +6. **`session_id` is optional for single-session debugging.** When only one debug session exists, all tools auto-select it. Only specify `session_id` when multiple sessions are active. + +7. **`project_path` is required when multiple projects are open.** If omitted with multiple projects, tools return an error listing available projects. + +## Debugging Patterns + +### Pattern: Find Why a Value is Wrong +``` +1. set_breakpoint at the line where the wrong value is used +2. start_debug_session with the appropriate run configuration +3. wait_for_pause(timeout=60) -- blocks until breakpoint hit, returns full status +4. Inspect variables in the response -- the wrong value and its inputs are visible +5. evaluate_expression to test alternative calculations +6. If the value was already wrong here, set_breakpoint earlier in the call chain +7. resume_execution, then wait_for_pause(timeout=60) -- repeat +``` + +### Pattern: Debug a Specific Loop Iteration +``` +1. set_breakpoint with condition (e.g., condition: "i == 50") +2. start_debug_session +3. wait_for_pause(timeout=120) -- debugger runs at full speed until condition is true +4. Inspect variables in the response -- state at exactly iteration 50 +``` + +### Pattern: Trace Execution Without Stopping +``` +1. set_breakpoint with log_message and suspend_policy: "none" + Example: log_message: "Entering process() with id={id}, count={items.size()}" +2. start_debug_session +3. resume_execution +4. Check IDE console output for trace log -- execution never pauses +``` + +### Pattern: Inspect a Different Stack Frame +``` +1. get_debug_session_status -- see the stack summary +2. select_stack_frame with the frame_index of interest (0 = current, 1 = caller, etc.) +3. get_variables -- now shows variables from the selected frame +4. evaluate_expression -- expressions evaluated in the selected frame's context +``` + +### Pattern: Test a Fix Without Restarting +``` +1. Pause at the point of interest +2. evaluate_expression with the corrected logic to verify it produces the right result +3. set_variable to inject the correct value +4. resume_execution to see if the fix resolves the downstream issue +``` + +## Common Mistakes to Avoid + +| Mistake | Correct Approach | +|---------|-----------------| +| Calling `get_variables` + `get_stack_trace` + `get_source_context` separately | Use `get_debug_session_status` -- returns all three in one call | +| Starting debug session without setting breakpoints first | Set breakpoints BEFORE `start_debug_session` | +| Assuming `step_over` returns the new state | Call `wait_for_pause` after stepping to block until paused and get the new state | +| Using 0-based line numbers | Line numbers are **1-based** (as shown in the editor) | +| Using relative file paths | Always use **absolute** file paths | +| Not waiting after `resume_execution` | Use `wait_for_pause` to block until the next breakpoint is hit | +| Calling `evaluate_expression` with method calls in Rust/C++/Go | Use `get_variables` for native languages; method calls may fail in LLDB/GDB | +| Guessing variable values from source code | Use the debugger to inspect actual runtime values | +| Forgetting to `stop_debug_session` when done | Always clean up debug sessions | + +## Language-Specific Notes + +### Full Support (Java, Kotlin, Python, JavaScript, TypeScript, PHP, Ruby) +- All tools work as documented +- `evaluate_expression` supports method calls, field access, arithmetic +- `set_variable` works for all types including objects and strings + +### Limited Support (Rust, C++, C, Go, Swift) +These use native debuggers (LLDB/GDB) with restrictions: +- `evaluate_expression`: Variable inspection works, but method calls (e.g., `s.len()`, `vec.size()`) may fail +- `set_variable`: Works for primitives (int, float, bool). Complex types (String, Vec, structs) may fail +- **Workaround:** Use `get_variables` to inspect values instead of `evaluate_expression` with method calls + +## Tool Quick Reference + +| Tool | Purpose | Requires Paused | +|------|---------|:---:| +| `list_run_configurations` | Find debuggable configurations | No | +| `execute_run_configuration` | Run or debug a configuration | No | +| `start_debug_session` | Start debugging | No | +| `stop_debug_session` | End debugging | No | +| `list_debug_sessions` | See active sessions | No | +| `get_debug_session_status` | **Primary inspector** -- variables, stack, source, location | No (but most useful when paused) | +| `set_breakpoint` | Set line breakpoint (with optional condition/log) | No | +| `remove_breakpoint` | Remove a breakpoint | No | +| `list_breakpoints` | See all breakpoints | No | +| `resume_execution` | Continue running | **Yes** | +| `wait_for_pause` | Block until session pauses, return full status | No | +| `pause_execution` | Pause running program | No (must be running) | +| `step_over` | Next line (skip into functions) | **Yes** | +| `step_into` | Enter function call | **Yes** | +| `step_out` | Finish current function | **Yes** | +| `run_to_line` | Run to specific line | **Yes** | +| `get_stack_trace` | Full call stack | **Yes** | +| `select_stack_frame` | Change frame context | **Yes** | +| `list_threads` | See all threads | **Yes** | +| `get_variables` | Variables in current frame | **Yes** | +| `set_variable` | Modify a variable at runtime | **Yes** | +| `get_source_context` | Source code around a location | No | +| `evaluate_expression` | Evaluate any expression | **Yes** | diff --git a/.claude/skills/jetbrains-debugger/references/tool-reference.md b/.claude/skills/jetbrains-debugger/references/tool-reference.md new file mode 100644 index 0000000000..c6d688231b --- /dev/null +++ b/.claude/skills/jetbrains-debugger/references/tool-reference.md @@ -0,0 +1,333 @@ +# JetBrains Debugger MCP - Complete Tool Reference + +## Table of Contents +- [Session Management](#session-management) +- [Breakpoints](#breakpoints) +- [Execution Control](#execution-control) +- [Stack & Threads](#stack--threads) +- [Variables](#variables) +- [Navigation](#navigation) +- [Evaluation](#evaluation) + +--- + +## Session Management + +### `list_run_configurations` +List available run/debug configurations in the project. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `project_path` | string | No | Project path (required if multiple projects open) | + +**Returns:** `configurations[]` (name, type, canRun, canDebug, isTemporary, folder), `activeConfiguration` + +### `execute_run_configuration` +Execute a run configuration in debug or run mode. + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `project_path` | string | No | | Project path | +| `name` | string | **Yes** | | Configuration name (exact match) | +| `mode` | string | No | `"debug"` | `"debug"` or `"run"` | + +**Returns:** `status`, `configurationName`, `mode`, `message` + +### `list_debug_sessions` +List all active debug sessions. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `project_path` | string | No | Project path | + +**Returns:** `sessions[]` (id, name, state, isCurrent, runConfigurationName), `currentSessionId`, `totalCount` + +### `start_debug_session` +Start a new debug session for a run configuration. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `project_path` | string | No | Project path | +| `configuration_name` | string | **Yes** | Run configuration name | + +**Returns:** `status` ("started"/"starting"), `session` (DebugSessionInfo), `message` + +**Note:** Polls for up to 30 seconds for the session to start. The session may still be in "starting" state for very slow targets. + +### `stop_debug_session` +Stop/terminate a debug session. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `session_id` | string | No | Session ID (uses current if omitted) | +| `project_path` | string | No | Project path | + +**Returns:** `status` ("stopped"), `sessionId`, `message` + +### `get_debug_session_status` (PRIMARY INSPECTION TOOL) +Get comprehensive session state in a single call. **Use this as the first inspection tool when paused.** + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `session_id` | string | No | | Session ID | +| `include_variables` | boolean | No | `true` | Include variables in scope | +| `include_source_context` | boolean | No | `true` | Include surrounding source code | +| `source_context_lines` | integer | No | `5` | Lines of source context (0-50) | +| `max_stack_frames` | integer | No | `10` | Max stack frames (1-200) | +| `project_path` | string | No | | Project path | + +**Returns:** +- `sessionId`, `name`, `state` ("running", "paused", "stopped") +- `pausedReason` ("breakpoint", "step", "exception", "pause") - null if running +- `currentLocation` (file, line, className, methodName) - null if not paused +- `breakpointHit` (breakpoint info) - null if not hit +- `stackSummary[]` (index, file, line, className, methodName) +- `variables[]` (name, value, type, hasChildren) +- `sourceContext` (file, lines[], currentLine, breakpointsInView[]) +- `currentThread` (id, name, state) +- `threadCount` + +--- + +## Breakpoints + +### `list_breakpoints` +List all breakpoints in the project. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `project_path` | string | No | Project path | + +**Returns:** `breakpoints[]` (id, type, file, line, enabled, condition, logMessage, suspendPolicy, hitCount, temporary), `totalCount`, `enabledCount` + +### `set_breakpoint` +Set a line breakpoint with optional conditions or log messages. + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `project_path` | string | No | | Project path | +| `file_path` | string | **Yes** | | **Absolute** file path | +| `line` | integer | **Yes** | | 1-based line number (min: 1) | +| `condition` | string | No | | Boolean expression (e.g., `"count > 10"`) | +| `log_message` | string | No | | Message with `{expression}` placeholders | +| `suspend_policy` | string | No | `"all"` | `"all"`, `"thread"`, or `"none"` | +| `enabled` | boolean | No | `true` | Whether breakpoint is active | +| `temporary` | boolean | No | `false` | Remove after first hit | + +**Returns:** `breakpointId`, `status` ("set"), `verified`, `file`, `line`, `message` + +**Log message syntax:** Use `{expression}` placeholders. Auto-transformed per language: +- Java: `"x={x}"` becomes `"x=" + (x)` +- Kotlin: `"x={x}"` becomes `"x=$x"` +- Python: `"x={x}"` becomes `f"x={x}"` +- JS/TS: `"x={x}"` becomes `` `x=${x}` `` + +**Tracepoint:** Set `suspend_policy: "none"` with a `log_message` to log without stopping. + +### `remove_breakpoint` +Remove a breakpoint by its ID. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `project_path` | string | No | Project path | +| `breakpoint_id` | string | **Yes** | Breakpoint ID from `list_breakpoints` or `set_breakpoint` | + +**Returns:** `breakpointId`, `status` ("removed"), `message` + +--- + +## Execution Control + +All stepping/resume tools require the session to be **paused**. They return `ExecutionControlResult` with `sessionId`, `action`, `status`, `newState`, `message`. + +### `resume_execution` +Resume program execution from paused state. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `session_id` | string | No | Session ID | +| `project_path` | string | No | Project path | + +**Requires:** Session paused. **New state:** "running" + +### `pause_execution` +Pause a running debug session. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `session_id` | string | No | Session ID | +| `project_path` | string | No | Project path | + +**Requires:** Session running. **New state:** "paused" + +### `step_over` +Execute current line, stepping over function calls. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `session_id` | string | No | Session ID | +| `project_path` | string | No | Project path | + +**Requires:** Session paused. **New state:** "running" (will pause at next line) + +### `step_into` +Step into the function call on current line. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `session_id` | string | No | Session ID | +| `project_path` | string | No | Project path | + +**Requires:** Session paused. **New state:** "running" (will pause inside function) + +### `step_out` +Continue execution until current function returns. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `session_id` | string | No | Session ID | +| `project_path` | string | No | Project path | + +**Requires:** Session paused. **New state:** "running" (will pause at caller) + +### `run_to_line` +Continue execution until a specific line is reached. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `session_id` | string | No | Session ID | +| `file_path` | string | **Yes** | Absolute file path | +| `line` | integer | **Yes** | 1-based target line (min: 1) | +| `project_path` | string | No | Project path | + +**Requires:** Session paused. **New state:** "running" (will pause at target line) + +### `wait_for_pause` +Wait for a debug session to pause (breakpoint hit, exception, or manual pause). Returns the full session status when paused, equivalent to calling `get_debug_session_status`. Use after `resume_execution`, `start_debug_session`, or any execution control tool to avoid manual polling. + +If `session_id` is omitted and no session exists yet, the tool waits for a session to appear before waiting for it to pause. This means you can call `start_debug_session` followed by `wait_for_pause` without needing to poll for the session ID. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `session_id` | string | No | Session ID. If omitted, uses current session. If no session exists yet, waits for one to appear. | +| `timeout` | integer | **Yes** | Maximum wait time in seconds (must be positive) | +| `breakpoint_ids` | string[] | No | Only complete when one of these breakpoints is hit. Non-matching breakpoint pauses are auto-resumed. Pauses where no breakpoint is detected at the current location return immediately. Uses file/line heuristics — may not distinguish all pause causes perfectly. | +| `project_path` | string | No | Project path | + +**Returns:** `waitResult` ("paused"/"timeout"/"session_stopped"), `message`, plus full session status (sessionId, name, state, pausedReason, currentLocation, breakpointHit, stackSummary, variables, sourceContext, currentThread) + +--- + +## Stack & Threads + +### `get_stack_trace` +Get the call stack showing how execution reached current point. + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `session_id` | string | No | | Session ID | +| `max_frames` | integer | No | `50` | Max frames to return (1-200) | +| `project_path` | string | No | | Project path | + +**Requires:** Session paused. + +**Returns:** `sessionId`, `threadId`, `frames[]` (index, file, line, className, methodName, isCurrent, isLibrary, presentation), `totalFrames` + +### `select_stack_frame` +Change debugger context to a different stack frame (to inspect variables in a different call). + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `frame_index` | integer | **Yes** | 0-based frame index (0 = topmost/current) | +| `session_id` | string | No | Session ID | +| `project_path` | string | No | Project path | + +**Requires:** Session paused. + +**Returns:** `frameIndex`, `frame` (StackFrameInfo), `message` + +### `list_threads` +List all threads in the debugged process. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `session_id` | string | No | Session ID | +| `project_path` | string | No | Project path | + +**Requires:** Session paused. + +**Returns:** `sessionId`, `threads[]` (id, name, state, isCurrent), `currentThreadId` + +--- + +## Variables + +### `get_variables` +Get all variables visible in current or specified stack frame. + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `session_id` | string | No | | Session ID | +| `frame_index` | integer | No | `0` | Stack frame index (0 = current) | +| `project_path` | string | No | | Project path | + +**Requires:** Session paused. + +**Returns:** `sessionId`, `frameIndex`, `variables[]` (name, value, type, hasChildren) + +### `set_variable` +Modify a variable's value at runtime. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `session_id` | string | No | Session ID | +| `variable_name` | string | **Yes** | Variable name | +| `new_value` | string | **Yes** | New value expression (e.g., `"42"`, `"\"hello\""`, `"null"`) | +| `project_path` | string | No | Project path | + +**Requires:** Session paused. + +**Returns:** `sessionId`, `variableName`, `oldValue`, `newValue`, `type`, `message` + +**Limitation:** In native debuggers (Rust, C++, Go), complex types may fail. Primitives work reliably. + +--- + +## Navigation + +### `get_source_context` +Get source code lines around a location. + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `session_id` | string | No | | Session ID | +| `file_path` | string | No | | Absolute path (uses current location if omitted) | +| `line` | integer | No | | 1-based line (uses current if omitted) | +| `lines_before` | integer | No | `5` | Context lines before | +| `lines_after` | integer | No | `5` | Context lines after | +| `project_path` | string | No | | Project path | + +**Returns:** `file`, `startLine`, `endLine`, `currentLine`, `lines[]` (number, content, isCurrent), `breakpointsInView[]` + +--- + +## Evaluation + +### `evaluate_expression` +Evaluate an expression in the current debug context. + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `expression` | string | **Yes** | | Expression to evaluate (e.g., `"x"`, `"list.size()"`, `"a + b"`) | +| `session_id` | string | No | | Session ID | +| `frame_index` | integer | No | `0` | Stack frame index | +| `project_path` | string | No | | Project path | + +**Requires:** Session paused. + +**Returns:** `sessionId`, `frameIndex`, `result` (expression, value, type, hasChildren, error) + +**Limitations for native languages (Rust, C++, Go, Swift):** +- Variable inspection works +- Method calls (e.g., `s.len()`, `vec.size()`) may fail +- Use `get_variables` as an alternative diff --git a/CLAUDE.md b/CLAUDE.md index 94d8ead3c8..f9a59ff091 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -118,4 +118,15 @@ When searching for Java method usages, always include `*.jsp` and `*.jspf` files ## Pull Request Format -PRs should include sections for: **Rationale** (why the change is needed), **Related Pull Requests**, and **Changes** (notable items). \ No newline at end of file +PRs should include sections for: **Rationale** (why the change is needed), **Related Pull Requests**, and **Changes** (notable items). + +## Tool Usage Rules + +When navigating or searching this codebase, prefer IntelliJ MCP tools over shell commands: + +- **Finding a class or symbol** → use `find_usages` or `search_in_project` MCP tool, NOT `grep` or `find` +- **Checking errors/warnings** → use `get_file_problems` MCP tool, NOT manual inspection +- **Project structure** → use `get_project_modules` and `list_dependencies` MCP tools +- **Running Tomcat** → use `run_configuration` MCP tool, NOT shell + +Only fall back to shell commands if the MCP tool fails or is unavailable. \ No newline at end of file