@isolo/trinity 1.0.4 → 1.0.5
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/package.json +1 -1
- package/src/Server.ts +43 -18
- package/src/Tools.ts +17 -13
package/package.json
CHANGED
package/src/Server.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { Config } from "./Config.js";
|
|
|
13
13
|
import { Logger } from "./Logger.js";
|
|
14
14
|
import { Tools } from "./Tools.js";
|
|
15
15
|
import safeJsonStringify from "json-stringify-safe";
|
|
16
|
+
import { ZodType } from "zod";
|
|
16
17
|
|
|
17
18
|
export class Server {
|
|
18
19
|
private static instance: Server | null = null;
|
|
@@ -90,32 +91,53 @@ export class Server {
|
|
|
90
91
|
);
|
|
91
92
|
}
|
|
92
93
|
|
|
94
|
+
safeZodToJson(schema: ZodType) {
|
|
95
|
+
try {
|
|
96
|
+
// Validate it's a proper Zod schema
|
|
97
|
+
if (!schema || typeof schema !== "object" || !("_zod" in schema)) {
|
|
98
|
+
this.logger.error("Invalid Zod schema: missing _zod property", {
|
|
99
|
+
schemaType: typeof schema,
|
|
100
|
+
hasZodProp: schema ? "_zod" in schema : false,
|
|
101
|
+
});
|
|
102
|
+
return {
|
|
103
|
+
type: "object",
|
|
104
|
+
properties: {},
|
|
105
|
+
description: "Invalid Zod schema: not a valid Zod schema object",
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return schema.toJSONSchema();
|
|
109
|
+
} catch (err) {
|
|
110
|
+
this.logger.error("Failed to convert Zod schema to JSON Schema", {
|
|
111
|
+
error: (err as Error).message,
|
|
112
|
+
stack: (err as Error).stack,
|
|
113
|
+
});
|
|
114
|
+
return {
|
|
115
|
+
type: "object",
|
|
116
|
+
properties: {},
|
|
117
|
+
description:
|
|
118
|
+
"Failed to convert zod schema to JSON Schema, pls check your zod schema maybe it have some problems",
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
93
123
|
private async handleListTools() {
|
|
94
124
|
this.logger.debug("Handling list_tools request");
|
|
95
125
|
|
|
96
126
|
const toolDefs = await this.tools.loadTools();
|
|
97
127
|
|
|
98
128
|
const tools = toolDefs.map((tool) => {
|
|
99
|
-
// Convert Zod schema to JSON Schema for the MCP protocol
|
|
100
|
-
const jsonSchema = tool.inputSchema.toJSONSchema();
|
|
101
|
-
|
|
102
129
|
this.logger.debug(`Generated JSON schema for tool`, {
|
|
103
130
|
name: tool.name,
|
|
104
|
-
jsonSchema,
|
|
105
131
|
});
|
|
106
132
|
|
|
107
133
|
return {
|
|
108
134
|
name: tool.name,
|
|
109
135
|
description: tool.description,
|
|
110
|
-
inputSchema:
|
|
111
|
-
type: "object";
|
|
112
|
-
properties?: Record<string, unknown>;
|
|
113
|
-
required?: string[];
|
|
114
|
-
},
|
|
136
|
+
inputSchema: this.safeZodToJson(tool.inputSchema),
|
|
115
137
|
};
|
|
116
138
|
});
|
|
117
139
|
|
|
118
|
-
this.logger.debug(
|
|
140
|
+
this.logger.debug("Returning tools", { count: tools.length });
|
|
119
141
|
return { tools };
|
|
120
142
|
}
|
|
121
143
|
|
|
@@ -123,16 +145,16 @@ export class Server {
|
|
|
123
145
|
params: { name: string; arguments?: Record<string, unknown> };
|
|
124
146
|
}) {
|
|
125
147
|
const { name, arguments: args } = request.params;
|
|
126
|
-
this.logger.info(
|
|
148
|
+
this.logger.info("Calling tool", { name });
|
|
127
149
|
|
|
128
150
|
try {
|
|
129
151
|
const tool = await this.tools.loadTool(name);
|
|
130
152
|
const raw = await tool.execute(args || {});
|
|
131
|
-
this.logger.debug(
|
|
153
|
+
this.logger.debug("Tool executed successfully", { name, raw });
|
|
132
154
|
|
|
133
155
|
return this.formatToolResult(raw);
|
|
134
156
|
} catch (err) {
|
|
135
|
-
this.logger.error(
|
|
157
|
+
this.logger.error("Tool execution failed", { name, error: err as Error });
|
|
136
158
|
return {
|
|
137
159
|
content: [
|
|
138
160
|
{
|
|
@@ -187,7 +209,7 @@ export class Server {
|
|
|
187
209
|
return new StdioServerTransport();
|
|
188
210
|
}
|
|
189
211
|
|
|
190
|
-
this.logger.info(
|
|
212
|
+
this.logger.info("Starting HTTP server", { port: this.config.port });
|
|
191
213
|
return this.createHttpTransport();
|
|
192
214
|
}
|
|
193
215
|
|
|
@@ -219,7 +241,7 @@ export class Server {
|
|
|
219
241
|
},
|
|
220
242
|
});
|
|
221
243
|
|
|
222
|
-
this.logger.info(
|
|
244
|
+
this.logger.info("HTTP server listening", { port: this.config.port });
|
|
223
245
|
return transport;
|
|
224
246
|
}
|
|
225
247
|
|
|
@@ -236,13 +258,13 @@ export class Server {
|
|
|
236
258
|
},
|
|
237
259
|
];
|
|
238
260
|
|
|
239
|
-
this.logger.debug(
|
|
261
|
+
this.logger.debug("Returning resources", { count: resources.length });
|
|
240
262
|
return { resources };
|
|
241
263
|
}
|
|
242
264
|
|
|
243
265
|
private async handleReadResource(request: { params: { uri: string } }) {
|
|
244
266
|
const { uri } = request.params;
|
|
245
|
-
this.logger.info(
|
|
267
|
+
this.logger.info("Reading resource", { uri });
|
|
246
268
|
|
|
247
269
|
if (uri === "trinity://docs/tools") {
|
|
248
270
|
try {
|
|
@@ -259,7 +281,10 @@ export class Server {
|
|
|
259
281
|
],
|
|
260
282
|
};
|
|
261
283
|
} catch (err) {
|
|
262
|
-
this.logger.error(
|
|
284
|
+
this.logger.error("Failed to read resource", {
|
|
285
|
+
uri,
|
|
286
|
+
error: err as Error,
|
|
287
|
+
});
|
|
263
288
|
throw new Error(`Failed to read resource: ${(err as Error).message}`);
|
|
264
289
|
}
|
|
265
290
|
}
|
package/src/Tools.ts
CHANGED
|
@@ -32,22 +32,26 @@ export class Tools {
|
|
|
32
32
|
|
|
33
33
|
async loadTools(): Promise<ToolDefinition[]> {
|
|
34
34
|
const files = await this.resolveToolFiles();
|
|
35
|
-
this.logger.debug(
|
|
35
|
+
this.logger.debug("Resolved tool files", { count: files.length });
|
|
36
|
+
|
|
37
|
+
// Load all tools in parallel
|
|
38
|
+
const toolPromises = files.map((filePath) =>
|
|
39
|
+
this.loadToolFromFile(filePath),
|
|
40
|
+
);
|
|
41
|
+
const results = await Promise.allSettled(toolPromises);
|
|
36
42
|
|
|
37
43
|
const tools: ToolDefinition[] = [];
|
|
38
44
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
err:
|
|
45
|
+
results.forEach((result, index) => {
|
|
46
|
+
if (result.status === "fulfilled") {
|
|
47
|
+
tools.push(result.value);
|
|
48
|
+
} else {
|
|
49
|
+
this.logger.error(`Failed to load tool`, {
|
|
50
|
+
file: files[index],
|
|
51
|
+
err: result.reason?.message || result.reason,
|
|
46
52
|
});
|
|
47
53
|
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
this.logger.debug(`Loaded ${tools.length} tools successfully`);
|
|
54
|
+
});
|
|
51
55
|
|
|
52
56
|
return tools;
|
|
53
57
|
}
|
|
@@ -71,7 +75,7 @@ export class Tools {
|
|
|
71
75
|
|
|
72
76
|
startWatching(): void {
|
|
73
77
|
const targetFolder = this.config.targetFolder;
|
|
74
|
-
this.logger.info(
|
|
78
|
+
this.logger.info("Watching for changes", { targetFolder });
|
|
75
79
|
|
|
76
80
|
this.watcher = fs.watch(
|
|
77
81
|
targetFolder,
|
|
@@ -171,7 +175,7 @@ export class Tools {
|
|
|
171
175
|
return;
|
|
172
176
|
}
|
|
173
177
|
|
|
174
|
-
this.logger.info(
|
|
178
|
+
this.logger.info("File changed", { event, filename });
|
|
175
179
|
|
|
176
180
|
if (this.onChangeCallback) {
|
|
177
181
|
this.onChangeCallback();
|