███████╗███████╗██████╗  █████╗  ██████╗
██╔════╝██╔════╝██╔══██╗██╔══██╗██╔════╝
███████╗█████╗  ██████╔╝███████║██║     
╚════██║██╔══╝  ██╔══██╗██╔══██║██║     
███████║███████╗██║  ██║██║  ██║╚██████╗
╚══════╝╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝ ╚═════╝

A ServiceNow MCP server, and the skill guides that teach an agent to use it.

npm  Stars  License

Two packages, and nothing else: | Package | What it is | | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | [`@serac-labs/servicenow-mcp`](packages/servicenow-mcp) | An MCP server for ServiceNow. 400+ `snow_*` tools over stdio or streamable HTTP, plus blast-radius impact analysis. | | [`@serac-labs/skills`](packages/skills) | 57 ServiceNow skill guides. Plain markdown an agent loads into its prompt so it uses those tools like a practitioner. | The two are meant to be used together. The server gives a model the ability to act on a ServiceNow instance; the skills give it the judgement to do so without breaking one — which update set to be in, why a Business Rule needs ES5, what to check before renaming a field. Both work with any [MCP](https://modelcontextprotocol.io) client. Neither requires the Serac product. ## Quick start ```bash npm install -g @serac-labs/servicenow-mcp ``` Point your MCP client at the `servicenow-mcp-stdio` binary: ```json { "mcpServers": { "servicenow": { "command": "servicenow-mcp-stdio", "env": { "SNOW_INSTANCE": "https://dev12345.service-now.com", "SNOW_CLIENT_ID": "…", "SNOW_CLIENT_SECRET": "…" } } } } ``` Credentials come from an OAuth application registry entry on your instance (`System OAuth > Application Registry`). A developer instance from [developer.servicenow.com](https://developer.servicenow.com) is enough to try everything here. If nothing works — an auth error, or a response that will not parse — ask the server what is wrong before changing anything: ```bash servicenow-mcp-stdio --doctor ``` It names which credential source was used, whether the URL is usable, whether the instance is awake (a hibernating developer instance answers with an HTML login page, which makes every tool look broken), whether the OAuth exchange succeeds, and which roles the account holds. The model can ask for the same report by calling `snow_diagnose_setup`. The catalog is far larger than a context window, so tools are **deferred** by default: `tools/list` returns two meta-tools and the model widens its own surface as it works. ``` tool_search({query: "incident"}) → the matching tools, now enabled tool_execute({tool: "snow_query_incidents", args: {query: "priority=1"}}) ``` Set `SNOW_LAZY_TOOLS=false` to register the whole catalog up front instead. Full options, library usage and the multi-tenancy rules are in the [package README](packages/servicenow-mcp/README.md). ### As a Claude Code plugin The repository is also a plugin marketplace, so the server and all 70 skills arrive in one step: ``` /plugin marketplace add serac-labs/serac /plugin install servicenow@serac ``` The server runs through `npx`, so nothing has to be installed first: export the same three variables as above and it is ready. The same entry is in [`.mcp.json`](.mcp.json) at the repo root, which Claude Code reads for this project. Other clients each want it somewhere else: copy it into `.cursor/mcp.json` (Cursor), `~/.codeium/windsurf/mcp_config.json` (Windsurf), or `.vscode/mcp.json` for VS Code, which names the same block `servers` rather than `mcpServers`. ### Using the skills A skill is a directory with a `SKILL.md`: YAML frontmatter naming the skill and the `snow_*` tools it expects, then prose. Nothing loads them automatically — a host decides which ones to put in front of the model. Copy the ones you want into your agent's skills directory, or read them from the package: ```ts import { skillsRoot } from "@serac-labs/skills/root" ``` They are worth reading on their own, even without an agent involved. Start with [`es5-compliance`](packages/skills/es5-compliance/SKILL.md), [`update-set-workflow`](packages/skills/update-set-workflow/SKILL.md) or [`blast-radius`](packages/skills/blast-radius/SKILL.md). ## Working on it Requires [Bun](https://bun.sh) 1.3.14 — pinned in the root `package.json` `packageManager` field, which is also what CI installs. ```bash bun install bun typecheck # tsgo across both packages bun run test # both suites bun run lint # oxlint ``` Tests do not run from the repo root directly — run them per package, or through turbo with `bun run test`: ```bash cd packages/servicenow-mcp && bun test cd packages/skills && bun test ``` ### Adding a tool Tools live in `packages/servicenow-mcp/src/servicenow-mcp-unified/tools//snow_.ts`, one file per tool, each exporting a `toolDefinition` and an executor. The registry is generated by walking that directory, so a new file in the right shape is a new tool — there is no central list to edit. Regenerate the published manifest afterwards: ```bash bun run --cwd packages/servicenow-mcp generate:tools-json ``` ### Adding a skill Create `packages/skills//SKILL.md` with frontmatter, then regenerate the embedded map: ```bash bun run --cwd packages/skills generate ``` `bun test` in that package fails if the embedded map drifts from the tree, or if frontmatter names a tool the MCP server does not actually have. Both of those have shipped to users before. ### Two files that are production, not build output `packages/servicenow-mcp/tools.json` and `packages/servicenow-mcp/sn-roles.manifest.json` are committed generated files, and live services fetch them straight from `main` over `raw.githubusercontent.com`. They are published by being committed. Moving or renaming either one is a production change: the consumer has to be repointed and deployed first, and the old path removed in a separate commit afterwards. See [the package README](packages/servicenow-mcp/README.md#published-manifests--read-before-moving-them). ## Releases `@serac-labs/servicenow-mcp` publishes from `.github/workflows/publish-mcp.yml` — a manual `workflow_dispatch`, versioned from `packages/servicenow-mcp/package.json` and nothing else, with OIDC trusted publishing and signed provenance. Every PR that touches the package runs the same build, test and packaging gates without publishing, including one that copies the package out of the workspace entirely and proves it installs, builds and tests with no monorepo around it. The [MCP registry](https://registry.modelcontextprotocol.io) listing is a second, separate dispatch: `.github/workflows/publish-mcp-registry.yml` uploads the repo-root `server.json` once the npm version is live. `server.json` repeats that version and the package name, so a gate on every PR touching either file fails when the two disagree — `bun run --cwd packages/servicenow-mcp check:registry-manifest`. `@serac-labs/skills` releases the same way, from `.github/workflows/publish-skills.yml`, with gates adapted to what that package actually ships: the tarball must contain every entrypoint **and** every skill directory, and every published subpath must load under node from a real `npm install` — `skillsRoot()` hands consumers a filesystem path, so an import that merely succeeds proves nothing. Its npm trusted publisher does not exist yet, so no version has gone out. Creating it (bound to `serac-labs/serac` + `publish-skills.yml`) is a manual step on npmjs.com; see the workflow header. ## What used to be here This repository was a fork of [opencode](https://github.com/anomalyco/opencode) carrying a terminal AI agent, a TUI, a desktop app and a web console. Twenty-five packages went; the two above remain. The `@serac-labs/core` CLI those packages built is discontinued — it stays installable on npm at its final version, but there are no further releases and no security fixes for it. The ServiceNow work was always the part worth keeping, and it was the part buried deepest. It is now the whole repository. One artifact of that era is deliberately still here: the `install` script at the repo root. Every CLI already installed in the world fetches that exact URL when it self-upgrades, and `serac.build/install` redirects to it. Deleting the file would pipe a GitHub 404 page into those users' shells. It stays until it is replaced with something that tells them what happened — do not tidy it away. ## Contributing Read [CONTRIBUTING.md](./CONTRIBUTING.md) first — it is short. Every PR links an issue, and the code style rules are in [AGENTS.md](./AGENTS.md). ## License [Apache License 2.0](LICENSE). See [`NOTICE`](NOTICE) for third-party attributions: this code's history begins in the MIT-licensed [opencode](https://github.com/anomalyco/opencode) project.