run_skill_script
Execute scripts within skill directories with automatic dependency management, environment variable injection, and secure execution boundaries.
Instructions
Execute a script within a skill directory. Skills are modular libraries with reusable code - scripts can import from their own modules or use external dependencies.
IMPORTANT: ALWAYS use this tool to execute scripts. DO NOT use external bash/shell tools to execute scripts directly. This tool provides:
Automatic dependency management (Python PEP 723, npm packages)
Proper environment variable injection from .env files
Secure execution within skill directory boundaries
Proper error handling and output capture
SKILLS AS LIBRARIES: Scripts within a skill can import from local modules naturally:
In main.py:
Execute with:
SUPPORTED LANGUAGES:
Python: Automatically detects and installs PEP 723 inline dependencies via 'uv run'
JavaScript/Node.js: Automatically runs 'npm install' if package.json exists
Bash: Executes shell scripts (.sh files)
Other: Any executable file with proper shebang line
FEATURES:
Module imports: Scripts can import from other files within the skill directory
Automatic PEP 723 dependency detection: Python scripts with inline metadata are automatically run with 'uv run'
Automatic npm dependency installation: Node.js scripts install dependencies from package.json
Environment variables: Loads skill-specific .env file and injects variables into script environment
Working directory: Can specify a subdirectory to run the script from
Arguments: Pass command-line arguments to the script
Output capture: Returns stdout, stderr, and exit code
PEP 723 AUTOMATIC DEPENDENCY DETECTION: Python scripts with inline dependencies are automatically detected and executed with 'uv run':
Example Python script with PEP 723 (e.g., weather-skill/fetch_weather.py):
Execute with automatic dependency handling:
No manual dependency installation needed - the server automatically:
Detects the PEP 723 metadata in your script
Uses 'uv run' to create an isolated environment
Installs the declared dependencies
Executes your script with access to those dependencies
PARAMETERS:
skill_name: The name of the skill directory (e.g., 'weather-skill')
script_path: Relative path to the script within skill directory (e.g., 'main.py', 'scripts/fetch_weather.py', 'bin/process.sh')
args: Optional list of command-line arguments (e.g., ['--verbose', 'input.txt'])
working_dir: Optional working directory relative to skill root (e.g., 'scripts')
timeout: Optional timeout in seconds (defaults to 30 seconds if not specified)
IMPORTANT PATH NOTES:
All paths are RELATIVE to the skill directory, never absolute paths
Script path example: 'main.py' NOT '/Users/username/.skill-mcp/skills/my-skill/main.py'
Working dir example: 'scripts' NOT '/full/path/to/scripts'
RETURNS: Script execution result with:
Exit code (0 = success, non-zero = failure)
STDOUT (standard output)
STDERR (error output)
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| skill_name | Yes | Name of the skill | |
| script_path | Yes | Relative path to the script within the skill directory | |
| args | No | Optional command-line arguments to pass to the script | |
| working_dir | No | Optional working directory for script execution | |
| timeout | No | Optional timeout in seconds (defaults to 30 seconds if not specified) |
Implementation Reference
- The primary handler function for the 'run_skill_script' tool. It calls ScriptService.run_script to execute the script and formats the output including exit code, stdout, and stderr.async def run_skill_script(input_data: RunSkillScriptInput) -> list[types.TextContent]: """Execute a skill script.""" try: result = await ScriptService.run_script( input_data.skill_name, input_data.script_path, input_data.args, input_data.working_dir, input_data.timeout, ) output = f"Script: {input_data.skill_name}/{input_data.script_path}\n" output += f"Exit code: {result.exit_code}\n\n" if result.stdout: output += f"STDOUT:\n{result.stdout}\n" if result.stderr: output += f"STDERR:\n{result.stderr}\n" if not result.stdout and not result.stderr: output += "(No output)\n" return [types.TextContent(type="text", text=output)] except SkillMCPException as e: return [types.TextContent(type="text", text=f"Error: {str(e)}")] except Exception as e: return [types.TextContent(type="text", text=f"Error running script: {str(e)}")]
- src/skill_mcp/models.py:56-71 (schema)Pydantic model defining the input schema (parameters and types) for the 'run_skill_script' tool.class RunSkillScriptInput(BaseModel): """Input for running a skill script.""" skill_name: str = Field(description="Name of the skill") script_path: str = Field(description="Relative path to the script within the skill directory") args: Optional[List[str]] = Field( default=None, description="Optional command-line arguments to pass to the script" ) working_dir: Optional[str] = Field( default=None, description="Optional working directory for script execution" ) timeout: Optional[int] = Field( default=None, description="Optional timeout in seconds (defaults to 30 seconds if not specified)", )
- src/skill_mcp/tools/script_tools.py:129-235 (registration)The Tool object definition for 'run_skill_script', including name, detailed description, and input schema reference. This is returned by ScriptTools.get_script_tools().types.Tool( name="run_skill_script", description="""Execute a script within a skill directory. Skills are modular libraries with reusable code - scripts can import from their own modules or use external dependencies. IMPORTANT: ALWAYS use this tool to execute scripts. DO NOT use external bash/shell tools to execute scripts directly. This tool provides: - Automatic dependency management (Python PEP 723, npm packages) - Proper environment variable injection from .env files - Secure execution within skill directory boundaries - Proper error handling and output capture SKILLS AS LIBRARIES: Scripts within a skill can import from local modules naturally: ``` weather-skill/ ├── main.py # Script that imports from modules below ├── api_client.py # Reusable API client module ├── parsers.py # Data parsing utilities └── formatters.py # Output formatting ``` In main.py: ```python from api_client import WeatherAPI from formatters import format_temperature api = WeatherAPI() data = api.get_weather("London") print(format_temperature(data)) ``` Execute with: ```json { "skill_name": "weather-skill", "script_path": "main.py", "args": ["--city", "London"] } ``` SUPPORTED LANGUAGES: - Python: Automatically detects and installs PEP 723 inline dependencies via 'uv run' - JavaScript/Node.js: Automatically runs 'npm install' if package.json exists - Bash: Executes shell scripts (.sh files) - Other: Any executable file with proper shebang line FEATURES: - Module imports: Scripts can import from other files within the skill directory - **Automatic PEP 723 dependency detection**: Python scripts with inline metadata are automatically run with 'uv run' - Automatic npm dependency installation: Node.js scripts install dependencies from package.json - Environment variables: Loads skill-specific .env file and injects variables into script environment - Working directory: Can specify a subdirectory to run the script from - Arguments: Pass command-line arguments to the script - Output capture: Returns stdout, stderr, and exit code PEP 723 AUTOMATIC DEPENDENCY DETECTION: Python scripts with inline dependencies are automatically detected and executed with 'uv run': Example Python script with PEP 723 (e.g., weather-skill/fetch_weather.py): ```python #!/usr/bin/env python3 # /// script # dependencies = [ # "requests>=2.31.0", # "beautifulsoup4>=4.12.0", # ] # /// import requests from bs4 import BeautifulSoup response = requests.get("https://api.weather.com/data") print(response.json()) ``` Execute with automatic dependency handling: ```json { "skill_name": "weather-skill", "script_path": "fetch_weather.py", "args": ["--city", "London"] } ``` No manual dependency installation needed - the server automatically: 1. Detects the PEP 723 metadata in your script 2. Uses 'uv run' to create an isolated environment 3. Installs the declared dependencies 4. Executes your script with access to those dependencies PARAMETERS: - skill_name: The name of the skill directory (e.g., 'weather-skill') - script_path: Relative path to the script within skill directory (e.g., 'main.py', 'scripts/fetch_weather.py', 'bin/process.sh') - args: Optional list of command-line arguments (e.g., ['--verbose', 'input.txt']) - working_dir: Optional working directory relative to skill root (e.g., 'scripts') - timeout: Optional timeout in seconds (defaults to 30 seconds if not specified) IMPORTANT PATH NOTES: - All paths are RELATIVE to the skill directory, never absolute paths - Script path example: 'main.py' NOT '/Users/username/.skill-mcp/skills/my-skill/main.py' - Working dir example: 'scripts' NOT '/full/path/to/scripts' RETURNS: Script execution result with: - Exit code (0 = success, non-zero = failure) - STDOUT (standard output) - STDERR (error output)""", inputSchema=RunSkillScriptInput.model_json_schema(), ),
- src/skill_mcp/server.py:30-38 (registration)MCP server registration via list_tools() decorator, which includes ScriptTools.get_script_tools() to add the 'run_skill_script' tool to the server's tool list.@app.list_tools() # type: ignore[misc] async def list_tools() -> list[types.Tool]: """List available tools.""" tools = [] tools.extend(SkillCrud.get_tool_definition()) tools.extend(SkillFilesCrud.get_tool_definition()) tools.extend(SkillEnvCrud.get_tool_definition()) tools.extend(ScriptTools.get_script_tools()) return tools
- src/skill_mcp/server.py:60-62 (handler)Dispatch handler in the MCP server's call_tool function that validates input with RunSkillScriptInput and delegates to ScriptTools.run_skill_script.elif name == "run_skill_script": script_input = RunSkillScriptInput(**arguments) return await ScriptTools.run_skill_script(script_input)