Skip to main content
Glama
moimran

EVE-NG MCP Server

by moimran

add_node

Add a new network node to an existing EVE-NG lab using specified templates, configurations, and positioning for network topology expansion.

Instructions

Add a node to a lab.

This tool adds a new node to an existing lab with the specified template, configuration, and positioning. The node will be created but not automatically started.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
argumentsYes

Implementation Reference

  • The main handler function for the 'add_node' MCP tool. It is decorated with @mcp.tool() for automatic registration, validates input via AddNodeArgs, prepares node parameters, calls the underlying eveng_client.add_node(), and returns formatted TextContent results.
    @mcp.tool()
    async def add_node(arguments: AddNodeArgs) -> list[TextContent]:
        """
        Add a node to a lab.
    
        This tool adds a new node to an existing lab with the specified
        template, configuration, and positioning. The node will be created
        but not automatically started.
        """
        try:
            logger.info(f"Adding node to lab: {arguments.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."
                )]
    
            # Prepare node parameters
            node_params = {
                "name": arguments.name,
                "node_type": arguments.node_type,
                "left": arguments.left,
                "top": arguments.top,
                "delay": arguments.delay,
                "console": arguments.console,
                "config": arguments.config,
            }
    
            # Add optional parameters if specified
            if arguments.ethernet is not None:
                node_params["ethernet"] = arguments.ethernet
            if arguments.serial is not None:
                node_params["serial"] = arguments.serial
            if arguments.image is not None:
                node_params["image"] = arguments.image
            if arguments.ram is not None:
                node_params["ram"] = arguments.ram
            if arguments.cpu is not None:
                node_params["cpu"] = arguments.cpu
    
            # Add node
            result = await eveng_client.add_node(arguments.lab_path, arguments.template, **node_params)
    
            if result.get('status') == 'success':
                node_id = result.get('data', {}).get('id', 'Unknown')
                return [TextContent(
                    type="text",
                    text=f"Successfully added node to lab!\n\n"
                         f"Lab: {arguments.lab_path}\n"
                         f"Template: {arguments.template}\n"
                         f"Node ID: {node_id}\n"
                         f"Name: {arguments.name or f'Node{node_id}'}\n"
                         f"Type: {arguments.node_type}\n"
                         f"Position: ({arguments.left}%, {arguments.top}%)\n\n"
                         f"Node created successfully. Use start_node to power it on."
                )]
            else:
                return [TextContent(
                    type="text",
                    text=f"Failed to add node: {result.get('message', 'Unknown error')}"
                )]
    
        except Exception as e:
            logger.error(f"Failed to add node: {e}")
            return [TextContent(
                type="text",
                text=f"Failed to add node: {str(e)}"
            )]
  • Pydantic model defining the input schema and validation for the add_node tool arguments.
    class AddNodeArgs(BaseModel):
        """Arguments for add_node tool."""
        lab_path: str = Field(description="Full path to the lab (e.g., /lab_name.unl)")
        template: str = Field(description="Node template name (e.g., 'vios', 'linux', 'iol')")
        name: str = Field(default="", description="Node name (optional, auto-generated if empty)")
        node_type: str = Field(default="qemu", description="Node type (qemu, iol, dynamips)")
        left: int = Field(default=50, description="Position from left (percentage, 0-100)")
        top: int = Field(default=50, description="Position from top (percentage, 0-100)")
        delay: int = Field(default=0, description="Seconds to wait before starting node")
        console: str = Field(default="telnet", description="Console type (telnet, vnc)")
        config: str = Field(default="Unconfigured", description="Config state (Unconfigured, Saved)")
        ethernet: Optional[int] = Field(default=None, description="Number of ethernet interfaces")
        serial: Optional[int] = Field(default=None, description="Number of serial interfaces")
        image: Optional[str] = Field(default=None, description="Specific image to use")
        ram: Optional[int] = Field(default=None, description="RAM in MB")
        cpu: Optional[int] = Field(default=None, description="Number of CPUs")
  • Within register_tools(), calls register_node_tools() which defines and registers the add_node tool (along with other node tools) by executing the decorated function definitions.
    # Node management tools
    register_node_tools(mcp, eveng_client)
  • Top-level call to register_tools() in the MCP server initialization, which triggers the registration chain for all tools including add_node.
    register_tools(self.mcp, self.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