@toolplex/client 0.1.46 → 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.
@@ -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 and submit_feedback
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, SubmitFeedbackParams } from "../../shared/mcpServerTypes.js";
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.
@@ -50,7 +50,7 @@ export async function handleCallTool(params) {
50
50
  server_id: params.server_id,
51
51
  tool_name: params.tool_name,
52
52
  args: params.arguments,
53
- context: `Requesting approval to run "${params.tool_name}" on "${params.server_id}"`,
53
+ context: `Requesting approval to run "${params.tool_name}"`,
54
54
  }),
55
55
  },
56
56
  ],
@@ -85,12 +85,17 @@ export async function handleLookupEntityTool(params) {
85
85
  text: `Found ${params.entity_type}: ${lookupResponse.server_name || lookupResponse.description || params.entity_id}`,
86
86
  },
87
87
  ];
88
- if (params.entity_type === "server") {
89
- content.push({
90
- type: "text",
91
- text: promptsCache.getPrompt("lookup_entity_install_guidance"),
92
- _meta: { role: "system" },
93
- });
88
+ // Add installation guidance for server lookups, but not for org users
89
+ // (org users don't have install tools - they use pre-approved tools only)
90
+ if (params.entity_type === "server" && !clientContext.isOrgUser) {
91
+ const installGuidance = promptsCache.getPrompt("lookup_entity_install_guidance");
92
+ if (installGuidance) {
93
+ content.push({
94
+ type: "text",
95
+ text: installGuidance,
96
+ _meta: { role: "system" },
97
+ });
98
+ }
94
99
  }
95
100
  return {
96
101
  content,
@@ -1,4 +1,4 @@
1
- import { CreatePlaybookResponse, LogPlaybookUsageResponse, SubmitFeedbackResponse, SecurityAssessment, FeedbackSummaryResponse, LogTelemetryRequest, LogTelemetryBatchResponse, InitResponse, SearchResponse, NotificationRecipient } from "./types.js";
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, SubmitFeedbackParamsSchema, GetServerConfigParamsSchema, NotifyParamsSchema, } from "../shared/mcpServerTypes.js";
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/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "0.1.46";
1
+ export declare const version = "0.1.47";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '0.1.46';
1
+ export const version = '0.1.47';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toolplex/client",
3
- "version": "0.1.46",
3
+ "version": "0.2.0",
4
4
  "author": "ToolPlex LLC",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "description": "The official ToolPlex client for AI agent tool discovery and execution",
@@ -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,3 +0,0 @@
1
- import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2
- import { GetServerConfigParams } from "../../shared/mcpServerTypes.js";
3
- export declare function handleGetServerConfig(params: GetServerConfigParams): Promise<CallToolResult>;
@@ -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,3 +0,0 @@
1
- import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2
- import { SubmitFeedbackParams } from "../../shared/mcpServerTypes.js";
3
- export declare function handleSubmitFeedback(params: SubmitFeedbackParams): Promise<CallToolResult>;
@@ -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
- }