Skip to main content
Glama
moimran
by moimran

get_lab_details

Retrieve comprehensive details about a specific lab on the EVE-NG MCP Server, including metadata, nodes, networks, and current status.

Instructions

Get detailed information about a specific lab.

This tool retrieves comprehensive information about a lab including its metadata, nodes, networks, and current status.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
lab_pathYes

Implementation Reference

  • Core handler function for 'get_lab_details' tool. Fetches lab metadata, lists nodes/networks/links/interfaces via EVENGClientWrapper, parses status/console/etc., and constructs a comprehensive formatted text report returned as list[TextContent]. Handles connection checks and errors.
    async def get_lab_details(lab_path: str) -> list[TextContent]: """ Get detailed information about a specific lab. This tool retrieves comprehensive information about a lab including its metadata, nodes, networks, and current status. """ try: logger.info(f"Getting details for lab: {lab_path}") if not eveng_client.is_connected: return [TextContent( type="text", text="Not connected to EVE-NG server. Use connect_eveng_server tool first." )] # Get lab details lab_response = await eveng_client.get_lab(lab_path) # Extract lab data from the response lab = lab_response.get('data', {}) # Get nodes, networks, and topology separately try: nodes_response = await asyncio.to_thread(eveng_client.api.list_nodes, lab_path) nodes = nodes_response.get('data', {}) except Exception as e: logger.warning(f"Failed to get nodes for lab {lab_path}: {e}") nodes = {} try: networks_response = await asyncio.to_thread(eveng_client.api.list_lab_networks, lab_path) networks = networks_response.get('data', {}) except Exception as e: logger.warning(f"Failed to get networks for lab {lab_path}: {e}") networks = {} try: links_response = await asyncio.to_thread(eveng_client.api.list_lab_links, lab_path) links = links_response.get('data', {}) except Exception as e: logger.warning(f"Failed to get links for lab {lab_path}: {e}") links = {} # Get node interfaces for each node node_interfaces = {} for node_id in nodes.keys(): try: interfaces_response = await asyncio.to_thread(eveng_client.api.get_node_interfaces, lab_path, node_id) node_interfaces[node_id] = interfaces_response.get('data', {}) except Exception as e: logger.warning(f"Failed to get interfaces for node {node_id}: {e}") node_interfaces[node_id] = {} # Format lab information details_text = f"Lab Details: {lab.get('name', 'Unknown')}\n\n" # Basic information details_text += "📋 Basic Information:\n" details_text += f" Name: {lab.get('name', 'Unknown')}\n" details_text += f" Filename: {lab.get('filename', 'Unknown')}\n" details_text += f" Path: {lab_path}\n" details_text += f" Description: {lab.get('description', 'No description')}\n" details_text += f" Author: {lab.get('author', 'Unknown')}\n" details_text += f" Version: {lab.get('version', 'Unknown')}\n" details_text += f" ID: {lab.get('id', 'Unknown')}\n" details_text += f" Script Timeout: {lab.get('scripttimeout', 'Unknown')} seconds\n" details_text += f" Lock Status: {'Locked' if lab.get('lock', 0) else 'Unlocked'}\n\n" # Nodes information details_text += f"🖥️ Nodes ({len(nodes)}):\n" if nodes: for node_id, node in nodes.items(): # Parse status status_map = {0: "Stopped", 1: "Starting", 2: "Running", 3: "Stopping"} status = status_map.get(node.get('status', 0), f"Unknown ({node.get('status', 0)})") # Parse console URL to extract port console_url = node.get('url', '') console_port = '' if console_url and ':' in console_url: console_port = console_url.split(':')[-1] details_text += f" • {node.get('name', f'Node {node_id}')}\n" details_text += f" ID: {node_id}\n" details_text += f" Type: {node.get('type', 'Unknown')}\n" details_text += f" Template: {node.get('template', 'Unknown')}\n" details_text += f" Image: {node.get('image', 'Unknown')}\n" details_text += f" Status: {status}\n" details_text += f" CPU: {node.get('cpu', 'Unknown')}\n" details_text += f" RAM: {node.get('ram', 'Unknown')} MB\n" details_text += f" Ethernet Ports: {node.get('ethernet', 'Unknown')}\n" details_text += f" Console Type: {node.get('console', 'None')}\n" if console_url: details_text += f" Console URL: {console_url}\n" if console_port: details_text += f" Console Port: {console_port}\n" details_text += f" UUID: {node.get('uuid', 'Unknown')}\n" # Add interface information interfaces = node_interfaces.get(node_id, {}) ethernet_interfaces = interfaces.get('ethernet', []) serial_interfaces = interfaces.get('serial', []) if ethernet_interfaces or serial_interfaces: details_text += f" Interfaces:\n" for eth_int in ethernet_interfaces: int_name = eth_int.get('name', 'Unknown') net_id = eth_int.get('network_id', 0) if net_id == 0: connection = "Not connected" else: # Find network name network_name = networks.get(str(net_id), {}).get('name', f'Network {net_id}') connection = f"Connected to {network_name}" details_text += f" - {int_name}: {connection}\n" for ser_int in serial_interfaces: int_name = ser_int.get('name', 'Unknown') details_text += f" - {int_name} (Serial): Not connected\n" details_text += "\n" else: details_text += " No nodes configured\n" details_text += "\n" # Networks information details_text += f"🌐 Networks ({len(networks)}):\n" if networks: for net_id, network in networks.items(): details_text += f" • {network.get('name', f'Network {net_id}')}\n" details_text += f" ID: {net_id}\n" details_text += f" Type: {network.get('type', 'Unknown')}\n" details_text += f" Connected Devices: {network.get('count', 0)}\n" details_text += f" Visibility: {'Visible' if network.get('visibility', 1) else 'Hidden'}\n" details_text += f" Icon: {network.get('icon', 'Unknown')}\n" details_text += f" Position: ({network.get('left', 'Unknown')}, {network.get('top', 'Unknown')})\n" details_text += "\n" else: details_text += " No networks configured\n" # Topology/Links information details_text += f"\n🔗 Topology & Connections:\n" if links: ethernet_links = links.get('ethernet', {}) serial_links = links.get('serial', []) if ethernet_links: details_text += f" Ethernet Connections:\n" for net_id, net_name in ethernet_links.items(): details_text += f" - Network {net_id} ({net_name})\n" if serial_links: details_text += f" Serial Connections:\n" for serial_link in serial_links: details_text += f" - {serial_link}\n" if not ethernet_links and not serial_links: details_text += " No connections configured\n" else: details_text += " No topology information available\n" return [TextContent( type="text", text=details_text )] except Exception as e: logger.error(f"Failed to get lab details: {e}") return [TextContent( type="text", text=f"Failed to get lab details: {str(e)}" )]
  • Pydantic BaseModel defining the input schema for the get_lab_details tool, specifying the required 'lab_path' parameter with description.
    class GetLabDetailsArgs(BaseModel): """Arguments for get_lab_details tool.""" lab_path: str = Field(description="Full path to the lab (e.g., /lab_name.unl)")
  • Top-level registration of all tools (including get_lab_details via register_lab_tools) in the main EVENGMCPServer._register_components method, called during server initialization.
    # Register tools register_tools(self.mcp, self.eveng_client)
  • Intermediate registration call for lab management tools specifically, within the aggregate register_tools function.
    # Lab management tools register_lab_tools(mcp, eveng_client)

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/moimran/eveng-mcp'

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