npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@serac-labs/servicenow-mcp

v0.2.1

Published

Unified ServiceNow MCP server (437 snow_* tools), blast-radius analysis, stdio + HTTP transports.

Readme

@serac-labs/servicenow-mcp

A Model Context Protocol server for ServiceNow: 437 snow_* tools over stdio or streamable HTTP, plus blast-radius impact analysis. Part of Serac.

npm install -g @serac-labs/servicenow-mcp@next

Why @next: the latest tag still points at 0.1.0, whose main entrypoint cannot be imported under Node — it does a named import of machineIdSync from node-machine-id, a CJS module Node's lexer cannot read named exports from, which takes out 4 of 11 subpaths and both bins. 0.2.0 on next is the fixed build. Promote it (npm dist-tag add @serac-labs/[email protected] latest, see the header of .github/workflows/publish-mcp.yml), then drop the @next and this note.

Use it as an MCP server

Point any MCP client at the servicenow-mcp-stdio binary:

{
  "mcpServers": {
    "servicenow": {
      "command": "servicenow-mcp-stdio",
      "env": {
        "SNOW_INSTANCE_URL": "https://dev12345.service-now.com",
        "SNOW_CLIENT_ID": "…",
        "SNOW_CLIENT_SECRET": "…"
      }
    }
  }
}

The catalog is large enough to blow a context window, so tools are deferred by default: tools/list returns two meta-tools, and the model widens its own surface as it goes.

tool_search({query: "incident"})     → the matching tools, marked [ENABLED]
tool_execute({tool: "snow_query_incidents", args: {query: "priority=1"}})

Set SNOW_LAZY_TOOLS=false to register the whole catalog up front instead.

Use it as a library

ESM only. The package exports named subpaths rather than one barrel, so importing blast-radius does not pull in the transports:

import { snow_blast_radius_dependents_exec } from "@serac-labs/servicenow-mcp/blast-radius"

const result = await snow_blast_radius_dependents_exec(
  { artifact_type: "script_include", artifact_identifier: "AcmeUtils" },
  { instanceUrl, clientId, clientSecret, accessToken, tenantId: "customer-1042", origin: "http" },
)

Each tool is exported as a *_def / *_exec pair: the MCP tool definition and the executor.

| Subpath | What it is | | ------------------- | ------------------------------------------------------------- | | . | Everything — the barrel | | /server | createServer(), to embed the MCP server in your own process | | /stdio | The stdio transport | | /http | The streamable-HTTP transport, as a Hono app | | /blast-radius | Impact-analysis tools, usable without the MCP layer | | /types | ServiceNowContext, MCPToolDefinition, … | | /auth | OAuth + basic auth, token cache, authenticated Axios client | | /error-handler | Result envelopes and error classification | | /enterprise-proxy | Client for the licensed enterprise tool catalog |

A note on tenancy

ServiceNowContext carries a tenantId and an origin, and they are not decoration.

  • stdio is single-tenant: one process, one user, one credential set. In-process caches are shared across requests and that is correct.
  • HTTP is multi-tenant: one process serves every customer, so every cache and every piece of session state is keyed by tenant. A request that cannot be placed in a tenant is refused rather than pooled into a shared bucket — see src/servicenow-mcp-unified/shared/tenant-scope.ts.

If you embed a tool executor directly (rather than going through a transport), pass a tenantId whenever your process serves more than one customer. Without one, tenant-keyed caches fall back to fingerprinting the credentials, which is safe but colder.

None of this state is shared between processes, so an HTTP deployment should run single-replica or supply its own shared store.

Published manifests — read before moving them

Two generated JSON files live at the root of this package. They are not part of the npm tarball; they are published by being committed, because live services fetch them straight from main over raw.githubusercontent.com:

| File | Fetched at runtime by | If the URL 404s | | ------------------------ | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | tools.json | docs.serac.build — the Complete Tool Reference | Hard and immediate. The fetch throws and the whole section renders an error box for every visitor. | | sn-roles.manifest.json | The Serac Portal's tool-permissions API and docs.serac.build separately | Silent and delayed. The portal caches for 30 min and serves stale, so it breaks on the next cold start, not at deploy. The docs copy null-guards and quietly drops the role column. |

So: changing the path of either file is a production change, not a refactor. It needs the consumer repointed and deployed first, then the old path removed in a separate commit. Never both in one.

"Published by being committed" also means git add is part of the release. When these two files were moved here out of packages/opencode, they spent a while as untracked files: every gate — install, typecheck, tests, build, the standalone packaging gate — passed, because nothing in this package imports them. A git commit -am at that moment would have shipped the deletion of the old path with nothing at the new one, and the first symptom would have been docs.serac.build erroring for every visitor.

script/__tests__/published-manifests.test.ts is the backstop: it fails if either manifest is missing, unparseable, or has lost the top-level shape its consumers destructure. It asserts nothing about freshness — that is generate:tools-json:check, which .github/workflows/test.yml runs on every push and PR.

Regenerating them

bun run --cwd packages/servicenow-mcp generate:tools-json         # writes tools.json
bun run --cwd packages/servicenow-mcp generate:tools-json:check   # drift gate, no write
bun run --cwd packages/servicenow-mcp probe:sn-roles              # writes sn-roles.manifest.json

generate-tools-json.ts walks src/servicenow-mcp-unified/tools/, imports each tool and reads its toolDefinition — it is pure and safe to run in CI, and it refuses to write a partial manifest if any tool file fails to import.

probe-sn-roles/ cannot run in CI: it resolves each tool's minimum ServiceNow role by reading sys_security_acl on a live instance, so it needs OAuth credentials and is a deliberate manual run. Re-run and diff it after a ServiceNow family upgrade. See script/probe-sn-roles/README.md.

Both generators were stranded on an unmerged branch for two months while the manifests they own sat frozen on main — that is why they now live next to the tools they describe, and why generate:tools-json:check exists.

Requirements

Node 20+ or Bun 1.2+. ESM only — there is no CommonJS require entrypoint.

Links

Apache-2.0