@sonisoft/now-sdk-ext-mcp 1.0.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/README.md +393 -0
- package/dist/common/connection.d.ts +42 -0
- package/dist/common/connection.d.ts.map +1 -0
- package/dist/common/connection.js +119 -0
- package/dist/common/connection.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +108 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/aggregate.d.ts +20 -0
- package/dist/tools/aggregate.d.ts.map +1 -0
- package/dist/tools/aggregate.js +271 -0
- package/dist/tools/aggregate.js.map +1 -0
- package/dist/tools/app-manager.d.ts +50 -0
- package/dist/tools/app-manager.d.ts.map +1 -0
- package/dist/tools/app-manager.js +756 -0
- package/dist/tools/app-manager.js.map +1 -0
- package/dist/tools/atf.d.ts +16 -0
- package/dist/tools/atf.d.ts.map +1 -0
- package/dist/tools/atf.js +246 -0
- package/dist/tools/atf.js.map +1 -0
- package/dist/tools/attachment.d.ts +20 -0
- package/dist/tools/attachment.d.ts.map +1 -0
- package/dist/tools/attachment.js +223 -0
- package/dist/tools/attachment.js.map +1 -0
- package/dist/tools/batch.d.ts +15 -0
- package/dist/tools/batch.d.ts.map +1 -0
- package/dist/tools/batch.js +159 -0
- package/dist/tools/batch.js.map +1 -0
- package/dist/tools/cmdb.d.ts +14 -0
- package/dist/tools/cmdb.d.ts.map +1 -0
- package/dist/tools/cmdb.js +199 -0
- package/dist/tools/cmdb.js.map +1 -0
- package/dist/tools/codesearch.d.ts +31 -0
- package/dist/tools/codesearch.d.ts.map +1 -0
- package/dist/tools/codesearch.js +371 -0
- package/dist/tools/codesearch.js.map +1 -0
- package/dist/tools/discovery.d.ts +15 -0
- package/dist/tools/discovery.d.ts.map +1 -0
- package/dist/tools/discovery.js +204 -0
- package/dist/tools/discovery.js.map +1 -0
- package/dist/tools/execute-script.d.ts +9 -0
- package/dist/tools/execute-script.d.ts.map +1 -0
- package/dist/tools/execute-script.js +106 -0
- package/dist/tools/execute-script.js.map +1 -0
- package/dist/tools/find-atf-tests.d.ts +9 -0
- package/dist/tools/find-atf-tests.d.ts.map +1 -0
- package/dist/tools/find-atf-tests.js +152 -0
- package/dist/tools/find-atf-tests.js.map +1 -0
- package/dist/tools/health.d.ts +9 -0
- package/dist/tools/health.d.ts.map +1 -0
- package/dist/tools/health.js +137 -0
- package/dist/tools/health.js.map +1 -0
- package/dist/tools/lookup-app.d.ts +11 -0
- package/dist/tools/lookup-app.d.ts.map +1 -0
- package/dist/tools/lookup-app.js +242 -0
- package/dist/tools/lookup-app.js.map +1 -0
- package/dist/tools/lookup-columns.d.ts +10 -0
- package/dist/tools/lookup-columns.d.ts.map +1 -0
- package/dist/tools/lookup-columns.js +180 -0
- package/dist/tools/lookup-columns.js.map +1 -0
- package/dist/tools/lookup-table.d.ts +10 -0
- package/dist/tools/lookup-table.d.ts.map +1 -0
- package/dist/tools/lookup-table.js +150 -0
- package/dist/tools/lookup-table.js.map +1 -0
- package/dist/tools/query-batch.d.ts +16 -0
- package/dist/tools/query-batch.d.ts.map +1 -0
- package/dist/tools/query-batch.js +197 -0
- package/dist/tools/query-batch.js.map +1 -0
- package/dist/tools/query-syslog.d.ts +9 -0
- package/dist/tools/query-syslog.d.ts.map +1 -0
- package/dist/tools/query-syslog.js +127 -0
- package/dist/tools/query-syslog.js.map +1 -0
- package/dist/tools/query-table.d.ts +8 -0
- package/dist/tools/query-table.d.ts.map +1 -0
- package/dist/tools/query-table.js +137 -0
- package/dist/tools/query-table.js.map +1 -0
- package/dist/tools/schema.d.ts +24 -0
- package/dist/tools/schema.d.ts.map +1 -0
- package/dist/tools/schema.js +321 -0
- package/dist/tools/schema.js.map +1 -0
- package/dist/tools/scope.d.ts +25 -0
- package/dist/tools/scope.d.ts.map +1 -0
- package/dist/tools/scope.js +226 -0
- package/dist/tools/scope.js.map +1 -0
- package/dist/tools/scriptsync.d.ts +14 -0
- package/dist/tools/scriptsync.d.ts.map +1 -0
- package/dist/tools/scriptsync.js +167 -0
- package/dist/tools/scriptsync.js.map +1 -0
- package/dist/tools/task.d.ts +39 -0
- package/dist/tools/task.d.ts.map +1 -0
- package/dist/tools/task.js +390 -0
- package/dist/tools/task.js.map +1 -0
- package/dist/tools/updateset.d.ts +46 -0
- package/dist/tools/updateset.d.ts.map +1 -0
- package/dist/tools/updateset.js +475 -0
- package/dist/tools/updateset.js.map +1 -0
- package/dist/tools/workflow.d.ts +9 -0
- package/dist/tools/workflow.d.ts.map +1 -0
- package/dist/tools/workflow.js +164 -0
- package/dist/tools/workflow.js.map +1 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
# now-sdk-ext-mcp
|
|
2
|
+
|
|
3
|
+
An MCP (Model Context Protocol) server that enables AI assistants to interact directly with ServiceNow instances — executing background scripts, querying data, running ATF tests, tailing logs, and more.
|
|
4
|
+
|
|
5
|
+
Built on [`@modelcontextprotocol/sdk`](https://github.com/modelcontextprotocol/typescript-sdk) and [`@sonisoft/now-sdk-ext-core`](https://git.sonisoft.io).
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
### Prerequisites
|
|
10
|
+
|
|
11
|
+
- **Node.js** >= 18
|
|
12
|
+
- **ServiceNow CLI credentials** configured via `snc configure`
|
|
13
|
+
|
|
14
|
+
### Install and Build
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
git clone <repo-url>
|
|
18
|
+
cd now-sdk-ext-mcp
|
|
19
|
+
npm install
|
|
20
|
+
npm run build
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Configure Credentials
|
|
24
|
+
|
|
25
|
+
This server uses the same credential store as the ServiceNow CLI (`snc`). If you haven't already, configure your instance credentials:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
now-sdk auth --add <instance_alias>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This stores credentials locally so the MCP server can authenticate without prompting.
|
|
32
|
+
|
|
33
|
+
### Run the Server
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
node dist/index.js
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The server communicates over **stdio** (standard input/output) using the MCP JSON-RPC protocol. It is not meant to be run interactively — it's designed to be launched by an MCP client (Claude Desktop, VS Code, Cursor, etc.).
|
|
40
|
+
|
|
41
|
+
## Connecting to an MCP Client
|
|
42
|
+
|
|
43
|
+
### Claude Desktop
|
|
44
|
+
|
|
45
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"servicenow": {
|
|
51
|
+
"command": "node",
|
|
52
|
+
"args": ["/absolute/path/to/now-sdk-ext-mcp/dist/index.js"]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
To set a default instance (so you don't have to specify it every time):
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"mcpServers": {
|
|
63
|
+
"servicenow": {
|
|
64
|
+
"command": "node",
|
|
65
|
+
"args": ["/absolute/path/to/now-sdk-ext-mcp/dist/index.js"],
|
|
66
|
+
"env": {
|
|
67
|
+
"SN_AUTH_ALIAS": "dev224436"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### VS Code / Cursor
|
|
75
|
+
|
|
76
|
+
Add to your `.vscode/mcp.json` or Cursor MCP settings:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"servers": {
|
|
81
|
+
"servicenow": {
|
|
82
|
+
"command": "node",
|
|
83
|
+
"args": ["/absolute/path/to/now-sdk-ext-mcp/dist/index.js"],
|
|
84
|
+
"env": {
|
|
85
|
+
"SN_AUTH_ALIAS": "dev224436"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Claude Code
|
|
93
|
+
|
|
94
|
+
Add to your `.claude/settings.json` or project-level `.mcp.json`:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"mcpServers": {
|
|
99
|
+
"servicenow": {
|
|
100
|
+
"command": "node",
|
|
101
|
+
"args": ["/absolute/path/to/now-sdk-ext-mcp/dist/index.js"],
|
|
102
|
+
"env": {
|
|
103
|
+
"SN_AUTH_ALIAS": "dev224436"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Opencode
|
|
111
|
+
|
|
112
|
+
Add to your `.config/opencode/opencode.json` or project-level `opencode.jsonc`
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"mcp": {
|
|
117
|
+
"servicenow": {
|
|
118
|
+
"type": "local",
|
|
119
|
+
"command": ["node", "/absolute/path/to/now-sdk-ext-mcp/dist/index.js"],
|
|
120
|
+
"enabled": true,
|
|
121
|
+
"environment": {
|
|
122
|
+
"SN_AUTH_ALIAS": "dev224436"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
## How It Works
|
|
129
|
+
|
|
130
|
+
Once connected, you can talk to your AI assistant naturally:
|
|
131
|
+
|
|
132
|
+
> "Find all CMDB CI records in the computer class on my dev224436 instance"
|
|
133
|
+
|
|
134
|
+
> "Run a script on dev224436 that counts all active incidents by priority"
|
|
135
|
+
|
|
136
|
+
> "Query the sys_user table for users with the admin role on prod"
|
|
137
|
+
|
|
138
|
+
The AI will:
|
|
139
|
+
1. Write the appropriate ServiceNow server-side JavaScript
|
|
140
|
+
2. Call the `execute_script` tool with the instance alias and script
|
|
141
|
+
3. Return the results in a readable format
|
|
142
|
+
|
|
143
|
+
The `instance` parameter can be passed explicitly per-request or defaulted via the `SN_AUTH_ALIAS` environment variable, so if you only work with one instance you can set-and-forget.
|
|
144
|
+
|
|
145
|
+
## Available Tools
|
|
146
|
+
|
|
147
|
+
See **[TOOLS.md](TOOLS.md)** for the full list of available tools with parameters and examples.
|
|
148
|
+
|
|
149
|
+
## Environment Variables
|
|
150
|
+
|
|
151
|
+
| Variable | Default | Description |
|
|
152
|
+
|----------|---------|-------------|
|
|
153
|
+
| `SN_AUTH_ALIAS` | _(none)_ | Default ServiceNow auth alias. Used when a tool call doesn't specify an `instance` parameter. |
|
|
154
|
+
|
|
155
|
+
## Development
|
|
156
|
+
|
|
157
|
+
### Project Structure
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
src/
|
|
161
|
+
├── index.ts # Server entry point — registers tools, starts stdio transport
|
|
162
|
+
├── tools/ # MCP tool implementations (one file per tool)
|
|
163
|
+
│ └── execute-script.ts # execute_script tool
|
|
164
|
+
└── common/
|
|
165
|
+
└── connection.ts # ServiceNow connection manager (credential resolution + caching)
|
|
166
|
+
|
|
167
|
+
test/
|
|
168
|
+
├── __mocks__/ # Manual mocks for external dependencies
|
|
169
|
+
├── helpers/ # Shared test utilities and factories
|
|
170
|
+
├── unit/ # Unit tests (mocked external deps)
|
|
171
|
+
│ ├── common/
|
|
172
|
+
│ └── tools/
|
|
173
|
+
└── integration/ # Integration tests (full MCP protocol, no real SN calls)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Scripts
|
|
177
|
+
|
|
178
|
+
| Command | Description |
|
|
179
|
+
|---------|-------------|
|
|
180
|
+
| `npm run build` | Clean and compile TypeScript to `dist/` |
|
|
181
|
+
| `npm run dev` | Build and run the server |
|
|
182
|
+
| `npm test` | Run unit tests |
|
|
183
|
+
| `npm run test:unit` | Run unit tests with coverage and junit reporting |
|
|
184
|
+
| `npm run test:integration` | Run MCP protocol integration tests |
|
|
185
|
+
| `npm run test:all` | Run all tests |
|
|
186
|
+
| `npm run lint` | Type-check with `tsc --noEmit` |
|
|
187
|
+
|
|
188
|
+
### Adding a New Tool
|
|
189
|
+
|
|
190
|
+
1. Create a new file in `src/tools/` (e.g., `src/tools/query-table.ts`).
|
|
191
|
+
2. Export a registration function:
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
195
|
+
import { z } from "zod";
|
|
196
|
+
import { getServiceNowInstance } from "../common/connection.js";
|
|
197
|
+
|
|
198
|
+
export function registerQueryTableTool(server: McpServer): void {
|
|
199
|
+
server.registerTool(
|
|
200
|
+
"query_table",
|
|
201
|
+
{
|
|
202
|
+
title: "Query Table",
|
|
203
|
+
description: "Query records from a ServiceNow table.",
|
|
204
|
+
inputSchema: {
|
|
205
|
+
instance: z.string().optional().describe("ServiceNow instance auth alias"),
|
|
206
|
+
table: z.string().describe("Table name to query"),
|
|
207
|
+
// ... more params
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
async ({ instance, table }) => {
|
|
211
|
+
const snInstance = await getServiceNowInstance(instance);
|
|
212
|
+
// ... use core library to query
|
|
213
|
+
return {
|
|
214
|
+
content: [{ type: "text" as const, text: "results here" }],
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
3. Register it in `src/index.ts`:
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
import { registerQueryTableTool } from "./tools/query-table.js";
|
|
225
|
+
|
|
226
|
+
registerQueryTableTool(server);
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
4. Add tests in `test/unit/tools/` following the existing pattern.
|
|
230
|
+
5. Document the tool in [`TOOLS.md`](TOOLS.md).
|
|
231
|
+
|
|
232
|
+
### Testing Approach
|
|
233
|
+
|
|
234
|
+
Tests use the MCP SDK's `InMemoryTransport` to create linked client+server pairs entirely in-process. This means tests go through the full MCP protocol stack (JSON-RPC serialization, schema validation, handler dispatch) without spawning processes or touching the network.
|
|
235
|
+
|
|
236
|
+
- **Unit tests** (`test/unit/`): Mock external dependencies (`@sonisoft/now-sdk-ext-core`, `@servicenow/sdk-cli`) using `jest.unstable_mockModule()` for ESM compatibility. Test tool behavior through the MCP client.
|
|
237
|
+
- **Integration tests** (`test/integration/`): Verify the MCP protocol lifecycle (handshake, tool listing, sequential calls) without mocking.
|
|
238
|
+
|
|
239
|
+
### Sibling Projects
|
|
240
|
+
|
|
241
|
+
This MCP server wraps the same core library used by the CLI:
|
|
242
|
+
|
|
243
|
+
- **Core library**: [`@sonisoft/now-sdk-ext-core`](../now-sdk-ext-core) — all ServiceNow communication (auth, HTTP, WebSocket, script execution, ATF, syslog)
|
|
244
|
+
- **CLI**: [`@sonisoft/now-sdk-ext-cli`](../now-sdk-ext-cli) — the `nex` CLI that wraps the core library with oclif
|
|
245
|
+
|
|
246
|
+
When adding new MCP tools, reference the corresponding CLI command in `now-sdk-ext-cli/src/commands/` for the expected behavior and data flow.
|
|
247
|
+
|
|
248
|
+
## Contributing
|
|
249
|
+
|
|
250
|
+
### Testing
|
|
251
|
+
|
|
252
|
+
There are three layers of testing for this project:
|
|
253
|
+
|
|
254
|
+
#### 1. Automated Tests (Jest)
|
|
255
|
+
|
|
256
|
+
Unit and integration tests run entirely in-process using the MCP SDK's `InMemoryTransport` — no server process, no network, no credentials needed.
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
npm test # Unit tests (default, fast)
|
|
260
|
+
npm run test:unit # Unit tests with coverage + junit
|
|
261
|
+
npm run test:integration # MCP protocol integration tests
|
|
262
|
+
npm run test:all # Everything
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Unit tests mock all external dependencies (`@sonisoft/now-sdk-ext-core`, `@servicenow/sdk-cli`) so they are fast and deterministic. Integration tests verify the MCP protocol lifecycle (handshake, tool listing, tool calls, error responses) without hitting real ServiceNow instances.
|
|
266
|
+
|
|
267
|
+
Always run `npm test` before committing.
|
|
268
|
+
|
|
269
|
+
#### 2. MCP Inspector (Interactive Testing)
|
|
270
|
+
|
|
271
|
+
The official [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is a web UI that acts as an MCP client, letting you interactively browse tools, invoke them with custom inputs, and see results — without connecting to Claude or any AI client.
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
# Build first
|
|
275
|
+
npm run build
|
|
276
|
+
|
|
277
|
+
# Launch the inspector (opens a browser UI at http://localhost:6274)
|
|
278
|
+
npx @modelcontextprotocol/inspector node dist/index.js
|
|
279
|
+
|
|
280
|
+
# Pass env vars to the server (e.g., default instance alias)
|
|
281
|
+
npx @modelcontextprotocol/inspector -e SN_AUTH_ALIAS=dev224436 node dist/index.js
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
In the inspector UI you can:
|
|
285
|
+
- Browse registered tools and their input schemas in the **Tools** tab
|
|
286
|
+
- Fill in parameters and invoke tools
|
|
287
|
+
- See the JSON-RPC request/response and tool output
|
|
288
|
+
- View server stderr logs in the **Notifications** pane
|
|
289
|
+
|
|
290
|
+
The inspector also has a headless CLI mode for scripting:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
# List all tools
|
|
294
|
+
npx @modelcontextprotocol/inspector --cli node dist/index.js --method tools/list
|
|
295
|
+
|
|
296
|
+
# Call a specific tool
|
|
297
|
+
npx @modelcontextprotocol/inspector --cli node dist/index.js \
|
|
298
|
+
--method tools/call --tool-name execute_script \
|
|
299
|
+
--tool-arg instance=dev224436 \
|
|
300
|
+
--tool-arg script='gs.print("hello")' \
|
|
301
|
+
--tool-arg scope=global
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
#### 3. Testing with Claude Code
|
|
305
|
+
|
|
306
|
+
To test the server end-to-end with Claude Code as the MCP client:
|
|
307
|
+
|
|
308
|
+
**Add the server:**
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
# From the now-sdk-ext-mcp project root (after building):
|
|
312
|
+
claude mcp add --transport stdio --env SN_AUTH_ALIAS=dev224436 servicenow \
|
|
313
|
+
-- node /absolute/path/to/now-sdk-ext-mcp/dist/index.js
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Or create a `.mcp.json` at your project root (this is shareable via version control):
|
|
317
|
+
|
|
318
|
+
```json
|
|
319
|
+
{
|
|
320
|
+
"mcpServers": {
|
|
321
|
+
"servicenow": {
|
|
322
|
+
"command": "node",
|
|
323
|
+
"args": ["/absolute/path/to/now-sdk-ext-mcp/dist/index.js"],
|
|
324
|
+
"env": {
|
|
325
|
+
"SN_AUTH_ALIAS": "dev224436"
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**Verify the connection:**
|
|
333
|
+
|
|
334
|
+
Inside a Claude Code session, run `/mcp` to see all connected servers and their status. The `servicenow` server should show as connected.
|
|
335
|
+
|
|
336
|
+
**Test it:**
|
|
337
|
+
|
|
338
|
+
Ask Claude something like:
|
|
339
|
+
|
|
340
|
+
> "Run a script on dev224436 that prints the current user's name using gs.print(gs.getUserName())"
|
|
341
|
+
|
|
342
|
+
Claude should call the `execute_script` tool and return the result.
|
|
343
|
+
|
|
344
|
+
**Manage servers:**
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
claude mcp list # List all configured servers
|
|
348
|
+
claude mcp get servicenow # Show details for the servicenow server
|
|
349
|
+
claude mcp remove servicenow # Remove it
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
#### Manual stdin Testing
|
|
353
|
+
|
|
354
|
+
Since the server communicates via JSON-RPC over stdio, you can pipe messages directly for quick smoke tests:
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
# List tools (single-message shortcut — works for basic inspection)
|
|
358
|
+
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' \
|
|
359
|
+
| node dist/index.js 2>/dev/null \
|
|
360
|
+
| jq '.result.tools[].name'
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
For a full protocol exchange (initialize handshake + tool call):
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
printf '%s\n%s\n%s\n' \
|
|
367
|
+
'{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}},"id":0}' \
|
|
368
|
+
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
|
|
369
|
+
'{"jsonrpc":"2.0","method":"tools/list","id":1}' \
|
|
370
|
+
| node dist/index.js 2>/dev/null \
|
|
371
|
+
| jq
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Debugging
|
|
375
|
+
|
|
376
|
+
Since stdout is reserved for JSON-RPC, **never use `console.log()` in server code** — it corrupts the protocol stream. Use these approaches instead:
|
|
377
|
+
|
|
378
|
+
- **`console.error()`** — writes to stderr, which is safe and visible in the MCP Inspector's Notifications pane and in Claude Desktop's log files (`~/Library/Logs/Claude/mcp*.log`).
|
|
379
|
+
- **MCP Inspector** — run the server under the inspector to see all JSON-RPC messages and stderr output in real time.
|
|
380
|
+
- **File logging** — for persistent debug logs, the core library's `Logger` class writes to `logs/` with Winston. Set the log level via the tool's logic as needed.
|
|
381
|
+
|
|
382
|
+
### Code Conventions
|
|
383
|
+
|
|
384
|
+
- ES Modules (`"type": "module"` in package.json)
|
|
385
|
+
- TypeScript strict mode
|
|
386
|
+
- Target ES2022, module Node16
|
|
387
|
+
- Match the patterns and style of the sibling `now-sdk-ext-core` and `now-sdk-ext-cli` projects
|
|
388
|
+
- Every tool that talks to ServiceNow should accept an optional `instance` parameter
|
|
389
|
+
- Test every tool through the MCP client (not by calling handler functions directly) so the full protocol stack is exercised
|
|
390
|
+
|
|
391
|
+
## License
|
|
392
|
+
|
|
393
|
+
MIT
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ServiceNowInstance } from "@sonisoft/now-sdk-ext-core";
|
|
2
|
+
/**
|
|
3
|
+
* Returns a ServiceNowInstance using stored credentials from the ServiceNow
|
|
4
|
+
* CLI credential store (snc configure).
|
|
5
|
+
*
|
|
6
|
+
* Resolution order: explicit authAlias parameter → SN_AUTH_ALIAS env var.
|
|
7
|
+
* Throws if neither is available.
|
|
8
|
+
*
|
|
9
|
+
* Instances are cached per alias with a 30-minute TTL so that repeated
|
|
10
|
+
* calls reuse the same session, but stale sessions are automatically
|
|
11
|
+
* refreshed. This allows the AI to work with multiple instances in a
|
|
12
|
+
* single conversation (e.g., dev224436 and prod).
|
|
13
|
+
*/
|
|
14
|
+
export declare function getServiceNowInstance(authAlias?: string): Promise<ServiceNowInstance>;
|
|
15
|
+
/**
|
|
16
|
+
* Evicts a cached instance so the next call to getServiceNowInstance()
|
|
17
|
+
* creates a fresh connection.
|
|
18
|
+
*/
|
|
19
|
+
export declare function clearInstance(authAlias?: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* Returns true if an HTTP response indicates a stale or dead session.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isRetryableResponse(response: {
|
|
24
|
+
status?: number;
|
|
25
|
+
statusText?: string;
|
|
26
|
+
} | null | undefined): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Executes an operation against a ServiceNow instance with automatic retry.
|
|
29
|
+
*
|
|
30
|
+
* On the first attempt, uses the (possibly cached) instance. If the operation
|
|
31
|
+
* throws a retryable error, the cached instance is evicted and the operation
|
|
32
|
+
* is retried once with a fresh connection.
|
|
33
|
+
*
|
|
34
|
+
* Usage:
|
|
35
|
+
* ```ts
|
|
36
|
+
* return withConnectionRetry(instance, async (snInstance) => {
|
|
37
|
+
* // ... use snInstance ...
|
|
38
|
+
* });
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function withConnectionRetry<T>(authAlias: string | undefined, operation: (instance: ServiceNowInstance) => Promise<T>): Promise<T>;
|
|
42
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/common/connection.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAEnB,MAAM,4BAA4B,CAAC;AA4BpC;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,kBAAkB,CAAC,CAmC7B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAKtD;AAgBD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,GACpE,OAAO,CAIT;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,SAAS,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,OAAO,CAAC,CAAC,CAAC,GACtD,OAAO,CAAC,CAAC,CAAC,CAeZ"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { getCredentials } from "@servicenow/sdk-cli/dist/auth/index.js";
|
|
2
|
+
import { ServiceNowInstance, } from "@sonisoft/now-sdk-ext-core";
|
|
3
|
+
/** Cache TTL — 30 minutes. ServiceNow sessions typically expire after idle time. */
|
|
4
|
+
const CACHE_TTL_MS = 30 * 60 * 1000;
|
|
5
|
+
const instanceCache = new Map();
|
|
6
|
+
/**
|
|
7
|
+
* Resolves the auth alias from the explicit parameter or the SN_AUTH_ALIAS env var.
|
|
8
|
+
* Throws if neither is available.
|
|
9
|
+
*/
|
|
10
|
+
function resolveAlias(authAlias) {
|
|
11
|
+
const resolved = authAlias || process.env.SN_AUTH_ALIAS;
|
|
12
|
+
if (!resolved) {
|
|
13
|
+
throw new Error("No instance specified. Either pass an instance alias " +
|
|
14
|
+
'(e.g., "on my dev224436 instance") or set the SN_AUTH_ALIAS environment variable.');
|
|
15
|
+
}
|
|
16
|
+
return resolved;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Returns a ServiceNowInstance using stored credentials from the ServiceNow
|
|
20
|
+
* CLI credential store (snc configure).
|
|
21
|
+
*
|
|
22
|
+
* Resolution order: explicit authAlias parameter → SN_AUTH_ALIAS env var.
|
|
23
|
+
* Throws if neither is available.
|
|
24
|
+
*
|
|
25
|
+
* Instances are cached per alias with a 30-minute TTL so that repeated
|
|
26
|
+
* calls reuse the same session, but stale sessions are automatically
|
|
27
|
+
* refreshed. This allows the AI to work with multiple instances in a
|
|
28
|
+
* single conversation (e.g., dev224436 and prod).
|
|
29
|
+
*/
|
|
30
|
+
export async function getServiceNowInstance(authAlias) {
|
|
31
|
+
const resolvedAlias = resolveAlias(authAlias);
|
|
32
|
+
const cached = instanceCache.get(resolvedAlias);
|
|
33
|
+
if (cached) {
|
|
34
|
+
const age = Date.now() - cached.createdAt;
|
|
35
|
+
if (age < CACHE_TTL_MS) {
|
|
36
|
+
return cached.instance;
|
|
37
|
+
}
|
|
38
|
+
// TTL expired — evict and create fresh
|
|
39
|
+
console.error(`[connection] Cache TTL expired for "${resolvedAlias}", refreshing session`);
|
|
40
|
+
instanceCache.delete(resolvedAlias);
|
|
41
|
+
}
|
|
42
|
+
const credential = await getCredentials(resolvedAlias);
|
|
43
|
+
if (!credential) {
|
|
44
|
+
throw new Error(`No credentials found for auth alias "${resolvedAlias}". ` +
|
|
45
|
+
`Run "snc configure --auth ${resolvedAlias}" to set up credentials.`);
|
|
46
|
+
}
|
|
47
|
+
const snSettings = {
|
|
48
|
+
alias: resolvedAlias,
|
|
49
|
+
credential,
|
|
50
|
+
};
|
|
51
|
+
const instance = new ServiceNowInstance(snSettings);
|
|
52
|
+
instanceCache.set(resolvedAlias, {
|
|
53
|
+
instance,
|
|
54
|
+
createdAt: Date.now(),
|
|
55
|
+
});
|
|
56
|
+
return instance;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Evicts a cached instance so the next call to getServiceNowInstance()
|
|
60
|
+
* creates a fresh connection.
|
|
61
|
+
*/
|
|
62
|
+
export function clearInstance(authAlias) {
|
|
63
|
+
const resolved = authAlias || process.env.SN_AUTH_ALIAS;
|
|
64
|
+
if (resolved) {
|
|
65
|
+
instanceCache.delete(resolved);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Patterns that indicate a connection/session problem worth retrying. */
|
|
69
|
+
const RETRYABLE_PATTERNS = /ECONNREFUSED|ECONNRESET|ETIMEDOUT|EPIPE|socket hang up|fetch failed|No response|Body not XML/i;
|
|
70
|
+
/**
|
|
71
|
+
* Returns true if the error looks like a transient connection or stale-session
|
|
72
|
+
* problem that could be fixed by creating a fresh ServiceNowInstance.
|
|
73
|
+
*/
|
|
74
|
+
function isRetryableError(error) {
|
|
75
|
+
if (!error)
|
|
76
|
+
return false;
|
|
77
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
78
|
+
return RETRYABLE_PATTERNS.test(msg);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Returns true if an HTTP response indicates a stale or dead session.
|
|
82
|
+
*/
|
|
83
|
+
export function isRetryableResponse(response) {
|
|
84
|
+
if (!response || response.status == null)
|
|
85
|
+
return true; // no response at all
|
|
86
|
+
if (response.status === 401)
|
|
87
|
+
return true; // session expired
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Executes an operation against a ServiceNow instance with automatic retry.
|
|
92
|
+
*
|
|
93
|
+
* On the first attempt, uses the (possibly cached) instance. If the operation
|
|
94
|
+
* throws a retryable error, the cached instance is evicted and the operation
|
|
95
|
+
* is retried once with a fresh connection.
|
|
96
|
+
*
|
|
97
|
+
* Usage:
|
|
98
|
+
* ```ts
|
|
99
|
+
* return withConnectionRetry(instance, async (snInstance) => {
|
|
100
|
+
* // ... use snInstance ...
|
|
101
|
+
* });
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export async function withConnectionRetry(authAlias, operation) {
|
|
105
|
+
const snInstance = await getServiceNowInstance(authAlias);
|
|
106
|
+
try {
|
|
107
|
+
return await operation(snInstance);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
if (isRetryableError(error)) {
|
|
111
|
+
console.error(`[connection] Retryable error detected, refreshing session and retrying: ${error}`);
|
|
112
|
+
clearInstance(authAlias);
|
|
113
|
+
const freshInstance = await getServiceNowInstance(authAlias);
|
|
114
|
+
return await operation(freshInstance);
|
|
115
|
+
}
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/common/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,EACL,kBAAkB,GAEnB,MAAM,4BAA4B,CAAC;AAQpC,oFAAoF;AACpF,MAAM,YAAY,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEpC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAsB,CAAC;AAEpD;;;GAGG;AACH,SAAS,YAAY,CAAC,SAAkB;IACtC,MAAM,QAAQ,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IACxD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,uDAAuD;YACrD,mFAAmF,CACtF,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,SAAkB;IAElB,MAAM,aAAa,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IAE9C,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAChD,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC;QAC1C,IAAI,GAAG,GAAG,YAAY,EAAE,CAAC;YACvB,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;QACD,uCAAuC;QACvC,OAAO,CAAC,KAAK,CACX,uCAAuC,aAAa,uBAAuB,CAC5E,CAAC;QACF,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,CAAC,CAAC;IACvD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,wCAAwC,aAAa,KAAK;YACxD,6BAA6B,aAAa,0BAA0B,CACvE,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAA+B;QAC7C,KAAK,EAAE,aAAa;QACpB,UAAU;KACX,CAAC;IAEF,MAAM,QAAQ,GAAG,IAAI,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACpD,aAAa,CAAC,GAAG,CAAC,aAAa,EAAE;QAC/B,QAAQ;QACR,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACtB,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,SAAkB;IAC9C,MAAM,QAAQ,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IACxD,IAAI,QAAQ,EAAE,CAAC;QACb,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,MAAM,kBAAkB,GACtB,+FAA+F,CAAC;AAElG;;;GAGG;AACH,SAAS,gBAAgB,CAAC,KAAc;IACtC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnE,OAAO,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAqE;IAErE,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC,CAAC,qBAAqB;IAC5E,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC,CAAC,kBAAkB;IAC5D,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAA6B,EAC7B,SAAuD;IAEvD,MAAM,UAAU,GAAG,MAAM,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC1D,IAAI,CAAC;QACH,OAAO,MAAM,SAAS,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CACX,2EAA2E,KAAK,EAAE,CACnF,CAAC;YACF,aAAa,CAAC,SAAS,CAAC,CAAC;YACzB,MAAM,aAAa,GAAG,MAAM,qBAAqB,CAAC,SAAS,CAAC,CAAC;YAC7D,OAAO,MAAM,SAAS,CAAC,aAAa,CAAC,CAAC;QACxC,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { registerExecuteScriptTool } from "./tools/execute-script.js";
|
|
5
|
+
import { registerRunAtfTestTool, registerRunAtfTestSuiteTool, } from "./tools/atf.js";
|
|
6
|
+
import { registerQueryTableTool } from "./tools/query-table.js";
|
|
7
|
+
import { registerFindAtfTestsTool } from "./tools/find-atf-tests.js";
|
|
8
|
+
import { registerQuerySyslogTool } from "./tools/query-syslog.js";
|
|
9
|
+
import { registerLookupAppTool } from "./tools/lookup-app.js";
|
|
10
|
+
import { registerLookupTableTool } from "./tools/lookup-table.js";
|
|
11
|
+
import { registerLookupColumnsTool } from "./tools/lookup-columns.js";
|
|
12
|
+
import { registerCodeSearchTool, registerListCodeSearchGroupsTool, registerListCodeSearchTablesTool, registerAddCodeSearchTableTool, } from "./tools/codesearch.js";
|
|
13
|
+
import { registerDiscoverTableSchemaTool, registerExplainFieldTool, registerValidateCatalogTool, } from "./tools/schema.js";
|
|
14
|
+
import { registerGetCurrentScopeTool, registerSetCurrentScopeTool, registerListScopedAppsTool, } from "./tools/scope.js";
|
|
15
|
+
import { registerGetCurrentUpdateSetTool, registerListUpdateSetsTool, registerCreateUpdateSetTool, registerSetCurrentUpdateSetTool, registerInspectUpdateSetTool, registerCloneUpdateSetTool, registerMoveUpdateSetRecordsTool, } from "./tools/updateset.js";
|
|
16
|
+
import { registerAddTaskCommentTool, registerAssignTaskTool, registerResolveIncidentTool, registerCloseIncidentTool, registerApproveChangeTool, registerFindTaskTool, } from "./tools/task.js";
|
|
17
|
+
import { registerBatchCreateRecordsTool, registerBatchUpdateRecordsTool, } from "./tools/batch.js";
|
|
18
|
+
import { registerListAttachmentsTool, registerGetAttachmentInfoTool, registerUploadAttachmentTool, } from "./tools/attachment.js";
|
|
19
|
+
import { registerGetAppDetailsTool, registerValidateAppInstallTool, registerSearchStoreAppsTool, registerListCompanyAppsTool, registerInstallStoreAppTool, registerUpdateStoreAppTool, registerInstallFromAppRepoTool, registerPublishToAppRepoTool, } from "./tools/app-manager.js";
|
|
20
|
+
import { registerCreateWorkflowTool } from "./tools/workflow.js";
|
|
21
|
+
import { registerPullScriptTool, registerPushScriptTool, } from "./tools/scriptsync.js";
|
|
22
|
+
import { registerCountRecordsTool, registerAggregateQueryTool, registerAggregateGroupedTool, } from "./tools/aggregate.js";
|
|
23
|
+
import { registerCheckInstanceHealthTool } from "./tools/health.js";
|
|
24
|
+
import { registerGetCmdbRelationshipsTool, registerTraverseCmdbGraphTool, } from "./tools/cmdb.js";
|
|
25
|
+
import { registerListInstanceTablesTool, registerListPluginsTool, } from "./tools/discovery.js";
|
|
26
|
+
import { registerQueryUpdateRecordsTool, registerQueryDeleteRecordsTool, } from "./tools/query-batch.js";
|
|
27
|
+
const server = new McpServer({
|
|
28
|
+
name: "now-sdk-ext-mcp",
|
|
29
|
+
version: "1.0.0-alpha.0",
|
|
30
|
+
});
|
|
31
|
+
// Register tools
|
|
32
|
+
registerExecuteScriptTool(server);
|
|
33
|
+
registerRunAtfTestTool(server);
|
|
34
|
+
registerRunAtfTestSuiteTool(server);
|
|
35
|
+
registerQueryTableTool(server);
|
|
36
|
+
registerFindAtfTestsTool(server);
|
|
37
|
+
registerQuerySyslogTool(server);
|
|
38
|
+
registerLookupAppTool(server);
|
|
39
|
+
registerLookupTableTool(server);
|
|
40
|
+
registerLookupColumnsTool(server);
|
|
41
|
+
registerCodeSearchTool(server);
|
|
42
|
+
registerListCodeSearchGroupsTool(server);
|
|
43
|
+
registerListCodeSearchTablesTool(server);
|
|
44
|
+
registerAddCodeSearchTableTool(server);
|
|
45
|
+
registerDiscoverTableSchemaTool(server);
|
|
46
|
+
registerExplainFieldTool(server);
|
|
47
|
+
registerValidateCatalogTool(server);
|
|
48
|
+
registerGetCurrentScopeTool(server);
|
|
49
|
+
registerSetCurrentScopeTool(server);
|
|
50
|
+
registerListScopedAppsTool(server);
|
|
51
|
+
registerGetCurrentUpdateSetTool(server);
|
|
52
|
+
registerListUpdateSetsTool(server);
|
|
53
|
+
registerCreateUpdateSetTool(server);
|
|
54
|
+
registerSetCurrentUpdateSetTool(server);
|
|
55
|
+
registerInspectUpdateSetTool(server);
|
|
56
|
+
registerAddTaskCommentTool(server);
|
|
57
|
+
registerAssignTaskTool(server);
|
|
58
|
+
registerResolveIncidentTool(server);
|
|
59
|
+
registerCloseIncidentTool(server);
|
|
60
|
+
registerApproveChangeTool(server);
|
|
61
|
+
registerFindTaskTool(server);
|
|
62
|
+
registerBatchCreateRecordsTool(server);
|
|
63
|
+
registerBatchUpdateRecordsTool(server);
|
|
64
|
+
registerListAttachmentsTool(server);
|
|
65
|
+
registerGetAttachmentInfoTool(server);
|
|
66
|
+
registerGetAppDetailsTool(server);
|
|
67
|
+
registerValidateAppInstallTool(server);
|
|
68
|
+
registerSearchStoreAppsTool(server);
|
|
69
|
+
registerListCompanyAppsTool(server);
|
|
70
|
+
registerInstallStoreAppTool(server);
|
|
71
|
+
registerUpdateStoreAppTool(server);
|
|
72
|
+
registerInstallFromAppRepoTool(server);
|
|
73
|
+
registerPublishToAppRepoTool(server);
|
|
74
|
+
registerCreateWorkflowTool(server);
|
|
75
|
+
registerPullScriptTool(server);
|
|
76
|
+
registerPushScriptTool(server);
|
|
77
|
+
registerCountRecordsTool(server);
|
|
78
|
+
registerAggregateQueryTool(server);
|
|
79
|
+
registerAggregateGroupedTool(server);
|
|
80
|
+
registerCheckInstanceHealthTool(server);
|
|
81
|
+
registerGetCmdbRelationshipsTool(server);
|
|
82
|
+
registerTraverseCmdbGraphTool(server);
|
|
83
|
+
registerListInstanceTablesTool(server);
|
|
84
|
+
registerListPluginsTool(server);
|
|
85
|
+
registerQueryUpdateRecordsTool(server);
|
|
86
|
+
registerQueryDeleteRecordsTool(server);
|
|
87
|
+
registerCloneUpdateSetTool(server);
|
|
88
|
+
registerMoveUpdateSetRecordsTool(server);
|
|
89
|
+
registerUploadAttachmentTool(server);
|
|
90
|
+
// Prevent the process from crashing silently on unexpected errors.
|
|
91
|
+
// Log to stderr (stdout is reserved for JSON-RPC).
|
|
92
|
+
process.on("uncaughtException", (error) => {
|
|
93
|
+
console.error("[now-sdk-ext-mcp] Uncaught exception:", error);
|
|
94
|
+
});
|
|
95
|
+
process.on("unhandledRejection", (reason) => {
|
|
96
|
+
console.error("[now-sdk-ext-mcp] Unhandled rejection:", reason);
|
|
97
|
+
});
|
|
98
|
+
// Start the server on stdio transport
|
|
99
|
+
async function main() {
|
|
100
|
+
const transport = new StdioServerTransport();
|
|
101
|
+
await server.connect(transport);
|
|
102
|
+
console.error("now-sdk-ext-mcp server running on stdio");
|
|
103
|
+
}
|
|
104
|
+
main().catch((error) => {
|
|
105
|
+
console.error("Fatal error:", error);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
});
|
|
108
|
+
//# sourceMappingURL=index.js.map
|