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), andinputSchema(optional).
How It Works
- Client Lookup - Retrieves the MCP client using the provided Client ID
- List Request - Sends a ListToolsRequest to the MCP server
- Response Processing - Extracts tool information including names, descriptions, and JSON schemas
- Array Creation - Converts tools to an array of objects with metadata
- 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
-
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
-
Schema Analysis:
- Parse inputSchema to understand required parameters
- Extract enum values for constrained parameters
- Build UI or documentation from schemas
-
Error Handling:
- Check if tools array is not empty
- Handle servers with no tools gracefully
- Validate required tools are available
-
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
- Initial Discovery - Use at flow start to discover capabilities
- Validation - Validate tool names exist before Call Tool
- Schema Inspection - Parse schemas to understand parameters
- Documentation - Generate tool documentation automatically
- Dynamic Selection - Select tools based on context
- Caching - Store tool list to avoid repeated calls
- 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');
}