servicenow-mcp 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +16 -0
- package/LICENSE +21 -0
- package/README.md +189 -0
- package/dist/auth-browser.d.ts +21 -0
- package/dist/auth-browser.js +161 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +2759 -0
- package/package.json +57 -0
package/.env.example
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# ServiceNow MCP Configuration
|
|
2
|
+
# Choose ONE authentication method:
|
|
3
|
+
|
|
4
|
+
# Option 1: Browser SSO (recommended for enterprise)
|
|
5
|
+
# Just set instance URL, then use auth_browser tool
|
|
6
|
+
SERVICENOW_INSTANCE_URL=https://yourinstance.service-now.com
|
|
7
|
+
|
|
8
|
+
# Option 2: Basic Auth (username/password)
|
|
9
|
+
# SERVICENOW_INSTANCE_URL=https://yourinstance.service-now.com
|
|
10
|
+
# SERVICENOW_USERNAME=your-username
|
|
11
|
+
# SERVICENOW_PASSWORD=your-password
|
|
12
|
+
|
|
13
|
+
# Option 3: Session Token Auth (for GraphQL)
|
|
14
|
+
# SERVICENOW_INSTANCE_URL=https://yourinstance.service-now.com
|
|
15
|
+
# SERVICENOW_SESSION_TOKEN=your-cookie-string
|
|
16
|
+
# SERVICENOW_USER_TOKEN=your-g_ck-token
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Timothy Schwarz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# ServiceNow MCP Server
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/servicenow-mcp)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
[](https://modelcontextprotocol.io)
|
|
7
|
+
|
|
8
|
+
A comprehensive Model Context Protocol (MCP) server for ServiceNow ITSM with **browser-based SSO authentication** support.
|
|
9
|
+
|
|
10
|
+
> **Perfect for enterprise environments** - No API keys required. Works with Okta, Azure AD, and any SSO provider.
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- **Browser Authentication**: Log in via your enterprise SSO (Okta, Azure AD, etc.) - no API keys needed
|
|
15
|
+
- **70+ Tools**: Incidents, Changes, Problems, Catalog, CMDB, Knowledge Base, Users, Approvals, and more
|
|
16
|
+
- **GraphQL & REST Support**: Works with both ServiceNow APIs
|
|
17
|
+
- **Session Management**: Automatic cookie handling and refresh
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
### NPM
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install servicenow-mcp
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or install globally:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install -g servicenow-mcp
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### From Source
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
git clone https://github.com/schwarztim/servicenow-mcp.git
|
|
37
|
+
cd servicenow-mcp
|
|
38
|
+
npm install
|
|
39
|
+
npm run build
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Authentication Methods
|
|
43
|
+
|
|
44
|
+
### 1. Browser SSO (Recommended for Enterprise)
|
|
45
|
+
|
|
46
|
+
Use the `auth_browser` tool from Claude:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
> Use auth_browser to log into ServiceNow
|
|
50
|
+
|
|
51
|
+
A browser will open. Log in with your SSO credentials.
|
|
52
|
+
Cookies are automatically captured and saved.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Or from command line:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm run auth https://yourinstance.service-now.com
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 2. Basic Auth (Username/Password)
|
|
62
|
+
|
|
63
|
+
Set environment variables:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
export SERVICENOW_INSTANCE_URL="https://yourinstance.service-now.com"
|
|
67
|
+
export SERVICENOW_USERNAME="your-username"
|
|
68
|
+
export SERVICENOW_PASSWORD="your-password"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 3. Session Token Auth
|
|
72
|
+
|
|
73
|
+
For GraphQL API access:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
export SERVICENOW_INSTANCE_URL="https://yourinstance.service-now.com"
|
|
77
|
+
export SERVICENOW_SESSION_TOKEN="your-session-cookie"
|
|
78
|
+
export SERVICENOW_USER_TOKEN="your-g_ck-token"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Usage with Claude
|
|
82
|
+
|
|
83
|
+
After browser authentication:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
> List open P1 incidents
|
|
87
|
+
> Show me change CHG0012345
|
|
88
|
+
> Create an incident for "Email server down"
|
|
89
|
+
> Search CMDB for servers in the Atlanta datacenter
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Available Tools
|
|
93
|
+
|
|
94
|
+
### Incidents
|
|
95
|
+
|
|
96
|
+
- `incidents_list` - List incidents with filtering
|
|
97
|
+
- `incidents_get` - Get incident details
|
|
98
|
+
- `incidents_create` - Create new incident
|
|
99
|
+
- `incidents_update` - Update incident
|
|
100
|
+
- `incidents_resolve` - Resolve incident
|
|
101
|
+
|
|
102
|
+
### Changes
|
|
103
|
+
|
|
104
|
+
- `changes_list` - List change requests
|
|
105
|
+
- `changes_get` - Get change details
|
|
106
|
+
- `changes_create` - Create change request
|
|
107
|
+
- `changes_tasks` - Get change tasks
|
|
108
|
+
|
|
109
|
+
### Service Catalog
|
|
110
|
+
|
|
111
|
+
- `catalog_items` - Browse catalog items
|
|
112
|
+
- `catalog_item_get` - Get item details
|
|
113
|
+
- `catalog_order` - Order catalog item
|
|
114
|
+
- `catalog_requests` - List requests
|
|
115
|
+
|
|
116
|
+
### CMDB
|
|
117
|
+
|
|
118
|
+
- `cmdb_list` - Query configuration items
|
|
119
|
+
- `cmdb_get` - Get CI details
|
|
120
|
+
- `cmdb_relationships` - View CI relationships
|
|
121
|
+
- `cmdb_create` - Create CI
|
|
122
|
+
|
|
123
|
+
### Knowledge Base
|
|
124
|
+
|
|
125
|
+
- `kb_search` - Search knowledge articles
|
|
126
|
+
- `kb_article_get` - Get article content
|
|
127
|
+
|
|
128
|
+
### Users & Groups
|
|
129
|
+
|
|
130
|
+
- `users_search` - Search users
|
|
131
|
+
- `user_get` - Get user details
|
|
132
|
+
- `groups_list` - List groups
|
|
133
|
+
- `group_members` - Get group members
|
|
134
|
+
|
|
135
|
+
### And many more...
|
|
136
|
+
|
|
137
|
+
- Approvals, SLAs, Workflows, Email, Events, Audit, Update Sets, Security ACLs, Discovery, etc.
|
|
138
|
+
|
|
139
|
+
## Configuration
|
|
140
|
+
|
|
141
|
+
Add to `~/.claude/user-mcps.json`:
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"mcpServers": {
|
|
146
|
+
"servicenow": {
|
|
147
|
+
"command": "node",
|
|
148
|
+
"args": [
|
|
149
|
+
"/Users/yourname/Scripts/mcp-servers/servicenow-mcp/dist/index.js"
|
|
150
|
+
],
|
|
151
|
+
"env": {
|
|
152
|
+
"SERVICENOW_INSTANCE_URL": "https://yourinstance.service-now.com"
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Troubleshooting
|
|
160
|
+
|
|
161
|
+
### "No authentication configured"
|
|
162
|
+
|
|
163
|
+
Run `auth_browser` tool or set environment variables.
|
|
164
|
+
|
|
165
|
+
### "Cookies expired"
|
|
166
|
+
|
|
167
|
+
Browser cookies are valid for ~8 hours. Re-run `auth_browser` to refresh.
|
|
168
|
+
|
|
169
|
+
### "Access denied"
|
|
170
|
+
|
|
171
|
+
Ensure your ServiceNow user has appropriate roles (itil, admin, etc.).
|
|
172
|
+
|
|
173
|
+
## Contributing
|
|
174
|
+
|
|
175
|
+
Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
|
|
176
|
+
|
|
177
|
+
## Support
|
|
178
|
+
|
|
179
|
+
- **Issues**: [GitHub Issues](https://github.com/schwarztim/servicenow-mcp/issues)
|
|
180
|
+
- **Discussions**: [GitHub Discussions](https://github.com/schwarztim/servicenow-mcp/discussions)
|
|
181
|
+
|
|
182
|
+
## Acknowledgments
|
|
183
|
+
|
|
184
|
+
- Built with [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/sdk)
|
|
185
|
+
- Browser automation powered by [Playwright](https://playwright.dev/)
|
|
186
|
+
|
|
187
|
+
## License
|
|
188
|
+
|
|
189
|
+
MIT © Timothy Schwarz - see [LICENSE](LICENSE) for details
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ServiceNow Browser Authentication
|
|
4
|
+
*
|
|
5
|
+
* Launches a browser for SSO login and captures session cookies.
|
|
6
|
+
* Cookies are saved to ~/.servicenow-mcp/cookies.json for MCP to use.
|
|
7
|
+
*/
|
|
8
|
+
import { type Cookie } from "playwright";
|
|
9
|
+
export interface AuthResult {
|
|
10
|
+
success: boolean;
|
|
11
|
+
instanceUrl: string;
|
|
12
|
+
cookies: Cookie[];
|
|
13
|
+
userToken?: string;
|
|
14
|
+
error?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function authenticateViaBrowser(instanceUrl: string): Promise<AuthResult>;
|
|
17
|
+
export declare function loadCookies(): {
|
|
18
|
+
cookies: string;
|
|
19
|
+
userToken: string;
|
|
20
|
+
instanceUrl: string;
|
|
21
|
+
} | null;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ServiceNow Browser Authentication
|
|
4
|
+
*
|
|
5
|
+
* Launches a browser for SSO login and captures session cookies.
|
|
6
|
+
* Cookies are saved to ~/.servicenow-mcp/cookies.json for MCP to use.
|
|
7
|
+
*/
|
|
8
|
+
import { chromium } from "playwright";
|
|
9
|
+
import { writeFileSync, mkdirSync, existsSync, readFileSync } from "node:fs";
|
|
10
|
+
import { homedir } from "node:os";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
const COOKIE_DIR = join(homedir(), ".servicenow-mcp");
|
|
13
|
+
const COOKIE_FILE = join(COOKIE_DIR, "cookies.json");
|
|
14
|
+
export async function authenticateViaBrowser(instanceUrl) {
|
|
15
|
+
console.log(`\n🔐 ServiceNow Browser Authentication`);
|
|
16
|
+
console.log(` Instance: ${instanceUrl}`);
|
|
17
|
+
console.log(` A browser window will open. Please log in using your SSO credentials.\n`);
|
|
18
|
+
const browser = await chromium.launch({
|
|
19
|
+
headless: false, // User needs to see and interact
|
|
20
|
+
args: ["--disable-blink-features=AutomationControlled"],
|
|
21
|
+
});
|
|
22
|
+
const context = await browser.newContext({
|
|
23
|
+
viewport: { width: 1280, height: 800 },
|
|
24
|
+
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
25
|
+
});
|
|
26
|
+
const page = await context.newPage();
|
|
27
|
+
try {
|
|
28
|
+
// Navigate to ServiceNow
|
|
29
|
+
await page.goto(instanceUrl, { waitUntil: "networkidle" });
|
|
30
|
+
console.log("⏳ Waiting for you to complete SSO login...");
|
|
31
|
+
console.log(" (The browser will close automatically once authenticated)\n");
|
|
32
|
+
// Wait for successful authentication by detecting:
|
|
33
|
+
// 1. URL no longer contains login/saml/sso keywords
|
|
34
|
+
// 2. We're on a ServiceNow page (contains nav or workspace)
|
|
35
|
+
let authenticated = false;
|
|
36
|
+
let attempts = 0;
|
|
37
|
+
const maxAttempts = 300; // 5 minutes - allows time for MFA flows
|
|
38
|
+
while (!authenticated && attempts < maxAttempts) {
|
|
39
|
+
await page.waitForTimeout(1000);
|
|
40
|
+
const currentUrl = page.url();
|
|
41
|
+
// Check if we're past the login page
|
|
42
|
+
const isLoginPage = currentUrl.includes("/login") ||
|
|
43
|
+
currentUrl.includes("/saml") ||
|
|
44
|
+
currentUrl.includes("/sso") ||
|
|
45
|
+
currentUrl.includes("idp") ||
|
|
46
|
+
currentUrl.includes("okta") ||
|
|
47
|
+
currentUrl.includes("auth0") ||
|
|
48
|
+
currentUrl.includes("login.microsoftonline");
|
|
49
|
+
const isServiceNowPage = currentUrl.includes("service-now.com") &&
|
|
50
|
+
(currentUrl.includes("/nav/") ||
|
|
51
|
+
currentUrl.includes("/now/") ||
|
|
52
|
+
currentUrl.includes("/$") ||
|
|
53
|
+
currentUrl.includes("/welcome"));
|
|
54
|
+
if (!isLoginPage && isServiceNowPage) {
|
|
55
|
+
authenticated = true;
|
|
56
|
+
console.log("✅ Authentication detected!");
|
|
57
|
+
}
|
|
58
|
+
attempts++;
|
|
59
|
+
}
|
|
60
|
+
if (!authenticated) {
|
|
61
|
+
throw new Error("Authentication timeout. Please try again.");
|
|
62
|
+
}
|
|
63
|
+
// Get all cookies from the session
|
|
64
|
+
const cookies = await context.cookies();
|
|
65
|
+
// Try to extract user token from page (used for CSRF protection)
|
|
66
|
+
let userToken;
|
|
67
|
+
try {
|
|
68
|
+
userToken = await page.evaluate(() => {
|
|
69
|
+
// ServiceNow stores g_ck (security token) in window object
|
|
70
|
+
return window.g_ck || window.NOW?.g_ck || "";
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Token extraction optional
|
|
75
|
+
}
|
|
76
|
+
// Save cookies to file
|
|
77
|
+
ensureCookieDir();
|
|
78
|
+
const cookieData = {
|
|
79
|
+
instanceUrl: instanceUrl.replace(/\/$/, ""),
|
|
80
|
+
cookies: cookies,
|
|
81
|
+
userToken: userToken,
|
|
82
|
+
timestamp: new Date().toISOString(),
|
|
83
|
+
};
|
|
84
|
+
writeFileSync(COOKIE_FILE, JSON.stringify(cookieData, null, 2));
|
|
85
|
+
console.log(`\n✅ Authentication successful!`);
|
|
86
|
+
console.log(` Cookies saved to: ${COOKIE_FILE}`);
|
|
87
|
+
console.log(` Found ${cookies.length} cookies`);
|
|
88
|
+
if (userToken) {
|
|
89
|
+
console.log(` User token captured`);
|
|
90
|
+
}
|
|
91
|
+
await browser.close();
|
|
92
|
+
return {
|
|
93
|
+
success: true,
|
|
94
|
+
instanceUrl: instanceUrl.replace(/\/$/, ""),
|
|
95
|
+
cookies,
|
|
96
|
+
userToken,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
await browser.close();
|
|
101
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
102
|
+
console.error(`\n❌ Authentication failed: ${message}`);
|
|
103
|
+
return {
|
|
104
|
+
success: false,
|
|
105
|
+
instanceUrl,
|
|
106
|
+
cookies: [],
|
|
107
|
+
error: message,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function ensureCookieDir() {
|
|
112
|
+
if (!existsSync(COOKIE_DIR)) {
|
|
113
|
+
mkdirSync(COOKIE_DIR, { recursive: true });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export function loadCookies() {
|
|
117
|
+
try {
|
|
118
|
+
if (!existsSync(COOKIE_FILE)) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
const data = JSON.parse(readFileSync(COOKIE_FILE, "utf-8"));
|
|
122
|
+
// Check if cookies are expired (older than 45 minutes)
|
|
123
|
+
// ServiceNow sessions typically expire in ~1 hour, so we check earlier
|
|
124
|
+
const timestamp = new Date(data.timestamp);
|
|
125
|
+
const ageMinutes = (Date.now() - timestamp.getTime()) / (1000 * 60);
|
|
126
|
+
if (ageMinutes > 45) {
|
|
127
|
+
console.error("⚠️ Cookies are older than 45 minutes (ServiceNow sessions expire in ~1 hour). Please re-authenticate with auth_browser tool.");
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
// Format cookies as header string
|
|
131
|
+
const cookieString = data.cookies
|
|
132
|
+
.map((c) => `${c.name}=${c.value}`)
|
|
133
|
+
.join("; ");
|
|
134
|
+
return {
|
|
135
|
+
cookies: cookieString,
|
|
136
|
+
userToken: data.userToken || "",
|
|
137
|
+
instanceUrl: data.instanceUrl,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// CLI entry point
|
|
145
|
+
if (process.argv[1]?.endsWith("auth-browser.ts") ||
|
|
146
|
+
process.argv[1]?.endsWith("auth-browser.js")) {
|
|
147
|
+
const instanceUrl = process.argv[2] || process.env.SERVICENOW_INSTANCE_URL;
|
|
148
|
+
if (!instanceUrl) {
|
|
149
|
+
console.error("Usage: npm run auth <SERVICENOW_INSTANCE_URL>");
|
|
150
|
+
console.error(" Or: set SERVICENOW_INSTANCE_URL environment variable");
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
authenticateViaBrowser(instanceUrl)
|
|
154
|
+
.then((result) => {
|
|
155
|
+
process.exit(result.success ? 0 : 1);
|
|
156
|
+
})
|
|
157
|
+
.catch((error) => {
|
|
158
|
+
console.error("Fatal error:", error);
|
|
159
|
+
process.exit(1);
|
|
160
|
+
});
|
|
161
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ServiceNow MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Comprehensive MCP for ServiceNow ITSM operations:
|
|
6
|
+
* - Incidents, Changes, Problems
|
|
7
|
+
* - Service Catalog & Requests
|
|
8
|
+
* - CMDB Configuration Items
|
|
9
|
+
* - Knowledge Base
|
|
10
|
+
* - Users, Groups, Approvals
|
|
11
|
+
*
|
|
12
|
+
* Supports:
|
|
13
|
+
* - Browser-based SSO authentication (recommended for enterprise)
|
|
14
|
+
* - REST Table API (basic auth)
|
|
15
|
+
* - GraphQL API (session-based)
|
|
16
|
+
*/
|
|
17
|
+
export {};
|