6
6
from typing import IO , Any , Dict , List , Optional , Tuple , Union
7
7
8
8
from mcp_shell_server .command_validator import CommandValidator
9
+ from mcp_shell_server .directory_manager import DirectoryManager
9
10
10
11
11
12
class ShellExecutor :
@@ -15,9 +16,10 @@ class ShellExecutor:
15
16
16
17
def __init__ (self ):
17
18
"""
18
- Initialize the executor with a command validator.
19
+ Initialize the executor with a command validator and directory manager .
19
20
"""
20
21
self .validator = CommandValidator ()
22
+ self .directory_manager = DirectoryManager ()
21
23
22
24
def _validate_redirection_syntax (self , command : List [str ]) -> None :
23
25
"""
@@ -221,18 +223,7 @@ def _validate_directory(self, directory: Optional[str]) -> None:
221
223
Raises:
222
224
ValueError: If the directory doesn't exist, not absolute or is not accessible
223
225
"""
224
- # make directory required
225
- if directory is None :
226
- raise ValueError ("Directory is required" )
227
- # verify directory is absolute path
228
- if not os .path .isabs (directory ):
229
- raise ValueError (f"Directory must be an absolute path: { directory } " )
230
- if not os .path .exists (directory ):
231
- raise ValueError (f"Directory does not exist: { directory } " )
232
- if not os .path .isdir (directory ):
233
- raise ValueError (f"Not a directory: { directory } " )
234
- if not os .access (directory , os .R_OK | os .X_OK ):
235
- raise ValueError (f"Directory is not accessible: { directory } " )
226
+ self .directory_manager .validate_directory (directory )
236
227
237
228
def _validate_no_shell_operators (self , cmd : str ) -> None :
238
229
"""Validate that the command does not contain shell operators"""
@@ -465,10 +456,8 @@ async def execute(
465
456
466
457
# Update stdin from redirects if present
467
458
if redirects ["stdin" ]:
468
- stdin_path = (
469
- os .path .join (directory , str (redirects ["stdin" ]))
470
- if directory and redirects ["stdin" ]
471
- else str (redirects ["stdin" ])
459
+ stdin_path = self .directory_manager .get_absolute_path (
460
+ str (redirects ["stdin" ]), directory
472
461
)
473
462
try :
474
463
with open (stdin_path , "r" ) as f :
@@ -479,10 +468,8 @@ async def execute(
479
468
# Setup output redirection
480
469
stdout_handle : Union [int , IO [Any ]] = asyncio .subprocess .PIPE
481
470
if redirects ["stdout" ]:
482
- stdout_path = (
483
- os .path .join (directory , str (redirects ["stdout" ]))
484
- if directory and redirects ["stdout" ]
485
- else str (redirects ["stdout" ])
471
+ stdout_path = self .directory_manager .get_absolute_path (
472
+ str (redirects ["stdout" ]), directory
486
473
)
487
474
mode = "a" if redirects ["stdout_append" ] else "w"
488
475
try :
@@ -593,19 +580,18 @@ async def _execute_pipeline(
593
580
parsed_commands .append (parsed_cmd )
594
581
595
582
if commands .index (cmd ) == 0 and redirects ["stdin" ]:
596
- stdin_path = (
597
- os .path .join (directory , str (redirects ["stdin" ]))
598
- if directory
599
- else str (redirects ["stdin" ])
583
+ stdin_path = self .directory_manager .get_absolute_path (
584
+ str (redirects ["stdin" ]), directory
600
585
)
601
586
with open (stdin_path , "r" ) as f :
602
587
first_stdin = f .read ().encode ()
603
588
604
589
if commands .index (cmd ) == len (commands ) - 1 and redirects ["stdout" ]:
605
- stdout_path = (
606
- os .path .join (directory , str (redirects ["stdout" ]))
607
- if directory
608
- else str (redirects ["stdout" ])
590
+ stdout_path = self .directory_manager .get_absolute_path (
591
+ str (redirects ["stdout" ]), directory
592
+ )
593
+ last_stdout = open (
594
+ stdout_path , "a" if redirects ["stdout_append" ] else "w"
609
595
)
610
596
last_stdout = open (
611
597
stdout_path , "a" if redirects ["stdout_append" ] else "w"
0 commit comments