A FastMCP server that exposes Cisco Catalyst Center automation as MCP tools for AI agents.
- 70 MCP tools for Catalyst Center workflows
- 3 Direct tools: Simplified interfaces for common operations
- 38 Workflow tools: Full control over Catalyst Center configuration
- 29 Config generators: Read-only tools for querying current state
- Async task execution with Redis persistence
- Multi-tenant support for multiple Catalyst Center instances
- Cluster support through YAML catalog configuration
- Version fallback for automatic Catalyst Center compatibility
- Schema-driven tool registry for easy maintenance
For production deployments, start with the Docker or Docker Compose workflows in the Installation section. The local Python quick start below is intended for development and lab environments.
# Python 3.11+
python3 --version
# Redis 6.0+
redis-cli ping # Should return "PONG"
# Python package and Ansible collection manifests
ls pyproject.toml requirements.yml# Clone repository
git clone https://github.com/cisco-en-programmability/catalyst_center_iac_mcpserver.git
cd catalyst_center_iac_mcpserver
# Create virtual environment
python3 -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install Python package and Ansible runtime separately
pip install --upgrade pip setuptools wheel
pip install "ansible-core>=2.16,<2.19"
pip install .
# Install Ansible collection
ansible-galaxy collection install -r requirements.yml# Create config directory
mkdir -p ~/.config/catalyst-center-iac-mcp
# Create environment file
cat > ~/.config/catalyst-center-iac-mcp/env << 'EOF'
REDIS_URL=redis://127.0.0.1:6379/0
RUNNER_ARTIFACT_ROOT=$HOME/.local/share/catalyst-center-iac-mcp/artifacts
CATALYSTCENTER_HOST=your-catalyst-center.example.com
CATALYSTCENTER_USERNAME=admin
CATALYSTCENTER_PASSWORD=your-password
CATALYSTCENTER_VERIFY_SSL=false
CATALYSTCENTER_PORT=443
CATALYSTCENTER_VERSION=2.6.0
SERVER_HOST=127.0.0.1
SERVER_PORT=8000
EOF
# Edit with your credentials
nano ~/.config/catalyst-center-iac-mcp/env# Load environment and start
export $(grep -v '^#' ~/.config/catalyst-center-iac-mcp/env | xargs)
catalyst-center-iac-mcpServer will be available at: http://127.0.0.1:8000
Step 1: Generate a secure API key
# Generate a random 32-character API key
API_KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
echo "Generated API Key: $API_KEY"
# Or use a custom key
API_KEY="my-secure-key-12345"Step 2: Configure the server
# Add to your .env file or export
export API_KEY_ENABLED=true
export API_KEYS="$API_KEY"
# Restart server to apply changes
catalyst-center-iac-mcpStep 3: Test with API key
# Health check with API key
curl -k https://127.0.0.1:8000/healthz \
-H "X-API-Key: $API_KEY"
# Expected response:
# {"status": "ok", "subject": "apikey:my-secur..."}
# List available tools with API key
curl -k -X POST https://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
# Call a tool with API key
curl -k -X POST https://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "list_catalyst_centers",
"arguments": {}
}
}'
# Check task status with API key
TASK_ID="your-task-id-here"
curl -k https://127.0.0.1:8000/iactasks/get/$TASK_ID \
-H "X-API-Key: $API_KEY"
# Get task logs with API key
curl -k https://127.0.0.1:8000/iactasks/get/$TASK_ID/logs \
-H "X-API-Key: $API_KEY"Multiple API Keys (for different clients):
# Generate multiple keys
KEY_CI_CD=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
KEY_MONITORING=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
KEY_BACKUP=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
# Configure server with multiple keys
export API_KEYS="$KEY_CI_CD,$KEY_MONITORING,$KEY_BACKUP"
# Each client uses their own key
curl -H "X-API-Key: $KEY_CI_CD" https://127.0.0.1:8000/mcp ...
curl -H "X-API-Key: $KEY_MONITORING" https://127.0.0.1:8000/mcp ...Custom Header Name:
# Use a custom header instead of X-API-Key
export API_KEY_HEADER="X-Custom-Auth"
# Restart server, then use custom header
curl -H "X-Custom-Auth: $API_KEY" https://127.0.0.1:8000/healthz# Health check
curl -k https://127.0.0.1:8000/healthz
# Initialize MCP session and capture the session ID
SESSION_ID=$(curl -k -s -D - https://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}' \
| awk 'BEGIN{IGNORECASE=1} /^mcp-session-id:/{print $2}' | tr -d '\r')
echo "Session ID: $SESSION_ID"
# List available tools with the returned session ID
curl -k -X POST https://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "mcp-session-id: ${SESSION_ID}" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'# Disable authentication
export API_KEY_ENABLED=false
export OAUTH_ENABLED=false
# Restart server, then test without headers
curl -k https://127.0.0.1:8000/healthz
curl -k -X POST https://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Simplified interfaces for common operations:
provision_site- Create/update sites with flat parametersdelete_site- Delete sites (destructive)configure_network_settings- Configure DHCP, DNS, NTP, SNMP, Syslog
Full control over configuration (pattern: <module> without the _workflow_manager suffix):
- Site management, ISE/AAA, templates, PnP, wireless
- Network profiles, assurance, application policy
- Discovery, inventory, provisioning, reports
- SD-Access fabric (8 tools), LAN automation, RMA
Read-only tools for querying state (pattern: <domain>_config):
- Query current configuration without making changes
- Default to
state: gatheredfor safe operations - Same categories as workflow tools
See tool_catalog.yaml and the MCP tools/list response for the complete tool inventory.
Most tools accept:
tenant_id: Routes through tenant-scoped environment variablescatalyst_center: Selects cluster fromcatalyst_center_clusters.yamlby name, label, location, or host
If both provided, catalyst_center takes precedence.
FastMCP: MCP tool registration and request handlingFastAPI: HTTP app for/mcp,/healthz, and/iactasks/get/{task_id}ansible-runner: the only execution path for Catalyst Center operationsRedis: task state, progress, results, and artifact indexingtransformers.py: flat tool input to nested workflow payload translationrunner_engine.py: module submission, ansible-runner lifecycle, artifact persistence
The server is stateless by design. Redis and runner artifacts hold the operational state, which makes multi-instance deployment practical.
Use catalyst_center_clusters.yaml to define multiple Catalyst Center clusters that the MCP server can target by name, label, location, or host. You can also mark exactly one enabled cluster with default: true so calls that omit catalyst_center use that cluster automatically.
Example:
catalyst_centers:
- name: "Portland"
label: "dev"
host: "Portland-center.domain.com"
version: "3.1.3.0"
location: "Portland"
enabled: true
default: true
- name: "San Jose"
label: "produsion"
host: "SanJose-catalyst.domain.com"
version: "2.3.7.9"
location: "San Jose"
enabled: falseCluster credentials stay in environment variables, not in YAML. For a cluster with label dev, set:
CC_DEV_USERNAME=automation
CC_DEV_PASSWORD=change-me
CC_DEV_VERIFY_SSL=false
CC_DEV_PORT=443
CC_DEV_VERSION=3.1.3.0Then pass catalyst_center="Portland" or catalyst_center="dev" in any tool call. If catalyst_center is omitted, the server falls back to the existing tenant_id and default CATALYSTCENTER_* environment variables. The older CATALYSTCENTER_CLUSTER_* names are still accepted for backward compatibility.
- Operating System: macOS, Linux (Ubuntu/Debian/RHEL/CentOS), or Windows WSL2
- Python: 3.11 or higher
- Redis: 6.0 or higher
- Ansible Collection:
cisco.catalystcenter2.6.0+ - Network: Reachability to Cisco Catalyst Center instance
Recommended production paths:
- Docker for single-node deployments
- Docker Compose HTTPS stack for Redis, NGINX, and the MCP server
Use the local Python installation steps below for development and lab environments.
Choose your platform and deployment mode:
# Install Homebrew (if not already installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Install Python 3.11+
brew install python@3.11
# Install Redis
brew install redis
brew services start redis
# Verify installations
python3 --version # Should be 3.11+
redis-cli ping # Should return "PONG"# Clone repository
git clone https://github.com/cisco-en-programmability/catalyst_center_iac_mcpserver.git
cd catalyst_center_iac_mcpserver
# Create virtual environment
python3 -m venv .venv
source .venv/bin/activate
# Install Python package and Ansible runtime separately
pip install --upgrade pip setuptools wheel
pip install "ansible-core>=2.16,<2.19"
pip install .
# Install Ansible collection
ansible-galaxy collection install -r requirements.yml# Create config directory
mkdir -p ~/.config/catalyst-center-iac-mcp
# Create environment file
cat > ~/.config/catalyst-center-iac-mcp/env << 'EOF'
# Redis Configuration
REDIS_URL=redis://127.0.0.1:6379/0
# Artifact Storage
RUNNER_ARTIFACT_ROOT=$HOME/.local/share/catalyst-center-iac-mcp/artifacts
# Catalyst Center Credentials
CATALYSTCENTER_HOST=your-catalyst-center.example.com
CATALYSTCENTER_USERNAME=admin
CATALYSTCENTER_PASSWORD=your-password
CATALYSTCENTER_VERIFY_SSL=false
CATALYSTCENTER_PORT=443
CATALYSTCENTER_VERSION=2.6.0
# Server Configuration
SERVER_HOST=127.0.0.1
SERVER_PORT=8000
EOF
# Edit with your actual credentials
nano ~/.config/catalyst-center-iac-mcp/env# Activate virtual environment
cd ~/path/to/catalyst_center_iac_mcpserver
source .venv/bin/activate
# Load environment variables
export $(grep -v '^#' ~/.config/catalyst-center-iac-mcp/env | xargs)
# Start server
catalyst-center-iac-mcpServer will be available at: http://127.0.0.1:8000
# Update package list
sudo apt-get update
# Install dependencies
sudo apt-get install -y \
python3.11 \
python3.11-venv \
python3-pip \
build-essential \
ca-certificates \
redis-server \
git
# Start Redis
sudo systemctl enable redis-server
sudo systemctl start redis-server# Create system user
sudo useradd --system --create-home \
--home-dir /opt/catalyst-center-iac-mcp \
--shell /usr/sbin/nologin \
catalystmcp
# Create directories
sudo mkdir -p /opt/catalyst-center-iac-mcp \
/var/lib/catalyst-center-iac-mcp/artifacts \
/etc/catalyst-center-iac-mcp
sudo chown -R catalystmcp:catalystmcp \
/opt/catalyst-center-iac-mcp \
/var/lib/catalyst-center-iac-mcp \
/etc/catalyst-center-iac-mcp
# Clone repository
cd /tmp
git clone https://github.com/cisco-en-programmability/catalyst_center_iac_mcpserver.git
sudo cp -r catalyst_center_iac_mcpserver/* /opt/catalyst-center-iac-mcp/
sudo chown -R catalystmcp:catalystmcp /opt/catalyst-center-iac-mcp
# Install as catalystmcp user
sudo -u catalystmcp bash << 'EOSU'
cd /opt/catalyst-center-iac-mcp
python3.11 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip setuptools wheel
pip install "ansible-core>=2.16,<2.19"
pip install .
ansible-galaxy collection install -r requirements.yml
EOSU# Create environment file
sudo tee /etc/catalyst-center-iac-mcp/catalyst-center-iac-mcp.env > /dev/null << 'EOF'
# Redis Configuration
REDIS_URL=redis://127.0.0.1:6379/0
# Artifact Storage
RUNNER_ARTIFACT_ROOT=/var/lib/catalyst-center-iac-mcp/artifacts
# Catalyst Center Credentials
CATALYSTCENTER_HOST=your-catalyst-center.example.com
CATALYSTCENTER_USERNAME=admin
CATALYSTCENTER_PASSWORD=your-password
CATALYSTCENTER_VERIFY_SSL=false
CATALYSTCENTER_PORT=443
CATALYSTCENTER_VERSION=2.6.0
# Server Configuration
SERVER_HOST=127.0.0.1
SERVER_PORT=8000
SERVER_WORKERS=4
EOF
# Edit with your credentials
sudo nano /etc/catalyst-center-iac-mcp/catalyst-center-iac-mcp.env
# Secure the file
sudo chmod 600 /etc/catalyst-center-iac-mcp/catalyst-center-iac-mcp.env
sudo chown catalystmcp:catalystmcp /etc/catalyst-center-iac-mcp/catalyst-center-iac-mcp.env# Manual start
sudo -u catalystmcp bash << 'EOSU'
cd /opt/catalyst-center-iac-mcp
source .venv/bin/activate
export $(grep -v '^#' /etc/catalyst-center-iac-mcp/catalyst-center-iac-mcp.env | xargs)
catalyst-center-iac-mcp
EOSU# Install EPEL repository
sudo dnf install -y epel-release
# Install dependencies
sudo dnf install -y \
python3.11 \
python3.11-devel \
python3-pip \
gcc \
git \
redis
# Start Redis
sudo systemctl enable redis
sudo systemctl start redisFollow the same installation steps as Ubuntu/Debian above, adjusting paths as needed.
- Install WSL2 with Ubuntu 22.04:
wsl --install -d Ubuntu-22.04- Open Ubuntu terminal and follow the Ubuntu installation instructions above.
For development on any platform:
# Clone repository
git clone https://github.com/cisco-en-programmability/catalyst_center_iac_mcpserver.git
cd catalyst_center_iac_mcpserver
# Create virtual environment
python3.11 -m venv .venv
source .venv/bin/activate # On Windows WSL2: source .venv/bin/activate
# Install Python package and Ansible runtime separately
pip install --upgrade pip setuptools wheel
pip install "ansible-core>=2.16,<2.19"
pip install -e ".[dev]"
# Install Ansible collection
ansible-galaxy collection install -r requirements.yml
# Run tests
python -m pytest -q
# Create local config
mkdir -p ~/.config/catalyst-center-iac-mcp
cp deploy/env/catalyst-center-iac-mcp.env.example ~/.config/catalyst-center-iac-mcp/env
nano ~/.config/catalyst-center-iac-mcp/env # Edit with your settingsREDIS_URL=redis://127.0.0.1:6379/0
RUNNER_ARTIFACT_ROOT=/var/lib/catalyst-center-iac-mcp/artifacts
CATALYSTCENTER_HOST=catalyst-center.example.com
CATALYSTCENTER_USERNAME=automation
CATALYSTCENTER_PASSWORD=change-me
CATALYSTCENTER_VERIFY_SSL=false
CATALYSTCENTER_PORT=443
CATALYSTCENTER_VERSION=2.6.0APP_NAME=catalyst_center_iac_mcp
APP_VERSION=0.1.0
SERVER_HOST=127.0.0.1
SERVER_PORT=8000
SERVER_WORKERS=2
PROXY_HEADERS=true
FORWARDED_ALLOW_IPS=127.0.0.1
HTTPS_ONLY=true
MCP_PATH=/mcp
MCP_TRANSPORT=http
MCP_STATELESS_HTTP=true
RUNNER_TIMEOUT_SECONDS=3600
TASK_TTL_SECONDS=86400
TASK_POLL_INTERVAL_MS=2000
CATALYST_CENTER_CLUSTERS_FILE=./catalyst_center_clusters.yamlMCP_STATELESS_HTTP=true is the default and is the correct mode for app-level MCP server registrations, including Codex app-level MCP servers. Set it to false only if you explicitly want session-backed HTTP behavior and your client supports user-specific MCP sessions.
If you run the server with MCP_STATELESS_HTTP=false and register it as an app-level MCP server, some clients may fail with errors like:
Trying to create user-specific connection for app-level server
That happens because session-backed MCP HTTP requires a per-user session, while app-level registrations are shared and stateless by design.
For the reports workflow tool, each generate_report entry must include a non-empty view field. If the report view is not known, ask the user to choose the view before executing the tool instead of guessing.
HTTPS_ONLY=true is the default. The server will refuse to start unless TLS_CERTFILE and TLS_KEYFILE are configured. Set HTTPS_ONLY=false only for local development or when HTTP is intentionally used behind another TLS terminator.
If you want the app itself to terminate HTTPS:
TLS_CERTFILE=/etc/ssl/certs/catalyst-center-iac-mcp/fullchain.pem
TLS_KEYFILE=/etc/ssl/private/catalyst-center-iac-mcp/privkey.pem
TLS_CA_CERTS=/etc/ssl/certs/ca-certificates.crt
SERVER_PORT=8443# Enable API key authentication
API_KEY_ENABLED=true
# Comma-separated list of valid API keys
API_KEYS=your-secret-key-12345,another-key-67890
# Optional: Custom header name (default: X-API-Key)
API_KEY_HEADER=X-API-KeyUsage:
curl -H "X-API-Key: your-secret-key-12345" \
http://localhost:8000/mcp \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Generate secure keys:
python3 -c "import secrets; print(secrets.token_urlsafe(32))"See docs/API_KEY_AUTHENTICATION.md for the complete guide.
OAUTH_ENABLED=true
OAUTH_ISSUER=https://auth.example.com
OAUTH_AUDIENCE=catalyst-center-mcp
OAUTH_JWKS_URL=https://auth.example.com/.well-known/jwks.json
ALLOW_ANONYMOUS_HEALTHCHECK=trueCATALYSTCENTER_ACME_HOST=acme-catc.example.com
CATALYSTCENTER_ACME_USERNAME=svc-acme
CATALYSTCENTER_ACME_PASSWORD=acme-secret
CATALYSTCENTER_ACME_VERIFY_SSL=true
CATALYSTCENTER_ACME_VERSION=2.6.0When invoking a tool, pass tenant_id="acme" to target that Catalyst Center instance.
Define the cluster inventory in catalyst_center_clusters.yaml, then provide credentials by cluster label or slug:
CC_DEV_USERNAME=svc-dev
CC_DEV_PASSWORD=dev-secret
CC_DEV_VERIFY_SSL=false
CC_DEV_PORT=443
CC_DEV_VERSION=3.1.3.0The older CATALYSTCENTER_CLUSTER_* variable names are still accepted for backward compatibility.
- Use
catalyst_centerwhen you want the model or caller to pick from a named Catalyst Center cluster inventory. - Use
tenant_idwhen you want the legacy tenant-scoped environment variable routing. - If both are provided,
catalyst_centertakes precedence. - If
catalyst_centeris omitted, the enabled cluster marked withdefault: trueis used automatically. - If no default is configured and there is exactly one enabled cluster, that single enabled cluster is used automatically.
- Use
list_catalyst_centersto inspect enabled cluster names, labels, locations, and hosts before selecting one.
An example environment file is included at catalyst-center-iac-mcp.env.example.
. /opt/catalyst-center-iac-mcp/.venv/bin/activate
export $(grep -v '^#' /etc/catalyst-center-iac-mcp/catalyst-center-iac-mcp.env | xargs)
catalyst-center-iac-mcpThis is acceptable for labs or small deployments:
export SERVER_HOST=0.0.0.0
export SERVER_PORT=8443
export TLS_CERTFILE=/etc/letsencrypt/live/mcp.example.com/fullchain.pem
export TLS_KEYFILE=/etc/letsencrypt/live/mcp.example.com/privkey.pem
catalyst-center-iac-mcpThen access:
https://mcp.example.com:8443/healthzhttps://mcp.example.com:8443/mcp
For production Linux deployments, use:
- the app on
127.0.0.1:8000 - NGINX or another reverse proxy for HTTPS
- systemd for process supervision
This is the better pattern because it gives you:
- TLS termination and certificate rotation
- reverse-proxy buffering control for MCP and SSE
- cleaner operational boundaries
- easier log and service management
Provided deployment examples:
- systemd unit: catalyst-center-iac-mcp.service
- NGINX config: catalyst-center-iac-mcp.conf
- Copy the example environment file:
sudo cp /opt/catalyst-center-iac-mcp/deploy/env/catalyst-center-iac-mcp.env.example /etc/catalyst-center-iac-mcp/catalyst-center-iac-mcp.env
sudo vi /etc/catalyst-center-iac-mcp/catalyst-center-iac-mcp.env- Copy the service file:
sudo cp /opt/catalyst-center-iac-mcp/deploy/systemd/catalyst-center-iac-mcp.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now catalyst-center-iac-mcp- Verify:
sudo systemctl status catalyst-center-iac-mcp
curl http://127.0.0.1:8000/healthz- Install NGINX and obtain a certificate.
- Copy the example config:
sudo cp /opt/catalyst-center-iac-mcp/deploy/nginx/catalyst-center-iac-mcp.conf /etc/nginx/conf.d/
sudo nginx -t
sudo systemctl reload nginx- Verify over HTTPS:
curl https://mcp.example.com/healthzImportant for MCP and SSE:
- reverse proxy buffering must stay disabled on
/mcp/ proxy_read_timeoutshould be large enough for long-running jobsX-Forwarded-Protoshould be passed through
Build:
docker build -t catalyst-center-iac-mcp .Run:
docker run -d \
--name catalyst-center-iac-mcp \
-p 8000:8000 \
-e SERVER_HOST=0.0.0.0 \
-e SERVER_PORT=8000 \
-e REDIS_URL=redis://redis:6379/0 \
-e CATALYSTCENTER_HOST=catalyst-center.example.com \
-e CATALYSTCENTER_USERNAME=automation \
-e CATALYSTCENTER_PASSWORD=change-me \
-e CATALYSTCENTER_VERSION=2.6.0 \
-v /var/lib/catalyst-center-iac-mcp:/var/lib/catalyst-center-iac-mcp \
catalyst-center-iac-mcpFor production HTTPS, put the container behind NGINX, Caddy, HAProxy, or a Kubernetes ingress.
For a single-host Linux deployment with Redis, the MCP app, and NGINX HTTPS termination, use the included compose.yaml.
This stack includes:
redisappnginx
It expects:
- an app environment file at
deploy/env/catalyst-center-iac-mcp.env - TLS certificates at:
deploy/certs/fullchain.pemdeploy/certs/privkey.pem
The Docker-specific NGINX config is catalyst-center-iac-mcp-docker.conf.
- Copy and edit the environment file:
cp deploy/env/catalyst-center-iac-mcp.env.example deploy/env/catalyst-center-iac-mcp.env
vi deploy/env/catalyst-center-iac-mcp.env- Place your TLS certificate and private key here:
deploy/certs/fullchain.pem
deploy/certs/privkey.pem- Start the full stack:
docker compose up -d --build- Verify:
docker compose ps
curl https://your-hostname/healthz- The MCP app listens on the internal Docker network at
app:8000 - NGINX exposes
80and443 - Redis persists data in the
redis-datavolume - ansible-runner artifacts persist in the
app-artifactsvolume - NGINX disables proxy buffering for
/mcp/so HTTP/SSE transport remains usable
After the env file and TLS files are in place:
docker compose up -d --buildThen register the MCP server in your client as:
{
"mcpServers": {
"catalyst-center": {
"url": "https://your-hostname/mcp",
"transport": "http"
}
}
}This section provides step-by-step instructions for common user workflows.
Step 1: Verify Installation
# Check server is installed
catalyst-center-iac-mcp --help
# Check Redis is running
redis-cli ping # Should return "PONG"Step 2: Configure Credentials
Edit your environment file with your Catalyst Center details:
# macOS
nano ~/.config/catalyst-center-iac-mcp/env
# Linux
sudo nano /etc/catalyst-center-iac-mcp/catalyst-center-iac-mcp.envUpdate these values:
CATALYSTCENTER_HOST=your-actual-catalyst-center.example.com
CATALYSTCENTER_USERNAME=your-username
CATALYSTCENTER_PASSWORD=your-passwordStep 3: Start the Server
# macOS
cd ~/path/to/catalyst_center_iac_mcpserver
source .venv/bin/activate
export $(grep -v '^#' ~/.config/catalyst-center-iac-mcp/env | xargs)
catalyst-center-iac-mcp
# Linux
sudo systemctl start catalyst-center-iac-mcpServer runs at: http://127.0.0.1:8000
Step 4: Verify Server is Running
# Health check
curl http://127.0.0.1:8000/healthz
# Should return: {"status":"healthy"}Add to claude_desktop_config.json:
Local HTTP:
{
"mcpServers": {
"catalyst-center": {
"url": "http://127.0.0.1:8000/mcp",
"transport": "http"
}
}
}Production HTTPS:
{
"mcpServers": {
"catalyst-center": {
"url": "https://mcp.example.com/mcp",
"transport": "http"
}
}
}curl -X POST http://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "provision_site",
"arguments": {
"site_type": "building",
"name": "San Jose HQ",
"parent_path": "Global/USA",
"latitude": 37.3382,
"longitude": -121.8863
}
}
}'curl -X POST http://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "configure_network_settings",
"arguments": {
"site_name": "Global/USA/San Jose HQ",
"dhcp_servers": ["10.10.10.10"],
"dns_servers": ["8.8.8.8", "8.8.4.4"],
"ntp_servers": ["time.nist.gov"],
"timezone": "America/Los_Angeles"
}
}
}'curl -X POST http://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "generate_site_config",
"arguments": {
"module_args_json": "{\"config\":{\"component_specific_filters\":{\"site\":[{\"parent_name_hierarchy\":\"Global/USA\",\"site_type\":[\"building\"]}]}}}"
}
}
}'Long operations return IaC task IDs. Poll for completion:
# Extract IaC task ID from response
IAC_TASK_ID="abc-123-def-456"
# Poll task status
curl http://127.0.0.1:8000/iactasks/get/$IAC_TASK_ID
# Response includes status, progress, and results
{
"iacTaskId": "abc-123-def-456",
"iacStatus": "completed",
"iacProgress": 100,
"iacTotal": 100,
"iacStatusMessage": "Task completed successfully",
"result": {...}
}Use the MCP tools get_task_stdout and get_task_log to read task artifacts.
- Pass
head_linesortail_lines, not both. - You do not need to send
tail_lines: nullwhen usinghead_lines. - If neither is provided, the server defaults internally to the last
100lines.
Examples:
{
"iac_task_id": "abc-123-def-456",
"head_lines": 200
}{
"iac_task_id": "abc-123-def-456",
"log_type": "catalystcenter",
"tail_lines": 500
}Use get_iac_task for a compact task summary and get_iac_taskdetail for the full stored task payload, including result, iacEvents, artifact paths, and progress fields.
See the examples directory for complete Python examples:
provision_site_example.py- Site hierarchy creationdiscovery_example.py- Device discovery with pollingfabric_workflow_example.py- SD-Access fabric setupnetwork_settings_example.py- Network settings configurationversion_fallback_example.py- Version normalization behavior
All examples support HTTPS with SSL verification and OAuth authentication.
Add tenant-specific credentials to environment:
This path is still supported for legacy tenant-scoped routing.
Add to your environment file:
CATALYSTCENTER_ACME_HOST=acme-catalyst.example.com
CATALYSTCENTER_ACME_USERNAME=acme-admin
CATALYSTCENTER_ACME_PASSWORD=acme-secretUse with tenant_id="acme" in tool calls.
For multi-cluster routing, use the catalyst_center argument with selectors defined in catalyst_center_clusters.yaml. Inspect configured clusters first with list_catalyst_centers.
For end-to-end request examples, see the examples directory and the module dependency guide.
Example:
curl -X POST http://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_catalyst_centers",
"arguments": {}
}
}'The MCP server automatically normalizes Catalyst Center versions for compatibility:
- 2.3.7.10 or 2.3.7 automatically falls back to 2.3.7.9
- 3.1.3.1 or 3.1.3.7 automatically falls back to 3.1.3.6
- Unsupported versions remain unchanged
This ensures any version within the same major.minor.patch family works with the nearest supported version.
# These all normalize to 2.3.7.9
CATALYSTCENTER_VERSION=2.3.7.10
CATALYSTCENTER_VERSION=2.3.7
# These all normalize to 3.1.3.6
CATALYSTCENTER_VERSION=3.1.3.1
CATALYSTCENTER_VERSION=3.1.3.7
CATALYSTCENTER_VERSION=3.1.3See the examples directory for complete workflows:
- Site provisioning
- Device discovery
- Network settings
- SD-Access fabric
- Multi-tenant operations (2 Catalyst Center instances)
- Version fallback (automatic version normalization)
For production, prefer:
- Docker Compose HTTPS stack for Redis, the MCP app, and NGINX
- Docker behind an external reverse proxy for simpler single-node deployments
- systemd with NGINX only when you intentionally manage a host-based Python install
See compose.yaml and the files under deploy/ for production configurations.
GET /healthz- Health checkPOST /mcp- MCP protocol endpointGET /iactasks/get/{task_id}- Task statusGET /iactasks/get/{task_id}/logs- Task logs and artifacts
See MODULE_DEPENDENCIES.md for comprehensive documentation on:
- Mandatory requirements for each workflow module
- How to get required information (device IPs, site IDs, etc.)
- Prerequisite data gathering using config generators
- Complete workflow examples with dependency chains
- Troubleshooting common prerequisite errors
Example: For compliance checks, you need either:
- Device IP (get from
generate_inventory_config()) - Site ID (get from
generate_site_config())
- Examples - Working code samples
- Tool Catalog - All available modules
- Schema Architecture - Tool registry design
- Contributing - Development guide
See CHANGELOG.md for version history, release notes, and upgrade guidance.
Missing tools: Reinstall Ansible collection
ansible-galaxy collection install cisco.catalystcenter:==2.6.0 --forceConnection issues: Verify Catalyst Center reachability and credentials
Redis errors: Ensure Redis is running and accessible
For the certified cisco.catalystcenter collection on Red Hat Automation Hub, use the Create issue action from the collection page instead of opening GitHub issues for collection certification support.
For this MCP server repository, open issues in GitHub Issues. For broader Catalyst Center platform guidance, see Cisco DevNet.
This repository is provided under the Cisco Sample Code License, Version 1.1.