@imjaineel-dev/sn-mcp-server
v2.2.0
Published
Multi-instance read-only MCP server for ServiceNow
Downloads
407
Maintainers
Readme
📘 SN-MCP-Server
A read-only Model Context Protocol (MCP) server for ServiceNow — built for developers, AI workflows, and tools that need deep visibility into ServiceNow across multiple instances (Prod, Dev, Test, PDI).
✨ Features
- 🔗 Multi-instance — Prod, Dev, Test, PDI in one server
- 🔍 Powerful querying — Table, Aggregate, Code Search APIs
- 🧠 Intelligent record resolution — INC, CHG, RITM, sys_id
- 🔄 Flow Designer + Legacy Workflows
- 🧩 Schema inspection & discovery
- 👥 Identity & access data
- 🔑 Multiple Auth Methods — Basic Auth and OAuth 2.0 (Client Credentials, Password, Auth Code, JWT)
- 🧰 ServiceNow SDK support — optional
sn_sdk_explaintool is registered whennow-sdkis installed globally (npm install -g now-sdk) - Read-only by design — safe on production instances
- 📄 Per-run log files — one file per server start, stored in OS temp folder
- 🔬 Verbose tool logging — per-call called/received debug lines (instance, args, result summary) when
SN_MCP_VERBOSE=true - 📚 ServiceNow Docs search —
sn_read_docssearches the ServiceNowDocs repo, returnsfile_path/raw_urlfor direct reads, and can resolve the selected branch when a non-default version is requested
🚀 Quick Start
Option A — npx (no install needed)
npx @imjaineel-dev/sn-mcp-server --config ./sn-instance.jsonOption B — Local clone
git clone https://github.com/ImJaineel/SN-MCP-Server.git
cd SN-MCP-Server
npm install
npm start # auto-detects sn-instance.json in repo root⚙️ Configuration
1. Create sn-instance.json
{
"default": "dev",
"instances": [
{
"alias": "prod",
"label": "Production",
"instance": "mycompany-prod",
"auth": "oauth2",
"grant_type": "client_credentials",
"client_id": "your-client-id",
"client_secret": "your-client-secret"
},
{
"alias": "dev",
"label": "Development",
"instance": "mycompany-dev",
"auth": "basic",
"username": "svc_mcp_readonly",
"password": "your-password-here"
}
]
}📄 Full example: sn-instance.example.json
Common fields
| Field | Required | Description |
|---|---|---|
| alias | ✅ | Short name used in tool calls ("prod", "dev-2") |
| instance | ✅ | Subdomain ("mycompany-dev") or full URL ("https://...") |
| auth | optional | "basic" (default) or "oauth2" |
| label | optional | Human-friendly display name |
| default | optional | Use either a top-level "default" alias or per-entry "default": true to select the default instance |
Basic Auth (auth: "basic")
| Field | Required | Description |
|---|---|---|
| username | ✅ | Service account username |
| password | ✅ | Password or API token |
OAuth 2.0 (auth: "oauth2")
| Field | Required | Description |
|---|---|---|
| grant_type | ✅ | "client_credentials", "password", "authorization_code", or "jwt_bearer" |
| client_id / client_secret | ✅ | OAuth application credentials |
| username / password | conditional | Required for password grant |
| refresh_token | conditional | Required for authorization_code grant |
| jwt_private_key / jwt_subject | conditional | Required for jwt_bearer grant (PEM key string & subject user) |
| jwt_issuer | optional | Optional issuer value for jwt_bearer |
| token_url | optional | Override the default token endpoint (default: /oauth_token.do) |
Default selection is resolved in this order:
- explicit top-level
"default"alias in the config object - an entry with
"default": true - the first entry in the list
2. Environment variables (optional)
All optional — set them in your shell, in the MCP client "env" block, or in a .env file at the project root. Values from the shell take precedence over .env.
Note: If you are running the server from a local clone, a root-level
.envfile is loaded automatically at startup.
| Variable | Description | Default |
|---|---|---|
| SN_INSTANCE_CONFIG | Path to sn-instance.json | Auto-resolved |
| SN_MCP_VERBOSE | Set to "true" to enable debug logs | false |
| LOGS_TIMEZONE | IANA timezone for log timestamps (CURRENT, GLOBAL, or a named zone) | CURRENT |
| SN_LOG_DIR | Override log file directory | OS temp folder |
| GITHUB_TOKEN | GitHub Personal Access Token for sn_read_docs (branch lookup and GitHub search) | none |
CLI flags are also supported as an alternative to environment variables:
--config <path>→ setsSN_INSTANCE_CONFIG--verbose→ setsSN_MCP_VERBOSE=true--github-token <token>→ setsGITHUB_TOKEN
🔌 MCP Client Setup
For Anyone, Everyone
VS Code: Press
Ctrl+Shift+P, select Add MCP
Claude Desktop: Edit
~/Library/Application Support/Claude/claude_desktop_config.json(macOS) or%APPDATA%\Claude\claude_desktop_config.json(Windows)
Gemini Code Assist: Create or edit
~/.gemini/mcp.json
Amazon Q: Create or edit
~/.aws/amazonq/mcp.json
Using npx (recommended):
{
"mcpServers": {
"servicenow": {
"command": "npx",
"args": ["sn-mcp-server", "--config", "/absolute/path/to/sn-instance.json"],
}
}
}Using local clone:
{
"mcpServers": {
"servicenow": {
"command": "node",
"args": ["/absolute/path/to/SN-MCP-Server/src/index.js"]
}
}
}⚠️ Always use absolute paths in MCP client configs.
▶️ Running locally
# Standard start (auto-detects ./sn-instance.json)
npm start
# With explicit config path
node src/index.js --config /path/to/sn-instance.json
# With verbose logging
npm run dev
node src/index.js --config ./sn-instance.json --verbose
# Auto-restart on file changes (development)
npm run watch
# Open MCP Inspector UI in browser (test tools interactively)
npm run inspect
# The inspector launcher accepts localhost and 127.0.0.1 origins so the browser can connect reliably.
# Show help
npx sn-mcp-server --help🪵 Logs
Each server run creates a new timestamped log file:
2026-04-09T14-32-01.123Z.logStored in the OS temp directory:
| OS | Default log location |
|---|---|
| Windows | %TEMP%\ImJaineel_SN-MCP-Instance_logs\ |
| macOS | $TMPDIR/ImJaineel_SN-MCP-Instance_logs/ |
| Linux | /tmp/ImJaineel_SN-MCP-Instance_logs/ |
Override with SN_LOG_DIR env var. Log files are cleaned up automatically by the OS on reboot.
The startup banner always prints the exact log file path:
Log file : /tmp/ImJaineel_SN-MCP-Instance_logs/2026-04-09T14-32-01.123Z.log🧰 Available Tools
The server exposes 16 tools at runtime when the current environment supports them:
- 14 instance tools — require a configured
sn-instance.json - 2 knowledge tools — instance-independent tools for docs and SDK guidance
14 instance tools
| Tool | Description | Visibility |
|---|---|---|
| sn_list_instances | List all configured instances and their aliases, labels, and URLs. | Visible when sn-instance.json is configured and loaded. |
| sn_ping | Test connectivity to a specific instance or the default instance. | Visible when sn-instance.json is configured and loaded. |
| sn_get_identity | Query users, groups, and group membership from identity tables. | Visible when sn-instance.json is configured and loaded. |
| sn_inspect_table | Inspect table schema or search for matching tables by name/label. | Visible when sn-instance.json is configured and loaded. |
| sn_aggregate_table | Run aggregate queries such as count, sum, avg, min, and max. | Visible when sn-instance.json is configured and loaded. |
| sn_query_table | Generic read from any ServiceNow table with encoded queries, fields, paging, and display values. | Visible when sn-instance.json is configured and loaded. |
| sn_get_record | Resolve and fetch a record by sys_id, record number, task table, or CMDB CI class. | Visible when sn-instance.json is configured and loaded. |
| sn_get_attachment | Fetch attachment metadata or file content from the Attachment API. | Visible when sn-instance.json is configured and loaded. |
| sn_get_update_sets | List update sets or drill into the files inside a specific update set. | Visible when sn-instance.json is configured and loaded. |
| sn_code_search | Search scripting artifacts using the native ServiceNow Code Search API. | Visible when sn-instance.json is configured and loaded. |
| sn_get_scripted_artifacts | Fetch Script Includes, Business Rules, Client Scripts, UI Actions, Scheduled Jobs, Fix Scripts, and Scripted REST artifacts. | Visible when sn-instance.json is configured and loaded. |
| sn_legacy_workflow_search | Search classic workflow activity variable values and resolve the owning workflow versions. | Visible when sn-instance.json is configured and loaded. |
| sn_get_legacy_workflow_artifacts | Fetch legacy workflow artifacts from wf_* tables. | Visible when sn-instance.json is configured and loaded. |
| sn_get_workflow_studio_artifacts | Fetch Workflow Studio and Flow Designer artifacts from sys_hub_* and related tables. | Visible when sn-instance.json is configured and loaded. |
2 knowledge tools
| Tool | Description | Visibility |
|---|---|---|
| sn_read_docs | Search, browse, and read ServiceNowDocs markdown by release branch. Search mode returns file_path and raw_url values for direct reads, and get_file accepts either a raw GitHub URL or a repo-relative path. | Always visible. |
| sn_sdk_explain | Query the ServiceNow SDK for explanations of SDK skills, APIs, and concepts via now-sdk. | Visible only when now-sdk is installed and can be executed successfully. |
Runtime visibility rules
- Instance tools (14) are hidden when the server starts in config-less mode (no
sn-instance.jsonprovided). In that mode, only the 2 knowledge tools remain visible. sn_read_docsis always registered, because it does not depend on ServiceNow instance credentials.sn_sdk_explainis added only after a successful probe ofnow-sdk; if the package is not installed or cannot be executed, the tool is omitted entirely. Install it globally with:npm install -g now-sdk- Every instance tool accepts an optional
instanceparameter. If omitted, the server uses the configured default instance.
💡 Usage Examples
Target a specific instance
sn_get_scripted_artifacts table="sys_script_include" query="nameLIKEMorpheus" instance="prod"
sn_query_table table="incident" query="state=1" instance="dev"
sn_get_update_sets instance="pdi"Query incidents
{ "tool": "sn_query_table", "table": "incident", "query": "active=true", "limit": 5 }Search ServiceNow Docs
{ "tool": "sn_read_docs", "mode": "search", "search": "Install the ServiceNow SDK in an application", "version": "australia" }Use mode": "get_file" with the returned file_path or raw_url to read the matching doc.
Get record by number
{ "tool": "sn_get_record", "number": "INC0012345" }Search legacy workflows
{ "tool": "sn_legacy_workflow_search", "query": "morpheus", "instance": "prod" }Aggregate
{
"tool": "sn_aggregate_table",
"table": "incident",
"aggregates": [{ "field": "priority", "function": "count" }],
"group_by": ["priority"]
}📁 Project Structure
SN-MCP-Server/
├── src/
│ ├── cli.js ← npx entrypoint (--config, --verbose, --github-token, --help)
│ ├── index.js ← server bootstrap and startup banner
│ ├── config.js ← config path resolution and validation
│ ├── validator.js ← sn-instance.json schema validation
│ ├── constants.js ← shared repo/example URLs
│ ├── env-loader.js ← .env file parser (no external deps)
│ ├── logger.js ← structured logger, per-run log files
│ ├── multi-client.js ← multi-instance routing and default-instance resolution
│ ├── sn-client.js ← per-instance REST client
│ ├── handler.js ← tool name → method router
│ ├── tools.js ← MCP tool definitions
│ ├── docs-client.js ← ServiceNowDocs search/browse/read implementation
│ └── sdk-client.js ← ServiceNow SDK availability probe and explain helper
├── scripts/
│ ├── dev.js ← development helper
│ └── inspect.js ← MCP Inspector launcher with origin allowlist
├── sn-instance.json ← your credentials (git-ignored)
├── sn-instance.example.json ← template with supported auth flows
├── .env.example ← environment variable documentation
├── README.md ← full project documentation
└── package.json⚠️ Troubleshooting
Invalid credentials
- Verify username/password in
sn-instance.json - Ensure the account has REST API access enabled in ServiceNow
Instance unreachable
- Check the
instancevalue format — subdomain or full URL - Verify VPN / network connectivity
sn-instance.json validation error
- The server prints a specific error message pointing to the exact field/entry
- See the example: sn-instance.example.json
MCP client not detecting server
- Always use absolute paths in MCP client config
- Restart the MCP client after config changes
🔐 Security Notes
sn-instance.jsonis in.gitignore— never commit it- Use a dedicated read-only service account per instance
- PDI instances can use
admincredentials safely since they're isolated - Do not store credentials in environment variables in shared environments
🤝 Contributing
PRs welcome! Please open an issue first for larger changes.
🐛 Report a bug
If you hit a bug, please open a GitHub issue here:
- https://github.com/ImJaineel/SN-MCP-Server/issues/new
Include the following in your report so it can be fixed quickly:
- what you expected to happen
- what actually happened
- the command or MCP client configuration you used
- the relevant log output or error text
- any redacted snippets from
sn-instance.jsonor.env
📄 License
See LICENSE for details.
