vrfsUpdateFabricVrf
Update Virtual Routing and Forwarding (VRF) configurations in network fabrics by modifying fields like ASN, VNI, annotations, labels, and descriptions for network segmentation.
Instructions
Update a specific VRF.
To use this tool, pass the resource ID and the fields to update as arguments
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| fabricId | Yes | This is a read-only field. The unique identifier of the fabric to which this VRF belongs to. | |
| vrfId | Yes | The VRF id or name. | |
| annotations | No | A list of name-value annotations to store user-defined data including complex data such as JSON associated with the VRF. | |
| asn | No | The Autonomous System Number (ASN) used for the VRF external BGP peering. | |
| description | No | The description is a user-defined field to store notes about the VRF. | |
| enabled | No | This is a read-only field. The enabled state of the VRF which indicates if the VRF is enabled or disabled. | |
| id | No | This is a read-only field. The unique identifier of the VRF. | |
| interfaces | No | This is a read-only field. A list of interfaces that are associated with the VRF. | |
| isDefault | No | This is a read-only field. The flag that indicates if the VRF is the default (auto-created) VRF or not. | |
| labels | No | A list of user-defined labels that can be used for grouping and filtering VRFs. | |
| metadata | No | Metadata defines a map of attributes related to the lifecycle of the object. | |
| name | No | The user-defined name of the VRF. The VRF name has to be unique, and is case-insensitive. The name should start with `Vrf`, `VRF`, `VRf` or `VrF`, followed by an optional `-` separator and end with an alpha-numeric string of 1 to 16 character. | |
| vni | No | The VXLAN Network Identifier (VNI) used for the VRF. |
Implementation Reference
- src/main.ts:337-448 (handler)This is the core handler function that executes ALL MCP tools, including 'vrfsUpdateFabricVrf'. It dynamically maps the tool name back to the corresponding OpenAPI path/method/operation, constructs the HTTP request using the provided arguments, and calls the Hyperfabric API at https://hyperfabric.cisco.com/api/v1. The tool logic is generic but exact for this tool based on its operationId.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; } }
- src/main.ts:134-158 (registration)Registers all tools, including 'vrfsUpdateFabricVrf', by iterating OpenAPI spec paths/operations, generating tool names from operationId (exact match expected), creating Tool objects, and adding to this.tools list returned by listTools.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:213-290 (schema)Generates the inputSchema for 'vrfsUpdateFabricVrf' by processing the OpenAPI operation's parameters (path/query) and requestBody schema properties, resolving $ref, exposing them as direct arguments.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:297-335 (registration)MCP protocol handler for tool calls: receives CallToolRequest, looks up tool by name ('vrfsUpdateFabricVrf'), invokes the generic executeApiCall handler.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 }; } }); }
- src/main.ts:160-169 (helper)Generates tool name from operation.operationId if present (likely 'vrfsUpdateFabricVrf' from spec), else from method+path. Used in both tool generation and reverse lookup.private generateToolName(method: string, path: string, operation: OpenAPIOperation): string { if (operation.operationId) { return operation.operationId; } // Generate a name from the method and path const pathParts = path.split('/').filter(part => part && !part.startsWith('{')); const nameBase = pathParts.join('_').replace(/[^a-zA-Z0-9_]/g, '_'); return `${method}_${nameBase}`; }