RG-agentic_terminal 0.1.0__tar.gz

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.
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: RG-agentic_terminal
3
+ Version: 0.1.0
4
+ Summary: An MCP which adds the terminal capabilities to an agent.
5
+ Author-email: Rohan <rohangorde0505@gmail.com>
6
+ Requires-Python: >=3.13
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: fastmcp>=4.2.0
File without changes
@@ -0,0 +1,22 @@
1
+ [project]
2
+ name = "RG-agentic_terminal"
3
+ version = "0.1.0"
4
+ description = "An MCP which adds the terminal capabilities to an agent."
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Rohan", email = "rohangorde0505@gmail.com" }
8
+ ]
9
+ requires-python = ">=3.13"
10
+ dependencies = [
11
+ "fastmcp>=4.2.0",
12
+ ]
13
+
14
+ [build-system]
15
+ requires = ["setuptools>=42", "wheel"]
16
+ build-backend = "setuptools.build_meta"
17
+
18
+ [tools.setuptools.packages.find]
19
+ where = ["src"]
20
+
21
+ [project.scripts]
22
+ agentic_terminal = "agentic_terminal.main:main"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: RG-agentic_terminal
3
+ Version: 0.1.0
4
+ Summary: An MCP which adds the terminal capabilities to an agent.
5
+ Author-email: Rohan <rohangorde0505@gmail.com>
6
+ Requires-Python: >=3.13
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: fastmcp>=4.2.0
@@ -0,0 +1,12 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/__init__.py
4
+ src/RG_agentic_terminal.egg-info/PKG-INFO
5
+ src/RG_agentic_terminal.egg-info/SOURCES.txt
6
+ src/RG_agentic_terminal.egg-info/dependency_links.txt
7
+ src/RG_agentic_terminal.egg-info/entry_points.txt
8
+ src/RG_agentic_terminal.egg-info/requires.txt
9
+ src/RG_agentic_terminal.egg-info/top_level.txt
10
+ src/agentic_terminal/__init__.py
11
+ src/agentic_terminal/main.py
12
+ src/agentic_terminal/tools.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ agentic_terminal = agentic_terminal.main:main
@@ -0,0 +1,2 @@
1
+ __init__
2
+ agentic_terminal
File without changes
@@ -0,0 +1,7 @@
1
+ from agentic_terminal.tools import mcp
2
+
3
+ def main():
4
+ mcp.run(transport="stdio")
5
+
6
+ if __name__ == "__main__":
7
+ main()
@@ -0,0 +1,460 @@
1
+
2
+ from fastmcp import FastMCP
3
+
4
+ import os
5
+ import sys
6
+ import shutil
7
+ import subprocess
8
+ import platform
9
+ import hashlib
10
+ import json
11
+ from pathlib import Path
12
+ from datetime import datetime
13
+
14
+ mcp = FastMCP()
15
+
16
+
17
+ # ============================================================
18
+ # 1. ORIGINAL TOOLS - PRESERVED
19
+ # ============================================================
20
+
21
+ @mcp.tool()
22
+ def bash(command: str):
23
+ '''This function will execute a bash command and return the output. This function
24
+ is useful for executing bash commands including creating files, directories, and other bash commands.'''
25
+ import subprocess
26
+ try:
27
+ result = subprocess.run(command, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
28
+ return result.stdout.decode('utf-8')
29
+ except subprocess.CalledProcessError as e:
30
+ return e.stderr.decode('utf-8')
31
+
32
+
33
+ @mcp.tool()
34
+ def python_code(code: str):
35
+ '''This function will execute a python code and return the output.'''
36
+ import subprocess
37
+ try:
38
+ result = subprocess.run(['python', '-c', code], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
39
+ return result.stdout.decode('utf-8')
40
+ except subprocess.CalledProcessError as e:
41
+ return e.stderr.decode('utf-8')
42
+
43
+
44
+ @mcp.tool()
45
+ def python_file(file: str):
46
+ '''This function will execute a python file and return the output.'''
47
+ import subprocess
48
+ try:
49
+ result = subprocess.run(['python', file], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
50
+ return result.stdout.decode('utf-8')
51
+ except subprocess.CalledProcessError as e:
52
+ return e.stderr.decode('utf-8')
53
+
54
+
55
+ @mcp.tool()
56
+ def glob(pattern: str):
57
+ '''This function will return a list of files that match the given pattern. This function is useful for finding files in a directory.'''
58
+ import glob
59
+ return glob.glob(pattern)
60
+
61
+
62
+ @mcp.tool()
63
+ def grep(pattern: str, file: str):
64
+ '''This function will search for the given pattern in the specified file and return the matching lines.'''
65
+ import subprocess
66
+
67
+ result = subprocess.run(
68
+ ['findstr', pattern, file],
69
+ stdout=subprocess.PIPE,
70
+ text=True
71
+ )
72
+
73
+ print(result.stdout)
74
+
75
+
76
+ @mcp.tool()
77
+ def read_file(file: str):
78
+ '''This function will read the contents of a file and return it as a string.'''
79
+ try:
80
+ with open(file, 'r') as f:
81
+ return f.read()
82
+ except Exception as e:
83
+ return str(e)
84
+
85
+
86
+ @mcp.tool()
87
+ def write_file(file: str, content: str):
88
+ '''This function will write the given content to a file. If the file does not exist, it will be created.'''
89
+ try:
90
+ with open(file, 'w') as f:
91
+ f.write(content)
92
+ return f"Content written to {file} successfully."
93
+ except Exception as e:
94
+ return str(e)
95
+
96
+
97
+ @mcp.tool()
98
+ def create_folder(folder: str):
99
+ '''This function will create a folder with the given name. If the folder already exists, it will return a message indicating that the folder already exists.'''
100
+ import os
101
+ try:
102
+ os.makedirs(folder)
103
+ return f"Folder '{folder}' created successfully."
104
+ except FileExistsError:
105
+ return f"Folder '{folder}' already exists."
106
+ except Exception as e:
107
+ return str(e)
108
+
109
+
110
+ @mcp.tool()
111
+ def delete_folder(folder: str):
112
+ '''This function will delete a folder with the given name. If the folder does not exist, it will return a message indicating that the folder does not exist.'''
113
+ import shutil
114
+ import os
115
+ try:
116
+ if os.path.exists(folder):
117
+ shutil.rmtree(folder)
118
+ return f"Folder '{folder}' deleted successfully."
119
+ else:
120
+ return f"Folder '{folder}' does not exist."
121
+ except Exception as e:
122
+ return str(e)
123
+
124
+
125
+ # ============================================================
126
+ # 2. DIRECTORY MANAGEMENT TOOLS
127
+ # ============================================================
128
+
129
+ @mcp.tool()
130
+ def list_directory(directory: str = "."):
131
+ '''List all files and folders inside a directory with their types.'''
132
+ try:
133
+ path = Path(directory)
134
+
135
+ if not path.exists():
136
+ return f"Directory '{directory}' does not exist."
137
+
138
+ if not path.is_dir():
139
+ return f"'{directory}' is not a directory."
140
+
141
+ items = []
142
+
143
+ for item in sorted(path.iterdir()):
144
+ item_type = "Directory" if item.is_dir() else "File"
145
+ items.append({
146
+ "name": item.name,
147
+ "type": item_type,
148
+ "path": str(item.resolve())
149
+ })
150
+
151
+ return json.dumps(items, indent=4)
152
+
153
+ except Exception as e:
154
+ return str(e)
155
+
156
+
157
+ @mcp.tool()
158
+ def directory_tree(directory: str = ".", max_depth: int = 3):
159
+ '''Generate a visual tree structure of directories and files.'''
160
+ try:
161
+ root = Path(directory)
162
+
163
+ if not root.is_dir():
164
+ return "Invalid directory."
165
+
166
+ lines = [root.name]
167
+
168
+ def build_tree(path, prefix="", depth=0):
169
+ if depth >= max_depth:
170
+ return
171
+
172
+ try:
173
+ entries = sorted(
174
+ path.iterdir(),
175
+ key=lambda p: (p.is_file(), p.name.lower())
176
+ )
177
+ except PermissionError:
178
+ lines.append(prefix + "[Permission denied]")
179
+ return
180
+
181
+ for index, entry in enumerate(entries):
182
+ last = index == len(entries) - 1
183
+ connector = "└── " if last else "├── "
184
+
185
+ lines.append(prefix + connector + entry.name)
186
+
187
+ if entry.is_dir():
188
+ extension = " " if last else "│ "
189
+ build_tree(entry, prefix + extension, depth + 1)
190
+
191
+ build_tree(root)
192
+
193
+ return "\n".join(lines)
194
+
195
+ except Exception as e:
196
+ return str(e)
197
+
198
+
199
+ # ============================================================
200
+ # 3. ADVANCED FILE MANAGEMENT
201
+ # ============================================================
202
+
203
+ @mcp.tool()
204
+ def append_file(file: str, content: str):
205
+ '''Append new content to an existing file or create a new file.'''
206
+ try:
207
+ with open(file, "a", encoding="utf-8") as f:
208
+ f.write(content)
209
+
210
+ return f"Content appended successfully to {file}."
211
+
212
+ except Exception as e:
213
+ return str(e)
214
+
215
+
216
+ @mcp.tool()
217
+ def copy_file(source: str, destination: str):
218
+ '''Copy a file from source to destination.'''
219
+ try:
220
+ if not os.path.isfile(source):
221
+ return "Source file does not exist."
222
+
223
+ shutil.copy2(source, destination)
224
+
225
+ return f"File copied from {source} to {destination}."
226
+
227
+ except Exception as e:
228
+ return str(e)
229
+
230
+
231
+ @mcp.tool()
232
+ def move_file(source: str, destination: str):
233
+ '''Move a file from one location to another.'''
234
+ try:
235
+ if not os.path.exists(source):
236
+ return "Source does not exist."
237
+
238
+ shutil.move(source, destination)
239
+
240
+ return f"Moved {source} to {destination}."
241
+
242
+ except Exception as e:
243
+ return str(e)
244
+
245
+
246
+ @mcp.tool()
247
+ def rename_file(file: str, new_name: str):
248
+ '''Rename a file or directory.'''
249
+ try:
250
+ path = Path(file)
251
+
252
+ if not path.exists():
253
+ return "File or directory does not exist."
254
+
255
+ new_path = path.with_name(new_name)
256
+ path.rename(new_path)
257
+
258
+ return f"Renamed successfully to {new_path}."
259
+
260
+ except Exception as e:
261
+ return str(e)
262
+
263
+
264
+ @mcp.tool()
265
+ def file_info(file: str):
266
+ '''Get detailed information about a file including size, extension and timestamps.'''
267
+ try:
268
+ path = Path(file)
269
+
270
+ if not path.exists():
271
+ return "File does not exist."
272
+
273
+ stats = path.stat()
274
+
275
+ information = {
276
+ "name": path.name,
277
+ "absolute_path": str(path.resolve()),
278
+ "extension": path.suffix,
279
+ "size_bytes": stats.st_size,
280
+ "size_kb": round(stats.st_size / 1024, 2),
281
+ "created_time": datetime.fromtimestamp(stats.st_ctime).isoformat(),
282
+ "modified_time": datetime.fromtimestamp(stats.st_mtime).isoformat(),
283
+ "is_file": path.is_file(),
284
+ "is_directory": path.is_dir()
285
+ }
286
+
287
+ return json.dumps(information, indent=4)
288
+
289
+ except Exception as e:
290
+ return str(e)
291
+
292
+
293
+ # ============================================================
294
+ # 4. CODE INTELLIGENCE TOOLS
295
+ # ============================================================
296
+
297
+ @mcp.tool()
298
+ def search_files(directory: str, pattern: str, file_extension: str = "*"):
299
+ '''Search for text inside files recursively.
300
+ Supports filtering by file extension, for example .py or .js.
301
+ '''
302
+ try:
303
+ root = Path(directory)
304
+
305
+ if not root.is_dir():
306
+ return "Invalid directory."
307
+
308
+ results = []
309
+
310
+ for file in root.rglob("*"):
311
+ if not file.is_file():
312
+ continue
313
+
314
+ if file_extension != "*" and file.suffix.lower() != file_extension.lower():
315
+ continue
316
+
317
+ try:
318
+ with file.open("r", encoding="utf-8") as f:
319
+ for line_number, line in enumerate(f, start=1):
320
+ if pattern.lower() in line.lower():
321
+ results.append({
322
+ "file": str(file),
323
+ "line": line_number,
324
+ "content": line.strip()
325
+ })
326
+
327
+ except (UnicodeDecodeError, PermissionError, OSError):
328
+ continue
329
+
330
+ return json.dumps(results, indent=4)
331
+
332
+ except Exception as e:
333
+ return str(e)
334
+
335
+
336
+ @mcp.tool()
337
+ def count_lines(file: str):
338
+ '''Count total lines, non-empty lines and characters in a source-code file.'''
339
+ try:
340
+ path = Path(file)
341
+
342
+ if not path.is_file():
343
+ return "File does not exist."
344
+
345
+ with path.open("r", encoding="utf-8") as f:
346
+ content = f.read()
347
+
348
+ lines = content.splitlines()
349
+
350
+ result = {
351
+ "file": str(path),
352
+ "total_lines": len(lines),
353
+ "non_empty_lines": sum(1 for line in lines if line.strip()),
354
+ "characters": len(content),
355
+ "words": len(content.split())
356
+ }
357
+
358
+ return json.dumps(result, indent=4)
359
+
360
+ except Exception as e:
361
+ return str(e)
362
+
363
+
364
+ @mcp.tool()
365
+ def file_hash(file: str):
366
+ '''Calculate SHA-256 hash of a file for integrity verification.'''
367
+ try:
368
+ path = Path(file)
369
+
370
+ if not path.is_file():
371
+ return "File does not exist."
372
+
373
+ sha256 = hashlib.sha256()
374
+
375
+ with path.open("rb") as f:
376
+ for chunk in iter(lambda: f.read(1024 * 1024), b""):
377
+ sha256.update(chunk)
378
+
379
+ return {
380
+ "file": str(path),
381
+ "algorithm": "SHA-256",
382
+ "hash": sha256.hexdigest()
383
+ }
384
+
385
+ except Exception as e:
386
+ return str(e)
387
+
388
+
389
+ # ============================================================
390
+ # 5. SYSTEM INFORMATION TOOLS
391
+ # ============================================================
392
+
393
+ @mcp.tool()
394
+ def system_info():
395
+ '''Get operating system, architecture, Python version and machine information.'''
396
+ try:
397
+ information = {
398
+ "operating_system": platform.system(),
399
+ "os_release": platform.release(),
400
+ "os_version": platform.version(),
401
+ "architecture": platform.machine(),
402
+ "processor": platform.processor(),
403
+ "hostname": platform.node(),
404
+ "python_version": sys.version,
405
+ "python_executable": sys.executable,
406
+ "current_directory": os.getcwd()
407
+ }
408
+
409
+ return json.dumps(information, indent=4)
410
+
411
+ except Exception as e:
412
+ return str(e)
413
+
414
+
415
+ @mcp.tool()
416
+ def disk_usage(path: str = "."):
417
+ '''Check total, used and available disk space for a given path.'''
418
+ try:
419
+ total, used, free = shutil.disk_usage(path)
420
+
421
+ information = {
422
+ "path": str(Path(path).resolve()),
423
+ "total_gb": round(total / (1024 ** 3), 2),
424
+ "used_gb": round(used / (1024 ** 3), 2),
425
+ "free_gb": round(free / (1024 ** 3), 2),
426
+ "usage_percent": round((used / total) * 100, 2)
427
+ }
428
+
429
+ return json.dumps(information, indent=4)
430
+
431
+ except Exception as e:
432
+ return str(e)
433
+
434
+
435
+ @mcp.tool()
436
+ def installed_packages():
437
+ '''List all Python packages installed in the active Python environment.'''
438
+ try:
439
+ result = subprocess.run(
440
+ [sys.executable, "-m", "pip", "list", "--format=json"],
441
+ capture_output=True,
442
+ text=True,
443
+ check=True
444
+ )
445
+
446
+ return result.stdout
447
+
448
+ except subprocess.CalledProcessError as e:
449
+ return e.stderr
450
+
451
+ except Exception as e:
452
+ return str(e)
453
+
454
+
455
+ # ============================================================
456
+ # 6. SERVER ENTRY POINT
457
+ # ============================================================
458
+
459
+ if __name__ == "__main__":
460
+ mcp.run()