@toolplex/client 0.1.47 → 0.2.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/dist/mcp-server/index.js +1 -1
- package/dist/mcp-server/policy/policyEnforcer.d.ts +1 -7
- package/dist/mcp-server/policy/policyEnforcer.js +0 -13
- package/dist/mcp-server/toolplexApi/service.d.ts +1 -2
- package/dist/mcp-server/toolplexApi/service.js +0 -23
- package/dist/mcp-server/toolplexApi/types.d.ts +0 -28
- package/dist/mcp-server/toolplexServer.js +1 -22
- package/dist/server-manager/stdioServer.js +0 -9
- package/dist/shared/mcpServerTypes.d.ts +0 -62
- package/dist/shared/mcpServerTypes.js +0 -27
- package/dist/src/mcp-server/policy/policyEnforcer.js +0 -13
- package/dist/src/mcp-server/toolplexApi/service.js +0 -23
- package/dist/src/shared/mcpServerTypes.js +0 -27
- package/package.json +1 -1
- package/dist/mcp-server/policy/feedbackPolicy.d.ts +0 -27
- package/dist/mcp-server/policy/feedbackPolicy.js +0 -39
- package/dist/mcp-server/toolHandlers/getServerConfigHandler.d.ts +0 -3
- package/dist/mcp-server/toolHandlers/getServerConfigHandler.js +0 -73
- package/dist/mcp-server/toolHandlers/submitFeedbackHandler.d.ts +0 -3
- package/dist/mcp-server/toolHandlers/submitFeedbackHandler.js +0 -71
- package/dist/src/mcp-server/policy/feedbackPolicy.js +0 -39
package/dist/mcp-server/index.js
CHANGED
|
@@ -27,7 +27,7 @@ const bundledDependencies = {
|
|
|
27
27
|
git: process.env.TOOLPLEX_GIT_PATH,
|
|
28
28
|
};
|
|
29
29
|
// Parse session resume history for restored chat sessions
|
|
30
|
-
// This allows the enforcement layer to validate save_playbook
|
|
30
|
+
// This allows the enforcement layer to validate save_playbook
|
|
31
31
|
// based on historical tool usage from the database
|
|
32
32
|
let sessionResumeHistory;
|
|
33
33
|
if (process.env.TOOLPLEX_SESSION_RESUME_HISTORY) {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { ClientContext } from "../clientContext.js";
|
|
2
2
|
import CallToolObserver from "./callToolObserver.js";
|
|
3
3
|
import InstallObserver from "./installObserver.js";
|
|
4
|
-
import { SavePlaybookParams
|
|
4
|
+
import { SavePlaybookParams } from "../../shared/mcpServerTypes.js";
|
|
5
5
|
export declare class PolicyEnforcer {
|
|
6
6
|
private playbookPolicy;
|
|
7
|
-
private feedbackPolicy;
|
|
8
7
|
private serverPolicy;
|
|
9
8
|
private callToolObserver;
|
|
10
9
|
private installObserver;
|
|
@@ -18,11 +17,6 @@ export declare class PolicyEnforcer {
|
|
|
18
17
|
* Throws if the playbook does not pass policy.
|
|
19
18
|
*/
|
|
20
19
|
enforceSavePlaybookPolicy(playbook: SavePlaybookParams): void;
|
|
21
|
-
/**
|
|
22
|
-
* Enforce feedback policy validation.
|
|
23
|
-
* Throws if the feedback does not pass policy.
|
|
24
|
-
*/
|
|
25
|
-
enforceFeedbackPolicy(feedback: SubmitFeedbackParams): void;
|
|
26
20
|
/**
|
|
27
21
|
* Enforce server call tool policy validation.
|
|
28
22
|
* Throws if attempting to call a tool on a blocked server.
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { PlaybookPolicy } from "./playbookPolicy.js";
|
|
2
|
-
import { FeedbackPolicy } from "./feedbackPolicy.js";
|
|
3
2
|
import CallToolObserver from "./callToolObserver.js";
|
|
4
3
|
import InstallObserver from "./installObserver.js";
|
|
5
4
|
import { ServerPolicy } from "./serverPolicy.js";
|
|
6
5
|
export class PolicyEnforcer {
|
|
7
6
|
constructor() {
|
|
8
7
|
this.playbookPolicy = null;
|
|
9
|
-
this.feedbackPolicy = null;
|
|
10
8
|
this.serverPolicy = null;
|
|
11
9
|
this.callToolObserver = null;
|
|
12
10
|
this.installObserver = null;
|
|
@@ -18,7 +16,6 @@ export class PolicyEnforcer {
|
|
|
18
16
|
this.callToolObserver = new CallToolObserver();
|
|
19
17
|
this.installObserver = new InstallObserver();
|
|
20
18
|
this.playbookPolicy = new PlaybookPolicy(clientContext, this.callToolObserver);
|
|
21
|
-
this.feedbackPolicy = new FeedbackPolicy(clientContext, this.callToolObserver, this.installObserver);
|
|
22
19
|
this.serverPolicy = new ServerPolicy(clientContext);
|
|
23
20
|
}
|
|
24
21
|
/**
|
|
@@ -31,16 +28,6 @@ export class PolicyEnforcer {
|
|
|
31
28
|
}
|
|
32
29
|
this.playbookPolicy.enforceSavePlaybookPolicy(playbook);
|
|
33
30
|
}
|
|
34
|
-
/**
|
|
35
|
-
* Enforce feedback policy validation.
|
|
36
|
-
* Throws if the feedback does not pass policy.
|
|
37
|
-
*/
|
|
38
|
-
enforceFeedbackPolicy(feedback) {
|
|
39
|
-
if (!this.feedbackPolicy) {
|
|
40
|
-
throw new Error("PolicyEnforcer not initialized");
|
|
41
|
-
}
|
|
42
|
-
this.feedbackPolicy.enforceFeedbackPolicy(feedback);
|
|
43
|
-
}
|
|
44
31
|
/**
|
|
45
32
|
* Enforce server call tool policy validation.
|
|
46
33
|
* Throws if attempting to call a tool on a blocked server.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CreatePlaybookResponse, LogPlaybookUsageResponse,
|
|
1
|
+
import { CreatePlaybookResponse, LogPlaybookUsageResponse, FeedbackSummaryResponse, LogTelemetryRequest, LogTelemetryBatchResponse, InitResponse, SearchResponse, NotificationRecipient } from "./types.js";
|
|
2
2
|
import { ClientContext } from "../clientContext.js";
|
|
3
3
|
import { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
4
4
|
import { PlaybookAction } from "../../shared/mcpServerTypes.js";
|
|
@@ -24,7 +24,6 @@ export declare class ToolplexApiService {
|
|
|
24
24
|
search(query: string, expandedKeywords?: string[], filter?: string, size?: number, scope?: string): Promise<SearchResponse>;
|
|
25
25
|
createPlaybook(playbook_name: string, description: string, actions: Array<PlaybookAction>, domain?: string, keywords?: string[], requirements?: string[], privacy?: "public" | "private" | "organization", sourcePlaybookId?: string, forkReason?: string): Promise<CreatePlaybookResponse>;
|
|
26
26
|
logPlaybookUsage(playbookId: string, success: boolean, errorMessage?: string): Promise<LogPlaybookUsageResponse>;
|
|
27
|
-
submitFeedback(targetType: "server" | "playbook", targetId: string, vote: "up" | "down", message?: string, securityAssessment?: SecurityAssessment): Promise<SubmitFeedbackResponse>;
|
|
28
27
|
getFeedbackSummary(): Promise<FeedbackSummaryResponse>;
|
|
29
28
|
/**
|
|
30
29
|
* Create an automation notification (HITL)
|
|
@@ -191,29 +191,6 @@ export class ToolplexApiService {
|
|
|
191
191
|
throw err;
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
|
-
async submitFeedback(targetType, targetId, vote, message, securityAssessment) {
|
|
195
|
-
const requestBody = {
|
|
196
|
-
target_type: targetType,
|
|
197
|
-
target_id: targetId,
|
|
198
|
-
vote,
|
|
199
|
-
message,
|
|
200
|
-
llm_context: this.clientContext.llmContext,
|
|
201
|
-
machine_context: this.machineContext,
|
|
202
|
-
security_assessment: securityAssessment,
|
|
203
|
-
};
|
|
204
|
-
try {
|
|
205
|
-
const response = await fetch(`${this.baseUrl}/feedback/submit`, {
|
|
206
|
-
method: "POST",
|
|
207
|
-
headers: this.getHeadersWithSession(),
|
|
208
|
-
body: JSON.stringify(requestBody),
|
|
209
|
-
});
|
|
210
|
-
return this.handleFetchResponse(response);
|
|
211
|
-
}
|
|
212
|
-
catch (err) {
|
|
213
|
-
await logger.error(`Error submitting feedback: ${err}`);
|
|
214
|
-
throw err;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
194
|
async getFeedbackSummary() {
|
|
218
195
|
try {
|
|
219
196
|
const response = await fetch(`${this.baseUrl}/feedback/summarize`, {
|
|
@@ -48,16 +48,6 @@ export interface InitResponse {
|
|
|
48
48
|
announcement?: string;
|
|
49
49
|
flags: ClientFlags;
|
|
50
50
|
}
|
|
51
|
-
export type SecurityFlag = string;
|
|
52
|
-
export type RiskLevel = string;
|
|
53
|
-
export interface CustomSecurityFlag {
|
|
54
|
-
custom_flag: string;
|
|
55
|
-
}
|
|
56
|
-
export interface SecurityAssessment {
|
|
57
|
-
security_flags: Array<SecurityFlag | CustomSecurityFlag>;
|
|
58
|
-
risk_assessment: RiskLevel;
|
|
59
|
-
context_note?: string;
|
|
60
|
-
}
|
|
61
51
|
export interface LlmContext {
|
|
62
52
|
model_family: string;
|
|
63
53
|
model_name: string;
|
|
@@ -92,24 +82,6 @@ export interface LogPlaybookUsageRequest {
|
|
|
92
82
|
export interface LogPlaybookUsageResponse {
|
|
93
83
|
success: boolean;
|
|
94
84
|
}
|
|
95
|
-
export interface SubmitFeedbackRequest {
|
|
96
|
-
target_type: "server" | "playbook";
|
|
97
|
-
target_id: string;
|
|
98
|
-
vote: "up" | "down";
|
|
99
|
-
message?: string;
|
|
100
|
-
llm_context: LlmContext;
|
|
101
|
-
machine_context: {
|
|
102
|
-
os: string;
|
|
103
|
-
arch: string;
|
|
104
|
-
memory_gb: number;
|
|
105
|
-
cpu_cores: string;
|
|
106
|
-
};
|
|
107
|
-
security_assessment?: SecurityAssessment;
|
|
108
|
-
}
|
|
109
|
-
export interface SubmitFeedbackResponse {
|
|
110
|
-
id: string;
|
|
111
|
-
success: boolean;
|
|
112
|
-
}
|
|
113
85
|
export interface FeedbackSummaryResponse {
|
|
114
86
|
servers: Array<{
|
|
115
87
|
server_id: string;
|
|
@@ -18,12 +18,10 @@ import { handleUninstallServer } from "./toolHandlers/uninstallServerHandler.js"
|
|
|
18
18
|
import { handleSavePlaybook } from "./toolHandlers/savePlaybookHandler.js";
|
|
19
19
|
import { handleLogPlaybookUsage } from "./toolHandlers/logPlaybookUsageHandler.js";
|
|
20
20
|
import { handleLookupEntityTool } from "./toolHandlers/lookupEntityHandler.js";
|
|
21
|
-
import { handleSubmitFeedback } from "./toolHandlers/submitFeedbackHandler.js";
|
|
22
|
-
import { handleGetServerConfig } from "./toolHandlers/getServerConfigHandler.js";
|
|
23
21
|
import { handleNotify } from "./toolHandlers/notifyHandler.js";
|
|
24
22
|
import { StdioServerManagerClient } from "../shared/stdioServerManagerClient.js";
|
|
25
23
|
import { FileLogger } from "../shared/fileLogger.js";
|
|
26
|
-
import { CallToolParamsSchema, InitializeToolplexParamsSchema, InstallParamsSchema, ListToolsParamsSchema, SearchParamsSchema, UninstallParamsSchema, SavePlaybookParamsSchema, LogPlaybookUsageParamsSchema, LookupEntityParamsSchema,
|
|
24
|
+
import { CallToolParamsSchema, InitializeToolplexParamsSchema, InstallParamsSchema, ListToolsParamsSchema, SearchParamsSchema, UninstallParamsSchema, SavePlaybookParamsSchema, LogPlaybookUsageParamsSchema, LookupEntityParamsSchema, NotifyParamsSchema, } from "../shared/mcpServerTypes.js";
|
|
27
25
|
import { version as clientVersion } from "../version.js";
|
|
28
26
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
29
27
|
const logger = FileLogger;
|
|
@@ -223,25 +221,6 @@ export async function serve(config) {
|
|
|
223
221
|
result = await handleLookupEntityTool(parsed.data);
|
|
224
222
|
break;
|
|
225
223
|
}
|
|
226
|
-
case "submit_feedback": {
|
|
227
|
-
await logger.debug("Handling submit_feedback request");
|
|
228
|
-
const parsed = SubmitFeedbackParamsSchema.safeParse(params);
|
|
229
|
-
if (!parsed.success)
|
|
230
|
-
throw new Error(`Invalid submit_feedback params: ${parsed.error}`);
|
|
231
|
-
if (!clientContext.isInitialized())
|
|
232
|
-
throw new Error(`ToolPlex is not initialized`);
|
|
233
|
-
result = await handleSubmitFeedback(parsed.data);
|
|
234
|
-
break;
|
|
235
|
-
}
|
|
236
|
-
// Add get_server_config tool handler
|
|
237
|
-
case "get_server_config": {
|
|
238
|
-
await logger.debug("Handling get_server_config request");
|
|
239
|
-
const parsed = GetServerConfigParamsSchema.safeParse(params);
|
|
240
|
-
if (!parsed.success)
|
|
241
|
-
throw new Error(`Invalid get_server_config params: ${parsed.error}`);
|
|
242
|
-
result = await handleGetServerConfig(parsed.data);
|
|
243
|
-
break;
|
|
244
|
-
}
|
|
245
224
|
// Notify tool handler (automation mode only)
|
|
246
225
|
case "notify": {
|
|
247
226
|
await logger.debug("Handling notify request");
|
|
@@ -103,15 +103,6 @@ export class ServerManagerProtocol {
|
|
|
103
103
|
const server_name = await this.serverManager.getServerName(list_tools_params.server_id);
|
|
104
104
|
return { server_id: list_tools_params.server_id, server_name, tools };
|
|
105
105
|
}
|
|
106
|
-
case "get_server_config": {
|
|
107
|
-
if (!params || typeof params.server_id !== "string") {
|
|
108
|
-
throw new Error("Missing or invalid server_id");
|
|
109
|
-
}
|
|
110
|
-
await logger.debug(`Getting config for server ${params.server_id}`);
|
|
111
|
-
// Just return the config directly
|
|
112
|
-
const config = await this.serverManager.getServerConfig(params.server_id);
|
|
113
|
-
return config;
|
|
114
|
-
}
|
|
115
106
|
case "call_tool": {
|
|
116
107
|
const call_tool_params = CallToolParamsSchema.parse(params);
|
|
117
108
|
await logger.debug(`Calling tool ${call_tool_params.tool_name} on server ${call_tool_params.server_id}`);
|
|
@@ -234,14 +234,6 @@ export declare const ListToolsParamsSchema: z.ZodObject<{
|
|
|
234
234
|
server_id?: string | undefined;
|
|
235
235
|
}>;
|
|
236
236
|
export type ListToolplexToolsParams = z.infer<typeof ListToolsParamsSchema>;
|
|
237
|
-
export declare const GetServerConfigParamsSchema: z.ZodObject<{
|
|
238
|
-
server_id: z.ZodOptional<z.ZodString>;
|
|
239
|
-
}, "strip", z.ZodTypeAny, {
|
|
240
|
-
server_id?: string | undefined;
|
|
241
|
-
}, {
|
|
242
|
-
server_id?: string | undefined;
|
|
243
|
-
}>;
|
|
244
|
-
export type GetServerConfigParams = z.infer<typeof GetServerConfigParamsSchema>;
|
|
245
237
|
export declare const CallToolParamsSchema: z.ZodObject<{
|
|
246
238
|
server_id: z.ZodString;
|
|
247
239
|
tool_name: z.ZodString;
|
|
@@ -397,60 +389,6 @@ export declare const LogPlaybookUsageParamsSchema: z.ZodObject<{
|
|
|
397
389
|
error_message?: string | undefined;
|
|
398
390
|
}>;
|
|
399
391
|
export type LogPlaybookUsageParams = z.infer<typeof LogPlaybookUsageParamsSchema>;
|
|
400
|
-
export declare const SubmitFeedbackParamsSchema: z.ZodObject<{
|
|
401
|
-
target_type: z.ZodEnum<["server", "playbook"]>;
|
|
402
|
-
target_id: z.ZodString;
|
|
403
|
-
vote: z.ZodEnum<["up", "down"]>;
|
|
404
|
-
message: z.ZodOptional<z.ZodString>;
|
|
405
|
-
security_assessment: z.ZodOptional<z.ZodObject<{
|
|
406
|
-
security_flags: z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodObject<{
|
|
407
|
-
custom_flag: z.ZodString;
|
|
408
|
-
}, "strip", z.ZodTypeAny, {
|
|
409
|
-
custom_flag: string;
|
|
410
|
-
}, {
|
|
411
|
-
custom_flag: string;
|
|
412
|
-
}>]>, "many">;
|
|
413
|
-
risk_assessment: z.ZodString;
|
|
414
|
-
context_note: z.ZodOptional<z.ZodString>;
|
|
415
|
-
}, "strip", z.ZodTypeAny, {
|
|
416
|
-
security_flags: (string | {
|
|
417
|
-
custom_flag: string;
|
|
418
|
-
})[];
|
|
419
|
-
risk_assessment: string;
|
|
420
|
-
context_note?: string | undefined;
|
|
421
|
-
}, {
|
|
422
|
-
security_flags: (string | {
|
|
423
|
-
custom_flag: string;
|
|
424
|
-
})[];
|
|
425
|
-
risk_assessment: string;
|
|
426
|
-
context_note?: string | undefined;
|
|
427
|
-
}>>;
|
|
428
|
-
}, "strip", z.ZodTypeAny, {
|
|
429
|
-
target_type: "server" | "playbook";
|
|
430
|
-
target_id: string;
|
|
431
|
-
vote: "up" | "down";
|
|
432
|
-
message?: string | undefined;
|
|
433
|
-
security_assessment?: {
|
|
434
|
-
security_flags: (string | {
|
|
435
|
-
custom_flag: string;
|
|
436
|
-
})[];
|
|
437
|
-
risk_assessment: string;
|
|
438
|
-
context_note?: string | undefined;
|
|
439
|
-
} | undefined;
|
|
440
|
-
}, {
|
|
441
|
-
target_type: "server" | "playbook";
|
|
442
|
-
target_id: string;
|
|
443
|
-
vote: "up" | "down";
|
|
444
|
-
message?: string | undefined;
|
|
445
|
-
security_assessment?: {
|
|
446
|
-
security_flags: (string | {
|
|
447
|
-
custom_flag: string;
|
|
448
|
-
})[];
|
|
449
|
-
risk_assessment: string;
|
|
450
|
-
context_note?: string | undefined;
|
|
451
|
-
} | undefined;
|
|
452
|
-
}>;
|
|
453
|
-
export type SubmitFeedbackParams = z.infer<typeof SubmitFeedbackParamsSchema>;
|
|
454
392
|
export declare const NotifyParamsSchema: z.ZodObject<{
|
|
455
393
|
title: z.ZodString;
|
|
456
394
|
content: z.ZodString;
|
|
@@ -70,12 +70,6 @@ export const ListToolsParamsSchema = z.object({
|
|
|
70
70
|
server_id: z.string().optional(),
|
|
71
71
|
});
|
|
72
72
|
// --------------------
|
|
73
|
-
// GetServerConfigParams
|
|
74
|
-
// --------------------
|
|
75
|
-
export const GetServerConfigParamsSchema = z.object({
|
|
76
|
-
server_id: z.string().optional(),
|
|
77
|
-
});
|
|
78
|
-
// --------------------
|
|
79
73
|
// CallToolParams
|
|
80
74
|
// --------------------
|
|
81
75
|
export const CallToolParamsSchema = z.object({
|
|
@@ -141,27 +135,6 @@ export const LogPlaybookUsageParamsSchema = z.object({
|
|
|
141
135
|
error_message: z.string().optional(),
|
|
142
136
|
});
|
|
143
137
|
// --------------------
|
|
144
|
-
// SubmitFeedbackParams
|
|
145
|
-
// --------------------
|
|
146
|
-
export const SubmitFeedbackParamsSchema = z.object({
|
|
147
|
-
target_type: z.enum(["server", "playbook"]),
|
|
148
|
-
target_id: z.string(),
|
|
149
|
-
vote: z.enum(["up", "down"]),
|
|
150
|
-
message: z.string().optional(),
|
|
151
|
-
security_assessment: z
|
|
152
|
-
.object({
|
|
153
|
-
security_flags: z.array(z.union([
|
|
154
|
-
z.string(),
|
|
155
|
-
z.object({
|
|
156
|
-
custom_flag: z.string(),
|
|
157
|
-
}),
|
|
158
|
-
])),
|
|
159
|
-
risk_assessment: z.string(),
|
|
160
|
-
context_note: z.string().optional(),
|
|
161
|
-
})
|
|
162
|
-
.optional(),
|
|
163
|
-
});
|
|
164
|
-
// --------------------
|
|
165
138
|
// NotifyParams (for automation HITL notifications)
|
|
166
139
|
// --------------------
|
|
167
140
|
export const NotifyParamsSchema = z.object({
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { PlaybookPolicy } from "./playbookPolicy.js";
|
|
2
|
-
import { FeedbackPolicy } from "./feedbackPolicy.js";
|
|
3
2
|
import CallToolObserver from "./callToolObserver.js";
|
|
4
3
|
import InstallObserver from "./installObserver.js";
|
|
5
4
|
import { ServerPolicy } from "./serverPolicy.js";
|
|
6
5
|
export class PolicyEnforcer {
|
|
7
6
|
constructor() {
|
|
8
7
|
this.playbookPolicy = null;
|
|
9
|
-
this.feedbackPolicy = null;
|
|
10
8
|
this.serverPolicy = null;
|
|
11
9
|
this.callToolObserver = null;
|
|
12
10
|
this.installObserver = null;
|
|
@@ -18,7 +16,6 @@ export class PolicyEnforcer {
|
|
|
18
16
|
this.callToolObserver = new CallToolObserver();
|
|
19
17
|
this.installObserver = new InstallObserver();
|
|
20
18
|
this.playbookPolicy = new PlaybookPolicy(clientContext, this.callToolObserver);
|
|
21
|
-
this.feedbackPolicy = new FeedbackPolicy(clientContext, this.callToolObserver, this.installObserver);
|
|
22
19
|
this.serverPolicy = new ServerPolicy(clientContext);
|
|
23
20
|
}
|
|
24
21
|
/**
|
|
@@ -31,16 +28,6 @@ export class PolicyEnforcer {
|
|
|
31
28
|
}
|
|
32
29
|
this.playbookPolicy.enforceSavePlaybookPolicy(playbook);
|
|
33
30
|
}
|
|
34
|
-
/**
|
|
35
|
-
* Enforce feedback policy validation.
|
|
36
|
-
* Throws if the feedback does not pass policy.
|
|
37
|
-
*/
|
|
38
|
-
enforceFeedbackPolicy(feedback) {
|
|
39
|
-
if (!this.feedbackPolicy) {
|
|
40
|
-
throw new Error("PolicyEnforcer not initialized");
|
|
41
|
-
}
|
|
42
|
-
this.feedbackPolicy.enforceFeedbackPolicy(feedback);
|
|
43
|
-
}
|
|
44
31
|
/**
|
|
45
32
|
* Enforce server call tool policy validation.
|
|
46
33
|
* Throws if attempting to call a tool on a blocked server.
|
|
@@ -191,29 +191,6 @@ export class ToolplexApiService {
|
|
|
191
191
|
throw err;
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
|
-
async submitFeedback(targetType, targetId, vote, message, securityAssessment) {
|
|
195
|
-
const requestBody = {
|
|
196
|
-
target_type: targetType,
|
|
197
|
-
target_id: targetId,
|
|
198
|
-
vote,
|
|
199
|
-
message,
|
|
200
|
-
llm_context: this.clientContext.llmContext,
|
|
201
|
-
machine_context: this.machineContext,
|
|
202
|
-
security_assessment: securityAssessment,
|
|
203
|
-
};
|
|
204
|
-
try {
|
|
205
|
-
const response = await fetch(`${this.baseUrl}/feedback/submit`, {
|
|
206
|
-
method: "POST",
|
|
207
|
-
headers: this.getHeadersWithSession(),
|
|
208
|
-
body: JSON.stringify(requestBody),
|
|
209
|
-
});
|
|
210
|
-
return this.handleFetchResponse(response);
|
|
211
|
-
}
|
|
212
|
-
catch (err) {
|
|
213
|
-
await logger.error(`Error submitting feedback: ${err}`);
|
|
214
|
-
throw err;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
194
|
async getFeedbackSummary() {
|
|
218
195
|
try {
|
|
219
196
|
const response = await fetch(`${this.baseUrl}/feedback/summarize`, {
|
|
@@ -70,12 +70,6 @@ export const ListToolsParamsSchema = z.object({
|
|
|
70
70
|
server_id: z.string().optional(),
|
|
71
71
|
});
|
|
72
72
|
// --------------------
|
|
73
|
-
// GetServerConfigParams
|
|
74
|
-
// --------------------
|
|
75
|
-
export const GetServerConfigParamsSchema = z.object({
|
|
76
|
-
server_id: z.string().optional(),
|
|
77
|
-
});
|
|
78
|
-
// --------------------
|
|
79
73
|
// CallToolParams
|
|
80
74
|
// --------------------
|
|
81
75
|
export const CallToolParamsSchema = z.object({
|
|
@@ -141,27 +135,6 @@ export const LogPlaybookUsageParamsSchema = z.object({
|
|
|
141
135
|
error_message: z.string().optional(),
|
|
142
136
|
});
|
|
143
137
|
// --------------------
|
|
144
|
-
// SubmitFeedbackParams
|
|
145
|
-
// --------------------
|
|
146
|
-
export const SubmitFeedbackParamsSchema = z.object({
|
|
147
|
-
target_type: z.enum(["server", "playbook"]),
|
|
148
|
-
target_id: z.string(),
|
|
149
|
-
vote: z.enum(["up", "down"]),
|
|
150
|
-
message: z.string().optional(),
|
|
151
|
-
security_assessment: z
|
|
152
|
-
.object({
|
|
153
|
-
security_flags: z.array(z.union([
|
|
154
|
-
z.string(),
|
|
155
|
-
z.object({
|
|
156
|
-
custom_flag: z.string(),
|
|
157
|
-
}),
|
|
158
|
-
])),
|
|
159
|
-
risk_assessment: z.string(),
|
|
160
|
-
context_note: z.string().optional(),
|
|
161
|
-
})
|
|
162
|
-
.optional(),
|
|
163
|
-
});
|
|
164
|
-
// --------------------
|
|
165
138
|
// NotifyParams (for automation HITL notifications)
|
|
166
139
|
// --------------------
|
|
167
140
|
export const NotifyParamsSchema = z.object({
|
package/package.json
CHANGED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import CallToolObserver from "./callToolObserver.js";
|
|
2
|
-
import InstallObserver from "./installObserver.js";
|
|
3
|
-
import { ClientContext } from "../clientContext.js";
|
|
4
|
-
import { SubmitFeedbackParams } from "../../shared/mcpServerTypes.js";
|
|
5
|
-
export declare class FeedbackPolicy {
|
|
6
|
-
private callToolObserver;
|
|
7
|
-
private installObserver;
|
|
8
|
-
private clientContext;
|
|
9
|
-
private blockedMcpServersSet;
|
|
10
|
-
constructor(clientContext: ClientContext, callToolObserver: CallToolObserver, installObserver: InstallObserver);
|
|
11
|
-
/**
|
|
12
|
-
* Validates feedback by checking that:
|
|
13
|
-
* - The referenced server has been used or had an install/uninstall action
|
|
14
|
-
* - The server is not in the blocked servers list
|
|
15
|
-
*
|
|
16
|
-
* For server feedback, verifies that:
|
|
17
|
-
* - The referenced server has been connected to and used or had an install/uninstall action
|
|
18
|
-
* - The server is not blocked
|
|
19
|
-
*
|
|
20
|
-
* For playbook feedback, no validation is currently performed
|
|
21
|
-
* since playbooks can reference other playbooks.
|
|
22
|
-
*
|
|
23
|
-
* @throws Error if feedback references a server that hasn't been used or had an install/uninstall action
|
|
24
|
-
* in the current session or if the server is blocked
|
|
25
|
-
*/
|
|
26
|
-
enforceFeedbackPolicy(feedback: SubmitFeedbackParams): void;
|
|
27
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
export class FeedbackPolicy {
|
|
2
|
-
constructor(clientContext, callToolObserver, installObserver) {
|
|
3
|
-
this.callToolObserver = callToolObserver;
|
|
4
|
-
this.installObserver = installObserver;
|
|
5
|
-
this.clientContext = clientContext;
|
|
6
|
-
this.blockedMcpServersSet = new Set(clientContext.flags.blocked_mcp_servers || []);
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Validates feedback by checking that:
|
|
10
|
-
* - The referenced server has been used or had an install/uninstall action
|
|
11
|
-
* - The server is not in the blocked servers list
|
|
12
|
-
*
|
|
13
|
-
* For server feedback, verifies that:
|
|
14
|
-
* - The referenced server has been connected to and used or had an install/uninstall action
|
|
15
|
-
* - The server is not blocked
|
|
16
|
-
*
|
|
17
|
-
* For playbook feedback, no validation is currently performed
|
|
18
|
-
* since playbooks can reference other playbooks.
|
|
19
|
-
*
|
|
20
|
-
* @throws Error if feedback references a server that hasn't been used or had an install/uninstall action
|
|
21
|
-
* in the current session or if the server is blocked
|
|
22
|
-
*/
|
|
23
|
-
enforceFeedbackPolicy(feedback) {
|
|
24
|
-
const { target_type, target_id } = feedback;
|
|
25
|
-
if (target_type === "server") {
|
|
26
|
-
// Check if server is blocked
|
|
27
|
-
if (this.blockedMcpServersSet.has(target_id)) {
|
|
28
|
-
throw new Error(`Cannot submit feedback for blocked server "${target_id}"`);
|
|
29
|
-
}
|
|
30
|
-
// For server feedback, verify the server was actually used or had an install/uninstall action
|
|
31
|
-
if (!this.callToolObserver.wasServerCalled(target_id) &&
|
|
32
|
-
!this.installObserver.wasServerInstalled(target_id) &&
|
|
33
|
-
!this.installObserver.wasServerUninstalled(target_id)) {
|
|
34
|
-
throw new Error(`Cannot submit feedback for server "${target_id}" which has not been used or had an install/uninstall action in this session.`);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
// For playbook feedback, we don't validate usage since playbooks can reference other playbooks
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { FileLogger } from "../../shared/fileLogger.js";
|
|
2
|
-
import { findServerManagerClient } from "./serverManagerUtils.js";
|
|
3
|
-
import { sanitizeServerIdForLogging, validateServerIdOrThrow, } from "../utils/serverIdValidator.js";
|
|
4
|
-
import Registry from "../registry.js";
|
|
5
|
-
const logger = FileLogger;
|
|
6
|
-
export async function handleGetServerConfig(params) {
|
|
7
|
-
const startTime = Date.now();
|
|
8
|
-
const serverManagerClients = Registry.getServerManagerClients();
|
|
9
|
-
const telemetryLogger = Registry.getTelemetryLogger();
|
|
10
|
-
const promptsCache = Registry.getPromptsCache();
|
|
11
|
-
const policyEnforcer = Registry.getPolicyEnforcer();
|
|
12
|
-
try {
|
|
13
|
-
const server_id = params.server_id;
|
|
14
|
-
if (!server_id) {
|
|
15
|
-
throw new Error("Missing server_id");
|
|
16
|
-
}
|
|
17
|
-
// Validate server ID format
|
|
18
|
-
validateServerIdOrThrow(server_id);
|
|
19
|
-
// Check if server is blocked using policy enforcer
|
|
20
|
-
policyEnforcer.enforceUseServerPolicy(server_id);
|
|
21
|
-
await logger.debug(`Getting config for server: ${server_id}`);
|
|
22
|
-
const client = await findServerManagerClient(server_id, serverManagerClients);
|
|
23
|
-
const response_data = await client.sendRequest("get_server_config", {
|
|
24
|
-
server_id,
|
|
25
|
-
});
|
|
26
|
-
if ("error" in response_data) {
|
|
27
|
-
throw new Error(`Failed to get config for server_id ${server_id}, error message: ${response_data.error.message}`);
|
|
28
|
-
}
|
|
29
|
-
// The config is returned directly as an object
|
|
30
|
-
const config = response_data;
|
|
31
|
-
await logger.debug("Successfully retrieved server config");
|
|
32
|
-
await telemetryLogger.log("client_get_server_config", {
|
|
33
|
-
success: true,
|
|
34
|
-
log_context: {
|
|
35
|
-
server_id: sanitizeServerIdForLogging(server_id),
|
|
36
|
-
},
|
|
37
|
-
latency_ms: Date.now() - startTime,
|
|
38
|
-
});
|
|
39
|
-
return {
|
|
40
|
-
content: [
|
|
41
|
-
{
|
|
42
|
-
type: "text",
|
|
43
|
-
text: JSON.stringify(config, null, 2),
|
|
44
|
-
},
|
|
45
|
-
],
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
catch (error) {
|
|
49
|
-
const errorMessage = error instanceof Error
|
|
50
|
-
? error.message
|
|
51
|
-
: promptsCache.getPrompt("unexpected_error");
|
|
52
|
-
await logger.error(`Failed to get server config: ${errorMessage}`);
|
|
53
|
-
await telemetryLogger.log("client_get_server_config", {
|
|
54
|
-
success: false,
|
|
55
|
-
log_context: {
|
|
56
|
-
server_id: sanitizeServerIdForLogging(params.server_id || ""),
|
|
57
|
-
},
|
|
58
|
-
pii_sanitized_error_message: errorMessage,
|
|
59
|
-
latency_ms: Date.now() - startTime,
|
|
60
|
-
});
|
|
61
|
-
return {
|
|
62
|
-
isError: true,
|
|
63
|
-
content: [
|
|
64
|
-
{
|
|
65
|
-
type: "text",
|
|
66
|
-
text: promptsCache
|
|
67
|
-
.getPrompt("get_server_config_failure")
|
|
68
|
-
.replace("{ERROR}", errorMessage),
|
|
69
|
-
},
|
|
70
|
-
],
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { FileLogger } from "../../shared/fileLogger.js";
|
|
2
|
-
import Registry from "../registry.js";
|
|
3
|
-
const logger = FileLogger;
|
|
4
|
-
export async function handleSubmitFeedback(params) {
|
|
5
|
-
const startTime = Date.now();
|
|
6
|
-
await logger.info("Handling submit feedback request");
|
|
7
|
-
await logger.debug(`Feedback params: ${JSON.stringify(params)}`);
|
|
8
|
-
const { target_type, target_id, vote, message, security_assessment } = params;
|
|
9
|
-
const apiService = Registry.getToolplexApiService();
|
|
10
|
-
const telemetryLogger = Registry.getTelemetryLogger();
|
|
11
|
-
const promptsCache = Registry.getPromptsCache();
|
|
12
|
-
const policyEnforcer = Registry.getPolicyEnforcer();
|
|
13
|
-
const clientContext = Registry.getClientContext();
|
|
14
|
-
try {
|
|
15
|
-
// Check if the client is in restricted mode
|
|
16
|
-
if (clientContext.clientMode === "restricted") {
|
|
17
|
-
throw new Error("Feedback functionality is disabled in restricted mode.");
|
|
18
|
-
}
|
|
19
|
-
// Check if read-only mode is enabled
|
|
20
|
-
if (clientContext.permissions.enable_read_only_mode) {
|
|
21
|
-
throw new Error("Saving playbooks is disabled in read-only mode");
|
|
22
|
-
}
|
|
23
|
-
// Enforce feedback policy before submitting
|
|
24
|
-
policyEnforcer.enforceFeedbackPolicy(params);
|
|
25
|
-
const response = await apiService.submitFeedback(target_type, target_id, vote, message, security_assessment);
|
|
26
|
-
await logger.info(`Feedback submitted successfully for ${target_type} ${target_id}`);
|
|
27
|
-
await telemetryLogger.log("client_submit_feedback", {
|
|
28
|
-
success: true,
|
|
29
|
-
log_context: {
|
|
30
|
-
target_type,
|
|
31
|
-
target_id,
|
|
32
|
-
feedback_id: response.id,
|
|
33
|
-
},
|
|
34
|
-
latency_ms: Date.now() - startTime,
|
|
35
|
-
});
|
|
36
|
-
return {
|
|
37
|
-
content: [
|
|
38
|
-
{
|
|
39
|
-
type: "text",
|
|
40
|
-
text: promptsCache
|
|
41
|
-
.getPrompt("submit_feedback_success")
|
|
42
|
-
.replace("{FEEDBACK_ID}", response.id),
|
|
43
|
-
},
|
|
44
|
-
],
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
catch (error) {
|
|
48
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
49
|
-
await logger.error(`Failed to submit feedback: ${errorMessage}`);
|
|
50
|
-
await telemetryLogger.log("client_submit_feedback", {
|
|
51
|
-
success: false,
|
|
52
|
-
log_context: {
|
|
53
|
-
target_type,
|
|
54
|
-
target_id,
|
|
55
|
-
},
|
|
56
|
-
pii_sanitized_error_message: errorMessage,
|
|
57
|
-
latency_ms: Date.now() - startTime,
|
|
58
|
-
});
|
|
59
|
-
return {
|
|
60
|
-
isError: true,
|
|
61
|
-
content: [
|
|
62
|
-
{
|
|
63
|
-
type: "text",
|
|
64
|
-
text: promptsCache
|
|
65
|
-
.getPrompt("unexpected_error")
|
|
66
|
-
.replace("{ERROR}", errorMessage),
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
export class FeedbackPolicy {
|
|
2
|
-
constructor(clientContext, callToolObserver, installObserver) {
|
|
3
|
-
this.callToolObserver = callToolObserver;
|
|
4
|
-
this.installObserver = installObserver;
|
|
5
|
-
this.clientContext = clientContext;
|
|
6
|
-
this.blockedMcpServersSet = new Set(clientContext.flags.blocked_mcp_servers || []);
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Validates feedback by checking that:
|
|
10
|
-
* - The referenced server has been used or had an install/uninstall action
|
|
11
|
-
* - The server is not in the blocked servers list
|
|
12
|
-
*
|
|
13
|
-
* For server feedback, verifies that:
|
|
14
|
-
* - The referenced server has been connected to and used or had an install/uninstall action
|
|
15
|
-
* - The server is not blocked
|
|
16
|
-
*
|
|
17
|
-
* For playbook feedback, no validation is currently performed
|
|
18
|
-
* since playbooks can reference other playbooks.
|
|
19
|
-
*
|
|
20
|
-
* @throws Error if feedback references a server that hasn't been used or had an install/uninstall action
|
|
21
|
-
* in the current session or if the server is blocked
|
|
22
|
-
*/
|
|
23
|
-
enforceFeedbackPolicy(feedback) {
|
|
24
|
-
const { target_type, target_id } = feedback;
|
|
25
|
-
if (target_type === "server") {
|
|
26
|
-
// Check if server is blocked
|
|
27
|
-
if (this.blockedMcpServersSet.has(target_id)) {
|
|
28
|
-
throw new Error(`Cannot submit feedback for blocked server "${target_id}"`);
|
|
29
|
-
}
|
|
30
|
-
// For server feedback, verify the server was actually used or had an install/uninstall action
|
|
31
|
-
if (!this.callToolObserver.wasServerCalled(target_id) &&
|
|
32
|
-
!this.installObserver.wasServerInstalled(target_id) &&
|
|
33
|
-
!this.installObserver.wasServerUninstalled(target_id)) {
|
|
34
|
-
throw new Error(`Cannot submit feedback for server "${target_id}" which has not been used or had an install/uninstall action in this session.`);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
// For playbook feedback, we don't validate usage since playbooks can reference other playbooks
|
|
38
|
-
}
|
|
39
|
-
}
|