Production-ready tool scripts for self-hosted AI agents.
Give any AI agent the ability to manage files, execute code, clone repos, schedule cron jobs, query databases, send messages — all from a single, self-hosted toolkit.
ServeKit is a curated collection of standalone Python tool scripts that provide infrastructure capabilities to AI agents. Each tool follows a simple contract: receive parameters via environment variables, return results as JSON on stdout.
No framework lock-in. No cloud dependency. No API keys required for core tools.
┌─────────────────────────────────────────────────┐
│ Your AI Agent (Claude, GPT, Cursor, etc.) │
└──────────────────────┬──────────────────────────┘
│ calls tools
┌──────────────────────▼──────────────────────────┐
│ Any tool server (MCP, REST, or direct call) │
└──────────────────────┬──────────────────────────┘
│ spawns subprocess
┌──────────────────────▼──────────────────────────┐
│ ServeKit tools/*.py │
│ ┌────┐ ┌──────────┐ ┌─────┐ ┌──────┐ ┌──────┐ │
│ │ fs │ │run-python│ │ git │ │ cron │ │ ... │ │
│ └────┘ └──────────┘ └─────┘ └──────┘ └──────┘ │
└─────────────────────────────────────────────────┘
git clone https://github.com/simontt88/servekit.git
cd servekit
# Try a tool directly — zero dependencies, just Python 3
SERVEKIT_PARAMS='{"action":"list","path":"."}' \
SERVEKIT_FS_ROOT=/tmp/sandbox \
SERVEKIT_USER_ID=demo \
python3 tools/fs.py
# Run the test suite
pip install pytest
python3 -m pytest tests/ -vEvery tool uses these environment variables. Set them before calling any tool.
| Variable | Required | Description |
|---|---|---|
SERVEKIT_PARAMS |
Yes | JSON string containing the tool's parameters (action, arguments, etc.) |
SERVEKIT_FS_ROOT |
Yes | Root directory for sandboxed file access. Each user's data lives under {FS_ROOT}/{USER_ID}/ |
SERVEKIT_USER_ID |
Yes | User identifier — tools use this for per-user isolation |
SERVEKIT_CREDENTIALS |
Only for adapters | JSON string containing secrets (SMTP, database, API keys, etc.) |
export SERVEKIT_FS_ROOT=/var/servekit/data
export SERVEKIT_USER_ID=alice
# Write a file
SERVEKIT_PARAMS='{"action":"write","path":"notes.txt","content":"hello world"}' \
python3 tools/fs.py
# → {"action":"write","path":"notes.txt","size":11}
# Read it back
SERVEKIT_PARAMS='{"action":"read","path":"notes.txt"}' \
python3 tools/fs.py
# → {"action":"read","path":"notes.txt","content":"hello world","size":11}When using adapters that connect to external services, pass secrets via SERVEKIT_CREDENTIALS:
# Example: send-email requires SMTP credentials
SERVEKIT_CREDENTIALS='{"host":"smtp.gmail.com","port":465,"user":"you@gmail.com","pass":"app-password","from_addr":"you@gmail.com"}' \
SERVEKIT_PARAMS='{"to":"friend@example.com","subject":"Hello","body":"Hi there"}' \
python3 tools/send-email.py| Adapter | Credential fields |
|---|---|
send-email |
host, port, user, pass, from_addr |
sql/postgres |
host, port, database, user, password |
storage/s3 |
endpoint, access_key_id, access_key_secret, bucket, region |
messaging/slack |
bot_token, default_channel |
messaging/lark |
app_id, app_secret |
These tools use only the Python standard library — no pip install needed.
| Tool | Description | Actions |
|---|---|---|
| fs | Sandboxed filesystem operations | read, write, list, delete |
| run-python | Execute Python code with stdout capture | Arbitrary code execution |
| git | Git repository operations (sandboxed per-user) | clone, pull, ls, read, log, diff, explore, search |
| cron | Cron job management + auto-start scheduler | add, remove, update, list, status, logs, health |
| tasks | Browse pipeline/cron task history | list, search, detail |
| data-serve | Pre-computed dataset API | catalog, get (batch), meta |
| send-email | Send email via SMTP | HTML and plain text support |
| pipeline | Async background Python tasks | submit, status, cancel |
Adapters connect to external services. Enable them by copying into tools/:
./scripts/enable-adapter.sh sql/postgres # PostgreSQL queries
./scripts/enable-adapter.sh storage/s3 # S3-compatible object storage
./scripts/enable-adapter.sh messaging/slack # Slack bot messages
./scripts/enable-adapter.sh messaging/lark # Lark/Feishu bot messages| Category | Adapter | Dependencies |
|---|---|---|
| SQL | sql/postgres |
psycopg2-binary |
| Storage | storage/s3 |
boto3 |
| Messaging | messaging/slack |
— (stdlib only) |
| Messaging | messaging/lark |
— (stdlib only) |
Create adapters/<category>/<name>/ with:
adapter.json— manifest (credentials, tools, config fragment)*.py— tool script(s)
See adapters/sql/postgres/ for a complete example.
ServeKit tools can be served through three paths:
Set environment variables and call tools directly. No server needed.
export SERVEKIT_FS_ROOT=./data
export SERVEKIT_USER_ID=default
# List files
SERVEKIT_PARAMS='{"action":"list","path":"."}' python3 tools/fs.py
# Execute Python
SERVEKIT_PARAMS='{"code":"import platform; print(platform.node())"}' python3 tools/run-python.py
# Clone a repo
SERVEKIT_PARAMS='{"action":"clone","repo":"https://github.com/user/repo.git"}' python3 tools/git.pyThis works from any Python script, CI pipeline, shell script, or automation. Here's a reusable wrapper:
import subprocess, json, os
def call_tool(tool_name, params, credentials=None, fs_root="./data", user_id="default"):
env = os.environ.copy()
env["SERVEKIT_PARAMS"] = json.dumps(params)
env["SERVEKIT_CREDENTIALS"] = json.dumps(credentials or {})
env["SERVEKIT_FS_ROOT"] = fs_root
env["SERVEKIT_USER_ID"] = user_id
r = subprocess.run(
["python3", f"tools/{tool_name}.py"],
capture_output=True, text=True, env=env, timeout=60,
)
return json.loads(r.stdout)
# Usage
result = call_tool("fs", {"action": "list", "path": "."})
print(result)The tool contract (env vars in, JSON stdout out) maps directly to MCP tool calls. Wrap ServeKit tools with any MCP SDK to expose them to AI agents:
from mcp.server import Server
import subprocess, json, os
app = Server("servekit")
@app.tool()
async def fs(action: str, path: str, content: str = None):
"""Sandboxed filesystem operations"""
params = {"action": action, "path": path}
if content:
params["content"] = content
env = os.environ.copy()
env["SERVEKIT_PARAMS"] = json.dumps(params)
env["SERVEKIT_FS_ROOT"] = "./data"
env["SERVEKIT_USER_ID"] = "default"
r = subprocess.run(
["python3", "tools/fs.py"],
capture_output=True, text=True, env=env, timeout=30,
)
return json.loads(r.stdout)vibeserve is a tool server that auto-discovers ServeKit tools, provides REST + MCP endpoints, authentication, sandboxing, and remote access via the Vibespace relay.
Note: vibeserve and the Vibespace platform are currently available to Advance Intelligence Group internal teams only. The tool server is not yet publicly released. If you're not part of the organization, use Path 1 or Path 2.
cp vibeserve.yaml.example vibeserve.yaml
cp .env.example .env
# Edit .env with your secrets, then:
vibeserve startThis gives you:
GET /tools— list available toolsPOST /tools/:name— execute a toolGET /mcp— MCP SSE transport for AI agents- Remote access via Vibespace WebSocket relay
Every tool follows the same interface:
Input (environment variables):
SERVEKIT_PARAMS JSON string — tool parameters
SERVEKIT_CREDENTIALS JSON string — secrets (optional, injected by server)
SERVEKIT_FS_ROOT String — sandbox root directory
SERVEKIT_USER_ID String — current user identifier
Output (stdout):
Single-line JSON object with the result
Errors:
{"error": "description of what went wrong"}
Each tool declares its schema via docstring annotations:
"""
@tool my-tool
@description What this tool does
@param name string required "Parameter description"
@param count number optional "With a default" default=10
@credentials my_service
@timeout 30
"""These annotations enable auto-discovery and schema generation by tool servers.
The built-in scheduler runs as a lightweight Python daemon:
python3 cron-scheduler.py & # start in background
python3 cron-scheduler.py --once # run due jobs once (for testing)Features:
- Standard 5-field cron expressions
- Per-job timeouts with health tracking
- Consecutive failure detection (healthy → degraded → failing)
- Task history recording in
data/tasks/ - Auto-start via the
crontool (firstaddlaunches the scheduler)
The data-serve tool serves JSON datasets from datasets/:
datasets/my-metrics/
├── latest.json ← current data (always served by default)
├── 20260528.json ← historical snapshots
└── 20260529.json
Write pipeline scripts in pipelines/, schedule them via cron, and serve the output through data-serve.
- Sandbox isolation:
fsandgittools enforce path boundaries — users cannot escape their sandbox directory - Path traversal protection: All file access is validated against the sandbox root via
os.path.realpath() - Credential separation: Secrets are injected via
SERVEKIT_CREDENTIALSand never exposed to callers - Per-user isolation: Each user gets their own data directory under
SERVEKIT_FS_ROOT/{user_id}/ - No network by default: Core tools make no outbound network calls (adapters do, with explicit credential requirements)
# Run all 70 tests
python3 -m pytest tests/ -v
# Run a specific tool's tests
python3 -m pytest tests/test_fs.py -v
python3 -m pytest tests/test_git.py -v
python3 -m pytest tests/test_cron.py -v| Suite | Tests | Coverage |
|---|---|---|
| test_fs | 13 | write, read, list, delete, path traversal defense |
| test_run_python | 9 | execution, errors, DATA_DIR injection |
| test_git | 12 | repos, ls, read, log, explore, search, security |
| test_cron | 10 | CRUD, cron expression parsing, schedule matching |
| test_tasks | 9 | list, search, detail, source filtering |
| test_data_serve | 7 | catalog, get, meta, snapshots, column filtering |
| test_pipeline | 6 | submit, status, cancel |
servekit/
├── tools/ # Core tool scripts (zero external deps)
│ ├── fs.py # Sandboxed filesystem
│ ├── run-python.py # Python code execution
│ ├── git.py # Git repository operations
│ ├── cron.py # Cron job management
│ ├── tasks.py # Task history browser
│ ├── data-serve.py # Dataset serving API
│ ├── send-email.py # SMTP email
│ └── pipeline.py # Async background tasks
│
├── adapters/ # Optional service connectors
│ ├── sql/postgres/ # PostgreSQL async queries
│ ├── storage/s3/ # S3/OSS object storage
│ ├── messaging/slack/ # Slack notifications
│ └── messaging/lark/ # Lark/Feishu notifications
│
├── cron-scheduler.py # Cron daemon (background process)
├── crons/ # Job definitions + logs (runtime)
├── datasets/ # Pre-computed data (runtime)
├── data/ # Sandbox root (runtime, per-user)
│
├── tests/ # 70 tests across 7 suites
├── scripts/
│ └── enable-adapter.sh # Copy adapter tools into tools/
│
├── AGENTS.md # Instructions for AI agents
├── vibeserve.yaml.example # vibeserve config template
├── .env.example # Environment variables template
└── requirements.txt # Python dependencies
- Fork the repository
- Create a feature branch (
git checkout -b feat/my-adapter) - Add your tool or adapter following the tool contract
- Write tests in
tests/ - Run
python3 -m pytest tests/ -v— all tests must pass - Submit a pull request
We especially welcome adapters for:
- Databases: MySQL, ClickHouse, BigQuery, SQLite
- Storage: GCS, Azure Blob, MinIO
- Messaging: Discord, Telegram, Microsoft Teams, Webhook
- Docs: Notion, Confluence, Google Docs
- Logs: Elasticsearch, Loki, Datadog
MIT