skydeckai-code 0.1.34__py3-none-any.whl → 0.1.36__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: skydeckai-code
3
- Version: 0.1.34
4
- Summary: This MCP server provides a comprehensive set of tools for AI-driven Development workflows including file operations, code analysis, code linting, multi-language execution, Git operations, web content fetching with HTML-to-markdown conversion, multi-engine web search, code content searching, and system information retrieval.
3
+ Version: 0.1.36
4
+ Summary: This MCP server provides a comprehensive set of tools for AI-driven Development workflows including file operations, code analysis, multi-language execution, web content fetching with HTML-to-markdown conversion, multi-engine web search, code content searching, and system information retrieval.
5
5
  Project-URL: Homepage, https://github.com/skydeckai/skydeckai-code
6
6
  Project-URL: Repository, https://github.com/skydeckai/skydeckai-code
7
7
  Project-URL: Documentation, https://github.com/skydeckai/skydeckai-code/blob/main/README.md
@@ -11,7 +11,6 @@ License-File: LICENSE
11
11
  Keywords: ai,aidd,code,code-analysis,development,mcp
12
12
  Requires-Python: >=3.11
13
13
  Requires-Dist: beautifulsoup4>=4.13.3
14
- Requires-Dist: gitpython>=3.1.44
15
14
  Requires-Dist: html2text>=2025.4.15
16
15
  Requires-Dist: mcp>=1.6.0
17
16
  Requires-Dist: mss>=10.0.0
@@ -36,7 +35,7 @@ Description-Content-Type: text/markdown
36
35
 
37
36
  # SkyDeckAI Code
38
37
 
39
- An MCP server that provides a comprehensive set of tools for AI-driven development workflows. Features include file system operations, code analysis using tree-sitter for multiple programming languages, Git operations, code execution, web content fetching with HTML-to-markdown conversion, multi-engine web search, code content searching, linting detection, and system information retrieval. Designed to enhance AI's capability to assist in software development tasks by providing direct access to both local and remote resources.
38
+ An MCP server that provides a comprehensive set of tools for AI-driven development workflows. Features include file system operations, code analysis using tree-sitter for multiple programming languages, code execution, web content fetching with HTML-to-markdown conversion, multi-engine web search, code content searching, and system information retrieval. Designed to enhance AI's capability to assist in software development tasks by providing direct access to both local and remote resources.
40
39
 
41
40
  # Formerly Known As MCP-Server-AIDD
42
41
 
@@ -80,7 +79,6 @@ If you're using SkyDeck AI Helper app, you can search for "SkyDeckAI Code" and i
80
79
  - Code linting and issue detection for Python and JavaScript/TypeScript
81
80
  - Code content searching with regex pattern matching
82
81
  - Multi-language code execution with safety measures
83
- - Git operations (status, diff, commit, branch management, cloning)
84
82
  - Web content fetching from APIs and websites with HTML-to-markdown conversion
85
83
  - Multi-engine web search with reliable fallback mechanisms
86
84
  - Batch operations for parallel and serial tool execution
@@ -92,27 +90,32 @@ If you're using SkyDeck AI Helper app, you can search for "SkyDeckAI Code" and i
92
90
 
93
91
  ### Basic File Operations
94
92
 
95
- | Tool | Parameters | Returns |
96
- | ------------------- | -------------------------------------------------------- | --------------------------------------------- |
97
- | read_file | path: string, offset?: integer, limit?: integer | File content (whole or partial) |
98
- | read_multiple_files | paths: string[] | Multiple file contents with headers |
99
- | write_file | path: string, content: string | Success confirmation |
100
- | move_file | source: string, destination: string | Success confirmation |
101
- | copy_file | source: string, destination: string, recursive?: boolean | Success confirmation |
102
- | delete_file | path: string | Success confirmation |
103
- | get_file_info | path: string | File metadata (size, timestamps, permissions) |
93
+ | Tool | Parameters | Returns |
94
+ | ------------- | ---------------------------------------------------------- | --------------------------------------------- |
95
+ | read_file | files: [{path: string, offset?: integer, limit?: integer}] | File content (single or multiple files) |
96
+ | write_file | path: string, content: string | Success confirmation |
97
+ | move_file | source: string, destination: string | Success confirmation |
98
+ | copy_file | source: string, destination: string, recursive?: boolean | Success confirmation |
99
+ | delete_file | path: string | Success confirmation |
100
+ | get_file_info | path: string | File metadata (size, timestamps, permissions) |
104
101
 
105
102
  Common usage:
106
103
 
107
104
  ```bash
108
105
  # Read entire file
109
- skydeckai-code-cli --tool read_file --args '{"path": "src/main.py"}'
106
+ skydeckai-code-cli --tool read_file --args '{"files": [{"path": "src/main.py"}]}'
110
107
 
111
108
  # Read 10 lines starting from line 20
112
- skydeckai-code-cli --tool read_file --args '{"path": "src/main.py", "offset": 20, "limit": 10}'
109
+ skydeckai-code-cli --tool read_file --args '{"files": [{"path": "src/main.py", "offset": 20, "limit": 10}]}'
113
110
 
114
111
  # Read from line 50 to the end of the file
115
- skydeckai-code-cli --tool read_file --args '{"path": "src/main.py", "offset": 50}'
112
+ skydeckai-code-cli --tool read_file --args '{"files": [{"path": "src/main.py", "offset": 50}]}'
113
+
114
+ # Read multiple files with different line ranges
115
+ skydeckai-code-cli --tool read_file --args '{"files": [
116
+ {"path": "src/main.py", "offset": 1, "limit": 10},
117
+ {"path": "README.md"}
118
+ ]}'
116
119
 
117
120
  # Write file
118
121
  skydeckai-code-cli --tool write_file --args '{"path": "output.txt", "content": "Hello World"}'
@@ -183,69 +186,6 @@ skydeckai-code-cli --tool list_directory --args '{"path": "."}'
183
186
  skydeckai-code-cli --tool search_files --args '{"pattern": ".py", "path": "src"}'
184
187
  ```
185
188
 
186
- ### Git Operations
187
-
188
- | Tool | Parameters | Returns |
189
- | ----------------- | ------------------------------------------------- | -------------------------------- |
190
- | git_init | path: string, initial_branch?: string | Repository initialization status |
191
- | git_status | repo_path: string | Working directory status |
192
- | git_add | repo_path: string, files: string[] | Staging confirmation |
193
- | git_reset | repo_path: string | Unstaging confirmation |
194
- | git_checkout | repo_path: string, branch_name: string | Branch switch confirmation |
195
- | git_create_branch | repo_path: string, branch_name: string | Branch creation confirmation |
196
- | git_clone | url: string, target_path: string, branch?: string | Clone confirmation |
197
- | git_diff_unstaged | repo_path: string | Unstaged changes diff |
198
- | git_diff_staged | repo_path: string | Staged changes diff |
199
- | git_show | repo_path: string, commit_hash: string | Details of a specific commit |
200
-
201
- #### Complex Git Operations
202
-
203
- ##### git_commit
204
-
205
- ```json
206
- {
207
- "repo_path": ".",
208
- "message": "feat: add new feature"
209
- }
210
- ```
211
-
212
- Returns: Commit hash and confirmation.
213
-
214
- ##### git_diff
215
-
216
- ```json
217
- {
218
- "repo_path": ".",
219
- "target": "main"
220
- }
221
- ```
222
-
223
- Returns: Detailed diff output showing all changes between the current branch and the specified target branch or commit.
224
-
225
- ##### git_log
226
-
227
- ```json
228
- {
229
- "repo_path": ".",
230
- "max_count": 10
231
- }
232
- ```
233
-
234
- Returns: Array of commit entries with hash, author, date, and message.
235
-
236
- Common usage:
237
-
238
- ```bash
239
- # Check status
240
- skydeckai-code-cli --tool git_status --args '{"repo_path": "."}'
241
-
242
- # Clone a repository
243
- skydeckai-code-cli --tool git_clone --args '{"url": "https://github.com/username/repo.git", "target_path": "repo"}'
244
-
245
- # Create and switch to new branch
246
- skydeckai-code-cli --tool git_create_branch --args '{"repo_path": ".", "branch_name": "feature/new-branch"}'
247
- ```
248
-
249
189
  ### Code Analysis
250
190
 
251
191
  #### codebase_mapper
@@ -269,8 +209,8 @@ Returns:
269
209
  Supported Languages:
270
210
 
271
211
  - Python (.py)
272
- - JavaScript (.js, .jsx, .mjs, .cjs)
273
- - TypeScript (.ts, .tsx)
212
+ - JavaScript (.js/.jsx, .mjs, .cjs)
213
+ - TypeScript (.ts/.tsx)
274
214
  - Java (.java)
275
215
  - C++ (.cpp, .hpp, .cc)
276
216
  - Ruby (.rb, .rake)
@@ -280,71 +220,17 @@ Supported Languages:
280
220
  - C# (.cs)
281
221
  - Kotlin (.kt, .kts)
282
222
 
283
- #### check_lint
284
-
285
- Check for linting issues in your codebase using native linting tools:
286
-
287
- ```json
288
- {
289
- "path": "src",
290
- "languages": ["python", "javascript"],
291
- "linters": {
292
- "pylint": "--disable=C0111",
293
- "flake8": true,
294
- "eslint": "--fix"
295
- },
296
- "max_issues": 100
297
- }
298
- ```
299
-
300
- **Parameters:**
301
- | Parameter | Type | Required | Description |
302
- |-----------|------|----------|-------------|
303
- | path | string | No | Directory or file to lint (default: ".") |
304
- | languages | array | No | List of languages to lint (auto-detects if empty) |
305
- | linters | object | No | Configuration for specific linters - can use booleans or CLI arguments |
306
- | max_issues | integer | No | Maximum number of issues to return (default: 100, 0 for unlimited) |
307
-
308
- **Returns:**
309
- A detailed report of linting issues found in the codebase, including file paths, line numbers, issue descriptions, and severity levels. Issues are grouped by file and sorted by severity.
310
-
311
- **Supported Languages and Linters:**
312
-
313
- - Python: pylint, flake8 (automatically uses what's available)
314
- - JavaScript/TypeScript: ESLint
315
- - Dart/Flutter: dart_analyze (also reports compilation errors)
316
-
317
223
  **Example Usage:**
318
224
 
319
225
  ```bash
320
- # Check entire codebase with default settings
321
- skydeckai-code-cli --tool check_lint
322
-
323
- # Check specific directory with custom pylint flags
324
- skydeckai-code-cli --tool check_lint --args '{
325
- "path": "src",
326
- "linters": {
327
- "pylint": "--disable=missing-docstring,invalid-name"
328
- }
329
- }'
226
+ # Map the entire codebase structure
227
+ skydeckai-code-cli --tool codebase_mapper --args '{"path": "."}'
330
228
 
331
- # Check only Python files and disable flake8
332
- skydeckai-code-cli --tool check_lint --args '{
333
- "path": "src",
334
- "languages": ["python"],
335
- "linters": {
336
- "flake8": false
337
- }
338
- }'
229
+ # Map only the source directory
230
+ skydeckai-code-cli --tool codebase_mapper --args '{"path": "src"}'
339
231
 
340
- # Check Dart/Flutter files for linting and compilation errors
341
- skydeckai-code-cli --tool check_lint --args '{
342
- "path": "lib",
343
- "languages": ["dart"],
344
- "linters": {
345
- "dart_analyze": "--fatal-infos"
346
- }
347
- }'
232
+ # Map a specific component or module
233
+ skydeckai-code-cli --tool codebase_mapper --args '{"path": "src/components"}'
348
234
  ```
349
235
 
350
236
  #### search_code
@@ -353,7 +239,7 @@ Fast content search tool using regular expressions:
353
239
 
354
240
  ```json
355
241
  {
356
- "pattern": "function\\s+\\w+",
242
+ "patterns": ["function\\s+\\w+", "class\\s+\\w+"],
357
243
  "include": "*.js",
358
244
  "exclude": "node_modules/**",
359
245
  "max_results": 50,
@@ -365,10 +251,10 @@ Fast content search tool using regular expressions:
365
251
  **Parameters:**
366
252
  | Parameter | Type | Required | Description |
367
253
  |-----------|------|----------|-------------|
368
- | pattern | string | Yes | Regular expression pattern to search in file contents |
254
+ | patterns | array of strings | Yes | List of regular expression patterns to search for in file contents |
369
255
  | include | string | No | File pattern to include (glob syntax, default: "\*") |
370
256
  | exclude | string | No | File pattern to exclude (glob syntax, default: "") |
371
- | max_results | integer | No | Maximum results to return (default: 100) |
257
+ | max_results | integer | No | Maximum results to return per pattern (default: 100) |
372
258
  | case_sensitive | boolean | No | Whether search is case-sensitive (default: false) |
373
259
  | path | string | No | Base directory to search from (default: ".") |
374
260
 
@@ -380,21 +266,21 @@ This tool uses ripgrep when available for optimal performance, with a Python fal
380
266
  **Example Usage:**
381
267
 
382
268
  ```bash
383
- # Find function declarations in JavaScript files
269
+ # Find function and class declarations in JavaScript files
384
270
  skydeckai-code-cli --tool search_code --args '{
385
- "pattern": "function\\s+\\w+",
271
+ "patterns": ["function\\s+\\w+", "class\\s+\\w+"],
386
272
  "include": "*.js"
387
273
  }'
388
274
 
389
- # Find all console.log statements with errors
275
+ # Find all console.log statements with errors or warnings
390
276
  skydeckai-code-cli --tool search_code --args '{
391
- "pattern": "console\\.log.*[eE]rror",
277
+ "patterns": ["console\\.log.*[eE]rror", "console\\.log.*[wW]arning"],
392
278
  "path": "src"
393
279
  }'
394
280
 
395
- # Find import statements in TypeScript files
281
+ # Find import and export statements in TypeScript files
396
282
  skydeckai-code-cli --tool search_code --args '{
397
- "pattern": "import.*from",
283
+ "patterns": ["import.*from", "export.*"],
398
284
  "include": "*.{ts,tsx}",
399
285
  "exclude": "node_modules/**"
400
286
  }'
@@ -692,10 +578,9 @@ Execute multiple tool invocations in a single request with parallel execution wh
692
578
  }
693
579
  },
694
580
  {
695
- "tool": "git_init",
581
+ "tool": "execute_shell_script",
696
582
  "arguments": {
697
- "path": ".",
698
- "initial_branch": "main"
583
+ "script": "git init"
699
584
  }
700
585
  }
701
586
  ]
@@ -2,26 +2,24 @@ src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  src/aidd/__init__.py,sha256=c9HBWxWruCxoAqLCJqltylAwz_7xmaK3g8DKViJZs0Q,222
3
3
  src/aidd/cli.py,sha256=cLtaQJmMBfr7fHkd0dyJqpDrVTIwybL48PotniWGrFM,5031
4
4
  src/aidd/server.py,sha256=kPRyWeWkMCZjabelC65XTmzZG7yw8htMJKSfnUcKnb0,1575
5
- src/aidd/tools/__init__.py,sha256=abFameL2CdSZohi7Sa1tUEOzD2M6bcXSOkRpgxfZ1mo,5429
5
+ src/aidd/tools/__init__.py,sha256=j1uL7WVH3xS8JTGnpSIhaz7qkc3gcxuDyvZIYP9UztI,3731
6
6
  src/aidd/tools/base.py,sha256=wHSAaGGYWM8ECmoYd7KEcmjsZRWesNQFf3zMjCKGMcc,380
7
7
  src/aidd/tools/code_analysis.py,sha256=fDpm2o_If5PsngXzHN2-ezSkPVT0ZxivLuzmHrOAmVU,33188
8
- src/aidd/tools/code_execution.py,sha256=dIPxHBtclsetDZY4jGlSBrw_t-7VlIVrK8mflnZ6c4w,13176
9
- src/aidd/tools/code_tools.py,sha256=3CgkQ78iVKMd5j8aLmolLp4c59seD42Qw6VbdUcg2wA,12628
8
+ src/aidd/tools/code_execution.py,sha256=HRLUR1-q1PiCXKZV5QmTknDJKsfvPvFSWZbTpYFcv7I,13703
9
+ src/aidd/tools/code_tools.py,sha256=DQ6N34Wbz5DwUPzt6RG7jk9HF2SsWFCFn99mencHK1c,14263
10
10
  src/aidd/tools/directory_tools.py,sha256=Hxzge_ziYw_FsjYb5yF0R0dHEdvuWRsg7WsdYDG0AUg,12971
11
- src/aidd/tools/file_tools.py,sha256=-OQHFCL_r1TI16-xBrwKfhzHKFgG965Jr0tAmZ9mKbI,44137
11
+ src/aidd/tools/file_tools.py,sha256=GYzP6WxGbV1V42FlWNSuGIyiCtRp09kwF6lOZrFtq_U,43112
12
12
  src/aidd/tools/get_active_apps_tool.py,sha256=BjLF7iXSDgyAmm_gfFgAul2Gn3iX-CNVYHM7Sh4jTAI,19427
13
13
  src/aidd/tools/get_available_windows_tool.py,sha256=OVIYhItTn9u_DftOr3vPCT-R0DOFvMEEJXA6tD6gqWQ,15952
14
- src/aidd/tools/git_tools.py,sha256=AgolgrZnpN2NALV7SfIwc6D7U7tdPrPTSFmU2WjPfVE,39846
15
14
  src/aidd/tools/image_tools.py,sha256=wT3EcJAfZWcM0IsXdDfbTNjgFhKZM9nu2wHN6Mk_TTQ,5970
16
- src/aidd/tools/lint_tools.py,sha256=0RYE-cXSbfw1VV_03GiFgYhC9ElhdWc4ecEjfMd9Els,25831
17
15
  src/aidd/tools/other_tools.py,sha256=iG3Sd2FP0M0pRv5esPBAUMvlwxTyAMDUdS77IqA_f5s,10822
18
16
  src/aidd/tools/path_tools.py,sha256=RGoOhqP69eHJzM8tEgn_5-GRaR0gp25fd0XZIJ_RnQE,4045
19
17
  src/aidd/tools/screenshot_tool.py,sha256=NMO5B4UG8qfMEOMRd2YoOjtwz_oQ2y1UAGU22jV1yGU,46337
20
18
  src/aidd/tools/state.py,sha256=RWSw0Jfsui8FqC0xsI7Ik07tAg35hRwLHa5xGBVbiI4,1493
21
19
  src/aidd/tools/system_tools.py,sha256=H4_qveKC2HA7SIbi-j4vxA0W4jYh2wfu9A6ni5wkZyA,7249
22
20
  src/aidd/tools/web_tools.py,sha256=gdsj2DEVYb_oYChItK5I1ugt2w25U7IAa5kEw9q6MVg,35534
23
- skydeckai_code-0.1.34.dist-info/METADATA,sha256=t-8R2yEUD7n3NIKyztRZoxG5TfsDshSa3Su9STh8Ojs,32850
24
- skydeckai_code-0.1.34.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
- skydeckai_code-0.1.34.dist-info/entry_points.txt,sha256=ZkU1spOhLEnz5MpUn4dDihVcE0DMUC6ejzbsF-eNth4,88
26
- skydeckai_code-0.1.34.dist-info/licenses/LICENSE,sha256=uHse04vmI6ZjW7TblegFl30X-sDyyF0-QvH8ItPca3c,10865
27
- skydeckai_code-0.1.34.dist-info/RECORD,,
21
+ skydeckai_code-0.1.36.dist-info/METADATA,sha256=V76YaV--GsD3nv6GFQa9ch7oEgez1cOXOdFzUPXoyH4,29110
22
+ skydeckai_code-0.1.36.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ skydeckai_code-0.1.36.dist-info/entry_points.txt,sha256=ZkU1spOhLEnz5MpUn4dDihVcE0DMUC6ejzbsF-eNth4,88
24
+ skydeckai_code-0.1.36.dist-info/licenses/LICENSE,sha256=uHse04vmI6ZjW7TblegFl30X-sDyyF0-QvH8ItPca3c,10865
25
+ skydeckai_code-0.1.36.dist-info/RECORD,,
@@ -25,47 +25,16 @@ from .file_tools import (
25
25
  handle_get_file_info,
26
26
  handle_move_file,
27
27
  handle_read_file,
28
- handle_read_multiple_files,
29
28
  handle_search_files,
30
29
  handle_write_file,
31
30
  move_file_tool,
32
31
  read_file_tool,
33
- read_multiple_files_tool,
34
32
  search_files_tool,
35
33
  write_file_tool,
36
34
  )
37
35
  from .get_active_apps_tool import get_active_apps_tool, handle_get_active_apps
38
36
  from .get_available_windows_tool import get_available_windows_tool, handle_get_available_windows
39
- from .git_tools import (
40
- git_add_tool,
41
- git_checkout_tool,
42
- git_clone_tool,
43
- git_commit_tool,
44
- git_create_branch_tool,
45
- git_diff_staged_tool,
46
- git_diff_tool,
47
- git_diff_unstaged_tool,
48
- git_init_tool,
49
- git_log_tool,
50
- git_reset_tool,
51
- git_show_tool,
52
- git_status_tool,
53
- handle_git_add,
54
- handle_git_checkout,
55
- handle_git_clone,
56
- handle_git_commit,
57
- handle_git_create_branch,
58
- handle_git_diff,
59
- handle_git_diff_staged,
60
- handle_git_diff_unstaged,
61
- handle_git_init,
62
- handle_git_log,
63
- handle_git_reset,
64
- handle_git_show,
65
- handle_git_status,
66
- )
67
37
  from .image_tools import read_image_file_tool, handle_read_image_file
68
- from .lint_tools import check_lint_tool, handle_check_lint
69
38
  from .other_tools import batch_tools_tool, handle_batch_tools, think_tool, handle_think
70
39
  from .path_tools import (
71
40
  get_allowed_directory_tool,
@@ -89,7 +58,6 @@ TOOL_DEFINITIONS = [
89
58
  edit_file_tool(),
90
59
  list_directory_tool(),
91
60
  read_file_tool(),
92
- read_multiple_files_tool(),
93
61
  move_file_tool(),
94
62
  copy_file_tool(),
95
63
  search_files_tool(),
@@ -100,24 +68,8 @@ TOOL_DEFINITIONS = [
100
68
  execute_shell_script_tool(),
101
69
  codebase_mapper_tool(),
102
70
  search_code_tool(),
103
- check_lint_tool(),
104
71
  batch_tools_tool(),
105
72
  think_tool(),
106
- # Git tools
107
- git_init_tool(),
108
- git_status_tool(),
109
- git_diff_unstaged_tool(),
110
- git_diff_staged_tool(),
111
- git_diff_tool(),
112
- git_commit_tool(),
113
- git_add_tool(),
114
- git_reset_tool(),
115
- git_log_tool(),
116
- git_create_branch_tool(),
117
- git_checkout_tool(),
118
- git_clone_tool(),
119
- git_show_tool(),
120
- get_system_info_tool(),
121
73
  # Screenshot tools
122
74
  capture_screenshot_tool(),
123
75
  # System context tools
@@ -128,6 +80,8 @@ TOOL_DEFINITIONS = [
128
80
  # Web tools
129
81
  web_fetch_tool(),
130
82
  web_search_tool(),
83
+ # System tools
84
+ get_system_info_tool(),
131
85
  ]
132
86
 
133
87
  # Export all handlers
@@ -139,12 +93,10 @@ TOOL_HANDLERS = {
139
93
  "read_file": handle_read_file,
140
94
  "write_file": handle_write_file,
141
95
  "edit_file": handle_edit_file,
142
- "read_multiple_files": handle_read_multiple_files,
143
96
  "move_file": handle_move_file,
144
97
  "copy_file": handle_copy_file,
145
98
  "search_files": handle_search_files,
146
99
  "search_code": handle_search_code,
147
- "check_lint": handle_check_lint,
148
100
  "delete_file": handle_delete_file,
149
101
  "get_file_info": handle_get_file_info,
150
102
  "directory_tree": handle_directory_tree,
@@ -153,20 +105,6 @@ TOOL_HANDLERS = {
153
105
  "codebase_mapper": handle_codebase_mapper,
154
106
  "batch_tools": handle_batch_tools,
155
107
  "think": handle_think,
156
- # Git handlers
157
- "git_init": handle_git_init,
158
- "git_status": handle_git_status,
159
- "git_diff_unstaged": handle_git_diff_unstaged,
160
- "git_diff_staged": handle_git_diff_staged,
161
- "git_diff": handle_git_diff,
162
- "git_commit": handle_git_commit,
163
- "git_add": handle_git_add,
164
- "git_reset": handle_git_reset,
165
- "git_log": handle_git_log,
166
- "git_create_branch": handle_git_create_branch,
167
- "git_checkout": handle_git_checkout,
168
- "git_clone": handle_git_clone,
169
- "git_show": handle_git_show,
170
108
  "get_system_info": handle_get_system_info,
171
109
  # Screenshot handlers
172
110
  "capture_screenshot": handle_capture_screenshot,
@@ -100,6 +100,9 @@ def execute_shell_script_tool() -> Dict[str, Any]:
100
100
  "Execute a shell script (bash/sh) on the user's local machine within the current working directory. "
101
101
  "WHEN TO USE: When you need to automate system tasks, run shell commands, interact with the operating system, or perform operations "
102
102
  "that are best expressed as shell commands. Useful for file system operations, system configuration, or running system utilities. "
103
+ "Also ideal when you need to run code linters to check for style issues or potential bugs in the codebase, "
104
+ "or when you need to perform version control operations such as initializing git repositories, checking status, "
105
+ "committing changes, cloning repositories, and other git commands without dedicated tools. "
103
106
  "WHEN NOT TO USE: When you need more structured programming (use execute_code instead), when you need to execute potentially "
104
107
  "dangerous system operations, or when you want to run commands outside the allowed directory. "
105
108
  "RETURNS: Text output including stdout, stderr, and exit code of the execution. The output sections are clearly labeled with "
@@ -110,6 +113,8 @@ def execute_shell_script_tool() -> Dict[str, Any]:
110
113
  "Examples: "
111
114
  "- script='echo \"Current directory:\" && pwd'. "
112
115
  "- script='for i in {1..5}; do echo $i; done'. "
116
+ "- script='eslint src/ --format stylish' (for linting). "
117
+ "- script='git init && git add . && git commit -m \"Initial commit\"' (for git operations)."
113
118
  ),
114
119
  "inputSchema": {
115
120
  "type": "object",
@@ -20,17 +20,19 @@ def search_code_tool():
20
20
  "WHEN NOT TO USE: When you need to find files by name (use search_files instead), when you need "
21
21
  "semantic code understanding (use codebase_mapper instead), or when analyzing individual file "
22
22
  "structure. "
23
- "RETURNS: Lines of code matching the specified pattern, grouped by file with line numbers. "
23
+ "RETURNS: Lines of code matching the specified patterns, grouped by file with line numbers. "
24
24
  "Results are sorted by file modification time with newest files first. Respects file filtering "
25
25
  "and ignores binary files. Search is restricted to the allowed directory.",
26
26
  "inputSchema": {
27
27
  "type": "object",
28
28
  "properties": {
29
- "pattern": {
30
- "type": "string",
31
- "description": "Regular expression pattern to search for in file contents. Supports full regex syntax. "
32
- "Examples: 'function\\s+\\w+' to find function declarations, 'import\\s+.*from' to find "
33
- "import statements, 'console\\.log.*Error' to find error logs."
29
+ "patterns": {
30
+ "type": "array",
31
+ "items": {
32
+ "type": "string"
33
+ },
34
+ "description": "List of regular expression patterns to search for in file contents. Supports full regex syntax. "
35
+ "Examples: ['function\\s+\\w+', 'class\\s+\\w+'] to find both function and class declarations."
34
36
  },
35
37
  "include": {
36
38
  "type": "string",
@@ -47,7 +49,7 @@ def search_code_tool():
47
49
  },
48
50
  "max_results": {
49
51
  "type": "integer",
50
- "description": "Maximum number of matching results to return. Use to limit output size for common patterns. "
52
+ "description": "Maximum number of matching results to return per pattern. Use to limit output size for common patterns. "
51
53
  "Default is 100, which is sufficient for most searches while preventing excessive output.",
52
54
  "default": 100
53
55
  },
@@ -65,22 +67,22 @@ def search_code_tool():
65
67
  "default": "."
66
68
  }
67
69
  },
68
- "required": ["pattern"]
70
+ "required": ["patterns"]
69
71
  }
70
72
  }
71
73
 
72
74
 
73
75
  async def handle_search_code(arguments: dict) -> List[TextContent]:
74
76
  """Handle searching for patterns in code files."""
75
- pattern = arguments.get("pattern")
77
+ patterns = arguments.get("patterns", [])
76
78
  include = arguments.get("include", "*")
77
79
  exclude = arguments.get("exclude", "")
78
80
  max_results = arguments.get("max_results", 100)
79
81
  case_sensitive = arguments.get("case_sensitive", False)
80
82
  path = arguments.get("path", ".")
81
83
 
82
- if not pattern:
83
- raise ValueError("Pattern must be provided")
84
+ if not patterns:
85
+ raise ValueError("At least one pattern must be provided")
84
86
 
85
87
  # Determine full path for search start
86
88
  if os.path.isabs(path):
@@ -97,17 +99,36 @@ async def handle_search_code(arguments: dict) -> List[TextContent]:
97
99
  if not os.path.isdir(full_path):
98
100
  raise ValueError(f"Path is not a directory: {path}")
99
101
 
102
+ # Results from all patterns
103
+ all_results = []
104
+
100
105
  try:
101
- # Use ripgrep if available for faster results
102
- try:
103
- return await _search_with_ripgrep(
104
- pattern, include, exclude, max_results, case_sensitive, full_path
105
- )
106
- except (subprocess.SubprocessError, FileNotFoundError):
107
- # Fallback to Python implementation if ripgrep not available
108
- return await _search_with_python(
109
- pattern, include, exclude, max_results, case_sensitive, full_path
110
- )
106
+ for i, pattern in enumerate(patterns):
107
+ pattern_header = f"\n{'='*30}\nPattern {i+1}: {pattern}\n{'='*30}\n" if len(patterns) > 1 else ""
108
+ try:
109
+ # Use ripgrep if available for faster results
110
+ try:
111
+ result = await _search_with_ripgrep(
112
+ pattern, include, exclude, max_results, case_sensitive, full_path
113
+ )
114
+ except (subprocess.SubprocessError, FileNotFoundError):
115
+ # Fallback to Python implementation if ripgrep not available
116
+ result = await _search_with_python(
117
+ pattern, include, exclude, max_results, case_sensitive, full_path
118
+ )
119
+
120
+ # Add pattern header for multiple patterns
121
+ if len(patterns) > 1 and result and result[0].text != f"No matches found for pattern '{pattern}'.":
122
+ result[0].text = pattern_header + result[0].text
123
+
124
+ all_results.extend(result)
125
+ except Exception as e:
126
+ all_results.append(TextContent(
127
+ type="text",
128
+ text=f"{pattern_header}Error searching for pattern '{pattern}': {str(e)}"
129
+ ))
130
+
131
+ return all_results
111
132
  except Exception as e:
112
133
  raise ValueError(f"Error searching code: {str(e)}")
113
134
 
@@ -193,9 +214,17 @@ async def _search_with_ripgrep(
193
214
 
194
215
  # Format output
195
216
  formatted_output = []
217
+ match_count = 0
196
218
  for file_path, data in sorted_files:
197
219
  formatted_output.append(f"\n{file_path} (modified: {datetime.fromtimestamp(data['mod_time']).strftime('%Y-%m-%d %H:%M:%S')})")
198
220
  formatted_output.extend(data["matches"])
221
+ match_count += len(data["matches"])
222
+
223
+ summary = f"Found {match_count} matches in {len(sorted_files)} files for pattern '{pattern}'"
224
+ if match_count > 0:
225
+ formatted_output.insert(0, summary)
226
+ else:
227
+ formatted_output = [summary]
199
228
 
200
229
  return [TextContent(
201
230
  type="text",
@@ -207,7 +236,7 @@ async def _search_with_ripgrep(
207
236
  # ripgrep returns 1 when no matches are found
208
237
  return [TextContent(
209
238
  type="text",
210
- text="No matches found."
239
+ text=f"No matches found for pattern '{pattern}'."
211
240
  )]
212
241
  raise
213
242
 
@@ -310,7 +339,7 @@ async def _search_with_python(
310
339
  if not files_with_matches:
311
340
  return [TextContent(
312
341
  type="text",
313
- text="No matches found."
342
+ text=f"No matches found for pattern '{pattern}'."
314
343
  )]
315
344
 
316
345
  # Sort files by modification time (newest first)
@@ -322,10 +351,21 @@ async def _search_with_python(
322
351
 
323
352
  # Format output
324
353
  formatted_output = []
354
+ total_matches = 0
355
+ files_with_actual_matches = 0
356
+
325
357
  for file_path, data in sorted_files:
326
358
  if data["matches"]: # Only include files that actually have matches
327
359
  formatted_output.append(f"\n{file_path} (modified: {datetime.fromtimestamp(data['mod_time']).strftime('%Y-%m-%d %H:%M:%S')})")
328
360
  formatted_output.extend(data["matches"])
361
+ total_matches += len(data["matches"])
362
+ files_with_actual_matches += 1
363
+
364
+ summary = f"Found {total_matches} matches in {files_with_actual_matches} files for pattern '{pattern}'"
365
+ if total_matches > 0:
366
+ formatted_output.insert(0, summary)
367
+ else:
368
+ formatted_output = [summary]
329
369
 
330
370
  return [TextContent(
331
371
  type="text",