@tenonhq/dovetail-mcp 0.0.14 → 0.0.16
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/dist/registry.js
CHANGED
|
@@ -191,7 +191,7 @@ function buildDescriptors(deps) {
|
|
|
191
191
|
},
|
|
192
192
|
{
|
|
193
193
|
name: "servicenow_query_table",
|
|
194
|
-
description: "Read-only GET against the ServiceNow Table API. Required: table (lower-case identifier), sysparm_query (ServiceNow encoded query). Optional: fields[] limits the columns returned, limit caps row count (default 100, max 1000). Tables on the deny list (sys_user_password, sys_credential, etc.) are rejected unless SINC_MCP_SN_TABLE_OVERRIDE=<table> is set.",
|
|
194
|
+
description: "Read-only GET against the ServiceNow Table API. Required: table (lower-case identifier), sysparm_query (ServiceNow encoded query). Optional: fields[] limits the columns returned, limit caps row count (default 100, max 1000), env retargets a single call to a different instance by naming an env file in the server's working directory ('prod' or '.env.prod' → reads creds from .env.prod; omit to use the startup instance). Tables on the deny list (sys_user_password, sys_credential, etc.) are rejected unless SINC_MCP_SN_TABLE_OVERRIDE=<table> is set.",
|
|
195
195
|
shape: servicenow_1.servicenowQueryTableSchema.shape,
|
|
196
196
|
annotations: dovetail_mcp_kit_1.READ_ONLY,
|
|
197
197
|
handler: function (args) {
|
|
@@ -4,15 +4,18 @@ export declare var servicenowQueryTableSchema: z.ZodObject<{
|
|
|
4
4
|
sysparm_query: z.ZodString;
|
|
5
5
|
fields: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
6
6
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
7
|
+
env: z.ZodOptional<z.ZodString>;
|
|
7
8
|
}, "strict", z.ZodTypeAny, {
|
|
8
9
|
table: string;
|
|
9
10
|
sysparm_query: string;
|
|
10
11
|
fields?: string[] | undefined;
|
|
11
12
|
limit?: number | undefined;
|
|
13
|
+
env?: string | undefined;
|
|
12
14
|
}, {
|
|
13
15
|
table: string;
|
|
14
16
|
sysparm_query: string;
|
|
15
17
|
fields?: string[] | undefined;
|
|
16
18
|
limit?: number | undefined;
|
|
19
|
+
env?: string | undefined;
|
|
17
20
|
}>;
|
|
18
21
|
export type ServicenowQueryTableInput = z.infer<typeof servicenowQueryTableSchema>;
|
|
@@ -6,5 +6,17 @@ exports.servicenowQueryTableSchema = zod_1.z.object({
|
|
|
6
6
|
table: zod_1.z.string().regex(/^[a-z][a-z0-9_]*$/, "Table name must match /^[a-z][a-z0-9_]*$/"),
|
|
7
7
|
sysparm_query: zod_1.z.string(),
|
|
8
8
|
fields: zod_1.z.array(zod_1.z.string().min(1)).optional(),
|
|
9
|
-
limit: zod_1.z.number().int().min(1).max(1000).optional()
|
|
9
|
+
limit: zod_1.z.number().int().min(1).max(1000).optional(),
|
|
10
|
+
// Optional per-call instance retarget. Names an env file in the server's
|
|
11
|
+
// working directory: a bare token like "prod" or "workshop" resolves to
|
|
12
|
+
// ".env.<token>", or pass the full ".env.<name>" basename. Path separators
|
|
13
|
+
// and traversal are rejected (no arbitrary filesystem reads) — see
|
|
14
|
+
// resolveEnvFilePath in tools/servicenow.ts. Omit to use the instance the
|
|
15
|
+
// server was started with.
|
|
16
|
+
env: zod_1.z
|
|
17
|
+
.string()
|
|
18
|
+
.min(1)
|
|
19
|
+
.max(100)
|
|
20
|
+
.regex(/^(\.env(\.[A-Za-z0-9_-]+)?|[A-Za-z0-9_-]+)$/, "env must be an env-file name like 'prod' or '.env.prod' — no path separators or '..'")
|
|
21
|
+
.optional()
|
|
10
22
|
}).strict();
|
|
@@ -14,7 +14,17 @@ import { ServicenowQueryTableInput } from "../schemas/servicenow";
|
|
|
14
14
|
export interface ServiceNowDeps {
|
|
15
15
|
safety: ServiceNowSafetyConfig;
|
|
16
16
|
clientFactory?: () => ServiceNowClient;
|
|
17
|
+
/** Injectable for tests — defaults to the real createClientFromEnvFile. */
|
|
18
|
+
clientFromEnvFile?: (envPath: string) => ServiceNowClient;
|
|
17
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the caller-supplied `env` token to an absolute env-file path inside
|
|
22
|
+
* the server's working directory. The token is untrusted tool input, so this
|
|
23
|
+
* is defense-in-depth on top of the schema regex: reject anything with a path
|
|
24
|
+
* separator or traversal, accept only a `.env` basename (or a bare token that
|
|
25
|
+
* maps to `.env.<token>`), and confirm the resolved path stays within cwd.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveEnvFilePath(env: string): string;
|
|
18
28
|
export declare function servicenowQueryTable(args: ServicenowQueryTableInput, deps: ServiceNowDeps): Promise<{
|
|
19
29
|
table: string;
|
|
20
30
|
count: number;
|
package/dist/tools/servicenow.js
CHANGED
|
@@ -9,10 +9,43 @@
|
|
|
9
9
|
* Tables on the deny list (sys_user_password, sys_credential, sys_audit, …)
|
|
10
10
|
* are rejected unless the operator opts in via SINC_MCP_SN_TABLE_OVERRIDE.
|
|
11
11
|
*/
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
12
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.resolveEnvFilePath = resolveEnvFilePath;
|
|
13
17
|
exports.servicenowQueryTable = servicenowQueryTable;
|
|
18
|
+
const path_1 = __importDefault(require("path"));
|
|
14
19
|
const dovetail_servicenow_1 = require("@tenonhq/dovetail-servicenow");
|
|
15
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the caller-supplied `env` token to an absolute env-file path inside
|
|
22
|
+
* the server's working directory. The token is untrusted tool input, so this
|
|
23
|
+
* is defense-in-depth on top of the schema regex: reject anything with a path
|
|
24
|
+
* separator or traversal, accept only a `.env` basename (or a bare token that
|
|
25
|
+
* maps to `.env.<token>`), and confirm the resolved path stays within cwd.
|
|
26
|
+
*/
|
|
27
|
+
function resolveEnvFilePath(env) {
|
|
28
|
+
if (typeof env !== "string" || env.length === 0) {
|
|
29
|
+
throw new Error("env must be a non-empty string.");
|
|
30
|
+
}
|
|
31
|
+
if (/[\\/]/.test(env) || env.indexOf("..") !== -1) {
|
|
32
|
+
throw new Error("env '" + env + "' is invalid — no path separators or '..'; " +
|
|
33
|
+
"pass a name like 'prod' or '.env.prod'.");
|
|
34
|
+
}
|
|
35
|
+
var basename = env.indexOf(".env") === 0 ? env : ".env." + env;
|
|
36
|
+
var cwd = process.cwd();
|
|
37
|
+
var resolved = path_1.default.resolve(cwd, basename);
|
|
38
|
+
// path.resolve collapses any residual traversal; verify containment.
|
|
39
|
+
if (resolved !== path_1.default.join(cwd, basename) || path_1.default.dirname(resolved) !== cwd) {
|
|
40
|
+
throw new Error("env '" + env + "' resolves outside the working directory.");
|
|
41
|
+
}
|
|
42
|
+
return resolved;
|
|
43
|
+
}
|
|
44
|
+
function resolveClient(deps, env) {
|
|
45
|
+
if (env) {
|
|
46
|
+
var fromEnvFile = deps.clientFromEnvFile || dovetail_servicenow_1.createClientFromEnvFile;
|
|
47
|
+
return fromEnvFile(resolveEnvFilePath(env));
|
|
48
|
+
}
|
|
16
49
|
if (deps.clientFactory) {
|
|
17
50
|
return deps.clientFactory();
|
|
18
51
|
}
|
|
@@ -29,7 +62,7 @@ async function servicenowQueryTable(args, deps) {
|
|
|
29
62
|
throw new Error("Table '" + args.table + "' is in the default deny list. " +
|
|
30
63
|
"Set SINC_MCP_SN_TABLE_OVERRIDE=" + args.table + " (comma-separated for multiple) to enable.");
|
|
31
64
|
}
|
|
32
|
-
var client = resolveClient(deps);
|
|
65
|
+
var client = resolveClient(deps, args.env);
|
|
33
66
|
var limit = args.limit !== undefined ? args.limit : 100;
|
|
34
67
|
var records;
|
|
35
68
|
if (args.fields && args.fields.length > 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tenonhq/dovetail-mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"description": "MCP server exposing read tools for ClickUp / Gmail / Calendar / ServiceNow plus gated ClickUp writes, backed by the Dovetail integration packages.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"@tenonhq/dovetail-google-auth": "~0.0.12",
|
|
23
23
|
"@tenonhq/dovetail-google-calendar": "~0.0.11",
|
|
24
24
|
"@tenonhq/dovetail-mcp-kit": "~0.0.1",
|
|
25
|
-
"@tenonhq/dovetail-servicenow": "~0.0.
|
|
25
|
+
"@tenonhq/dovetail-servicenow": "~0.0.21",
|
|
26
26
|
"dotenv": "^16.3.1",
|
|
27
27
|
"zod": "^3.23.0"
|
|
28
28
|
},
|