{
  "markdown": "# Baremetal MCP Server\n\nAn MCP (Model Context Protocol) server for managing bare-metal infrastructure. It exposes Redfish BMC operations (Dell iDRAC, HPE iLO, Supermicro), BMC console capture and command paging, and Junos/Dell OS10 switch queries as tools for AI assistants.\n\nBuilt with [FastMCP](https://github.com/jlowin/fastmcp), it works with any MCP-compatible client including **Claude Code**, **Gemini CLI**, and others.\n\n## Table of Contents\n\n- [Features](#features)\n- [Portable Agent Skills](#portable-agent-skills)\n- [Requirements](#requirements)\n- [Prerequisites](#prerequisites)\n- [Installation](#installation)\n- [Claude Code](#claude-code)\n- [Gemini CLI](#gemini-cli)\n- [Cursor](#cursor)\n- [Other MCP Clients](#other-mcp-clients)\n- [Configuration](#configuration)\n- [Usage](#usage)\n\n## Features\n\n- **Inventory:** Detailed hardware overview (CPUs, Memory, NICs, Storage).\n- **Power Control:** On, Off, Graceful Shutdown, and Reboots.\n- **Boot Management:** Set one-time boot targets (PXE, CD/ISO, HDD, USB).\n- **Virtual Media:** Mount and eject ISO images remotely.\n- **Dell-Specific:** Firmware updates and detailed XML inventory exports.\n- **BMC Console Tools:** Run guarded Dell SOL/HPE VSP commands in batches, or capture and page through a visually confirmed VNC console.\n- **Network Inventory:** Collect Linux network facts, query firmware-visible Redfish NIC ports, save per-host YAML, validate identity and duplicates, and export searchable MAC/IP indexes.\n- **Junos Switches:** Query Juniper switch configuration, interfaces, MAC tables, and run arbitrary CLI commands via SSH.\n- **Dell OS10 Switches:** Run read-only `show` queries or dry-run/confirm unrestricted CLI sequences across switches via SSH.\n- **Parallelism:** Perform actions on multiple servers simultaneously.\n- **Caching:** Slow inventory calls (`get_firmware_inventory`, `get_hardware_overview`, `get_system_info`) are cached in memory with TTLs to avoid redundant BMC requests.\n\n## Portable Agent Skills\n\nModel-neutral workflows are available under [`skills/`](skills/) using the standard [Agent Skills](https://agentskills.io/specification) `SKILL.md` format. They use YAML frontmatter plus Markdown instructions and do not require model-specific metadata. See [`SKILLS.md`](SKILLS.md) for the catalog.\n\n## Requirements\n\nEnsure you have Python installed and install the necessary dependencies:\n\n```bash\npip install -e .\n```\n\n## Prerequisites\n\nBefore using the MCP server with any AI agent, you **must** configure two mandatory environment variables pointing to your server and credentials files:\n\n```bash\n# Required — must be set before running Claude Code or Gemini CLI\nexport REDFISH_CONFIG=\"/path/to/redfish_servers.yaml\"\nexport REDFISH_SECRETS=\"/path/to/redfish_secrets.yaml\"\n```\n\n```bash\n# Optional — only if you need firmware ISOs or custom settings\nexport ISOS_FILE=\"/path/to/isos.yaml\"\nexport GLOBAL_CONFIG=\"/path/to/global_config.yaml\"\nexport NETWORK_INVENTORY_DIR=\"/path/to/network_inventory\"\nexport HARDWARE_INVENTORY_DIR=\"/path/to/hardware_inventory\"\n```\n\nAdd these to your `~/.bashrc` or `~/.zshrc` to make them permanent. See [Configuration](#configuration) for file format details.\n\n## Installation\n\n### Running manually\n\n```bash\n# stdio transport (for MCP clients)\nfastmcp run -t stdio main.py\n\n# HTTP transport (for network access)\nfastmcp run --port 5004 --host 127.0.0.1 -t streamable-http main.py\n```\n\n## Claude Code\n\n### Install as a plugin from GitHub (recommended)\n\nMake sure the [prerequisite env vars](#prerequisites) are exported in your shell, then:\n\n```bash\nclaude plugin marketplace add sshnaidm/baremetal-mcp\nclaude plugin install baremetal-mcp@baremetal-mcp-marketplace\n```\n\nVerify it works:\n\n```bash\nclaude mcp list                  # see configured servers\n```\n\nOr within a Claude Code session, run `/mcp` to see active tools and server status.\n\n### Alternative: clone and auto-detect\n\nClone the repository and open it with Claude Code. The included `.mcp.json` is detected automatically — you'll be prompted to approve the server on first use.\n\n```bash\ngit clone https://github.com/sshnaidm/baremetal-mcp.git\ncd baremetal-mcp\nclaude\n```\n\n### Alternative: manual setup with env vars\n\nRegister the server directly and pass config paths as env vars:\n\n```bash\nclaude mcp add --transport stdio baremetal-mcp \\\n  --env REDFISH_CONFIG=/path/to/redfish_servers.yaml \\\n  --env REDFISH_SECRETS=/path/to/redfish_secrets.yaml \\\n  -- fastmcp run -t stdio /path/to/baremetal-mcp/main.py\n```\n\n## Gemini CLI\n\nMake sure the [prerequisite env vars](#prerequisites) are exported in your shell, then install directly from the repository:\n\n```bash\ngemini extensions install https://github.com/sshnaidm/baremetal-mcp.git\n```\n\nVerify it works:\n\n- `/extensions list` - See installed extensions.\n- `/mcp` - See active tools and server status.\n\n## Cursor\n\nAdd the server to your Cursor MCP configuration file (`.cursor/mcp.json` in your project or `~/.cursor/mcp.json` globally):\n\n```json\n{\n  \"mcpServers\": {\n    \"baremetal-mcp\": {\n      \"command\": \"fastmcp\",\n      \"args\": [\"run\", \"-t\", \"stdio\", \"/path/to/baremetal-mcp/main.py\"],\n      \"env\": {\n        \"REDFISH_CONFIG\": \"/path/to/redfish_servers.yaml\",\n        \"REDFISH_SECRETS\": \"/path/to/redfish_secrets.yaml\"\n      }\n    }\n  }\n}\n```\n\n## Other MCP Clients\n\nAny MCP-compatible client can use this server via stdio transport. Add it to your client's MCP configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"baremetal-mcp\": {\n      \"command\": \"fastmcp\",\n      \"args\": [\"run\", \"-t\", \"stdio\", \"/path/to/baremetal-mcp/main.py\"],\n      \"env\": {\n        \"REDFISH_CONFIG\": \"/path/to/redfish_servers.yaml\",\n        \"REDFISH_SECRETS\": \"/path/to/redfish_secrets.yaml\"\n      }\n    }\n  }\n}\n```\n\nOptionally add `GLOBAL_CONFIG` and `ISOS_FILE` env vars if you need custom settings or firmware ISOs.\n\nFor HTTP transport instead of stdio:\n\n```json\n{\n  \"mcpServers\": {\n    \"baremetal-mcp\": {\n      \"url\": \"http://127.0.0.1:5004/mcp\"\n    }\n  }\n}\n```\n\nStart the server separately with: `fastmcp run --port 5004 --host 127.0.0.1 -t streamable-http main.py`\n\n## Configuration\n\nThe server uses up to four YAML configuration files controlled by environment variables.\n\n| Env var | Default filename | Required | Description |\n| --------- | ----------------- | ---------- | ------------- |\n| `REDFISH_CONFIG` | `redfish_servers.yaml` | **Yes** | Server/switch definitions (BMC IPs, vendor, tags) |\n| `REDFISH_SECRETS` | `redfish_secrets.yaml` | **Yes** | Per-server credentials (username/password) |\n| `ISOS_FILE` | `isos.yaml` | No | Firmware/ISO URL catalog |\n| `GLOBAL_CONFIG` | `global_config.yaml` | No | Settings overrides (timeouts, retries, cache TTLs) |\n| `NETWORK_INVENTORY_DIR` | `network_inventory` | No | Per-host YAML network snapshots; overrides the global setting |\n| `HARDWARE_INVENTORY_DIR` | `data/hardware_inventory` | No | Validated Dell XML files and manifests; overrides the global setting |\n\n### Servers Configuration (`redfish_servers.yaml`)\n\nEach entry requires `bmc_ip` (the BMC management address). Connection ports are never inferred by the MCP server: define shared values in `server_defaults` and `switch_defaults`, then override them per target when necessary. `vendor` remains optional and is auto-detected through the configured Redfish endpoint.\n\n```yaml\nserver_defaults:\n  redfish:\n    port: 443\n  serial_console:\n    transport: auto\n    port: 22\n  verify_ssl: false\n\nswitch_defaults:\n  port: 22\n\nservers:\n  srv-dell-01:\n    bmc_ip: \"10.10.1.5\"          # required\n    vendor: \"dell\"                # optional, auto-detected if omitted\n    lab: \"lab-a\"\n    tags: [\"compute\", \"gpu\"]\n    serial_number: \"ABC123\"       # optional identity guard\n    expected_host_macs:\n      - \"aa:bb:cc:dd:ee:01\"\n    credential_profile: \"dell-lab\"\n    vnc:                           # optional; all connection values explicit\n      port: 5901\n      timeout: 30\n      key_delay: 0.01\n  srv-hpe-02:\n    bmc_ip: \"10.10.1.6\"\n    vendor: \"hpe\"\n    lab: \"lab-b\"\n```\n\n### Switches Configuration\n\nSwitches are defined under a separate `switches:` section in the same file. Each needs a `hostname` and an SSH `port`, either directly or through `switch_defaults`.\n\n```yaml\nswitches:\n  lab1-switch:\n    hostname: \"192.168.1.200\"\n    vendor: \"Juniper\"          # optional\n    model: \"Juniper QFX5120\"   # optional\n    tags: [\"switch\", \"lab1\"]   # optional\n  lab1-dell-switch:\n    hostname: \"192.168.1.201\"\n    vendor: \"Dell\"\n    model: \"S5232F-ON\"\n    tags: [\"switch\", \"lab1\"]\n```\n\n### Secrets Configuration (`redfish_secrets.yaml`)\n\nDefine the credentials for each server ID.\n\n```yaml\nprofiles:\n  dell-lab:\n    username: \"example-dell-user\"\n    password: \"example-dell-password\"\n    vnc_password: \"example-vnc-password\"\nsrv-dell-01:\n  # Per-host values override a referenced profile.\n  password: \"example-override-password\"\nsrv-hpe-02:\n  username: \"example-hpe-user\"\n  password: \"example-hpe-password\"\n```\n\nSee `*.example.yaml` files for complete format examples.\n\n`boot_from_iso` validates HTTP(S) image URLs, bounds fleet concurrency, verifies that the exact image is inserted, and confirms `Cd`/`Once` before it sends a reset. If verification fails, it does not reboot. A powered-off verified host is started with `On` instead of an invalid restart request. Results retain each accepted, rejected, or ambiguous media/boot mutation, so a late failure cannot make a partially changed host look safe to retry; an accepted reset request is never described as a verified power transition.\n\n`export_hardware_inventory_xml` replaces external Dell export wrappers. It handles case-insensitive `Location` headers, polls task monitors with deadlines and `Retry-After`, rejects cross-BMC redirects or malformed/oversized/non-inventory XML, and requires the XML service tag to match the live Redfish identity before using either a fresh download or cache. It writes XML atomically and creates a checksum manifest. It returns metadata by default; use `include_xml=true` only when the raw payload is needed. For large exports, use `start_hardware_inventory_export` and `get_operation`.\n\nUse `redfish_call` and `parallel_redfish_call` only when no high-level tool covers a standard Redfish resource. They accept same-BMC origin-relative paths only. GET/HEAD/OPTIONS run normally; POST/PUT/PATCH/DELETE make no request by default and require `dry_run=false` plus `confirm_method_path` exactly matching the returned `required_confirmation`. Mutating requests are never automatically replayed after an ambiguous failure, and missing credentials fail closed instead of falling back to vendor defaults.\n\n### BMC Console Commands\n\n`run_console_command_batch` is the normal text interface. It attaches with Dell iDRAC SSH SOL (`console com2`) or HPE iLO VSP, proves that a shell interprets a random nonce, sends one single-line command, and captures its output plus exit code. It defaults to `dry_run=true`, which checks configuration without connecting. Execution requires both `dry_run=false` and `confirm_command` exactly equal to `command`.\n\nEvery host result reports `command_sent`, `result_confirmed`, `retry_safe`, transport, phase, exit code, bounded output, and truncation. Never repeat a `command_sent=true` result whose completion is unknown. `retry_console_operation_failures` selects only hosts proven not to have received the previous command. Use `start_console_command_batch` and poll `get_operation` for fleet commands that could exceed an MCP client timeout. Completed operation records aggregate `remote_state`, `outcome_unknown`, and `retry_safe` across their host results. Operation records live only in the MCP server process; after a restart, completion is unknown and mutating work must not be blindly retried.\n\nVNC remains a visual fallback. `capture_console_screen` sends no input and returns PNG `ImageContent` plus a short-lived `input_confirmation_token`. Before every command, inspect a fresh token-producing image and confirm a focused shell, then pass that one-use token as `confirmation_token` to `run_console_command`. The command is displayed through a restricted `less` pager; navigate it with `console_pager_action`. If pager tracking expires, `get_console_session_status` reports remote state as unknown: make and inspect a new post-expiry capture, then pass its token to `console_pager_action` for one recovery, quit, interrupt, or visually justified abandon action. A VNC send or capture failure can leave partial text or an unknown command outcome, which is returned explicitly rather than retried.\n\nVNC commands need POSIX `sh` and `less`. Console text is visible and may enter shell history, so never include passwords or tokens. Dell iDRAC VNC SSL encryption requires an external tunnel; the tools do not weaken BMC security settings.\n\n### Persistent Network Inventory\n\nCall `collect_network_inventory(server_ids, transport=\"auto\", save=true)` to run short read-only Linux probes over SOL/VSP. It captures `ip`, sysfs carrier and physical-port data, `ethtool`, PCI vendor/model details, DMI identity, routes, addresses, and optional LLDP neighbors. It compares OS identity with Redfish and configured serial/MAC evidence before replacing a snapshot. Only verified identity is persisted; mismatched and unverified collections are returned as evidence but remain unsaved. For large sets, use `start_network_inventory_collection` and poll `get_operation`.\n\nIf serial collection cannot prove a shell, the result says whether visually guarded VNC fallback is available. The tool does not treat OCR as authoritative data. `get_network_hardware` is a separate read-only Redfish fallback for firmware-visible Ethernet interfaces, adapters, physical ports, and device functions; keep its evidence distinct from Linux interface names and carrier state.\n\nThe latest validated snapshots live under `network_inventory/hosts/<server_id>.yaml`. `save_network_inventory` and `save_network_inventories` support explicitly supplied structured observations, reject secrets and older timestamps by default, and write atomically.\n\nUse these MCP tools for later retrieval:\n\n- `get_network_inventory(server_id)` returns one complete host document.\n- `list_network_inventories()` returns per-host counts of interfaces, active links, and addresses.\n- `search_network_inventory(...)` combines paginated filters for `mac`, interface-name substring, `link_up`, exact IP or subnet, vendor substring, exact PCI address, and server ID.\n- `validate_network_inventories(...)` reports missing, stale, malformed, duplicate-MAC, and host-identity problems.\n- `export_network_inventory(...)` atomically produces one YAML or JSON file with connected-interface, MAC, IP, and separate BMC-MAC indexes.\n\nExamples:\n\n```text\nsearch_network_inventory(mac=\"b4:96:91:c8:aa:28\")\nsearch_network_inventory(link_up=true)\nsearch_network_inventory(ip=\"fe80::/64\", vendor=\"Intel\")\nsearch_network_inventory(interface=\"ens1\", server_id=\"bmc18-live\")\nvalidate_network_inventories(server_ids=[\"srv-dell-01\", \"srv-hpe-02\"])\nexport_network_inventory(format=\"yaml\", collection=\"rack-14\")\n```\n\nThe YAML remains directly searchable without MCP:\n\n```bash\nrg -l 'mac_address: b4:96:91:c8:aa:28' network_inventory/hosts\n```\n\n## Usage\n\nOnce the MCP server is running, your AI assistant will discover the Redfish tools automatically. You can ask it to perform tasks naturally:\n\n- \"List all servers in lab-a\"\n- \"What is the power state of srv-dell-01?\"\n- \"Get a hardware inventory for all servers with the 'gpu' tag\"\n- \"Mount the Ubuntu ISO to srv-hpe-02 and boot from it once\"\n- \"Update the firmware on srv-dell-01 using this URL: http://...\"\n- \"Show me the MAC address table on lab1-switch\"\n- \"Run 'show lldp neighbors' on the Junos switch\"\n- \"Run 'show interface status' on the Dell OS10 switch\"\n- \"Dry-run these Dell OS10 configuration commands on both switches, then run the unchanged confirmed plan\"\n- \"Capture the console screen for srv-dell-01 and explain what is happening\"\n- \"Run `journalctl -b` on the console, inspect every page, and tell me why boot failed\"\n- \"Dry-run `systemctl restart NetworkManager` for these hosts over SOL, then execute it only on the confirmed targets\"\n- \"Collect and save network data for every host tagged rack-14, then export its connected-MAC index\"\n- \"Save this host's network inventory, then show every connected Intel interface across all saved hosts\"\n\n> **Note on caching:** `get_firmware_inventory`, `get_hardware_overview`, and `get_system_info` cache their responses in memory to reduce BMC load. If results look stale after a hardware change, ask the assistant to run `clear_server_cache` for the affected servers. TTL values are configurable in `global_config.yaml`.\n",
  "bytes": 16702,
  "sha": "6556e1eaf2a29ef974daa26c91b5a35616be19e6c1db270e4ce4471d3b3ac418",
  "repo_slug": "sshnaidm/baremetal-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_sshnaidm_baremetal_mcp_fbdc22b4/readme"
}