ClouisleClouisle

Tools API

Manage and execute tools

Endpoints

MethodPathPurpose
GET/api/v1/toolsList all tools
GET/api/v1/tools/filtersGet filter options (types, categories, statuses, teams, creators)
GET/api/v1/tools/legacy?team_id={team_id}Legacy team tool list (grouped by kind)
GET/api/v1/tools/builtinList every builtin tool
GET/api/v1/tools/file-parsers?team_id={team_id}List tools usable as file-upload parsers
GET/api/v1/tools/id/{tool_id}Get tool details by ID
GET/api/v1/tools/name/{tool_name}?team_id={team_id}Get tool details by name
POST/api/v1/tools/testTest a tool once (no standalone execute endpoint)
POST/api/v1/tools/execute-codeRun code directly in the sandbox
POST/api/v1/tools?team_id={team_id}Create a custom tool
PUT/api/v1/tools/{tool_id}Update tool configuration
DELETE/api/v1/tools/{tool_id}Delete a custom tool
POST/api/v1/tools/{tool_id}/toggleToggle a tool's enabled state
POST/api/v1/tools/{tool_id}/duplicateDuplicate a tool (the copy starts disabled)
GET/api/v1/tools/config?team_id={team_id}List tool configurations (credentials)
GET/api/v1/tools/config/{tool_name}?team_id={team_id}Get one tool configuration
POST/api/v1/tools/config?team_id={team_id}Create a tool configuration
PUT/api/v1/tools/config/{tool_name}?team_id={team_id}Update a tool configuration
DELETE/api/v1/tools/config/{tool_name}?team_id={team_id}Delete a tool configuration
POST/api/v1/tools/{tool_id}/shareShare a tool with another team
GET/api/v1/tools/{tool_id}/sharesList shares for a tool
DELETE/api/v1/tools/{tool_id}/share/{team_id}Revoke a team's share
GET/api/v1/tools/shared-with-me?team_id={team_id}List tools shared with a team
POST/api/v1/tools/mcp/list-toolsDiscover an MCP server's tool definitions
POST/api/v1/tools/database/test-connectionTest database connectivity

Authentication

All endpoints require an authenticated JWT user session. API-key authentication is not accepted by these management and execution routes.

Required permissions:

  • tool:read — View tools
  • tool:create — Create tools
  • tool:update — Update tools
  • tool:delete — Delete tools
  • tool:execute — Execute/test tools

List Tools

Get a list of all available tools, with pagination, search, and multi-dimensional filtering.

Query Parameters

ParameterTypeRequiredDefaultDescription
pageintegerNo1Page number
page_sizeintegerNo10Items per page (max: 100)
searchstringNo-Search by name or display name
typearrayNo-Filter by type: builtin, custom, mcp (repeatable)
categoryarrayNo-Filter by category (repeatable)
statusarrayNo-Filter by enabled status (repeatable)
team_idarrayNo-Filter by owning team (repeatable)
creatorarrayNo-Filter by creator (repeatable)

Request Example

curl -X GET "https://your-domain.com/api/v1/tools?category=search" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response

Success (200 OK):

{
  "code": 0,
  "data": {
    "items": [
      {
        "id": "tool-123",
        "name": "web_search",
        "display_name": "Web Search",
        "description": "Search the internet for information",
        "type": "builtin",
        "category": "search",
        "icon": "🔍",
        "parameters": [
          {
            "name": "query",
            "type": "string",
            "description": "Search query",
            "required": true
          },
          {
            "name": "max_results",
            "type": "integer",
            "description": "Maximum number of results",
            "required": false,
            "default": 5
          }
        ],
        "is_enabled": true,
        "requires_config": false,
        "config_fields": [],
        "custom_type": null,
        "http_config": null,
        "code_config": null,
        "mcp_config": null,
        "team_id": null,
        "created_by_id": null,
        "created_by_name": null,
        "is_owned": true,
        "owner_team_id": null,
        "owner_team_name": null,
        "share_permission": null,
        "shared_with_count": 0
      }
    ],
    "total": 15,
    "page": 1,
    "page_size": 10
  },
  "msg": "success"
}

Tool Filter Options

GET /api/v1/tools/filters

Requires tool:read. Returns the filter options for the tools the caller can access, for building list-page filters.

{
  "code": 0,
  "data": {
    "types": [
      { "value": "builtin", "label": "builtin" },
      { "value": "custom", "label": "custom" },
      { "value": "mcp", "label": "mcp" }
    ],
    "categories": [{ "value": "search", "label": "search" }],
    "statuses": [
      { "value": "enabled", "label": "enabled" },
      { "value": "disabled", "label": "disabled" }
    ],
    "teams": [{ "value": "team-123", "label": "Engineering" }],
    "creators": [{ "value": "alice", "label": "alice" }]
  },
  "msg": "success"
}

categories is every defined tool category combined with any custom category present on accessible tools; teams lists teams the user can access; creators lists the distinct creator names of accessible tools.

List Legacy Team Tools

GET /api/v1/tools/legacy?team_id={team_id}

Legacy compatibility endpoint returning a team's tools grouped by kind (builtin / custom / mcp). New integrations should prefer List Tools.

ParameterTypeRequiredDefaultDescription
team_idstringYes-Team UUID
include_sharedbooleanNotrueInclude tools shared with the team by other teams

builtin always contains the full builtin tool list; custom and mcp contain the team's own tools (excluding other members' private tools) and, when include_shared=true, tools shared into the team.

List Builtin Tools

GET /api/v1/tools/builtin

Returns every builtin tool (including the sandbox tools artifact, bash, edit, read, write). Builtin tools have no database record, so their objects have id: null and custom_type: null.

List File Parsers

GET /api/v1/tools/file-parsers?team_id={team_id}

Returns the tools usable as document parsers for file uploads: builtin parsers (such as markitdown) plus the team's enabled custom tools with category=file. Requires tool:read and team membership.

Get Tool Details

Supports querying by tool ID or name. Name query requires an additional team_id parameter.

Path Parameters

ParameterTypeRequiredDescription
tool_idstringYesTool UUID (for GET /id/{tool_id})
tool_namestringYesTool name (for GET /name/{tool_name})

Request Example

curl -X GET "https://your-domain.com/api/v1/tools/id/tool-123" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response

Success (200 OK):

{
  "code": 0,
  "data": {
    "id": "tool-123",
    "name": "web_search",
    "display_name": "Web Search",
    "description": "Search the internet for information",
    "type": "builtin",
    "category": "search",
    "icon": "🔍",
    "parameters": [...],
    "is_enabled": true,
    "requires_config": false,
    "config_fields": [],
    "custom_type": null,
    "http_config": null,
    "code_config": null,
    "mcp_config": null,
    "team_id": null,
    "created_by_id": null,
    "created_by_name": null,
    "is_owned": true,
    "owner_team_id": null,
    "owner_team_name": null,
    "share_permission": null,
    "shared_with_count": 0,
    "created_at": null,
    "updated_at": null
  },
  "msg": "success"
}

Test Tool

Execute a tool once by name with arguments. Note: There is no standalone POST /tools/{tool_id}/execute endpoint; use this unified interface instead.

Request Body

{
  "name": "web_search",
  "arguments": {
    "query": "artificial intelligence",
    "max_results": 5
  }
}

Request Fields

FieldTypeRequiredDescription
namestringYesTool name
argumentsobjectNoTool arguments

Request Example

curl -X POST "https://your-domain.com/api/v1/tools/test" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "web_search",
    "arguments": {
      "query": "artificial intelligence",
      "max_results": 5
    }
  }'

Response

Success (200 OK):

{
  "code": 0,
  "data": {
    "name": "web_search",
    "success": true,
    "result": {
      "results": [
        {
          "title": "Artificial Intelligence - Wikipedia",
          "url": "https://en.wikipedia.org/wiki/Artificial_intelligence",
          "snippet": "Artificial intelligence (AI) is intelligence demonstrated by machines..."
        }
      ]
    },
    "error": null,
    "logs": null,
    "artifacts": [],
    "duration_ms": 1200
  },
  "msg": "success"
}

Error (400 Bad Request):

{
  "code": 1001,
  "data": {
    "field": "arguments.query",
    "error": "Query is required"
  },
  "msg": "Validation failed"
}

Execute Code

Run JavaScript/Python code directly in the sandbox without saving a tool.

Request Body

{
  "language": "python",
  "code": "print(1 + 1)",
  "params": {},
  "timeout": 30,
  "python_packages": ["requests"]
}

Request Fields

FieldTypeRequiredDescription
languagestringYesCode language: javascript, python
codestringYesCode content
paramsobjectNoInput parameters
timeoutnumberNoTimeout in seconds (1-60, default: 30)
commandarrayNoCustom command (argv array)
python_packagesarrayNoPython packages to install
js_packagesarrayNoJavaScript packages to install
python_package_index_urlstringNoPython package mirror URL
node_package_registry_urlstringNoJavaScript package registry URL
artifactsarrayNoSandbox artifact configuration
limitsobjectNoResource limits (timeout_seconds, disk_mb, max_stdout_kb, max_stderr_kb)

Request Example

curl -X POST "https://your-domain.com/api/v1/tools/execute-code" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "language": "python",
    "code": "print(1 + 1)"
  }'

Response

Success (200 OK):

{
  "code": 0,
  "data": {
    "success": true,
    "result": "2\n",
    "error": null,
    "logs": null,
    "artifacts": [],
    "duration_ms": 350
  },
  "msg": "success"
}

Create Custom Tool

Create a custom tool. team_id is a required query parameter.

Query Parameters

ParameterTypeRequiredDescription
team_idstringYesTeam UUID that owns the tool

Request Body

{
  "name": "crm_lookup",
  "display_name": "CRM Lookup",
  "description": "Look up customer information in CRM",
  "category": "data",
  "type": "custom",
  "custom_type": "http",
  "icon": "👤",
  "parameters": [
    {
      "name": "customer_id",
      "type": "string",
      "required": true,
      "description": "Customer ID to lookup"
    }
  ],
  "http_config": {
    "method": "GET",
    "url": "https://api.crm.example.com/customers/{customer_id}",
    "headers": {
      "X-API-Key": "crm_..."
    },
    "timeout": 30
  },
  "credentials": {},
  "is_enabled": true
}

Request Fields

FieldTypeRequiredDescription
namestringYesTool name (unique identifier, max 100 chars)
display_namestringYesDisplay name (max 100 chars)
descriptionstringNoTool description
iconstringNoIcon (emoji or URL, max 100 chars)
categorystringNoTool category (default: other)
typestringNoTool type: builtin, custom, mcp (default: custom)
custom_typestringNoCustom tool type: http, code, database (only for type=custom)
visibilitystringNoTool visibility: private or team (default: private)
parametersarrayNoParameter definitions (name, type, description, required, enum, default)
http_configobjectNoHTTP config (method, url, headers, query_params, body_template, content_type, form_fields, timeout, response_path)
code_configobjectNoCode config (language, code, command, python_packages, js_packages, python_package_index_url, node_package_registry_url, artifacts, limits)
database_configobjectNoDatabase config (db_type, host, port, database, username, password, ssl, url, db, auth_source, timeout, max_limit)
mcp_configobjectNoMCP Server config (transport, command, args, env, url, headers)
credentialsobjectNoTool credentials
is_enabledbooleanNoEnabled status (default: true)

name must match ^[a-zA-Z][a-zA-Z0-9_]*$ (starts with a letter, letters/digits/underscores only), otherwise 1001 tool_name_invalid_format; a duplicate name within the team returns 5001 tool_name_exists.

Request Example

curl -X POST "https://your-domain.com/api/v1/tools?team_id=team-123" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "crm_lookup",
    "display_name": "CRM Lookup",
    "description": "Look up customer information in CRM",
    "category": "data",
    "type": "custom",
    "custom_type": "http",
    "parameters": [
      {
        "name": "customer_id",
        "type": "string",
        "required": true
      }
    ],
    "http_config": {
      "method": "GET",
      "url": "https://api.crm.example.com/customers/{customer_id}"
    }
  }'

Response

Success (200 OK):

{
  "code": 0,
  "data": {
    "id": "tool-789",
    "name": "crm_lookup",
    "display_name": "CRM Lookup",
    "description": "Look up customer information in CRM",
    "type": "custom",
    "category": "data",
    "custom_type": "http",
    "is_enabled": true,
    "team_id": "team-123",
    "created_at": "2026-02-11T16:00:00Z",
    "updated_at": "2026-02-11T16:00:00Z",
    "created_by_name": "alice"
  },
  "msg": "Tool created successfully"
}

Update Tool

Update tool configuration. All fields are optional; include only the fields you want to update.

Path Parameters

ParameterTypeRequiredDescription
tool_idstringYesTool UUID

Request Body

{
  "display_name": "CRM Lookup (Updated)",
  "is_enabled": true,
  "http_config": {
    "timeout": 60
  }
}

Request Example

curl -X PUT "https://your-domain.com/api/v1/tools/tool-789" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "CRM Lookup (Updated)",
    "is_enabled": true
  }'

Response

Success (200 OK):

{
  "code": 0,
  "data": {
    "id": "tool-789",
    "name": "crm_lookup",
    "display_name": "CRM Lookup (Updated)",
    "type": "custom",
    "is_enabled": true,
    "team_id": "team-123",
    "created_at": "2026-02-11T16:00:00Z",
    "updated_at": "2026-02-11T16:05:00Z",
    "created_by_name": "alice"
  },
  "msg": "Tool updated successfully"
}

Delete Tool

Delete a custom tool.

Path Parameters

ParameterTypeRequiredDescription
tool_idstringYesTool UUID

Request Example

curl -X DELETE "https://your-domain.com/api/v1/tools/tool-789" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response

Success (200 OK):

{
  "code": 0,
  "data": null,
  "msg": "Tool deleted successfully"
}

Toggle Tool

POST /api/v1/tools/{tool_id}/toggle

Flips a tool's enabled state. There is no request body. Only database-backed tools (custom, mcp) can be toggled; builtin tools are always enabled. The caller must be the tool creator or a team admin and hold tool:update.

curl -X POST "https://your-domain.com/api/v1/tools/tool-789/toggle" \
  -H "Authorization: Bearer YOUR_TOKEN"

Success (200 OK): returns the updated ToolDetailOut with is_enabled flipped and msg set to "Tool updated successfully".

Duplicate Tool

POST /api/v1/tools/{tool_id}/duplicate

Copies a tool within its owning team. Requires tool:create and the admin role in the tool's team.

curl -X POST "https://your-domain.com/api/v1/tools/tool-789/duplicate" \
  -H "Authorization: Bearer YOUR_TOKEN"

Copy rules:

  • Visibility is always private and is_enabled is always false (enable it manually after copying).
  • The name gets a _copy suffix, falling back to _copy_1, _copy_2, … until unique.
  • The display name gets a (Copy) suffix.
  • code_config, database_config, mcp_config, and credentials are copied.

Duplication copies credentials, so the copy inherits the original tool's secrets. Rotate or delete unneeded credentials after copying.

Cross-Team Tool Sharing

Share custom or MCP tools with other teams within the workspace. Sharing requires admin or owner role in the tool's owner team; a tool cannot be shared with its own team.

Share Tool

POST /api/v1/tools/{tool_id}/share
FieldTypeRequiredDescription
team_idstringYesTarget team UUID
permissionstringNoread_only (view and use) or read_execute (view, use, and see execution results), default read_only
curl -X POST "https://your-domain.com/api/v1/tools/tool-789/share" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"team_id": "team-456", "permission": "read_execute"}'

Returns the created share record with id, tool_id, tool_name, tool_display_name, shared_with_team_id, shared_with_team_name, permission, shared_by_id, shared_by_name, and shared_at.

List Shares for a Tool

GET /api/v1/tools/{tool_id}/shares

Returns { "shares": [...], "total": N }. Accessible only to members of the tool's owner team.

List Tools Shared With a Team

GET /api/v1/tools/shared-with-me?team_id={team_id}

team_id is a required query parameter. Items in the list return is_owned: false, owner_team_id, owner_team_name, and share_permission.

Revoke Share

DELETE /api/v1/tools/{tool_id}/share/{team_id}

Tool Configuration (Credentials)

Tool configurations store credentials (API keys, tokens) for builtin or database tools, either globally (superusers only) or per team.

GET    /api/v1/tools/config?team_id={team_id}
GET    /api/v1/tools/config/{tool_name}?team_id={team_id}
POST   /api/v1/tools/config?team_id={team_id}
PUT    /api/v1/tools/config/{tool_name}?team_id={team_id}
DELETE /api/v1/tools/config/{tool_name}?team_id={team_id}
ParameterLocationRequiredDescription
team_idQueryNoTeam UUID; omit to operate on the global configuration (superusers only)
tool_namePathYes (get/put/delete)Tool name, e.g. web_search

Create body:

{
  "tool_name": "web_search",
  "credentials": {
    "TAVILY_API_KEY": "tvly-..."
  }
}

Update body contains only credentials:

{
  "credentials": {
    "TAVILY_API_KEY": "tvly-updated"
  }
}

Permissions and behavior:

  • With team_id, create/update/delete require the team admin role and reads require team membership.
  • Without team_id, both reads and writes are limited to superusers.
  • Reading a team configuration for a known builtin tool name that has no record yet creates an empty configuration automatically; an unknown name returns 404.
  • Deleting returns data: null.

MCP & Database Tool Diagnostics

Discover MCP Server Tools

POST /api/v1/tools/mcp/list-tools

Connect to an MCP server dynamically to inspect its declared tools before creating a tool record.

{
  "mcp_config": {
    "transport": "sse",
    "command": null,
    "args": [],
    "env": {},
    "url": "https://mcp.internal.example.com/sse",
    "headers": {}
  }
}

mcp_config.transport accepts stdio, sse, and http: stdio uses command, args, and env; sse/http use url and headers.

The response returns tools (each with name, description, and input parameter schema), server_name, and server_version.

This endpoint initiates a real network request or process launch. Target URLs are subject to the deployment outbound network allowlist.

Test Database Tool Connection

POST /api/v1/tools/database/test-connection
{
  "db_type": "postgresql",
  "host": "db.example.com",
  "port": 5432,
  "database": "analytics",
  "username": "readonly",
  "password": "secret_password",
  "ssl": true,
  "timeout": 15,
  "max_limit": 100
}
FieldTypeRequiredDescription
db_typestringYespostgresql, mysql, redis, mongodb
hoststringNoHostname or IP
portintegerNoPort
databasestringNoDatabase name
usernamestringNoUsername
passwordstringNoPassword
sslstring | booleanNoSSL mode
urlstringNoConnection URL for Redis or MongoDB (replaces host/port)
dbintegerNoRedis database index
auth_sourcestringNoMongoDB authentication source
timeoutintegerNoQuery timeout in seconds (1–120, default 15)
max_limitintegerNoMaximum rows returned (1–1000, default 100)

Returns 400 with msg set to the failure reason (such as database_connection_failed) when connection testing fails.

Error Codes

CodeMessageDescription
4000Not foundTool does not exist
4004Team not foundTarget team does not exist
3000Permission deniedInsufficient permissions (sharing requires team admin)
3003Team admin requiredAdmin role required in the tool owner team
5001Already existsA tool with the same name already exists in the team
5104Duplicate nameThe tool is already shared with that team, or the tool configuration already exists
1001Validation failedInvalid request data (including an invalid tool-name format)
1002Bad requestSharing to the tool's own team or failed connection test

Note: No per-endpoint rate limits are implemented. There is no rate-limit middleware on these endpoints. Codes 6300-6306 are reserved for SSO errors and are not used by the Tools API.

Code Examples

Python

import requests

def list_tools(token):
    """List all available tools."""
    url = "https://your-domain.com/api/v1/tools"
    headers = {
        "Authorization": f"Bearer {token}"
    }

    response = requests.get(url, headers=headers)
    result = response.json()

    if result['code'] == 0:
        return result['data']['items']
    else:
        raise Exception(f"Error: {result['msg']}")

def test_tool(token, name, arguments):
    """Execute a tool once."""
    url = "https://your-domain.com/api/v1/tools/test"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    data = {
        "name": name,
        "arguments": arguments
    }

    response = requests.post(url, headers=headers, json=data)
    result = response.json()

    if result['code'] == 0:
        return result['data']['result']
    else:
        raise Exception(f"Error: {result['msg']}")

# Usage
tools = list_tools("YOUR_TOKEN")
for tool in tools:
    print(f"Tool: {tool['display_name']} ({tool['category']})")

# Execute web search
result = test_tool(
    "YOUR_TOKEN",
    "web_search",
    {"query": "artificial intelligence", "max_results": 5}
)
print(f"Search results: {result['results']}")

JavaScript

async function listTools(token) {
  const response = await fetch(
    'https://your-domain.com/api/v1/tools',
    {
      headers: {
        'Authorization': `Bearer ${token}`,
      },
    }
  );

  const result = await response.json();

  if (result.code === 0) {
    return result.data.items;
  } else {
    throw new Error(result.msg);
  }
}

async function testTool(token, name, arguments) {
  const response = await fetch(
    'https://your-domain.com/api/v1/tools/test',
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        name: name,
        arguments: arguments,
      }),
    }
  );

  const result = await response.json();

  if (result.code === 0) {
    return result.data.result;
  } else {
    throw new Error(result.msg);
  }
}

// Usage
const tools = await listTools('YOUR_TOKEN');
tools.forEach(tool => {
  console.log(`Tool: ${tool.display_name} (${tool.category})`);
});

// Execute web search
const result = await testTool(
  'YOUR_TOKEN',
  'web_search',
  { query: 'artificial intelligence', max_results: 5 }
);
console.log('Search results:', result.results);

How is this guide?

On this page