Tools Module¶
Pydantic-AI compatible tools for sandboxed command execution in MCP servers and AI agents.
Overview¶
The tools module provides type-safe, reusable tools that integrate Shannot's sandbox capabilities with Model Context Protocol (MCP) servers and Pydantic-AI agents. These tools handle command execution, file reading, and output streaming with proper error handling.
Key Components:
SandboxDeps- Dependency container for sandbox configuration and executorsrun_sandbox_command- Execute arbitrary commands in the sandboxread_sandbox_file- Read file contents from sandboxed pathsstream_sandbox_output- Stream command output (for long-running processes)
Common Usage Patterns¶
With MCP Servers¶
from shannot.tools import SandboxDeps, run_sandbox_command
from shannot.executors import LocalExecutor
# Create dependencies
executor = LocalExecutor()
deps = SandboxDeps(profile_name="diagnostics", executor=executor)
# Use in MCP tool
result = await run_sandbox_command(
deps,
command=["df", "-h"],
args=[]
)
print(result.stdout)
With Pydantic-AI¶
from pydantic_ai import Agent
from shannot.tools import SandboxDeps, run_sandbox_command
# Create agent with sandbox tools
agent = Agent(
"openai:gpt-4",
deps_type=SandboxDeps,
system_prompt="You can execute read-only system commands."
)
# Register tool
@agent.tool
async def check_disk_usage(ctx) -> str:
result = await run_sandbox_command(
ctx.deps,
command=["df", "-h"],
args=[]
)
return result.stdout
# Run agent
deps = SandboxDeps(profile_name="diagnostics")
result = await agent.run("What's the disk usage?", deps=deps)
Remote Execution¶
from shannot.tools import SandboxDeps
from shannot.executors import SSHExecutor
# Configure SSH executor
executor = SSHExecutor(
host="prod.example.com",
username="readonly",
key_filename="/path/to/key"
)
# Create deps with remote executor
deps = SandboxDeps(
profile_name="diagnostics",
executor=executor
)
# Commands now execute on remote host
result = await run_sandbox_command(deps, command=["uptime"], args=[])
File Reading¶
from shannot.tools import read_sandbox_file
# Read a configuration file
result = await read_sandbox_file(
deps,
filepath="/etc/os-release"
)
print(result.content)
# With line limits for large files
result = await read_sandbox_file(
deps,
filepath="/var/log/syslog",
max_lines=100
)
Custom Profiles¶
from pathlib import Path
# Use custom profile path
deps = SandboxDeps(
profile_path=Path("/etc/shannot/custom.json"),
executor=executor
)
# Or specify profile name from standard locations
deps = SandboxDeps(
profile_name="minimal", # Loads ~/.config/shannot/minimal.json
executor=executor
)
Error Handling¶
The tools convert SandboxError exceptions to failed ProcessResult objects for compatibility with MCP and AI frameworks:
result = await run_sandbox_command(deps, command=["forbidden"], args=[])
if result.returncode != 0:
print(f"Command failed: {result.stderr}")
else:
print(f"Success: {result.stdout}")
Related Documentation¶
- MCP Server Module - MCP server implementation using these tools
- Execution Module - Underlying execution interface
- MCP Integration Guide - Setting up MCP servers with LLM clients
- Python API Guide - General API usage patterns
API Reference¶
tools
¶
Pydantic-AI tools for sandbox operations.
This module provides type-safe, reusable tools for interacting with the Shannot sandbox. These tools can be used standalone, in MCP servers, or with Pydantic-AI agents.
Classes¶
SandboxDeps
¶
Dependencies for sandbox tools.
Supports both legacy mode (with bubblewrap_path) and new executor mode.
Examples: Legacy mode (backward compatible): >>> deps = SandboxDeps(profile_name="minimal")
With LocalExecutor:
>>> from shannot.executors import LocalExecutor
>>> executor = LocalExecutor()
>>> deps = SandboxDeps(profile_name="minimal", executor=executor)
With SSHExecutor (for remote execution):
>>> from shannot.executors import SSHExecutor
>>> executor = SSHExecutor(host="prod.example.com")
>>> deps = SandboxDeps(profile_name="minimal", executor=executor)
Source code in shannot/tools.py
Functions¶
cleanup()
async
¶
Cleanup executor resources (e.g., SSH connections).
Should be called when done using the dependencies, especially when using SSHExecutor to ensure connections are closed.
Example: >>> deps = SandboxDeps(profile_name="minimal", executor=ssh_executor) >>> try: ... result = await run_command(deps, CommandInput(command=["ls", "/"])) ... finally: ... await deps.cleanup()
Source code in shannot/tools.py
CommandInput
¶
CommandOutput
¶
Bases: BaseModel
Output from sandbox command execution.
Source code in shannot/tools.py
FileReadInput
¶
DirectoryListInput
¶
Bases: BaseModel
Input for listing a directory.
Source code in shannot/tools.py
Functions¶
run_command(deps, input)
async
¶
Execute a command in the read-only sandbox.
The sandbox provides: - Read-only access to system files - Network isolation - Ephemeral /tmp (changes lost after command exits) - Command allowlisting (only approved commands run)
Use this for: - Inspecting files: cat, head, tail, grep - Listing directories: ls, find - Checking system status: df, free, ps
Args: deps: Sandbox dependencies (profile, manager) input: Command to execute
Returns: CommandOutput with stdout, stderr, returncode, duration, and success status
Source code in shannot/tools.py
read_file(deps, input)
async
¶
Read the contents of a file from the system.
Args: deps: Sandbox dependencies input: Path to file
Returns: File contents as string, or error message if failed
Source code in shannot/tools.py
list_directory(deps, input)
async
¶
List contents of a directory.
Args: deps: Sandbox dependencies input: Directory path and options
Returns: Directory listing as string, or error message if failed
Source code in shannot/tools.py
check_disk_usage(deps)
async
¶
Get disk usage information for all mounted filesystems.
Returns: Human-readable disk usage output (df -h), or error message if failed
Source code in shannot/tools.py
check_memory(deps)
async
¶
Get memory usage information.
Returns: Human-readable memory info (free -h), or error message if failed
Source code in shannot/tools.py
search_files(deps, pattern=Field(description='Filename pattern to search for'))
async
¶
Find files matching a pattern.
Args: deps: Sandbox dependencies pattern: Pattern to search for (e.g., "*.log")
Returns: List of matching file paths, or error message if failed
Source code in shannot/tools.py
grep_content(deps, pattern=Field(description='Text pattern to search for'), path=Field(description='File or directory to search in'), recursive=Field(default=False, description='Search recursively in directories'))
async
¶
Search for text pattern in files.
Args: deps: Sandbox dependencies pattern: Text pattern to search for path: File or directory to search recursive: Whether to search recursively
Returns: Matching lines, or error message if failed