Ir al contenido

Herramientas personalizadas

Las herramientas personalizadas permiten ampliar el servidor MCP de Guida con funcionalidad específica del espacio de trabajo. Defina herramientas en tools.json y cualquier agente de IA conectado podrá invocarlas.

Cree un archivo tools.json en la raíz del espacio de trabajo:

{
"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"]
}
}
]
}
CampoRequeridoDescripción
nameNombre de herramienta expuesto mediante MCP; debe ser único
descriptionDescripción legible mostrada en las listas de herramientas
scriptRuta del script relativa a la raíz del espacio de trabajo
timeoutNoTiempo máximo de ejecución en segundos
parametersNoJSON Schema que describe los parámetros de entrada
headersNoCabeceras HTTP inyectadas en llamadas g.http.makeHttpRequest()

El campo parameters usa JSON Schema para describir las entradas de la herramienta. El agente de IA ve el esquema y proporciona argumentos compatibles.

Dentro del script, los parámetros están disponibles como 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);
}

El valor devuelto por main() se convierte en el resultado de la herramienta y se envía de vuelta al agente de IA.

Use plantillas {{SECRET_NAME}} en cabeceras para inyectar credenciales de acceso sin exponerlas a la IA:

{
"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}}"
}
}
]
}

Las cabeceras se resuelven en tiempo de ejecución usando credenciales almacenadas en el panel Secrets de Guida. El agente de IA nunca ve los valores de cabecera, solo el nombre de la herramienta y el esquema de parámetros.

Las cabeceras resueltas se inyectan automáticamente en cualquier llamada g.http.makeHttpRequest() dentro del script.

Cuando un agente de IA invoca una herramienta personalizada:

  1. Guida carga el script desde el espacio de trabajo
  2. Se procesa el pragma @timeout
  3. Los parámetros están disponibles como g.tool.args
  4. Las cabeceras se resuelven, reemplazando plantillas de credenciales por valores descifrados
  5. El script se ejecuta con ScriptTaskOrigin.Mcp, por lo que g.secrets.getSecret() está bloqueado
  6. El valor devuelto por main() se serializa y se envía al agente

Tres herramientas MCP integradas gestionan herramientas personalizadas:

HerramientaDescripción
GetWorkspaceToolsLista todas las herramientas personalizadas con sus esquemas de parámetros
ExecuteWorkspaceToolEjecuta una herramienta personalizada con parámetros
ReloadWorkspaceToolsRecarga tools.json después de cambios
{
"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 };
}
}