Skip to main content
Glama
vinayulli

ServiceNow CMDB MCP Server

by vinayulli
README.md
# ServiceNow CMDB + Change Management MCP Server

This project exposes read-only CMDB and Change Management tools by default,
with explicitly guarded write tools for an authorized ServiceNow PDI.

## Capabilities

### CMDB

- List and search CIs.
- Search by manufacturer, model, serial number, IP address, and class.
- Read direct relationships from `cmdb_rel_ci`.
- Build dependency graphs with cycle protection.

### Change Management

- List and search change requests.
- Get a change by `CHG...` number or `sys_id`.
- Read change tasks.
- Read approval records.
- Read affected CIs from `task_ci`.
- Read impacted services/CIs from `task_cmdb_ci_service`.
- Retrieve valid next states.
- List standard change templates.
- Build a combined change + CMDB impact graph.
- Check whether important patch planning fields are populated.
- Optionally create/update changes and tasks in a PDI.
- Optionally add or remove Affected CIs.
- Optionally run risk calculation, conflict detection, impacted-service refresh,
  and the current user's approval/rejection action.

## 1. Setup

Windows PowerShell:

```powershell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
Copy-Item .env.example .env
```

macOS/Linux:

```bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
```

Edit `.env` with your PDI URL and credentials.

```env
SERVICENOW_INSTANCE=Instance URL
SERVICENOW_USERNAME=admin
SERVICENOW_PASSWORD=replace-with-your-password

SERVICENOW_ENABLE_WRITES=false
SERVICENOW_WRITE_CONFIRMATION=CONFIRM_PDI_WRITE

MCP_TRANSPORT=stdio
MCP_HOST=127.0.0.1
MCP_PORT=9000
```

Do not commit `.env`.

## 2. Test CMDB REST APIs

### Check connectivity

```powershell
python test_api.py health
```

### List CIs

List ten configuration items:

```powershell
python test_api.py list --limit 10
```

Paginate through CIs:

```powershell
python test_api.py list --limit 20 --offset 20
```

Filter by exact CI class:

```powershell
python test_api.py list --ci-class cmdb_ci_server --limit 20
```

### Search CIs

Search by manufacturer:

```powershell
python test_api.py search --manufacturer Cisco
```

Search by model name:

```powershell
python test_api.py search --model-name Catalyst
```

Search by model number:

```powershell
python test_api.py search --model-number C9300
```

Combine manufacturer and model:

```powershell
python test_api.py search `
  --manufacturer Cisco `
  --model-name Catalyst
```

Search by CI name:

```powershell
python test_api.py search --name server-prod
```

Search by serial number:

```powershell
python test_api.py search `
  --serial-number ABC123 `
  --match exact
```

Search by IP address:

```powershell
python test_api.py search `
  --ip-address 192.168.1.10 `
  --match exact
```

Search by FQDN:

```powershell
python test_api.py search `
  --fqdn server01.example.com `
  --match exact
```

Search by CI class and model:

```powershell
python test_api.py search `
  --ci-class cmdb_ci_server `
  --model-name PowerEdge
```

Supported match modes:

```text
contains
exact
starts_with
```

### Get one CI

Use a 32-character ServiceNow `sys_id` returned by list or search:

```powershell
python test_api.py get-ci YOUR_32_CHARACTER_SYS_ID
```

Query a class-specific CI table:

```powershell
python test_api.py get-ci `
  YOUR_32_CHARACTER_SYS_ID `
  --table cmdb_ci_server
```

### Get direct CI relationships

Get parent and child relationships:

```powershell
python test_api.py relationships YOUR_32_CHARACTER_SYS_ID
```

Only parent-side relationships:

```powershell
python test_api.py relationships `
  YOUR_32_CHARACTER_SYS_ID `
  --direction parents
```

Only child-side relationships:

```powershell
python test_api.py relationships `
  YOUR_32_CHARACTER_SYS_ID `
  --direction children
```

### Build a dependency graph

Build a two-level graph in both directions:

```powershell
python test_api.py tree `
  YOUR_32_CHARACTER_SYS_ID `
  --depth 2
```

Explore only parent-side dependencies:

```powershell
python test_api.py tree `
  YOUR_32_CHARACTER_SYS_ID `
  --depth 3 `
  --direction parents `
  --max-nodes 200
```

Explore underlying child-side dependencies:

```powershell
python test_api.py tree `
  YOUR_32_CHARACTER_SYS_ID `
  --depth 2 `
  --direction children `
  --max-nodes 100
```

Important traversal parameters:

| Parameter | Meaning |
|---|---|
| `depth` | Maximum number of relationship hops from the starting CI |
| `direction` | `parents`, `children`, or `both` |
| `max-nodes` | Maximum number of unique CIs returned |

An empty list normally means that the PDI does not contain matching sample CIs
or relationships. HTTP `401` usually means invalid credentials, while HTTP
`403` normally indicates an ACL or role issue.

## 3. Test Change Management reads

### Check connectivity

```powershell
python test_change_api.py health
```

### List and search changes

```powershell
python test_change_api.py list --limit 10
python test_change_api.py list --active-only
python test_change_api.py list --type normal
python test_change_api.py list --type emergency
python test_change_api.py search --short-description patch
python test_change_api.py search --number CHG0030001 --match exact
python test_change_api.py search --ci-name "Cisco Switch"
python test_change_api.py search --ci-sys-id YOUR_32_CHARACTER_CI_SYS_ID
```

### Read one change and its related data

```powershell
python test_change_api.py get CHG0030001
python test_change_api.py tasks CHG0030001
python test_change_api.py tasks CHG0030001 --active-only
python test_change_api.py approvals CHG0030001
python test_change_api.py approvals CHG0030001 --pending-only
python test_change_api.py affected-cis CHG0030001
python test_change_api.py impacted-services CHG0030001
python test_change_api.py next-states CHG0030001
python test_change_api.py readiness CHG0030001
python test_change_api.py bundle CHG0030001
```

### Search standard change templates

```powershell
python test_change_api.py templates --text network
```

The `state` filter may require the internal state value used by your change
model. Use `next-states` or inspect a returned record to see the correct values.

## 4. Test a guarded write in the PDI

Writes remain disabled until `.env` contains:

```env
SERVICENOW_ENABLE_WRITES=true
SERVICENOW_WRITE_CONFIRMATION=CONFIRM_PDI_WRITE
```

Create a normal change:

```powershell
python test_change_api.py create-normal `
  --short-description "Patch test server" `
  --description "PDI test change created through the API" `
  --implementation-plan "Take snapshot, install patch, restart service" `
  --backout-plan "Restore snapshot and previous package" `
  --test-plan "Verify service health and application smoke tests" `
  --confirmation CONFIRM_PDI_WRITE
```

Keep writes disabled when connecting the MCP server to any production instance.

## 5. Start the MCP server

### Stdio

Keep this in `.env`:

```env
MCP_TRANSPORT=stdio
```

Run:

```powershell
python mcp_server.py
```

### Streamable HTTP

Set:

```env
MCP_TRANSPORT=http
MCP_HOST=127.0.0.1
MCP_PORT=9000
```

Start the server:

```powershell
python mcp_server.py
```

The endpoint is:

```text
http://127.0.0.1:9000/mcp
```

Test it from another terminal:

```powershell
python test_mcp_client.py
```

You can also use MCP Inspector:

```powershell
npx -y @modelcontextprotocol/inspector
```

Connect it to:

```text
http://127.0.0.1:9000/mcp
```

## Important ServiceNow tables

| Purpose | Table |
|---|---|
| Configuration items | `cmdb_ci` |
| CI relationships | `cmdb_rel_ci` |
| Change requests | `change_request` |
| Change tasks | `change_task` |
| Approval records | `sysapproval_approver` |
| Affected CIs | `task_ci` |
| Impacted services/CIs | `task_cmdb_ci_service` |

## Notes

- CMDB and Change Management read operations are available by default.
- Change Management writes are disabled by default.
- Search field names and query operators are allowlisted.
- Arbitrary agent-generated encoded queries are not accepted.
- CMDB graphs can contain cycles, so dependency results use `nodes` and `edges`.
- A change identifier may be either a `CHG...` number or a 32-character `sys_id`.
- ServiceNow roles and ACLs still control every API operation.