The server is published on PyPI and can be installed with pip. It is recommended to install it in a virtual environment.
# 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-mcpTransform your ServiceNow experience by integrating this MCP server with Claude Desktop. This allows you to use natural language to manage incidents, create change requests, query ServiceNow data, and automate complex ITSM workflows directly through conversation with Claude.
pip install snow-mcpTest that the installation was successful:
snow-mcp --list-toolsLocate your Claude Desktop configuration file:
- Windows:
%APPDATA%\Claude\claude_desktop_config.json - macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
Add the ServiceNow MCP server configuration:
{
"mcpServers": {
"servicenow": {
"command": "snow-mcp",
"args": [],
"env": {
"SERVICENOW_INSTANCE": "https://your-instance.service-now.com",
"SERVICENOW_USERNAME": "your-username",
"SERVICENOW_PASSWORD": "your-password"
}
}
}
}Option A: Direct Configuration (shown above) Replace the placeholder values with your actual ServiceNow credentials in the config file.
Option B: Environment Variables Set system environment variables and use a simpler config:
# Windows
set SERVICENOW_INSTANCE=https://your-instance.service-now.com
set SERVICENOW_USERNAME=your-username
set SERVICENOW_PASSWORD=your-password
# macOS/Linux
export SERVICENOW_INSTANCE="https://your-instance.service-now.com"
export SERVICENOW_USERNAME="your-username"
export SERVICENOW_PASSWORD="your-password"Then use this simplified config:
{
"mcpServers": {
"servicenow": {
"command": "snow-mcp",
"args": []
}
}
}- Completely close Claude Desktop
- Reopen Claude Desktop
- The ServiceNow MCP server should now be connected
Test the integration by asking Claude:
"What ServiceNow tools are available?"
Claude should respond with a list of available ServiceNow operations.
Once integrated, you can use natural language to:
- "Create a high-priority incident for database server outage"
- "Show me all open incidents assigned to the network team"
- "Add a work note to incident INC0010001 saying we've identified the root cause"
- "Resolve incident INC0010001 with resolution notes about the fix applied"
- "Create a change request for patching the web servers next weekend"
- "List all pending change approvals"
- "Approve change CHG0040001 with notes about successful CAB review"
- "Create a new user account for John Doe in the IT department"
- "Add user john.doe to the Database Administrators group"
- "Show me all inactive users in the Development team"
- "Submit a laptop request for a new employee"
- "Check the status of my software license request RITM0010001"
- "List all available catalog items related to software"
- "Show me incident statistics grouped by priority and state"
- "Generate a report of all changes implemented last month"
- "Count how many open incidents are assigned to each team"
Solution 1: Use Python module execution
{
"mcpServers": {
"servicenow": {
"command": "python",
"args": ["-m", "servicenow_mcp_server"],
"env": {
"SERVICENOW_INSTANCE": "https://your-instance.service-now.com",
"SERVICENOW_USERNAME": "your-username",
"SERVICENOW_PASSWORD": "your-password"
}
}
}
}Solution 2: Use full Python path
{
"mcpServers": {
"servicenow": {
"command": "C:\\Python39\\python.exe",
"args": ["-m", "servicenow_mcp_server"],
"env": {
"SERVICENOW_INSTANCE": "https://your-instance.service-now.com",
"SERVICENOW_USERNAME": "your-username",
"SERVICENOW_PASSWORD": "your-password"
}
}
}
}- Verify credentials work in ServiceNow web interface
- Check instance URL format (must include
https://) - Ensure API access is enabled for your user
- Verify required roles are assigned to your ServiceNow user
- Check config file syntax (valid JSON)
- Restart Claude Desktop completely
- Check Claude Desktop logs for error messages
- Test server manually with
snow-mcp --list-tools
- Use dedicated service accounts with minimal required permissions
- Store credentials securely using environment variables
- Regularly rotate passwords and API keys
- Monitor API usage and access logs
- Restrict instance access to authorized networks when possible
Ensure your ServiceNow user has appropriate roles:
itil: Basic ITSM operations (incidents, changes, requests)catalog_admin: Service catalog managementuser_admin: User and group managementadmin: Full administrative access (for advanced operations)
Once installed, you can easily discover all available tools directly from your command line:
# List all available tools and their short descriptions
snow-mcp --list-toolsAll 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.
This setup is the same for any script you write. It tells the client library how to start your snow-mcp server.
import asyncio
from fastmcp import Client
client = Client({
"mcpServers": {
"servicenow": {
"command": "snow-mcp",
"args": [],
"transport": "stdio"
}
}
})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.
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.
# 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)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:
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)
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:
payload = { "params": { **SERVICENOW_CREDS, "table_name": "change_request" } } result = await client.call_tool("get_table_schema", payload)
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:
payload = { "params": { **SERVICENOW_CREDS, "table_name": "kb_knowledge", "search_term": "password reset" } } result = await client.call_tool("search_records_by_text", payload)
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:
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)
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:
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)
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:
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)
Retrieves an incident by its number (e.g., 'INC0010001').
- Parameters:
number(string, required): The incident number.
- Code Example:
payload = { "params": { **SERVICENOW_CREDS, "number": "INC0010001" } } result = await client.call_tool("get_incident_by_number", payload)
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:
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)
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:
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)
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:
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)
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:
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)
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:
payload = { "params": { **SERVICENOW_CREDS, "query": "state=1^type=normal", # New normal changes "limit": 10 } } result = await client.call_tool("list_change_requests", payload)
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:
payload = { "params": { **SERVICENOW_CREDS, "number": "CHG0040001" } } result = await client.call_tool("get_change_request_details", payload)
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:
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)
Moves a change to the 'Assess' state for approval workflow.
- Parameters:
sys_id(string, required): The sys_id of the change request.
- Code Example:
payload = { "params": { **SERVICENOW_CREDS, "sys_id": "def456ghi789jkl012" } } result = await client.call_tool("submit_change_for_approval", payload)
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:
payload = { "params": { **SERVICENOW_CREDS, "sys_id": "def456ghi789jkl012", "approval_notes": "Change approved by CAB. Proceed with implementation." } } result = await client.call_tool("approve_change", payload)
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:
payload = { "params": { **SERVICENOW_CREDS, "sys_id": "def456ghi789jkl012", "rejection_comments": "Insufficient testing plan provided." } } result = await client.call_tool("reject_change", payload)
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:
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)
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:
payload = { "params": { **SERVICENOW_CREDS, "user_name": "john.doe" } } result = await client.call_tool("get_user", payload)
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:
payload = { "params": { **SERVICENOW_CREDS, "name": "Development Team", "description": "Software development team", "type": "itil" } } result = await client.call_tool("create_group", payload)
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:
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)
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:
payload = { "params": { **SERVICENOW_CREDS, "group_sys_id": "ghi789jkl012mno345", "user_sys_ids": ["user1_sys_id"] } } result = await client.call_tool("remove_group_members", payload)
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:
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)
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:
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)
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:
payload = { "params": { **SERVICENOW_CREDS, "number": "RITM0010001" } } result = await client.call_tool("get_requested_item", payload)
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:
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)
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:
payload = { "params": { **SERVICENOW_CREDS, "filter_text": "laptop", "limit": 20 } } result = await client.call_tool("list_catalog_items", payload)
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:
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)
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:
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)
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:
payload = { "params": { **SERVICENOW_CREDS, "sys_id": "story_sys_id_here", "state": "complete", "story_points": 8 } } result = await client.call_tool("update_story", payload)
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:
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)
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:
payload = { "params": { **SERVICENOW_CREDS, "sys_id": "epic_sys_id_here", "state": "complete" } } result = await client.call_tool("update_epic", payload)
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:
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)
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:
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)
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:
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)
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:
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)
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:
payload = { "params": { **SERVICENOW_CREDS, "query": "state=in_progress", "limit": 10 } } result = await client.call_tool("list_projects", payload)
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:
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)
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:
payload = { "params": { **SERVICENOW_CREDS, "sys_id": "workflow_sys_id_here", "active": False, "description": "Updated workflow description" } } result = await client.call_tool("update_workflow", payload)
Deletes a workflow definition.
- Parameters:
sys_id(string, required): The sys_id of the workflow to delete.
- Code Example:
payload = { "params": { **SERVICENOW_CREDS, "sys_id": "workflow_sys_id_here" } } result = await client.call_tool("delete_workflow", payload)
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:
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)
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:
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)
Deletes a script include.
- Parameters:
sys_id(string, required): The sys_id of the script include to delete.
- Code Example:
payload = { "params": { **SERVICENOW_CREDS, "sys_id": "script_include_sys_id_here" } } result = await client.call_tool("delete_script_include", payload)
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:
payload = { "params": { **SERVICENOW_CREDS, "name": "Feature Enhancement v2.1", "description": "Update set for new feature enhancements" } } result = await client.call_tool("create_changeset", payload)
Marks a changeset as 'complete'.
- Parameters:
sys_id(string, required): The sys_id of the update set.
- Code Example:
payload = { "params": { **SERVICENOW_CREDS, "sys_id": "update_set_sys_id_here" } } result = await client.call_tool("commit_changeset", payload)
Lists local Update Sets.
- Parameters:
query(string, optional): ServiceNow query filter.limit(integer, optional): Maximum number of records to return.
- Code Example:
payload = { "params": { **SERVICENOW_CREDS, "query": "state=in_progress", "limit": 20 } } result = await client.call_tool("list_changesets", payload)
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:
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)
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:
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)
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:
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)
Here's a complete example showing how to create an incident, add comments, and then resolve it:
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())It's recommended to store your ServiceNow credentials as environment variables:
# 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-passwordAll tools return structured responses. In case of errors, the response will include error details:
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}")This server is built using the FastMCP 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.