systems/mcp/tools/ directory for subdirectories that contain both a metadata.yaml and a script.ps1. There is no registration step — dropping the right files into the right folder is all that is needed. This same discovery mechanism applies to tools added by workflows and stacks installed in your project.
How tool discovery works
When the MCP server starts, it walks every subdirectory undersystems/mcp/tools/ (and under .bot/workflows/*/tools/ for workflow and stack tools). For each subdirectory that contains both metadata.yaml and script.ps1, the server:
- Reads the tool name and input schema from
metadata.yaml - Dot-sources
script.ps1to load theInvoke-*function into memory - Registers the tool with the MCP protocol handler
Directory structure
Each tool lives in its own folder undersystems/mcp/tools/. Use kebab-case for the folder name:
Naming conventions
The three files follow different case conventions that must be consistent with each other:| Location | Convention | Example |
|---|---|---|
| Folder name | kebab-case | send-notification |
name field in metadata.yaml | snake_case | send_notification |
Function name in script.ps1 | Invoke- + PascalCase | Invoke-SendNotification |
name field in metadata.yaml by capitalizing each underscore-separated segment and prepending Invoke-. If the naming is inconsistent, the tool will load but fail at call time with a function-not-found error.
The required files
metadata.yaml
Defines the tool’s name, description, and JSON Schema for its input parameters. The following is the realmetadata.yaml for the built-in task_create tool, which you can use as a reference for field structure:
required array. Parameters not in required are treated as optional.
script.ps1
Contains a single PowerShell function namedInvoke-YourToolName. The function receives a [hashtable]$Arguments parameter and returns a hashtable with the result data. The MCP server serializes the returned hashtable to JSON before sending it back to the AI tool.
The MCP server sets
$global:DotbotProjectRoot before loading tool scripts. Use this variable to build paths to .bot/workspace/, .bot/.control/, or any other project-relative location — do not hardcode paths.test.ps1
Tests the tool by sending a JSON-RPC request to a running MCP server process. Including a test file is optional but recommended, especially for tools that modify project state.Creating a custom tool
The following example creates a tool calledproject_summary that returns a count of tasks in each lifecycle state.
Write metadata.yaml
Create
systems/mcp/tools/project-summary/metadata.yaml with the snake_case tool name, a description, and the input schema. For a tool with no required inputs, use an empty properties object:Write script.ps1
Create
systems/mcp/tools/project-summary/script.ps1 with the Invoke-ProjectSummary function: