Skip to main content
Glama

snow-mcp: read-only ServiceNow RITM server

An MCP server that lets Claude (or any MCP client) read a ServiceNow requested item (RITM): its details, catalog variables, approvals, SLAs, comments and work notes, and attachments. It can also start from a catalog task (SCTASK) and resolve its parent RITM.

It has no write path: the ServiceNow client only issues GET requests, so it cannot approve, update or create anything.

It runs as a hardened systemd service. The ServiceNow password and the MCP access token are sealed with the machine's TPM, and systemd decrypts them into memory only when the service starts. Secrets never sit in plain-text files or environment variables.

Tools

Tool

Returns

get_ritm_full(number)

Everything below except attachment contents, in one call

get_ritm(number)

Main attributes, parent REQ, link to the record

get_ritm_variables(number)

Catalog form answers

get_ritm_approvals(number)

Approvers and states on the RITM and parent REQ, group approvals

get_ritm_slas(number)

SLA definitions, stage, breach flag, time left

get_ritm_activity(number)

Comments and work notes

list_ritm_attachments(number)

Attachments on the RITM and REQ, with IDs

get_attachment(attachment_id)

Text of PDF/DOCX/XLSX/text files, or the image itself

get_sctask(number, include_ritm=True)

Catalog task attributes, its parent RITM number, and optionally the RITM's details

Related MCP server: ServiceNow MCP Server

Requirements

  • Server: Linux with systemd 250 or newer and a TPM 2.0 chip (for example Ubuntu 24.04 or Debian 12), plus Python 3.10+ with venv support (sudo apt install python3-venv on Ubuntu/Debian).

  • ServiceNow: an integration account with basic authentication and read access to these tables: sc_req_item, sc_request, sc_task, sc_item_option_mtom, sysapproval_approver, sysapproval_group, task_sla and sys_attachment. Tables the account can't read return a 403 note in the matching section. The rest still works.

Installation

Run these on the server from a clone of this repository.

# 1. Install code, virtual environment, config file and systemd unit
sudo ./deploy/install.sh

# 2. Set your instance URL and integration user
sudo nano /etc/snow-mcp/snow-mcp.env

# 3. Seal the secrets (input is read without echo and never written to disk)
sudo ./deploy/seal-credential.sh snow_pass               # the ServiceNow password
sudo ./deploy/seal-credential.sh mcp_token --generate    # a new random MCP access token

# 4. Start the service and enable it at boot
sudo systemctl enable --now snow-mcp

# 5. Check it
systemctl status snow-mcp
journalctl -u snow-mcp -n 30
curl -s localhost:8765/health                            # {"status":"ok"}

Show the generated token once so you can put it in your MCP client config:

sudo systemd-creds decrypt --name=mcp_token /etc/credstore.encrypted/snow-mcp.mcp_token.cred -; echo

Connecting a client

The service listens on 127.0.0.1:8765 only. The MCP endpoint is /mcp, and every request except /health must send Authorization: Bearer <token>.

To reach it from another machine, put an HTTPS front end in front of the port: a reverse proxy (nginx, Caddy), a Tailscale service, or an SSH tunnel.

Example Claude Desktop config using mcp-remote:

{
  "mcpServers": {
    "snow_mcp": {
      "command": "npx",
      "args": ["mcp-remote", "https://your-host.example.com/mcp",
               "--header", "Authorization:${AUTH}"],
      "env": { "AUTH": "Bearer <your-token>" }
    }
  }
}

Then ask Claude about a real RITM or SCTASK to confirm it works end to end.

Layout on the server

Path

What

/opt/snow-mcp/app

Application code (read-only to the service)

/opt/snow-mcp/venv

Python virtual environment

/etc/snow-mcp/snow-mcp.env

Non-secret settings: instance URL, user name, limits

/etc/credstore.encrypted/snow-mcp.*.cred

TPM-sealed password and MCP token

/etc/systemd/system/snow-mcp.service

The unit

Configuration

Settings in /etc/snow-mcp/snow-mcp.env (see deploy/snow-mcp.env.example):

Variable

Default

Meaning

SNOW_INSTANCE_URL

required

e.g. https://yourinstance.service-now.com

SNOW_USER

required

Integration account user name

MAX_ATTACHMENT_MB

15

Largest attachment get_attachment will download

MAX_TEXT_CHARS

150000

Extracted text is cut off after this many characters

SAVE_DIR

off

Keep copies of downloaded attachments; must be under /var/lib/snow-mcp/

Restart the service after changing settings.

Day-to-day

sudo systemctl restart snow-mcp               # after changing settings or credentials
journalctl -u snow-mcp -f                      # follow logs
systemd-analyze security snow-mcp             # hardening score (lower is better)

# Update code: pull the new version, then
sudo ./deploy/install.sh                       # keeps config and credentials, restarts if running

# Change the ServiceNow password
sudo ./deploy/seal-credential.sh snow_pass
sudo systemctl restart snow-mcp

# Rotate the MCP token
sudo ./deploy/seal-credential.sh mcp_token --generate
sudo systemd-creds decrypt --name=mcp_token /etc/credstore.encrypted/snow-mcp.mcp_token.cred -; echo
sudo systemctl restart snow-mcp                # then update your MCP client with the new token

To reuse an existing token instead of generating one, run sudo ./deploy/seal-credential.sh mcp_token and paste it at the prompt.

Notes

  • After a BIOS/firmware update or a Secure Boot change, the TPM may refuse to decrypt the credentials. The service then fails to start with a credential error in the journal. Fix it by re-running both seal-credential.sh commands.

  • What the TPM sealing protects against: copies of the disk, backups, sync tools or a git push picking up the files, and other users or services on the server. It does not stop someone with root on the running machine, so keep SSH key-only and root access tight.

  • If the service won't start and the journal mentions a memory-protection error, a dependency needs writable executable memory. Comment out MemoryDenyWriteExecute=yes in the unit, then run sudo systemctl daemon-reload && sudo systemctl restart snow-mcp.

  • If a section of get_ritm_full returns {"error": "... 403 ..."}, the integration account lacks read access to that table. The rest still works.

Local development

Without systemd, secrets fall back to the SNOW_PASS / MCP_TOKEN environment variables (or to files named by SNOW_PASS_FILE / MCP_TOKEN_FILE).

python3 -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
export SNOW_INSTANCE_URL=https://yourinstance.service-now.com SNOW_USER=integration.user
export SNOW_PASS=... MCP_TOKEN=...
python server.py                               # serves http://127.0.0.1:8765/mcp

License

MIT, see LICENSE.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    Not graded
    maintenance
    Enables Claude to interact with ServiceNow instances through the ServiceNow API. Supports comprehensive ServiceNow operations including incident management, service catalog management, change requests, user management, and workflow automation through natural language.
    82
    MIT
  • A
    license
    Not graded
    quality
    Not graded
    maintenance
    Enables Claude to interact with ServiceNow instances for incident management, service catalog operations, change requests, knowledge base management, user administration, and agile project workflows through various authentication methods.
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides AI assistants with read access to ServiceNow instances to aid in building and debugging applications. It enables users to query tables, retrieve specific records, and inspect table schemas using standard ServiceNow encoded query strings.
    -