Skip to main content
Glama
README.md
# Cisco MCP Server

Production-grade Model Context Protocol (MCP) server for executing Cisco CLI commands on network devices over SSH.

## Architecture

```
MCP Client (LLM)
       ↓
   Tool Selection
   ┌─────────────────────┐
   │ execute_exec_command │  ← show, ping, clear, traceroute, dir
   │ execute_config_command│  ← interface, hostname, router, acl
   └─────────────────────┘
       ↓
Validation Layer (validator)
       ↓
Connector Layer (cisco.py)
       ↓
SSH Transport (Scrapli + Paramiko)
       ↓
Cisco Device
```

## Features

- **Two MCP Tools**: LLM decides whether to call the exec or config tool
  - `execute_exec_command` — operational/exec mode commands (show, ping, clear, traceroute, etc.)
  - `execute_config_command` — configuration mode commands (interface, hostname, router, etc.)
- **Configuration Mode Management**: Automatically handles `enable → configure terminal → commands → end`
- **Pagination Handling**: Automatically disables pagination (`terminal length 0`) for exec commands
- **Dangerous Command Blocking**: Rejects `reload`, `write erase`, `debug`, etc.
- **Managed Command Rejection**: Rejects `conf t`, `enable`, `end`, `exit` (server manages these)
- **Structured Audit Logging**: JSON-line audit trail for every execution
- **Legacy SSH Support**: Paramiko transport for devices with older SSH (e.g., `diffie-hellman-group1-sha1`)
- **Vendor Extensible**: Abstract base connector supports future vendors (Juniper, Arista, etc.)

## Project Structure

```
mcp_server/
├── server.py                  # MCP server entry point (two tools registered)
├── config.py                  # Configuration management (env vars)
├── models.py                  # Pydantic request/response models
├── tools/
│   └── execute_commands.py    # ExecCommandTool + ConfigCommandTool
├── connectors/
│   ├── base.py                # Abstract base connector
│   └── cisco.py               # Cisco IOS/IOS-XE connector (Scrapli + Paramiko)
├── validation/
│   ├── classifier.py          # Command classifier (kept for reference/utility)
│   └── validator.py           # Input validator (dangerous cmds, device check)
├── inventory/
│   └── devices.yaml           # Device inventory
├── audit/
│   └── audit_logger.py        # Structured audit logger
├── utils/
│   ├── logger.py              # Logging configuration
│   └── exceptions.py          # Custom exceptions
└── tests/
    ├── test_classifier.py
    ├── test_validator.py
    ├── test_models.py
    └── test_execute_commands.py
```

## Setup

### Prerequisites

- Python 3.11+
- Access to Cisco devices via SSH

### Installation

```bash
# Clone and enter project directory
cd Cicsco_MCP_New

# Create virtual environment
python -m venv .venv
.venv\Scripts\activate  # Windows
# source .venv/bin/activate  # Linux/Mac

# Install dependencies
pip install -r requirements.txt
```

### Configuration

1. Copy the environment template:
```bash
copy .env.example .env
```

2. Edit `.env` with your credentials:
```env
CISCO_USERNAME=admin
CISCO_PASSWORD=your_password
CISCO_ENABLE_PASSWORD=your_enable_password
SSH_TIMEOUT=30
SSH_PORT=22
LOG_LEVEL=INFO
```

3. Edit `mcp_server/inventory/devices.yaml` to add your devices:
```yaml
devices:
  "10.10.10.1":
    hostname: "R1"
    platform: "cisco_iosxe"
    description: "Core Router"
```

> **Note**: If `devices.yaml` is empty or missing, the server allows connections to any device.

## Running the Server

### Standalone (stdio transport)
```bash
python -m mcp_server.server
```

### Testing with MCP Inspector
```bash
npx @modelcontextprotocol/inspector python -m mcp_server.server
```
Opens a browser UI where you can select either tool and test with real devices.

### VS Code / Claude Desktop Integration

Add to your MCP client configuration:

```json
{
  "mcpServers": {
    "cisco": {
      "command": "python",
      "args": ["-m", "mcp_server.server"],
      "cwd": "C:/path/to/Cicsco_MCP_New"
    }
  }
}
```

## Usage

### Tool 1: execute_exec_command

For operational/exec mode commands — the LLM calls this for show, ping, clear, traceroute, etc.

**Request:**
```json
{
  "device": "10.10.10.1",
  "commands": [
    "show version",
    "show ip interface brief"
  ]
}
```

**Response:**
```json
{
  "success": true,
  "mode": "exec",
  "device": "10.10.10.1",
  "execution_time": 2.31,
  "results": [
    {
      "command": "show version",
      "output": "Cisco IOS XE Software, Version 17.03.04a..."
    },
    {
      "command": "show ip interface brief",
      "output": "Interface              IP-Address      OK? Method Status..."
    }
  ]
}
```

### Tool 2: execute_config_command

For configuration mode commands — the LLM calls this for interface, routing, ACL changes, etc.
The server automatically handles `enable → configure terminal → commands → end`.

**Request:**
```json
{
  "device": "10.10.10.1",
  "commands": [
    "interface Loopback100",
    "ip address 10.100.0.1 255.255.255.0",
    "no shutdown"
  ]
}
```

**Response:**
```json
{
  "success": true,
  "mode": "config",
  "device": "10.10.10.1",
  "execution_time": 1.92,
  "results": [
    {
      "command": "interface Loopback100",
      "status": "success"
    },
    {
      "command": "ip address 10.100.0.1 255.255.255.0",
      "status": "success"
    },
    {
      "command": "no shutdown",
      "status": "success"
    }
  ]
}
```

### Error Responses

**Authentication failure:**
```json
{
  "success": false,
  "device": "10.10.10.1",
  "error": "Authentication failed for device 10.10.10.1."
}
```

**Blocked dangerous command:**
```json
{
  "success": false,
  "device": "10.10.10.1",
  "error": "Blocked dangerous command: 'reload'"
}
```

**Managed command rejected:**
```json
{
  "success": false,
  "device": "10.10.10.1",
  "error": "Command 'configure terminal' is managed automatically by the server. Do not include it in the command list."
}
```

## Running Tests

```bash
pytest mcp_server/tests/ -v
```

## Security

- All inputs are validated before any device connection
- Dangerous commands are blocked at the validation layer
- No shell commands are executed on the MCP server host
- Credentials are loaded from environment variables (never hardcoded)
- SSH connections use secure authentication
- Audit logs record every execution for compliance

## Extending for Other Vendors

To add support for a new vendor (e.g., Juniper):

1. Create `mcp_server/connectors/juniper.py`
2. Implement the `BaseConnector` interface
3. Update device inventory with platform type

The tool, validation, and audit layers remain unchanged.

## License

Internal use only.