@toolplex/client 0.1.4 → 0.1.6

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.
@@ -11,7 +11,6 @@ export async function handleListServers() {
11
11
  const policyEnforcer = Registry.getPolicyEnforcer();
12
12
  try {
13
13
  await logger.debug("Listing all installed servers");
14
- let response = "Currently installed MCP servers:\n\n";
15
14
  // Collect all servers for updating the cache
16
15
  const allServers = [];
17
16
  for (const [runtime, client] of Object.entries(serverManagerClients)) {
@@ -28,10 +27,7 @@ export async function handleListServers() {
28
27
  // Filter out blocked servers
29
28
  const filteredServers = policyEnforcer.filterBlockedMcpServers(parsed.data.servers, (server) => server.server_id);
30
29
  filteredServers.forEach((server) => {
31
- response += `- Server ID: ${server.server_id}\n`;
32
- response += ` Name: ${server.server_name}\n`;
33
- response += ` Description: ${server.description}\n\n`;
34
- // Add to allServers for cache update
30
+ // Add to allServers for cache update and structured response
35
31
  allServers.push({
36
32
  server_id: server.server_id,
37
33
  server_name: server.server_name,
@@ -42,20 +38,36 @@ export async function handleListServers() {
42
38
  }
43
39
  // Update the servers cache with the fresh list
44
40
  serversCache.updateServers(allServers);
45
- if (response === "Currently installed MCP servers:\n\n") {
46
- response = promptsCache.getPrompt("list_servers_empty");
47
- }
48
41
  await logger.debug("Successfully retrieved servers list");
49
42
  await telemetryLogger.log("client_list_servers", {
50
43
  success: true,
51
44
  latency_ms: Date.now() - startTime,
52
45
  });
46
+ // Build response content
47
+ if (allServers.length === 0) {
48
+ return {
49
+ role: "system",
50
+ content: [
51
+ {
52
+ type: "text",
53
+ text: promptsCache.getPrompt("list_servers_empty"),
54
+ },
55
+ ],
56
+ };
57
+ }
53
58
  return {
54
59
  role: "system",
55
60
  content: [
56
61
  {
57
62
  type: "text",
58
- text: response,
63
+ text: JSON.stringify({
64
+ servers: allServers,
65
+ count: allServers.length,
66
+ }),
67
+ },
68
+ {
69
+ type: "text",
70
+ text: `Found ${allServers.length} installed MCP server${allServers.length !== 1 ? "s" : ""}`,
59
71
  },
60
72
  ],
61
73
  };
@@ -11,7 +11,7 @@ export async function handleListTools(params) {
11
11
  const policyEnforcer = Registry.getPolicyEnforcer();
12
12
  try {
13
13
  const server_id = params.server_id;
14
- let response = "";
14
+ const content = [];
15
15
  if (server_id) {
16
16
  // Check if server is blocked using policy enforcer
17
17
  policyEnforcer.enforceUseServerPolicy(server_id);
@@ -27,23 +27,34 @@ export async function handleListTools(params) {
27
27
  if (!parsed.success) {
28
28
  throw new Error(`Invalid response from server manager: ${parsed.error}`);
29
29
  }
30
- response = promptsCache
31
- .getPrompt("list_tools_server_header")
32
- .replace("{SERVER_ID}", parsed.data.server_id)
33
- .replace("{SERVER_NAME}", parsed.data.server_name);
34
- if (!parsed.data.tools || parsed.data.tools.length === 0) {
35
- response += promptsCache.getPrompt("list_tools_empty");
30
+ const tools = parsed.data.tools || [];
31
+ if (tools.length > 0) {
32
+ // First: Structured JSON for easy parsing
33
+ content.push({
34
+ type: "text",
35
+ text: JSON.stringify({
36
+ server_id: parsed.data.server_id,
37
+ server_name: parsed.data.server_name,
38
+ tools: tools,
39
+ tool_count: tools.length,
40
+ }),
41
+ });
42
+ // Second: Human-readable summary
43
+ content.push({
44
+ type: "text",
45
+ text: `Available tools from server '${parsed.data.server_name}' (${parsed.data.server_id}): ${tools.length} tool${tools.length !== 1 ? "s" : ""}`,
46
+ });
36
47
  }
37
48
  else {
38
- parsed.data.tools.forEach((tool) => {
39
- response += `- ${tool.name}: ${tool.description}\n`;
40
- response += ` Input Schema: ${JSON.stringify(tool.inputSchema, null, 2)}\n\n`;
49
+ content.push({
50
+ type: "text",
51
+ text: promptsCache.getPrompt("list_tools_empty"),
41
52
  });
42
53
  }
43
54
  }
44
55
  else {
45
56
  await logger.debug("Listing tools from all installed servers");
46
- response = promptsCache.getPrompt("list_tools_all_header");
57
+ const allServerTools = [];
47
58
  for (const [runtime, client] of Object.entries(serverManagerClients)) {
48
59
  const response_data = await client.sendRequest("list_all_tools", {});
49
60
  if (response_data.error) {
@@ -59,17 +70,35 @@ export async function handleListTools(params) {
59
70
  const filteredEntries = policyEnforcer.filterBlockedMcpServers(serverEntries, ([serverId]) => serverId);
60
71
  for (const [serverId, serverTools] of filteredEntries) {
61
72
  if (serverTools && serverTools.length > 0) {
62
- response += `Server: ${serverId}\n`;
63
- serverTools.forEach((tool) => {
64
- response += `- ${tool.name}: ${tool.description}\n`;
65
- response += ` Input Schema: ${JSON.stringify(tool.inputSchema, null, 2)}\n\n`;
73
+ allServerTools.push({
74
+ server_id: serverId,
75
+ tools: serverTools,
66
76
  });
67
- response += "\n";
68
77
  }
69
78
  }
70
79
  }
71
- if (response === promptsCache.getPrompt("list_tools_all_header")) {
72
- response += promptsCache.getPrompt("list_tools_empty");
80
+ if (allServerTools.length > 0) {
81
+ const totalTools = allServerTools.reduce((sum, server) => sum + server.tools.length, 0);
82
+ // First: Structured JSON for easy parsing
83
+ content.push({
84
+ type: "text",
85
+ text: JSON.stringify({
86
+ server_tools: allServerTools,
87
+ server_count: allServerTools.length,
88
+ total_tools: totalTools,
89
+ }),
90
+ });
91
+ // Second: Human-readable summary
92
+ content.push({
93
+ type: "text",
94
+ text: `Found ${totalTools} tools across ${allServerTools.length} server${allServerTools.length !== 1 ? "s" : ""}`,
95
+ });
96
+ }
97
+ else {
98
+ content.push({
99
+ type: "text",
100
+ text: promptsCache.getPrompt("list_tools_empty"),
101
+ });
73
102
  }
74
103
  }
75
104
  await logger.debug("Successfully retrieved tools list");
@@ -82,12 +111,7 @@ export async function handleListTools(params) {
82
111
  });
83
112
  return {
84
113
  role: "system",
85
- content: [
86
- {
87
- type: "text",
88
- text: response,
89
- },
90
- ],
114
+ content,
91
115
  };
92
116
  }
93
117
  catch (error) {
@@ -21,6 +21,20 @@ export async function handleLookupEntityTool(params) {
21
21
  policyEnforcer.enforceUseServerPolicy(params.entity_id);
22
22
  }
23
23
  let lookupResponse = await apiService.lookupEntity(params.entity_type, params.entity_id);
24
+ // Annotate installed server using resultAnnotators
25
+ if (params.entity_type === "server" &&
26
+ lookupResponse &&
27
+ typeof lookupResponse === "object" &&
28
+ lookupResponse.result &&
29
+ typeof lookupResponse.result === "object") {
30
+ try {
31
+ lookupResponse.result = annotateInstalledServer(lookupResponse.result, serversCache);
32
+ }
33
+ catch (err) {
34
+ await logger.warn(`Error annotating installed server: ${err}`);
35
+ // fallback: do not annotate
36
+ }
37
+ }
24
38
  if (!lookupResponse) {
25
39
  await logger.debug("No entity found");
26
40
  await telemetryLogger.log("client_lookup_entity", {
@@ -44,22 +58,7 @@ export async function handleLookupEntityTool(params) {
44
58
  ],
45
59
  };
46
60
  }
47
- // Use resultAnnotators to annotate if the server is installed
48
- if (params.entity_type === "server" &&
49
- lookupResponse &&
50
- typeof lookupResponse === "object") {
51
- try {
52
- lookupResponse = annotateInstalledServer(lookupResponse, serversCache);
53
- }
54
- catch (err) {
55
- await logger.warn(`Error annotating installed server: ${err}`);
56
- // fallback: do not annotate
57
- }
58
- }
59
61
  await logger.debug(`Found entity: ${JSON.stringify(lookupResponse)}`);
60
- let response = `Found ${params.entity_type}:\n`;
61
- response += JSON.stringify(lookupResponse, null, 2);
62
- response += "\n";
63
62
  await logger.debug("Lookup completed successfully");
64
63
  await telemetryLogger.log("client_lookup_entity", {
65
64
  success: true,
@@ -69,10 +68,21 @@ export async function handleLookupEntityTool(params) {
69
68
  },
70
69
  latency_ms: Date.now() - startTime,
71
70
  });
71
+ // Return structured data first for easy frontend parsing, then instructions
72
72
  const content = [
73
+ // First: Structured JSON for easy parsing
74
+ {
75
+ type: "text",
76
+ text: JSON.stringify({
77
+ entity_type: params.entity_type,
78
+ entity_id: params.entity_id,
79
+ result: lookupResponse,
80
+ }),
81
+ },
82
+ // Second: Human-readable summary
73
83
  {
74
84
  type: "text",
75
- text: response,
85
+ text: `Found ${params.entity_type}: ${lookupResponse.server_name || lookupResponse.description || params.entity_id}`,
76
86
  },
77
87
  ];
78
88
  if (params.entity_type === "server") {
@@ -65,32 +65,34 @@ export async function handleSearchTool(params) {
65
65
  };
66
66
  }
67
67
  await logger.debug(`Found ${totalResults} results`);
68
- let response = promptsCache.getPrompt("search_results_header");
69
- if ((annotatedServers.length ?? 0) > 0) {
70
- response += "\n=== Servers ===\n";
71
- response += JSON.stringify(annotatedServers, null, 2);
72
- response += "\n";
73
- }
74
- else {
75
- response += "\n(No servers found)\n";
76
- }
77
- if (playbooks.length > 0) {
78
- response += "\n=== Playbooks ===\n";
79
- response += JSON.stringify(playbooks, null, 2);
80
- response += "\n";
81
- }
82
- else {
83
- response += "\n(No playbooks found)\n";
84
- }
68
+ // Build structured response content
69
+ const content = [
70
+ // First: Structured JSON for easy parsing
71
+ {
72
+ type: "text",
73
+ text: JSON.stringify({
74
+ query,
75
+ expanded_keywords: expandedKeywords,
76
+ filter,
77
+ scope,
78
+ size,
79
+ servers: annotatedServers,
80
+ playbooks,
81
+ server_count: annotatedServers.length,
82
+ playbook_count: playbooks.length,
83
+ total_results: totalResults,
84
+ }),
85
+ },
86
+ // Second: Human-readable summary
87
+ {
88
+ type: "text",
89
+ text: `Found ${totalResults} results for "${query}": ${annotatedServers.length} servers, ${playbooks.length} playbooks`,
90
+ },
91
+ ];
85
92
  await logger.info("Search completed successfully");
86
93
  return {
87
94
  role: "system",
88
- content: [
89
- {
90
- type: "text",
91
- text: response,
92
- },
93
- ],
95
+ content,
94
96
  };
95
97
  }
96
98
  catch (error) {
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "0.1.4";
1
+ export declare const version = "0.1.6";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '0.1.4';
1
+ export const version = '0.1.6';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toolplex/client",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
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",