Aller au contenu

Outils personnalisés

Les outils personnalisés permettent d’étendre le serveur MCP de Guida avec des fonctions propres à l’espace de travail. Définissez les outils dans tools.json et tout agent IA connecté peut les invoquer.

Créez un fichier tools.json à la racine de votre espace de travail :

{
"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"]
}
}
]
}
ChampObligatoireDescription
nameOuiNom d’outil exposé via MCP, unique
descriptionOuiDescription lisible affichée dans les listes d’outils
scriptOuiChemin du script relatif à la racine de l’espace de travail
timeoutNonDélai d’exécution en secondes
parametersNonSchéma JSON décrivant les paramètres d’entrée
headersNonEn-têtes HTTP injectés dans les appels g.http.makeHttpRequest()

Le champ parameters utilise JSON Schema pour décrire les entrées de l’outil. L’agent IA voit le schéma et fournit des arguments correspondants.

Dans votre script, les paramètres sont disponibles via 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);
}

La valeur renvoyée par main() devient le résultat de l’outil, envoyé à l’agent IA.

En-têtes appuyés par des identifiants d’accès

Section intitulée « En-têtes appuyés par des identifiants d’accès »

Utilisez des modèles {{SECRET_NAME}} dans les en-têtes pour injecter des identifiants d’accès sans les exposer à l’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}}"
}
}
]
}

Les en-têtes sont résolus à l’exécution à partir des identifiants stockés dans le panneau Secrets de Guida. L’agent IA ne voit jamais les valeurs d’en-tête, seulement le nom de l’outil et son schéma de paramètres.

Les en-têtes résolus sont automatiquement injectés dans les appels g.http.makeHttpRequest() du script.

Lorsqu’un agent IA invoque un outil personnalisé :

  1. Guida charge le script depuis l’espace de travail.
  2. Le pragma @timeout est traité.
  3. Les paramètres sont disponibles via g.tool.args.
  4. Les en-têtes sont résolus, en remplaçant les modèles d’identifiants par les valeurs déchiffrées.
  5. Le script s’exécute avec ScriptTaskOrigin.Mcp, ce qui signifie que g.secrets.getSecret() est bloqué.
  6. La valeur renvoyée par main() est sérialisée et envoyée à l’agent.

Trois outils MCP intégrés gèrent les outils personnalisés :

OutilDescription
GetWorkspaceToolsListe tous les outils personnalisés avec leurs schémas de paramètres
ExecuteWorkspaceToolExécute un outil personnalisé avec des paramètres
ReloadWorkspaceToolsRecharge tools.json après modification
{
"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 };
}
}