Skip to content

Tools

A tool capability represents an executable capability with a typed parameter contract. Unlike skills (which inject prose into agent context), tools can change files, call services, or run commands, and with that power comes stricter validation.

tuff.toml
id = "security-review"
version = "1.0.0"
type = "tool"
description = "Scan a directory for security vulnerabilities"
files = ["index.js"] # optional: entrypoint auto-included
[parameters]
type = "object"
required = ["target_dir"]
[parameters.properties.target_dir]
type = "string"
description = "Directory to scan"
[implementation]
language = "node"
entrypoint = "index.js"
mcp = true # only true for MCP-native tools
runtime_deps = ["chalk", "@octokit/rest"] # shown at install time, never auto-installed
FieldDescriptionRequired
idStable identifier for the toolYes
versionSemantic versionYes
typeMust be "tool"Yes
descriptionShown to the agent: what the tool does and when to call itYes
filesSource files to copy (entrypoint auto-added if present)No
parametersJSON Schema object defining input contractYes
parameters.typeMust be "object"Yes
parameters.propertiesAt least one parameter definition requiredYes
parameters.requiredArray of required parameter namesNo
implementationExecution configurationYes
implementation.languageRuntime language (node, python, bash, etc.)Yes
implementation.entrypointRelative path to the executable scriptYes
implementation.mcpSet to true only when the entrypoint is an MCP stdio serverNo
implementation.runtime_depsDependencies displayed at install timeNo

Every tool goes through these checks at tuff add time:

  1. Schema validation: parameters must be a valid JSON Schema with type: object and at least one property
  2. Entrypoint validation: entrypoint must resolve to an existing file, with no path traversal (../ or absolute paths rejected)
  3. Dependencies displayed: runtime_deps are shown in a note before install; they are never auto-installed
  4. MCP opt-in: only tools with implementation.mcp = true are registered as MCP servers
  5. No execution: installing a tool only writes files; the entrypoint is never run
Terminal window
# Local directory (type auto-detected from parent directory)
tuff add --agent claude ./my-tool
# Local file with explicit type (subcommand)
tuff add tool ./scripts/deploy.sh --agent open-agents
# Git repository
tuff add tool https://github.com/owner/repo security-review --agent claude
# Multiple agents
tuff add --agent claude --agent open-agents ./my-tool

The repository includes example tools under examples/tools/ that demonstrate common executable shapes:

ExampleWhat it demonstrates
local-binary-wrapperWraps approved local binaries such as git or rg
python-script-toolRuns a Python stdlib script with typed parameters
mcp-server-toolProvides a minimal stdio MCP server
http-api-toolCalls an HTTP endpoint with stdlib networking
repo-command-toolRuns an allowlisted repository command
docker-container-toolWraps an allowlisted Docker command

Install one into the configured default agent:

Terminal window
tuff add examples/tools/python-script-tool
tuff list --type tool

Tuff records the source, emitted files, and baseline for every tool. MCP registration is generated only for tools that set mcp = true.

TargetTool directoryMCP registration
open-agents.agents/tools/<id>/.agents/mcp.json
claude.claude/tools/<id>/.mcp.json

For MCP-native tools, set implementation.mcp = true. Tuff then writes a launch command pointing at the copied entrypoint and read-merges it into the harness’s native MCP config:

{
"mcpServers": {
"security-review": {
"command": "node",
"args": [".claude/tools/security-review/index.js"]
}
}
}

Command-style tools are copied and tracked but are not registered as MCP servers. Multiple MCP-native tools share a single mcpServers object. tuff delete cleans up both Tuff-generated tool directories and their MCP entries. tuff untrack preserves the tool directory and MCP entry while removing Tuff tracking.

Terminal window
# Show only tools
tuff list --type tool
# Show only skills
tuff list --type skill
# Combine with scope filter
tuff list --type tool --scope global