Skip to main content
Glama

nodesUpdatePort

Configure network port settings like speed, MTU, VLAN, and FEC mode for a specific node in Hyperfabric infrastructure using REST API calls.

Instructions

Update a specific port.

[SAFE OPERATION] This tool configures network fabric port settings (speed, MTU, VLAN, etc.) via REST API. It does NOT execute code or commands on the system.

To use this tool, pass the resource ID and the fields to update as arguments

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
fabricIdYesThe fabric id or name.
nodeIdYesThis is a read-only field. The unique identifier of the node to which this port belongs to.
portIdYesThe port name, id or index.
annotationsNoA list of name-value annotations to store user-defined data including complex data such as JSON associated with the port.
breakoutNoThis is a read-only field. The flag that indicates if the port is in breakout mode or not.
breakoutIndexNoThis is a read-only field. The index number of the breakout in the parent port. The breakout index is not set when the port is not in breakout mode.
descriptionNoThe description is a user-defined field to store notes about the port.
enabledNoThe enabled state of the port which indicates if the port is enabled or disabled.
fecNoThe Forward Error Correction (FEC) mode of the port. Supported modes are "rs" and "none". The FEC must be set to "none" for 100G DR/FR/LR pluggable optics.
forceCounterNoThe Force Counter can be incremented to force the port configuration to be forcefully reapplied when there are no other configuration changes such as to recover (un-shut) a port blocked by STP.
idNoThis is a read-only field. The unique identifier of the port.
indexNoThis is a read-only field. The index number of the port on the linecard.
ipv4AddressesNoA list of up to two IPv4 host addresses with subnet mask to be configured on the port. Requires the `ROUTED_PORT` role to be configured in roles and the port to be associated with a VRF.
ipv6AddressesNoA list of up to two IPv6 host addresses with subnet mask to be configured on the port. Requires the `ROUTED_PORT` role to be configured in roles and the port to be associated with a VRF.
labelsNoA list of user-defined labels that can be used for grouping and filtering ports.
linecardNoThis is a read-only field. The index number of the linecard to which this port belongs to.
linkDownNoPrevent traffic from being forwarded by the port. Requires `enabled` to be set to `true` (equivalent to `Admin State` set to `Up`) and role to be one of `UNUSED_PORT`, `ROUTED_PORT` or `HOST_PORT`.
maxSpeedNoThis is a read-only field. The maximum speed of the port as reported by the system (E.g. 10G).
metadataNoMetadata defines a map of attributes related to the lifecycle of the object.
mtuNoThe Maximum Transmission Unit (MTU) of the port of the node. Default value is 9216 for "FABRIC_PORT" and 9100 for all other roles. The MTU value must be 9216 for "FABRIC_PORT" and between 1500 and 9100 for all other roles.
nameNoThe name of the port of the node. The name must have a prefix of Ethernet (E.g. Ethernet1_1) and cannot be modified.
pluggableNoThe name of the model (PID) of the pluggable cable or optic expected to be used in the port.
portAliasNoThe name alias of the port.
rolesNoA list of roles of the port. The port roles list is mandatory, and must contain exactly one role.
speedNoThe configurable speed mode of the port (E.g. 10G). The port speed cannot be set for a port in breakout mode.
stpNoThe Spanning Tree Protocol (STP) interface configuration for the port. The configuration is only used when a VLAN is deployed on the port.
subInfCountNoThis is a read-only field. The number of sub-interfaces configured on the port.
vlanIdsNoThis is a read-only field. A list of VLAN IDs deployed on the port of the node.
vnisNoThis is a read-only field. A list of VNIs attached to the port of the node.
vrfIdNoThe unique identifier of the VRF associated with the port. The VRF identifier is required for a port with the `ROUTED_PORT` role.

Implementation Reference

  • Core handler function that implements the execution logic for the 'nodesUpdatePort' tool (shared with all tools). It performs security validation specific to port configuration tools, maps the tool name to the OpenAPI operation, constructs the HTTP request using tool arguments, and executes the API call to Hyperfabric.
    private async executeApiCall(toolName: string, args: any): Promise<any> { // Validate inputs for port configuration tools to prevent misuse if (toolName === 'nodesSetPorts' || toolName === 'nodesUpdatePort') { // Ensure no executable content or shell commands in arguments const argsStr = JSON.stringify(args); if (/(\$\(|`|eval|exec|system|spawn|child_process)/.test(argsStr)) { throw new Error('Security: Invalid arguments detected. Port configuration tools only accept network settings (speed, MTU, VLAN, etc.)'); } } // Extract the original method and path from the tool name // This is a simplified approach - in a production system you'd want a more robust mapping if (!this.openApiSpec?.paths) { throw new Error("OpenAPI spec not loaded"); } // Find the corresponding operation let foundOperation: { method: string; path: string; operation: OpenAPIOperation } | null = null; for (const [pathKey, pathItem] of Object.entries(this.openApiSpec.paths)) { for (const [method, operation] of Object.entries(pathItem)) { if (typeof operation !== 'object' || !operation) continue; const op = operation as OpenAPIOperation; const expectedToolName = this.generateToolName(method, pathKey, op); if (expectedToolName === toolName) { foundOperation = { method, path: pathKey, operation: op }; break; } } if (foundOperation) break; } if (!foundOperation) { throw new Error(`No operation found for tool: ${toolName}`); } // Build the URL by replacing path parameters let url = foundOperation.path; const queryParams: Record<string, string> = {}; // Handle path and query parameters if (foundOperation.operation.parameters) { for (const param of foundOperation.operation.parameters) { const value = args[param.name]; if (value !== undefined) { if (param.in === 'path') { url = url.replace(`{${param.name}}`, encodeURIComponent(value)); } else if (param.in === 'query') { queryParams[param.name] = value; } } } } // Prepare the request const requestConfig: any = { method: foundOperation.method.toUpperCase(), url, params: queryParams, }; // Handle request body for POST/PUT/PATCH if (['post', 'put', 'patch'].includes(foundOperation.method.toLowerCase())) { // Check if args has a requestBody property (legacy format) if (args.requestBody) { requestConfig.data = args.requestBody; } else { // Build request body from exposed properties // This handles cases where schema properties are exposed directly (e.g., fabrics, nodes, etc.) const requestBody: Record<string, any> = {}; const pathItem = this.openApiSpec?.paths?.[foundOperation.path]; const operation = (pathItem as any)?.[foundOperation.method]; if (operation?.requestBody) { const requestBodyDef = this.resolveSchemaRef(operation.requestBody); const schema = this.deepResolveSchema(requestBodyDef.content?.['application/json']?.schema); // Collect all properties that are part of the request body schema if (schema?.properties) { for (const propName of Object.keys(schema.properties)) { if (args.hasOwnProperty(propName)) { requestBody[propName] = args[propName]; } } } } if (Object.keys(requestBody).length > 0) { requestConfig.data = requestBody; } } } logger.debug(`Making API call: ${requestConfig.method} ${url}`); try { const response = await this.httpClient.request(requestConfig); return { status: response.status, statusText: response.statusText, data: response.data }; } catch (error) { if (axios.isAxiosError(error)) { throw new Error(`API call failed: ${error.response?.status} ${error.response?.statusText} - ${JSON.stringify(error.response?.data)}`); } throw error; } }
  • Generates the Tool definition including input schema, description, and special security note for 'nodesUpdatePort' from the OpenAPI operation schema.
    private createToolFromOperation( name: string, method: string, path: string, operation: OpenAPIOperation ): Tool | null { let description = operation.summary || operation.description || `${method.toUpperCase()} ${path}`; // Add security context for network port configuration operations if (name === 'nodesSetPorts' || name === 'nodesUpdatePort') { description += '\n\n[SAFE OPERATION] This tool configures network fabric port settings (speed, MTU, VLAN, etc.) via REST API. It does NOT execute code or commands on the system.'; } // Enhance description for create/update operations if (['post', 'put', 'patch'].includes(method.toLowerCase())) { if (method.toLowerCase() === 'post') { description += '\n\nTo use this tool, pass the required fields as direct arguments (e.g., fabrics=[{name:"my-fabric", description:"...", ...}])'; } else if (method.toLowerCase() === 'put') { description += '\n\nTo use this tool, pass the resource ID and the fields to update as arguments'; } else if (method.toLowerCase() === 'patch') { description += '\n\nTo use this tool, pass the resource ID and the fields to patch as arguments'; } } const properties: Record<string, any> = {}; const required: string[] = []; // Process parameters if (operation.parameters) { for (const param of operation.parameters) { if (param.in === 'path' || param.in === 'query') { properties[param.name] = { type: param.schema?.type || 'string', description: param.description || '' }; if (param.required) { required.push(param.name); } } } } // Process request body for POST/PUT/PATCH requests if (operation.requestBody && ['post', 'put', 'patch'].includes(method.toLowerCase())) { // Resolve the requestBody reference if it exists const requestBody = this.resolveSchemaRef(operation.requestBody); const content = requestBody.content; if (content?.['application/json']?.schema) { let schema = content['application/json'].schema; // Deeply resolve schema references schema = this.deepResolveSchema(schema); if (schema.properties) { // Expose the request body properties directly for (const [propName, propSchema] of Object.entries(schema.properties)) { const propDef = propSchema as any; properties[propName] = this.deepResolveSchema(propDef, 0); if (schema.required?.includes(propName)) { required.push(propName); } } } } } return { name, description, inputSchema: { type: 'object', properties, required } }; }
  • src/main.ts:134-157 (registration)
    Dynamically generates and registers all tools, including 'nodesUpdatePort', by iterating over OpenAPI spec paths/operations and creating Tool objects.
    private generateTools(): void { if (!this.openApiSpec?.paths) { logger.error("No paths found in OpenAPI spec"); return; } this.tools = []; for (const [pathKey, pathItem] of Object.entries(this.openApiSpec.paths)) { for (const [method, operation] of Object.entries(pathItem)) { if (typeof operation !== 'object' || !operation) continue; const op = operation as OpenAPIOperation; const toolName = this.generateToolName(method, pathKey, op); const tool = this.createToolFromOperation(toolName, method, pathKey, op); if (tool) { this.tools.push(tool); logger.debug(`Generated tool: ${toolName}`); } } } logger.info(`Generated ${this.tools.length} tools from OpenAPI spec`);
  • src/main.ts:292-335 (registration)
    Registers the MCP protocol handlers: listTools (returns registered tools) and callToolRequest (dispatches to executeApiCall for tool execution).
    private setupHandlers(): void { this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: this.tools }; }); this.server.setRequestHandler(CallToolRequestSchema, async (request: any) => { const { name, arguments: args } = request.params; logger.info(`Calling tool: ${name}`); logger.debug(`Tool arguments: ${JSON.stringify(args, null, 2)}`); try { // Find the tool definition const tool = this.tools.find(t => t.name === name); if (!tool) { throw new Error(`Tool ${name} not found`); } // Execute the API call const result = await this.executeApiCall(name, args); return { content: [ { type: "text", text: JSON.stringify(result, null, 2) } ] }; } catch (error) { logger.error(`Error executing tool ${name}:`, error); return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } }); }

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jim-coyne/hyperfabric_MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server