Skip to main content

List Tools

Discovers all available tools on an MCP server. This node returns a list of tools with their names, descriptions, and input schemas, enabling dynamic tool discovery and validation.

Common Properties

  • Name - The custom name of the node.
  • Color - The custom color of the node.
  • Delay Before (sec) - Waits in seconds before executing the node.
  • Delay After (sec) - Waits in seconds after executing node.
  • Continue On Error - Automation will continue regardless of any error. The default value is false.

Inputs

  • Client Id - The MCP client connection identifier from the Connect node.

Options

  • Timeout - Timeout in seconds for the operation (default: 30).

Outputs

  • Tools - Array of tool objects, each containing name, description (optional), and inputSchema (optional).

How It Works

  1. Client Lookup - Retrieves the MCP client using the provided Client ID
  2. List Request - Sends a ListToolsRequest to the MCP server
  3. Response Processing - Extracts tool information including names, descriptions, and JSON schemas
  4. Array Creation - Converts tools to an array of objects with metadata
  5. Output - Returns the tools array

Output Format

Each tool in the array contains:

{
"name": "tool_name",
"description": "What the tool does",
"inputSchema": {
"type": "object",
"properties": {
"param": {
"type": "string",
"description": "Parameter description"
}
},
"required": ["param"]
}
}

The description and inputSchema fields are optional but usually present.

Examples

Example 1: List All Tools

Inputs:

  • Client Id: tool-server

Tools Output:

[
{
"name": "get_weather",
"description": "Get current weather for a location",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City and country"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
},
{
"name": "send_email",
"description": "Send an email message",
"inputSchema": {
"type": "object",
"properties": {
"to": {"type": "string"},
"subject": {"type": "string"},
"body": {"type": "string"}
},
"required": ["to", "subject", "body"]
}
}
]

Example 2: Extract Tool Names

JavaScript processing:

const tools = msg.tools;

// Get all tool names
msg.tool_names = tools.map(t => t.name);
// ["get_weather", "send_email", "query_database"]

// Find tools with no required parameters
msg.optional_param_tools = tools.filter(t => {
const schema = t.inputSchema;
return !schema || !schema.required || schema.required.length === 0;
});

Example 3: Validate Tool Availability

Flow:

List Tools → Check required tools → Proceed or Error

JavaScript:

const requiredTools = ['get_weather', 'send_email'];
const availableTools = msg.tools.map(t => t.name);

const missing = requiredTools.filter(t => !availableTools.includes(t));

if (missing.length > 0) {
throw new Error(`Missing required tools: ${missing.join(', ')}`);
}

Example 4: Build Tool Documentation

Flow:

List Tools → Generate docs → Store or display

JavaScript:

const docs = msg.tools.map(tool => {
const params = tool.inputSchema?.properties || {};
const required = tool.inputSchema?.required || [];

return {
name: tool.name,
description: tool.description,
parameters: Object.entries(params).map(([name, schema]) => ({
name,
type: schema.type,
description: schema.description,
required: required.includes(name),
enum: schema.enum || null
}))
};
});

msg.tool_documentation = docs;

Example 5: Analyze Tool Capabilities

JavaScript:

const tools = msg.tools;

// Count tools by capability
const analysis = {
total: tools.length,
with_descriptions: tools.filter(t => t.description).length,
with_schemas: tools.filter(t => t.inputSchema).length,
no_params: tools.filter(t => {
const props = t.inputSchema?.properties;
return !props || Object.keys(props).length === 0;
}).length
};

msg.tool_analysis = analysis;

Best Practices

  1. Discovery:

    • List tools at the start to understand server capabilities
    • Cache the list if tools don't change frequently
    • Use to validate tool names before Call Tool
  2. Schema Analysis:

    • Parse inputSchema to understand required parameters
    • Extract enum values for constrained parameters
    • Build UI or documentation from schemas
  3. Error Handling:

    • Check if tools array is not empty
    • Handle servers with no tools gracefully
    • Validate required tools are available
  4. Performance:

    • Cache tool lists to reduce server calls
    • Only refresh when needed
    • Use for initialization, not every iteration

Common Errors and Solutions

Error: "Client Id cannot be empty"

Solution:

  • Ensure Connect node executed successfully
  • Pass Client Id from Connect node
  • Verify client connection is active

Error: "Failed to list tools"

Solution:

  • Check server is running and accessible
  • Verify Client Id is correct
  • Check server logs for errors
  • Ensure server has ListTools capability enabled

Empty Tools Array

Cause: Server has no tools registered.

Solution:

  • Verify server has tools configured
  • Check server is properly initialized
  • Ensure tools are registered correctly on server

Tips for Effective Use

  1. Initial Discovery - Use at flow start to discover capabilities
  2. Validation - Validate tool names exist before Call Tool
  3. Schema Inspection - Parse schemas to understand parameters
  4. Documentation - Generate tool documentation automatically
  5. Dynamic Selection - Select tools based on context
  6. Caching - Store tool list to avoid repeated calls
  7. Requirement Checking - Validate required tools are available

Integration Patterns

Pattern 1: Tool Discovery and Usage

Connect → List Tools → Select Tool → Call Tool → Use Result

Pattern 2: Validation Before Call

List Tools → Check if exists → Call Tool
↓ (if not exists)
Error Handler

Pattern 3: Build Catalog

List Tools → Format → Store in Database → Display to Users

Pattern 4: Dynamic Tool Selection

List Tools → Filter by criteria → Select best match → Call Tool

Processing Examples

Extract Tool Names Only

const toolNames = msg.tools.map(t => t.name);
// ["get_weather", "send_email", "query_database"]

Find Tools by Name Pattern

const emailTools = msg.tools.filter(t =>
t.name.includes('email') || t.description?.toLowerCase().includes('email')
);

Extract Required Parameters

msg.tools.forEach(tool => {
tool.requiredParams = tool.inputSchema?.required || [];
tool.optionalParams = Object.keys(tool.inputSchema?.properties || {})
.filter(p => !tool.requiredParams.includes(p));
});

Create Tool Lookup Map

const toolMap = {};
msg.tools.forEach(t => {
toolMap[t.name] = {
description: t.description,
schema: t.inputSchema
};
});
msg.tool_lookup = toolMap;

Group Tools by Category

const categorized = {
communication: [],
data: [],
utility: [],
other: []
};

msg.tools.forEach(tool => {
const name = tool.name.toLowerCase();
if (name.includes('email') || name.includes('send')) {
categorized.communication.push(tool);
} else if (name.includes('query') || name.includes('database')) {
categorized.data.push(tool);
} else if (name.includes('get') || name.includes('search')) {
categorized.utility.push(tool);
} else {
categorized.other.push(tool);
}
});

msg.tools_by_category = categorized;

Validate Schema Complexity

msg.tools.forEach(tool => {
const schema = tool.inputSchema;
if (!schema) {
tool.complexity = 'none';
} else {
const paramCount = Object.keys(schema.properties || {}).length;
const requiredCount = schema.required?.length || 0;

if (paramCount === 0) {
tool.complexity = 'none';
} else if (paramCount <= 2 && requiredCount <= 1) {
tool.complexity = 'simple';
} else if (paramCount <= 5) {
tool.complexity = 'moderate';
} else {
tool.complexity = 'complex';
}
}
});

Check Tool Exists

function hasToolfunction hasTool(toolName) {
return msg.tools.some(t => t.name === toolName);
}

if (!hasTool('get_weather')) {
throw new Error('Weather tool not available');
}