mcp-dataverse 0.1.5 → 0.1.7
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/CAPABILITIES.md +1049 -992
- package/README.md +92 -80
- package/config.example.json +0 -1
- package/dist/auth/auth-provider.factory.d.ts +2 -2
- package/dist/auth/auth-provider.factory.js +4 -4
- package/dist/auth/msal-auth-provider.d.ts +2 -2
- package/dist/auth/msal-auth-provider.d.ts.map +1 -1
- package/dist/auth/msal-auth-provider.js +9 -7
- package/dist/auth/msal-auth-provider.js.map +1 -1
- package/dist/auth/pac-auth-provider.d.ts +1 -1
- package/dist/auth/pac-auth-provider.d.ts.map +1 -1
- package/dist/auth/pac-auth-provider.js +39 -35
- package/dist/auth/pac-auth-provider.js.map +1 -1
- package/dist/config/config.loader.d.ts +1 -1
- package/dist/config/config.loader.js +25 -28
- package/dist/config/config.loader.js.map +1 -1
- package/dist/config/config.schema.d.ts +1 -4
- package/dist/config/config.schema.d.ts.map +1 -1
- package/dist/config/config.schema.js +11 -11
- package/dist/config/config.schema.js.map +1 -1
- package/dist/dataverse/dataverse-client-advanced.d.ts +1 -1
- package/dist/dataverse/dataverse-client-advanced.d.ts.map +1 -1
- package/dist/dataverse/dataverse-client-advanced.js +70 -39
- package/dist/dataverse/dataverse-client-advanced.js.map +1 -1
- package/dist/dataverse/dataverse-client.actions.d.ts +11 -0
- package/dist/dataverse/dataverse-client.actions.d.ts.map +1 -0
- package/dist/dataverse/dataverse-client.actions.js +25 -0
- package/dist/dataverse/dataverse-client.actions.js.map +1 -0
- package/dist/dataverse/dataverse-client.batch.d.ts +2 -2
- package/dist/dataverse/dataverse-client.batch.d.ts.map +1 -1
- package/dist/dataverse/dataverse-client.batch.js +12 -12
- package/dist/dataverse/dataverse-client.batch.js.map +1 -1
- package/dist/dataverse/dataverse-client.d.ts +5 -8
- package/dist/dataverse/dataverse-client.d.ts.map +1 -1
- package/dist/dataverse/dataverse-client.js +81 -81
- package/dist/dataverse/dataverse-client.js.map +1 -1
- package/dist/dataverse/dataverse-client.metadata.d.ts +3 -3
- package/dist/dataverse/dataverse-client.metadata.d.ts.map +1 -1
- package/dist/dataverse/dataverse-client.metadata.js +45 -45
- package/dist/dataverse/dataverse-client.metadata.js.map +1 -1
- package/dist/dataverse/dataverse-client.utils.d.ts.map +1 -1
- package/dist/dataverse/dataverse-client.utils.js +5 -5
- package/dist/dataverse/dataverse-client.utils.js.map +1 -1
- package/dist/dataverse/http-client.d.ts +1 -1
- package/dist/dataverse/http-client.d.ts.map +1 -1
- package/dist/dataverse/http-client.js +25 -18
- package/dist/dataverse/http-client.js.map +1 -1
- package/dist/dataverse/types.d.ts +5 -5
- package/dist/server.js +57 -57
- package/dist/server.js.map +1 -1
- package/dist/setup-auth.js +8 -8
- package/dist/setup-auth.js.map +1 -1
- package/dist/tools/actions.tools.d.ts +2 -2
- package/dist/tools/actions.tools.d.ts.map +1 -1
- package/dist/tools/actions.tools.js +108 -65
- package/dist/tools/actions.tools.js.map +1 -1
- package/dist/tools/annotations.tools.d.ts +2 -2
- package/dist/tools/annotations.tools.d.ts.map +1 -1
- package/dist/tools/annotations.tools.js +79 -70
- package/dist/tools/annotations.tools.js.map +1 -1
- package/dist/tools/audit.tools.d.ts +2 -2
- package/dist/tools/audit.tools.d.ts.map +1 -1
- package/dist/tools/audit.tools.js +51 -48
- package/dist/tools/audit.tools.js.map +1 -1
- package/dist/tools/auth.tools.d.ts +2 -2
- package/dist/tools/auth.tools.d.ts.map +1 -1
- package/dist/tools/auth.tools.js +9 -7
- package/dist/tools/auth.tools.js.map +1 -1
- package/dist/tools/batch.tools.d.ts +2 -2
- package/dist/tools/batch.tools.d.ts.map +1 -1
- package/dist/tools/batch.tools.js +39 -26
- package/dist/tools/batch.tools.js.map +1 -1
- package/dist/tools/crud.tools.d.ts +2 -2
- package/dist/tools/crud.tools.d.ts.map +1 -1
- package/dist/tools/crud.tools.js +140 -83
- package/dist/tools/crud.tools.js.map +1 -1
- package/dist/tools/customization.tools.d.ts +2 -2
- package/dist/tools/customization.tools.d.ts.map +1 -1
- package/dist/tools/customization.tools.js +72 -62
- package/dist/tools/customization.tools.js.map +1 -1
- package/dist/tools/environment.tools.d.ts +2 -2
- package/dist/tools/environment.tools.d.ts.map +1 -1
- package/dist/tools/environment.tools.js +62 -55
- package/dist/tools/environment.tools.js.map +1 -1
- package/dist/tools/file.tools.d.ts +2 -2
- package/dist/tools/file.tools.d.ts.map +1 -1
- package/dist/tools/file.tools.js +63 -44
- package/dist/tools/file.tools.js.map +1 -1
- package/dist/tools/impersonate.tools.d.ts +3 -3
- package/dist/tools/impersonate.tools.d.ts.map +1 -1
- package/dist/tools/impersonate.tools.js +22 -20
- package/dist/tools/impersonate.tools.js.map +1 -1
- package/dist/tools/metadata.tools.d.ts +2 -2
- package/dist/tools/metadata.tools.d.ts.map +1 -1
- package/dist/tools/metadata.tools.js +110 -75
- package/dist/tools/metadata.tools.js.map +1 -1
- package/dist/tools/org.tools.d.ts +2 -2
- package/dist/tools/org.tools.d.ts.map +1 -1
- package/dist/tools/org.tools.js +21 -15
- package/dist/tools/org.tools.js.map +1 -1
- package/dist/tools/quality.tools.d.ts +2 -2
- package/dist/tools/quality.tools.d.ts.map +1 -1
- package/dist/tools/quality.tools.js +19 -17
- package/dist/tools/quality.tools.js.map +1 -1
- package/dist/tools/query.tools.d.ts +2 -2
- package/dist/tools/query.tools.d.ts.map +1 -1
- package/dist/tools/query.tools.js +81 -58
- package/dist/tools/query.tools.js.map +1 -1
- package/dist/tools/relations.tools.d.ts +2 -2
- package/dist/tools/relations.tools.d.ts.map +1 -1
- package/dist/tools/relations.tools.js +62 -26
- package/dist/tools/relations.tools.js.map +1 -1
- package/dist/tools/search.tools.d.ts +2 -2
- package/dist/tools/search.tools.d.ts.map +1 -1
- package/dist/tools/search.tools.js +45 -45
- package/dist/tools/search.tools.js.map +1 -1
- package/dist/tools/solution.tools.d.ts +2 -2
- package/dist/tools/solution.tools.d.ts.map +1 -1
- package/dist/tools/solution.tools.js +89 -55
- package/dist/tools/solution.tools.js.map +1 -1
- package/dist/tools/teams.tools.d.ts +2 -2
- package/dist/tools/teams.tools.d.ts.map +1 -1
- package/dist/tools/teams.tools.js +33 -29
- package/dist/tools/teams.tools.js.map +1 -1
- package/dist/tools/trace.tools.d.ts +2 -2
- package/dist/tools/trace.tools.d.ts.map +1 -1
- package/dist/tools/trace.tools.js +111 -101
- package/dist/tools/trace.tools.js.map +1 -1
- package/dist/tools/tracking.tools.d.ts +2 -2
- package/dist/tools/tracking.tools.d.ts.map +1 -1
- package/dist/tools/tracking.tools.js +16 -14
- package/dist/tools/tracking.tools.js.map +1 -1
- package/dist/tools/users.tools.d.ts +2 -2
- package/dist/tools/users.tools.d.ts.map +1 -1
- package/dist/tools/users.tools.js +62 -57
- package/dist/tools/users.tools.js.map +1 -1
- package/dist/tools/validation.utils.d.ts +1 -1
- package/dist/tools/validation.utils.d.ts.map +1 -1
- package/dist/tools/validation.utils.js +9 -3
- package/dist/tools/validation.utils.js.map +1 -1
- package/dist/tools/views.tools.d.ts +2 -2
- package/dist/tools/views.tools.d.ts.map +1 -1
- package/dist/tools/views.tools.js +32 -24
- package/dist/tools/views.tools.js.map +1 -1
- package/package.json +81 -81
- package/server.json +59 -4
package/dist/tools/file.tools.js
CHANGED
|
@@ -1,77 +1,95 @@
|
|
|
1
|
-
import { z } from
|
|
1
|
+
import { z } from "zod";
|
|
2
2
|
const SAFE_NAME_REGEX = /^[a-zA-Z0-9_]+$/;
|
|
3
3
|
const PATH_TRAVERSAL_REGEX = /\.\.|[/\\]/;
|
|
4
4
|
const UploadFileColumnInput = z.object({
|
|
5
|
-
entitySetName: z
|
|
6
|
-
|
|
5
|
+
entitySetName: z
|
|
6
|
+
.string()
|
|
7
|
+
.min(1)
|
|
8
|
+
.refine((v) => !PATH_TRAVERSAL_REGEX.test(v), {
|
|
9
|
+
message: "entitySetName must not contain path traversal characters",
|
|
7
10
|
}),
|
|
8
11
|
recordId: z.string().uuid(),
|
|
9
|
-
columnName: z
|
|
10
|
-
|
|
12
|
+
columnName: z
|
|
13
|
+
.string()
|
|
14
|
+
.min(1)
|
|
15
|
+
.refine((v) => SAFE_NAME_REGEX.test(v), {
|
|
16
|
+
message: "columnName must be alphanumeric/underscore only",
|
|
11
17
|
}),
|
|
12
|
-
fileContent: z.string().min(1).describe(
|
|
18
|
+
fileContent: z.string().min(1).describe("Base64-encoded file content"),
|
|
13
19
|
fileName: z.string().min(1),
|
|
14
20
|
});
|
|
15
21
|
const DownloadFileColumnInput = z.object({
|
|
16
|
-
entitySetName: z
|
|
17
|
-
|
|
22
|
+
entitySetName: z
|
|
23
|
+
.string()
|
|
24
|
+
.min(1)
|
|
25
|
+
.refine((v) => !PATH_TRAVERSAL_REGEX.test(v), {
|
|
26
|
+
message: "entitySetName must not contain path traversal characters",
|
|
18
27
|
}),
|
|
19
28
|
recordId: z.string().uuid(),
|
|
20
|
-
columnName: z
|
|
21
|
-
|
|
29
|
+
columnName: z
|
|
30
|
+
.string()
|
|
31
|
+
.min(1)
|
|
32
|
+
.refine((v) => SAFE_NAME_REGEX.test(v), {
|
|
33
|
+
message: "columnName must be alphanumeric/underscore only",
|
|
22
34
|
}),
|
|
23
35
|
});
|
|
24
36
|
export const fileTools = [
|
|
25
37
|
{
|
|
26
|
-
name:
|
|
27
|
-
description:
|
|
38
|
+
name: "dataverse_upload_file_column",
|
|
39
|
+
description: "Uploads a file to a Dataverse file column. Provide the entity set name, record GUID, column name, base64-encoded file content, and file name. The file is stored in the specified file-type column on the record.",
|
|
28
40
|
inputSchema: {
|
|
29
|
-
type:
|
|
41
|
+
type: "object",
|
|
30
42
|
properties: {
|
|
31
43
|
entitySetName: {
|
|
32
|
-
type:
|
|
44
|
+
type: "string",
|
|
33
45
|
description: 'OData entity set name (e.g., "accounts")',
|
|
34
46
|
},
|
|
35
47
|
recordId: {
|
|
36
|
-
type:
|
|
37
|
-
description:
|
|
48
|
+
type: "string",
|
|
49
|
+
description: "Record GUID",
|
|
38
50
|
},
|
|
39
51
|
columnName: {
|
|
40
|
-
type:
|
|
41
|
-
description:
|
|
52
|
+
type: "string",
|
|
53
|
+
description: "File column logical name",
|
|
42
54
|
},
|
|
43
55
|
fileContent: {
|
|
44
|
-
type:
|
|
45
|
-
description:
|
|
56
|
+
type: "string",
|
|
57
|
+
description: "Base64-encoded file content",
|
|
46
58
|
},
|
|
47
59
|
fileName: {
|
|
48
|
-
type:
|
|
60
|
+
type: "string",
|
|
49
61
|
description: 'File name including extension (e.g., "report.pdf")',
|
|
50
62
|
},
|
|
51
63
|
},
|
|
52
|
-
required: [
|
|
64
|
+
required: [
|
|
65
|
+
"entitySetName",
|
|
66
|
+
"recordId",
|
|
67
|
+
"columnName",
|
|
68
|
+
"fileContent",
|
|
69
|
+
"fileName",
|
|
70
|
+
],
|
|
53
71
|
},
|
|
54
72
|
},
|
|
55
73
|
{
|
|
56
|
-
name:
|
|
57
|
-
description:
|
|
74
|
+
name: "dataverse_download_file_column",
|
|
75
|
+
description: "Downloads a file from a Dataverse file column. Returns the file content as a base64-encoded string along with the file name and size.",
|
|
58
76
|
inputSchema: {
|
|
59
|
-
type:
|
|
77
|
+
type: "object",
|
|
60
78
|
properties: {
|
|
61
79
|
entitySetName: {
|
|
62
|
-
type:
|
|
80
|
+
type: "string",
|
|
63
81
|
description: 'OData entity set name (e.g., "accounts")',
|
|
64
82
|
},
|
|
65
83
|
recordId: {
|
|
66
|
-
type:
|
|
67
|
-
description:
|
|
84
|
+
type: "string",
|
|
85
|
+
description: "Record GUID",
|
|
68
86
|
},
|
|
69
87
|
columnName: {
|
|
70
|
-
type:
|
|
71
|
-
description:
|
|
88
|
+
type: "string",
|
|
89
|
+
description: "File column logical name",
|
|
72
90
|
},
|
|
73
91
|
},
|
|
74
|
-
required: [
|
|
92
|
+
required: ["entitySetName", "recordId", "columnName"],
|
|
75
93
|
},
|
|
76
94
|
},
|
|
77
95
|
];
|
|
@@ -80,20 +98,20 @@ export async function handleFileTool(name, args, client) {
|
|
|
80
98
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
81
99
|
const http = client.http;
|
|
82
100
|
switch (name) {
|
|
83
|
-
case
|
|
101
|
+
case "dataverse_upload_file_column": {
|
|
84
102
|
const { entitySetName, recordId, columnName, fileContent, fileName } = UploadFileColumnInput.parse(args);
|
|
85
|
-
const buffer = Buffer.from(fileContent,
|
|
103
|
+
const buffer = Buffer.from(fileContent, "base64");
|
|
86
104
|
const url = `${entitySetName}(${recordId})/${columnName}`;
|
|
87
105
|
await http.patch(url, buffer, {
|
|
88
106
|
headers: {
|
|
89
|
-
|
|
90
|
-
|
|
107
|
+
"Content-Type": "application/octet-stream",
|
|
108
|
+
"x-ms-file-name": fileName,
|
|
91
109
|
},
|
|
92
110
|
});
|
|
93
111
|
return {
|
|
94
112
|
content: [
|
|
95
113
|
{
|
|
96
|
-
type:
|
|
114
|
+
type: "text",
|
|
97
115
|
text: JSON.stringify({
|
|
98
116
|
success: true,
|
|
99
117
|
entitySetName,
|
|
@@ -106,23 +124,24 @@ export async function handleFileTool(name, args, client) {
|
|
|
106
124
|
],
|
|
107
125
|
};
|
|
108
126
|
}
|
|
109
|
-
case
|
|
127
|
+
case "dataverse_download_file_column": {
|
|
110
128
|
const { entitySetName, recordId, columnName } = DownloadFileColumnInput.parse(args);
|
|
111
129
|
const url = `${entitySetName}(${recordId})/${columnName}/$value`;
|
|
112
130
|
const response = await http.get(url, {
|
|
113
|
-
responseType:
|
|
131
|
+
responseType: "text",
|
|
114
132
|
});
|
|
115
133
|
const data = response.data;
|
|
116
134
|
// The response may be binary data returned as a string; encode to base64
|
|
117
|
-
const base64 = Buffer.from(data,
|
|
118
|
-
const fileName = response.headers[
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const fileSize = parseInt(response.headers[
|
|
135
|
+
const base64 = Buffer.from(data, "binary").toString("base64");
|
|
136
|
+
const fileName = response.headers["x-ms-file-name"] ??
|
|
137
|
+
response.headers["content-disposition"]?.match(/filename="?([^";\n]+)"?/)?.[1] ??
|
|
138
|
+
"download";
|
|
139
|
+
const fileSize = parseInt(response.headers["content-length"] ?? "0", 10) ||
|
|
140
|
+
base64.length;
|
|
122
141
|
return {
|
|
123
142
|
content: [
|
|
124
143
|
{
|
|
125
|
-
type:
|
|
144
|
+
type: "text",
|
|
126
145
|
text: JSON.stringify({
|
|
127
146
|
entitySetName,
|
|
128
147
|
recordId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.tools.js","sourceRoot":"","sources":["../../src/tools/file.tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAC1C,MAAM,oBAAoB,GAAG,YAAY,CAAC;AAE1C,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,aAAa,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"file.tools.js","sourceRoot":"","sources":["../../src/tools/file.tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { DataverseAdvancedClient } from
|
|
1
|
+
import type { DataverseAdvancedClient } from "../dataverse/dataverse-client-advanced.js";
|
|
2
2
|
type DispatchFn = (toolName: string, args: unknown, client: DataverseAdvancedClient) => Promise<{
|
|
3
3
|
content: Array<{
|
|
4
|
-
type:
|
|
4
|
+
type: "text";
|
|
5
5
|
text: string;
|
|
6
6
|
}>;
|
|
7
7
|
}>;
|
|
@@ -29,7 +29,7 @@ export declare const impersonateTools: {
|
|
|
29
29
|
}[];
|
|
30
30
|
export declare function handleImpersonateTool(name: string, args: unknown, client: DataverseAdvancedClient, dispatch: DispatchFn): Promise<{
|
|
31
31
|
content: Array<{
|
|
32
|
-
type:
|
|
32
|
+
type: "text";
|
|
33
33
|
text: string;
|
|
34
34
|
}>;
|
|
35
35
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impersonate.tools.d.ts","sourceRoot":"","sources":["../../src/tools/impersonate.tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"impersonate.tools.d.ts","sourceRoot":"","sources":["../../src/tools/impersonate.tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AAqBzF,KAAK,UAAU,GAAG,CAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,uBAAuB,KAC5B,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAAC;AAKjE,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;GA0B5B,CAAC;AAEF,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,uBAAuB,EAC/B,QAAQ,EAAE,UAAU,GACnB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CA0D7D"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { z } from
|
|
2
|
-
import { esc } from
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { esc } from "../dataverse/dataverse-client.utils.js";
|
|
3
3
|
const ImpersonateInput = z.object({
|
|
4
4
|
callerId: z
|
|
5
5
|
.string()
|
|
@@ -9,61 +9,63 @@ const ImpersonateInput = z.object({
|
|
|
9
9
|
.string()
|
|
10
10
|
.min(1)
|
|
11
11
|
.describe('Name of the MCP tool to execute on behalf of the user (e.g., "dataverse_create", "dataverse_query")'),
|
|
12
|
-
toolArgs: z
|
|
12
|
+
toolArgs: z
|
|
13
|
+
.record(z.unknown())
|
|
14
|
+
.describe("Arguments for the wrapped tool, as an object"),
|
|
13
15
|
});
|
|
14
16
|
export const impersonateTools = [
|
|
15
17
|
{
|
|
16
|
-
name:
|
|
18
|
+
name: "dataverse_impersonate",
|
|
17
19
|
description: 'Executes another Dataverse tool on behalf of a different system user by injecting the MSCRMCallerId header. Requires the executing account to have the "Act on behalf of another user" privilege in Dataverse. The impersonation applies ONLY to the single tool call specified. Use for auditing workflows that must create or update records under a specific user identity.',
|
|
18
20
|
inputSchema: {
|
|
19
|
-
type:
|
|
21
|
+
type: "object",
|
|
20
22
|
properties: {
|
|
21
23
|
callerId: {
|
|
22
|
-
type:
|
|
23
|
-
description:
|
|
24
|
+
type: "string",
|
|
25
|
+
description: "GUID (Azure AD Object ID) of the Dataverse system user to impersonate",
|
|
24
26
|
},
|
|
25
27
|
toolName: {
|
|
26
|
-
type:
|
|
28
|
+
type: "string",
|
|
27
29
|
description: 'MCP tool to execute while impersonating (e.g., "dataverse_create")',
|
|
28
30
|
},
|
|
29
31
|
toolArgs: {
|
|
30
|
-
type:
|
|
31
|
-
description:
|
|
32
|
+
type: "object",
|
|
33
|
+
description: "Arguments for the wrapped tool",
|
|
32
34
|
},
|
|
33
35
|
},
|
|
34
|
-
required: [
|
|
36
|
+
required: ["callerId", "toolName", "toolArgs"],
|
|
35
37
|
},
|
|
36
38
|
},
|
|
37
39
|
];
|
|
38
40
|
export async function handleImpersonateTool(name, args, client, dispatch) {
|
|
39
|
-
if (name !==
|
|
41
|
+
if (name !== "dataverse_impersonate") {
|
|
40
42
|
throw new Error(`Unknown impersonate tool: ${name}`);
|
|
41
43
|
}
|
|
42
44
|
const { callerId, toolName, toolArgs } = ImpersonateInput.parse(args);
|
|
43
45
|
// Security guard: prevent privilege escalation via System Administrator impersonation.
|
|
44
46
|
// Best-effort check — if it fails for non-security reasons, log and proceed.
|
|
45
47
|
try {
|
|
46
|
-
const roleCheck = await client.query(`systemusers(${esc(callerId)})/systemuserroles_association`, { select: [
|
|
48
|
+
const roleCheck = await client.query(`systemusers(${esc(callerId)})/systemuserroles_association`, { select: ["name"], filter: `name eq 'System Administrator'`, top: 1 });
|
|
47
49
|
if ((roleCheck.value?.length ?? 0) > 0) {
|
|
48
|
-
throw new Error(
|
|
50
|
+
throw new Error("Security policy: impersonation of users with System Administrator role is prohibited to prevent privilege escalation.");
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
catch (err) {
|
|
52
|
-
if (err instanceof Error && err.message.includes(
|
|
54
|
+
if (err instanceof Error && err.message.includes("Security policy"))
|
|
53
55
|
throw err;
|
|
54
56
|
// Fail-closed: any failure verifying roles means we cannot confirm safety — deny impersonation.
|
|
55
57
|
throw new Error(`Security policy: cannot verify callerId roles — impersonation denied. Cause: ${String(err)}`);
|
|
56
58
|
}
|
|
57
59
|
// Access the HttpClient defaultHeaders via type cast — the http property is protected
|
|
58
60
|
const http = client.http;
|
|
59
|
-
const prev = http.defaultHeaders[
|
|
61
|
+
const prev = http.defaultHeaders["MSCRMCallerId"];
|
|
60
62
|
try {
|
|
61
|
-
http.defaultHeaders[
|
|
63
|
+
http.defaultHeaders["MSCRMCallerId"] = callerId;
|
|
62
64
|
const result = await dispatch(toolName, toolArgs, client);
|
|
63
65
|
return {
|
|
64
66
|
content: [
|
|
65
67
|
{
|
|
66
|
-
type:
|
|
68
|
+
type: "text",
|
|
67
69
|
text: JSON.stringify({
|
|
68
70
|
impersonatedAs: callerId,
|
|
69
71
|
tool: toolName,
|
|
@@ -75,10 +77,10 @@ export async function handleImpersonateTool(name, args, client, dispatch) {
|
|
|
75
77
|
}
|
|
76
78
|
finally {
|
|
77
79
|
if (prev === undefined) {
|
|
78
|
-
delete http.defaultHeaders[
|
|
80
|
+
delete http.defaultHeaders["MSCRMCallerId"];
|
|
79
81
|
}
|
|
80
82
|
else {
|
|
81
|
-
http.defaultHeaders[
|
|
83
|
+
http.defaultHeaders["MSCRMCallerId"] = prev;
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
86
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impersonate.tools.js","sourceRoot":"","sources":["../../src/tools/impersonate.tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,GAAG,EAAE,MAAM,wCAAwC,CAAC;AAE7D,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,IAAI,EAAE;SACN,QAAQ,CACP,2KAA2K,CAC5K;IACH,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,
|
|
1
|
+
{"version":3,"file":"impersonate.tools.js","sourceRoot":"","sources":["../../src/tools/impersonate.tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DataverseMetadataClient } from
|
|
1
|
+
import type { DataverseMetadataClient } from "../dataverse/dataverse-client.metadata.js";
|
|
2
2
|
export declare const metadataTools: ({
|
|
3
3
|
name: string;
|
|
4
4
|
description: string;
|
|
@@ -149,7 +149,7 @@ export declare const metadataTools: ({
|
|
|
149
149
|
})[];
|
|
150
150
|
export declare function handleMetadataTool(name: string, args: unknown, client: DataverseMetadataClient): Promise<{
|
|
151
151
|
content: Array<{
|
|
152
|
-
type:
|
|
152
|
+
type: "text";
|
|
153
153
|
text: string;
|
|
154
154
|
}>;
|
|
155
155
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.tools.d.ts","sourceRoot":"","sources":["../../src/tools/metadata.tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AAEzF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"metadata.tools.d.ts","sourceRoot":"","sources":["../../src/tools/metadata.tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AAEzF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAqHzB,CAAC;AA8CF,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAqH7D"}
|