@sonisoft/now-sdk-ext-mcp 4.6.0 → 4.7.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 +31 -0
- package/dist/common/annotations.d.ts +14 -9
- package/dist/common/annotations.d.ts.map +1 -1
- package/dist/common/annotations.js +39 -54
- package/dist/common/annotations.js.map +1 -1
- package/dist/common/guard.d.ts +18 -0
- package/dist/common/guard.d.ts.map +1 -0
- package/dist/common/guard.js +124 -0
- package/dist/common/guard.js.map +1 -0
- package/dist/index.js +16 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -266,6 +266,35 @@ This MCP server wraps the same core library used by the CLI:
|
|
|
266
266
|
|
|
267
267
|
When adding new MCP tools, reference the corresponding CLI command in `now-sdk-ext-cli/src/commands/` for the expected behavior and data flow.
|
|
268
268
|
|
|
269
|
+
## Restricting what can be changed
|
|
270
|
+
|
|
271
|
+
Instance changes are **permitted by default**. Set `NEX_POLICY_DENY` in the server's
|
|
272
|
+
environment to refuse them:
|
|
273
|
+
|
|
274
|
+
```json
|
|
275
|
+
{
|
|
276
|
+
"mcpServers": {
|
|
277
|
+
"now-sdk-ext": {
|
|
278
|
+
"command": "now-sdk-ext-mcp",
|
|
279
|
+
"env": { "NEX_POLICY_DENY": "all" }
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Refused tools return an error result explaining that nothing was changed; read-only
|
|
286
|
+
tools are unaffected. There is deliberately **no tool parameter** to grant permission —
|
|
287
|
+
on this surface the caller is the model, so a parameter it can set would not be a
|
|
288
|
+
control.
|
|
289
|
+
|
|
290
|
+
> `NEX_POLICY_DENY` only holds when set somewhere the model cannot write. The config
|
|
291
|
+
> file above usually lives **in the workspace**, and an agent with file-write access can
|
|
292
|
+
> edit it. For a real lockdown set it in the environment that launches the client — a
|
|
293
|
+
> shell profile, a systemd unit, or a container env.
|
|
294
|
+
>
|
|
295
|
+
> This is a guardrail, not a security boundary. Anything holding the credential can
|
|
296
|
+
> reach the instance directly.
|
|
297
|
+
|
|
269
298
|
## Contributing
|
|
270
299
|
|
|
271
300
|
### Testing
|
|
@@ -405,6 +434,8 @@ Since stdout is reserved for JSON-RPC, **never use `console.log()` in server cod
|
|
|
405
434
|
| `NEX_LOG_FILE` | `1`/`true` writes a log file to `$XDG_STATE_HOME/now-sdk-ext/logs` (`~/.local/state/...`) |
|
|
406
435
|
| `NEX_LOG_DIR` | Write log files to this directory instead. Implies `NEX_LOG_FILE` |
|
|
407
436
|
| `NEX_LOG_LEVEL` | `error`, `warn`, `info` (default), `http`, `verbose`, `debug`, `silly` |
|
|
437
|
+
| `NEX_POLICY_DENY` | `write`, `execute`, or `all` — refuses matching instance changes. Malformed values **fail closed** |
|
|
438
|
+
| `NEX_POLICY_ALLOW` | Grants verbs. Inert while changes are permitted by default |
|
|
408
439
|
|
|
409
440
|
Diagnostics always go to **stderr**, never stdout — stdout carries JSON-RPC. Credential material is stripped from both metadata and message text before anything is written.
|
|
410
441
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Requirement, Target, Verb } from "@sonisoft/now-sdk-ext-core";
|
|
1
2
|
/**
|
|
2
3
|
* Tool annotations — the machine-readable risk classification for every tool.
|
|
3
4
|
*
|
|
@@ -41,16 +42,20 @@ export interface ToolAnnotations {
|
|
|
41
42
|
destructiveHint?: boolean;
|
|
42
43
|
idempotentHint?: boolean;
|
|
43
44
|
openWorldHint?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* What permission this tool needs. NOT part of MCP — `annotationsFor` strips both
|
|
47
|
+
* of these before the annotations go over the wire.
|
|
48
|
+
*
|
|
49
|
+
* Carried here rather than in a second table because the completeness test already
|
|
50
|
+
* guarantees every registered tool appears in TOOL_ANNOTATIONS, so a new tool
|
|
51
|
+
* cannot arrive without a classification. A parallel table would drift.
|
|
52
|
+
*/
|
|
53
|
+
verbs?: readonly Verb[];
|
|
54
|
+
target?: Target;
|
|
44
55
|
}
|
|
45
56
|
export declare const TOOL_ANNOTATIONS: Record<string, ToolAnnotations>;
|
|
46
|
-
/**
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
* Throws on an unknown name rather than returning a permissive default. An
|
|
50
|
-
* unannotated tool would silently inherit the spec defaults — `readOnlyHint`
|
|
51
|
-
* false, `destructiveHint` TRUE — which is safe, but it would also mean a new
|
|
52
|
-
* tool could ship with no deliberate classification and nobody would notice.
|
|
53
|
-
* Failing at registration makes that impossible.
|
|
54
|
-
*/
|
|
57
|
+
/** What permission a tool needs. Throws on an unknown name — see `lookup`. */
|
|
58
|
+
export declare function requirementFor(toolName: string): Requirement;
|
|
59
|
+
/** The annotations sent to the client. */
|
|
55
60
|
export declare function annotationsFor(toolName: string): ToolAnnotations;
|
|
56
61
|
//# sourceMappingURL=annotations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../src/common/annotations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,MAAM,WAAW,eAAe;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../src/common/annotations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,MAAM,WAAW,eAAe;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAoCD,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAwJ5D,CAAC;AAEF,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAM5D;AA2BD,0CAA0C;AAC1C,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAKhE"}
|
|
@@ -1,51 +1,13 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool annotations — the machine-readable risk classification for every tool.
|
|
3
|
-
*
|
|
4
|
-
* Until now the only signal that a tool deletes records rather than reads them
|
|
5
|
-
* was prose in its description ("IMPORTANT: This PERMANENTLY DELETES..."). A
|
|
6
|
-
* host client cannot act on prose, so it had to prompt for all 86 tools equally
|
|
7
|
-
* — including `query_table` and `count_records`, which cannot change anything.
|
|
8
|
-
* Prompting uniformly trains people to click through, which is worse than not
|
|
9
|
-
* prompting at all.
|
|
10
|
-
*
|
|
11
|
-
* Kept as ONE table rather than inlined at 86 registration sites, because
|
|
12
|
-
* NEX-40 (role-based tool filtering) needs exactly the same central metadata.
|
|
13
|
-
* Building it twice would guarantee the two drift.
|
|
14
|
-
*
|
|
15
|
-
* These are HINTS, not guarantees. The authority on what a tool may do is the
|
|
16
|
-
* ServiceNow ACLs of the authenticated user; this only describes intent.
|
|
17
|
-
*
|
|
18
|
-
* ---
|
|
19
|
-
*
|
|
20
|
-
* Classification rules used here, since the spec defaults are easy to misread:
|
|
21
|
-
*
|
|
22
|
-
* - `readOnlyHint: true` — cannot modify anything. destructive/idempotent are
|
|
23
|
-
* meaningless alongside it and are omitted.
|
|
24
|
-
* - `destructiveHint` — DEFAULTS TO TRUE, so it must be set false explicitly for
|
|
25
|
-
* writes that only add. Reserved for operations that can lose or overwrite
|
|
26
|
-
* data that already existed.
|
|
27
|
-
* - `idempotentHint` — repeating the call with identical arguments leaves the
|
|
28
|
-
* same end state. True for "set this field to X"; false for "append a comment"
|
|
29
|
-
* or "create a record", which accumulate.
|
|
30
|
-
* - `openWorldHint` — TRUE FOR EVERY TOOL HERE, and set explicitly rather than
|
|
31
|
-
* left to the spec's default. All of them talk to a live ServiceNow instance,
|
|
32
|
-
* which is exactly what the spec means by an open world. It was tempting to use
|
|
33
|
-
* it to single out arbitrary code execution, but that would have been wrong in
|
|
34
|
-
* both directions: the spec default is already `true`, so the marking would
|
|
35
|
-
* have been a no-op, and leaving it off the other 80-odd would have implied
|
|
36
|
-
* they were closed-world when they are not. MCP has no hint for "runs
|
|
37
|
-
* caller-supplied logic" — the tool description carries that.
|
|
38
|
-
*/
|
|
39
1
|
/** Cannot modify anything. */
|
|
40
|
-
const READ = { readOnlyHint: true, openWorldHint: true };
|
|
2
|
+
const READ = { verbs: [], target: "instance", readOnlyHint: true, openWorldHint: true };
|
|
41
3
|
/** Adds something new; nothing pre-existing is lost. Repeating accumulates. */
|
|
42
|
-
const CREATE = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true };
|
|
4
|
+
const CREATE = { verbs: ["write"], target: "instance", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true };
|
|
43
5
|
/** Sets state to a given value. Nothing is destroyed; repeating is a no-op. */
|
|
44
|
-
const SET = { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true };
|
|
6
|
+
const SET = { verbs: ["write"], target: "instance", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true };
|
|
45
7
|
/** Overwrites or removes data that already existed. Repeating settles. */
|
|
46
|
-
const OVERWRITE = { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true };
|
|
8
|
+
const OVERWRITE = { verbs: ["write"], target: "instance", readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true };
|
|
47
9
|
/** Overwrites or removes, and repeating does NOT settle. */
|
|
48
|
-
const OVERWRITE_ONCE = { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true };
|
|
10
|
+
const OVERWRITE_ONCE = { verbs: ["write"], target: "instance", readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true };
|
|
49
11
|
/**
|
|
50
12
|
* Runs caller-supplied logic — a script or a flow someone else authored.
|
|
51
13
|
*
|
|
@@ -54,7 +16,15 @@ const OVERWRITE_ONCE = { readOnlyHint: false, destructiveHint: true, idempotentH
|
|
|
54
16
|
* tools are in that category; the warning that actually reaches the model is in
|
|
55
17
|
* the tool description.
|
|
56
18
|
*/
|
|
57
|
-
const ARBITRARY =
|
|
19
|
+
const ARBITRARY = {
|
|
20
|
+
...OVERWRITE_ONCE,
|
|
21
|
+
// The MCP hints stay identical to OVERWRITE_ONCE — the protocol has no hint for
|
|
22
|
+
// "unbounded effect". What differs is the permission: running caller-supplied or
|
|
23
|
+
// third-party logic needs `execute`, and it can write, so it needs both.
|
|
24
|
+
verbs: ["execute", "write"],
|
|
25
|
+
};
|
|
26
|
+
/** Writes to the LOCAL filesystem. Read-only with respect to the instance. */
|
|
27
|
+
const LOCAL_WRITE = { ...OVERWRITE, target: "local" };
|
|
58
28
|
export const TOOL_ANNOTATIONS = {
|
|
59
29
|
// ---- meta: reports this server's own configuration, touches no instance.
|
|
60
30
|
// Registered outside TOOL_REGISTRY because it is always available regardless
|
|
@@ -79,8 +49,8 @@ export const TOOL_ANNOTATIONS = {
|
|
|
79
49
|
// ---- ATF: tests execute real logic against the instance and routinely
|
|
80
50
|
// create and modify records as part of running.
|
|
81
51
|
find_atf_tests: READ,
|
|
82
|
-
run_atf_test:
|
|
83
|
-
run_atf_test_suite:
|
|
52
|
+
run_atf_test: ARBITRARY,
|
|
53
|
+
run_atf_test_suite: ARBITRARY,
|
|
84
54
|
// ---- attachments
|
|
85
55
|
list_attachments: READ,
|
|
86
56
|
get_attachment_info: READ,
|
|
@@ -158,7 +128,7 @@ export const TOOL_ANNOTATIONS = {
|
|
|
158
128
|
// Writes to the LOCAL filesystem and will overwrite an existing file. Read-only
|
|
159
129
|
// with respect to ServiceNow, but "read-only" means the environment, not the
|
|
160
130
|
// instance.
|
|
161
|
-
pull_script:
|
|
131
|
+
pull_script: LOCAL_WRITE,
|
|
162
132
|
// Overwrites the script record on the instance.
|
|
163
133
|
push_script: OVERWRITE,
|
|
164
134
|
// ---- tasks: field updates and appends
|
|
@@ -185,16 +155,24 @@ export const TOOL_ANNOTATIONS = {
|
|
|
185
155
|
// Imports can update existing records, matched by sys_id.
|
|
186
156
|
import_records_xml: OVERWRITE_ONCE,
|
|
187
157
|
};
|
|
158
|
+
/** What permission a tool needs. Throws on an unknown name — see `lookup`. */
|
|
159
|
+
export function requirementFor(toolName) {
|
|
160
|
+
const annotations = lookup(toolName);
|
|
161
|
+
return {
|
|
162
|
+
verbs: annotations.verbs ?? ["write"],
|
|
163
|
+
target: annotations.target ?? "instance",
|
|
164
|
+
};
|
|
165
|
+
}
|
|
188
166
|
/**
|
|
189
|
-
*
|
|
167
|
+
* The raw table entry, including the non-MCP fields.
|
|
190
168
|
*
|
|
191
|
-
* Throws on an unknown name rather than returning a permissive default. An
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
169
|
+
* Throws on an unknown name rather than returning a permissive default. An unannotated
|
|
170
|
+
* tool would silently inherit the spec defaults — `readOnlyHint` false,
|
|
171
|
+
* `destructiveHint` TRUE — which is safe on the wire, but it would also mean a new tool
|
|
172
|
+
* could ship with no deliberate permission classification and nobody would notice.
|
|
173
|
+
* Because the guard calls this at REGISTRATION, failing here stops the server booting.
|
|
196
174
|
*/
|
|
197
|
-
|
|
175
|
+
function lookup(toolName) {
|
|
198
176
|
// hasOwnProperty, not bracket access: TOOL_ANNOTATIONS["constructor"] would
|
|
199
177
|
// otherwise return the Object constructor — truthy — and this would hand back
|
|
200
178
|
// a function instead of throwing.
|
|
@@ -207,4 +185,11 @@ export function annotationsFor(toolName) {
|
|
|
207
185
|
}
|
|
208
186
|
return annotations;
|
|
209
187
|
}
|
|
188
|
+
/** The annotations sent to the client. */
|
|
189
|
+
export function annotationsFor(toolName) {
|
|
190
|
+
// `verbs` and `target` are ours, not MCP's. Strip them here so nothing
|
|
191
|
+
// non-standard reaches the client — the wire shape is unchanged by this feature.
|
|
192
|
+
const { verbs: _verbs, target: _target, ...wire } = lookup(toolName);
|
|
193
|
+
return wire;
|
|
194
|
+
}
|
|
210
195
|
//# sourceMappingURL=annotations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"annotations.js","sourceRoot":"","sources":["../../src/common/annotations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"annotations.js","sourceRoot":"","sources":["../../src/common/annotations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
/** Installs the ladder for this server process. Call once, at startup. */
|
|
3
|
+
export declare function initPolicy(): void;
|
|
4
|
+
/**
|
|
5
|
+
* Wraps a server so every tool registered through it is permission-checked.
|
|
6
|
+
*
|
|
7
|
+
* A Proxy over `registerTool` rather than a change to `ToolRegistrar`. That signature is
|
|
8
|
+
* `(server) => void` across all 87 registrations, and `registry.test.ts` calls each
|
|
9
|
+
* registrar with a bare `{registerTool}` fake — changing it would mean 87 edits and a
|
|
10
|
+
* broken test for no benefit. Wrapping the server leaves both untouched, and because
|
|
11
|
+
* `annotations.test.ts` already regexes on the exact `server.registerTool(` call shape,
|
|
12
|
+
* a new tool cannot be added in a way that avoids this.
|
|
13
|
+
*
|
|
14
|
+
* Refusals are RETURNED as `isError` results, never thrown: a throw becomes a protocol
|
|
15
|
+
* error, while a result is something the model can read and act on.
|
|
16
|
+
*/
|
|
17
|
+
export declare function guardServer(server: McpServer): McpServer;
|
|
18
|
+
//# sourceMappingURL=guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/common/guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA8BpE,0EAA0E;AAC1E,wBAAgB,UAAU,IAAI,IAAI,CA6BjC;AAgCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAkDxD"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { allowFromEnvironment, checkRequirement, denyFromEnvironment, grantLayer, installPolicy, setRemediationWriter, } from "@sonisoft/now-sdk-ext-core";
|
|
2
|
+
import { requirementFor } from "./annotations.js";
|
|
3
|
+
import { getLogger } from "./logging.js";
|
|
4
|
+
/**
|
|
5
|
+
* Permission enforcement for tool calls.
|
|
6
|
+
*
|
|
7
|
+
* Changes are PERMITTED by default, matching the CLI. Configuration is environment-only
|
|
8
|
+
* because an MCP server does not control its own argv — whoever launches it sets
|
|
9
|
+
* `NEX_POLICY_DENY`, and that is the layer the model cannot reach.
|
|
10
|
+
*
|
|
11
|
+
* There is deliberately NO per-tool "allow" parameter. On this surface the caller IS
|
|
12
|
+
* the model, so a parameter it can set is not a control — and with a permissive default
|
|
13
|
+
* it would grant nothing it did not already have. The same reasoning that kept
|
|
14
|
+
* `--allow-write` off the CLI.
|
|
15
|
+
*/
|
|
16
|
+
const log = getLogger("policy");
|
|
17
|
+
/** Installs the ladder for this server process. Call once, at startup. */
|
|
18
|
+
export function initPolicy() {
|
|
19
|
+
const layers = [];
|
|
20
|
+
// 0. Operator lockdown, and the only rung the model cannot reach.
|
|
21
|
+
//
|
|
22
|
+
// The guarantee has a precise limit worth stating: it holds only when set
|
|
23
|
+
// somewhere the model cannot write. An MCP server is launched from a config file
|
|
24
|
+
// — often .mcp.json inside the workspace — and an agent with file-write access
|
|
25
|
+
// can edit that. Set it in a shell profile, systemd unit, or container env.
|
|
26
|
+
const envDeny = denyFromEnvironment(process.env, (m) => log.warn(m));
|
|
27
|
+
if (envDeny)
|
|
28
|
+
layers.push(envDeny);
|
|
29
|
+
// 1. Grants from the environment. Inert while the default is permissive; kept so
|
|
30
|
+
// the ladder does not need rebuilding if the default ever flips.
|
|
31
|
+
const envAllow = allowFromEnvironment(process.env, (m) => log.warn(m));
|
|
32
|
+
if (envAllow)
|
|
33
|
+
layers.push(envAllow);
|
|
34
|
+
// 2. THE DEFAULT. Delete this layer to make the server deny-by-default.
|
|
35
|
+
layers.push(grantLayer("default (changes permitted)", ["write", "execute"]));
|
|
36
|
+
installPolicy(layers);
|
|
37
|
+
setRemediationWriter((_verbs, missing, layer) => {
|
|
38
|
+
const what = missing === "execute" ? "Running scripts or flows" : "Changing instance data";
|
|
39
|
+
return `${what} is not permitted in this session (${layer}).`;
|
|
40
|
+
});
|
|
41
|
+
if (envDeny) {
|
|
42
|
+
log.info("Instance changes are restricted by the environment", { layer: envDeny.name });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function refusalResult(toolName, verbs, layer) {
|
|
46
|
+
const what = verbs.includes("execute")
|
|
47
|
+
? "run scripts, flows or tests"
|
|
48
|
+
: "change instance data";
|
|
49
|
+
return {
|
|
50
|
+
content: [
|
|
51
|
+
{
|
|
52
|
+
type: "text",
|
|
53
|
+
// States the situation without naming an escape hatch. There is nothing
|
|
54
|
+
// the model can pass to get past this, and implying otherwise would just
|
|
55
|
+
// produce a retry loop.
|
|
56
|
+
text: `Refused: this session is not permitted to ${what}.\n\n` +
|
|
57
|
+
`The tool "${toolName}" was not called and nothing was changed. ` +
|
|
58
|
+
`This restriction is set in the server's environment (${layer}) and ` +
|
|
59
|
+
`cannot be changed from a tool call. Read-only tools are unaffected.`,
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
isError: true,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Wraps a server so every tool registered through it is permission-checked.
|
|
67
|
+
*
|
|
68
|
+
* A Proxy over `registerTool` rather than a change to `ToolRegistrar`. That signature is
|
|
69
|
+
* `(server) => void` across all 87 registrations, and `registry.test.ts` calls each
|
|
70
|
+
* registrar with a bare `{registerTool}` fake — changing it would mean 87 edits and a
|
|
71
|
+
* broken test for no benefit. Wrapping the server leaves both untouched, and because
|
|
72
|
+
* `annotations.test.ts` already regexes on the exact `server.registerTool(` call shape,
|
|
73
|
+
* a new tool cannot be added in a way that avoids this.
|
|
74
|
+
*
|
|
75
|
+
* Refusals are RETURNED as `isError` results, never thrown: a throw becomes a protocol
|
|
76
|
+
* error, while a result is something the model can read and act on.
|
|
77
|
+
*/
|
|
78
|
+
export function guardServer(server) {
|
|
79
|
+
return new Proxy(server, {
|
|
80
|
+
get(target, property, receiver) {
|
|
81
|
+
// Function results are rebound to `target` below, which sidesteps the
|
|
82
|
+
// classic Proxy-vs-#private brand-check failure for METHODS. Non-function
|
|
83
|
+
// properties are still read with `receiver = proxy`, so if a future SDK
|
|
84
|
+
// version adds an accessor that touches a real `#private` field, reading it
|
|
85
|
+
// through the guard would throw. Nothing does today — TS `private` alone is
|
|
86
|
+
// not a real private field — but it is a hard failure to trace back here.
|
|
87
|
+
const value = Reflect.get(target, property, receiver);
|
|
88
|
+
if (property !== "registerTool" || typeof value !== "function") {
|
|
89
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
90
|
+
}
|
|
91
|
+
const original = value;
|
|
92
|
+
return function registerToolGuarded(name, config, handler) {
|
|
93
|
+
// Throws for an unclassified tool, at REGISTRATION time — so a tool
|
|
94
|
+
// without a permission classification cannot start the server, rather
|
|
95
|
+
// than failing on first call in front of a user.
|
|
96
|
+
const requirement = requirementFor(name);
|
|
97
|
+
const guarded = async (...args) => {
|
|
98
|
+
const decision = checkRequirement(requirement);
|
|
99
|
+
if (!decision.allowed) {
|
|
100
|
+
log.warn("Refused a tool call", {
|
|
101
|
+
tool: name,
|
|
102
|
+
verbs: decision.verbs,
|
|
103
|
+
decidingLayer: decision.decidingLayer,
|
|
104
|
+
});
|
|
105
|
+
return refusalResult(name, decision.verbs, decision.decidingLayer);
|
|
106
|
+
}
|
|
107
|
+
// Logged so a session's mutations are reconstructable afterwards.
|
|
108
|
+
// Reads are not logged — they are the overwhelming majority and
|
|
109
|
+
// would drown the signal.
|
|
110
|
+
if (requirement.verbs.length > 0 && requirement.target === "instance") {
|
|
111
|
+
log.info("Permitted a change", {
|
|
112
|
+
tool: name,
|
|
113
|
+
verbs: requirement.verbs,
|
|
114
|
+
grantedBy: decision.decidingLayer,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return handler(...args);
|
|
118
|
+
};
|
|
119
|
+
return original.call(target, name, config, guarded);
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/common/guard.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,11 @@ import "./common/credstore-boot.js";
|
|
|
9
9
|
import { flushLogs } from "@sonisoft/now-sdk-ext-core";
|
|
10
10
|
import { initLogging, getLogger } from "./common/logging.js";
|
|
11
11
|
initLogging();
|
|
12
|
+
// Third, before any tool is registered: the permission ladder. Changes are permitted
|
|
13
|
+
// by default; NEX_POLICY_DENY in the server's environment is what restricts them, and
|
|
14
|
+
// it is the only layer the model cannot reach.
|
|
15
|
+
import { guardServer, initPolicy } from "./common/guard.js";
|
|
16
|
+
initPolicy();
|
|
12
17
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
13
18
|
import { registerServiceNowResources } from "./resources/servicenow.js";
|
|
14
19
|
import { TOOL_REGISTRY } from "./tools/registry.js";
|
|
@@ -31,6 +36,11 @@ const server = new McpServer({
|
|
|
31
36
|
resources: {},
|
|
32
37
|
},
|
|
33
38
|
});
|
|
39
|
+
// Intentionally the RAW server, not the guard. MCP resources are representational and
|
|
40
|
+
// read-only — the ServiceNow ones expose scope, update-set and schema — so there is
|
|
41
|
+
// nothing here for a permission check to refuse. Stated explicitly because the loop
|
|
42
|
+
// below deliberately does use the guard, and the difference should not read as an
|
|
43
|
+
// oversight in a security-relevant path.
|
|
34
44
|
registerServiceNowResources(server);
|
|
35
45
|
// Tools are registered through the registry rather than 86 direct calls, so a
|
|
36
46
|
// package can select a subset. Resolution happens once, before registration —
|
|
@@ -38,13 +48,17 @@ registerServiceNowResources(server);
|
|
|
38
48
|
// the tools in tools/list.
|
|
39
49
|
const activePackage = resolveToolPackage(process.env.MCP_TOOL_PACKAGE);
|
|
40
50
|
reportResolution(activePackage);
|
|
51
|
+
// Registered through the guard, not the server directly. The Proxy intercepts
|
|
52
|
+
// registerTool and wraps each handler with a permission check — a tool cannot opt out,
|
|
53
|
+
// and an unclassified tool fails at startup rather than on first use.
|
|
54
|
+
const guarded = guardServer(server);
|
|
41
55
|
for (const name of activePackage.tools) {
|
|
42
|
-
TOOL_REGISTRY[name](
|
|
56
|
+
TOOL_REGISTRY[name](guarded);
|
|
43
57
|
}
|
|
44
58
|
// Always registered, whatever the package. A filtered session otherwise has no
|
|
45
59
|
// way to tell "this server cannot do that" from "that tool is filtered out of
|
|
46
60
|
// this session".
|
|
47
|
-
registerListToolPackagesTool(
|
|
61
|
+
registerListToolPackagesTool(guarded, activePackage);
|
|
48
62
|
// Prevent the process from crashing silently on unexpected errors.
|
|
49
63
|
// Log to stderr (stdout is reserved for JSON-RPC).
|
|
50
64
|
// Through the logger, not console.error: an uncaught error here can be an auth or
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,iFAAiF;AACjF,uEAAuE;AACvE,uEAAuE;AACvE,OAAO,4BAA4B,CAAC;AAEpC,kFAAkF;AAClF,oFAAoF;AACpF,4DAA4D;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC7D,WAAW,EAAE,CAAC;AAEd,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;AAC7B,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;IACE,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,iBAAiB,EAAE;CAC7B,EACD;IACE,gFAAgF;IAChF,EAAE;IACF,8EAA8E;IAC9E,+EAA+E;IAC/E,gFAAgF;IAChF,YAAY,EAAE;QACZ,KAAK,EAAE,EAAE;QACT,SAAS,EAAE,EAAE;KACd;CACF,CACF,CAAC;AAEF,2BAA2B,CAAC,MAAM,CAAC,CAAC;AAEpC,8EAA8E;AAC9E,8EAA8E;AAC9E,+EAA+E;AAC/E,2BAA2B;AAC3B,MAAM,aAAa,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AACvE,gBAAgB,CAAC,aAAa,CAAC,CAAC;AAEhC,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,KAAK,EAAE,CAAC;IACvC,aAAa,CAAC,IAAI,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sonisoft/now-sdk-ext-mcp",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.0",
|
|
4
4
|
"description": "MCP server for interacting with ServiceNow instances via @sonisoft/now-sdk-ext-core",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"servicenow",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"@servicenow/sdk-cli": "4.9.2",
|
|
48
48
|
"@servicenow/sdk-cli-core": "3.0.3",
|
|
49
49
|
"@servicenow/sdk-core": "4.9.2",
|
|
50
|
-
"@sonisoft/now-sdk-ext-core": "^6.
|
|
50
|
+
"@sonisoft/now-sdk-ext-core": "^6.1.0",
|
|
51
51
|
"@sonisoft/sn-credstore": "^1.0.0",
|
|
52
52
|
"zod": "^3.23.8"
|
|
53
53
|
},
|