An MCP (Model Context Protocol) server for managing bare-metal infrastructure. It exposes Redfish BMC operations (Dell iDRAC, HPE iLO, Supermicro) and Junos switch queries as tools for AI assistants, providing inventory collection, power management, virtual media injection, boot control, firmware updates, and network switch CLI access.
Built with FastMCP, it works with any MCP-compatible client including Claude Code, Gemini CLI, and others.
- Features
- Requirements
- Prerequisites
- Installation
- Claude Code
- Gemini CLI
- Cursor
- Other MCP Clients
- Configuration
- Usage
- Inventory: Detailed hardware overview (CPUs, Memory, NICs, Storage).
- Power Control: On, Off, Graceful Shutdown, and Reboots.
- Boot Management: Set one-time boot targets (PXE, CD/ISO, HDD, USB).
- Virtual Media: Mount and eject ISO images remotely.
- Dell-Specific: Firmware updates and detailed XML inventory exports.
- Junos Switches: Query Juniper switch configuration, interfaces, MAC tables, and run arbitrary CLI commands via SSH.
- Parallelism: Perform actions on multiple servers simultaneously.
- Caching: Slow inventory calls (
get_firmware_inventory,get_hardware_overview,get_system_info) are cached in memory with TTLs to avoid redundant BMC requests.
Ensure you have Python installed and install the necessary dependencies:
pip install fastmcp httpx PyYAML urllib3 paramikoBefore using the MCP server with any AI agent, you must configure two mandatory environment variables pointing to your server and credentials files:
# Required — must be set before running Claude Code or Gemini CLI
export REDFISH_CONFIG="/path/to/redfish_servers.yaml"
export REDFISH_SECRETS="/path/to/redfish_secrets.yaml"# Optional — only if you need firmware ISOs or custom settings
export ISOS_FILE="/path/to/isos.yaml"
export GLOBAL_CONFIG="/path/to/global_config.yaml"Add these to your ~/.bashrc or ~/.zshrc to make them permanent. See Configuration for file format details.
# stdio transport (for MCP clients)
fastmcp run -t stdio main.py
# HTTP transport (for network access)
fastmcp run --port 5004 --host 127.0.0.1 -t streamable-http main.pyMake sure the prerequisite env vars are exported in your shell, then:
claude plugin marketplace add sshnaidm/baremetal-mcp
claude plugin install baremetal-mcp@baremetal-mcp-marketplaceVerify it works:
claude mcp list # see configured serversOr within a Claude Code session, run /mcp to see active tools and server status.
Clone 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.
git clone https://github.com/sshnaidm/baremetal-mcp.git
cd baremetal-mcp
claudeRegister the server directly and pass config paths as env vars:
claude mcp add --transport stdio baremetal-mcp \
--env REDFISH_CONFIG=/path/to/redfish_servers.yaml \
--env REDFISH_SECRETS=/path/to/redfish_secrets.yaml \
-- fastmcp run -t stdio /path/to/baremetal-mcp/main.pyMake sure the prerequisite env vars are exported in your shell, then install directly from the repository:
gemini extensions install https://github.com/sshnaidm/baremetal-mcp.gitVerify it works:
/extensions list- See installed extensions./mcp- See active tools and server status.
Add the server to your Cursor MCP configuration file (.cursor/mcp.json in your project or ~/.cursor/mcp.json globally):
{
"mcpServers": {
"baremetal-mcp": {
"command": "fastmcp",
"args": ["run", "-t", "stdio", "/path/to/baremetal-mcp/main.py"],
"env": {
"REDFISH_CONFIG": "/path/to/redfish_servers.yaml",
"REDFISH_SECRETS": "/path/to/redfish_secrets.yaml"
}
}
}
}Any MCP-compatible client can use this server via stdio transport. Add it to your client's MCP configuration:
{
"mcpServers": {
"baremetal-mcp": {
"command": "fastmcp",
"args": ["run", "-t", "stdio", "/path/to/baremetal-mcp/main.py"],
"env": {
"REDFISH_CONFIG": "/path/to/redfish_servers.yaml",
"REDFISH_SECRETS": "/path/to/redfish_secrets.yaml"
}
}
}
}Optionally add GLOBAL_CONFIG and ISOS_FILE env vars if you need custom settings or firmware ISOs.
For HTTP transport instead of stdio:
{
"mcpServers": {
"baremetal-mcp": {
"url": "http://127.0.0.1:5004/mcp"
}
}
}Start the server separately with: fastmcp run --port 5004 --host 127.0.0.1 -t streamable-http main.py
The server uses up to four YAML configuration files controlled by environment variables.
| Env var | Default filename | Required | Description |
|---|---|---|---|
REDFISH_CONFIG |
redfish_servers.yaml |
Yes | Server/switch definitions (BMC IPs, vendor, tags) |
REDFISH_SECRETS |
redfish_secrets.yaml |
Yes | Per-server credentials (username/password) |
ISOS_FILE |
isos.yaml |
No | Firmware/ISO URL catalog |
GLOBAL_CONFIG |
global_config.yaml |
No | Settings overrides (timeouts, retries, cache TTLs) |
Each entry requires bmc_ip (the BMC management address). All other fields are optional — vendor is auto-detected if omitted.
srv-dell-01:
bmc_ip: "10.10.1.5" # required
vendor: "dell" # optional, auto-detected if omitted
lab: "lab-a" # optional
tags: ["compute", "gpu"] # optional
srv-hpe-02:
bmc_ip: "10.10.1.6"
vendor: "hpe"
lab: "lab-b"Switches are defined under a separate switches: section in the same file. Only hostname is required.
switches:
lab1-switch:
hostname: "192.168.1.200"
model: "Juniper QFX5120" # optional
tags: ["switch", "lab1"] # optionalDefine the credentials for each server ID.
srv-dell-01:
username: "root"
password: "calvin-password"
srv-hpe-02:
username: "admin"
password: "hp-password"See *.example.yaml files for complete format examples.
Once the MCP server is running, your AI assistant will discover the Redfish tools automatically. You can ask it to perform tasks naturally:
- "List all servers in lab-a"
- "What is the power state of srv-dell-01?"
- "Get a hardware inventory for all servers with the 'gpu' tag"
- "Mount the Ubuntu ISO to srv-hpe-02 and boot from it once"
- "Update the firmware on srv-dell-01 using this URL: http://..."
- "Show me the MAC address table on lab1-switch"
- "Run 'show lldp neighbors' on the Junos switch"
Note on caching:
get_firmware_inventory,get_hardware_overview, andget_system_infocache their responses in memory to reduce BMC load. If results look stale after a hardware change, ask the assistant to runclear_server_cachefor the affected servers. TTL values are configurable inglobal_config.yaml.