@toolplex/client 0.1.1 → 0.1.3
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/clientContext.d.ts +7 -4
- package/dist/mcp-server/clientContext.js +21 -10
- package/dist/mcp-server/index.js +9 -7
- package/dist/mcp-server/logging/telemetryLogger.d.ts +2 -2
- package/dist/mcp-server/logging/telemetryLogger.js +2 -2
- package/dist/mcp-server/policy/callToolObserver.js +4 -2
- package/dist/mcp-server/policy/feedbackPolicy.d.ts +4 -4
- package/dist/mcp-server/policy/feedbackPolicy.js +1 -1
- package/dist/mcp-server/policy/installObserver.js +4 -4
- package/dist/mcp-server/policy/playbookPolicy.d.ts +3 -3
- package/dist/mcp-server/policy/playbookPolicy.js +5 -5
- package/dist/mcp-server/policy/policyEnforcer.d.ts +4 -4
- package/dist/mcp-server/policy/policyEnforcer.js +13 -13
- package/dist/mcp-server/policy/serverPolicy.d.ts +1 -1
- package/dist/mcp-server/policy/serverPolicy.js +4 -2
- package/dist/mcp-server/promptsCache.js +2 -2
- package/dist/mcp-server/registry.d.ts +8 -8
- package/dist/mcp-server/registry.js +19 -17
- package/dist/mcp-server/serversCache.d.ts +1 -1
- package/dist/mcp-server/serversCache.js +6 -6
- package/dist/mcp-server/staticPrompts.js +2 -2
- package/dist/mcp-server/toolDefinitionsCache.d.ts +3 -3
- package/dist/mcp-server/toolDefinitionsCache.js +3 -3
- package/dist/mcp-server/toolHandlers/callToolHandler.d.ts +2 -2
- package/dist/mcp-server/toolHandlers/callToolHandler.js +32 -20
- package/dist/mcp-server/toolHandlers/getServerConfigHandler.d.ts +2 -2
- package/dist/mcp-server/toolHandlers/getServerConfigHandler.js +24 -18
- package/dist/mcp-server/toolHandlers/initHandler.d.ts +2 -2
- package/dist/mcp-server/toolHandlers/initHandler.js +41 -39
- package/dist/mcp-server/toolHandlers/installServerHandler.d.ts +2 -2
- package/dist/mcp-server/toolHandlers/installServerHandler.js +36 -32
- package/dist/mcp-server/toolHandlers/listServersHandler.d.ts +1 -1
- package/dist/mcp-server/toolHandlers/listServersHandler.js +21 -17
- package/dist/mcp-server/toolHandlers/listToolsHandler.d.ts +2 -2
- package/dist/mcp-server/toolHandlers/listToolsHandler.js +32 -26
- package/dist/mcp-server/toolHandlers/logPlaybookUsageHandler.d.ts +2 -2
- package/dist/mcp-server/toolHandlers/logPlaybookUsageHandler.js +14 -14
- package/dist/mcp-server/toolHandlers/lookupEntityHandler.d.ts +2 -2
- package/dist/mcp-server/toolHandlers/lookupEntityHandler.js +30 -28
- package/dist/mcp-server/toolHandlers/savePlaybookHandler.d.ts +2 -2
- package/dist/mcp-server/toolHandlers/savePlaybookHandler.js +17 -15
- package/dist/mcp-server/toolHandlers/searchHandler.d.ts +2 -2
- package/dist/mcp-server/toolHandlers/searchHandler.js +33 -28
- package/dist/mcp-server/toolHandlers/serverManagerUtils.d.ts +1 -1
- package/dist/mcp-server/toolHandlers/serverManagerUtils.js +2 -2
- package/dist/mcp-server/toolHandlers/submitFeedbackHandler.d.ts +2 -2
- package/dist/mcp-server/toolHandlers/submitFeedbackHandler.js +17 -15
- package/dist/mcp-server/toolHandlers/uninstallServerHandler.d.ts +2 -2
- package/dist/mcp-server/toolHandlers/uninstallServerHandler.js +21 -19
- package/dist/mcp-server/toolplexApi/service.d.ts +8 -8
- package/dist/mcp-server/toolplexApi/service.js +24 -28
- package/dist/mcp-server/toolplexApi/types.d.ts +3 -3
- package/dist/mcp-server/toolplexServer.d.ts +1 -1
- package/dist/mcp-server/toolplexServer.js +78 -77
- package/dist/mcp-server/tools.d.ts +1 -1
- package/dist/mcp-server/tools.js +3 -3
- package/dist/mcp-server/utils/initServerManagers.d.ts +4 -4
- package/dist/mcp-server/utils/initServerManagers.js +5 -5
- package/dist/mcp-server/utils/resultAnnotators.js +3 -7
- package/dist/mcp-server/utils/runtimeCheck.js +8 -8
- package/dist/server-manager/index.js +4 -4
- package/dist/server-manager/serverManager.d.ts +6 -6
- package/dist/server-manager/serverManager.js +34 -36
- package/dist/server-manager/stdioServer.js +37 -35
- package/dist/server-manager/stdioTransportProtocol.d.ts +2 -2
- package/dist/server-manager/stdioTransportProtocol.js +7 -7
- package/dist/shared/enhancedPath.js +13 -13
- package/dist/shared/fileLogger.js +19 -19
- package/dist/shared/mcpServerTypes.d.ts +4 -3
- package/dist/shared/mcpServerTypes.js +17 -10
- package/dist/shared/serverManagerTypes.d.ts +1 -1
- package/dist/shared/serverManagerTypes.js +1 -1
- package/dist/shared/stdioServerManagerClient.js +20 -18
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -25,7 +25,7 @@ export class ToolDefinitionsCache {
|
|
|
25
25
|
*/
|
|
26
26
|
getTools() {
|
|
27
27
|
if (!this._tools) {
|
|
28
|
-
throw new Error(
|
|
28
|
+
throw new Error("ToolDefinitionsCache not initialized");
|
|
29
29
|
}
|
|
30
30
|
return this._tools;
|
|
31
31
|
}
|
|
@@ -34,7 +34,7 @@ export class ToolDefinitionsCache {
|
|
|
34
34
|
*/
|
|
35
35
|
getTool(name) {
|
|
36
36
|
if (!this._tools) {
|
|
37
|
-
throw new Error(
|
|
37
|
+
throw new Error("ToolDefinitionsCache not initialized");
|
|
38
38
|
}
|
|
39
39
|
const tool = this._tools.find((t) => t.name === name);
|
|
40
40
|
if (!tool) {
|
|
@@ -47,7 +47,7 @@ export class ToolDefinitionsCache {
|
|
|
47
47
|
*/
|
|
48
48
|
getVersion() {
|
|
49
49
|
if (!this._version) {
|
|
50
|
-
throw new Error(
|
|
50
|
+
throw new Error("ToolDefinitionsCache not initialized");
|
|
51
51
|
}
|
|
52
52
|
return this._version;
|
|
53
53
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { CallToolResult } from
|
|
2
|
-
import { CallToolParams } from
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { CallToolParams } from "../../shared/mcpServerTypes.js";
|
|
3
3
|
export declare function handleCallTool(params: CallToolParams): Promise<CallToolResult>;
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import { findServerManagerClient } from
|
|
2
|
-
import { CallToolResultSchema } from
|
|
3
|
-
import { FileLogger } from
|
|
4
|
-
import Registry from
|
|
1
|
+
import { findServerManagerClient } from "./serverManagerUtils.js";
|
|
2
|
+
import { CallToolResultSchema } from "../../shared/serverManagerTypes.js";
|
|
3
|
+
import { FileLogger } from "../../shared/fileLogger.js";
|
|
4
|
+
import Registry from "../registry.js";
|
|
5
5
|
const logger = FileLogger;
|
|
6
|
+
function safeLength(obj) {
|
|
7
|
+
try {
|
|
8
|
+
return JSON.stringify(obj).length;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return -1;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
6
14
|
export async function handleCallTool(params) {
|
|
7
15
|
await logger.debug(`Handling call tool request with params: ${JSON.stringify(params)}`);
|
|
8
16
|
const serverManagerClients = Registry.getServerManagerClients();
|
|
@@ -17,8 +25,8 @@ export async function handleCallTool(params) {
|
|
|
17
25
|
// Enforce call tool policy
|
|
18
26
|
policyEnforcer.enforceCallToolPolicy(params.server_id);
|
|
19
27
|
const client = await findServerManagerClient(params.server_id, serverManagerClients);
|
|
20
|
-
const response = await client.sendRequest(
|
|
21
|
-
if (
|
|
28
|
+
const response = await client.sendRequest("call_tool", params);
|
|
29
|
+
if ("error" in response) {
|
|
22
30
|
throw new Error(`Failed to call tool with params: ${JSON.stringify(params)}, error message: ${response.error.message}`);
|
|
23
31
|
}
|
|
24
32
|
const parsed = CallToolResultSchema.safeParse(response);
|
|
@@ -30,30 +38,34 @@ export async function handleCallTool(params) {
|
|
|
30
38
|
const result = parsed.data.result;
|
|
31
39
|
const content = Array.isArray(result) ? result : [result];
|
|
32
40
|
if (!clientContext.permissions.enable_read_only_mode &&
|
|
33
|
-
clientContext.clientMode !==
|
|
41
|
+
clientContext.clientMode !== "restricted") {
|
|
34
42
|
content.push({
|
|
35
|
-
type:
|
|
36
|
-
text: promptsCache.getPrompt(
|
|
43
|
+
type: "text",
|
|
44
|
+
text: promptsCache.getPrompt("tool_call_next_steps"),
|
|
37
45
|
});
|
|
38
46
|
}
|
|
39
|
-
await logger.debug(
|
|
40
|
-
await telemetryLogger.log(
|
|
47
|
+
await logger.debug("Tool called successfully");
|
|
48
|
+
await telemetryLogger.log("client_call_tool", {
|
|
41
49
|
success: true,
|
|
42
50
|
log_context: {
|
|
43
51
|
server_id: params.server_id,
|
|
44
52
|
tool_name: params.tool_name,
|
|
53
|
+
input_length: safeLength(params),
|
|
54
|
+
response_length: safeLength(content),
|
|
45
55
|
},
|
|
46
56
|
latency_ms: Date.now() - startTime,
|
|
47
57
|
});
|
|
48
58
|
return {
|
|
49
|
-
role:
|
|
59
|
+
role: "system",
|
|
50
60
|
content: content,
|
|
51
61
|
};
|
|
52
62
|
}
|
|
53
63
|
catch (error) {
|
|
54
|
-
const errorMessage = error instanceof Error
|
|
64
|
+
const errorMessage = error instanceof Error
|
|
65
|
+
? error.message
|
|
66
|
+
: promptsCache.getPrompt("unexpected_error");
|
|
55
67
|
await logger.error(`Failed to call tool: ${errorMessage}`);
|
|
56
|
-
await telemetryLogger.log(
|
|
68
|
+
await telemetryLogger.log("client_call_tool", {
|
|
57
69
|
success: false,
|
|
58
70
|
log_context: {
|
|
59
71
|
server_id: params.server_id,
|
|
@@ -63,15 +75,15 @@ export async function handleCallTool(params) {
|
|
|
63
75
|
latency_ms: Date.now() - startTime,
|
|
64
76
|
});
|
|
65
77
|
return {
|
|
66
|
-
role:
|
|
78
|
+
role: "system",
|
|
67
79
|
content: [
|
|
68
80
|
{
|
|
69
|
-
type:
|
|
81
|
+
type: "text",
|
|
70
82
|
text: promptsCache
|
|
71
|
-
.getPrompt(
|
|
72
|
-
.replace(
|
|
73
|
-
.replace(
|
|
74
|
-
.replace(
|
|
83
|
+
.getPrompt("tool_call_failure")
|
|
84
|
+
.replace("{ERROR}", errorMessage)
|
|
85
|
+
.replace("{SERVER_ID}", params.server_id)
|
|
86
|
+
.replace("{TOOL_NAME}", params.tool_name),
|
|
75
87
|
},
|
|
76
88
|
],
|
|
77
89
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { CallToolResult } from
|
|
2
|
-
import { GetServerConfigParams } from
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { GetServerConfigParams } from "../../shared/mcpServerTypes.js";
|
|
3
3
|
export declare function handleGetServerConfig(params: GetServerConfigParams): Promise<CallToolResult>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { FileLogger } from
|
|
2
|
-
import { findServerManagerClient } from
|
|
3
|
-
import Registry from
|
|
1
|
+
import { FileLogger } from "../../shared/fileLogger.js";
|
|
2
|
+
import { findServerManagerClient } from "./serverManagerUtils.js";
|
|
3
|
+
import Registry from "../registry.js";
|
|
4
4
|
const logger = FileLogger;
|
|
5
5
|
export async function handleGetServerConfig(params) {
|
|
6
6
|
const startTime = Date.now();
|
|
@@ -11,20 +11,22 @@ export async function handleGetServerConfig(params) {
|
|
|
11
11
|
try {
|
|
12
12
|
const server_id = params.server_id;
|
|
13
13
|
if (!server_id) {
|
|
14
|
-
throw new Error(
|
|
14
|
+
throw new Error("Missing server_id");
|
|
15
15
|
}
|
|
16
16
|
// Check if server is blocked using policy enforcer
|
|
17
17
|
policyEnforcer.enforceUseServerPolicy(server_id);
|
|
18
18
|
await logger.debug(`Getting config for server: ${server_id}`);
|
|
19
19
|
const client = await findServerManagerClient(server_id, serverManagerClients);
|
|
20
|
-
const response_data = await client.sendRequest(
|
|
21
|
-
|
|
20
|
+
const response_data = await client.sendRequest("get_server_config", {
|
|
21
|
+
server_id,
|
|
22
|
+
});
|
|
23
|
+
if ("error" in response_data) {
|
|
22
24
|
throw new Error(`Failed to get config for server_id ${server_id}, error message: ${response_data.error.message}`);
|
|
23
25
|
}
|
|
24
26
|
// The config is returned directly as an object
|
|
25
27
|
const config = response_data;
|
|
26
|
-
await logger.debug(
|
|
27
|
-
await telemetryLogger.log(
|
|
28
|
+
await logger.debug("Successfully retrieved server config");
|
|
29
|
+
await telemetryLogger.log("client_get_server_config", {
|
|
28
30
|
success: true,
|
|
29
31
|
log_context: {
|
|
30
32
|
server_id,
|
|
@@ -32,21 +34,25 @@ export async function handleGetServerConfig(params) {
|
|
|
32
34
|
latency_ms: Date.now() - startTime,
|
|
33
35
|
});
|
|
34
36
|
return {
|
|
35
|
-
role:
|
|
37
|
+
role: "system",
|
|
36
38
|
content: [
|
|
37
39
|
{
|
|
38
|
-
type:
|
|
39
|
-
text: promptsCache
|
|
40
|
-
|
|
40
|
+
type: "text",
|
|
41
|
+
text: promptsCache
|
|
42
|
+
.getPrompt("get_server_config_header")
|
|
43
|
+
.replace("{SERVER_ID}", server_id) +
|
|
44
|
+
"\n" +
|
|
41
45
|
JSON.stringify(config, null, 2),
|
|
42
46
|
},
|
|
43
47
|
],
|
|
44
48
|
};
|
|
45
49
|
}
|
|
46
50
|
catch (error) {
|
|
47
|
-
const errorMessage = error instanceof Error
|
|
51
|
+
const errorMessage = error instanceof Error
|
|
52
|
+
? error.message
|
|
53
|
+
: promptsCache.getPrompt("unexpected_error");
|
|
48
54
|
await logger.error(`Failed to get server config: ${errorMessage}`);
|
|
49
|
-
await telemetryLogger.log(
|
|
55
|
+
await telemetryLogger.log("client_get_server_config", {
|
|
50
56
|
success: false,
|
|
51
57
|
log_context: {
|
|
52
58
|
server_id: params.server_id,
|
|
@@ -55,13 +61,13 @@ export async function handleGetServerConfig(params) {
|
|
|
55
61
|
latency_ms: Date.now() - startTime,
|
|
56
62
|
});
|
|
57
63
|
return {
|
|
58
|
-
role:
|
|
64
|
+
role: "system",
|
|
59
65
|
content: [
|
|
60
66
|
{
|
|
61
|
-
type:
|
|
67
|
+
type: "text",
|
|
62
68
|
text: promptsCache
|
|
63
|
-
.getPrompt(
|
|
64
|
-
.replace(
|
|
69
|
+
.getPrompt("get_server_config_failure")
|
|
70
|
+
.replace("{ERROR}", errorMessage),
|
|
65
71
|
},
|
|
66
72
|
],
|
|
67
73
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { CallToolResult } from
|
|
2
|
-
import { InitializeToolplexParams } from
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { InitializeToolplexParams } from "../../shared/mcpServerTypes.js";
|
|
3
3
|
export declare function handleInitialize(params: InitializeToolplexParams): Promise<CallToolResult>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { FileLogger } from
|
|
2
|
-
import os from
|
|
3
|
-
import { initServerManagersOnly } from
|
|
4
|
-
import Registry from
|
|
1
|
+
import { FileLogger } from "../../shared/fileLogger.js";
|
|
2
|
+
import os from "os";
|
|
3
|
+
import { initServerManagersOnly } from "../utils/initServerManagers.js";
|
|
4
|
+
import Registry from "../registry.js";
|
|
5
5
|
const logger = FileLogger;
|
|
6
6
|
export async function handleInitialize(params) {
|
|
7
7
|
const startTime = Date.now();
|
|
8
|
-
await logger.info(
|
|
8
|
+
await logger.info("Initializing ToolPlex");
|
|
9
9
|
await logger.debug(`Initialization params: ${JSON.stringify(params)}`);
|
|
10
10
|
const clientContext = Registry.getClientContext();
|
|
11
11
|
const apiService = Registry.getToolplexApiService();
|
|
@@ -14,12 +14,12 @@ export async function handleInitialize(params) {
|
|
|
14
14
|
const promptsCache = Registry.getPromptsCache();
|
|
15
15
|
const serversCache = Registry.getServersCache();
|
|
16
16
|
const policyEnforcer = Registry.getPolicyEnforcer();
|
|
17
|
-
await logger.debug(`Server manager clients: ${Object.keys(serverManagerClients).join(
|
|
17
|
+
await logger.debug(`Server manager clients: ${Object.keys(serverManagerClients).join(", ")}`);
|
|
18
18
|
const platform = os.platform();
|
|
19
|
-
const osName = platform ===
|
|
20
|
-
?
|
|
21
|
-
: platform ===
|
|
22
|
-
?
|
|
19
|
+
const osName = platform === "darwin"
|
|
20
|
+
? "macOS"
|
|
21
|
+
: platform === "win32"
|
|
22
|
+
? "Windows"
|
|
23
23
|
: platform.charAt(0).toUpperCase() + platform.slice(1);
|
|
24
24
|
const systemInfo = {
|
|
25
25
|
os: `${osName} ${os.release()}`,
|
|
@@ -28,7 +28,7 @@ export async function handleInitialize(params) {
|
|
|
28
28
|
cpuCores: os.cpus().length,
|
|
29
29
|
workDir: process.cwd(),
|
|
30
30
|
};
|
|
31
|
-
await logger.debug(
|
|
31
|
+
await logger.debug("Initializing server managers and API service");
|
|
32
32
|
const [serverManagerInitResults, toolplexApiInitResponse] = await Promise.all([
|
|
33
33
|
initServerManagersOnly(serverManagerClients).catch((err) => {
|
|
34
34
|
logger.warn(`Server manager init failed: ${err}`);
|
|
@@ -48,57 +48,59 @@ export async function handleInitialize(params) {
|
|
|
48
48
|
// Initialize the serversCache with the succeeded servers
|
|
49
49
|
serversCache.init(allSucceeded);
|
|
50
50
|
await logger.debug(`Total successes: ${allSucceeded.length}, Total failures: ${Object.keys(allFailures).length}`);
|
|
51
|
-
await logger.debug(
|
|
51
|
+
await logger.debug("Building initialization response");
|
|
52
52
|
// Safe to use prompts after init.
|
|
53
53
|
const result = {
|
|
54
|
-
role:
|
|
54
|
+
role: "system",
|
|
55
55
|
content: [
|
|
56
56
|
{
|
|
57
|
-
type:
|
|
57
|
+
type: "text",
|
|
58
58
|
text: promptsCache
|
|
59
|
-
.getPrompt(
|
|
60
|
-
.replace(
|
|
61
|
-
.replace(
|
|
62
|
-
.replace(
|
|
63
|
-
.replace(
|
|
64
|
-
.replace(
|
|
59
|
+
.getPrompt("initialization")
|
|
60
|
+
.replace("{ARGS.os}", systemInfo.os)
|
|
61
|
+
.replace("{ARGS.arch}", systemInfo.arch)
|
|
62
|
+
.replace("{ARGS.memory}", systemInfo.memory)
|
|
63
|
+
.replace("{ARGS.cpuCores}", systemInfo.cpuCores.toString())
|
|
64
|
+
.replace("{ARGS.workDir}", systemInfo.workDir),
|
|
65
65
|
},
|
|
66
66
|
],
|
|
67
67
|
};
|
|
68
68
|
result.content.push({
|
|
69
|
-
type:
|
|
69
|
+
type: "text",
|
|
70
70
|
text: promptsCache
|
|
71
|
-
.getPrompt(
|
|
72
|
-
.replace(
|
|
73
|
-
.
|
|
71
|
+
.getPrompt("initialization_results")
|
|
72
|
+
.replace("{SUCCEEDED}", allSucceeded
|
|
73
|
+
.map((s) => `${s.server_id} (${s.server_name})`)
|
|
74
|
+
.join(", ") || "none")
|
|
75
|
+
.replace("{FAILURES}", Object.entries(allFailures)
|
|
74
76
|
.map(([serverId, failure]) => `${serverId} (${failure.server_name}): ${failure.error}`)
|
|
75
|
-
.join(
|
|
76
|
-
.replace(
|
|
77
|
-
?
|
|
78
|
-
:
|
|
77
|
+
.join(", ") || "none")
|
|
78
|
+
.replace("{FAILURE_NOTE}", Object.keys(allFailures).length > 0
|
|
79
|
+
? "Please note there were failures installing some servers. Inform the user."
|
|
80
|
+
: ""),
|
|
79
81
|
});
|
|
80
82
|
if (clientContext.permissions.allowed_mcp_servers &&
|
|
81
83
|
clientContext.permissions.allowed_mcp_servers.length > 0) {
|
|
82
84
|
result.content.push({
|
|
83
|
-
type:
|
|
85
|
+
type: "text",
|
|
84
86
|
text: promptsCache
|
|
85
|
-
.getPrompt(
|
|
86
|
-
.replace(
|
|
87
|
+
.getPrompt("allowed_mcp_servers")
|
|
88
|
+
.replace("{ALLOWED_MCP_SERVERS}", clientContext.permissions.allowed_mcp_servers.join(", ")),
|
|
87
89
|
});
|
|
88
90
|
}
|
|
89
91
|
result.content.push({
|
|
90
|
-
type:
|
|
91
|
-
text:
|
|
92
|
+
type: "text",
|
|
93
|
+
text: "Your Most Recently Used Playbooks:\n" +
|
|
92
94
|
toolplexApiInitResponse.playbooks.playbooks
|
|
93
95
|
.map((p) => `- ${p.id}: ${p.description}\n` +
|
|
94
96
|
` Used ${p.times_used} times` +
|
|
95
97
|
(p.days_since_last_used !== null
|
|
96
|
-
? `, last use: ${p.days_since_last_used} ${p.days_since_last_used === 1 ?
|
|
97
|
-
:
|
|
98
|
-
.join(
|
|
99
|
-
|
|
98
|
+
? `, last use: ${p.days_since_last_used} ${p.days_since_last_used === 1 ? "day" : "days"} ago`
|
|
99
|
+
: ""))
|
|
100
|
+
.join("\n") +
|
|
101
|
+
"\n\nMore playbooks are available through the search tool.",
|
|
100
102
|
});
|
|
101
|
-
await telemetryLogger.log(
|
|
103
|
+
await telemetryLogger.log("client_initialize_toolplex", {
|
|
102
104
|
session_id: toolplexApiInitResponse.session_id,
|
|
103
105
|
success: Object.keys(allFailures).length === 0,
|
|
104
106
|
log_context: {
|
|
@@ -112,6 +114,6 @@ export async function handleInitialize(params) {
|
|
|
112
114
|
},
|
|
113
115
|
latency_ms: Date.now() - startTime,
|
|
114
116
|
});
|
|
115
|
-
await logger.info(
|
|
117
|
+
await logger.info("ToolPlex initialization completed");
|
|
116
118
|
return result;
|
|
117
119
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { CallToolResult } from
|
|
2
|
-
import { InstallParams } from
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { InstallParams } from "../../shared/mcpServerTypes.js";
|
|
3
3
|
export declare function handleInstallServer(params: InstallParams): Promise<CallToolResult>;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { FileLogger } from
|
|
2
|
-
import { ServerInstallResultSchema, ListToolsResultSchema, } from
|
|
3
|
-
import Registry from
|
|
4
|
-
import { RuntimeCheck } from
|
|
1
|
+
import { FileLogger } from "../../shared/fileLogger.js";
|
|
2
|
+
import { ServerInstallResultSchema, ListToolsResultSchema, } from "../../shared/serverManagerTypes.js";
|
|
3
|
+
import Registry from "../registry.js";
|
|
4
|
+
import { RuntimeCheck } from "../utils/runtimeCheck.js";
|
|
5
5
|
const logger = FileLogger;
|
|
6
6
|
async function installServer(serverId, serverName, description, serverManagerClient, serverConfig) {
|
|
7
7
|
await logger.info(`Starting installation of tool ${serverId}: ${serverName}`);
|
|
8
8
|
await logger.debug(`Server config: ${JSON.stringify(serverConfig)}, Server ID: ${serverId}`);
|
|
9
|
-
const response = await serverManagerClient.sendRequest(
|
|
9
|
+
const response = await serverManagerClient.sendRequest("install", {
|
|
10
10
|
server_id: serverId,
|
|
11
11
|
server_name: serverName,
|
|
12
12
|
description: description,
|
|
13
13
|
config: serverConfig,
|
|
14
14
|
});
|
|
15
|
-
if (
|
|
15
|
+
if ("error" in response) {
|
|
16
16
|
const error = `Server installation failed: ${response.error.message}`;
|
|
17
17
|
await logger.error(error);
|
|
18
18
|
throw new Error(error);
|
|
@@ -23,7 +23,7 @@ async function installServer(serverId, serverName, description, serverManagerCli
|
|
|
23
23
|
}
|
|
24
24
|
logger.debug(`Install response: ${JSON.stringify(response)}`);
|
|
25
25
|
if (!response) {
|
|
26
|
-
const error =
|
|
26
|
+
const error = "Server installation failed: No response received";
|
|
27
27
|
await logger.error(error);
|
|
28
28
|
throw new Error(error);
|
|
29
29
|
}
|
|
@@ -42,13 +42,13 @@ export async function handleInstallServer(params) {
|
|
|
42
42
|
let errorMessage;
|
|
43
43
|
try {
|
|
44
44
|
// Check if the client is in restricted mode
|
|
45
|
-
if (clientContext.clientMode ===
|
|
46
|
-
throw new Error(
|
|
45
|
+
if (clientContext.clientMode === "restricted") {
|
|
46
|
+
throw new Error("Install functionality is disabled in restricted mode.");
|
|
47
47
|
}
|
|
48
48
|
const { config, server_id, server_name } = params;
|
|
49
49
|
const description = params.description || server_name;
|
|
50
50
|
if (!config || !server_id || !server_name) {
|
|
51
|
-
throw new Error(
|
|
51
|
+
throw new Error("Missing required install parameters");
|
|
52
52
|
}
|
|
53
53
|
// Validate command is installed before proceeding
|
|
54
54
|
if (config.command) {
|
|
@@ -56,8 +56,8 @@ export async function handleInstallServer(params) {
|
|
|
56
56
|
}
|
|
57
57
|
// Check if server is disallowed using policy enforcer
|
|
58
58
|
policyEnforcer.enforceUseServerPolicy(server_id);
|
|
59
|
-
const runtime = config.runtime ||
|
|
60
|
-
const runtimeKey =
|
|
59
|
+
const runtime = config.runtime || "node";
|
|
60
|
+
const runtimeKey = "node";
|
|
61
61
|
const client = serverManagerClients[runtimeKey];
|
|
62
62
|
// Keep for now -- may add separate server managers for different runtimes if needed.
|
|
63
63
|
if (!client) {
|
|
@@ -68,26 +68,26 @@ export async function handleInstallServer(params) {
|
|
|
68
68
|
// After successful install, refresh the servers cache
|
|
69
69
|
await serversCache.refreshCache(serverManagerClients);
|
|
70
70
|
// List tools on the newly installed server
|
|
71
|
-
const toolsResponse = await client.sendRequest(
|
|
71
|
+
const toolsResponse = await client.sendRequest("list_tools", {
|
|
72
72
|
server_id: installResult.server_id,
|
|
73
73
|
});
|
|
74
|
-
if (
|
|
74
|
+
if ("error" in toolsResponse) {
|
|
75
75
|
throw new Error(`Failed to list tools for server_id ${installResult.server_id}, error message: ${toolsResponse.error.message}`);
|
|
76
76
|
}
|
|
77
77
|
const parsed = ListToolsResultSchema.safeParse(toolsResponse);
|
|
78
78
|
if (!parsed.success) {
|
|
79
79
|
throw new Error(`Invalid list_tools response: ${JSON.stringify(parsed.error.errors)}, response was: ${JSON.stringify(toolsResponse)}`);
|
|
80
80
|
}
|
|
81
|
-
let toolsText =
|
|
81
|
+
let toolsText = "";
|
|
82
82
|
const tools = parsed.data.tools || [];
|
|
83
83
|
if (tools.length > 0) {
|
|
84
|
-
toolsText =
|
|
84
|
+
toolsText = "Available tools from this server:\n\n";
|
|
85
85
|
for (const tool of tools) {
|
|
86
86
|
toolsText += `- ${tool.name}: ${tool.description}\n`;
|
|
87
87
|
toolsText += ` Input Schema: ${JSON.stringify(tool.inputSchema, null, 2)}\n\n`;
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
-
await telemetryLogger.log(
|
|
90
|
+
await telemetryLogger.log("client_install", {
|
|
91
91
|
success: true,
|
|
92
92
|
log_context: {
|
|
93
93
|
server_id: installResult.server_id,
|
|
@@ -96,30 +96,32 @@ export async function handleInstallServer(params) {
|
|
|
96
96
|
});
|
|
97
97
|
const content = [
|
|
98
98
|
{
|
|
99
|
-
type:
|
|
99
|
+
type: "text",
|
|
100
100
|
text: promptsCache
|
|
101
|
-
.getPrompt(
|
|
102
|
-
.replace(
|
|
103
|
-
.replace(
|
|
104
|
-
.replace(
|
|
101
|
+
.getPrompt("install_success")
|
|
102
|
+
.replace("{SERVER_ID}", installResult.server_id)
|
|
103
|
+
.replace("{SERVER_NAME}", installResult.server_name)
|
|
104
|
+
.replace("{TOOLS_LIST}", toolsText),
|
|
105
105
|
},
|
|
106
106
|
];
|
|
107
107
|
if (!clientContext.permissions.enable_read_only_mode) {
|
|
108
108
|
content.push({
|
|
109
|
-
type:
|
|
110
|
-
text: promptsCache.getPrompt(
|
|
109
|
+
type: "text",
|
|
110
|
+
text: promptsCache.getPrompt("install_next_steps"),
|
|
111
111
|
});
|
|
112
112
|
}
|
|
113
113
|
return {
|
|
114
|
-
role:
|
|
114
|
+
role: "system",
|
|
115
115
|
content,
|
|
116
116
|
};
|
|
117
117
|
}
|
|
118
118
|
catch (error) {
|
|
119
119
|
errorMessage =
|
|
120
|
-
error instanceof Error
|
|
120
|
+
error instanceof Error
|
|
121
|
+
? error.message
|
|
122
|
+
: promptsCache.getPrompt("unexpected_error");
|
|
121
123
|
await logger.error(`Installation failed: ${errorMessage}`);
|
|
122
|
-
await telemetryLogger.log(
|
|
124
|
+
await telemetryLogger.log("client_install", {
|
|
123
125
|
success: false,
|
|
124
126
|
log_context: {
|
|
125
127
|
server_id: params.server_id,
|
|
@@ -129,18 +131,20 @@ export async function handleInstallServer(params) {
|
|
|
129
131
|
});
|
|
130
132
|
const content = [
|
|
131
133
|
{
|
|
132
|
-
type:
|
|
133
|
-
text: promptsCache
|
|
134
|
+
type: "text",
|
|
135
|
+
text: promptsCache
|
|
136
|
+
.getPrompt("install_failure")
|
|
137
|
+
.replace("{ERROR}", errorMessage),
|
|
134
138
|
},
|
|
135
139
|
];
|
|
136
140
|
if (!clientContext.permissions.enable_read_only_mode) {
|
|
137
141
|
content.push({
|
|
138
|
-
type:
|
|
139
|
-
text: promptsCache.getPrompt(
|
|
142
|
+
type: "text",
|
|
143
|
+
text: promptsCache.getPrompt("install_next_steps"),
|
|
140
144
|
});
|
|
141
145
|
}
|
|
142
146
|
return {
|
|
143
|
-
role:
|
|
147
|
+
role: "system",
|
|
144
148
|
content,
|
|
145
149
|
};
|
|
146
150
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { CallToolResult } from
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
2
|
export declare function handleListServers(): Promise<CallToolResult>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { FileLogger } from
|
|
2
|
-
import { ListServersResultSchema } from
|
|
3
|
-
import Registry from
|
|
1
|
+
import { FileLogger } from "../../shared/fileLogger.js";
|
|
2
|
+
import { ListServersResultSchema } from "../../shared/serverManagerTypes.js";
|
|
3
|
+
import Registry from "../registry.js";
|
|
4
4
|
const logger = FileLogger;
|
|
5
5
|
export async function handleListServers() {
|
|
6
6
|
const startTime = Date.now();
|
|
@@ -10,12 +10,12 @@ export async function handleListServers() {
|
|
|
10
10
|
const serversCache = Registry.getServersCache();
|
|
11
11
|
const policyEnforcer = Registry.getPolicyEnforcer();
|
|
12
12
|
try {
|
|
13
|
-
await logger.debug(
|
|
14
|
-
let response =
|
|
13
|
+
await logger.debug("Listing all installed servers");
|
|
14
|
+
let response = "Currently installed MCP servers:\n\n";
|
|
15
15
|
// Collect all servers for updating the cache
|
|
16
16
|
const allServers = [];
|
|
17
17
|
for (const [runtime, client] of Object.entries(serverManagerClients)) {
|
|
18
|
-
const response_data = await client.sendRequest(
|
|
18
|
+
const response_data = await client.sendRequest("list_servers", {});
|
|
19
19
|
if (response_data.error) {
|
|
20
20
|
continue;
|
|
21
21
|
}
|
|
@@ -42,38 +42,42 @@ export async function handleListServers() {
|
|
|
42
42
|
}
|
|
43
43
|
// Update the servers cache with the fresh list
|
|
44
44
|
serversCache.updateServers(allServers);
|
|
45
|
-
if (response ===
|
|
46
|
-
response = promptsCache.getPrompt(
|
|
45
|
+
if (response === "Currently installed MCP servers:\n\n") {
|
|
46
|
+
response = promptsCache.getPrompt("list_servers_empty");
|
|
47
47
|
}
|
|
48
|
-
await logger.debug(
|
|
49
|
-
await telemetryLogger.log(
|
|
48
|
+
await logger.debug("Successfully retrieved servers list");
|
|
49
|
+
await telemetryLogger.log("client_list_servers", {
|
|
50
50
|
success: true,
|
|
51
51
|
latency_ms: Date.now() - startTime,
|
|
52
52
|
});
|
|
53
53
|
return {
|
|
54
|
-
role:
|
|
54
|
+
role: "system",
|
|
55
55
|
content: [
|
|
56
56
|
{
|
|
57
|
-
type:
|
|
57
|
+
type: "text",
|
|
58
58
|
text: response,
|
|
59
59
|
},
|
|
60
60
|
],
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
catch (error) {
|
|
64
|
-
const errorMessage = error instanceof Error
|
|
64
|
+
const errorMessage = error instanceof Error
|
|
65
|
+
? error.message
|
|
66
|
+
: promptsCache.getPrompt("unexpected_error");
|
|
65
67
|
await logger.error(`Failed to list servers: ${errorMessage}`);
|
|
66
|
-
await telemetryLogger.log(
|
|
68
|
+
await telemetryLogger.log("client_list_servers", {
|
|
67
69
|
success: false,
|
|
68
70
|
pii_sanitized_error_message: errorMessage,
|
|
69
71
|
latency_ms: Date.now() - startTime,
|
|
70
72
|
});
|
|
71
73
|
return {
|
|
72
|
-
role:
|
|
74
|
+
role: "system",
|
|
73
75
|
content: [
|
|
74
76
|
{
|
|
75
|
-
type:
|
|
76
|
-
text: promptsCache
|
|
77
|
+
type: "text",
|
|
78
|
+
text: promptsCache
|
|
79
|
+
.getPrompt("unexpected_error")
|
|
80
|
+
.replace("{ERROR}", errorMessage),
|
|
77
81
|
},
|
|
78
82
|
],
|
|
79
83
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { CallToolResult } from
|
|
2
|
-
import { ListToolplexToolsParams } from
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { ListToolplexToolsParams } from "../../shared/mcpServerTypes.js";
|
|
3
3
|
export declare function handleListTools(params: ListToolplexToolsParams): Promise<CallToolResult>;
|