{
  "markdown": "# servicenow-mcp-ai — ServiceNow MCP Server\n\n| [![npm version](https://img.shields.io/npm/v/servicenow-mcp-ai?style=flat-square&logo=npm&logoColor=white&label=npm)](https://www.npmjs.com/package/servicenow-mcp-ai) | [![npm downloads](https://img.shields.io/npm/dm/servicenow-mcp-ai?style=flat-square&logo=npm&logoColor=white&label=downloads)](https://www.npmjs.com/package/servicenow-mcp-ai) | [![node](https://img.shields.io/node/v/servicenow-mcp-ai?style=flat-square&logo=nodedotjs&logoColor=white&label=node)](https://www.npmjs.com/package/servicenow-mcp-ai) | [![tools](https://img.shields.io/badge/tools-67-blue?style=flat-square)](https://github.com/IvanBBaev/servicenow-mcp-ai#tools) | [![License: MIT](https://img.shields.io/npm/l/servicenow-mcp-ai?style=flat-square&color=blue&label=license)](LICENSE) |\n| :--: | :--: | :--: | :--: | :--: |\n| [![CI](https://img.shields.io/github/actions/workflow/status/IvanBBaev/servicenow-mcp-ai/ci.yml?branch=main&style=flat-square&logo=githubactions&logoColor=white&label=CI)](https://github.com/IvanBBaev/servicenow-mcp-ai/actions/workflows/ci.yml) | [![coverage](https://img.shields.io/codecov/c/github/IvanBBaev/servicenow-mcp-ai/main?style=flat-square&logo=codecov&logoColor=white&label=coverage)](https://codecov.io/gh/IvanBBaev/servicenow-mcp-ai) | [![last commit](https://img.shields.io/github/last-commit/IvanBBaev/servicenow-mcp-ai?style=flat-square&logo=git&logoColor=white&label=last%20commit)](https://github.com/IvanBBaev/servicenow-mcp-ai/commits/main) | [![MCP](https://img.shields.io/badge/MCP-server-orange?style=flat-square)](https://modelcontextprotocol.io) | [![Known Vulnerabilities](https://snyk.io/test/npm/servicenow-mcp-ai/badge.svg)](https://snyk.io/test/npm/servicenow-mcp-ai) |\n\n📖 **[Documentation site →](https://ivanbbaev.github.io/servicenow-mcp-ai/)**\n\nA [Model Context Protocol](https://modelcontextprotocol.io) server that lets an\nMCP client (VS Code, Claude Desktop, etc.) run commands against a **ServiceNow**\ninstance through its REST APIs — Table, Aggregate, Attachment, Import Set, Batch\nand CMDB, plus the Service Catalog, Change Management and Knowledge plugin APIs.\nCredentials are kept in a local env file and can be updated at runtime through a tool.\n\n> **Upgrading from 1.x?** v2.0 makes writes **plan-by-default**: `create`/`update`/`delete`\n> and the other record-write tools return a non-mutating preview unless you pass\n> `apply: true` (or set `SN_WRITE_MODE=apply` to restore the v1 \"execute immediately\"\n> behaviour). See the [CHANGELOG](CHANGELOG.md) → 2.0.0 for the full migration note.\n\n**Contents:** [Quick demo](#quick-demo) · [Features](#features) ·\n[Requirements](#requirements) · [Setup](#setup) ·\n[Configure credentials](#configure-credentials) · [Run / debug](#run--debug) ·\n[Develop](#develop) · [Tools](#tools) · [Resources](#resources) ·\n[Prompts](#prompts) · [Project structure](#project-structure) ·\n[Security notes](#security-notes) · [Project documentation](#project-documentation) ·\n[Support](#support)\n\n_Built and maintained in my own time — if it helps, a\n[GitHub Sponsors](https://github.com/sponsors/IvanBBaev) tip keeps it going.\nFull [Support](#support) options are near the end._\n\n## Quick demo\n\nThree things the platform makes hard, one call each. Point your MCP client at an\ninstance ([Setup](#setup)) and ask:\n\n**1. \"Where is this field actually used?\"** — every script, business rule, client\nscript, UI policy/action and ACL that touches it, as JSON or a Mermaid graph. The\nIDE-grade _find usages_ ServiceNow has no button for:\n\n```jsonc\n// servicenow_where_used\n{\n  \"kind\": \"field\", // \"table\" | \"field\" | \"script\"\n  \"name\": \"u_cost_center\",\n  \"mermaid\": true, // also render a reference graph\n}\n```\n\n**2. \"What runs when I save this record?\"** — the full automation chain in\nexecution order (display → before → after → async business rules, then flows,\nworkflows and notifications), each with its condition — a logical test that runs\n**nothing**:\n\n```jsonc\n// servicenow_trace_table_event\n{\n  \"table\": \"incident\",\n  \"operation\": \"update\", // insert | update | delete | query\n}\n```\n\n**3. \"What drifted between dev and prod?\"** — a Markdown diff of tables, columns,\nscripts (by SHA-256) and plugins between two configured profiles, with a CI-friendly\nexit code so a pipeline can block a risky deploy:\n\n```bash\nservicenow-mcp-ai drift dev prod   # report on stdout; exit 1 on drift, 0 if clean\n```\n\nAll three are **read-only** and work against any instance — including a free PDI —\nwith the model and client of your choice.\n\n## Features\n\n- Full **Table API**: query, read, create, update and delete records on **any**\n  table, with encoded queries, field selection and pagination.\n- Extra ServiceNow APIs: **Aggregate** (Stats), **Attachment**\n  (list/upload/download/delete), **Import Set**, **Batch** (many REST calls in a\n  single request), plus table/column **metadata** (`sys_db_object`,\n  `sys_dictionary`).\n- Process & plugin APIs: **CMDB** (class-aware CI CRUD + meta via IRE),\n  **Service Catalog** (browse/order items), **Change Management** (typed\n  creation + conflict detection) and **Knowledge** (article search).\n  Plugin-scoped APIs report clearly when not active on the instance.\n- **Script intelligence**: read and search the instance's own code (business\n  rules, script includes, client scripts, UI policies/actions, scheduled jobs,\n  transform/REST scripts, ACLs) and get a table's full automation picture — all\n  read-only over the Table API.\n- **Flow tracing & code checking** (Phase 8): deterministically trace what a\n  table operation runs (`flows` package — business rules, flows, workflows and\n  notifications, in order, with a Mermaid flowchart), read Flow Designer flows\n  and run history, and lint scripts against a local rule set with an aggregate\n  code-health report (`codecheck`). Run ATF tests via the CI/CD API (`atf`,\n  opt-in, non-default — the run tools execute on the instance).\n- **Self-documentation**: a local Markdown knowledge base (read/write/search) plus\n  deterministic Mermaid generators (ER diagrams from references, record-lifecycle\n  flowcharts from business rules) so the server builds durable, reusable context.\n- **Prompts**: ready-made workflows (incident triage, change impact analysis,\n  document a table) that orchestrate the tools.\n- **Tool packages**: load only the tool groups you need via `SN_TOOL_PACKAGES`\n  (default profile `core`; `all` enables everything).\n- **Basic** or **OAuth 2.0** authentication over HTTPS; the password/token is\n  never echoed back.\n- Least-privilege controls: table allow/deny lists and a global read-only mode.\n- Resilience: per-request timeout, retry with backoff and `Retry-After`, SSRF\n  guard, and a result-size guard.\n- MCP **tool annotations** and **resources**, structured error payloads, and\n  structured logging on stderr.\n- Credentials in an env file (project, `~/.config`, or `SN_ENV_FILE`), updatable\n  at runtime via `servicenow_set_credentials`.\n\n## Requirements\n\n- Node.js 20+ (enforced: `engines` + a runtime guard with a clear message;\n  the project targets the version in `.nvmrc`).\n\n## Setup\n\nFrom source (for development):\n\n```bash\nnpm install\nnpm run build\n```\n\nOr run the published package directly, without cloning:\n\n```bash\nnpx servicenow-mcp-ai\n```\n\nRegister it with an MCP client (Claude Desktop, VS Code Chat, the Inspector…) by\npointing the server command at `npx`:\n\n```json\n{\n  \"mcpServers\": {\n    \"servicenow\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"servicenow-mcp-ai\"]\n    }\n  }\n}\n```\n\n**Claude Code plugin** (zero-config — installs the server wired up):\n\n```bash\n/plugin marketplace add IvanBBaev/servicenow-mcp-ai\n/plugin install servicenow-mcp-ai\n```\n\n**VS Code** — install the **ServiceNow MCP** extension from the Marketplace\n(`code --install-extension ivanbbaev.servicenow-mcp-ai`); it registers the server\nin Copilot Chat (agent mode) automatically, no manual `mcp.json`. Source:\n[extension/](extension/).\n\nCredentials are read from `~/.config/servicenow-mcp-ai/.env` (or real environment\nvariables) — see below.\n\n### Quickstart\n\nThe fastest path is three lines of Basic auth — set these (in the env file or the\nreal environment) and you are connected:\n\n```dotenv\nSN_INSTANCE=dev12345.service-now.com\nSN_USER=your.username\nSN_PASSWORD=your-password\n```\n\nEverything else is optional tuning; see the full\n[Environment variables](#environment-variables) reference for the rest.\n\n> **Past a quick try, prefer OAuth over a stored password.** For anything shared or\n> long-lived, run the one-time `npx servicenow-mcp-ai login` instead — it stores a\n> refresh token, not your password. See\n> [Configure credentials](#configure-credentials) → _OAuth 2.1_.\n\n### Verify your setup\n\nOnce the three variables are set, confirm the connection before you start:\n\n1. Run the `servicenow_test_connection` tool — it reads one `sys_user` record and\n   reports `ok`, HTTP status and latency.\n2. Run `servicenow_check_capabilities` — it previews which admin-restricted `sys_*`\n   tables the connected user can actually read.\n\nOr do both from the shell in one shot:\n\n```bash\nnpx servicenow-mcp-ai doctor   # checks credentials, reachability and capabilities\n```\n\n## Configure credentials\n\nCredentials live in `.env` at the project root (git-ignored):\n\n```dotenv\nSN_INSTANCE=your-instance.service-now.com\nSN_USER=your.username@example.com\nSN_PASSWORD=your-password\n```\n\n`SN_INSTANCE` accepts `dev12345`, `dev12345.service-now.com` or a full `https://` URL.\n\nYou can also set or change them at runtime by calling the\n`servicenow_set_credentials` tool — the new values are written straight back to the env file.\n\nThe env file is resolved in this order: `SN_ENV_FILE`, then\n`~/.config/servicenow-mcp-ai/.env` (XDG) if present, then the project-root `.env`.\nA global/`npx` install therefore writes to your user config rather than into\n`node_modules`. Real environment variables always take precedence over the file.\n\n### OAuth 2.1 (Authorization Code + PKCE) — recommended\n\nRegister an **Authorization Code** OAuth API endpoint in ServiceNow with a\nloopback redirect URL (e.g. `http://localhost:53682/callback`), set\n`SN_OAUTH_CLIENT_ID` (and `SN_OAUTH_CLIENT_SECRET` for a confidential client),\nthen run the one-time interactive login:\n\n```bash\nnpx servicenow-mcp-ai login\n```\n\nIt opens the browser, you approve, and the obtained **refresh token** is stored\nin your env file. The server then runs non-interactively (refresh_token grant) —\nno password is ever stored. PKCE (S256) is always used.\n\n> The OAuth 2.0 **password grant (ROPC) is deprecated** in OAuth 2.1 and disabled\n> on many instances; prefer `login`. `client_credentials` and `refresh_token`\n> grants remain supported for service accounts. See [.env.example](.env.example).\n\n### Supported authentication methods\n\nEvery inbound REST auth method ServiceNow offers is covered:\n\n| Method | `SN_AUTH` | Set | Notes |\n| ------ | --------- | --- | ----- |\n| Basic | `basic` | `SN_USER` / `SN_PASSWORD` | Default. |\n| OAuth 2.1 — Authorization Code + PKCE | `oauth` | `npx servicenow-mcp-ai login` | **Recommended.** Interactive, stores a refresh token. |\n| OAuth — Client Credentials | `oauth` | `SN_OAUTH_GRANT=client_credentials` | Service-to-service. |\n| OAuth — Refresh Token | `oauth` | `SN_OAUTH_GRANT=refresh_token` + `SN_OAUTH_REFRESH_TOKEN` | Set by `login`. |\n| OAuth — JWT Bearer | `oauth` | `SN_OAUTH_GRANT=jwt_bearer` + `SN_OAUTH_JWT_KEY` | RS256 assertion; no password. |\n| OAuth — Password (ROPC) | `oauth` | `SN_OAUTH_GRANT=password` | **Deprecated.** |\n| API Key | `apikey` | `SN_API_KEY` | `x-sn-apikey` header. |\n| Bearer token | `token` | `SN_BEARER_TOKEN` | Pre-obtained token, used verbatim. |\n| Mutual TLS (client cert) | `none` (or layered) | `SN_TLS_CLIENT_CERT` / `_KEY` | Cert maps to a user; needs optional `undici`. |\n\n### Environment variables\n\nAll settings are read from `.env` (or the real process environment, which takes\nprecedence). Only the first three are required; the rest are optional tuning knobs.\nSee [.env.example](.env.example) for a template.\n\n| Variable                 | Required | Default         | Description                                                                                                                                                                                                                                                                |\n| ------------------------ | :------: | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `SN_INSTANCE`            |   yes    | —               | Instance name, host, or `https://` URL (`dev12345`, `dev12345.service-now.com`).                                                                                                                                                                                           |\n| `SN_USER`                |   yes    | —               | ServiceNow username for Basic auth.                                                                                                                                                                                                                                        |\n| `SN_PASSWORD`            |   yes    | —               | ServiceNow password. Never logged or returned by any tool.                                                                                                                                                                                                                 |\n| `SN_TIMEOUT_MS`          |    no    | `30000`         | Per-request timeout in milliseconds.                                                                                                                                                                                                                                       |\n| `SN_MAX_RETRIES`         |    no    | `2`             | Retries for transient failures (429/5xx, network errors). Non-idempotent writes are only retried on connect errors.                                                                                                                                                        |\n| `SN_MAX_RECORDS`         |    no    | `10000`         | Hard cap on records returned by a `fetchAll` query.                                                                                                                                                                                                                        |\n| `SN_MAX_RESULT_CHARS`    |    no    | `100000`        | Character budget for a query result before it is truncated for the client.                                                                                                                                                                                                 |\n| `SN_ALLOWED_HOSTS`       |    no    | —               | Comma-separated allow-list of permitted hosts (for custom or sovereign-cloud domains). When set, only matching hosts are contacted. When unset, only `*.service-now.com` instances are allowed and internal/loopback hosts are blocked (SSRF guard).                        |\n| `SN_AUTH`                |    no    | auto            | Auth method: `basic`, `oauth`, `apikey`, `token` or `none` (cert-only mTLS). Auto-detected from the keys present (API key → bearer → OAuth → Basic).                                                                                                                        |\n| `SN_API_KEY`             |    no    | —               | ServiceNow Inbound API Key, sent as the `x-sn-apikey` header (enables `apikey` mode).                                                                                                                                                                                      |\n| `SN_BEARER_TOKEN`        |    no    | —               | A pre-obtained bearer token, sent verbatim as `Authorization: Bearer …` (enables `token` mode).                                                                                                                                                                            |\n| `SN_OAUTH_CLIENT_ID`     |    no    | —               | OAuth client id (its presence enables OAuth).                                                                                                                                                                                                                              |\n| `SN_OAUTH_CLIENT_SECRET` |    no    | —               | OAuth client secret.                                                                                                                                                                                                                                                       |\n| `SN_OAUTH_GRANT`         |    no    | `password`      | OAuth grant: `password` (**deprecated** — ROPC), `client_credentials`, `refresh_token` or `jwt_bearer`. The `login` command sets this to `refresh_token` for you.                                                                                                           |\n| `SN_OAUTH_JWT_KEY`       |    no    | —               | PEM private key for the `jwt_bearer` grant (or `SN_OAUTH_JWT_KEY_FILE`). Optional claims: `SN_OAUTH_JWT_ISS` (default client id), `SN_OAUTH_JWT_SUB` (default `SN_USER`), `SN_OAUTH_JWT_AUD`, `SN_OAUTH_JWT_KID`, `SN_OAUTH_JWT_EXP_SEC` (default 300).                       |\n| `SN_OAUTH_REFRESH_TOKEN` |    no    | —               | Refresh token for the `refresh_token` grant. Obtained automatically by `npx servicenow-mcp-ai login` (Authorization Code + PKCE).                                                                                                                                          |\n| `SN_OAUTH_REDIRECT_URI`  |    no    | `http://localhost:53682/callback` | Loopback redirect URL for the PKCE `login` flow. Must match the redirect registered on the OAuth endpoint.                                                                                                                                               |\n| `SN_OAUTH_SCOPE`         |    no    | —               | Optional OAuth scope requested during `login`.                                                                                                                                                                                                                             |\n| `SN_TLS_CLIENT_CERT`     |    no    | —               | Client certificate (PEM) for **mutual TLS** (or `SN_TLS_CLIENT_CERT_FILE`). With `SN_TLS_CLIENT_KEY` it presents a client cert; ServiceNow's mutual-auth profile maps it to a user. Needs the optional `undici` package (`npm i undici`).                                    |\n| `SN_TLS_CLIENT_KEY`      |    no    | —               | Private key (PEM) for the client certificate (or `SN_TLS_CLIENT_KEY_FILE`).                                                                                                                                                                                                |\n| `SN_TLS_CA`              |    no    | —               | Optional CA bundle (PEM) to trust (or `SN_TLS_CA_FILE`). `SN_TLS_REJECT_UNAUTHORIZED=false` disables verification (not recommended).                                                                                                                                        |\n| `SN_TABLES_ALLOW`        |    no    | —               | Comma-separated table allowlist; when set, only these tables are reachable.                                                                                                                                                                                                |\n| `SN_TABLES_DENY`         |    no    | —               | Comma-separated table denylist; always wins over the allowlist.                                                                                                                                                                                                            |\n| `SN_READONLY`            |    no    | `false`         | When truthy, refuse every create/update/delete.                                                                                                                                                                                                                            |\n| `SN_WRITE_MODE` | no | `plan` | `plan` (default) previews a write as a before/after diff without mutating; `apply` executes; passing `apply:true` forces a single call. |\n| `SN_REDACT_FIELDS` | no | — | DF-5: mask these field values before records reach the model (comma/space-separated). |\n| `SN_REDACT_PII` | no | `false` | DF-5: also mask email/phone/national-id patterns inside string values. |\n| `SN_TRANSPORT` | no | `stdio` | DF-6: `stdio` (default) or `http` (Streamable HTTP for remote/agent clients). |\n| `SN_PORT` | no | `3000` | DF-6: TCP port for the http transport. |\n| `SN_HTTP_HOST` | no | `127.0.0.1` | DF-6: bind address for the http transport (loopback by default). |\n| `SN_HTTP_TOKEN` | no | — | DF-6: when set, http requests must send `Authorization: Bearer <token>`. |\n| `SN_LOG_LEVEL`           |    no    | `info`          | Log verbosity on stderr: `error`, `warn`, `info`, `debug`.                                                                                                                                                                                                                 |\n| `SN_ENV_FILE`            |    no    | —               | Explicit path to the env file to read/write.                                                                                                                                                                                                                               |\n| `SN_TOOL_PACKAGES`       |    no    | `core`          | Comma/space-separated tool packages or profiles to enable. Profiles: `core` (default) and `all`. Packages: `table`, `schema`, `aggregate`, `attachment`, `importset`, `batch`, `catalog`, `change`, `knowledge`, `cmdb`, `scripts`, `flows`, `codecheck`, `docs`, `instance`, `email`, `atf`. The admin tools are always on. `atf` runs tests on the instance — enable it only on a non-production instance. |\n| `SN_PACKAGES_DENY`       |    no    | —               | Comma/space-separated packages to exclude even if enabled by `SN_TOOL_PACKAGES`. The only way to block plugin APIs (catalog, change, knowledge…) — the table policy does not see them.                                                                                     |\n| `SN_PACKAGES_READONLY`   |    no    | —               | Comma/space-separated packages whose write tools are not registered; their read tools stay. Per-package complement to the global `SN_READONLY`.                                                                                                                            |\n| `SN_SCHEMA_CACHE_TTL_SEC` |   no    | `300`           | TTL for the near-static schema reads cache (`list_tables`, `describe_table`, `get_cmdb_meta`). `0` disables caching.                                                                                                                                                       |\n| `SN_MAX_CONCURRENT`      |    no    | `4`             | Maximum parallel HTTP requests to the instance (simple in-process semaphore).                                                                                                                                                                                              |\n| `SN_INCLUDE_REF_LINKS`   |    no    | `false`         | Reference fields come back without their `link` URLs by default (token savings). Set `true` to include them.                                                                                                                                                               |\n| `SN_RESULT_PRETTY`       |    no    | `false`         | Tool results are compact JSON by default (pretty-printing ~doubles tokens). Set `true` for indented output.                                                                                                                                                                |\n| `SN_DOCS_DIR`            |    no    | `docs/instance` | Directory the `docs` package reads/writes Markdown in. Relative paths resolve against the working directory.                                                                                                                                                               |\n| `SN_CODESEARCH`          |    no    | `false`         | Opt in to the Code Search API (`sn_codesearch`) for `servicenow_search_code` (FT-7). When `true` and the plugin is active it replaces the LIKE iteration; falls back to LIKE on any failure.                                                                                |\n| `SN_PROFILE_<NAME>_*`    |    no    | —               | Named connection profiles: `SN_PROFILE_DEV_INSTANCE` / `_USER` / `_PASSWORD` define profile `dev`. The bare `SN_INSTANCE`/`SN_USER`/`SN_PASSWORD` keys are the `default` profile.                                                                                          |\n| `SN_ACTIVE_PROFILE`      |    no    | `default`       | Which profile tools use. Switch at runtime with `servicenow_use_instance` (persisted to the env file).                                                                                                                                                                     |\n\n### Two-axis access policy\n\nAccess is controlled on **two independent axes**, because a table restriction does\nnot reach the plugin-backed APIs (Change, Catalog, Knowledge…). Guard both:\n\n| Axis         | Enable / deny / read-only                                | Example                                                                       |\n| ------------ | -------------------------------------------------------- | ----------------------------------------------------------------------------- |\n| **Tables**   | `SN_TABLES_ALLOW` / `SN_TABLES_DENY` / `SN_READONLY`     | `SN_TABLES_DENY=change_request` blocks the **Table API** path only.           |\n| **Packages** | `SN_TOOL_PACKAGES` / `SN_PACKAGES_DENY` / `SN_PACKAGES_READONLY` | `SN_PACKAGES_DENY=change` also blocks the Change Management **plugin API**. |\n\nSo denying the `change_request` table still leaves the Change Management API\n(`sn_chg_rest`) able to read/write changes — the **package axis is why it exists**.\nSee [Security notes](#security-notes) for the full model (including how the Batch\nAPI obeys both axes).\n\n**List syntax:** table lists (`SN_TABLES_ALLOW` / `SN_TABLES_DENY`) are\ncomma-separated; package lists (`SN_TOOL_PACKAGES`, `SN_PACKAGES_DENY`,\n`SN_PACKAGES_READONLY`) accept commas **or** whitespace. Surrounding spaces are\ntrimmed in both, and table matching is case-insensitive — so\n`SN_TABLES_DENY=Change_Request, sys_user` works.\n\n## Run / debug\n\n- **VS Code**: open the Command Palette and start the server defined in\n  [.vscode/mcp.json](.vscode/mcp.json), then use it from Chat.\n- **MCP Inspector**: `npm run inspector`\n- **Directly**: `npm start`\n\n### Command-line interface\n\nThe published `servicenow-mcp-ai` binary (run it directly, or via\n`npx servicenow-mcp-ai`) has three invocations. All connection settings come from\nenvironment variables / the env file (see [Environment variables](#environment-variables));\nonly `drift` takes positional arguments.\n\n| Command                                         | Positional parameters                                        | What it does                                                                                                                  | Exit codes                                          |\n| ----------------------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |\n| `servicenow-mcp-ai`                             | _(none)_                                                    | Starts the MCP server. The transport (`stdio` default, or `http`) is chosen by `SN_TRANSPORT`; runs until `SIGINT`/`SIGTERM`. | `0` clean shutdown · `1` fatal startup error        |\n| `servicenow-mcp-ai login`                       | _(none — operates on the active profile)_                   | One-time OAuth 2.1 Authorization Code + PKCE login: opens the browser, captures the loopback redirect, stores a refresh token. | `0` success · `1` login failed                      |\n| `servicenow-mcp-ai drift <profileA> <profileB>` | `<profileA>`, `<profileB>` — two configured profile names   | DF-3 CI drift gate: compares the two instances and writes a Markdown diff report.                                            | `0` no drift · `1` drift found · `2` usage / error  |\n\n**`login`** operates on the active profile (`SN_ACTIVE_PROFILE`, default\n`default`) and reads, for that profile:\n\n- `SN_INSTANCE` — **required**; the target instance.\n- `SN_OAUTH_CLIENT_ID` — **required**; client id of an Authorization Code OAuth API endpoint.\n- `SN_OAUTH_CLIENT_SECRET` — optional; for a confidential client.\n- `SN_OAUTH_REDIRECT_URI` — optional; loopback URL, default `http://localhost:53682/callback`. Must match the redirect registered on the endpoint.\n- `SN_OAUTH_SCOPE` — optional; requested OAuth scope.\n\nOn success it writes `SN_AUTH=oauth`, `SN_OAUTH_GRANT=refresh_token` and\n`SN_OAUTH_REFRESH_TOKEN` back to the env file (profile-prefixed when the profile\nis not `default`). The authorization URL is printed on stderr in case the browser\ndoes not open automatically.\n\n**`drift`** takes two positional profile names; each must resolve to a configured\nprofile (`SN_PROFILE_<NAME>_*`, or the bare `SN_INSTANCE` / `SN_USER` /\n`SN_PASSWORD` keys for `default`). The Markdown report is written to **stdout**\n(capture it as a CI artifact); a one-line drift summary goes to stderr.\n\n### CI drift gate (DF-3)\n\nCompare two configured profiles and **fail a pipeline on configuration drift**:\n\n```bash\nservicenow-mcp-ai drift dev prod   # report on stdout; exit 1 on drift, 0 if clean, 2 on error\n```\n\n## Develop\n\n```bash\nnpm run check     # full gate: build, lint, format check, coverage-gated tests, prod audit\nnpm test          # unit tests only (node:test; needs a prior npm run build)\nnpm run lint      # ESLint (flat config + typescript-eslint)\nnpm run format    # format with Prettier\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for the conventions (one commit per\ntask, tests ship with the change, generated docs).\n\n## Tools\n\n<!-- GENERATED:TOOLS:BEGIN (npm run docs:readme) -->\n\n_This table is generated from the tool registrations — edit the tool\ndefinitions in `src/tools/`, then run `npm run docs:readme`._\n\n| Package | Tool | Read-only | Description |\n| ------- | ---- | :-------: | ----------- |\n| `table` | `servicenow_query_table` | yes | Read records from any ServiceNow table through the Table API |\n| `table` | `servicenow_get_record` | yes | Read a single record from a table by its sys_id |\n| `table` | `servicenow_create_record` | no | Create a new record in a table with the given field values |\n| `table` | `servicenow_update_record` | no | Update fields on an existing record identified by its sys_id |\n| `table` | `servicenow_delete_record` | no | Delete a record from a table by its sys_id |\n| `schema` | `servicenow_list_tables` | yes | List tables from sys_db_object, optionally filtered by a name or label fragment |\n| `schema` | `servicenow_describe_table` | yes | List a table's columns (name, label, type, mandatory, reference) from sys_dictionary |\n| `aggregate` | `servicenow_aggregate` | yes | Compute server-side aggregates (count, avg, min, max, sum) over a table via the Stats API, with optional gr… |\n| `attachment` | `servicenow_list_attachments` | yes | List attachment metadata, optionally scoped to a specific record (table + sys_id) |\n| `attachment` | `servicenow_get_attachment` | yes | Read a single attachment's metadata by its sys_id |\n| `attachment` | `servicenow_download_attachment` | yes | Download an attachment's bytes, returned as base64 |\n| `attachment` | `servicenow_upload_attachment` | no | Attach a file (provided as base64) to a record identified by table + sys_id |\n| `attachment` | `servicenow_delete_attachment` | no | Delete an attachment by its sys_id |\n| `importset` | `servicenow_insert_import_set_row` | no | Insert a single row into a staging table and run its transform map |\n| `importset` | `servicenow_get_import_set_row` | yes | Read the transform outcome for a previously inserted staging row by its sys_id |\n| `batch` | `servicenow_batch` | no | Execute several ServiceNow REST sub-requests in a single HTTP round-trip via the Batch API |\n| `catalog` | `servicenow_list_catalogs` | yes | List the Service Catalogs available on the instance (Service Catalog API) |\n| `catalog` | `servicenow_list_catalog_categories` | yes | List the categories within a service catalog |\n| `catalog` | `servicenow_list_catalog_items` | yes | Search/list orderable catalog items, optionally by text or category |\n| `catalog` | `servicenow_get_catalog_item` | yes | Get a catalog item, including its order variables, by sys_id |\n| `catalog` | `servicenow_order_catalog_item` | no | Order a catalog item directly ('order now') |\n| `change` | `servicenow_list_changes` | yes | List change requests through the Change Management API |\n| `change` | `servicenow_get_change` | yes | Get a single change request by sys_id |\n| `change` | `servicenow_create_change` | no | Create a normal, standard or emergency change |\n| `change` | `servicenow_update_change` | no | Update fields on a change request by sys_id |\n| `change` | `servicenow_change_conflicts` | no | Read schedule conflicts for a change, or recalculate them (calculate=true) |\n| `knowledge` | `servicenow_search_knowledge` | yes | Full-text search of knowledge articles (Knowledge API), with optional encoded query and paging |\n| `knowledge` | `servicenow_get_knowledge_article` | yes | Get a knowledge article (content and metadata) by sys_id |\n| `knowledge` | `servicenow_knowledge_highlights` | yes | List featured or most-viewed knowledge articles for the current user |\n| `cmdb` | `servicenow_list_cis` | yes | List configuration items of a CMDB class through the class-aware CMDB Instance API |\n| `cmdb` | `servicenow_get_ci` | yes | Get a CI with its attributes and inbound/outbound relations by class and sys_id |\n| `cmdb` | `servicenow_create_ci` | no | Create a CI via the CMDB Instance API (routed through Identification & Reconciliation) |\n| `cmdb` | `servicenow_update_ci` | no | Update a CI's attributes via the CMDB Instance API (IRE) |\n| `cmdb` | `servicenow_get_cmdb_meta` | yes | Get the schema/metadata of a CMDB class (attributes, relationship rules) from the CMDB Meta API |\n| `scripts` | `servicenow_list_scripts` | yes | List script artefacts of one type as compact metadata (no source code) |\n| `scripts` | `servicenow_get_script` | yes | Read one script artefact in full, including its source code and execution context |\n| `scripts` | `servicenow_search_code` | yes | Search script source for a literal substring across one or all script types |\n| `scripts` | `servicenow_table_logic` | yes | Assemble the automation that runs on a table: business rules (ordered by when+order), client scripts, UI po… |\n| `scripts` | `servicenow_where_used` | yes | Find where a table, field or script is referenced across the instance's code: textual references in every s… |\n| `flows` | `servicenow_trace_table_event` | yes | Deterministically trace what ServiceNow would run for a table operation, in execution order: display/before… |\n| `flows` | `servicenow_list_flows` | yes | List Flow Designer flows (sys_hub_flow) or legacy workflows (kind: 'workflow') as compact metadata |\n| `flows` | `servicenow_get_flow` | yes | Get a structured view of one flow or workflow: its trigger (table/condition/when) and ordered steps |\n| `flows` | `servicenow_get_flow_runs` | yes | Read flow execution evidence from sys_flow_context — by flow sys_id or by the record (document) it ran agai… |\n| `codecheck` | `servicenow_lint_script` | yes | Run deterministic code-quality rules over one script artefact (hard-coded sys_ids/URLs, unbounded or in-loo… |\n| `codecheck` | `servicenow_lint_table` | yes | Lint every active business rule, client script and UI policy of a table (via table_logic), returning per-sc… |\n| `codecheck` | `servicenow_code_health` | no | Aggregate code-health picture: script counts by type, a security scan of the access-control layer (ACL scri… |\n| `docs` | `servicenow_docs_list` | yes | List the Markdown documents in the local instance-documentation folder (SN_DOCS_DIR) |\n| `docs` | `servicenow_docs_read` | yes | Read one Markdown document from the local instance-documentation folder |\n| `docs` | `servicenow_docs_search` | yes | Search the local instance documentation for a substring; returns a snippet per match |\n| `docs` | `servicenow_docs_write` | no | Create or overwrite a Markdown document in the local docs folder and refresh index.md |\n| `docs` | `servicenow_generate_er_diagram` | yes | Build a Mermaid erDiagram from sys_dictionary: an entity per table plus a relationship for every reference … |\n| `docs` | `servicenow_generate_table_flow` | yes | Build a Mermaid flowchart of a record's lifecycle on a table, grouping active business rules by phase (disp… |\n| `instance` | `servicenow_snapshot_instance` | no | Download the instance's structural metadata into the local docs folder (SN_DOCS_DIR/<profile>/): tables.md+… |\n| `instance` | `servicenow_compare_instances` | no | Diff two connection profiles: tables present in only one, common columns whose type/mandatory/reference dif… |\n| `email` | `servicenow_send_email` | no | Send an email through the instance's Email API, optionally associated with a record (table + sys_id) |\n| `email` | `servicenow_get_email` | yes | Read a sent/received email record by its sys_id (Email API) |\n| `atf` | `servicenow_list_atf_tests` | yes | List Automated Test Framework tests (sys_atf_test) as metadata: name, active flag, description |\n| `atf` | `servicenow_list_atf_suites` | yes | List Automated Test Framework test suites (sys_atf_test_suite) as metadata |\n| `atf` | `servicenow_run_atf_test` | no | Run a single ATF test through the CI/CD API |\n| `atf` | `servicenow_run_atf_suite` | no | Run an ATF test suite through the CI/CD API |\n| `atf` | `servicenow_get_atf_result` | yes | Poll an ATF run by its execution id: status, percent complete and message (CI/CD progress API) |\n| `admin` | `servicenow_set_credentials` | no | Save or update the ServiceNow connection credentials |\n| `admin` | `servicenow_list_instances` | yes | List the configured ServiceNow connection profiles (instances): name, host, user, read-only flag and whethe… |\n| `admin` | `servicenow_use_instance` | no | Switch the active ServiceNow connection profile (persisted to the env file) |\n| `admin` | `servicenow_get_status` | yes | Show the configured instance, user, auth mode and access policy, and whether credentials are complete |\n| `admin` | `servicenow_test_connection` | yes | Verify that the configured credentials actually work: reads one sys_user record and reports ok/status/latency |\n| `admin` | `servicenow_check_capabilities` | yes | Preflight which admin-restricted sys_* tables the connected user can actually read, and report which higher… |\n\n<!-- GENERATED:TOOLS:END -->\n\nAll tools carry MCP annotations (`readOnlyHint`, `destructiveHint`,\n`idempotentHint`) so clients can apply the right confirmation UX.\n\n### Tool packages\n\nTools are grouped into packages so you can expose only what a given client needs\n(fewer tools keep the model focused). Set `SN_TOOL_PACKAGES` to a comma/space\nseparated list of profiles or package names:\n\n- `core` (default) — `table`, `schema`, `aggregate`, `attachment`.\n- `all` — every package below.\n- Individual packages: `table`, `schema`, `aggregate`, `attachment`,\n  `importset`, `batch`, `catalog`, `change`, `knowledge`, `cmdb`, `scripts`,\n  `flows`, `codecheck`, `docs`, `instance`, `email`, `atf`.\n\nThe admin tools (`servicenow_set_credentials`, `servicenow_get_status`) are\nalways registered, regardless of the active packages. Unknown names are ignored.\n`servicenow_get_status` reports the resolved `enabledPackages`.\n\n```dotenv\n# Only table + batch tools (plus the always-on admin tools)\nSN_TOOL_PACKAGES=table,batch\n```\n\n#### Presets\n\nIf you would rather not curate the list yourself, three named presets cover the\ncommon roles. The admin tools are always on, so they are not listed. Each preset\nalso has a one-word alias — `SN_TOOL_PACKAGES=reader|developer|admin` — that\nexpands to the same package set.\n\n| Preset      | `SN_TOOL_PACKAGES=…`                                   | For whom                                                        |\n| ----------- | ----------------------------------------------------- | -------------------------------------------------------------- |\n| `reader`    | `table,schema,aggregate`                              | First contact, analysts, a PDI play — read and query only.     |\n| `developer` | `table,schema,aggregate,scripts,flows,codecheck,docs` | The core segment: script intelligence, flow tracing, linting, docs and diagrams. |\n| `admin`     | `all`                                                 | Everything, including the plugin and write-heavy packages.     |\n\nThe `developer` preset builds on the `reader` set; the `docs` package includes the\nMermaid diagram generators. Use the alias for brevity or spell the packages out to\nadd or drop one.\n\n### Examples\n\nQuery the 5 most recent active incidents:\n\n```jsonc\n// servicenow_query_table\n{\n  \"table\": \"incident\",\n  \"query\": \"active=true^ORDERBYDESCsys_created_on\",\n  \"fields\": [\"number\", \"short_description\", \"priority\", \"state\"],\n  \"limit\": 5,\n}\n```\n\nCreate an incident:\n\n```jsonc\n// servicenow_create_record\n{\n  \"table\": \"incident\",\n  \"fields\": {\n    \"short_description\": \"Printer on 3rd floor is down\",\n    \"urgency\": \"2\",\n    \"impact\": \"2\",\n  },\n}\n```\n\nUpdate credentials at runtime:\n\n```jsonc\n// servicenow_set_credentials\n{\n  \"instance\": \"dev98765.service-now.com\",\n  \"user\": \"admin\",\n  \"password\": \"••••••\",\n}\n```\n\n## Resources\n\nRead-only metadata is also exposed as MCP resources, so clients can attach it\ndeclaratively instead of calling a tool:\n\n| URI                           | Description                                    |\n| ----------------------------- | ---------------------------------------------- |\n| `servicenow://status`         | Connection status, auth mode, access policy.   |\n| `servicenow://tables`         | List of tables from `sys_db_object`.           |\n| `servicenow://schema/{table}` | Columns of a table from `sys_dictionary`.      |\n| `servicenow://docs/{path}`    | A Markdown document from the local docs store. |\n\n## Prompts\n\nReady-made workflows are exposed as MCP prompts; they orchestrate the tools and\ninsist on reading real values from the instance:\n\n| Prompt                              | Argument   | Purpose                                                          |\n| ----------------------------------- | ---------- | ---------------------------------------------------------------- |\n| `servicenow_incident_triage`        | `incident` | Summarize, assess priority, categorize and recommend next steps. |\n| `servicenow_change_impact_analysis` | `change`   | Affected CIs, schedule conflicts and a go/no-go call.            |\n| `servicenow_document_table`         | `table`    | Schema + automation + diagrams → saved Markdown doc.             |\n\n## Project structure\n\n```\n.\n├── .env                   # credentials (git-ignored; or ~/.config/servicenow-mcp-ai/.env)\n├── .env.example           # template\n├── .github/workflows/     # CI: build + lint + test\n├── .vscode/mcp.json       # VS Code MCP server registration\n├── eslint.config.js       # ESLint flat config\n├── .prettierrc.json       # Prettier config\n├── src/\n│   ├── index.ts           # bootstrap: load env, register, connect stdio\n│   ├── registry.ts        # registers all tool groups\n│   ├── resources.ts       # MCP resources (status, tables, schema, docs)\n│   ├── prompts.ts         # MCP prompts (triage, change impact, document table)\n│   ├── http.ts            # shared REST client (auth, retry, SSRF)\n│   ├── auth.ts            # Basic + OAuth 2.0 providers\n│   ├── host.ts            # host resolution + SSRF guard\n│   ├── policy.ts          # table allow/deny + read-only guards\n│   ├── settings.ts        # numeric env settings\n│   ├── logging.ts         # structured stderr logger\n│   ├── result.ts          # tool results + structured errors\n│   ├── servicenow.ts      # Table API client\n│   ├── config.ts          # env file read/write + location\n│   ├── api/               # aggregate, attachment, import set, batch, catalog, change, knowledge, cmdb, scripts, diagrams, docs, meta\n│   └── tools/             # tool registration per API group\n├── test/                  # node:test unit + mock-fetch tests\n└── build/                 # compiled output (after npm run build)\n```\n\n> **Note on names:** the npm package and the GitHub repository are both\n> [`servicenow-mcp-ai`](https://github.com/IvanBBaev/servicenow-mcp-ai) (the\n> unscoped `servicenow-mcp` was already taken on npm); the local working folder\n> is `servicenow-mcp`. The difference is cosmetic and does not affect the build\n> or runtime.\n\n## Security notes\n\n- The env file is git-ignored — do not commit real credentials.\n- The env file is written **owner-only (`0600`)** — it holds a plaintext password.\n- The server uses the stdio transport and only logs to `stderr`; secrets and raw\n  encoded queries are never logged.\n- The password/token is never returned by any tool.\n- Hosts are restricted: without `SN_ALLOWED_HOSTS`, only `*.service-now.com`\n  instances are contacted (internal/loopback always blocked), so a redirected or\n  mistyped host cannot silently receive credentials. Set `SN_ALLOWED_HOSTS` to\n  opt in a custom or sovereign-cloud domain.\n- Prefer **OAuth 2.0** over Basic where possible (`SN_OAUTH_CLIENT_ID`).\n- Apply least privilege with `SN_TABLES_ALLOW` / `SN_TABLES_DENY` and\n  `SN_READONLY=true` for read-only deployments.\n- **Table policy does not cover plugin APIs.** `SN_TABLES_DENY=change_request`\n  blocks the Table API path, but the Change Management API (`sn_chg_rest`) can\n  still read/write changes. To restrict the plugin-backed surfaces use\n  `SN_PACKAGES_DENY` (drop the whole package) or `SN_PACKAGES_READONLY`\n  (register only its read tools). The Batch API obeys both axes too: a\n  sub-request to a denied package's path is refused, and writes to a read-only\n  package are blocked — a batch cannot be used to bypass the package policy.\n\n## Project documentation\n\n| Document | Contents |\n| -------- | -------- |\n| [ARCHITECTURE.md](project/ARCHITECTURE.md) | Layered architecture, Mermaid diagrams (modules, request lifecycle, security model, auth, packages), condensed ADRs |\n| [PRODUCT-STATE.md](project/PRODUCT-STATE.md) | Current product state: API coverage map, quality status, history timeline, roadmap |\n| [ROADMAP.md](project/ROADMAP.md) | Forward plan: ship 1.0.0, Phase 8 (flow testing + code analysis), Phase 9 (competitive differentiators), optional and deferred items |\n| [COMPETITIVE-ANALYSIS.md](project/COMPETITIVE-ANALYSIS.md) | Positioning vs the official ServiceNow MCP Server Console: comparison, where it structurally lags, the Phase 9 boost plan, and platform risks |\n| [IMPLEMENTATION-PLAN.md](project/IMPLEMENTATION-PLAN.md) | Detailed specs for the upcoming phases (harness 2.0, multi-instance, flow testing) |\n| [DONE.md](project/DONE.md) / [TODO.md](project/TODO.md) | Completed work with commit refs / remaining decisions |\n| [WORKLOG.md](WORKLOG.md) / [CHANGELOG.md](CHANGELOG.md) | Detailed work journal / user-facing changelog |\n| [CONTRIBUTING.md](CONTRIBUTING.md) / [SECURITY.md](SECURITY.md) | Dev setup, gates and conventions / security model and reporting |\n\n## Support\n\nThis project is built and maintained in my own time. If it saves you or your team\ntime, please consider supporting its continued development — sponsorship directly\nfunds new tools, bug fixes and keeping pace with ServiceNow's REST surface.\n\n- **[GitHub Sponsors](https://github.com/sponsors/IvanBBaev)** — one-off or\n  recurring, with no platform fee taken out (the preferred option).\n- **[Ko-fi](https://ko-fi.com/ivanbbaev)** — quick one-off support; it also\n  accepts **PayPal**, so it's the fallback for anyone without a GitHub account.\n- **[Donate (Donatree)](https://donatr.ee/ivanbbaev/)** — a no-account donation\n  page (card, PayPal and more) for a one-off tip.\n\n[![Sponsor on GitHub](https://img.shields.io/badge/Sponsor-GitHub-ea4aaa?style=flat-square&logo=githubsponsors&logoColor=white)](https://github.com/sponsors/IvanBBaev)\n[![Support on Ko-fi](https://img.shields.io/badge/Ko--fi-Support-ff5e5b?style=flat-square&logo=kofi&logoColor=white)](https://ko-fi.com/ivanbbaev)\n[![Donate via Donatree](https://img.shields.io/badge/Donate-Donatree-22c55e?style=flat-square&logo=liberapay&logoColor=white)](https://donatr.ee/ivanbbaev/)\n\n## Trademark\n\n`servicenow-mcp-ai` is an independent, community-built project. It is **not\naffiliated with, endorsed by, or sponsored by ServiceNow, Inc.**\n\n\"ServiceNow\", the ServiceNow logo, \"Now\", and related marks are trademarks or\nregistered trademarks of ServiceNow, Inc. in the United States and other\ncountries. They are used in this project's name and documentation **only\nnominatively** — to identify the platform this software interoperates with — and\nno affiliation or endorsement is implied. All other product names and marks are\nthe property of their respective owners.\n\nThis project is licensed under the [MIT License](LICENSE); that license covers\nthe source code and does not grant any rights to use the ServiceNow trademarks.\n",
  "bytes": 50387,
  "sha": "ed3a2de21a9b20e98a7b2076d59625f2e8a6cdc4be2212532e96267959f64990",
  "repo_slug": "ivanbbaev/servicenow-mcp-ai",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_ivanbbaev_servicenow_mcp_ai_400a8630/readme"
}