@isolo/trinity 1.0.3 → 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 +45 -18
- package/src/Tools.ts +17 -11
- package/src/index.ts +4 -2
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;
|
|
@@ -51,6 +52,8 @@ export class Server {
|
|
|
51
52
|
port: this.config.port,
|
|
52
53
|
});
|
|
53
54
|
|
|
55
|
+
await this.tools.loadTools();
|
|
56
|
+
|
|
54
57
|
this.tools.startWatching();
|
|
55
58
|
|
|
56
59
|
const transport = await this.createTransport();
|
|
@@ -88,32 +91,53 @@ export class Server {
|
|
|
88
91
|
);
|
|
89
92
|
}
|
|
90
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
|
+
|
|
91
123
|
private async handleListTools() {
|
|
92
124
|
this.logger.debug("Handling list_tools request");
|
|
93
125
|
|
|
94
126
|
const toolDefs = await this.tools.loadTools();
|
|
95
127
|
|
|
96
128
|
const tools = toolDefs.map((tool) => {
|
|
97
|
-
// Convert Zod schema to JSON Schema for the MCP protocol
|
|
98
|
-
const jsonSchema = tool.inputSchema.toJSONSchema();
|
|
99
|
-
|
|
100
129
|
this.logger.debug(`Generated JSON schema for tool`, {
|
|
101
130
|
name: tool.name,
|
|
102
|
-
jsonSchema,
|
|
103
131
|
});
|
|
104
132
|
|
|
105
133
|
return {
|
|
106
134
|
name: tool.name,
|
|
107
135
|
description: tool.description,
|
|
108
|
-
inputSchema:
|
|
109
|
-
type: "object";
|
|
110
|
-
properties?: Record<string, unknown>;
|
|
111
|
-
required?: string[];
|
|
112
|
-
},
|
|
136
|
+
inputSchema: this.safeZodToJson(tool.inputSchema),
|
|
113
137
|
};
|
|
114
138
|
});
|
|
115
139
|
|
|
116
|
-
this.logger.debug(
|
|
140
|
+
this.logger.debug("Returning tools", { count: tools.length });
|
|
117
141
|
return { tools };
|
|
118
142
|
}
|
|
119
143
|
|
|
@@ -121,16 +145,16 @@ export class Server {
|
|
|
121
145
|
params: { name: string; arguments?: Record<string, unknown> };
|
|
122
146
|
}) {
|
|
123
147
|
const { name, arguments: args } = request.params;
|
|
124
|
-
this.logger.info(
|
|
148
|
+
this.logger.info("Calling tool", { name });
|
|
125
149
|
|
|
126
150
|
try {
|
|
127
151
|
const tool = await this.tools.loadTool(name);
|
|
128
152
|
const raw = await tool.execute(args || {});
|
|
129
|
-
this.logger.debug(
|
|
153
|
+
this.logger.debug("Tool executed successfully", { name, raw });
|
|
130
154
|
|
|
131
155
|
return this.formatToolResult(raw);
|
|
132
156
|
} catch (err) {
|
|
133
|
-
this.logger.error(
|
|
157
|
+
this.logger.error("Tool execution failed", { name, error: err as Error });
|
|
134
158
|
return {
|
|
135
159
|
content: [
|
|
136
160
|
{
|
|
@@ -185,7 +209,7 @@ export class Server {
|
|
|
185
209
|
return new StdioServerTransport();
|
|
186
210
|
}
|
|
187
211
|
|
|
188
|
-
this.logger.info(
|
|
212
|
+
this.logger.info("Starting HTTP server", { port: this.config.port });
|
|
189
213
|
return this.createHttpTransport();
|
|
190
214
|
}
|
|
191
215
|
|
|
@@ -217,7 +241,7 @@ export class Server {
|
|
|
217
241
|
},
|
|
218
242
|
});
|
|
219
243
|
|
|
220
|
-
this.logger.info(
|
|
244
|
+
this.logger.info("HTTP server listening", { port: this.config.port });
|
|
221
245
|
return transport;
|
|
222
246
|
}
|
|
223
247
|
|
|
@@ -234,13 +258,13 @@ export class Server {
|
|
|
234
258
|
},
|
|
235
259
|
];
|
|
236
260
|
|
|
237
|
-
this.logger.debug(
|
|
261
|
+
this.logger.debug("Returning resources", { count: resources.length });
|
|
238
262
|
return { resources };
|
|
239
263
|
}
|
|
240
264
|
|
|
241
265
|
private async handleReadResource(request: { params: { uri: string } }) {
|
|
242
266
|
const { uri } = request.params;
|
|
243
|
-
this.logger.info(
|
|
267
|
+
this.logger.info("Reading resource", { uri });
|
|
244
268
|
|
|
245
269
|
if (uri === "trinity://docs/tools") {
|
|
246
270
|
try {
|
|
@@ -257,7 +281,10 @@ export class Server {
|
|
|
257
281
|
],
|
|
258
282
|
};
|
|
259
283
|
} catch (err) {
|
|
260
|
-
this.logger.error(
|
|
284
|
+
this.logger.error("Failed to read resource", {
|
|
285
|
+
uri,
|
|
286
|
+
error: err as Error,
|
|
287
|
+
});
|
|
261
288
|
throw new Error(`Failed to read resource: ${(err as Error).message}`);
|
|
262
289
|
}
|
|
263
290
|
}
|
package/src/Tools.ts
CHANGED
|
@@ -32,20 +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
|
-
}
|
|
54
|
+
});
|
|
49
55
|
|
|
50
56
|
return tools;
|
|
51
57
|
}
|
|
@@ -69,7 +75,7 @@ export class Tools {
|
|
|
69
75
|
|
|
70
76
|
startWatching(): void {
|
|
71
77
|
const targetFolder = this.config.targetFolder;
|
|
72
|
-
this.logger.info(
|
|
78
|
+
this.logger.info("Watching for changes", { targetFolder });
|
|
73
79
|
|
|
74
80
|
this.watcher = fs.watch(
|
|
75
81
|
targetFolder,
|
|
@@ -169,7 +175,7 @@ export class Tools {
|
|
|
169
175
|
return;
|
|
170
176
|
}
|
|
171
177
|
|
|
172
|
-
this.logger.info(
|
|
178
|
+
this.logger.info("File changed", { event, filename });
|
|
173
179
|
|
|
174
180
|
if (this.onChangeCallback) {
|
|
175
181
|
this.onChangeCallback();
|
package/src/index.ts
CHANGED
|
@@ -9,8 +9,10 @@ const logger = new Logger("main");
|
|
|
9
9
|
try {
|
|
10
10
|
Config.getInstance().parse(process.argv.slice(2));
|
|
11
11
|
} catch (err) {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
logger.error((err as Error).message);
|
|
13
|
+
logger.error(
|
|
14
|
+
"Usage: bun --hot src/index.ts --target <path> [--glob <pattern>] [--port <number>]",
|
|
15
|
+
);
|
|
14
16
|
process.exit(1);
|
|
15
17
|
}
|
|
16
18
|
|