@toolplex/client 0.1.45 → 0.1.47
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/toolHandlers/callToolHandler.js +3 -2
- package/dist/mcp-server/toolHandlers/lookupEntityHandler.js +11 -6
- package/dist/mcp-server/toolHandlers/notifyHandler.d.ts +1 -1
- package/dist/mcp-server/toolHandlers/notifyHandler.js +24 -15
- package/dist/mcp-server/toolplexApi/service.d.ts +23 -1
- package/dist/mcp-server/toolplexApi/service.js +62 -0
- package/dist/mcp-server/toolplexApi/types.d.ts +30 -0
- package/dist/src/mcp-server/toolplexApi/service.js +62 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -35,7 +35,8 @@ export async function handleCallTool(params) {
|
|
|
35
35
|
const isPreApproved = automationContext.preApprovedToolCall?.server_id === params.server_id &&
|
|
36
36
|
automationContext.preApprovedToolCall?.tool_name === params.tool_name;
|
|
37
37
|
// Check if tool requires HITL approval (skip if pre-approved)
|
|
38
|
-
if (!isPreApproved &&
|
|
38
|
+
if (!isPreApproved &&
|
|
39
|
+
automationContext.toolsRequiringApproval.includes(toolKey)) {
|
|
39
40
|
await logger.info(`Tool ${toolKey} requires HITL approval`);
|
|
40
41
|
// Return HITL signal for cloud-agent to handle
|
|
41
42
|
return {
|
|
@@ -49,7 +50,7 @@ export async function handleCallTool(params) {
|
|
|
49
50
|
server_id: params.server_id,
|
|
50
51
|
tool_name: params.tool_name,
|
|
51
52
|
args: params.arguments,
|
|
52
|
-
context: `Requesting approval to run "${params.tool_name}"
|
|
53
|
+
context: `Requesting approval to run "${params.tool_name}"`,
|
|
53
54
|
}),
|
|
54
55
|
},
|
|
55
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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,
|
|
@@ -3,6 +3,6 @@ import { NotifyParams } from "../../shared/mcpServerTypes.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Handler for the notify tool.
|
|
5
5
|
* Only available in automation mode.
|
|
6
|
-
*
|
|
6
|
+
* Creates a notification via the API and optionally pauses the automation.
|
|
7
7
|
*/
|
|
8
8
|
export declare function handleNotify(params: NotifyParams): Promise<CallToolResult>;
|
|
@@ -4,13 +4,14 @@ const logger = FileLogger;
|
|
|
4
4
|
/**
|
|
5
5
|
* Handler for the notify tool.
|
|
6
6
|
* Only available in automation mode.
|
|
7
|
-
*
|
|
7
|
+
* Creates a notification via the API and optionally pauses the automation.
|
|
8
8
|
*/
|
|
9
9
|
export async function handleNotify(params) {
|
|
10
10
|
const startTime = Date.now();
|
|
11
11
|
await logger.debug(`Handling notify request with params: ${JSON.stringify(params)}`);
|
|
12
12
|
const telemetryLogger = Registry.getTelemetryLogger();
|
|
13
13
|
const clientContext = Registry.getClientContext();
|
|
14
|
+
const apiService = Registry.getToolplexApiService();
|
|
14
15
|
try {
|
|
15
16
|
// Verify we're in automation mode
|
|
16
17
|
if (clientContext.clientMode !== "automation") {
|
|
@@ -32,34 +33,42 @@ export async function handleNotify(params) {
|
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
await logger.info(`Sending HITL notification: ${params.title} (pause: ${params.pause_until_response})`);
|
|
36
|
+
// Call the API to create the notification (and pause if needed)
|
|
37
|
+
const result = await apiService.createAutomationNotification({
|
|
38
|
+
automationId: automationContext.automationId,
|
|
39
|
+
runId: automationContext.runId,
|
|
40
|
+
sessionId: clientContext.sessionId,
|
|
41
|
+
title: params.title,
|
|
42
|
+
content: params.content,
|
|
43
|
+
context: params.context,
|
|
44
|
+
responseType: params.response_type,
|
|
45
|
+
responseOptions: params.response_options,
|
|
46
|
+
pauseUntilResponse: params.pause_until_response,
|
|
47
|
+
notificationRecipients: [{ email: automationContext.notificationEmail }],
|
|
48
|
+
expirationHours: automationContext.expirationHours,
|
|
49
|
+
});
|
|
35
50
|
await telemetryLogger.log("client_notify", {
|
|
36
51
|
success: true,
|
|
37
52
|
log_context: {
|
|
38
53
|
response_type: params.response_type,
|
|
39
54
|
pause_until_response: params.pause_until_response,
|
|
40
55
|
has_context: !!params.context,
|
|
56
|
+
notification_id: result.notificationId,
|
|
41
57
|
},
|
|
42
58
|
latency_ms: Date.now() - startTime,
|
|
43
59
|
});
|
|
44
|
-
// Return
|
|
45
|
-
// The cloud-agent will parse this and create the notification
|
|
60
|
+
// Return simple result - cloud-agent checks for 'paused' flag
|
|
46
61
|
return {
|
|
47
62
|
content: [
|
|
48
63
|
{
|
|
49
64
|
type: "text",
|
|
50
65
|
text: JSON.stringify({
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
response_options: params.response_options,
|
|
58
|
-
pause_until_response: params.pause_until_response,
|
|
59
|
-
automation_id: automationContext.automationId,
|
|
60
|
-
run_id: automationContext.runId,
|
|
61
|
-
notification_email: automationContext.notificationEmail,
|
|
62
|
-
expiration_hours: automationContext.expirationHours,
|
|
66
|
+
success: true,
|
|
67
|
+
notificationId: result.notificationId,
|
|
68
|
+
paused: result.paused,
|
|
69
|
+
message: result.paused
|
|
70
|
+
? "Notification sent. Automation paused awaiting response."
|
|
71
|
+
: "Notification sent. Automation continues.",
|
|
63
72
|
}),
|
|
64
73
|
},
|
|
65
74
|
],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CreatePlaybookResponse, LogPlaybookUsageResponse, SubmitFeedbackResponse, SecurityAssessment, FeedbackSummaryResponse, LogTelemetryRequest, LogTelemetryBatchResponse, InitResponse, SearchResponse } from "./types.js";
|
|
1
|
+
import { CreatePlaybookResponse, LogPlaybookUsageResponse, SubmitFeedbackResponse, SecurityAssessment, 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";
|
|
@@ -26,4 +26,26 @@ export declare class ToolplexApiService {
|
|
|
26
26
|
logPlaybookUsage(playbookId: string, success: boolean, errorMessage?: string): Promise<LogPlaybookUsageResponse>;
|
|
27
27
|
submitFeedback(targetType: "server" | "playbook", targetId: string, vote: "up" | "down", message?: string, securityAssessment?: SecurityAssessment): Promise<SubmitFeedbackResponse>;
|
|
28
28
|
getFeedbackSummary(): Promise<FeedbackSummaryResponse>;
|
|
29
|
+
/**
|
|
30
|
+
* Create an automation notification (HITL)
|
|
31
|
+
* Optionally pauses the automation run if pauseUntilResponse is true
|
|
32
|
+
*
|
|
33
|
+
* @returns Object with notificationId and paused status
|
|
34
|
+
*/
|
|
35
|
+
createAutomationNotification(params: {
|
|
36
|
+
automationId: string;
|
|
37
|
+
runId: string;
|
|
38
|
+
sessionId?: string;
|
|
39
|
+
title: string;
|
|
40
|
+
content: string;
|
|
41
|
+
context?: string;
|
|
42
|
+
responseType: "boolean" | "multi_choice" | "freeform";
|
|
43
|
+
responseOptions?: string[];
|
|
44
|
+
pauseUntilResponse: boolean;
|
|
45
|
+
notificationRecipients: NotificationRecipient[];
|
|
46
|
+
expirationHours: number;
|
|
47
|
+
}): Promise<{
|
|
48
|
+
notificationId: string;
|
|
49
|
+
paused: boolean;
|
|
50
|
+
}>;
|
|
29
51
|
}
|
|
@@ -227,4 +227,66 @@ export class ToolplexApiService {
|
|
|
227
227
|
throw err;
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* Create an automation notification (HITL)
|
|
232
|
+
* Optionally pauses the automation run if pauseUntilResponse is true
|
|
233
|
+
*
|
|
234
|
+
* @returns Object with notificationId and paused status
|
|
235
|
+
*/
|
|
236
|
+
async createAutomationNotification(params) {
|
|
237
|
+
const { automationId, runId, sessionId, title, content, context, responseType, responseOptions, pauseUntilResponse, notificationRecipients, expirationHours, } = params;
|
|
238
|
+
try {
|
|
239
|
+
// Create the notification
|
|
240
|
+
const notificationRequest = {
|
|
241
|
+
automation_id: automationId,
|
|
242
|
+
run_id: runId,
|
|
243
|
+
session_id: sessionId,
|
|
244
|
+
notification_type: "agent_notify",
|
|
245
|
+
title,
|
|
246
|
+
content,
|
|
247
|
+
context,
|
|
248
|
+
response_type: responseType,
|
|
249
|
+
response_options: responseOptions,
|
|
250
|
+
requires_response: pauseUntilResponse,
|
|
251
|
+
notification_recipients: notificationRecipients,
|
|
252
|
+
expiration_hours: expirationHours,
|
|
253
|
+
};
|
|
254
|
+
const response = await fetch(`${this.baseUrl}/cloud/automation-notifications`, {
|
|
255
|
+
method: "POST",
|
|
256
|
+
headers: this.getHeadersWithSession(),
|
|
257
|
+
body: JSON.stringify(notificationRequest),
|
|
258
|
+
});
|
|
259
|
+
const notificationResult = await this.handleFetchResponse(response);
|
|
260
|
+
await logger.info(`Created automation notification: ${notificationResult.id}`);
|
|
261
|
+
// If pause is requested, update the run status
|
|
262
|
+
if (pauseUntilResponse) {
|
|
263
|
+
const pauseResponse = await fetch(`${this.baseUrl}/cloud/automation-runs/${runId}/pause`, {
|
|
264
|
+
method: "POST",
|
|
265
|
+
headers: this.getHeadersWithSession(),
|
|
266
|
+
body: JSON.stringify({
|
|
267
|
+
status: "awaiting_response",
|
|
268
|
+
resume_context: {
|
|
269
|
+
pending_notification_id: notificationResult.id,
|
|
270
|
+
paused_at: new Date().toISOString(),
|
|
271
|
+
},
|
|
272
|
+
}),
|
|
273
|
+
});
|
|
274
|
+
if (!pauseResponse.ok) {
|
|
275
|
+
const errorText = await pauseResponse.text();
|
|
276
|
+
await logger.warn(`Failed to pause automation run ${runId}: ${errorText}`);
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
await logger.info(`Automation run ${runId} paused awaiting response`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
notificationId: notificationResult.id,
|
|
284
|
+
paused: pauseUntilResponse,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
catch (err) {
|
|
288
|
+
await logger.error(`Error creating automation notification: ${err}`);
|
|
289
|
+
throw err;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
230
292
|
}
|
|
@@ -148,3 +148,33 @@ export interface SearchResponse {
|
|
|
148
148
|
mcp_servers?: any[];
|
|
149
149
|
playbooks?: any[];
|
|
150
150
|
}
|
|
151
|
+
export interface NotificationRecipient {
|
|
152
|
+
email: string;
|
|
153
|
+
name?: string;
|
|
154
|
+
role?: string;
|
|
155
|
+
}
|
|
156
|
+
export interface CreateAutomationNotificationRequest {
|
|
157
|
+
automation_id: string;
|
|
158
|
+
run_id: string;
|
|
159
|
+
session_id?: string;
|
|
160
|
+
notification_type: "agent_notify" | "tool_approval";
|
|
161
|
+
title: string;
|
|
162
|
+
content: string;
|
|
163
|
+
context?: string;
|
|
164
|
+
response_type: "boolean" | "multi_choice" | "freeform";
|
|
165
|
+
response_options?: string[];
|
|
166
|
+
requires_response: boolean;
|
|
167
|
+
notification_recipients: NotificationRecipient[];
|
|
168
|
+
expiration_hours: number;
|
|
169
|
+
}
|
|
170
|
+
export interface CreateAutomationNotificationResponse {
|
|
171
|
+
id: string;
|
|
172
|
+
decision_token: string;
|
|
173
|
+
}
|
|
174
|
+
export interface PauseAutomationRunRequest {
|
|
175
|
+
status: "awaiting_response";
|
|
176
|
+
resume_context: {
|
|
177
|
+
pending_notification_id: string;
|
|
178
|
+
paused_at: string;
|
|
179
|
+
};
|
|
180
|
+
}
|
|
@@ -227,4 +227,66 @@ export class ToolplexApiService {
|
|
|
227
227
|
throw err;
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* Create an automation notification (HITL)
|
|
232
|
+
* Optionally pauses the automation run if pauseUntilResponse is true
|
|
233
|
+
*
|
|
234
|
+
* @returns Object with notificationId and paused status
|
|
235
|
+
*/
|
|
236
|
+
async createAutomationNotification(params) {
|
|
237
|
+
const { automationId, runId, sessionId, title, content, context, responseType, responseOptions, pauseUntilResponse, notificationRecipients, expirationHours, } = params;
|
|
238
|
+
try {
|
|
239
|
+
// Create the notification
|
|
240
|
+
const notificationRequest = {
|
|
241
|
+
automation_id: automationId,
|
|
242
|
+
run_id: runId,
|
|
243
|
+
session_id: sessionId,
|
|
244
|
+
notification_type: "agent_notify",
|
|
245
|
+
title,
|
|
246
|
+
content,
|
|
247
|
+
context,
|
|
248
|
+
response_type: responseType,
|
|
249
|
+
response_options: responseOptions,
|
|
250
|
+
requires_response: pauseUntilResponse,
|
|
251
|
+
notification_recipients: notificationRecipients,
|
|
252
|
+
expiration_hours: expirationHours,
|
|
253
|
+
};
|
|
254
|
+
const response = await fetch(`${this.baseUrl}/cloud/automation-notifications`, {
|
|
255
|
+
method: "POST",
|
|
256
|
+
headers: this.getHeadersWithSession(),
|
|
257
|
+
body: JSON.stringify(notificationRequest),
|
|
258
|
+
});
|
|
259
|
+
const notificationResult = await this.handleFetchResponse(response);
|
|
260
|
+
await logger.info(`Created automation notification: ${notificationResult.id}`);
|
|
261
|
+
// If pause is requested, update the run status
|
|
262
|
+
if (pauseUntilResponse) {
|
|
263
|
+
const pauseResponse = await fetch(`${this.baseUrl}/cloud/automation-runs/${runId}/pause`, {
|
|
264
|
+
method: "POST",
|
|
265
|
+
headers: this.getHeadersWithSession(),
|
|
266
|
+
body: JSON.stringify({
|
|
267
|
+
status: "awaiting_response",
|
|
268
|
+
resume_context: {
|
|
269
|
+
pending_notification_id: notificationResult.id,
|
|
270
|
+
paused_at: new Date().toISOString(),
|
|
271
|
+
},
|
|
272
|
+
}),
|
|
273
|
+
});
|
|
274
|
+
if (!pauseResponse.ok) {
|
|
275
|
+
const errorText = await pauseResponse.text();
|
|
276
|
+
await logger.warn(`Failed to pause automation run ${runId}: ${errorText}`);
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
await logger.info(`Automation run ${runId} paused awaiting response`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
notificationId: notificationResult.id,
|
|
284
|
+
paused: pauseUntilResponse,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
catch (err) {
|
|
288
|
+
await logger.error(`Error creating automation notification: ${err}`);
|
|
289
|
+
throw err;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
230
292
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "0.1.
|
|
1
|
+
export declare const version = "0.1.47";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.1.
|
|
1
|
+
export const version = '0.1.47';
|