Skip to main content

Production-grade, read-only MCP server for ServiceNow

Project description

snow-mcp-server

CI License Python 3.11+

read-only ServiceNow tools driven over MCP

A production-grade, read-only MCP server for ServiceNow: query any table, fetch a single record, full-text search published knowledge articles, and discover a table's schema — from Claude Desktop, Claude Code, or any MCP client — with throttling handled properly (429/503 retried honoring Retry-After) and no live instance required to run the test suite.

Read-only by construction: the HTTP layer this server is built on (snow_mcp.client.SnowClient) exposes exactly one verb — get. There is no post, put, patch, or delete method anywhere in the codebase, so there is nothing in the tool layer that could ever issue a write, no matter what a caller asks for.

The server can read whatever the account it's configured with can read. ServiceNow ACLs are the actual security boundary — this server enforces nothing beyond what the account itself is permitted to see. Use a dedicated, least-privilege read account, not an admin account, especially against a production instance. Row-level ACLs can also filter individual records out of a table's results and its counts — a query that should match N rows may legitimately show fewer, silently, if the account can't see all of them.

snow-mcp-server is not affiliated with, endorsed by, or sponsored by ServiceNow, Inc.

Quickstart

Requires uv and a ServiceNow instance to point at. The easiest way to get one is a free Personal Developer Instance (PDI) from developer.servicenow.com — no cost, ready in a few minutes.

Once you have an instance, create a dedicated, least-privilege user for this server rather than reusing an admin account (see the warning above) — or, on a throwaway PDI where that's overkill, the built-in admin user is fine to start with.

uvx snow-mcp-server

That starts the server over stdio. Until snow-mcp-server is published to PyPI, run it from a local checkout instead:

uv run --directory <path-to-checkout> snow-mcp-server
# or, straight from GitHub without cloning:
uvx --from git+https://github.com/inogen-ai/snow-mcp-server snow-mcp-server

In practice you'll point an MCP client at it instead of running it directly — for Claude Code:

Note: until snow-mcp-server is published to PyPI, replace uvx snow-mcp-server in the commands below with the from-source form uvx --from git+https://github.com/inogen-ai/snow-mcp-server snow-mcp-server (see the run-from-checkout note above).

claude mcp add servicenow \
  -e SNOW_MCP_INSTANCE_URL=https://dev12345.service-now.com \
  -e SNOW_MCP_USERNAME=<your-username> \
  -e SNOW_MCP_PASSWORD=<your-password> \
  -- uvx snow-mcp-server

For Claude Desktop, add to claude_desktop_config.json:

{
  "mcpServers": {
    "servicenow": {
      "command": "uvx",
      "args": ["snow-mcp-server"],
      "env": {
        "SNOW_MCP_INSTANCE_URL": "https://dev12345.service-now.com",
        "SNOW_MCP_USERNAME": "<your-username>",
        "SNOW_MCP_PASSWORD": "<your-password>"
      }
    }
  }
}

Tools

Tool Parameters Returns
query_records table: str, query: str = "", limit: int = 20, fields: str = "" Records from any table (e.g. incident, problem, change_request, sys_user) matching the encoded query, restricted to fields (comma-separated) when given. sys_id is always present; number and short_description/name are prioritized when the table has them. Says plainly when more records are available than limit returned.
get_record table: str, sys_id: str One full record (all fields, display values) — typically the sys_id from a prior query_records or search_knowledge call.
search_knowledge query: str, limit: int = 10 Full-text search across published knowledge base articles (kb_knowledge) — number, short_description, an HTML-stripped snippet of the article body, and sys_id per hit. query is plain search text, not an encoded query. The published-only filter is best-effort relevance filtering, not a security boundary — ServiceNow ACLs are the boundary, same as every other tool here.
list_table_fields table: str The fields (element name, column label, internal type) defined on a table — schema discovery so you know what's queryable before writing an encoded query. Capped at 200 fields per table. Reads sys_dictionary, which a hardened instance may ACL — grant the account read access to it, or expect empty results.

Encoded-query cheat sheet

query_records's query parameter is a ServiceNow encoded query, the same syntax the platform's own list views use:

Syntax Meaning
^ AND — active=true^priority=1
^OR OR — priority=1^ORpriority=2
field=value Exact match
fieldLIKEvalue Partial/substring match
123TEXTQUERY321=text Full-text search over the table (what search_knowledge uses internally against kb_knowledge)

123TEXTQUERY321 relies on ServiceNow's Zing full-text indexing, which is on by default for kb_knowledge but may not be enabled (or may lag behind recent writes) for other tables — if a full-text query on a non-kb_knowledge table comes back empty unexpectedly, that's the first thing to check.

fields (a separate parameter, comma-separated) restricts which columns come back — sys_id is always included even if you don't ask for it, so results always compose into a follow-up get_record call.

Environment variables

All settings are prefixed SNOW_MCP_ and can be set in the environment or a .env file (see .env.example).

Variable Default Purpose
SNOW_MCP_INSTANCE_URL (unset, required) Your instance's bare origin, e.g. https://dev12345.service-now.com — must be https, no path/query/fragment.
SNOW_MCP_USERNAME (unset) Basic-auth username. Required together with SNOW_MCP_PASSWORD unless SNOW_MCP_TOKEN is set.
SNOW_MCP_PASSWORD (unset) Basic-auth password.
SNOW_MCP_TOKEN (unset) OAuth bearer token, sent as Authorization: Bearer. Mutually exclusive with SNOW_MCP_USERNAME/SNOW_MCP_PASSWORD — set exactly one auth mode.
SNOW_MCP_ITEM_LIMIT 20 Default max records returned per query_records/search_knowledge call before "more available" is reported.
SNOW_MCP_TIMEOUT_SECONDS 30.0 HTTP timeout (seconds) per ServiceNow request.

Exactly one auth mode must be configured — basic (SNOW_MCP_USERNAME + SNOW_MCP_PASSWORD) or bearer (SNOW_MCP_TOKEN). Setting both, or neither, fails startup immediately with a message naming the env vars to fix, rather than failing obscurely on the first tool call.

Security notes

  • Read-only by construction, not by policy: the HTTP client this server is built on has no write method to call in the first place. See the warning at the top of this README — the account's ServiceNow ACLs, not this server, decide what's actually readable.
  • Throttling handled. 429/503 responses are retried honoring the instance's Retry-After header (clamped to at most 60s so a hostile or buggy value can't hang the process), falling back to exponential backoff (1→2→4s) when no header is sent, capped at 3 retries.
  • Credentials never appear in error messages, logs, or exceptions raised to an MCP client — failures are reduced to plain, credential-free sentences before they leave the client layer.
  • Not affiliated with, endorsed by, or sponsored by ServiceNow, Inc.

Development

Requires Python 3.11+ and uv.

uv sync
uv run pytest -q
uv run ruff check .

No live ServiceNow instance is needed for the test suite — the Table API is faked at the httpx.MockTransport boundary. See docs/manual-verification.md for the live-PDI check a maintainer runs before releases.

Contributing

Contributions welcome — see CONTRIBUTING.md for dev setup and PR expectations, and SECURITY.md for reporting vulnerabilities privately.


Not affiliated with, endorsed by, or sponsored by ServiceNow, Inc.

Part of InoGen's open-source portfolio: kilnworks (self-hostable RAG assistant) and the read-only MCP connectors m365, servicenow, salesforce, and hubspot.

Built and maintained by InoGen.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

snow_mcp_server-0.1.0.tar.gz (2.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

snow_mcp_server-0.1.0-py3-none-any.whl (20.5 kB view details)

Uploaded Python 3

File details

Details for the file snow_mcp_server-0.1.0.tar.gz.

File metadata

  • Download URL: snow_mcp_server-0.1.0.tar.gz
  • Upload date:
  • Size: 2.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.29 {"installer":{"name":"uv","version":"0.9.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for snow_mcp_server-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0b5764d01a0658fd58ce88598e9589c87630b4278ac8bd68aa877d8830989a6f
MD5 0ebb5cb1ae6c4a34b3369531efbd66d2
BLAKE2b-256 473077017a53686ae2fcfcf0bb45a7f8c34aedb4120a7ea0a6c6a052e9a8efc7

See more details on using hashes here.

File details

Details for the file snow_mcp_server-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: snow_mcp_server-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 20.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.29 {"installer":{"name":"uv","version":"0.9.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for snow_mcp_server-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 65a28498aa602884131739d0234c567d56b3497ab24be000aa21cf2237726166
MD5 603d8a93344c6406531eb34e94d6948f
BLAKE2b-256 4077e6a63b8220ca21a403beb3ad329b2ba6fe009b4766f59a814928c41c3b88

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page