snow-mcp


Namesnow-mcp JSON
Version 0.1.1 PyPI version JSON
download
home_pageNone
SummaryA comprehensive MCP server for interacting with ServiceNow modules.
upload_time2025-08-23 06:10:44
maintainerNone
docs_urlNone
authorYour Name
requires_python>=3.8
licenseMIT
keywords servicenow mcp fastmcp api automation itsm snow
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # ServiceNow MCP Server (`snow-mcp`)

[![PyPI version](https://badge.fury.io/py/snow-mcp.svg)](https://badge.fury.io/py/snow-mcp)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

A comprehensive, production-ready, and extensible MCP (Machine-Conversation Protocol) server for interacting with a ServiceNow instance. This package provides a rich set of pre-built tools for managing nearly every aspect of ITSM, ITOM, and App Dev within ServiceNow, all callable via a simple, unified interface.

It allows developers and automation engineers to build powerful client applications, scripts, and AI agents that can perform complex, multi-step operations in ServiceNow without needing to handle the intricacies of the REST API directly.

## Features

- **Extensive Tool Library:** Over 60 pre-built tools covering Incidents, Changes, Users, Service Catalog, Projects, and much more.
- **Modular and Organized:** Tools are logically grouped into modules for clarity and extensibility.
- **Production-Ready:** All tools include robust input validation and clear schemas powered by Pydantic.
- **Easy to Use:** Packaged as a standard Python library and installable via `pip`.
- **Self-Documenting:** A built-in CLI allows you to list all available tools directly from your terminal.

## Installation

The server is published on PyPI and can be installed with `pip`. It is recommended to install it in a virtual environment.

```bash
# Create and activate a virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install the package
pip install snow-mcp
```

## Discovering Tools

Once installed, you can easily discover all available tools directly from your command line:

```bash
# List all available tools and their short descriptions
snow-mcp --list-tools
```

## Core Concepts: How to Use the Tools

All tools are called from a Python script using the `fastmcp` client library. Every tool call requires two main components: the client configuration and the parameters payload.

### 1. Client Configuration (Boilerplate)

This setup is the same for any script you write. It tells the client library how to start your `snow-mcp` server.

```python
import asyncio
from fastmcp import Client

client = Client({
    "mcpServers": {
        "servicenow": {
            "command": "snow-mcp",
            "args": [],
            "transport": "stdio"
        }
    }
})
```

### 2. Parameters Payload

Every tool call requires a payload dictionary. This dictionary **must** contain a single key, `"params"`, which holds another dictionary containing your credentials and all tool-specific arguments.

**Credential Setup:**
First, define your credentials. It's best practice to load these from environment variables or a secure vault.

```python
import os

SERVICENOW_CREDS = {
    "instance_url": os.getenv("SNOW_INSTANCE_URL", "https://your-instance.service-now.com"),
    "username": os.getenv("SNOW_USERNAME", "your-api-user"),
    "password": os.getenv("SNOW_PASSWORD", "your-api-password")
}
```

**Putting It Together:**
When you build the payload for a tool, you combine your credentials with the tool's specific parameters.

```python
# Example payload for the 'create_incident' tool
payload = {
    "params": {
        **SERVICENOW_CREDS,
        "short_description": "Network switch is offline",
        "impact": "1",
        "urgency": "1"
    }
}
# Make the call
result = await client.call_tool("create_incident", payload)
```

## Complete Tool Reference

### General & Table Management

#### `get_records_from_table`
Retrieves records from any specified table with advanced filtering, sorting, and pagination.
- **Parameters:**
  - `table_name` (string, required): The name of the table to query (e.g., 'incident').
  - `query` (string, optional): ServiceNow-encoded query (e.g., 'active=true^priority=1').
  - `limit` (integer, optional): The maximum number of records to return.
  - `offset` (integer, optional): The record number to start from.
  - `sort_by` (string, optional): Field to sort by.
  - `sort_dir` (string, optional): Sort direction ('ASC' or 'DESC').
  - `fields` (list of strings, optional): Specific fields to return.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "table_name": "cmdb_ci_server",
          "query": "os=Linux^active=true",
          "limit": 5,
          "fields": ["name", "ip_address"]
      }
  }
  result = await client.call_tool("get_records_from_table", payload)
  ```

#### `get_table_schema`
Retrieves the schema (all column names and their attributes) for a specific table.
- **Parameters:**
  - `table_name` (string, required): The name of the table to get the schema for.
- **Code Example:**
  ```python
  payload = { "params": { **SERVICENOW_CREDS, "table_name": "change_request" } }
  result = await client.call_tool("get_table_schema", payload)
  ```

#### `search_records_by_text`
Performs a search in the common text fields of a table using a LIKE query.
- **Parameters:**
  - `table_name` (string, required): The name of the table to search within.
  - `search_term` (string, required): The text or keyword to search for.
  - `limit` (integer, optional): The maximum number of matching records to return.
- **Code Example:**
  ```python
  payload = { 
      "params": { 
          **SERVICENOW_CREDS, 
          "table_name": "kb_knowledge", 
          "search_term": "password reset" 
      } 
  }
  result = await client.call_tool("search_records_by_text", payload)
  ```

#### `attach_file_to_record`
Attaches a file to any record in ServiceNow.
- **Parameters:**
  - `table_name` (string, required): The table of the record (e.g., 'incident').
  - `record_sys_id` (string, required): The sys_id of the record to attach the file to.
  - `file_name` (string, required): The name of the file (e.g., 'error_log.txt').
  - `file_content_base64` (string, required): The content of the file, encoded in Base64.
- **Code Example:**
  ```python
  import base64
  content = "This is my log file content."
  encoded_content = base64.b64encode(content.encode('utf-8')).decode('utf-8')
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "table_name": "incident",
          "record_sys_id": "paste_incident_sys_id_here",
          "file_name": "log.txt",
          "file_content_base64": encoded_content
      }
  }
  result = await client.call_tool("attach_file_to_record", payload)
  ```

### Incident Management

#### `create_incident`
Creates a new incident record in ServiceNow.
- **Parameters:**
  - `short_description` (string, required): Brief description of the incident.
  - `description` (string, optional): Detailed description of the incident.
  - `impact` (string, optional): Impact level (1-High, 2-Medium, 3-Low).
  - `urgency` (string, optional): Urgency level (1-High, 2-Medium, 3-Low).
  - `priority` (string, optional): Priority (calculated from impact/urgency if not provided).
  - `caller_id` (string, optional): Sys_id of the person reporting the incident.
  - `assigned_to` (string, optional): Sys_id of the assigned user.
  - `assignment_group` (string, optional): Sys_id of the assignment group.
  - `category` (string, optional): Incident category.
  - `subcategory` (string, optional): Incident subcategory.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "short_description": "Email server not responding",
          "description": "Users cannot access email. Server appears to be down.",
          "impact": "2",
          "urgency": "1",
          "category": "Software",
          "subcategory": "Email"
      }
  }
  result = await client.call_tool("create_incident", payload)
  ```

#### `update_incident`
Updates fields on an existing incident.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the incident to update.
  - `short_description` (string, optional): Updated brief description.
  - `description` (string, optional): Updated detailed description.
  - `impact` (string, optional): Updated impact level.
  - `urgency` (string, optional): Updated urgency level.
  - `priority` (string, optional): Updated priority.
  - `state` (string, optional): Updated incident state.
  - `assigned_to` (string, optional): Updated assigned user sys_id.
  - `assignment_group` (string, optional): Updated assignment group sys_id.
  - `resolution_notes` (string, optional): Resolution details.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "abc123def456ghi789",
          "state": "6",  # Resolved
          "resolution_notes": "Restarted email service. Issue resolved."
      }
  }
  result = await client.call_tool("update_incident", payload)
  ```

#### `get_incident_by_number`
Retrieves an incident by its number (e.g., 'INC0010001').
- **Parameters:**
  - `number` (string, required): The incident number.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "number": "INC0010001"
      }
  }
  result = await client.call_tool("get_incident_by_number", payload)
  ```

#### `add_comment_to_incident`
Adds a customer-visible comment to an incident.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the incident.
  - `comment` (string, required): The comment text to add.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "abc123def456ghi789",
          "comment": "Issue has been escalated to network team."
      }
  }
  result = await client.call_tool("add_comment_to_incident", payload)
  ```

#### `add_work_notes_to_incident`
Adds an internal work note to an incident (not visible to customer).
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the incident.
  - `notes` (string, required): The work notes text to add.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "abc123def456ghi789",
          "notes": "Checked server logs. Found memory leak in application."
      }
  }
  result = await client.call_tool("add_work_notes_to_incident", payload)
  ```

### Change Management

#### `create_change_request`
Creates a new change request.
- **Parameters:**
  - `short_description` (string, required): Brief description of the change.
  - `description` (string, optional): Detailed description of the change.
  - `type` (string, optional): Change type (standard, normal, emergency).
  - `risk` (string, optional): Risk assessment (high, medium, low).
  - `impact` (string, optional): Impact level.
  - `priority` (string, optional): Priority level.
  - `requested_by` (string, optional): Sys_id of requesting user.
  - `assigned_to` (string, optional): Sys_id of assigned user.
  - `assignment_group` (string, optional): Sys_id of assignment group.
  - `start_date` (string, optional): Planned start date (YYYY-MM-DD HH:MM:SS).
  - `end_date` (string, optional): Planned end date (YYYY-MM-DD HH:MM:SS).
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "short_description": "Upgrade database server to version 12.5",
          "description": "Scheduled maintenance to upgrade production database",
          "type": "normal",
          "risk": "medium",
          "start_date": "2024-12-01 02:00:00",
          "end_date": "2024-12-01 06:00:00"
      }
  }
  result = await client.call_tool("create_change_request", payload)
  ```

#### `update_change_request`
Updates an existing change request.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the change request.
  - `short_description` (string, optional): Updated description.
  - `state` (string, optional): Updated state.
  - `start_date` (string, optional): Updated start date.
  - `end_date` (string, optional): Updated end date.
  - `risk` (string, optional): Updated risk level.
  - `assigned_to` (string, optional): Updated assigned user.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "def456ghi789jkl012",
          "state": "3",  # Implement
          "start_date": "2024-12-02 02:00:00"
      }
  }
  result = await client.call_tool("update_change_request", payload)
  ```

#### `list_change_requests`
Lists change requests with optional filters.
- **Parameters:**
  - `query` (string, optional): ServiceNow query filter.
  - `limit` (integer, optional): Maximum number of records to return.
  - `offset` (integer, optional): Record offset for pagination.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "query": "state=1^type=normal",  # New normal changes
          "limit": 10
      }
  }
  result = await client.call_tool("list_change_requests", payload)
  ```

#### `get_change_request_details`
Gets details of a specific change by sys_id or number.
- **Parameters:**
  - `sys_id` (string, optional): The sys_id of the change request.
  - `number` (string, optional): The change request number.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "number": "CHG0040001"
      }
  }
  result = await client.call_tool("get_change_request_details", payload)
  ```

#### `add_change_task`
Adds a task to a change request.
- **Parameters:**
  - `change_request_sys_id` (string, required): Sys_id of the parent change request.
  - `short_description` (string, required): Brief description of the task.
  - `description` (string, optional): Detailed description of the task.
  - `assigned_to` (string, optional): Sys_id of assigned user.
  - `assignment_group` (string, optional): Sys_id of assignment group.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "change_request_sys_id": "def456ghi789jkl012",
          "short_description": "Backup database before upgrade",
          "description": "Create full backup of production database"
      }
  }
  result = await client.call_tool("add_change_task", payload)
  ```

#### `submit_change_for_approval`
Moves a change to the 'Assess' state for approval workflow.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the change request.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "def456ghi789jkl012"
      }
  }
  result = await client.call_tool("submit_change_for_approval", payload)
  ```

#### `approve_change`
Approves a change request.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the change request.
  - `approval_notes` (string, optional): Notes for the approval.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "def456ghi789jkl012",
          "approval_notes": "Change approved by CAB. Proceed with implementation."
      }
  }
  result = await client.call_tool("approve_change", payload)
  ```

#### `reject_change`
Rejects a change request.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the change request.
  - `rejection_comments` (string, required): Reason for rejection.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "def456ghi789jkl012",
          "rejection_comments": "Insufficient testing plan provided."
      }
  }
  result = await client.call_tool("reject_change", payload)
  ```

### User & Group Management

#### `create_user`
Creates a new user account in ServiceNow.
- **Parameters:**
  - `first_name` (string, required): User's first name.
  - `last_name` (string, required): User's last name.
  - `user_name` (string, required): Unique username.
  - `email` (string, required): User's email address.
  - `title` (string, optional): Job title.
  - `department` (string, optional): Department sys_id.
  - `manager` (string, optional): Manager's sys_id.
  - `active` (boolean, optional): Whether the user is active (default: true).
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "first_name": "John",
          "last_name": "Doe",
          "user_name": "john.doe",
          "email": "john.doe@company.com",
          "title": "Software Developer"
      }
  }
  result = await client.call_tool("create_user", payload)
  ```

#### `get_user`
Retrieves a user by user_id, user_name, or email.
- **Parameters:**
  - `user_id` (string, optional): The sys_id of the user.
  - `user_name` (string, optional): The username.
  - `email` (string, optional): The user's email address.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "user_name": "john.doe"
      }
  }
  result = await client.call_tool("get_user", payload)
  ```

#### `create_group`
Creates a new group in ServiceNow.
- **Parameters:**
  - `name` (string, required): Group name.
  - `description` (string, optional): Group description.
  - `type` (string, optional): Group type.
  - `manager` (string, optional): Manager's sys_id.
  - `active` (boolean, optional): Whether the group is active (default: true).
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "name": "Development Team",
          "description": "Software development team",
          "type": "itil"
      }
  }
  result = await client.call_tool("create_group", payload)
  ```

#### `add_group_members`
Adds users to a group.
- **Parameters:**
  - `group_sys_id` (string, required): The sys_id of the group.
  - `user_sys_ids` (list of strings, required): List of user sys_ids to add.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "group_sys_id": "ghi789jkl012mno345",
          "user_sys_ids": ["user1_sys_id", "user2_sys_id"]
      }
  }
  result = await client.call_tool("add_group_members", payload)
  ```

#### `remove_group_members`
Removes users from a group.
- **Parameters:**
  - `group_sys_id` (string, required): The sys_id of the group.
  - `user_sys_ids` (list of strings, required): List of user sys_ids to remove.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "group_sys_id": "ghi789jkl012mno345",
          "user_sys_ids": ["user1_sys_id"]
      }
  }
  result = await client.call_tool("remove_group_members", payload)
  ```

### Service Catalog & Request Management

#### `submit_catalog_request`
Orders a specific catalog item.
- **Parameters:**
  - `item_sys_id` (string, required): Sys_id of the catalog item.
  - `variables` (dict, optional): Key-value pairs for catalog item variables.
  - `quantity` (integer, optional): Number of items to request (default: 1).
  - `requested_for` (string, optional): Sys_id of user requesting for.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "item_sys_id": "catalog_item_sys_id_here",
          "variables": {
              "laptop_model": "Dell Latitude 5520",
              "memory": "16GB",
              "storage": "512GB SSD"
          },
          "quantity": 1
      }
  }
  result = await client.call_tool("submit_catalog_request", payload)
  ```

#### `create_request_ticket`
Creates a generic request ticket.
- **Parameters:**
  - `short_description` (string, required): Brief description of the request.
  - `description` (string, optional): Detailed description.
  - `requested_for` (string, optional): Sys_id of user the request is for.
  - `priority` (string, optional): Request priority.
  - `due_date` (string, optional): Due date (YYYY-MM-DD).
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "short_description": "Request for software license",
          "description": "Need Adobe Creative Suite license for design work",
          "priority": "3"
      }
  }
  result = await client.call_tool("create_request_ticket", payload)
  ```

#### `get_requested_item`
Retrieves a Requested Item (RITM) by sys_id or number.
- **Parameters:**
  - `sys_id` (string, optional): The sys_id of the RITM.
  - `number` (string, optional): The RITM number.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "number": "RITM0010001"
      }
  }
  result = await client.call_tool("get_requested_item", payload)
  ```

#### `add_comment_to_request`
Adds a comment to a Request (REQ).
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the request.
  - `comment` (string, required): The comment text.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "request_sys_id_here",
          "comment": "Additional information: User needs access by Friday."
      }
  }
  result = await client.call_tool("add_comment_to_request", payload)
  ```

#### `list_catalog_items`
Lists items from the service catalog.
- **Parameters:**
  - `filter_text` (string, optional): Text to filter catalog items.
  - `limit` (integer, optional): Maximum number of items to return.
  - `category` (string, optional): Category to filter by.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "filter_text": "laptop",
          "limit": 20
      }
  }
  result = await client.call_tool("list_catalog_items", payload)
  ```

#### `create_catalog_item_variable`
Adds a new question/field to a catalog item's form.
- **Parameters:**
  - `item_sys_id` (string, required): Sys_id of the catalog item.
  - `name` (string, required): Variable name (internal).
  - `question_text` (string, required): Question text shown to users.
  - `type` (string, required): Variable type (string, boolean, choice, etc.).
  - `order` (integer, optional): Display order.
  - `mandatory` (boolean, optional): Whether the field is required.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "item_sys_id": "catalog_item_sys_id_here",
          "name": "preferred_color",
          "question_text": "What is your preferred color?",
          "type": "choice",
          "mandatory": False
      }
  }
  result = await client.call_tool("create_catalog_item_variable", payload)
  ```

### Agile Development (Stories, Epics, Scrum Tasks)

#### `create_story`
Creates a new user story.
- **Parameters:**
  - `short_description` (string, required): Brief description of the story.
  - `description` (string, optional): Detailed description.
  - `story_points` (integer, optional): Effort estimation in story points.
  - `sprint` (string, optional): Sys_id of the sprint.
  - `epic` (string, optional): Sys_id of the parent epic.
  - `assigned_to` (string, optional): Sys_id of assigned developer.
  - `state` (string, optional): Story state (draft, ready, active, etc.).
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "short_description": "User login functionality",
          "description": "As a user, I want to log into the system using my credentials",
          "story_points": 5,
          "state": "ready"
      }
  }
  result = await client.call_tool("create_story", payload)
  ```

#### `update_story`
Updates an existing user story.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the story.
  - `short_description` (string, optional): Updated description.
  - `story_points` (integer, optional): Updated story points.
  - `state` (string, optional): Updated state.
  - `assigned_to` (string, optional): Updated assignee.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "story_sys_id_here",
          "state": "complete",
          "story_points": 8
      }
  }
  result = await client.call_tool("update_story", payload)
  ```

#### `create_epic`
Creates a new epic.
- **Parameters:**
  - `short_description` (string, required): Brief description of the epic.
  - `description` (string, optional): Detailed description.
  - `theme` (string, optional): Sys_id of the parent theme.
  - `owner` (string, optional): Sys_id of the epic owner.
  - `state` (string, optional): Epic state.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "short_description": "User Authentication System",
          "description": "Complete user authentication and authorization system",
          "state": "active"
      }
  }
  result = await client.call_tool("create_epic", payload)
  ```

#### `update_epic`
Updates an existing epic.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the epic.
  - `short_description` (string, optional): Updated description.
  - `state` (string, optional): Updated state.
  - `owner` (string, optional): Updated owner.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "epic_sys_id_here",
          "state": "complete"
      }
  }
  result = await client.call_tool("update_epic", payload)
  ```

#### `create_scrum_task`
Creates a new scrum task.
- **Parameters:**
  - `short_description` (string, required): Brief description of the task.
  - `description` (string, optional): Detailed description.
  - `story` (string, optional): Sys_id of the parent story.
  - `assigned_to` (string, optional): Sys_id of assigned team member.
  - `remaining_work` (float, optional): Remaining work in hours.
  - `state` (string, optional): Task state.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "short_description": "Design login page UI",
          "description": "Create mockups and implement login page design",
          "story": "story_sys_id_here",
          "remaining_work": 8.0
      }
  }
  result = await client.call_tool("create_scrum_task", payload)
  ```

#### `update_scrum_task`
Updates an existing scrum task.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the scrum task.
  - `short_description` (string, optional): Updated description.
  - `remaining_work` (float, optional): Updated remaining work.
  - `state` (string, optional): Updated state.
  - `assigned_to` (string, optional): Updated assignee.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "task_sys_id_here",
          "remaining_work": 2.0,
          "state": "in_progress"
      }
  }
  result = await client.call_tool("update_scrum_task", payload)
  ```

### Project Management

#### `create_project`
Creates a new project record.
- **Parameters:**
  - `short_description` (string, required): Brief description of the project.
  - `description` (string, optional): Detailed description.
  - `manager` (string, optional): Sys_id of the project manager.
  - `start_date` (string, optional): Project start date (YYYY-MM-DD).
  - `end_date` (string, optional): Project end date (YYYY-MM-DD).
  - `priority` (string, optional): Project priority.
  - `state` (string, optional): Project state.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "short_description": "Website Redesign Project",
          "description": "Complete redesign of corporate website",
          "start_date": "2024-01-01",
          "end_date": "2024-06-30",
          "priority": "2"
      }
  }
  result = await client.call_tool("create_project", payload)
  ```

#### `update_project`
Updates an existing project.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the project.
  - `short_description` (string, optional): Updated description.
  - `state` (string, optional): Updated state.
  - `manager` (string, optional): Updated manager.
  - `end_date` (string, optional): Updated end date.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "project_sys_id_here",
          "state": "in_progress",
          "end_date": "2024-07-31"
      }
  }
  result = await client.call_tool("update_project", payload)
  ```

#### `list_projects`
Lists projects with optional filters.
- **Parameters:**
  - `query` (string, optional): ServiceNow query filter.
  - `limit` (integer, optional): Maximum number of records to return.
  - `offset` (integer, optional): Record offset for pagination.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "query": "state=in_progress",
          "limit": 10
      }
  }
  result = await client.call_tool("list_projects", payload)
  ```

### Workflow Management

#### `create_workflow`
Creates a new workflow definition.
- **Parameters:**
  - `name` (string, required): Workflow name.
  - `description` (string, optional): Workflow description.
  - `table` (string, optional): Target table for the workflow.
  - `condition` (string, optional): Conditions for workflow execution.
  - `active` (boolean, optional): Whether the workflow is active.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "name": "Incident Auto-Assignment",
          "description": "Automatically assign incidents based on category",
          "table": "incident",
          "active": True
      }
  }
  result = await client.call_tool("create_workflow", payload)
  ```

#### `update_workflow`
Updates a workflow definition.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the workflow.
  - `name` (string, optional): Updated workflow name.
  - `description` (string, optional): Updated description.
  - `active` (boolean, optional): Updated active status.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "workflow_sys_id_here",
          "active": False,
          "description": "Updated workflow description"
      }
  }
  result = await client.call_tool("update_workflow", payload)
  ```

#### `delete_workflow`
Deletes a workflow definition.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the workflow to delete.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "workflow_sys_id_here"
      }
  }
  result = await client.call_tool("delete_workflow", payload)
  ```

### Script Include Management

#### `create_script_include`
Creates a new script include.
- **Parameters:**
  - `name` (string, required): Script include name.
  - `description` (string, optional): Description of the script include.
  - `script` (string, required): JavaScript code for the script include.
  - `api_name` (string, optional): API name (defaults to name).
  - `active` (boolean, optional): Whether the script include is active.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "name": "UtilityFunctions",
          "description": "Common utility functions",
          "script": """
    var UtilityFunctions = Class.create();
    UtilityFunctions.prototype = {
        initialize: function() {
        },
        
        formatDate: function(dateString) {
            // Format date logic here
            return dateString;
        }
    };
            """,
          "active": True
      }
  }
  result = await client.call_tool("create_script_include", payload)
  ```

#### `update_script_include`
Updates the code or properties of a script include.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the script include.
  - `name` (string, optional): Updated name.
  - `description` (string, optional): Updated description.
  - `script` (string, optional): Updated JavaScript code.
  - `active` (boolean, optional): Updated active status.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "script_include_sys_id_here",
          "script": """
    var UtilityFunctions = Class.create();
    UtilityFunctions.prototype = {
        initialize: function() {
        },
        
        formatDate: function(dateString) {
            // Updated format date logic
            return new GlideDateTime(dateString).getDisplayValue();
        }
    };
          """,
          "active": True
      }
  }
  result = await client.call_tool("update_script_include", payload)
  ```

#### `delete_script_include`
Deletes a script include.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the script include to delete.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "script_include_sys_id_here"
      }
  }
  result = await client.call_tool("delete_script_include", payload)
  ```

### Changeset (Update Set) Management

#### `create_changeset`
Creates a new local Update Set.
- **Parameters:**
  - `name` (string, required): Update set name.
  - `description` (string, optional): Update set description.
  - `application` (string, optional): Sys_id of associated application.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "name": "Feature Enhancement v2.1",
          "description": "Update set for new feature enhancements"
      }
  }
  result = await client.call_tool("create_changeset", payload)
  ```

#### `commit_changeset`
Marks a changeset as 'complete'.
- **Parameters:**
  - `sys_id` (string, required): The sys_id of the update set.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "sys_id": "update_set_sys_id_here"
      }
  }
  result = await client.call_tool("commit_changeset", payload)
  ```

#### `list_changesets`
Lists local Update Sets.
- **Parameters:**
  - `query` (string, optional): ServiceNow query filter.
  - `limit` (integer, optional): Maximum number of records to return.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "query": "state=in_progress",
          "limit": 20
      }
  }
  result = await client.call_tool("list_changesets", payload)
  ```

### UI Policy Management

#### `create_ui_policy`
Creates a new UI Policy.
- **Parameters:**
  - `short_description` (string, required): Brief description of the UI policy.
  - `table` (string, required): Target table for the UI policy.
  - `conditions` (string, optional): Conditions for when the policy applies.
  - `on_load` (boolean, optional): Whether to execute on form load.
  - `active` (boolean, optional): Whether the policy is active.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "short_description": "Hide priority when impact is low",
          "table": "incident",
          "conditions": "impact=3",
          "on_load": True,
          "active": True
      }
  }
  result = await client.call_tool("create_ui_policy", payload)
  ```

#### `create_ui_policy_action`
Creates an action for a UI Policy to control a variable's state.
- **Parameters:**
  - `ui_policy_sys_id` (string, required): Sys_id of the parent UI policy.
  - `field` (string, required): Field name to control.
  - `visible` (boolean, optional): Whether the field should be visible.
  - `mandatory` (boolean, optional): Whether the field should be mandatory.
  - `read_only` (boolean, optional): Whether the field should be read-only.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "ui_policy_sys_id": "ui_policy_sys_id_here",
          "field": "priority",
          "visible": False,
          "mandatory": False
      }
  }
  result = await client.call_tool("create_ui_policy_action", payload)
  ```

### Reporting & Analytics

#### `get_aggregate_data`
Performs aggregations (COUNT, SUM, AVG) on any table.
- **Parameters:**
  - `table_name` (string, required): The table for the aggregation.
  - `aggregation_function` (string, required): 'COUNT', 'AVG', 'SUM', 'MIN', or 'MAX'.
  - `field` (string, optional): Field to aggregate (required for SUM, AVG, MIN, MAX).
  - `group_by_fields` (list of strings, optional): Fields to group the results by.
  - `query` (string, optional): A filter query to apply before aggregating.
- **Code Example:**
  ```python
  payload = {
      "params": {
          **SERVICENOW_CREDS,
          "table_name": "incident",
          "aggregation_function": "COUNT",
          "group_by_fields": ["priority", "state"],
          "query": "active=true"
      }
  }
  result = await client.call_tool("get_aggregate_data", payload)
  ```

## Complete Example Script

Here's a complete example showing how to create an incident, add comments, and then resolve it:

```python
import asyncio
import os
from fastmcp import Client

# Set up credentials
SERVICENOW_CREDS = {
    "instance_url": os.getenv("SNOW_INSTANCE_URL"),
    "username": os.getenv("SNOW_USERNAME"),
    "password": os.getenv("SNOW_PASSWORD")
}

async def incident_workflow():
    # Initialize the MCP client
    client = Client({
        "mcpServers": {
            "servicenow": {
                "command": "snow-mcp",
                "args": [],
                "transport": "stdio"
            }
        }
    })
    
    try:
        # 1. Create a new incident
        create_payload = {
            "params": {
                **SERVICENOW_CREDS,
                "short_description": "Database server not responding",
                "description": "Production database server is not responding to connections",
                "impact": "1",  # High
                "urgency": "1",  # High
                "category": "Software",
                "subcategory": "Database"
            }
        }
        
        incident_result = await client.call_tool("create_incident", create_payload)
        incident_sys_id = incident_result["sys_id"]
        print(f"Created incident: {incident_result['number']}")
        
        # 2. Add work notes
        notes_payload = {
            "params": {
                **SERVICENOW_CREDS,
                "sys_id": incident_sys_id,
                "notes": "Checked server status. Database process is not running."
            }
        }
        
        await client.call_tool("add_work_notes_to_incident", notes_payload)
        print("Added work notes")
        
        # 3. Add customer comment
        comment_payload = {
            "params": {
                **SERVICENOW_CREDS,
                "sys_id": incident_sys_id,
                "comment": "We are investigating the database connectivity issue."
            }
        }
        
        await client.call_tool("add_comment_to_incident", comment_payload)
        print("Added customer comment")
        
        # 4. Resolve the incident
        resolve_payload = {
            "params": {
                **SERVICENOW_CREDS,
                "sys_id": incident_sys_id,
                "state": "6",  # Resolved
                "resolution_notes": "Restarted database service. Connection restored."
            }
        }
        
        await client.call_tool("update_incident", resolve_payload)
        print("Incident resolved")
        
    except Exception as e:
        print(f"Error: {e}")

# Run the workflow
if __name__ == "__main__":
    asyncio.run(incident_workflow())
```

## Environment Setup

It's recommended to store your ServiceNow credentials as environment variables:

```bash
# Linux/Mac
export SNOW_INSTANCE_URL="https://your-instance.service-now.com"
export SNOW_USERNAME="your-api-user"
export SNOW_PASSWORD="your-api-password"

# Windows
set SNOW_INSTANCE_URL=https://your-instance.service-now.com
set SNOW_USERNAME=your-api-user
set SNOW_PASSWORD=your-api-password
```

## Error Handling

All tools return structured responses. In case of errors, the response will include error details:

```python
try:
    result = await client.call_tool("create_incident", payload)
    if "error" in result:
        print(f"Error: {result['error']}")
    else:
        print(f"Success: Created incident {result['number']}")
except Exception as e:
    print(f"Exception: {e}")
```

## How It Works

This server is built using the [FastMCP](https://gofastmcp.com/) framework. When a client application calls a tool, FastMCP starts the `snow-mcp` command-line process in the background. The client and server then communicate over `stdio` using the MCP. The server executes the corresponding tool function, makes the necessary REST API calls to ServiceNow, and returns the result to the client. The server process is automatically terminated when the client exits.

## Authentication

The server supports basic authentication with ServiceNow. Make sure your API user has the necessary roles and permissions for the operations you want to perform:

- **itil**: Basic ITSM operations (incidents, changes, requests)
- **catalog_admin**: Service catalog management
- **user_admin**: User and group management
- **admin**: Full administrative access

## Rate Limiting

ServiceNow enforces rate limits on API calls. The server includes built-in retry logic with exponential backoff to handle temporary rate limit errors gracefully.


## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.



## Changelog

### v1.0.0
- Initial release with 60+ tools
- Support for ITSM, ITOM, and App Dev operations
- Complete documentation and examples

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "snow-mcp",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "servicenow, mcp, fastmcp, api, automation, itsm, snow",
    "author": "Your Name",
    "author_email": "Narayan Panigrahy  <narayanpanigrahy18@gmail.com>, Rohit Ranjan  <itzsrohit@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/d5/c0/fb76aa4fef450ee0a55ab40a39fd219bcf9c283710295a8ac4b885c8a9a3/snow_mcp-0.1.1.tar.gz",
    "platform": "any",
    "description": "# ServiceNow MCP Server (`snow-mcp`)\r\n\r\n[![PyPI version](https://badge.fury.io/py/snow-mcp.svg)](https://badge.fury.io/py/snow-mcp)\r\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\r\n\r\nA comprehensive, production-ready, and extensible MCP (Machine-Conversation Protocol) server for interacting with a ServiceNow instance. This package provides a rich set of pre-built tools for managing nearly every aspect of ITSM, ITOM, and App Dev within ServiceNow, all callable via a simple, unified interface.\r\n\r\nIt allows developers and automation engineers to build powerful client applications, scripts, and AI agents that can perform complex, multi-step operations in ServiceNow without needing to handle the intricacies of the REST API directly.\r\n\r\n## Features\r\n\r\n- **Extensive Tool Library:** Over 60 pre-built tools covering Incidents, Changes, Users, Service Catalog, Projects, and much more.\r\n- **Modular and Organized:** Tools are logically grouped into modules for clarity and extensibility.\r\n- **Production-Ready:** All tools include robust input validation and clear schemas powered by Pydantic.\r\n- **Easy to Use:** Packaged as a standard Python library and installable via `pip`.\r\n- **Self-Documenting:** A built-in CLI allows you to list all available tools directly from your terminal.\r\n\r\n## Installation\r\n\r\nThe server is published on PyPI and can be installed with `pip`. It is recommended to install it in a virtual environment.\r\n\r\n```bash\r\n# Create and activate a virtual environment\r\npython -m venv venv\r\nsource venv/bin/activate  # On Windows: venv\\Scripts\\activate\r\n\r\n# Install the package\r\npip install snow-mcp\r\n```\r\n\r\n## Discovering Tools\r\n\r\nOnce installed, you can easily discover all available tools directly from your command line:\r\n\r\n```bash\r\n# List all available tools and their short descriptions\r\nsnow-mcp --list-tools\r\n```\r\n\r\n## Core Concepts: How to Use the Tools\r\n\r\nAll tools are called from a Python script using the `fastmcp` client library. Every tool call requires two main components: the client configuration and the parameters payload.\r\n\r\n### 1. Client Configuration (Boilerplate)\r\n\r\nThis setup is the same for any script you write. It tells the client library how to start your `snow-mcp` server.\r\n\r\n```python\r\nimport asyncio\r\nfrom fastmcp import Client\r\n\r\nclient = Client({\r\n    \"mcpServers\": {\r\n        \"servicenow\": {\r\n            \"command\": \"snow-mcp\",\r\n            \"args\": [],\r\n            \"transport\": \"stdio\"\r\n        }\r\n    }\r\n})\r\n```\r\n\r\n### 2. Parameters Payload\r\n\r\nEvery tool call requires a payload dictionary. This dictionary **must** contain a single key, `\"params\"`, which holds another dictionary containing your credentials and all tool-specific arguments.\r\n\r\n**Credential Setup:**\r\nFirst, define your credentials. It's best practice to load these from environment variables or a secure vault.\r\n\r\n```python\r\nimport os\r\n\r\nSERVICENOW_CREDS = {\r\n    \"instance_url\": os.getenv(\"SNOW_INSTANCE_URL\", \"https://your-instance.service-now.com\"),\r\n    \"username\": os.getenv(\"SNOW_USERNAME\", \"your-api-user\"),\r\n    \"password\": os.getenv(\"SNOW_PASSWORD\", \"your-api-password\")\r\n}\r\n```\r\n\r\n**Putting It Together:**\r\nWhen you build the payload for a tool, you combine your credentials with the tool's specific parameters.\r\n\r\n```python\r\n# Example payload for the 'create_incident' tool\r\npayload = {\r\n    \"params\": {\r\n        **SERVICENOW_CREDS,\r\n        \"short_description\": \"Network switch is offline\",\r\n        \"impact\": \"1\",\r\n        \"urgency\": \"1\"\r\n    }\r\n}\r\n# Make the call\r\nresult = await client.call_tool(\"create_incident\", payload)\r\n```\r\n\r\n## Complete Tool Reference\r\n\r\n### General & Table Management\r\n\r\n#### `get_records_from_table`\r\nRetrieves records from any specified table with advanced filtering, sorting, and pagination.\r\n- **Parameters:**\r\n  - `table_name` (string, required): The name of the table to query (e.g., 'incident').\r\n  - `query` (string, optional): ServiceNow-encoded query (e.g., 'active=true^priority=1').\r\n  - `limit` (integer, optional): The maximum number of records to return.\r\n  - `offset` (integer, optional): The record number to start from.\r\n  - `sort_by` (string, optional): Field to sort by.\r\n  - `sort_dir` (string, optional): Sort direction ('ASC' or 'DESC').\r\n  - `fields` (list of strings, optional): Specific fields to return.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"table_name\": \"cmdb_ci_server\",\r\n          \"query\": \"os=Linux^active=true\",\r\n          \"limit\": 5,\r\n          \"fields\": [\"name\", \"ip_address\"]\r\n      }\r\n  }\r\n  result = await client.call_tool(\"get_records_from_table\", payload)\r\n  ```\r\n\r\n#### `get_table_schema`\r\nRetrieves the schema (all column names and their attributes) for a specific table.\r\n- **Parameters:**\r\n  - `table_name` (string, required): The name of the table to get the schema for.\r\n- **Code Example:**\r\n  ```python\r\n  payload = { \"params\": { **SERVICENOW_CREDS, \"table_name\": \"change_request\" } }\r\n  result = await client.call_tool(\"get_table_schema\", payload)\r\n  ```\r\n\r\n#### `search_records_by_text`\r\nPerforms a search in the common text fields of a table using a LIKE query.\r\n- **Parameters:**\r\n  - `table_name` (string, required): The name of the table to search within.\r\n  - `search_term` (string, required): The text or keyword to search for.\r\n  - `limit` (integer, optional): The maximum number of matching records to return.\r\n- **Code Example:**\r\n  ```python\r\n  payload = { \r\n      \"params\": { \r\n          **SERVICENOW_CREDS, \r\n          \"table_name\": \"kb_knowledge\", \r\n          \"search_term\": \"password reset\" \r\n      } \r\n  }\r\n  result = await client.call_tool(\"search_records_by_text\", payload)\r\n  ```\r\n\r\n#### `attach_file_to_record`\r\nAttaches a file to any record in ServiceNow.\r\n- **Parameters:**\r\n  - `table_name` (string, required): The table of the record (e.g., 'incident').\r\n  - `record_sys_id` (string, required): The sys_id of the record to attach the file to.\r\n  - `file_name` (string, required): The name of the file (e.g., 'error_log.txt').\r\n  - `file_content_base64` (string, required): The content of the file, encoded in Base64.\r\n- **Code Example:**\r\n  ```python\r\n  import base64\r\n  content = \"This is my log file content.\"\r\n  encoded_content = base64.b64encode(content.encode('utf-8')).decode('utf-8')\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"table_name\": \"incident\",\r\n          \"record_sys_id\": \"paste_incident_sys_id_here\",\r\n          \"file_name\": \"log.txt\",\r\n          \"file_content_base64\": encoded_content\r\n      }\r\n  }\r\n  result = await client.call_tool(\"attach_file_to_record\", payload)\r\n  ```\r\n\r\n### Incident Management\r\n\r\n#### `create_incident`\r\nCreates a new incident record in ServiceNow.\r\n- **Parameters:**\r\n  - `short_description` (string, required): Brief description of the incident.\r\n  - `description` (string, optional): Detailed description of the incident.\r\n  - `impact` (string, optional): Impact level (1-High, 2-Medium, 3-Low).\r\n  - `urgency` (string, optional): Urgency level (1-High, 2-Medium, 3-Low).\r\n  - `priority` (string, optional): Priority (calculated from impact/urgency if not provided).\r\n  - `caller_id` (string, optional): Sys_id of the person reporting the incident.\r\n  - `assigned_to` (string, optional): Sys_id of the assigned user.\r\n  - `assignment_group` (string, optional): Sys_id of the assignment group.\r\n  - `category` (string, optional): Incident category.\r\n  - `subcategory` (string, optional): Incident subcategory.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"short_description\": \"Email server not responding\",\r\n          \"description\": \"Users cannot access email. Server appears to be down.\",\r\n          \"impact\": \"2\",\r\n          \"urgency\": \"1\",\r\n          \"category\": \"Software\",\r\n          \"subcategory\": \"Email\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_incident\", payload)\r\n  ```\r\n\r\n#### `update_incident`\r\nUpdates fields on an existing incident.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the incident to update.\r\n  - `short_description` (string, optional): Updated brief description.\r\n  - `description` (string, optional): Updated detailed description.\r\n  - `impact` (string, optional): Updated impact level.\r\n  - `urgency` (string, optional): Updated urgency level.\r\n  - `priority` (string, optional): Updated priority.\r\n  - `state` (string, optional): Updated incident state.\r\n  - `assigned_to` (string, optional): Updated assigned user sys_id.\r\n  - `assignment_group` (string, optional): Updated assignment group sys_id.\r\n  - `resolution_notes` (string, optional): Resolution details.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"abc123def456ghi789\",\r\n          \"state\": \"6\",  # Resolved\r\n          \"resolution_notes\": \"Restarted email service. Issue resolved.\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"update_incident\", payload)\r\n  ```\r\n\r\n#### `get_incident_by_number`\r\nRetrieves an incident by its number (e.g., 'INC0010001').\r\n- **Parameters:**\r\n  - `number` (string, required): The incident number.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"number\": \"INC0010001\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"get_incident_by_number\", payload)\r\n  ```\r\n\r\n#### `add_comment_to_incident`\r\nAdds a customer-visible comment to an incident.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the incident.\r\n  - `comment` (string, required): The comment text to add.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"abc123def456ghi789\",\r\n          \"comment\": \"Issue has been escalated to network team.\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"add_comment_to_incident\", payload)\r\n  ```\r\n\r\n#### `add_work_notes_to_incident`\r\nAdds an internal work note to an incident (not visible to customer).\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the incident.\r\n  - `notes` (string, required): The work notes text to add.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"abc123def456ghi789\",\r\n          \"notes\": \"Checked server logs. Found memory leak in application.\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"add_work_notes_to_incident\", payload)\r\n  ```\r\n\r\n### Change Management\r\n\r\n#### `create_change_request`\r\nCreates a new change request.\r\n- **Parameters:**\r\n  - `short_description` (string, required): Brief description of the change.\r\n  - `description` (string, optional): Detailed description of the change.\r\n  - `type` (string, optional): Change type (standard, normal, emergency).\r\n  - `risk` (string, optional): Risk assessment (high, medium, low).\r\n  - `impact` (string, optional): Impact level.\r\n  - `priority` (string, optional): Priority level.\r\n  - `requested_by` (string, optional): Sys_id of requesting user.\r\n  - `assigned_to` (string, optional): Sys_id of assigned user.\r\n  - `assignment_group` (string, optional): Sys_id of assignment group.\r\n  - `start_date` (string, optional): Planned start date (YYYY-MM-DD HH:MM:SS).\r\n  - `end_date` (string, optional): Planned end date (YYYY-MM-DD HH:MM:SS).\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"short_description\": \"Upgrade database server to version 12.5\",\r\n          \"description\": \"Scheduled maintenance to upgrade production database\",\r\n          \"type\": \"normal\",\r\n          \"risk\": \"medium\",\r\n          \"start_date\": \"2024-12-01 02:00:00\",\r\n          \"end_date\": \"2024-12-01 06:00:00\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_change_request\", payload)\r\n  ```\r\n\r\n#### `update_change_request`\r\nUpdates an existing change request.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the change request.\r\n  - `short_description` (string, optional): Updated description.\r\n  - `state` (string, optional): Updated state.\r\n  - `start_date` (string, optional): Updated start date.\r\n  - `end_date` (string, optional): Updated end date.\r\n  - `risk` (string, optional): Updated risk level.\r\n  - `assigned_to` (string, optional): Updated assigned user.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"def456ghi789jkl012\",\r\n          \"state\": \"3\",  # Implement\r\n          \"start_date\": \"2024-12-02 02:00:00\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"update_change_request\", payload)\r\n  ```\r\n\r\n#### `list_change_requests`\r\nLists change requests with optional filters.\r\n- **Parameters:**\r\n  - `query` (string, optional): ServiceNow query filter.\r\n  - `limit` (integer, optional): Maximum number of records to return.\r\n  - `offset` (integer, optional): Record offset for pagination.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"query\": \"state=1^type=normal\",  # New normal changes\r\n          \"limit\": 10\r\n      }\r\n  }\r\n  result = await client.call_tool(\"list_change_requests\", payload)\r\n  ```\r\n\r\n#### `get_change_request_details`\r\nGets details of a specific change by sys_id or number.\r\n- **Parameters:**\r\n  - `sys_id` (string, optional): The sys_id of the change request.\r\n  - `number` (string, optional): The change request number.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"number\": \"CHG0040001\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"get_change_request_details\", payload)\r\n  ```\r\n\r\n#### `add_change_task`\r\nAdds a task to a change request.\r\n- **Parameters:**\r\n  - `change_request_sys_id` (string, required): Sys_id of the parent change request.\r\n  - `short_description` (string, required): Brief description of the task.\r\n  - `description` (string, optional): Detailed description of the task.\r\n  - `assigned_to` (string, optional): Sys_id of assigned user.\r\n  - `assignment_group` (string, optional): Sys_id of assignment group.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"change_request_sys_id\": \"def456ghi789jkl012\",\r\n          \"short_description\": \"Backup database before upgrade\",\r\n          \"description\": \"Create full backup of production database\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"add_change_task\", payload)\r\n  ```\r\n\r\n#### `submit_change_for_approval`\r\nMoves a change to the 'Assess' state for approval workflow.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the change request.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"def456ghi789jkl012\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"submit_change_for_approval\", payload)\r\n  ```\r\n\r\n#### `approve_change`\r\nApproves a change request.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the change request.\r\n  - `approval_notes` (string, optional): Notes for the approval.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"def456ghi789jkl012\",\r\n          \"approval_notes\": \"Change approved by CAB. Proceed with implementation.\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"approve_change\", payload)\r\n  ```\r\n\r\n#### `reject_change`\r\nRejects a change request.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the change request.\r\n  - `rejection_comments` (string, required): Reason for rejection.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"def456ghi789jkl012\",\r\n          \"rejection_comments\": \"Insufficient testing plan provided.\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"reject_change\", payload)\r\n  ```\r\n\r\n### User & Group Management\r\n\r\n#### `create_user`\r\nCreates a new user account in ServiceNow.\r\n- **Parameters:**\r\n  - `first_name` (string, required): User's first name.\r\n  - `last_name` (string, required): User's last name.\r\n  - `user_name` (string, required): Unique username.\r\n  - `email` (string, required): User's email address.\r\n  - `title` (string, optional): Job title.\r\n  - `department` (string, optional): Department sys_id.\r\n  - `manager` (string, optional): Manager's sys_id.\r\n  - `active` (boolean, optional): Whether the user is active (default: true).\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"first_name\": \"John\",\r\n          \"last_name\": \"Doe\",\r\n          \"user_name\": \"john.doe\",\r\n          \"email\": \"john.doe@company.com\",\r\n          \"title\": \"Software Developer\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_user\", payload)\r\n  ```\r\n\r\n#### `get_user`\r\nRetrieves a user by user_id, user_name, or email.\r\n- **Parameters:**\r\n  - `user_id` (string, optional): The sys_id of the user.\r\n  - `user_name` (string, optional): The username.\r\n  - `email` (string, optional): The user's email address.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"user_name\": \"john.doe\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"get_user\", payload)\r\n  ```\r\n\r\n#### `create_group`\r\nCreates a new group in ServiceNow.\r\n- **Parameters:**\r\n  - `name` (string, required): Group name.\r\n  - `description` (string, optional): Group description.\r\n  - `type` (string, optional): Group type.\r\n  - `manager` (string, optional): Manager's sys_id.\r\n  - `active` (boolean, optional): Whether the group is active (default: true).\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"name\": \"Development Team\",\r\n          \"description\": \"Software development team\",\r\n          \"type\": \"itil\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_group\", payload)\r\n  ```\r\n\r\n#### `add_group_members`\r\nAdds users to a group.\r\n- **Parameters:**\r\n  - `group_sys_id` (string, required): The sys_id of the group.\r\n  - `user_sys_ids` (list of strings, required): List of user sys_ids to add.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"group_sys_id\": \"ghi789jkl012mno345\",\r\n          \"user_sys_ids\": [\"user1_sys_id\", \"user2_sys_id\"]\r\n      }\r\n  }\r\n  result = await client.call_tool(\"add_group_members\", payload)\r\n  ```\r\n\r\n#### `remove_group_members`\r\nRemoves users from a group.\r\n- **Parameters:**\r\n  - `group_sys_id` (string, required): The sys_id of the group.\r\n  - `user_sys_ids` (list of strings, required): List of user sys_ids to remove.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"group_sys_id\": \"ghi789jkl012mno345\",\r\n          \"user_sys_ids\": [\"user1_sys_id\"]\r\n      }\r\n  }\r\n  result = await client.call_tool(\"remove_group_members\", payload)\r\n  ```\r\n\r\n### Service Catalog & Request Management\r\n\r\n#### `submit_catalog_request`\r\nOrders a specific catalog item.\r\n- **Parameters:**\r\n  - `item_sys_id` (string, required): Sys_id of the catalog item.\r\n  - `variables` (dict, optional): Key-value pairs for catalog item variables.\r\n  - `quantity` (integer, optional): Number of items to request (default: 1).\r\n  - `requested_for` (string, optional): Sys_id of user requesting for.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"item_sys_id\": \"catalog_item_sys_id_here\",\r\n          \"variables\": {\r\n              \"laptop_model\": \"Dell Latitude 5520\",\r\n              \"memory\": \"16GB\",\r\n              \"storage\": \"512GB SSD\"\r\n          },\r\n          \"quantity\": 1\r\n      }\r\n  }\r\n  result = await client.call_tool(\"submit_catalog_request\", payload)\r\n  ```\r\n\r\n#### `create_request_ticket`\r\nCreates a generic request ticket.\r\n- **Parameters:**\r\n  - `short_description` (string, required): Brief description of the request.\r\n  - `description` (string, optional): Detailed description.\r\n  - `requested_for` (string, optional): Sys_id of user the request is for.\r\n  - `priority` (string, optional): Request priority.\r\n  - `due_date` (string, optional): Due date (YYYY-MM-DD).\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"short_description\": \"Request for software license\",\r\n          \"description\": \"Need Adobe Creative Suite license for design work\",\r\n          \"priority\": \"3\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_request_ticket\", payload)\r\n  ```\r\n\r\n#### `get_requested_item`\r\nRetrieves a Requested Item (RITM) by sys_id or number.\r\n- **Parameters:**\r\n  - `sys_id` (string, optional): The sys_id of the RITM.\r\n  - `number` (string, optional): The RITM number.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"number\": \"RITM0010001\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"get_requested_item\", payload)\r\n  ```\r\n\r\n#### `add_comment_to_request`\r\nAdds a comment to a Request (REQ).\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the request.\r\n  - `comment` (string, required): The comment text.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"request_sys_id_here\",\r\n          \"comment\": \"Additional information: User needs access by Friday.\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"add_comment_to_request\", payload)\r\n  ```\r\n\r\n#### `list_catalog_items`\r\nLists items from the service catalog.\r\n- **Parameters:**\r\n  - `filter_text` (string, optional): Text to filter catalog items.\r\n  - `limit` (integer, optional): Maximum number of items to return.\r\n  - `category` (string, optional): Category to filter by.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"filter_text\": \"laptop\",\r\n          \"limit\": 20\r\n      }\r\n  }\r\n  result = await client.call_tool(\"list_catalog_items\", payload)\r\n  ```\r\n\r\n#### `create_catalog_item_variable`\r\nAdds a new question/field to a catalog item's form.\r\n- **Parameters:**\r\n  - `item_sys_id` (string, required): Sys_id of the catalog item.\r\n  - `name` (string, required): Variable name (internal).\r\n  - `question_text` (string, required): Question text shown to users.\r\n  - `type` (string, required): Variable type (string, boolean, choice, etc.).\r\n  - `order` (integer, optional): Display order.\r\n  - `mandatory` (boolean, optional): Whether the field is required.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"item_sys_id\": \"catalog_item_sys_id_here\",\r\n          \"name\": \"preferred_color\",\r\n          \"question_text\": \"What is your preferred color?\",\r\n          \"type\": \"choice\",\r\n          \"mandatory\": False\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_catalog_item_variable\", payload)\r\n  ```\r\n\r\n### Agile Development (Stories, Epics, Scrum Tasks)\r\n\r\n#### `create_story`\r\nCreates a new user story.\r\n- **Parameters:**\r\n  - `short_description` (string, required): Brief description of the story.\r\n  - `description` (string, optional): Detailed description.\r\n  - `story_points` (integer, optional): Effort estimation in story points.\r\n  - `sprint` (string, optional): Sys_id of the sprint.\r\n  - `epic` (string, optional): Sys_id of the parent epic.\r\n  - `assigned_to` (string, optional): Sys_id of assigned developer.\r\n  - `state` (string, optional): Story state (draft, ready, active, etc.).\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"short_description\": \"User login functionality\",\r\n          \"description\": \"As a user, I want to log into the system using my credentials\",\r\n          \"story_points\": 5,\r\n          \"state\": \"ready\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_story\", payload)\r\n  ```\r\n\r\n#### `update_story`\r\nUpdates an existing user story.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the story.\r\n  - `short_description` (string, optional): Updated description.\r\n  - `story_points` (integer, optional): Updated story points.\r\n  - `state` (string, optional): Updated state.\r\n  - `assigned_to` (string, optional): Updated assignee.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"story_sys_id_here\",\r\n          \"state\": \"complete\",\r\n          \"story_points\": 8\r\n      }\r\n  }\r\n  result = await client.call_tool(\"update_story\", payload)\r\n  ```\r\n\r\n#### `create_epic`\r\nCreates a new epic.\r\n- **Parameters:**\r\n  - `short_description` (string, required): Brief description of the epic.\r\n  - `description` (string, optional): Detailed description.\r\n  - `theme` (string, optional): Sys_id of the parent theme.\r\n  - `owner` (string, optional): Sys_id of the epic owner.\r\n  - `state` (string, optional): Epic state.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"short_description\": \"User Authentication System\",\r\n          \"description\": \"Complete user authentication and authorization system\",\r\n          \"state\": \"active\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_epic\", payload)\r\n  ```\r\n\r\n#### `update_epic`\r\nUpdates an existing epic.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the epic.\r\n  - `short_description` (string, optional): Updated description.\r\n  - `state` (string, optional): Updated state.\r\n  - `owner` (string, optional): Updated owner.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"epic_sys_id_here\",\r\n          \"state\": \"complete\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"update_epic\", payload)\r\n  ```\r\n\r\n#### `create_scrum_task`\r\nCreates a new scrum task.\r\n- **Parameters:**\r\n  - `short_description` (string, required): Brief description of the task.\r\n  - `description` (string, optional): Detailed description.\r\n  - `story` (string, optional): Sys_id of the parent story.\r\n  - `assigned_to` (string, optional): Sys_id of assigned team member.\r\n  - `remaining_work` (float, optional): Remaining work in hours.\r\n  - `state` (string, optional): Task state.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"short_description\": \"Design login page UI\",\r\n          \"description\": \"Create mockups and implement login page design\",\r\n          \"story\": \"story_sys_id_here\",\r\n          \"remaining_work\": 8.0\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_scrum_task\", payload)\r\n  ```\r\n\r\n#### `update_scrum_task`\r\nUpdates an existing scrum task.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the scrum task.\r\n  - `short_description` (string, optional): Updated description.\r\n  - `remaining_work` (float, optional): Updated remaining work.\r\n  - `state` (string, optional): Updated state.\r\n  - `assigned_to` (string, optional): Updated assignee.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"task_sys_id_here\",\r\n          \"remaining_work\": 2.0,\r\n          \"state\": \"in_progress\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"update_scrum_task\", payload)\r\n  ```\r\n\r\n### Project Management\r\n\r\n#### `create_project`\r\nCreates a new project record.\r\n- **Parameters:**\r\n  - `short_description` (string, required): Brief description of the project.\r\n  - `description` (string, optional): Detailed description.\r\n  - `manager` (string, optional): Sys_id of the project manager.\r\n  - `start_date` (string, optional): Project start date (YYYY-MM-DD).\r\n  - `end_date` (string, optional): Project end date (YYYY-MM-DD).\r\n  - `priority` (string, optional): Project priority.\r\n  - `state` (string, optional): Project state.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"short_description\": \"Website Redesign Project\",\r\n          \"description\": \"Complete redesign of corporate website\",\r\n          \"start_date\": \"2024-01-01\",\r\n          \"end_date\": \"2024-06-30\",\r\n          \"priority\": \"2\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_project\", payload)\r\n  ```\r\n\r\n#### `update_project`\r\nUpdates an existing project.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the project.\r\n  - `short_description` (string, optional): Updated description.\r\n  - `state` (string, optional): Updated state.\r\n  - `manager` (string, optional): Updated manager.\r\n  - `end_date` (string, optional): Updated end date.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"project_sys_id_here\",\r\n          \"state\": \"in_progress\",\r\n          \"end_date\": \"2024-07-31\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"update_project\", payload)\r\n  ```\r\n\r\n#### `list_projects`\r\nLists projects with optional filters.\r\n- **Parameters:**\r\n  - `query` (string, optional): ServiceNow query filter.\r\n  - `limit` (integer, optional): Maximum number of records to return.\r\n  - `offset` (integer, optional): Record offset for pagination.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"query\": \"state=in_progress\",\r\n          \"limit\": 10\r\n      }\r\n  }\r\n  result = await client.call_tool(\"list_projects\", payload)\r\n  ```\r\n\r\n### Workflow Management\r\n\r\n#### `create_workflow`\r\nCreates a new workflow definition.\r\n- **Parameters:**\r\n  - `name` (string, required): Workflow name.\r\n  - `description` (string, optional): Workflow description.\r\n  - `table` (string, optional): Target table for the workflow.\r\n  - `condition` (string, optional): Conditions for workflow execution.\r\n  - `active` (boolean, optional): Whether the workflow is active.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"name\": \"Incident Auto-Assignment\",\r\n          \"description\": \"Automatically assign incidents based on category\",\r\n          \"table\": \"incident\",\r\n          \"active\": True\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_workflow\", payload)\r\n  ```\r\n\r\n#### `update_workflow`\r\nUpdates a workflow definition.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the workflow.\r\n  - `name` (string, optional): Updated workflow name.\r\n  - `description` (string, optional): Updated description.\r\n  - `active` (boolean, optional): Updated active status.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"workflow_sys_id_here\",\r\n          \"active\": False,\r\n          \"description\": \"Updated workflow description\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"update_workflow\", payload)\r\n  ```\r\n\r\n#### `delete_workflow`\r\nDeletes a workflow definition.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the workflow to delete.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"workflow_sys_id_here\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"delete_workflow\", payload)\r\n  ```\r\n\r\n### Script Include Management\r\n\r\n#### `create_script_include`\r\nCreates a new script include.\r\n- **Parameters:**\r\n  - `name` (string, required): Script include name.\r\n  - `description` (string, optional): Description of the script include.\r\n  - `script` (string, required): JavaScript code for the script include.\r\n  - `api_name` (string, optional): API name (defaults to name).\r\n  - `active` (boolean, optional): Whether the script include is active.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"name\": \"UtilityFunctions\",\r\n          \"description\": \"Common utility functions\",\r\n          \"script\": \"\"\"\r\n    var UtilityFunctions = Class.create();\r\n    UtilityFunctions.prototype = {\r\n        initialize: function() {\r\n        },\r\n        \r\n        formatDate: function(dateString) {\r\n            // Format date logic here\r\n            return dateString;\r\n        }\r\n    };\r\n            \"\"\",\r\n          \"active\": True\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_script_include\", payload)\r\n  ```\r\n\r\n#### `update_script_include`\r\nUpdates the code or properties of a script include.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the script include.\r\n  - `name` (string, optional): Updated name.\r\n  - `description` (string, optional): Updated description.\r\n  - `script` (string, optional): Updated JavaScript code.\r\n  - `active` (boolean, optional): Updated active status.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"script_include_sys_id_here\",\r\n          \"script\": \"\"\"\r\n    var UtilityFunctions = Class.create();\r\n    UtilityFunctions.prototype = {\r\n        initialize: function() {\r\n        },\r\n        \r\n        formatDate: function(dateString) {\r\n            // Updated format date logic\r\n            return new GlideDateTime(dateString).getDisplayValue();\r\n        }\r\n    };\r\n          \"\"\",\r\n          \"active\": True\r\n      }\r\n  }\r\n  result = await client.call_tool(\"update_script_include\", payload)\r\n  ```\r\n\r\n#### `delete_script_include`\r\nDeletes a script include.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the script include to delete.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"script_include_sys_id_here\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"delete_script_include\", payload)\r\n  ```\r\n\r\n### Changeset (Update Set) Management\r\n\r\n#### `create_changeset`\r\nCreates a new local Update Set.\r\n- **Parameters:**\r\n  - `name` (string, required): Update set name.\r\n  - `description` (string, optional): Update set description.\r\n  - `application` (string, optional): Sys_id of associated application.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"name\": \"Feature Enhancement v2.1\",\r\n          \"description\": \"Update set for new feature enhancements\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_changeset\", payload)\r\n  ```\r\n\r\n#### `commit_changeset`\r\nMarks a changeset as 'complete'.\r\n- **Parameters:**\r\n  - `sys_id` (string, required): The sys_id of the update set.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"sys_id\": \"update_set_sys_id_here\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"commit_changeset\", payload)\r\n  ```\r\n\r\n#### `list_changesets`\r\nLists local Update Sets.\r\n- **Parameters:**\r\n  - `query` (string, optional): ServiceNow query filter.\r\n  - `limit` (integer, optional): Maximum number of records to return.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"query\": \"state=in_progress\",\r\n          \"limit\": 20\r\n      }\r\n  }\r\n  result = await client.call_tool(\"list_changesets\", payload)\r\n  ```\r\n\r\n### UI Policy Management\r\n\r\n#### `create_ui_policy`\r\nCreates a new UI Policy.\r\n- **Parameters:**\r\n  - `short_description` (string, required): Brief description of the UI policy.\r\n  - `table` (string, required): Target table for the UI policy.\r\n  - `conditions` (string, optional): Conditions for when the policy applies.\r\n  - `on_load` (boolean, optional): Whether to execute on form load.\r\n  - `active` (boolean, optional): Whether the policy is active.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"short_description\": \"Hide priority when impact is low\",\r\n          \"table\": \"incident\",\r\n          \"conditions\": \"impact=3\",\r\n          \"on_load\": True,\r\n          \"active\": True\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_ui_policy\", payload)\r\n  ```\r\n\r\n#### `create_ui_policy_action`\r\nCreates an action for a UI Policy to control a variable's state.\r\n- **Parameters:**\r\n  - `ui_policy_sys_id` (string, required): Sys_id of the parent UI policy.\r\n  - `field` (string, required): Field name to control.\r\n  - `visible` (boolean, optional): Whether the field should be visible.\r\n  - `mandatory` (boolean, optional): Whether the field should be mandatory.\r\n  - `read_only` (boolean, optional): Whether the field should be read-only.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"ui_policy_sys_id\": \"ui_policy_sys_id_here\",\r\n          \"field\": \"priority\",\r\n          \"visible\": False,\r\n          \"mandatory\": False\r\n      }\r\n  }\r\n  result = await client.call_tool(\"create_ui_policy_action\", payload)\r\n  ```\r\n\r\n### Reporting & Analytics\r\n\r\n#### `get_aggregate_data`\r\nPerforms aggregations (COUNT, SUM, AVG) on any table.\r\n- **Parameters:**\r\n  - `table_name` (string, required): The table for the aggregation.\r\n  - `aggregation_function` (string, required): 'COUNT', 'AVG', 'SUM', 'MIN', or 'MAX'.\r\n  - `field` (string, optional): Field to aggregate (required for SUM, AVG, MIN, MAX).\r\n  - `group_by_fields` (list of strings, optional): Fields to group the results by.\r\n  - `query` (string, optional): A filter query to apply before aggregating.\r\n- **Code Example:**\r\n  ```python\r\n  payload = {\r\n      \"params\": {\r\n          **SERVICENOW_CREDS,\r\n          \"table_name\": \"incident\",\r\n          \"aggregation_function\": \"COUNT\",\r\n          \"group_by_fields\": [\"priority\", \"state\"],\r\n          \"query\": \"active=true\"\r\n      }\r\n  }\r\n  result = await client.call_tool(\"get_aggregate_data\", payload)\r\n  ```\r\n\r\n## Complete Example Script\r\n\r\nHere's a complete example showing how to create an incident, add comments, and then resolve it:\r\n\r\n```python\r\nimport asyncio\r\nimport os\r\nfrom fastmcp import Client\r\n\r\n# Set up credentials\r\nSERVICENOW_CREDS = {\r\n    \"instance_url\": os.getenv(\"SNOW_INSTANCE_URL\"),\r\n    \"username\": os.getenv(\"SNOW_USERNAME\"),\r\n    \"password\": os.getenv(\"SNOW_PASSWORD\")\r\n}\r\n\r\nasync def incident_workflow():\r\n    # Initialize the MCP client\r\n    client = Client({\r\n        \"mcpServers\": {\r\n            \"servicenow\": {\r\n                \"command\": \"snow-mcp\",\r\n                \"args\": [],\r\n                \"transport\": \"stdio\"\r\n            }\r\n        }\r\n    })\r\n    \r\n    try:\r\n        # 1. Create a new incident\r\n        create_payload = {\r\n            \"params\": {\r\n                **SERVICENOW_CREDS,\r\n                \"short_description\": \"Database server not responding\",\r\n                \"description\": \"Production database server is not responding to connections\",\r\n                \"impact\": \"1\",  # High\r\n                \"urgency\": \"1\",  # High\r\n                \"category\": \"Software\",\r\n                \"subcategory\": \"Database\"\r\n            }\r\n        }\r\n        \r\n        incident_result = await client.call_tool(\"create_incident\", create_payload)\r\n        incident_sys_id = incident_result[\"sys_id\"]\r\n        print(f\"Created incident: {incident_result['number']}\")\r\n        \r\n        # 2. Add work notes\r\n        notes_payload = {\r\n            \"params\": {\r\n                **SERVICENOW_CREDS,\r\n                \"sys_id\": incident_sys_id,\r\n                \"notes\": \"Checked server status. Database process is not running.\"\r\n            }\r\n        }\r\n        \r\n        await client.call_tool(\"add_work_notes_to_incident\", notes_payload)\r\n        print(\"Added work notes\")\r\n        \r\n        # 3. Add customer comment\r\n        comment_payload = {\r\n            \"params\": {\r\n                **SERVICENOW_CREDS,\r\n                \"sys_id\": incident_sys_id,\r\n                \"comment\": \"We are investigating the database connectivity issue.\"\r\n            }\r\n        }\r\n        \r\n        await client.call_tool(\"add_comment_to_incident\", comment_payload)\r\n        print(\"Added customer comment\")\r\n        \r\n        # 4. Resolve the incident\r\n        resolve_payload = {\r\n            \"params\": {\r\n                **SERVICENOW_CREDS,\r\n                \"sys_id\": incident_sys_id,\r\n                \"state\": \"6\",  # Resolved\r\n                \"resolution_notes\": \"Restarted database service. Connection restored.\"\r\n            }\r\n        }\r\n        \r\n        await client.call_tool(\"update_incident\", resolve_payload)\r\n        print(\"Incident resolved\")\r\n        \r\n    except Exception as e:\r\n        print(f\"Error: {e}\")\r\n\r\n# Run the workflow\r\nif __name__ == \"__main__\":\r\n    asyncio.run(incident_workflow())\r\n```\r\n\r\n## Environment Setup\r\n\r\nIt's recommended to store your ServiceNow credentials as environment variables:\r\n\r\n```bash\r\n# Linux/Mac\r\nexport SNOW_INSTANCE_URL=\"https://your-instance.service-now.com\"\r\nexport SNOW_USERNAME=\"your-api-user\"\r\nexport SNOW_PASSWORD=\"your-api-password\"\r\n\r\n# Windows\r\nset SNOW_INSTANCE_URL=https://your-instance.service-now.com\r\nset SNOW_USERNAME=your-api-user\r\nset SNOW_PASSWORD=your-api-password\r\n```\r\n\r\n## Error Handling\r\n\r\nAll tools return structured responses. In case of errors, the response will include error details:\r\n\r\n```python\r\ntry:\r\n    result = await client.call_tool(\"create_incident\", payload)\r\n    if \"error\" in result:\r\n        print(f\"Error: {result['error']}\")\r\n    else:\r\n        print(f\"Success: Created incident {result['number']}\")\r\nexcept Exception as e:\r\n    print(f\"Exception: {e}\")\r\n```\r\n\r\n## How It Works\r\n\r\nThis server is built using the [FastMCP](https://gofastmcp.com/) framework. When a client application calls a tool, FastMCP starts the `snow-mcp` command-line process in the background. The client and server then communicate over `stdio` using the MCP. The server executes the corresponding tool function, makes the necessary REST API calls to ServiceNow, and returns the result to the client. The server process is automatically terminated when the client exits.\r\n\r\n## Authentication\r\n\r\nThe server supports basic authentication with ServiceNow. Make sure your API user has the necessary roles and permissions for the operations you want to perform:\r\n\r\n- **itil**: Basic ITSM operations (incidents, changes, requests)\r\n- **catalog_admin**: Service catalog management\r\n- **user_admin**: User and group management\r\n- **admin**: Full administrative access\r\n\r\n## Rate Limiting\r\n\r\nServiceNow enforces rate limits on API calls. The server includes built-in retry logic with exponential backoff to handle temporary rate limit errors gracefully.\r\n\r\n\r\n## License\r\n\r\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\r\n\r\n\r\n\r\n## Changelog\r\n\r\n### v1.0.0\r\n- Initial release with 60+ tools\r\n- Support for ITSM, ITOM, and App Dev operations\r\n- Complete documentation and examples\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A comprehensive MCP server for interacting with ServiceNow modules.",
    "version": "0.1.1",
    "project_urls": null,
    "split_keywords": [
        "servicenow",
        " mcp",
        " fastmcp",
        " api",
        " automation",
        " itsm",
        " snow"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "1b8f2abb25cd84c6e7f1335c6b723c4b7484eaddeeb1537663b60087b6ddcfbb",
                "md5": "3735696a2101534e1c080c67c3dc1c68",
                "sha256": "0b56acf4e29818ceecd8140cbc612e491a2ac039ae36623386dd508ed9e8a32d"
            },
            "downloads": -1,
            "filename": "snow_mcp-0.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "3735696a2101534e1c080c67c3dc1c68",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 52359,
            "upload_time": "2025-08-23T06:10:42",
            "upload_time_iso_8601": "2025-08-23T06:10:42.801973Z",
            "url": "https://files.pythonhosted.org/packages/1b/8f/2abb25cd84c6e7f1335c6b723c4b7484eaddeeb1537663b60087b6ddcfbb/snow_mcp-0.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d5c0fb76aa4fef450ee0a55ab40a39fd219bcf9c283710295a8ac4b885c8a9a3",
                "md5": "b1edb478e0cdf85b2feed1384e968ea9",
                "sha256": "599177a4748d83c5d54a6947a8a6d8a439f97fbed9c593b2e279ae10eab46760"
            },
            "downloads": -1,
            "filename": "snow_mcp-0.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "b1edb478e0cdf85b2feed1384e968ea9",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 52440,
            "upload_time": "2025-08-23T06:10:44",
            "upload_time_iso_8601": "2025-08-23T06:10:44.562094Z",
            "url": "https://files.pythonhosted.org/packages/d5/c0/fb76aa4fef450ee0a55ab40a39fd219bcf9c283710295a8ac4b885c8a9a3/snow_mcp-0.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-23 06:10:44",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "snow-mcp"
}
        
Elapsed time: 0.51250s