MCP Main Module¶
Entry point and CLI for the Shannot MCP server (v0.5.0).
Overview¶
The MCP main module provides the command-line interface for running the Shannot MCP server with PyPy sandbox integration. It handles argument parsing, profile loading, and server lifecycle management.
Key Components:
main()- Main entry point forshannot-mcpcommand- Argument parsing - Handle --profile and --verbose flags
- Server initialization - Create ShannotMCPServer with profiles
- Protocol serving - Start JSON-RPC 2.0 stdio transport
Command-Line Interface¶
Basic Usage¶
# Start MCP server with default profiles
shannot-mcp
# Enable verbose logging
shannot-mcp --verbose
# Load custom profile
shannot-mcp --profile ~/.config/shannot/custom.json
# Load multiple custom profiles
shannot-mcp --profile ~/profile1.json --profile ~/profile2.json
Command-Line Options¶
Usage: shannot-mcp [OPTIONS]
Options:
--profile PATH Custom profile path (can be specified multiple times)
--verbose Enable verbose logging (DEBUG level)
--help Show help message and exit
Entry Point¶
Console Script¶
Defined in pyproject.toml:
main() Function¶
def main() -> int:
"""Main entry point for shannot-mcp command."""
parser = argparse.ArgumentParser(
prog="shannot-mcp",
description="Shannot MCP server for LLM integration"
)
parser.add_argument(
"--profile",
action="append",
type=Path,
help="Custom profile path (can be specified multiple times)"
)
parser.add_argument(
"--verbose",
action="store_true",
help="Enable verbose logging"
)
args = parser.parse_args()
# Create server
server = ShannotMCPServer(
profile_paths=args.profile,
verbose=args.verbose
)
# Serve via stdio
serve(server.handle_request)
return 0
Usage Patterns¶
Default Profiles¶
Without --profile, server uses built-in profiles:
Loads:
- minimal (ls, cat, grep, find)
- readonly (minimal + head, tail, file, stat, wc, du)
- diagnostics (readonly + df, free, ps, uptime, hostname, uname, env, id)
Custom Profiles¶
Load custom profiles from filesystem:
# Single custom profile
shannot-mcp --profile ~/.config/shannot/custom.json
# Multiple profiles (stacked)
shannot-mcp --profile ~/minimal.json \
--profile ~/diagnostics.json
Profile Format (~/.config/shannot/custom.json):
Verbose Logging¶
Enable DEBUG-level logging for troubleshooting:
Output includes: - Profile loading details - PyPy runtime detection - Tool registration - Request/response JSON-RPC messages
Integration with LLM Clients¶
Claude Desktop¶
With verbose logging:
With custom profile:
{
"mcpServers": {
"shannot": {
"command": "shannot-mcp",
"args": ["--profile", "/path/to/custom.json"],
"env": {}
}
}
}
Claude Code¶
Via shannot mcp install:
Generates configuration for Claude Code's user or project scope.
Server Lifecycle¶
Startup Sequence¶
- Parse arguments - Handle --profile and --verbose flags
- Load profiles - From specified paths or use defaults
- Find runtime - Locate PyPy sandbox binary
- Create server - Initialize ShannotMCPServer
- Register tools - sandbox_run, session_result
- Register resources - profiles, status
- Start serving - JSON-RPC 2.0 over stdio (blocks)
Shutdown¶
- Server runs until EOF on stdin (client disconnect)
- Graceful shutdown on keyboard interrupt (Ctrl+C)
- Returns exit code 0 on success
Logging¶
Log Levels¶
Default (INFO): - Server initialization - Profile loading summary - Runtime detection status
Verbose (DEBUG): - Detailed profile loading - Runtime path discovery - Tool/resource registration - JSON-RPC request/response
Log Configuration¶
Logs to stderr (stdout reserved for JSON-RPC protocol).
Error Handling¶
Runtime Not Found¶
# Warning logged, server continues
logger.warning("PyPy runtime not found")
self.runtime = None
# Tools return error when called
{
"status": "error",
"error": "PyPy sandbox runtime not found. Run 'shannot setup' to install."
}
Profile Loading Failure¶
# Warning logged, profile skipped
logger.warning(f"Failed to load profile {path}: {e}")
# Server continues with remaining profiles
Invalid Arguments¶
$ shannot-mcp --invalid-flag
usage: shannot-mcp [-h] [--profile PROFILE] [--verbose]
shannot-mcp: error: unrecognized arguments: --invalid-flag
Testing¶
Manual Test¶
# Start server
shannot-mcp --verbose
# In another terminal, send JSON-RPC
echo '{"jsonrpc": "2.0", "method": "initialize", "params": {}, "id": 1}' | shannot-mcp
Integration Test¶
from shannot.mcp_main import main
import sys
# Mock argv
sys.argv = ["shannot-mcp", "--verbose"]
# Run main
exit_code = main()
assert exit_code == 0
Environment¶
No Environment Variables¶
Server does not use environment variables (intentional simplicity).
Working Directory¶
Server runs from current directory. Profile paths are resolved relative to CWD if not absolute.
Security¶
Stdio-Only Transport¶
- Server only accepts input from stdin
- Output only to stdout (protocol) and stderr (logs)
- No network sockets or file access
Profile Isolation¶
- Profiles loaded at startup
- No dynamic profile loading during runtime
- Profiles are immutable once loaded
Logging Safety¶
- Verbose mode logs to stderr (not protocol stdout)
- Sensitive data not logged (scripts may contain secrets)
Related Documentation¶
- MCP Server Module - Server implementation details
- MCP Integration Guide - Complete setup and usage
- MCP Testing - Testing procedures
API Reference¶
shannot.mcp_main¶
def main() -> int:
"""Main entry point for shannot-mcp command.
Returns
-------
int
Exit code (0 for success).
"""