UNPKG

node-red-contrib-mcp-server

Version:

A comprehensive Node-RED wrapper for Model Context Protocol (MCP) servers providing standardized AI agent tool interfaces, server lifecycle management, real-time communication capabilities, and visual MCP server creation

359 lines (317 loc) 16.1 kB
<!-- MCP Tool Registry Node --> <script type="text/javascript"> RED.nodes.registerType('mcp-tool-registry', { category: 'mcp', color: '#E91E63', defaults: { name: {value: ""}, toolName: {value: "", required: true}, toolDescription: {value: ""}, toolSchema: {value: '{\n "type": "object",\n "properties": {},\n "required": []\n}'}, autoRegister: {value: true} }, inputs: 1, outputs: 1, icon: "font-awesome/fa-plus", label: function() { return this.name || this.toolName || "Tool Registry"; }, labelStyle: function() { return this.name ? "node_label_italic" : ""; }, oneditprepare: function() { var node = this; // Common tool schema templates var schemaTemplates = { "simple": { name: "Simple Parameters", schema: '{\n "type": "object",\n "properties": {\n "input": {\n "type": "string",\n "description": "Input parameter"\n }\n },\n "required": ["input"]\n}' }, "todo": { name: "Todo Tool", schema: '{\n "type": "object",\n "properties": {\n "description": {\n "type": "string",\n "description": "Todo description"\n },\n "project": {\n "type": "string",\n "description": "Project name"\n },\n "priority": {\n "type": "string",\n "enum": ["Low", "Medium", "High"],\n "description": "Priority level"\n }\n },\n "required": ["description"]\n}' }, "calculator": { name: "Calculator Tool", schema: '{\n "type": "object",\n "properties": {\n "operation": {\n "type": "string",\n "enum": ["add", "subtract", "multiply", "divide"],\n "description": "Mathematical operation"\n },\n "a": {\n "type": "number",\n "description": "First number"\n },\n "b": {\n "type": "number",\n "description": "Second number"\n }\n },\n "required": ["operation", "a", "b"]\n}' }, "api": { name: "API Call Tool", schema: '{\n "type": "object",\n "properties": {\n "url": {\n "type": "string",\n "description": "API endpoint URL"\n },\n "method": {\n "type": "string",\n "enum": ["GET", "POST", "PUT", "DELETE"],\n "description": "HTTP method"\n },\n "data": {\n "type": "object",\n "description": "Request payload"\n }\n },\n "required": ["url"]\n}' } }; // Populate schema templates dropdown var templateSelect = $("#schema-templates"); Object.keys(schemaTemplates).forEach(function(key) { var template = schemaTemplates[key]; var option = $('<option></option>') .attr('value', key) .text(template.name); templateSelect.append(option); }); // Load schema template $("#load-template-btn").click(function() { var selectedTemplate = $("#schema-templates").val(); if (selectedTemplate && schemaTemplates[selectedTemplate]) { $("#node-input-toolSchema").val(schemaTemplates[selectedTemplate].schema); RED.notify(`Loaded ${schemaTemplates[selectedTemplate].name} template`, "success"); } }); // Auto-generate tool name from display name $("#node-input-name").on('input', function() { var name = $(this).val(); if (name && !$("#node-input-toolName").val()) { var toolName = name.toLowerCase() .replace(/[^a-z0-9\s]/g, '') .replace(/\s+/g, '_') + '_tool'; $("#node-input-toolName").val(toolName); } }); // Validate JSON schema $("#node-input-toolSchema").on('blur', function() { var schema = $(this).val(); try { var parsed = JSON.parse(schema); $(this).removeClass("input-error"); $("#schema-validation").hide(); // Basic schema validation if (!parsed.type || !parsed.properties) { $("#schema-validation").show() .css('color', '#f39c12') .text("Warning: Schema should have 'type' and 'properties' fields"); } } catch (error) { $(this).addClass("input-error"); $("#schema-validation").show() .css('color', '#e74c3c') .text("Invalid JSON: " + error.message); } }); // Format JSON button $("#format-schema-btn").click(function() { var schema = $("#node-input-toolSchema").val(); try { var parsed = JSON.parse(schema); var formatted = JSON.stringify(parsed, null, 2); $("#node-input-toolSchema").val(formatted); RED.notify("Schema formatted", "success"); } catch (error) { RED.notify("Invalid JSON: " + error.message, "error"); } }); // Generate example tools $("#generate-todo-tool-btn").click(function() { $("#node-input-name").val("Add Todo"); $("#node-input-toolName").val("add_todo_tool"); $("#node-input-toolDescription").val("Create a new todo item with description and project"); $("#node-input-toolSchema").val(schemaTemplates.todo.schema); RED.notify("Todo tool template created", "success"); }); $("#generate-calc-tool-btn").click(function() { $("#node-input-name").val("Calculator"); $("#node-input-toolName").val("calculate_tool"); $("#node-input-toolDescription").val("Perform mathematical calculations"); $("#node-input-toolSchema").val(schemaTemplates.calculator.schema); RED.notify("Calculator tool template created", "success"); }); // Tool name validation $("#node-input-toolName").on('input', function() { var toolName = $(this).val(); var isValid = /^[a-z][a-z0-9_]*_tool$/.test(toolName); if (toolName && !isValid) { $(this).addClass("input-error"); $("#tool-name-validation").show().text("Tool name should be lowercase, underscore-separated, and end with '_tool'"); } else { $(this).removeClass("input-error"); $("#tool-name-validation").hide(); } }); } }); </script> <script type="text/html" data-template-name="mcp-tool-registry"> <div class="form-row"> <label for="node-input-name"><i class="fa fa-tag"></i> Display Name</label> <input type="text" id="node-input-name" placeholder="Human-readable tool name"> </div> <div class="form-row"> <label for="node-input-toolName"><i class="fa fa-cog"></i> Tool Name</label> <input type="text" id="node-input-toolName" placeholder="my_custom_tool"> <div id="tool-name-validation" style="display: none; margin-top: 5px; font-size: 12px; color: #e74c3c;"></div> <div style="margin-top: 5px; font-size: 12px; color: #666;"> Unique tool identifier (lowercase, underscore-separated, ending with '_tool') </div> </div> <div class="form-row"> <label for="node-input-toolDescription"><i class="fa fa-info-circle"></i> Description</label> <textarea id="node-input-toolDescription" rows="2" placeholder="Describe what this tool does..."></textarea> <div style="margin-top: 5px; font-size: 12px; color: #666;"> Description shown to AI agents when listing available tools </div> </div> <hr> <h4>Parameter Schema</h4> <div class="form-row"> <label for="schema-templates"><i class="fa fa-magic"></i> Schema Templates</label> <select id="schema-templates"> <option value="">Select a template...</option> </select> <button type="button" id="load-template-btn" class="btn btn-secondary" style="margin-top: 5px;"> <i class="fa fa-download"></i> Load Template </button> </div> <div class="form-row"> <label for="node-input-toolSchema"><i class="fa fa-code"></i> JSON Schema</label> <textarea id="node-input-toolSchema" rows="8" placeholder='{"type": "object", "properties": {}, "required": []}'></textarea> <div id="schema-validation" style="display: none; margin-top: 5px; font-size: 12px;"></div> <div style="margin-top: 5px; font-size: 12px; color: #666;"> JSON Schema defining the tool's input parameters </div> <button type="button" id="format-schema-btn" class="btn btn-secondary" style="margin-top: 5px;"> <i class="fa fa-magic"></i> Format JSON </button> </div> <div class="form-row"> <label for="node-input-autoRegister"><i class="fa fa-play"></i> Auto Register</label> <input type="checkbox" id="node-input-autoRegister" style="width: auto;"> <span style="margin-left: 10px; font-size: 12px; color: #666;">Automatically register tool when Node-RED starts</span> </div> <!-- Quick Tool Generation --> <hr> <h4>Quick Tool Generation</h4> <div class="form-row"> <label></label> <button type="button" id="generate-todo-tool-btn" class="btn btn-primary" style="margin-right: 10px;"> <i class="fa fa-check-square-o"></i> Generate Todo Tool </button> <button type="button" id="generate-calc-tool-btn" class="btn btn-primary"> <i class="fa fa-calculator"></i> Generate Calculator Tool </button> </div> </script> <script type="text/html" data-help-name="mcp-tool-registry"> <p>A Node-RED node that defines and registers Model Context Protocol (MCP) tools for use with MCP Flow Servers. This allows you to create custom AI agent tools using visual flows.</p> <h3>Configuration</h3> <dl class="message-properties"> <dt>Display Name <span class="property-type">string</span></dt> <dd>Human-readable name for the tool (used for Node-RED display)</dd> <dt>Tool Name <span class="property-type">string</span></dt> <dd>Unique identifier for the tool (must end with '_tool')</dd> <dt>Description <span class="property-type">string</span></dt> <dd>Description shown to AI agents when listing available tools</dd> <dt>JSON Schema <span class="property-type">JSON</span></dt> <dd>JSON Schema defining the tool's input parameters</dd> <dt>Auto Register <span class="property-type">boolean</span></dt> <dd>Whether to automatically register the tool on startup</dd> </dl> <h3>How It Works</h3> <p>This node defines the interface for an MCP tool:</p> <ol> <li><strong>Tool Definition:</strong> Defines tool name, description, and parameter schema</li> <li><strong>Registration:</strong> Registers the tool with any running MCP Flow Servers</li> <li><strong>Discoverability:</strong> Makes the tool available to AI agents via tools/list</li> <li><strong>Execution:</strong> Works with MCP Tool Handler nodes to process requests</li> </ol> <h3>Tool Naming Convention</h3> <p>Tool names should follow these rules:</p> <ul> <li>Lowercase letters, numbers, and underscores only</li> <li>Must end with '_tool' (e.g., 'add_todo_tool')</li> <li>Should be descriptive and unique</li> <li>Examples: 'calculate_sum_tool', 'send_email_tool', 'get_weather_tool'</li> </ul> <h3>JSON Schema Format</h3> <p>The schema defines the parameters your tool accepts:</p> <pre><code>{ "type": "object", "properties": { "message": { "type": "string", "description": "Message to process" }, "priority": { "type": "string", "enum": ["low", "medium", "high"], "description": "Priority level" } }, "required": ["message"] }</code></pre> <h3>Input Commands</h3> <p>Send messages with the following topics to control registration:</p> <dl class="message-properties"> <dt>register <span class="property-type">string</span></dt> <dd>Register the tool with flow servers</dd> <dt>unregister <span class="property-type">string</span></dt> <dd>Unregister the tool from flow servers</dd> <dt>update <span class="property-type">object</span></dt> <dd>Update tool definition and re-register</dd> <dt>status <span class="property-type">string</span></dt> <dd>Get current registration status</dd> </dl> <h3>Output Messages</h3> <p>The node outputs messages for registration events:</p> <dl class="message-properties"> <dt>tool-registered <span class="property-type">object</span></dt> <dd>Tool successfully registered with details</dd> <dt>tool-unregistered <span class="property-type">object</span></dt> <dd>Tool unregistered event</dd> </dl> <h3>Schema Templates</h3> <p>Use the built-in templates for common tool types:</p> <ul> <li><strong>Simple Parameters:</strong> Basic string input</li> <li><strong>Todo Tool:</strong> Task creation with description and project</li> <li><strong>Calculator Tool:</strong> Mathematical operations</li> <li><strong>API Call Tool:</strong> HTTP request parameters</li> </ul> <h3>Example Usage</h3> <p><strong>Creating a Weather Tool:</strong></p> <pre><code>Tool Name: get_weather_tool Description: Get current weather for a location Schema: { "type": "object", "properties": { "location": { "type": "string", "description": "City name or coordinates" }, "units": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "Temperature units" } }, "required": ["location"] }</code></pre> <h3>Integration Flow</h3> <p>Complete tool creation workflow:</p> <pre><code> [MCP Tool Registry] → defines the tool interface ↓ [MCP Flow Server] → serves the tool to clients ↓ [MCP Tool Handler] → receives execution requests ↓ [Your Business Logic] → processes the request ↓ [Response] → returns result to client </code></pre> <h3>Quick Tool Generation</h3> <p>Use the generation buttons to create common tool types instantly:</p> <ul> <li><strong>Todo Tool:</strong> Creates task management tool template</li> <li><strong>Calculator Tool:</strong> Creates mathematical calculation tool</li> </ul> <h3>Best Practices</h3> <ul> <li>Use descriptive tool names and descriptions</li> <li>Define clear parameter schemas with proper types</li> <li>Include helpful descriptions for each parameter</li> <li>Mark required parameters appropriately</li> <li>Test tool registration before connecting handlers</li> </ul> <h3>Requirements</h3> <p>This node works with MCP Flow Server nodes to serve the defined tools. The tool registration is global across all flow servers in the Node-RED instance.</p> </script>