Content
# 🚀 ServiceNow MCP Server
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
[](https://github.com/sudhanshu-singh22/ServiceNow_MCP)
[](https://modelcontextprotocol.io/)
A **production-ready Model Context Protocol (MCP) Server** that exposes ServiceNow development capabilities as AI-callable tools. Connect any MCP-compatible AI agent (Claude Desktop, Claude Code, or custom implementations) to your ServiceNow instance and automate real development tasks through natural language.
---
## 📋 Table of Contents
- [Project Overview](#-project-overview)
- [Features](#-features)
- [Architecture](#-architecture)
- [Installation](#-installation)
- [Configuration](#-configuration)
- [Environment Variables](#-environment-variables)
- [Usage Examples](#-usage-examples)
- [MCP Client Configuration](#-mcp-client-configuration)
- [Available Tools](#-available-tools)
- [Folder Structure](#-folder-structure)
- [Security Considerations](#-security-considerations)
- [Development Setup](#-development-setup)
- [Contributing](#-contributing)
- [Roadmap](#-roadmap)
- [License](#-license)
---
## 🎯 Project Overview
### What is an MCP Server?
The **Model Context Protocol (MCP)** is a standardized interface that allows AI agents to access external tools and data sources. An MCP Server acts as a bridge between AI clients and backend systems, exposing business logic as callable functions.
### What This Server Does
ServiceNow MCP Server enables:
- **🤖 AI-Driven Development**: Let AI agents write ServiceNow code, create tables, configure business rules, and manage workflows
- **⚙️ Table Management**: Create and manage custom tables, fields, and data models
- **🔐 Access Control**: Define ACLs and authorization rules programmatically
- **🔄 Workflow Automation**: Trigger Flow Designer flows and monitor execution
- **📊 Data Operations**: Query, create, update, and delete records using GlideRecord-style queries
- **💼 Business Logic**: Create business rules, script includes, and scripted REST APIs
- **📥 Bulk Operations**: Manage import sets and transformation maps
### Key Benefits
✅ **21 pre-built tools** covering core ServiceNow operations
✅ **Multiple auth methods** (Basic, OAuth 2.0, Bearer Token, API Key)
✅ **Automatic retry logic** with exponential backoff
✅ **Structured logging** for debugging and monitoring
✅ **Production-grade** with error handling and validation
✅ **Async/await** for high-performance concurrent requests
---
## ✨ Features
| Category | Available Tools | Count |
|---|---|---|
| **Table Management** | `create_table`, `list_tables` | 2 |
| **Fields / Dictionary** | `create_field`, `read_dictionary` | 2 |
| **GlideRecord Queries** | `query_records`, `get_record`, `update_record`, `delete_record` | 4 |
| **Business Rules** | `create_business_rule`, `list_business_rules` | 2 |
| **Script Includes** | `create_script_include`, `list_script_includes` | 2 |
| **Access Control** | `create_acl`, `list_acls` | 2 |
| **Flow Designer** | `trigger_flow`, `get_flow_execution_status`, `list_flows` | 3 |
| **Import Sets** | `create_import_set_table`, `run_import_set`, `list_transform_maps` | 3 |
| **Scripted REST APIs** | `call_scripted_rest_api`, `list_scripted_rest_apis`, `get_scripted_rest_resources` | 3 |
| | **TOTAL** | **21 tools** |
---
## 🏗️ Architecture
### System Design
```
┌─────────────────────────────────────────────────────────┐
│ AI Agent │
│ (Claude, Claude Code, Custom) │
└────────────────────────┬────────────────────────────────┘
│ MCP Protocol
▼
┌─────────────────────────────────────────────────────────┐
│ ServiceNow MCP Server │
├─────────────────────────────────────────────────────────┤
│ ┌────────────────────────────────────────────────────┐ │
│ │ Tool Registry (21 Tools) │ │
│ │ - Tables, Fields, Records, Business Rules │ │
│ │ - ACLs, Flows, Import Sets, REST APIs │ │
│ └────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────▼────────────────────────────┐ │
│ │ ServiceNowClient (Async) │ │
│ │ - Auth Methods (Basic/OAuth/Bearer/API Key) │ │
│ │ - Retry Logic (Tenacity) │ │
│ │ - Request/Response Handling │ │
│ └────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────▼────────────────────────────┐ │
│ │ Configuration Manager (Pydantic) │ │
│ │ - Environment Validation │ │
│ │ - Auth Credential Management │ │
│ │ - Logging Configuration │ │
│ └────────────────────────────────────────────────┘ │
└────────────────────────┬────────────────────────────────┘
│ HTTPS/REST
▼
┌─────────────────────────────────────────────────────────┐
│ ServiceNow Instance REST API │
│ (v1 or v2) │
└─────────────────────────────────────────────────────────┘
```
### Core Components
| Component | Purpose | Key Features |
|---|---|---|
| **server.py** | MCP Server & Tool Registry | Main entry point, 21 tool definitions, SSE message handling |
| **client.py** | Async HTTP Client | Auth handling, retry logic, rate limit handling |
| **config.py** | Configuration Management | Pydantic-based settings, 4 auth methods, validation |
| **logger.py** | Structured Logging | JSON-formatted logs to stderr, configurable levels |
| **tools/** | Tool Implementations | Modular tool definitions organized by domain |
### Authentication Flow
```
Request Flow:
┌─────────────────────────────────────────────────────┐
│ 1. Tool receives parameters from AI Agent │
│ 2. Validation via Pydantic models │
│ 3. ServiceNowClient._request() called │
│ 4. Auth headers injected (_auth_headers) │
│ 5. Basic auth via httpx.BasicAuth (if basic) │
│ 6. Tenacity retry decorator applied │
│ 7. HTTP request sent with timeout │
│ 8. Response parsed and returned │
└─────────────────────────────────────────────────────┘
```
---
## 📦 Installation
### Prerequisites
- **Python 3.11+** – Required for async/await features
- **A ServiceNow Instance** – Developer sandbox available at https://developer.servicenow.com
- **Internet Access** – To communicate with ServiceNow REST APIs
- **Git** – For cloning the repository
### Step 1: Clone the Repository
```bash
git clone https://github.com/sudhanshu-singh22/ServiceNow_MCP.git
cd ServiceNow_MCP
```
### Step 2: Create a Virtual Environment
```bash
python -m venv .venv
```
### Step 3: Activate the Virtual Environment
**Windows:**
```bash
.venv\Scripts\activate
```
**macOS / Linux:**
```bash
source .venv/bin/activate
```
You should see `(.venv)` appear at the start of your terminal prompt.
### Step 4: Install the Package
```bash
pip install -e .
```
This installs the package in editable mode, along with all dependencies:
- `mcp>=1.0.0` – Model Context Protocol
- `httpx>=0.27.0` – Async HTTP client
- `tenacity>=9.0.0` – Retry library
- `pydantic>=2.7.0` – Data validation
- `pydantic-settings>=2.3.0` – Configuration management
- `python-dotenv>=1.0.0` – Environment variable loading
### Step 5: Configure Your Environment
```bash
# Windows
copy .env.example .env
# macOS / Linux
cp .env.example .env
```
Open `.env` and fill in your ServiceNow instance URL and authentication credentials (see [Configuration](#-configuration) section).
### Step 6: Run the Server
```bash
servicenow-mcp
```
or directly via Python:
```bash
python -m servicenow_mcp.server
```
Expected output:
```
2026-06-04 15:30:45,123 - servicenow_mcp.server - INFO - Initializing MCP server...
2026-06-04 15:30:45,234 - servicenow_mcp.server - INFO - ServiceNow MCP server started
```
The server will start on **stdio** (standard input/output) and wait for MCP client connections.
### Quick Start Verification
To verify your installation:
```bash
# Activate venv
source .venv/bin/activate # macOS/Linux
# or
.venv\Scripts\activate # Windows
# Verify imports work
python -c "from servicenow_mcp.server import main; print('✓ Installation successful')"
```
---
## ⚙️ Configuration
### Overview
Configuration is managed via **environment variables** loaded from a `.env` file using `pydantic-settings`. All variables are prefixed with `SERVICENOW_` (except `LOG_LEVEL`).
### Configuration Sources (Priority Order)
1. **`.env` file** – Default configuration
2. **Environment variables** – Override `.env`
3. **Defaults in code** – Fallback values
### Required Configuration
Every installation must set:
```env
SERVICENOW_INSTANCE_URL=https://dev12345.service-now.com
SERVICENOW_AUTH_METHOD=basic # or oauth, bearer, api_key
```
Then configure credentials for your chosen auth method (see below).
### Authentication Methods
#### 1️⃣ **Basic Auth** (Recommended for Development/Sandboxes)
```env
SERVICENOW_AUTH_METHOD=basic
SERVICENOW_USERNAME=admin
SERVICENOW_PASSWORD=your-password
```
**Pros:** Simple to set up, good for dev/test
**Cons:** Credentials in plaintext, not recommended for production
**When to use:** Local development, sandboxes
#### 2️⃣ **OAuth 2.0 Client Credentials** (Recommended for Production)
```env
SERVICENOW_AUTH_METHOD=oauth
SERVICENOW_OAUTH_CLIENT_ID=your-client-id
SERVICENOW_OAUTH_CLIENT_SECRET=your-client-secret
SERVICENOW_OAUTH_TOKEN_URL=https://your-instance.service-now.com/oauth_token.do
SERVICENOW_OAUTH_SCOPE=useraccount # optional
```
**Setup Instructions:**
1. In your ServiceNow instance, navigate to **System OAuth > Application Registry**
2. Click **New > Create an OAuth API endpoint for external clients**
3. Fill in the form:
- **Name**: ServiceNow MCP
- **Active**: ✓
4. Copy the **Client ID** and **Client Secret**
5. Paste them into your `.env` file
**Pros:** Secure token-based auth, supports scope-based permissions
**Cons:** Slightly more complex setup
**When to use:** Production, secure environments
#### 3️⃣ **Bearer Token / PAT** (Static Token)
```env
SERVICENOW_AUTH_METHOD=bearer
SERVICENOW_BEARER_TOKEN=your-static-bearer-token
```
**Setup Instructions:**
1. In ServiceNow, navigate to **System Security > API Authentication > Tokens**
2. Create a new token for your user
3. Copy the token value
4. Paste into `.env`
**Pros:** Simple, good for CI/CD pipelines
**Cons:** Static token, requires manual rotation
**When to use:** CI/CD, automated deployments
#### 4️⃣ **API Key** (Custom Header)
```env
SERVICENOW_AUTH_METHOD=api_key
SERVICENOW_API_KEY=your-api-key
SERVICENOW_API_KEY_HEADER=X-API-Key # optional, defaults to X-API-Key
```
**Pros:** Flexible, works with any custom auth header
**Cons:** Implementation-specific
**When to use:** Custom authentication systems
---
## 🔧 Environment Variables
### Complete Reference
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
| **Core** | | | | |
| `SERVICENOW_INSTANCE_URL` | URL | ✓ | — | ServiceNow instance base URL (e.g., `https://dev12345.service-now.com`) |
| `SERVICENOW_AUTH_METHOD` | Enum | | `basic` | Authentication method: `basic` \| `oauth` \| `bearer` \| `api_key` |
| `SERVICENOW_API_VERSION` | String | | `v2` | Table API version: `v1` \| `v2` |
| `SERVICENOW_TIMEOUT_SECONDS` | Int | | `30` | HTTP request timeout in seconds (1-300) |
| `SERVICENOW_MAX_RETRIES` | Int | | `3` | Number of retry attempts on 429/5xx (0-10) |
| **Basic Auth** | | | | |
| `SERVICENOW_USERNAME` | String | if basic | — | ServiceNow username |
| `SERVICENOW_PASSWORD` | String | if basic | — | ServiceNow password |
| **OAuth 2.0** | | | | |
| `SERVICENOW_OAUTH_CLIENT_ID` | String | if oauth | — | OAuth client ID from Application Registry |
| `SERVICENOW_OAUTH_CLIENT_SECRET` | String | if oauth | — | OAuth client secret from Application Registry |
| `SERVICENOW_OAUTH_TOKEN_URL` | URL | if oauth | — | OAuth token endpoint URL |
| `SERVICENOW_OAUTH_SCOPE` | String | | — | OAuth scope (optional, e.g., `useraccount`) |
| **Bearer Token** | | | | |
| `SERVICENOW_BEARER_TOKEN` | String | if bearer | — | Static bearer token or PAT |
| **API Key** | | | | |
| `SERVICENOW_API_KEY` | String | if api_key | — | Custom API key value |
| `SERVICENOW_API_KEY_HEADER` | String | | `X-API-Key` | HTTP header name for API key |
| **Logging** | | | | |
| `LOG_LEVEL` | Enum | | `INFO` | Logging level: `DEBUG` \| `INFO` \| `WARNING` \| `ERROR` |
### Example `.env` Files
**Development (Basic Auth):**
```env
SERVICENOW_INSTANCE_URL=https://dev12345.service-now.com
SERVICENOW_AUTH_METHOD=basic
SERVICENOW_USERNAME=admin
SERVICENOW_PASSWORD=devpassword123
LOG_LEVEL=DEBUG
```
**Production (OAuth):**
```env
SERVICENOW_INSTANCE_URL=https://prod.service-now.com
SERVICENOW_AUTH_METHOD=oauth
SERVICENOW_OAUTH_CLIENT_ID=abc123def456
SERVICENOW_OAUTH_CLIENT_SECRET=secret789xyz
SERVICENOW_OAUTH_TOKEN_URL=https://prod.service-now.com/oauth_token.do
SERVICENOW_OAUTH_SCOPE=useraccount
SERVICENOW_TIMEOUT_SECONDS=60
SERVICENOW_MAX_RETRIES=5
LOG_LEVEL=INFO
```
---
## 💡 Usage Examples
### 1. Start the Server
```bash
# Activate virtual environment
source .venv/bin/activate # macOS/Linux
# or
.venv\Scripts\activate # Windows
# Run server
servicenow-mcp
```
### 2. Create a Table via AI Agent
**Prompt to Claude:**
```
Create a new ServiceNow table for managing employee equipment requests.
The table should:
- Extend the "task" table
- Have a label of "Equipment Request"
- Table name: u_equipment_request
- Auto-create a module
```
**Behind the scenes, the MCP server calls:**
```json
{
"tool": "create_table",
"params": {
"label": "Equipment Request",
"name": "u_equipment_request",
"extends": "task",
"access": "public",
"create_module": true
}
}
```
### 3. Query Records
**Prompt:**
```
Fetch all active incidents with priority 1 or 2, assigned to anyone,
showing number, description, assigned person, and priority. Limit to 20 results.
```
**MCP Tool Call:**
```json
{
"tool": "query_records",
"params": {
"table": "incident",
"encoded_query": "active=true^ORpriority=1^ORpriority=2",
"fields": ["number", "short_description", "assigned_to", "priority"],
"limit": 20,
"order_by_desc": "sys_created_on"
}
}
```
### 4. Create a Business Rule
**Prompt:**
```
Create a business rule on the Equipment Request table that:
- Runs BEFORE insert or update
- Sets priority to 2 (Medium) for all new requests
- Sets state to "New" if not already set
```
**MCP Tool Call:**
```json
{
"tool": "create_business_rule",
"params": {
"name": "Set Default Priority and State",
"table": "u_equipment_request",
"when": "before",
"on_insert": true,
"on_update": true,
"script": "if (!current.priority) current.priority = 2;\nif (!current.state) current.state = 'New';",
"active": true
}
}
```
### 5. Trigger a Flow
**Prompt:**
```
Start the employee offboarding workflow for employee ID EMP-12345
with last day of employment as 2026-06-30
```
**MCP Tool Call:**
```json
{
"tool": "trigger_flow",
"params": {
"flow_id": "global.employee_offboarding",
"inputs": {
"employee_id": "EMP-12345",
"last_day": "2026-06-30"
},
"wait_for_completion": false
}
}
```
### 6. Create an Access Control Rule
**Prompt:**
```
Create an ACL on the Equipment Request table that allows:
- Admins to read, write, and delete
- Managers to read and write (based on their department)
- All other users to only read
```
**MCP Tool Call:**
```json
{
"tool": "create_acl",
"params": {
"operation": "write",
"table_name": "u_equipment_request",
"roles": ["admin", "manager"],
"script": "answer = gs.hasRole('admin') || (gs.hasRole('manager') && current.department == gs.getUser().department);",
"description": "Admins and departmental managers can edit requests"
}
}
```
---
## 🔌 MCP Client Configuration
### Claude Desktop Integration
1. **Find your Claude Desktop config file:**
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
2. **Add the MCP server configuration:**
```json
{
"mcpServers": {
"servicenow": {
"command": "python",
"args": ["-m", "servicenow_mcp.server"],
"cwd": "/path/to/servicenow-mcp",
"env": {
"SERVICENOW_INSTANCE_URL": "https://your-instance.service-now.com",
"SERVICENOW_AUTH_METHOD": "basic",
"SERVICENOW_USERNAME": "admin",
"SERVICENOW_PASSWORD": "your-password"
}
}
}
}
```
3. **Restart Claude Desktop**
4. **Verify connection:**
- In Claude Desktop, you should see "servicenow" in the available tools
### Claude Code Integration
1. **Create or update `.mcp.json` in your project root:**
```json
{
"mcpServers": {
"servicenow": {
"command": "python",
"args": ["-m", "servicenow_mcp.server"],
"cwd": "/path/to/servicenow-mcp",
"env": {
"SERVICENOW_INSTANCE_URL": "https://your-instance.service-now.com",
"SERVICENOW_AUTH_METHOD": "oauth",
"SERVICENOW_OAUTH_CLIENT_ID": "your-client-id",
"SERVICENOW_OAUTH_CLIENT_SECRET": "your-client-secret",
"SERVICENOW_OAUTH_TOKEN_URL": "https://your-instance.service-now.com/oauth_token.do"
}
}
}
}
```
2. **Reload Claude Code**
### Custom MCP Client
For custom clients, use the stdio protocol:
```python
import subprocess
import json
# Start the MCP server
proc = subprocess.Popen(
["python", "-m", "servicenow_mcp.server"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd="/path/to/servicenow-mcp",
env={
**os.environ,
"SERVICENOW_INSTANCE_URL": "https://your-instance.service-now.com",
"SERVICENOW_AUTH_METHOD": "bearer",
"SERVICENOW_BEARER_TOKEN": "your-token",
}
)
# Send MCP messages via JSON-RPC over stdin/stdout
# (Follow MCP protocol specification)
```
---
## 🛠️ Available Tools
### 📊 Table Management (2 tools)
#### `create_table`
Create a custom application table.
**Parameters:**
```json
{
"label": "string", // Human-readable table name (required)
"name": "string", // Table name, prefixed with u_ (required)
"extends": "string", // Parent table (default: "task")
"access": "string", // "public" or "protected" (default: "public")
"create_module": "boolean" // Auto-create navigation module (default: false)
}
```
**Example:**
```json
{
"label": "Employee Onboarding",
"name": "u_employee_onboarding",
"extends": "task",
"access": "public",
"create_module": true
}
```
#### `list_tables`
List all tables in the instance.
**Parameters:**
```json
{
"search_term": "string", // Optional filter (case-insensitive)
"limit": "integer" // Max results (default: 100)
}
```
---
### 🔑 Fields / Dictionary (2 tools)
#### `create_field`
Add a new column/field to a table.
**Parameters:**
```json
{
"table_name": "string", // Target table (required)
"column_label": "string", // User-friendly name (required)
"column_name": "string", // Technical name (required)
"field_type": "string", // Field type (required)
"reference_table": "string", // For reference fields
"active": "boolean", // Enable field (default: true)
"mandatory": "boolean", // Require field (default: false),
"max_length": "integer" // For string fields
}
```
**Field Types:** `string`, `text`, `number`, `date`, `reference`, `boolean`, `choice`, `json`
#### `read_dictionary`
Read field definitions from a table dictionary.
**Parameters:**
```json
{
"table_name": "string", // Target table (required)
"include_columns": "string", // Field names to retrieve (optional)
"active_only": "boolean" // Only active fields (default: true)
}
```
---
### 📝 GlideRecord Queries (4 tools)
#### `query_records`
Query records from a table using encoded query syntax.
**Parameters:**
```json
{
"table": "string", // Table name (required)
"encoded_query": "string", // Encoded query (e.g., "active=true^priority=1")
"fields": ["string"], // Columns to retrieve
"limit": "integer", // Max records (default: 100)
"offset": "integer", // Pagination offset (default: 0)
"order_by": "string", // Column to order by
"order_by_desc": "string" // Column to order descending
}
```
**Query Syntax Examples:**
- `active=true` – Active field equals true
- `priority=1^priority=2` – OR condition
- `nameLIKE%John%` – LIKE pattern match
- `created_on>2026-06-01` – Date comparison
#### `get_record`
Fetch a single record by sys_id.
**Parameters:**
```json
{
"table": "string", // Table name (required)
"sys_id": "string", // Record ID (required)
"fields": ["string"] // Columns to retrieve (optional)
}
```
#### `update_record`
Update an existing record.
**Parameters:**
```json
{
"table": "string", // Table name (required)
"sys_id": "string", // Record ID (required)
"updates": { // Field updates (required)
"field_name": "value"
}
}
```
#### `delete_record`
Delete a record.
**Parameters:**
```json
{
"table": "string", // Table name (required)
"sys_id": "string" // Record ID (required)
}
```
---
### ⚙️ Business Rules (2 tools)
#### `create_business_rule`
Create a server-side business rule.
**Parameters:**
```json
{
"name": "string", // Rule name (required)
"table": "string", // Table name (required)
"when": "string", // "before" or "after" (default: "before")
"on_insert": "boolean", // Trigger on insert (default: true)
"on_update": "boolean", // Trigger on update (default: true)
"on_delete": "boolean", // Trigger on delete (default: false)
"script": "string", // GlideScript code (required)
"active": "boolean", // Enable rule (default: true)
"description": "string" // Optional description
}
```
#### `list_business_rules`
List business rules for a table.
**Parameters:**
```json
{
"table": "string", // Table name (required)
"active_only": "boolean" // Only active rules (default: true)
}
```
---
### 📚 Script Includes (2 tools)
#### `create_script_include`
Create a reusable server-side library/include.
**Parameters:**
```json
{
"name": "string", // Include name (required)
"description": "string", // Optional description
"use_class_template": "boolean", // Use class template (default: true)
"client_callable": "boolean", // Callable from client-side (default: false)
"active": "boolean", // Enable include (default: true)
"script": "string" // Optional initial script
}
```
#### `list_script_includes`
List script includes in the instance.
**Parameters:**
```json
{
"search_term": "string", // Optional filter
"active_only": "boolean", // Only active includes (default: true)
"limit": "integer" // Max results (default: 100)
}
```
---
### 🔐 Access Control Lists (2 tools)
#### `create_acl`
Create an access control rule.
**Parameters:**
```json
{
"operation": "string", // "create", "read", "write", "delete" (required)
"table_name": "string", // Table name (required)
"roles": ["string"], // Applicable roles
"script": "string", // Optional GlideScript condition
"description": "string", // Optional description
"active": "boolean" // Enable ACL (default: true)
}
```
#### `list_acls`
List access control rules.
**Parameters:**
```json
{
"table_name": "string", // Filter by table (optional)
"operation": "string", // Filter by operation (optional)
"active_only": "boolean" // Only active ACLs (default: true)
}
```
---
### 🔄 Flow Designer (3 tools)
#### `trigger_flow`
Trigger a Flow Designer flow.
**Parameters:**
```json
{
"flow_id": "string", // Flow ID (e.g., "global.flow_name") (required)
"inputs": { // Flow input variables
"key": "value"
},
"wait_for_completion": "boolean" // Wait for completion (default: false)
}
```
#### `get_flow_execution_status`
Get status of a flow execution.
**Parameters:**
```json
{
"execution_id": "string" // Execution ID (required)
}
```
#### `list_flows`
List available flows.
**Parameters:**
```json
{
"search_term": "string", // Optional filter
"active_only": "boolean", // Only active flows (default: true)
"limit": "integer" // Max results (default: 100)
}
```
---
### 📥 Import Sets (3 tools)
#### `create_import_set_table`
Create an import set staging table.
**Parameters:**
```json
{
"name": "string", // Table name (required)
"label": "string", // Display label
"target_table": "string" // Target import table
}
```
#### `run_import_set`
Load records into an import set and optionally run transformations.
**Parameters:**
```json
{
"staging_table": "string", // Staging table name (required)
"records": [{"field": "value"}], // Records to import (required)
"transform_map_sys_id": "string", // Transform map ID (optional)
"run_transform": "boolean" // Execute transformation (default: false)
}
```
#### `list_transform_maps`
List available transformation maps.
**Parameters:**
```json
{
"search_term": "string", // Optional filter
"limit": "integer" // Max results (default: 100)
}
```
---
### 🌐 Scripted REST APIs (3 tools)
#### `call_scripted_rest_api`
Call a custom Scripted REST API endpoint.
**Parameters:**
```json
{
"api_namespace": "string", // API namespace (required)
"api_id": "string", // API ID (required)
"resource_path": "string", // Optional resource path
"method": "string", // HTTP method: GET, POST, PUT, DELETE
"query_params": { // Optional query parameters
"key": "value"
},
"body": {} // Optional request body (for POST/PUT)
}
```
#### `list_scripted_rest_apis`
List available Scripted REST APIs.
**Parameters:**
```json
{
"search_term": "string", // Optional filter
"active_only": "boolean", // Only active APIs (default: true)
"limit": "integer" // Max results (default: 100)
}
```
#### `get_scripted_rest_resources`
Get resources for a specific Scripted REST API.
**Parameters:**
```json
{
"api_id": "string" // API ID (required)
}
```
---
## 📂 Folder Structure
```
servicenow-mcp/
│
├── .env.example # Environment variable template
├── .gitignore # Git ignore rules
├── pyproject.toml # Python project metadata & dependencies
├── README.md # This file
│
└── src/
└── servicenow_mcp/
├── __init__.py # Package initialization
├── server.py # MCP server & tool registry (108KB)
│ # Contains all 21 tool definitions
│
├── config.py # Configuration management
│ # - Pydantic Settings
│ # - Auth method validation
│ # - Environment variable loading
│
├── client.py # Async HTTP client
│ # - ServiceNowClient class
│ # - OAuth token caching
│ # - Retry logic with Tenacity
│ # - Auth header injection
│
├── logger.py # Structured logging configuration
│ # - JSON-formatted logs
│ # - stderr output
│
└── tools/ # (Modular tools - currently in server.py)
├── __init__.py
├── tables.py # Table management tools
├── fields.py # Field/dictionary tools
├── glide_record.py # GlideRecord query tools
├── business_rules.py # Business rule tools
├── script_includes.py # Script include tools
├── acls.py # ACL management tools
├── flow_designer.py # Flow Designer tools
├── import_sets.py # Import set tools
└── scripted_rest.py # REST API tools
```
### Key Files Explained
| File | Size | Purpose |
|---|---|---|
| `server.py` | ~108 KB | MCP server entry point, all 21 tools defined here, SSE message handling |
| `config.py` | ~4.8 KB | Pydantic configuration with validation for 4 auth methods |
| `client.py` | ~10.7 KB | Async HTTP client with retry logic, auth injection, token caching |
| `logger.py` | ~1.3 KB | Structured logging setup |
| `pyproject.toml` | ~0.8 KB | Package metadata, dependencies, build config |
---
## 🔒 Security Considerations
### Authentication Best Practices
#### 1. **Never Commit Secrets**
```bash
# ❌ Bad – secrets in .env file
SERVICENOW_PASSWORD=SuperSecretPassword123
# ✓ Good – use .gitignore
# .gitignore
.env
.env.local
.env.*.local
```
#### 2. **Use OAuth for Production**
```env
# ✓ Production – OAuth 2.0
SERVICENOW_AUTH_METHOD=oauth
SERVICENOW_OAUTH_CLIENT_ID=${CLIENT_ID} # Set in CI/CD
SERVICENOW_OAUTH_CLIENT_SECRET=${CLIENT_SECRET} # Set in CI/CD
```
#### 3. **Rotate Credentials Regularly**
- Change basic auth passwords every 90 days
- Rotate OAuth client secrets annually
- Revoke unused API keys immediately
#### 4. **Principle of Least Privilege**
```
# Create a dedicated ServiceNow user with minimal permissions
ServiceNow Admin > User Administration > Users
Name: mcp_automation
Active: ✓
Roles: custom_mcp_role (minimal required permissions)
# Define custom role with only necessary permissions
```
### Transport Security
#### **HTTPS Only**
All communication with ServiceNow must use HTTPS:
```env
# ✓ Correct
SERVICENOW_INSTANCE_URL=https://dev12345.service-now.com
# ❌ Incorrect – never use HTTP
SERVICENOW_INSTANCE_URL=http://dev12345.service-now.com
```
#### **TLS Certificate Validation**
The client validates TLS certificates by default. To disable (not recommended):
```python
# In client.py – NOT RECOMMENDED FOR PRODUCTION
client = httpx.AsyncClient(verify=False) # ⚠️ Security risk
```
### Rate Limiting & Throttling
The client includes automatic retry logic for rate limits:
```env
SERVICENOW_MAX_RETRIES=5 # More retries (default: 3)
SERVICENOW_TIMEOUT_SECONDS=60 # Longer timeout (default: 30)
```
### Logging Security
#### **Never Log Passwords or Secrets**
```python
# ✓ Good – redact secrets in logs
log.info(f"Auth method: {method}, User: {user}, Password: ***REDACTED***")
# ❌ Bad – logging credentials
log.debug(f"Auth: {username}:{password}")
```
**Configure log level:**
```env
# Production – minimal logging
LOG_LEVEL=INFO
# Development – detailed logging
LOG_LEVEL=DEBUG
```
### Network Isolation
For maximum security, deploy the MCP server:
1. **Behind a firewall** – Restrict outbound connections to ServiceNow instance only
2. **In a private network** – Not directly exposed to the internet
3. **With VPN** – If accessing remote instances
4. **In containers** – Use Docker with network policies
### Monitoring & Audit
Enable ServiceNow audit logging to track all API calls:
```
ServiceNow Admin > System Audit > Audit Log
Filter: Made By = mcp_automation_user
Sort: Timestamp DESC
```
---
## 🛠️ Development Setup
### Prerequisites
- Python 3.11+
- Git
- VS Code or PyCharm (recommended)
### Setup Development Environment
```bash
# 1. Clone the repository
git clone https://github.com/sudhanshu-singh22/ServiceNow_MCP.git
cd ServiceNow_MCP
# 2. Create virtual environment
python -m venv .venv
# 3. Activate virtual environment
source .venv/bin/activate # macOS/Linux
# or
.venv\Scripts\activate # Windows
# 4. Install in development mode with dev dependencies
pip install -e ".[dev]"
# 5. Create .env file for testing
cp .env.example .env
# Edit .env with your dev instance credentials
```
### Running Tests
```bash
# Run all tests
pytest
# Run with coverage
pytest --cov=src/servicenow_mcp tests/
# Run specific test file
pytest tests/test_client.py -v
# Run tests matching pattern
pytest -k "test_oauth" -v
```
### Code Quality Tools
```bash
# Format code with Ruff
ruff format src/ tests/
# Lint code
ruff check src/ tests/
# Type checking with mypy
mypy src/servicenow_mcp/
# All checks
ruff format . && ruff check . && mypy src/
```
### Development Workflow
1. **Create a feature branch:**
```bash
git checkout -b feature/my-feature
```
2. **Make changes and test:**
```bash
# Edit code
# Run tests
pytest tests/
```
3. **Format and lint:**
```bash
ruff format .
ruff check . --fix
mypy src/
```
4. **Commit and push:**
```bash
git add .
git commit -m "feat: add new feature"
git push origin feature/my-feature
```
5. **Create pull request** on GitHub
### Adding New Tools
To add a new tool to the MCP server:
1. **Define the tool in `server.py`:**
```python
@server.call_tool()
async def handle_my_tool(arguments: dict[str, Any]) -> list[types.TextContent]:
"""
My new tool description.
Args:
arguments: Tool parameters
"""
try:
# Validate inputs
param1 = arguments.get("param1")
if not param1:
raise ValueError("param1 is required")
# Execute tool logic
async with ServiceNowClient() as sn:
result = await sn.some_operation(param1)
return [types.TextContent(type="text", text=json.dumps(result))]
except Exception as e:
error_msg = format_error(e)
return [types.TextContent(type="text", text=f"Error: {error_msg}")]
```
2. **Update tool count** in README
3. **Add tests** in `tests/test_tools.py`
4. **Document** the tool in this README
### Debugging
Enable debug logging:
```bash
LOG_LEVEL=DEBUG servicenow-mcp
```
View MCP server logs (written to stderr):
```bash
servicenow-mcp 2>&1 | tee server.log
```
Connect with a debugger:
```bash
# With debugpy
python -m debugpy --listen 5678 -m servicenow_mcp.server
```
---
## 🤝 Contributing
We welcome contributions! Please follow these guidelines:
### Code of Conduct
Be respectful and inclusive. This project adheres to the Contributor Covenant.
### How to Contribute
1. **Fork the repository** on GitHub
2. **Create a feature branch:**
```bash
git checkout -b feature/amazing-feature
```
3. **Make your changes** with clear commit messages
4. **Add tests** for new functionality
5. **Ensure all tests pass:**
```bash
pytest
```
6. **Format code:**
```bash
ruff format .
ruff check . --fix
```
7. **Push to your fork:**
```bash
git push origin feature/amazing-feature
```
8. **Create a Pull Request** with a clear description
### Pull Request Requirements
- ✅ Tests pass (`pytest`)
- ✅ Code is formatted (`ruff format`)
- ✅ Linting passes (`ruff check`)
- ✅ Type hints are correct (`mypy`)
- ✅ Documentation is updated
- ✅ Changelog is updated
### Reporting Issues
When reporting bugs, include:
- **Python version** (`python --version`)
- **OS** (Windows/macOS/Linux)
- **Error message** and stack trace
- **Steps to reproduce**
- **Expected vs. actual behavior**
- **.env configuration** (redact secrets!)
Example issue template:
```markdown
## Bug Report
**Description:**
Brief description of the issue
**Steps to Reproduce:**
1. Set up with [auth method]
2. Call [tool name] with [parameters]
3. Error occurs
**Error Message:**
```
[Paste error and traceback here]
```
**Environment:**
- Python: 3.11.0
- OS: macOS 13.2
- Auth Method: oauth
```
---
## 🗺️ Roadmap
### ✅ v1.0 (Current)
- [x] 21 core tools for table/record/flow management
- [x] 4 authentication methods
- [x] Retry logic with exponential backoff
- [x] Structured logging
- [x] MCP protocol support
### 🚀 v1.1 (Planned)
- [ ] Service Catalog tools
- [ ] Change Management tools
- [ ] Incident/Problem management tools
- [ ] CMDB integration
- [ ] Advanced query builder
### 📋 v1.2+ (Future)
- [ ] Webhook support
- [ ] GraphQL query support
- [ ] WebSocket streaming
- [ ] Batch operation optimization
- [ ] Caching layer
- [ ] Custom tool framework
- [ ] Plugin system
### 🎯 Long-term Vision
- Multi-instance support
- Distributed/federated MCP servers
- Zero-trust authentication
- AI-assisted query generation
- Natural language to GlideScript translation
---
## 📄 License
This project is licensed under the **MIT License** – see the [LICENSE](LICENSE) file for details.
### Summary
✓ **Free for commercial use**
✓ **Modification allowed**
✓ **Distribution allowed**
✓ **Private use allowed**
✗ **Liability**: As-is, no warranty
✗ **Trademark rights**: Not included
---
## 📞 Support & Community
- **GitHub Issues**: [Report bugs or request features](https://github.com/sudhanshu-singh22/ServiceNow_MCP/issues)
- **Discussions**: [Ask questions and share ideas](https://github.com/sudhanshu-singh22/ServiceNow_MCP/discussions)
- **Documentation**: Read the full docs in this README
---
## 🙏 Acknowledgments
- [Model Context Protocol](https://modelcontextprotocol.io/) – MCP specification
- [Anthropic Claude](https://claude.ai/) – AI agent technology
- [ServiceNow Developer Community](https://developer.servicenow.com/)
- All contributors and users who provide feedback
---
## 🎬 Quick Start Checklist
- [ ] Clone repository
- [ ] Create virtual environment
- [ ] Install package (`pip install -e .`)
- [ ] Create `.env` file
- [ ] Configure authentication
- [ ] Run server (`servicenow-mcp`)
- [ ] Configure MCP client (Claude Desktop / Code)
- [ ] Test with first prompt
- [ ] Read security considerations
- [ ] Set up development environment for contributions
---
**Made with ❤️ by ServiceNow developers for ServiceNow developers**
*Last updated: 2026-06-04*
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available