Skip to content

Custom Tools

Custom tools let you extend Guida’s MCP server with workspace-specific functionality. Define tools in tools.json and any connected AI agent can invoke them.

Create a tools.json file in your workspace root:

{
"tools": [
{
"name": "search-products",
"description": "Search the product catalog by keyword",
"script": "scripts/search-products.js",
"timeout": 30,
"parameters": {
"type": "object",
"properties": {
"keyword": {
"type": "string",
"description": "Search keyword"
},
"maxResults": {
"type": "number",
"description": "Maximum results to return (default: 10)"
}
},
"required": ["keyword"]
}
}
]
}
FieldRequiredDescription
nameYesTool name exposed via MCP (must be unique)
descriptionYesHuman-readable description shown in tool listings
scriptYesPath to script relative to workspace root
timeoutNoExecution timeout in seconds
parametersNoJSON Schema describing input parameters
headersNoHTTP headers injected into g.http.makeHttpRequest() calls

The parameters field uses JSON Schema to describe the tool’s inputs. The AI agent sees the schema and provides matching arguments.

Inside your script, parameters are available as g.tool.args:

async function main() {
const keyword = g.tool.args.keyword;
const maxResults = g.tool.args.maxResults || 10;
await g.nav.navigateToUrl("https://store.example.com/search?q=" + keyword);
// ... extract results ...
return results.slice(0, maxResults);
}

The main() function’s return value becomes the tool’s result, sent back to the AI agent.

Use {{SECRET_NAME}} templates in headers to inject secrets without exposing them to the AI:

{
"tools": [
{
"name": "fetch-api-data",
"description": "Fetch data from the internal API",
"script": "scripts/api-fetch.js",
"headers": {
"Authorization": "Bearer {{API_TOKEN}}",
"X-Api-Key": "{{API_KEY}}"
}
}
]
}

Headers are resolved at execution time using secrets stored in Guida’s Secrets pane. The AI agent never sees the header values — only the tool name and parameter schema.

The resolved headers are automatically injected into any g.http.makeHttpRequest() calls within the script.

When an AI agent invokes a custom tool:

  1. Guida loads the script from the workspace
  2. The @timeout pragma is processed
  3. Parameters are available as g.tool.args
  4. Headers are resolved (secret templates replaced with decrypted values)
  5. The script runs with ScriptTaskOrigin.Mcp — meaning g.secrets.getSecret() is blocked
  6. The main() return value is serialized and sent back to the agent

Three built-in MCP tools manage custom tools:

ToolDescription
GetWorkspaceToolsList all custom tools with their parameter schemas
ExecuteWorkspaceToolExecute a custom tool with parameters
ReloadWorkspaceToolsReload tools.json after changes
{
"tools": [
{
"name": "create-ticket",
"description": "Create a support ticket in the ticketing system",
"script": "scripts/create-ticket.js",
"timeout": 15,
"headers": {
"Authorization": "Bearer {{TICKETING_API_KEY}}"
},
"parameters": {
"type": "object",
"properties": {
"title": { "type": "string", "description": "Ticket title" },
"body": { "type": "string", "description": "Ticket description" },
"priority": { "type": "string", "enum": ["low", "medium", "high"] }
},
"required": ["title", "body"]
}
}
]
}
scripts/create-ticket.js
async function main() {
try {
const response = await g.http.makeHttpRequest({
url: "https://api.ticketing.example.com/tickets",
method: "POST",
body: JSON.stringify({
title: g.tool.args.title,
body: g.tool.args.body,
priority: g.tool.args.priority || "medium"
}),
headers: { "Content-Type": "application/json" }
});
const ticket = JSON.parse(response.body);
return { ticketId: ticket.id, url: ticket.url };
} catch (e) {
return { error: e.message };
}
}
  • MCP Integration — understand the security model for MCP tools
  • Secrets — store API keys used in header templates
  • Workspaces — workspace folder structure and configuration