servicenow-knowledge-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@servicenow-knowledge-mcpSearch for knowledge articles about password reset"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
snow-mcp
Read-only enterprise knowledge retrieval over MCP
ServiceNow Knowledge · Streamable HTTP · Python · Docker
Overview
A Python 3.15+ / FastMCP 4.x server exposing four read-only ServiceNow Knowledge retrieval tools over stateless Streamable HTTP. It returns source records, not generated answers; it does not provide generic table access, mutations, semantic reranking, OCR, or document parsing. ServiceNow controls downstream access and available content; publication and validity metadata are returned, not an additional MCP publication policy.
Related MCP server: ServiceNow MCP Server
Quick start
From the repository root, with Python 3.15+ and uv 0.13.1 or later installed:
uv python install
uv sync --frozen
cp .env.example .envSet SERVICENOW_BASE_URL and either a static SERVICENOW_ACCESS_TOKEN or both SERVICENOW_CLIENT_ID and SERVICENOW_CLIENT_SECRET. For local development keep MCP_SCOPE_VERIFY_ENABLED=false and SERVICENOW_OBO_ENABLED=false, then run:
uv run snow-mcpConnect to http://127.0.0.1:8080/mcp. The default listener is 0.0.0.0:8080; set HOST=127.0.0.1 to restrict local access. Never commit .env or real secrets.
Health endpoint | Meaning |
| Process can serve HTTP; returns |
| Lifespan is ready; returns |
Readiness is a lifecycle check, not a ServiceNow connectivity or credential check.
The repository pins Python 3.15.0 in .python-version; the Docker image uses the same release.
Docker
docker build -t snow-mcp .
docker run --rm --env-file .env -e HOST=0.0.0.0 -p 127.0.0.1:8080:8080 snow-mcpThe image builds native dependencies in a separate stage with C build tools; the runtime image contains no build toolchain. Initial builds can take longer while Python 3.15 wheels become available.
Use the same ServiceNow configuration as the local setup. The host binding limits access to localhost. These local modes do not authenticate incoming MCP clients; keep them isolated.
Deployment options
Local Python or Docker: no Azure account is required for integration-token or ServiceNow OAuth client-credential access.
Kubernetes: use the generic Helm chart. Azure identity and Istio are disabled by default.
Azure: optional deployment examples cover Azure DevOps, AKS, Terraform, and APIM. Replace all example infrastructure values before use.
For network deployments, provide a trusted authentication gateway and prevent direct backend access. The server's claim decoder does not validate JWT signatures. Scope checks require gateway-validated tokens. Entra ID is specifically required for the optional OBO path; Application Insights is optional telemetry. A subscription key is specific to the APIM example, not the MCP protocol.
Tools and client access
Tool | Purpose | Required scope when |
| Ordered candidates and snippets; optional limit, knowledge base, language and category |
|
| Accessible categories with parent IDs and hierarchy paths |
|
| Canonical content, metadata and attachment references; accepts a 32-hex sys_id or |
|
| Size-limited base64 binary content using known article and attachment sys_ids; no parsing |
|
Search first unless an article ID is already known, then retrieve the article and relevant attachments. Category listing is for discovery, not article retrieval. Search preserves ServiceNow ordering; it does not promise UI-equivalent or semantic ranking.
MCP scopes
The service defines four read-only scopes:
knowledge.search: search articles and read result snippets.knowledge.category.read: list knowledge categories and their hierarchy.knowledge.article.read: retrieve an article's full content, metadata and attachment references.knowledge.attachment.read: retrieve an article attachment's binary content.
With MCP_SCOPE_VERIFY_ENABLED=true, each tool requires its corresponding scope in the caller's token. Scopes do not imply one another: search access does not grant article or attachment access. With the switch off, tool scope checks are skipped, independently of OBO. These scopes authorize MCP tool calls, not access to individual ServiceNow records; ServiceNow still applies its own permissions to the downstream identity.
For isolated local use, a typical client configuration is:
{
"mcpServers": {
"snow-mcp": {
"type": "http",
"url": "http://127.0.0.1:8080/mcp"
}
}
}Client syntax varies. For remote access, configure the credentials required by your gateway using the client's supported mechanism; do not commit keys or tokens. The Azure example explains APIM subscription keys and Entra tokens.
Architecture: two implemented auth paths
SERVICENOW_OBO_ENABLED selects the downstream authenticator at runtime
graph TD
Client["MCP Client"] -->|User token| Gateway["Trusted Gateway: JWT Validation"]
Gateway -->|Validated token| MCP["FastMCP Server"]
MCP -->|Select downstream auth| Switch{"OBO Enabled?"}
Switch -->|false| Integration["Integration Authentication"]
Switch -->|true| Entra["Entra OBO Exchange"]
Integration -->|Integration identity| SN["ServiceNow Knowledge APIs"]
Entra -->|Delegated user identity| SNThe diagram shows a gateway-backed deployment; isolated local development may connect directly to FastMCP. The gateway performs JWT validation; Azure APIM is one optional implementation. FastMCP extracts claims when OBO or MCP scope verification is enabled; per-tool scope enforcement is controlled independently by MCP_SCOPE_VERIFY_ENABLED. The decision node corresponds to SERVICENOW_OBO_ENABLED; arrow labels distinguish the identity used for downstream access. Credential selection and prerequisites are detailed below.
Runtime path | Credentials and identity | Behavior |
OBO disabled ( | Static ServiceNow token, otherwise ServiceNow OAuth client credentials | ServiceNow authorizes the integration identity, not the caller. A configured static token takes precedence over client credentials. Inbound APIM scope checks remain independently configurable. |
OBO enabled ( | Incoming user assertion + Entra tenant/client/secret + downstream scope | Exchanges the assertion at the tenant-specific Entra v2 token endpoint, then calls ServiceNow with the delegated token. Independent of |
OBO caches tokens per incoming assertion, bounded by both token lifetimes (maximum 256 cache entries). ServiceNow must already accept the downstream Entra token and map the user to the intended ACLs. App registration, delegated permissions/consent and ServiceNow trust/user mapping are deployment prerequisites, not provisioned by this server.
Security boundary
The authentication gateway must validate the incoming JWT and forward its original Authorization header. With OBO enabled, ClientApp may instead forward that validated token as x-mcp-servicenow-auth: Bearer <token>. This header is used only when Authorization is absent, before claim extraction and OBO context creation. An empty or invalid Authorization header does not trigger fallback. The gateway must validate the token in whichever header is used and strip untrusted caller-supplied forwarding headers. The MCP verifier decodes trusted claims and applies tool scopes; it does not validate JWT signatures, issuer or audience. APIM_EXPECTED_* values only produce diagnostic comparisons, never enforce token validation. Block direct backend access and ensure every permitted route has the same validation guarantee before enabling APIM auth. With both scope verification and OBO disabled, MCP does not enforce inbound authentication or tool scopes; use this only for isolated local development or an explicitly secured deployment boundary.
TLS uses the operating-system trust store. The Docker image uses the system CA bundle; no organization certificate is bundled. Logs exclude raw credentials, authorization headers and article bodies; DEBUG diagnostics can include token fingerprints and claim comparisons, so restrict log access and retention. Application Insights is optional and initialization failures do not prevent startup.
Environment variable configuration
The application reads settings from .env in the working directory and from the process environment; process values take precedence. Names are case-insensitive. Unknown .env keys are ignored. Settings are cached: restart after changes. Defaults below are the code defaults, not example-file placeholders or Helm overrides. unset means no configured value; use omission for optional settings unless blank behavior is explicitly stated. Secrets belong in an approved secret manager/Kubernetes Secret, not a ConfigMap.
The tables cover every application setting and deployment-related variables. Recommendations are examples, not existing prod deployment configuration. dev means isolated local development; deployed dev should use the same APIM boundary as test/prod.
Required / failure impact distinguishes values you must supply from settings whose defaults already work. Conditional requirements apply only to the selected feature or authentication path; optional does not mean an invalid supplied value is accepted. Invalid types, ranges or constrained values can fail settings validation at startup. OBO/APIM configuration checks run during server construction. ServiceNow URL, integration credentials and the default/max search-limit relationship are checked when the retrieval service is first initialized (normally the first tool call), not by the readiness endpoint. Missing retrieval credentials can therefore leave HTTP/health running while tools fail. Valid configuration alone does not guarantee valid credentials, upstream connectivity, permissions or compatible API routes.
Connection and integration authentication
Variable | Required / failure impact | Code default | Purpose / affected functionality | Dev / test / prod recommendation or example |
| Required for all retrieval; no usable default |
| ServiceNow origin for all retrieval and integration OAuth calls; trailing | Separate instances: |
| Default sufficient; correct route required for search, articles and attachments |
| Search, article and article attachment API route | Keep default in all environments unless instance routing differs |
| Default sufficient; correct route required for category listing |
| Category hierarchy API route | Keep default in all environments |
| Conditional: OBO off; supply this or both integration client credentials | unset | Static outbound bearer token when OBO is off; takes precedence over integration client credentials | Dev: optional short-lived token; test/prod: omit when using managed client credentials or OBO |
| Conditional: OBO off and no static token; required with client secret | unset | Integration OAuth client ID when OBO is off and no static token is configured | Dedicated least-privilege client per instance; unused with OBO |
| Conditional: OBO off and no static token; required with client ID | unset | Secret paired with integration client ID | Dev: local secret; test/prod: secret-manager injection and rotation; unused with OBO |
| Default sufficient; correct route required for integration client credentials |
| Integration client-credentials token endpoint | Default in all environments unless instance requires another route |
| Optional; required only if the integration OAuth provider requires a scope | unset | Optional scope sent in integration token request | Omit unless required by the instance; use that instance's approved scope in each environment |
| Optional; required only if the ServiceNow instance requires a version header | unset | Optional | Omit unless the instance requires a specific version; test it before prod |
APIM and delegated OBO authentication
MCP_SCOPE_VERIFY_ENABLED controls tool scope checks independently of OBO. Trusted JWT claim extraction runs when either switch is enabled; OBO always requires a user token, even when tool scope checks are disabled. The gateway remains responsible for cryptographic JWT validation.
Variable | Required / failure impact | Code default | Purpose / affected functionality | Dev / test / prod recommendation or example |
| Optional; independent of OBO |
| Enables fixed per-tool scope checks; OBO still extracts user claims when this is off | Enable only with validated-token forwarding and blocked bypass routes |
| Optional; must be |
| Selects delegated OBO instead of integration authentication | Dev: |
| Conditional: required when OBO is enabled | unset | Tenant-specific OBO endpoint; required with OBO; | Actual tenant GUID per environment; omit without OBO |
| Conditional: required when OBO is enabled | unset | Middle-tier Entra app performing OBO; required with OBO | Environment-specific app registration ID; omit without OBO |
| Conditional: required when OBO is enabled | unset | Middle-tier app secret; required with OBO | Dev: local secret; test/prod: secret-manager injection and rotation; omit without OBO |
| Conditional: required when OBO is enabled | unset | Downstream delegated scope requested from Entra; required with OBO | Example |
| Default sufficient; non-empty matching claims required when APIM auth is enabled |
| Comma-separated claims merged for tool authorization | Keep default in all environments, or limit to the claims actually validated/issued by your identity setup; must be non-empty with APIM auth |
| Default sufficient; non-empty matching claims required when APIM auth is enabled |
| Ordered claims used to identify the caller | Keep default in all environments; must be non-empty with APIM auth |
| Optional; no explicit value required |
| Diagnostic audience comparison only | Local: blank; test/prod: expected middle-tier API audience, e.g. |
| Optional; no explicit value required |
| Diagnostic issuer comparison only | Local: blank; test/prod: exact issuer configured in APIM, e.g. |
| Optional; no explicit value required |
| Diagnostic tenant comparison only | Local: blank; test/prod: expected tenant GUID; enforce separately in APIM |
| Optional; if supplied, must be exactly 64 hex characters or settings validation fails | unset | DEBUG token correlation: unset/blank uses SHA-256; a key uses truncated HMAC-SHA-256 | Dev: omit unless troubleshooting; test/prod: separate secret of exactly 64 hexadecimal characters if diagnostics are needed; never reuse an app secret |
Tool scopes are fixed in src/snow_mcp/scopes.py, not configurable by environment variables. OBO requires all four ENTRA_*/scope values above and a gateway-validated user token, but does not require tool scope verification to be enabled. Missing or invalid OBO settings fail configuration validation.
Retrieval filters and fields
Variable | Required / failure impact | Code default | Purpose / affected functionality | Dev / test / prod recommendation or example |
| Optional; no explicit value required | unset | Default knowledge-base identifier for search; a tool argument can override it | Dev: omit or sandbox sys_id; test/prod: intended base sys_id if a default is needed; not an authorization boundary |
| Optional; no explicit value required | unset | Default search language; a tool argument can override it | Omit for unrestricted language; use e.g. |
| Optional |
| Search-only category display-name restriction; unset or blank disables it | Set approved comma-separated category names when restrictions are required |
| Optional; blank leaves knowledge bases unrestricted by this filter |
| Search-only knowledge-base display-name restriction; blank disables it | Dev: blank or sandbox base; test/prod: explicitly approved names, e.g. |
| Default sufficient; retain category/base fields when their search filters are active |
| Fields requested for search result mapping and allowlist checks | Keep default in all environments, especially |
| Default sufficient; retain content/metadata fields for complete article retrieval |
| Fields requested for canonical article content and metadata | Keep default in all environments; removing |
| Default sufficient; retain ID/name/parent fields for category hierarchy |
| Fields requested for category IDs, names and hierarchy | Keep default in all environments |
Allowlists use comma-separated display names, trimmed and matched case-insensitively. Names in each list are ORed; the two lists are ANDed. Search sends an encoded-query filter and also checks returned candidates locally. Missing/nonmatching fields are excluded when their list is non-empty; ranks are preserved, total counts retained results, and no extra request fills filtered-out slots. A caller's category narrows, never overrides, the category allowlist. Names containing ^, line breaks or a leading javascript: are rejected. These filters do not restrict category listing, direct article retrieval or attachment retrieval; downstream ACLs remain the access boundary.
Bounds, reliability and observability
Variable | Required / failure impact | Code default | Purpose / affected functionality | Dev / test / prod recommendation or example |
| Default sufficient; no explicit value required |
| HTTP timeout for ServiceNow and token exchanges; range | Start with |
| Default sufficient; no explicit value required |
| Result limit when caller omits it; at least 1 and no greater than max |
|
| Default sufficient; no explicit value required |
| Upper bound for search results; at least 1 |
|
| Default sufficient; no explicit value required |
| Category pagination batch size; range 1–500 |
|
| Default sufficient; no explicit value required |
| Article text truncation threshold; minimum 100 |
|
| Default sufficient; no explicit value required |
| Maximum attachment download size; minimum 1; oversized downloads rejected |
|
| Default sufficient; no explicit value required |
| Extra retries for transient ServiceNow retrieval failures; range 0–5, not an OBO exchange retry setting |
|
| Default sufficient; no explicit value required |
| Base delay for retrieval retry backoff; range 0–10 |
|
| Conditional: required only for Application Insights telemetry; server works without it | unset | Enables optional Azure Monitor telemetry; missing/placeholder disables it | Dev: omit or dedicated dev resource; test/prod: inject respective resource connection string |
| Default sufficient; no explicit value required |
| Environment label in lifecycle/telemetry setup logs; does not switch auth or retrieval behavior |
|
| Default sufficient; no explicit value required |
| Application logging verbosity, including DEBUG auth diagnostics | Dev: |
| Default sufficient; no explicit value required |
| CLI server bind address | Local dev: |
| Default sufficient; no explicit value required |
| CLI server port; range 1–65535 |
|
Deployment variables
These are not application settings in ServiceNowKnowledgeConfig:
Variable | Required / failure impact | Default | Consumer / effect | Dev / test / prod recommendation or example |
| Not required by Python server; deployment routing is configured separately | No application default | Not injected by the generic chart; Python server does not read it or change | Set routing through Helm/Istio/APIM, not this variable alone; e.g. environment suffix |
Helm runs Uvicorn with mcp.args.host and mcp.args.port as explicit command arguments; those, not HOST/PORT, control the Helm listener. ConfigMap values come from config, and secretEnv.existingSecret supplies secret environment values. .env.example is for local setup, not a production manifest.
The Dockerfile also sets these runtime/library variables (not Pydantic settings). Keep the image defaults across dev/test/prod unless your platform explicitly requires an override:
Variable | Required / failure impact | Docker default | Purpose / affected functionality |
| Default sufficient; no explicit value required |
| Prevents Python from writing |
| Default sufficient; no explicit value required |
| Flushes Python output promptly for container log collection |
| Default sufficient; no explicit value required |
| Disables FastMCP update checks |
| Default sufficient; no explicit value required |
| Resolves commands from the image's Python virtual environment |
| Default sufficient; no explicit value required |
| CA bundle for compatible TLS libraries; application HTTP clients explicitly use the OS trust store |
| Default sufficient; no explicit value required |
| CA bundle for Requests-based dependencies; not a switch to disable TLS verification |
Docker builds install locked dependencies from the public package index and use the system CA bundle. Configure any private package feed or organization CA outside this repository.
Example environment profiles
Shared safe starting values (apply the correct instance and explicit search allowlists from the tables for each environment):
REQUEST_TIMEOUT_SECONDS=10
DEFAULT_SEARCH_LIMIT=5
MAX_SEARCH_LIMIT=20
MAX_ATTACHMENT_BYTES=5000000
LOG_LEVEL=INFO
PORT=8080Isolated local dev, integration identity:
ENVIRONMENT=dev
HOST=127.0.0.1
MCP_SCOPE_VERIFY_ENABLED=false
SERVICENOW_OBO_ENABLED=false
SERVICENOW_BASE_URL=https://dev-instance.service-now.com
SERVICENOW_CLIENT_ID=<dev-integration-client-id>
SERVICENOW_CLIENT_SECRET=<inject-dev-secret>APIM-backed test, exercising delegated OBO:
ENVIRONMENT=test
HOST=0.0.0.0
MCP_SCOPE_VERIFY_ENABLED=true
SERVICENOW_OBO_ENABLED=true
SERVICENOW_BASE_URL=https://test-instance.service-now.com
ENTRA_TENANT_ID=<test-tenant-guid>
ENTRA_CLIENT_ID=<test-middle-tier-app-id>
ENTRA_CLIENT_SECRET=<inject-test-secret>
SERVICENOW_OBO_SCOPE=api://<test-downstream-app-id>/.defaultAPIM-backed prod uses the tested identity path. For delegated access use the test profile with production instance, tenant, app, scope. Set ENVIRONMENT=prod and inject credentials separately, and the production Application Insights connection string. For intentionally shared integration access use this profile instead:
ENVIRONMENT=prod
HOST=0.0.0.0
MCP_SCOPE_VERIFY_ENABLED=true
SERVICENOW_OBO_ENABLED=false
SERVICENOW_BASE_URL=https://prod-instance.service-now.com
SERVICENOW_CLIENT_ID=<prod-integration-client-id>
SERVICENOW_CLIENT_SECRET=<inject-prod-secret>
APPLICATIONINSIGHTS_CONNECTION_STRING=<prod-resource-connection-string>Placeholders are illustrative, not usable credentials. Omit SERVICENOW_ACCESS_TOKEN when using client credentials. Neither enabling OBO nor APIM auth configures the external identity provider, gateway policy or ServiceNow ACLs automatically.
Development
uv sync --frozen --extra dev
uv run pytest
uv run ruff format --check src tests
uv run ruff check src tests
uv run mypy srcThis server cannot be deployed
Maintenance
Related MCP Connectors
Knowledge base MCP for AI agents on iknow.dev. Search, read, and maintain via OAuth.
Read-only AgentiScript concept search, catalog, authenticity, license, and approved asset discovery.
Make your knowledge agent-ready. One MCP endpoint, 5 connectors, 3 search modes.
Search and retrieve permission-aware knowledge from connected sources through Remly.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceEnables Claude to interact with ServiceNow instances for incident management, service catalog operations, change requests, knowledge base management, user administration, and agile project workflows through various authentication methods.MIT
- AlicenseNot gradedqualityCmaintenanceEnables authenticated interaction with ServiceNow via its REST API using per-user OAuth 2.0 tokens. It provides tools for managing incidents, tasks, knowledge articles, and service catalog requests while maintaining user-specific permissions.23 npm4MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with ServiceNow instances for data retrieval, record management, and workflow execution via the ServiceNow API.MIT
- FlicenseAqualityCmaintenanceEnables searching ServiceNow's public best-practices library across content types without authentication.2-