instance | servicenow_snapshot_instance | no | Download structural metadata to SN_DOCS_DIR// as Markdown + JSON: tables, schema/.md, plugi…
instance | servicenow_compare_instances | no | Diff two profiles: tables in only one, column type/mandatory/reference differences, scripts missing/renamed… | email | servicenow_send_email | no | Send an email through the Email API (plugin must be active), optionally tied to a record (table + sys_id) | email | servicenow_get_email | yes | Read a sent/received email record by its sys_id (Email API) | atf | servicenow_list_atf_tests | yes | List Automated Test Framework tests (sys_atf_test) as metadata: name, active flag, description | atf | servicenow_list_atf_suites | yes | List Automated Test Framework test suites (sys_atf_test_suite) as metadata | atf | servicenow_run_atf_test | no | Run one ATF test through the CI/CD API | atf | servicenow_run_atf_suite | no | Run an ATF test suite through the CI/CD API | atf | servicenow_get_atf_result | yes | Poll an ATF run by its execution id: status, percent complete and message (CI/CD progress API) | revert | servicenow_list_writes | yes | List the local write journal (newest first): every create/update/delete/execute this server made, with its … | revert | servicenow_revert_write | no | Undo one applied write from the local journal: an update restores its before values, a create is deleted, a… | artifacts | servicenow_list_artifacts | yes | List records of any registry artifact type (business rules, UI policies, widgets, flows, catalog items, …) … | artifacts | servicenow_get_artifact | yes | Read one artifact of any registry type in full: the record, its registry child records (e.g | artifacts | servicenow_explain_artifact | yes | Explain one artifact of any registry type: summary, trigger fields, non-empty fields, children, referenced … | artifacts | servicenow_artifact_dependencies | yes | Dependency graph of one artifact: outbound (reference fields, decoded JSON, script calls and GlideRecord ta… | updatesets | servicenow_list_update_sets | yes | List update sets (sys_update_set), newest first, with state, application scope and whether each is the user… | updatesets | servicenow_get_update_set | yes | Summarise one update set: its customer updates (sys_update_xml) per artefact — type, target name, action, t… | updatesets | servicenow_compare_update_set | yes | Compare an update set's artefacts with another profile (live) or a stored snapshot: per artefact same / dif… | ops | servicenow_ops_read | yes | Bounded operational views for 'why is it slow' triage: overview (all counts), syslog (recent entries by lev… | ops | servicenow_data_health | yes | Data-quality counts for one table (twin of servicenow_code_health): duplicate groups over key_fields, and o… | history | servicenow_get_record_history | yes | Read a record's change history: sys_audit field changes and sys_journal_field entries (comments, work_notes… | properties | servicenow_get_properties | yes | Read system properties (sys_properties) by exact name or name prefix: value, type, description, read/write … | properties | servicenow_set_property | no | Set the value of one existing system property (sys_properties) by name | directory | servicenow_lookup_directory | yes | Find users (user_name, email prefix or name), groups or roles by search term or sys_id | ui | servicenow_explain_portal | yes | Explain a Service Portal (url_suffix or sys_id) or one page as a tree: theme, menu, pages, then layout cont… | admin | servicenow_set_credentials | no | Save connection credentials to the env file for later requests (any subset; auth / oauth_client_id / oauth_… | admin | servicenow_list_instances | yes | List the configured ServiceNow connection profiles (instances): name, host, user, auth method (and OAuth gr… | admin | servicenow_use_instance | no | Switch the active ServiceNow connection profile (persisted to the env file) | admin | servicenow_explain_policy | yes | Say whether a table may be read or written under the active policy and which rule decides (the guards' own … | admin | servicenow_get_status | yes | Show instance, auth, missing credentials, per-profile write mode, policy, limits, TLS, queue, write counter… | admin | servicenow_test_connection | yes | Verify that the configured credentials actually work: reads one sys_user record and reports ok/status/latency | admin | servicenow_check_capabilities | yes | Preflight which sys_* tables the user can read and which capabilities (schema, script intelligence, ACL aud… | admin | servicenow_list_packages | yes | List the tool packages with their state for this session: enabled, configured (SN_TOOL_PACKAGES), denied, r… | admin | servicenow_enable_package | no | Enable a tool package for this session: its tools, resources and prompts appear (list_changed is sent) | admin | servicenow_disable_package | no | Disable a tool package for this session: its tools, resources and prompts are withdrawn (list_changed is sent) |
All tools carry MCP annotations (readOnlyHint, destructiveHint,
idempotentHint) so clients can apply the right confirmation UX.
Tools are grouped into packages so you can expose only what a given client needs
(fewer tools keep the model focused). Set SN_TOOL_PACKAGES to a comma/space
separated list of profiles or package names:
core (default) — table, schema, aggregate, attachment.
all — every package below.
- Individual packages:
table, schema, aggregate, attachment,
importset, batch, catalog, change, knowledge, cmdb, scripts,
flows, codecheck, docs, instance, email, atf, revert,
artifacts, updatesets, ops, history, properties, directory, ui.
The admin tools (servicenow_set_credentials, servicenow_get_status,
servicenow_enable_package and the rest of the admin package) are always
registered, regardless of the active packages. Unknown names are ignored.
servicenow_get_status reports the resolved enabledPackages.
# Only table + batch tools (plus the always-on admin tools)
SN_TOOL_PACKAGES=table,batch
Presets
If you would rather not curate the list yourself, three named presets cover the
common roles. The admin tools are always on, so they are not listed. Each preset
also has a one-word alias — SN_TOOL_PACKAGES=reader|developer|admin — that
expands to the same package set.
| Preset | SN_TOOL_PACKAGES=… | For whom |
|---|
reader | table,schema,aggregate | First contact, analysts, a PDI play — read and query only. | developer | table,schema,aggregate,scripts,flows,codecheck,docs | The core segment: script intelligence, flow tracing, linting, docs and diagrams. | admin | all | Everything, including the plugin and write-heavy packages. |
The developer preset builds on the reader set; the docs package includes the
Mermaid diagram generators. Use the alias for brevity or spell the packages out to
add or drop one.
Switching packages at runtime
A client can widen or narrow its surface without a restart:
servicenow_list_packages shows every package with its state for this
session (enabled, configured, denied, read-only, tool count), and
servicenow_enable_package / servicenow_disable_package toggle one. The
server announces the change with notifications/tools/list_changed (and the
prompts / resources equivalents when those change too), one per list per toggle.
A toggle never exceeds the policy axes: a package in SN_PACKAGES_DENY is
refused (PACKAGE_DENIED), a package in SN_PACKAGES_READONLY brings only its
read tools, and the admin tools cannot be disabled. Toggles last for the
session; an HTTP session that closes returns to SN_TOOL_PACKAGES. Nothing
changes unless a client calls these tools.
The server also declares resources.subscribe: after servicenow_use_instance
or servicenow_set_credentials it sends notifications/resources/list_changed
and, to subscribers, notifications/resources/updated for
servicenow://status.
Upsert by key
servicenow_upsert_record({table, key, fields}) creates or updates one record
matched by key, an exact match on one or more field/value pairs (for example
{"u_external_id": "A-17"}; an empty string matches an empty field). No match
creates a record with the key and the fields, exactly one match updates it, and
more than one match is refused with AMBIGUOUS_KEY — so is a match the user
cannot read, since creating another would duplicate it.
The action is decided in the plan: without apply:true the tool returns
create or update (with the sys_id and the before values) plus
apply_with: {expected_action, expected_sys_id}. Pass those back with
apply:true; if the key now resolves differently (the record appeared, went
away or is another one) the call fails with STALE_RECORD and writes nothing.
The applied write is journaled as a create or an update, so
servicenow_revert_write undoes it like a direct create_record /
update_record.
Undo a write (journal-based revert)
Every applied write is recorded in the local, hash-chained write journal
(<SN_DOCS_DIR>/<profile>/write-journal.jsonl). The opt-in revert package
turns it into an undo:
servicenow_list_writes — the journal newest first, filtered by profile,
table, since (ISO date/time), result and action. Each row carries the
entry id and whether the line alone allows a revert (revertible +
reason).
servicenow_revert_write — entry_id → the inverse write through the Table
API: an update writes its journaled before values back, a create is
deleted, a delete is re-created from its before record (system fields
dropped, the original sys_id requested; the result reports
sys_id_preserved). It follows plan/apply like every write tool: without
apply:true it returns the inverse, the record's current state and the drift
check, and changes nothing.
Safety rules:
- Drift check. The record's
sys_mod_count is compared with the value the
journaled write left (after_mod_count, or before.sys_mod_count + 1); when
no count is available, the written field values are compared instead. If the
record changed since — or nothing could be compared — the revert is refused
with STALE_RECORD; pass force:true to overwrite anyway (the revert's
journal line then records force: true).
NOT_REVERTIBLE, with the reason, when the entry is unknown, the journal
chain is broken, the write was not applied, the line has no before state,
a before value was redacted (SN_REDACT_FIELDS / SN_REDACT_PII), the
entry was already reverted, or its origin has no safe inverse: attachment
upload/delete, send_email, import set rows, catalog orders, Batch API
sub-requests, ATF runs, CMDB creates (IRE may have matched an existing CI) and
local/config entries. A redacted value is never restored as [redacted]:
the whole entry is refused, with no partial revert — restore those fields by
hand.
- The revert is itself journaled (
reverts: <entry_id>, tool: servicenow_revert_write), so reverting the revert is a redo. Policy applies as
for a direct write: SN_READONLY, the table allow/deny lists and the package
axes of both the original package and table. Put revert in
SN_PACKAGES_READONLY to keep list_writes without the undo.
Update sets
The opt-in updatesets package reads update sets (all three tools are
read-only and go through the table policy and redaction like every reader):
servicenow_list_update_sets — optional state, name fragment,
application (scope namespace, global or sys_id), query, limit /
offset → sets newest first, with the user's current set marked.
servicenow_get_update_set — update_set (sys_id or exact name) → its
customer updates (sys_update_xml) per artefact: type, target name,
action, table, plus counts by_type / by_action. Payloads are omitted
unless include_payload: true; they are then parsed into field values,
each capped at payload_max_chars (default 500), with secret-looking
fields masked.
servicenow_compare_update_set — update_set plus with_profile (read
live) or with_snapshot (a servicenow_snapshot_instance snapshot) → per
artefact same / different (differing field names only) / missing /
not_comparable / not_covered / unknown. Only fields in the update
payload are compared; audit columns are ignored.
Writes: servicenow_create_record, servicenow_update_record,
servicenow_upsert_record and servicenow_delete_record take an optional
update_set (sys_id or exact name; default SN_UPDATE_SET). The plan
preview names the target set; applying switches the user's sys_update_set
preference (and the scope's updateSetForScope<scope> preference for a
scoped set), runs the write, and restores the previous value — the result
reports update_set: { bound, previous, restored } and the journal entry
records update_set. A set that is not in progress is refused
(UPDATE_SET_NOT_IN_PROGRESS); a data-row table (anything not extending
sys_metadata and without the update_synch attribute) is written without
switching, and the plan says so. Without the argument or the setting nothing
changes. Other write tools (batch, catalog, change…) are not bound.
Operations and data health
The opt-in ops package holds two read-only tools for "the instance is slow"
triage and data quality. Every section reads its own table; an unreadable
table (ACL, table policy, missing table) reports available: false with the
reason instead of failing the call, so a blank section never reads as healthy.
-
servicenow_ops_read — kind:
overview — the counts of every section below in one call.
syslog — entries of the last minutes (default 60, max 1440) at or
above level (default warning), optional source fragment: counts by
level, top sources and the newest rows (messages capped at 500 chars).
jobs — the scheduler queue (sys_trigger) by state, the number of
ready jobs more than overdue_minutes past their next action, and the
overdue (default), running or queued jobs with their claiming node.
email_queue — outbound sys_email: the send-ready backlog and its
oldest entry, counts by type in the window and the recent send failures.
semaphores — sys_semaphore rows, newest first.
Rows are capped by limit (default 25, max 200).
-
servicenow_data_health — the data twin of servicenow_code_health for one
table, optionally scoped by query (no ^NQ / ORDERBY): duplicate
groups over key_fields (Aggregate API grouping, count > 1, capped by
limit), and per reference field (reference_fields, default the first 10
non-system ones) the orphaned references (target row missing) and — when
the target has an active column and stale is not false — the stale
references (target inactive), each with the encoded query that lists the
rows. Field names are checked against the dictionary first. A target row
the user cannot read also counts as orphaned.
The servicenow_why_is_it_slow prompt walks through these reads and, with a
table, the logic that runs on its writes.
Record history, properties and directory
Three opt-in packages cover day-to-day operations questions. Every read goes
through the table policy and redaction like every other reader.
-
servicenow_get_record_history (history) — table + sys_id → field
changes from sys_audit and journal entries (comments, work notes) from
sys_journal_field, merged newest first. source (all / audit /
journal), fields, since (YYYY-MM-DD[ HH:MM:SS]), limit (default
100) and value_max_chars (default 2000) narrow it. Audit rows that repeat
a journal entry are skipped. If a source cannot be read (ACL or policy), it
is reported under sources and the other one is still returned.
-
servicenow_get_properties (properties) — an exact name or a name
prefix → sys_properties rows. Password-type or secret-looking properties
come back as [redacted], and long values are truncated.
-
servicenow_set_property (properties) — sets the value of one existing
property. It runs as plan/apply: the plan shows the current and the new
value, and apply is journaled. servicenow_revert_write can undo it,
except for secret properties, which are never journaled in clear. It honours
SN_READONLY and SN_PACKAGES_READONLY=properties. A missing property is
PROPERTY_NOT_FOUND; the tool never creates one.
-
servicenow_lookup_directory (directory) — kind (user / group /
role) plus a search term or a sys_id. With include_details and
exactly one match, the result adds:
- for a user, its roles and groups;
- for a group, its members and roles;
- for a role, its contained roles and the groups that grant it.
A detail table that cannot be read is listed in details_unavailable. Put
directory in SN_PACKAGES_DENY to remove the user-data surface.
Instance discovery
servicenow_document_instance (docs) takes an optional depth that adds a
discovery folder, <SN_DOCS_DIR>/<profile>/discovery/, next to README.md.
The tiers are cumulative:
depth | Files |
|---|
overview | overview.md — version, counts, automation, the files written | apps | + apps.md and one tables-<scope>.md per scope (tables and their dictionary) | artefacts | + one artifacts-<scope>.md per scope |
The scopes are the named apps, else every non-global sys_app scope, up to
the per-run target cap (the rest are listed as skipped). artifacts-<scope>.md
lists every artefact type with a Collected / not collected and why column:
collected (with a count), capped, unverified (the table is not readable here),
no such table, unreadable for this user, package off, or no records in this
scope. Every read goes through the same policy, redaction, capability preflight
and write journal as the other generators. Without depth the tool behaves as
before.
Plugin skills
The Claude Code plugin (/plugin install servicenow-mcp-ai) ships five skills
under skills/. Each one only orchestrates this server's tools; none holds
credentials or calls ServiceNow on its own.
| Skill | Use it to |
|---|
sn-discover | Map an instance or its custom apps with servicenow_document_instance({depth}) | sn-triage | Investigate a failing record, flow or script (status, history, logic, logs) | sn-impact | Assess what a change to a table, field or script would touch (where-used, table logic) | sn-drift | Compare two instances or a saved snapshot, or review an update set | sn-safe-write | Make a record change with plan-and-apply, the write journal and a revert path |
A test (test/plugin-skills.test.js) checks that every servicenow_* name in a
skill exists in the tool manifest. The skills are not part of the npm package.
Service Portal tree
servicenow_explain_portal (ui, opt-in) explains a Service Portal (portal:
url_suffix or sys_id) or one page (page: page id or sys_id) as a tree.
The tree runs page → container → row → column → widget instance → widget. Instance
widget_parameters are mapped onto the widget's option_schema, and each widget
lists its dependencies, JS / CSS includes, Angular providers and templates. The
theme, menu, header / footer and route maps are included. Nested rows are
followed to depth (default 3, max 6), and the layout is read for the first 5
pages. format is json, markdown, mermaid (layout tree) or file. A
Service Portal table that cannot be read becomes a caveat, not a failure.
The cmdb package also has servicenow_list_ci_relations (a CI's
cmdb_rel_ci relationships in either direction, with the related CI's name and
class) and servicenow_identify_reconcile, which sends an IRE payload of items
and relations. In plan mode, servicenow_identify_reconcile calls the
identify-only endpoint and shows what IRE would match; when the endpoint is
missing, the plan is marked degraded. Apply is journaled but not revertible,
because IRE decides per item.
servicenow_run_atf_test and servicenow_run_atf_suite take wait_seconds
(0–300). The tool polls the CI/CD progress endpoint with progress
notifications, and cancelling the request stops the wait. A run that is still
going when the time is up returns wait.state: "running" with a tracker
for servicenow_get_atf_result.
servicenow_insert_import_set_row also returns import_set_run (the
sys_import_set_run row of the import set) and transform_maps (the staging
table's maps, the ones this row used marked used: true). If either follow-up
read fails, you get warnings instead of an error.
Generic artifact reads
The opt-in artifacts package reads any type in the artifact registry (the
servicenow://artifact-types resource lists them, with their tables, key
fields and child tables):
servicenow_list_artifacts — artifactType plus optional scope
(namespace or sys_id), active, query and limit → summaries: sys_id,
name, natural key, scope, active flag, SDK-managed verdict and the type's
metadata. No script bodies.
servicenow_get_artifact — artifactType plus sys_id or the natural
key → the full record, its child records in registry order (a UI policy's
actions; a portal page's containers, rows, columns and widget instances; a
flow's action instances), its scope and whether that scope is SDK-managed.
servicenow_explain_artifact — same identification → a structured
explanation: a one-line summary, when it runs (the trigger fields that
are set), its non-empty fields, its child records as compact items, the
records it references, and its encoded JSON fields decoded (widget
parameters, UI Builder props and data, flow label caches). A value that
cannot be decoded comes back raw with decoded: false and a reason — one
bad field never fails the call. Long values are capped against
SN_MAX_RESULT_CHARS (a value gets at most a twentieth of it, the whole
explanation four fifths); truncatedFields, truncated / preview and
a child's omitted count say what was cut. Flow action values and UI
Builder compositions are read with the plain JSON decoder until their
dedicated decoders ship (via: "json").
Some types also get an explanation with lines of prose: a state model
lists its states and from -> to transitions with their conditions, a
choice set or table its choices per element in sequence order, and a UI
policy or data policy the effect on each field when its condition holds
(and, with reverse-if-false, when it does not).
servicenow_artifact_dependencies — same identification plus direction
(outbound / inbound / both, default), depth (1–3, default 1),
limit (rows per inbound source, 1–100) and format (json or
mermaid) → a dependency graph of nodes and edges (from depends on
to, with via and field). Outbound edges come from registry reference
fields on the record and its children, decoded JSON (flow step values,
widget options, UI Builder data) and script text (script-include calls,
GlideAjax classes, literal GlideRecord tables). Inbound edges come from
reverse reference queries and — for a script include — script callers,
flow steps whose values call it and the structural pass of the where-used
graph. The walk visits each node once (cycles are safe), stops at 150
nodes (truncated), and turns an unreadable source into an unavailable
entry instead of an error.
Every table read obeys SN_TABLES_ALLOW / SN_TABLES_DENY; a denied child
table comes back as redacted: true instead of failing the read, and
SN_REDACT_FIELDS / SN_REDACT_PII apply as everywhere. Types whose tables
are not yet confirmed on a live instance carry verified: false and a
caveat; when the instance rejects such a table the result is empty with a
degraded reason instead of an error, plus available: false when
sys_db_object shows that the table does not exist on the instance.
Examples
Query the 5 most recent active incidents:
{
"table": "incident",
"query": "active=true^ORDERBYDESCsys_created_on",
"fields": ["number", "short_description", "priority", "state"],
"limit": 5,
}
Create an incident:
{
"table": "incident",
"fields": {
"short_description": "Printer on 3rd floor is down",
"urgency": "2",
"impact": "2",
},
}
Update credentials at runtime:
{
"instance": "dev98765.service-now.com",
"user": "admin",
"password": "••••••",
}
Resources
Read-only metadata is also exposed as MCP resources, so clients can attach it
declaratively instead of calling a tool:
| URI | Description |
|---|
servicenow://status | Connection status, auth mode, access policy (never includes the password). | servicenow://capabilities | Capability preflight: which admin-restricted sys_* reads (schema, script intelligence, ACL audit) the connected user can actually achieve, plus the per-group capability matrix. | servicenow://tables | List of tables from sys_db_object. | servicenow://schema/{table} | Columns of a table from sys_dictionary (bound to the active profile). | servicenow://instances | Configured connection profiles: name, host, user, read-only flag, credential completeness. | servicenow://{profile}/schema/{table} | Columns of a table read through a specific named connection profile. | servicenow://docs/{+path} | A Markdown document from the local docs store (nested paths allowed), wrapped in an untrusted-content block. | servicenow://artifact-types | Artifact types |
|