servicenow-mcp

servicenow-mcp

A small MCP server that lets AI agents create, search, and update ServiceNow incidents through the Table API.

Category
访问服务器

README

servicenow-mcp

An MCP server that bridges AI coding agents (OpenHands, Claude Code, Claude Desktop, …) to ServiceNow ITSM. It exposes three tools — create, query and update incidents — over the ServiceNow Table API, so an agent that just shipped a fix can also leave the change trail where ops teams expect it: an incident with work notes and a state. Single file (server.py), official Python mcp package, httpx, python-dotenv. Built and verified against a live ServiceNow instance (Australia release) over both stdio and streamable HTTP transports.

Verified end-to-end

An OpenHands agent picked up todo-api issue #2 in the demo repo (matheuscalma/todo-api), fixed the code on a feature branch, ran the full test suite (24/24 passing) and opened todo-api PR #4. It then used this server to create incident INC0010002 documenting the change, attached the PR link as a work note, and moved the incident to In Progress. A human reviewed and merged the PR and resolved the incident — code change and ITSM record closed together, no manual ticketing. (All issue/PR references in this section are in the todo-api demo repo, not this one.)

Step Actor Tool / artifact
Pick up todo-api issue #2, fix on a feature branch OpenHands agent git
Run test suite → 24/24 OpenHands agent pytest
Open todo-api PR #4 OpenHands agent GitHub
Create incident INC0010002 describing the change OpenHands agent create_incident
Attach PR link as a work note OpenHands agent update_incident(work_notes=…)
Move incident to In Progress OpenHands agent update_incident(state="In Progress")
Review + merge PR, resolve incident Human GitHub / ServiceNow UI

Artifact trail: todo-api issue #2 → branch → todo-api PR #4 → INC0010002 (work note with PR URL, state New → In Progress → Resolved).

Architecture

┌──────────────────────┐   MCP (stdio  or   ┌───────────────────┐   HTTPS / basic auth   ┌────────────────────┐
│  Agent               │   streamable HTTP) │  server.py        │   Table API (JSON)     │  ServiceNow        │
│  OpenHands / Claude  │ ─────────────────▶ │  create_incident  │ ─────────────────────▶ │  /api/now/table/   │
│                      │ ◀───────────────── │  query_incidents  │ ◀───────────────────── │      incident      │
│                      │   tool results     │  update_incident  │   records / errors     │                    │
└──────────────────────┘                    └───────────────────┘                        └────────────────────┘
                                                     │
                                                     └── ServiceNowClient (httpx.AsyncClient, timeouts,
                                                         readable errors; swappable for tests)

Setup

Requires Python 3.12+ and uv.

uv sync

Create a .env next to server.py (it is git-ignored) with basic-auth credentials for your instance — a Personal Developer Instance works fine:

SNOW_INSTANCE_URL=https://devXXXXXX.service-now.com
SNOW_USERNAME=admin
SNOW_PASSWORD=your-password
# optional, default 15
SNOW_TIMEOUT_SECONDS=15

Running

Default is stdio (the MCP client launches the server as a subprocess; nothing to see):

uv run server.py

Run as HTTP (streamable HTTP on http://0.0.0.0:8765/mcp instead of stdio): uv run server.py --http, or set SNOW_MCP_TRANSPORT=http.

Run in Docker

The Dockerfile builds an HTTP-mode image (python 3.12-slim + uv, non-root, SNOW_MCP_TRANSPORT=http preset, port 8765). Credentials are passed at runtime only — .env is excluded via .dockerignore and never copied into the image.

docker build -t servicenow-mcp .
docker run --rm --env-file .env -p 8765:8765 servicenow-mcp

The MCP endpoint is then http://localhost:8765/mcp. Verify:

curl -s -X POST http://localhost:8765/mcp \
  -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'

Deploy to Kubernetes (Helm)

deploy/chart is a minimal chart: Deployment (1 replica), ClusterIP Service on 8765, and a Secret with SNOW_* credentials built from values. For real deployments create the Secret yourself and set servicenow.existingSecret instead of putting credentials in values.

kind create cluster --name servicenow-mcp && kind load docker-image servicenow-mcp:latest --name servicenow-mcp
helm install servicenow-mcp deploy/chart \
  --set servicenow.instanceUrl=https://devXXXXXX.service-now.com \
  --set servicenow.username=admin --set servicenow.password='...'
kubectl port-forward svc/servicenow-mcp 8765:8765   # then use http://localhost:8765/mcp

Registering with an MCP client

Point the client at uv with the project directory so the .venv and .env are picked up:

{
  "mcpServers": {
    "servicenow": {
      "command": "uv",
      "args": ["--directory", "/absolute/path/to/servicenow-mcp", "run", "server.py"]
    }
  }
}

For Claude Code: claude mcp add servicenow -- uv --directory /absolute/path/to/servicenow-mcp run server.py. For an HTTP client, start with --http and point it at http://<host>:8765/mcp.

Environment variables already set in the client's environment take precedence over .env.

Tools

Tool Parameters What it does Returns
create_incident short_description: str (required) · description: str = "" · urgency: str = "3" ("1" High, "2" Medium, "3" Low) Creates a new incident. {number, sys_id, short_description, state, urgency}
query_incidents query_text: str = "" · state: str = "" · limit: int = 5 (1–100) Lists incidents newest first. query_text that looks like INC0010001 matches the number exactly; other text runs ServiceNow keyword search (123TEXTQUERY321), falling back to a LIKE match on short_description/description so just-created records are found. state accepts a code ("1"…"8") or a name (New, In Progress, On Hold, Resolved, Closed, Canceled). [{number, sys_id, short_description, state, state_code, urgency, created_on}, …]
update_incident number: str (required) · work_notes: str = "" · state: str = "" Looks the incident up by number, appends a work note and/or sets the state. At least one of work_notes/state is required. {number, sys_id, changed: {…}, state}

Errors

All tools raise a readable tool error (surfaced to the agent as isError) instead of a stack trace, e.g.:

  • Authentication failed (401): check SNOW_USERNAME and SNOW_PASSWORD. ServiceNow said: User is not authenticated …
  • Could not connect to https://…: [Errno 8] nodename nor servname provided … Check SNOW_INSTANCE_URL and your network connection.
  • Timed out after 15s talking to https://… The instance may be hibernating (PDI) or unreachable.
  • Incident 'INC9999999' was not found on https://….
  • Forbidden (403): the user lacks permission … or the update was rejected by a business rule. ServiceNow said: … (e.g. resolving an incident without resolution fields).

Design notes

  • Query routing. query_incidents picks one of three encoded queries: input matching INC\d+ → exact number= match; anything else → ServiceNow full-text keyword search (123TEXTQUERY321=…, relevance-ranked, stemmed); if that returns nothing → LIKE on short_description/description. Two facts measured against the live instance forced this: 123TEXTQUERY321 cannot be OR'd with other clauses (the whole query silently returns nothing), and its index lags writes by ~3–5 s, so an agent that just created a ticket would not find it. The LIKE fallback sees fresh rows immediately; keyword search still wins for "what's open about printers?"-style lookups.
  • mcp 1.x / 2.x compat. mcp 2.x renamed FastMCP → MCPServer (mcp.server.mcpserver); server.py tries the 2.x import first and falls back to mcp.server.fastmcp.FastMCP, so it runs on either major version.
  • Swappable client seam. All network access goes through ServiceNowClient (one httpx.AsyncClient: basic auth, JSON headers, timeout; every failure becomes a ServiceNowError with a human-readable message). Tools obtain it via get_client(); tests call set_client(fake) to inject a mock without touching the network. Records are fetched with sysparm_display_value=all, so state/urgency labels come from the instance rather than a hard-coded map (friendly-name aliases are input-only).
  • Transport security. HTTP mode binds 0.0.0.0:8765. The mcp library only auto-enables DNS-rebinding protection for loopback binds, so on 0.0.0.0 any Host/Origin is accepted. Fine on a lab machine; pass a transport_security= (TransportSecuritySettings with allowed_hosts/allowed_origins) to mcp.run(...) before exposing it beyond localhost.

Smoke test

Run against the live instance (writes one incident):

uv run python -c "
import asyncio, server
async def main():
    c = await server.create_incident('MCP server smoke test', 'created by smoke test')
    print(c)
    print(await server.query_incidents(query_text='MCP server smoke test'))
    print(await server.update_incident(c['number'], work_notes='hello from MCP'))
asyncio.run(main())
"

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选