touchdesigner-mcp-server 1.2.0 → 1.3.1
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/README.ja.md +46 -0
- package/README.md +46 -0
- package/dist/cli.js +1 -1
- package/dist/core/compatibility.js +236 -0
- package/dist/core/constants.js +5 -3
- package/dist/core/errorHandling.js +18 -3
- package/dist/core/logger.js +17 -32
- package/dist/core/result.js +2 -2
- package/dist/core/version.js +24 -0
- package/dist/features/prompts/handlers/td_prompts.js +24 -18
- package/dist/features/tools/handlers/tdTools.js +75 -18
- package/dist/features/tools/metadata/touchDesignerToolMetadata.js +246 -172
- package/dist/features/tools/presenter/classListFormatter.js +22 -22
- package/dist/features/tools/presenter/index.js +2 -0
- package/dist/features/tools/presenter/moduleHelpFormatter.js +315 -0
- package/dist/features/tools/presenter/nodeDetailsFormatter.js +17 -17
- package/dist/features/tools/presenter/nodeErrorsFormatter.js +68 -0
- package/dist/features/tools/presenter/nodeListFormatter.js +12 -12
- package/dist/features/tools/presenter/operationFormatter.js +26 -19
- package/dist/features/tools/presenter/responseFormatter.js +4 -4
- package/dist/features/tools/presenter/scriptResultFormatter.js +14 -14
- package/dist/features/tools/presenter/toolMetadataFormatter.js +8 -8
- package/dist/gen/endpoints/TouchDesignerAPI.js +22 -4
- package/dist/gen/mcp/touchDesignerAPI.zod.js +52 -12
- package/dist/server/connectionManager.js +11 -28
- package/dist/server/touchDesignerServer.js +4 -3
- package/dist/tdClient/touchDesignerClient.js +267 -46
- package/package.json +31 -17
|
@@ -1,27 +1,31 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { getCompatibilityPolicy, getCompatibilityPolicyType, } from "../core/compatibility.js";
|
|
3
|
+
import { createErrorResult, createSuccessResult } from "../core/result.js";
|
|
4
|
+
import { MCP_SERVER_VERSION, MIN_COMPATIBLE_API_VERSION, } from "../core/version.js";
|
|
5
|
+
import { createNode as apiCreateNode, deleteNode as apiDeleteNode, execNodeMethod as apiExecNodeMethod, execPythonScript as apiExecPythonScript, getModuleHelp as apiGetModuleHelp, getNodeDetail as apiGetNodeDetail, getNodeErrors as apiGetNodeErrors, getNodes as apiGetNodes, getTdInfo as apiGetTdInfo, getTdPythonClassDetails as apiGetTdPythonClassDetails, getTdPythonClasses as apiGetTdPythonClasses, updateNode as apiUpdateNode, } from "../gen/endpoints/TouchDesignerAPI.js";
|
|
2
6
|
/**
|
|
3
7
|
* Default implementation of ITouchDesignerApi using generated API clients
|
|
4
8
|
*/
|
|
5
9
|
const defaultApiClient = {
|
|
10
|
+
createNode: apiCreateNode,
|
|
11
|
+
deleteNode: apiDeleteNode,
|
|
6
12
|
execNodeMethod: apiExecNodeMethod,
|
|
7
13
|
execPythonScript: apiExecPythonScript,
|
|
8
|
-
|
|
9
|
-
getNodes: apiGetNodes,
|
|
14
|
+
getModuleHelp: apiGetModuleHelp,
|
|
10
15
|
getNodeDetail: apiGetNodeDetail,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
getTdPythonClasses: apiGetTdPythonClasses,
|
|
16
|
+
getNodeErrors: apiGetNodeErrors,
|
|
17
|
+
getNodes: apiGetNodes,
|
|
18
|
+
getTdInfo: apiGetTdInfo,
|
|
15
19
|
getTdPythonClassDetails: apiGetTdPythonClassDetails,
|
|
20
|
+
getTdPythonClasses: apiGetTdPythonClasses,
|
|
21
|
+
updateNode: apiUpdateNode,
|
|
16
22
|
};
|
|
23
|
+
export const ERROR_CACHE_TTL_MS = 5000; // 5 seconds
|
|
17
24
|
/**
|
|
18
25
|
* Null logger implementation that discards all logs
|
|
19
26
|
*/
|
|
20
27
|
const nullLogger = {
|
|
21
|
-
|
|
22
|
-
log: () => { },
|
|
23
|
-
warn: () => { },
|
|
24
|
-
error: () => { },
|
|
28
|
+
sendLog: () => { },
|
|
25
29
|
};
|
|
26
30
|
/**
|
|
27
31
|
* Handle API error response
|
|
@@ -31,9 +35,9 @@ const nullLogger = {
|
|
|
31
35
|
function handleError(response) {
|
|
32
36
|
if (response.error) {
|
|
33
37
|
const errorMessage = response.error;
|
|
34
|
-
return {
|
|
38
|
+
return { error: new Error(errorMessage), success: false };
|
|
35
39
|
}
|
|
36
|
-
return {
|
|
40
|
+
return { error: new Error("Unknown error occurred"), success: false };
|
|
37
41
|
}
|
|
38
42
|
/**
|
|
39
43
|
* Handle API response and return a structured result
|
|
@@ -46,12 +50,12 @@ function handleApiResponse(response) {
|
|
|
46
50
|
return handleError(response);
|
|
47
51
|
}
|
|
48
52
|
if (data === null) {
|
|
49
|
-
return {
|
|
53
|
+
return { error: new Error("No data received"), success: false };
|
|
50
54
|
}
|
|
51
55
|
if (data === undefined) {
|
|
52
|
-
return {
|
|
56
|
+
return { error: new Error("No data received"), success: false };
|
|
53
57
|
}
|
|
54
|
-
return { success: true
|
|
58
|
+
return { data, success: true };
|
|
55
59
|
}
|
|
56
60
|
/**
|
|
57
61
|
* TouchDesigner client implementation with dependency injection
|
|
@@ -60,91 +64,308 @@ function handleApiResponse(response) {
|
|
|
60
64
|
export class TouchDesignerClient {
|
|
61
65
|
logger;
|
|
62
66
|
api;
|
|
67
|
+
verifiedCompatibilityError;
|
|
68
|
+
cachedCompatibilityCheck;
|
|
69
|
+
errorCacheTimestamp;
|
|
63
70
|
/**
|
|
64
71
|
* Initialize TouchDesigner client with optional dependencies
|
|
65
72
|
*/
|
|
66
73
|
constructor(params = {}) {
|
|
67
74
|
this.logger = params.logger || nullLogger;
|
|
68
75
|
this.api = params.httpClient || defaultApiClient;
|
|
76
|
+
this.verifiedCompatibilityError = null;
|
|
77
|
+
this.cachedCompatibilityCheck = false;
|
|
78
|
+
this.errorCacheTimestamp = null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Log debug message
|
|
82
|
+
*/
|
|
83
|
+
logDebug(message, context) {
|
|
84
|
+
const data = context ? { message, ...context } : { message };
|
|
85
|
+
this.logger.sendLog({
|
|
86
|
+
data,
|
|
87
|
+
level: "debug",
|
|
88
|
+
logger: "TouchDesignerClient",
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Check if the cached error should be cleared (TTL expired)
|
|
93
|
+
*/
|
|
94
|
+
shouldClearErrorCache() {
|
|
95
|
+
if (!this.errorCacheTimestamp) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
const now = Date.now();
|
|
99
|
+
return now - this.errorCacheTimestamp >= ERROR_CACHE_TTL_MS;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Verify compatibility with the TouchDesigner server
|
|
103
|
+
*/
|
|
104
|
+
async verifyCompatibility() {
|
|
105
|
+
// If we've already verified compatibility successfully, skip re-verification
|
|
106
|
+
if (this.cachedCompatibilityCheck && !this.verifiedCompatibilityError) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// Clear cached error if TTL has expired
|
|
110
|
+
if (this.verifiedCompatibilityError && this.shouldClearErrorCache()) {
|
|
111
|
+
this.logDebug("Clearing cached connection error (TTL expired), retrying...");
|
|
112
|
+
this.verifiedCompatibilityError = null;
|
|
113
|
+
this.errorCacheTimestamp = null;
|
|
114
|
+
this.cachedCompatibilityCheck = false;
|
|
115
|
+
}
|
|
116
|
+
if (this.verifiedCompatibilityError) {
|
|
117
|
+
// Re-log the cached error so users know it's still failing
|
|
118
|
+
const ttlRemaining = this.errorCacheTimestamp
|
|
119
|
+
? Math.max(0, Math.ceil((ERROR_CACHE_TTL_MS - (Date.now() - this.errorCacheTimestamp)) /
|
|
120
|
+
1000))
|
|
121
|
+
: 0;
|
|
122
|
+
this.logDebug(`Using cached connection error (retry in ${ttlRemaining} seconds)`, {
|
|
123
|
+
cacheAge: this.errorCacheTimestamp
|
|
124
|
+
? Date.now() - this.errorCacheTimestamp
|
|
125
|
+
: 0,
|
|
126
|
+
cachedError: this.verifiedCompatibilityError.message,
|
|
127
|
+
});
|
|
128
|
+
throw this.verifiedCompatibilityError;
|
|
129
|
+
}
|
|
130
|
+
const result = await this.verifyVersionCompatibility();
|
|
131
|
+
if (result.success) {
|
|
132
|
+
this.verifiedCompatibilityError = null;
|
|
133
|
+
this.errorCacheTimestamp = null;
|
|
134
|
+
this.cachedCompatibilityCheck = true;
|
|
135
|
+
this.logDebug("Compatibility verified successfully");
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
// Log when we're caching a NEW error
|
|
139
|
+
this.logDebug(`Caching connection error for ${ERROR_CACHE_TTL_MS / 1000} seconds`, {
|
|
140
|
+
error: result.error.message,
|
|
141
|
+
});
|
|
142
|
+
this.verifiedCompatibilityError = result.error;
|
|
143
|
+
this.errorCacheTimestamp = Date.now();
|
|
144
|
+
this.cachedCompatibilityCheck = false;
|
|
145
|
+
throw result.error;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Wrapper for API calls that require compatibility verification
|
|
149
|
+
* @private
|
|
150
|
+
*/
|
|
151
|
+
async apiCall(message, call, context) {
|
|
152
|
+
this.logDebug(message, context);
|
|
153
|
+
await this.verifyCompatibility();
|
|
154
|
+
const result = await call();
|
|
155
|
+
return handleApiResponse(result);
|
|
69
156
|
}
|
|
70
157
|
/**
|
|
71
158
|
* Execute a node method
|
|
72
159
|
*/
|
|
73
160
|
async execNodeMethod(params) {
|
|
74
|
-
this.
|
|
75
|
-
|
|
76
|
-
|
|
161
|
+
return this.apiCall("Executing node method", () => this.api.execNodeMethod(params), {
|
|
162
|
+
method: params.method,
|
|
163
|
+
nodePath: params.nodePath,
|
|
164
|
+
});
|
|
77
165
|
}
|
|
78
166
|
/**
|
|
79
167
|
* Execute a script in TouchDesigner
|
|
80
168
|
*/
|
|
81
169
|
async execPythonScript(params) {
|
|
82
|
-
this.
|
|
83
|
-
const result = await this.api.execPythonScript(params);
|
|
84
|
-
return handleApiResponse(result);
|
|
170
|
+
return this.apiCall("Executing Python script", () => this.api.execPythonScript(params), { params });
|
|
85
171
|
}
|
|
86
172
|
/**
|
|
87
173
|
* Get TouchDesigner server information
|
|
88
174
|
*/
|
|
89
175
|
async getTdInfo() {
|
|
90
|
-
this.
|
|
91
|
-
const result = await this.api.getTdInfo();
|
|
92
|
-
return handleApiResponse(result);
|
|
176
|
+
return this.apiCall("Getting server info", () => this.api.getTdInfo());
|
|
93
177
|
}
|
|
94
178
|
/**
|
|
95
179
|
* Get list of nodes
|
|
96
180
|
*/
|
|
97
181
|
async getNodes(params) {
|
|
98
|
-
this.
|
|
99
|
-
const result = await this.api.getNodes(params);
|
|
100
|
-
return handleApiResponse(result);
|
|
182
|
+
return this.apiCall("Getting nodes for parent", () => this.api.getNodes(params), { parentPath: params.parentPath });
|
|
101
183
|
}
|
|
102
184
|
/**
|
|
103
185
|
* Get node properties
|
|
104
186
|
*/
|
|
105
187
|
async getNodeDetail(params) {
|
|
106
|
-
this.
|
|
107
|
-
|
|
108
|
-
|
|
188
|
+
return this.apiCall("Getting properties for node", () => this.api.getNodeDetail(params), { nodePath: params.nodePath });
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get node error information
|
|
192
|
+
*/
|
|
193
|
+
async getNodeErrors(params) {
|
|
194
|
+
return this.apiCall("Checking node errors", () => this.api.getNodeErrors(params), { nodePath: params.nodePath });
|
|
109
195
|
}
|
|
110
196
|
/**
|
|
111
197
|
* Create a new node
|
|
112
198
|
*/
|
|
113
199
|
async createNode(params) {
|
|
114
|
-
this.
|
|
115
|
-
|
|
116
|
-
|
|
200
|
+
return this.apiCall("Creating node", () => this.api.createNode(params), {
|
|
201
|
+
nodeName: params.nodeName,
|
|
202
|
+
nodeType: params.nodeType,
|
|
203
|
+
parentPath: params.parentPath,
|
|
204
|
+
});
|
|
117
205
|
}
|
|
118
206
|
/**
|
|
119
207
|
* Update node properties
|
|
120
208
|
*/
|
|
121
209
|
async updateNode(params) {
|
|
122
|
-
this.
|
|
123
|
-
|
|
124
|
-
|
|
210
|
+
return this.apiCall("Updating node", () => this.api.updateNode(params), {
|
|
211
|
+
nodePath: params.nodePath,
|
|
212
|
+
});
|
|
125
213
|
}
|
|
126
214
|
/**
|
|
127
215
|
* Delete a node
|
|
128
216
|
*/
|
|
129
217
|
async deleteNode(params) {
|
|
130
|
-
this.
|
|
131
|
-
|
|
132
|
-
|
|
218
|
+
return this.apiCall("Deleting node", () => this.api.deleteNode(params), {
|
|
219
|
+
nodePath: params.nodePath,
|
|
220
|
+
});
|
|
133
221
|
}
|
|
134
222
|
/**
|
|
135
223
|
* Get list of available Python classes/modules in TouchDesigner
|
|
136
224
|
*/
|
|
137
225
|
async getClasses() {
|
|
138
|
-
this.
|
|
139
|
-
const result = await this.api.getTdPythonClasses();
|
|
140
|
-
return handleApiResponse(result);
|
|
226
|
+
return this.apiCall("Getting Python classes", () => this.api.getTdPythonClasses());
|
|
141
227
|
}
|
|
142
228
|
/**
|
|
143
229
|
* Get details of a specific class/module
|
|
144
230
|
*/
|
|
145
231
|
async getClassDetails(className) {
|
|
146
|
-
this.
|
|
147
|
-
|
|
148
|
-
|
|
232
|
+
return this.apiCall("Getting class details", () => this.api.getTdPythonClassDetails(className), { className });
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Retrieve Python help() documentation for modules/classes
|
|
236
|
+
*/
|
|
237
|
+
async getModuleHelp(params) {
|
|
238
|
+
return this.apiCall("Getting module help", () => this.api.getModuleHelp(params), { moduleName: params.moduleName });
|
|
239
|
+
}
|
|
240
|
+
async verifyVersionCompatibility() {
|
|
241
|
+
let tdInfoResult;
|
|
242
|
+
try {
|
|
243
|
+
tdInfoResult = await this.api.getTdInfo();
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
// Use axios.isAxiosError() for robust network/HTTP error detection
|
|
247
|
+
// AxiosError includes connection refused, timeout, network errors, etc.
|
|
248
|
+
// All other errors (TypeError, etc.) are programming errors and should propagate
|
|
249
|
+
if (!axios.isAxiosError(error)) {
|
|
250
|
+
// This is a programming error (e.g., TypeError, ReferenceError), not a connection error
|
|
251
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
252
|
+
const errorStack = error instanceof Error ? error.stack : undefined;
|
|
253
|
+
this.logger.sendLog({
|
|
254
|
+
data: {
|
|
255
|
+
error: errorMessage,
|
|
256
|
+
errorType: "programming_error",
|
|
257
|
+
stack: errorStack,
|
|
258
|
+
},
|
|
259
|
+
level: "error",
|
|
260
|
+
logger: "TouchDesignerClient",
|
|
261
|
+
});
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
// Handle AxiosError (network/HTTP errors)
|
|
265
|
+
const rawMessage = error.message || "Unknown network error";
|
|
266
|
+
const errorMessage = this.formatConnectionError(rawMessage);
|
|
267
|
+
this.logger.sendLog({
|
|
268
|
+
data: { error: rawMessage, errorType: "connection" },
|
|
269
|
+
level: "error",
|
|
270
|
+
logger: "TouchDesignerClient",
|
|
271
|
+
});
|
|
272
|
+
return createErrorResult(new Error(errorMessage));
|
|
273
|
+
}
|
|
274
|
+
if (!tdInfoResult.success) {
|
|
275
|
+
const errorMessage = this.formatConnectionError(tdInfoResult.error);
|
|
276
|
+
this.logger.sendLog({
|
|
277
|
+
data: { error: tdInfoResult.error, errorType: "api_response" },
|
|
278
|
+
level: "error",
|
|
279
|
+
logger: "TouchDesignerClient",
|
|
280
|
+
});
|
|
281
|
+
return createErrorResult(new Error(errorMessage));
|
|
282
|
+
}
|
|
283
|
+
const apiVersionRaw = tdInfoResult.data?.mcpApiVersion?.trim() || "";
|
|
284
|
+
const result = this.checkVersionCompatibility(MCP_SERVER_VERSION, apiVersionRaw);
|
|
285
|
+
this.logger.sendLog({
|
|
286
|
+
data: {
|
|
287
|
+
apiVersion: result.details.apiVersion,
|
|
288
|
+
mcpVersion: result.details.mcpVersion,
|
|
289
|
+
message: result.message,
|
|
290
|
+
minRequired: result.details.minRequired,
|
|
291
|
+
},
|
|
292
|
+
level: result.level,
|
|
293
|
+
logger: "TouchDesignerClient",
|
|
294
|
+
});
|
|
295
|
+
if (result.level === "error") {
|
|
296
|
+
return createErrorResult(new Error(result.message));
|
|
297
|
+
}
|
|
298
|
+
return createSuccessResult(undefined);
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Format connection errors with helpful messages
|
|
302
|
+
*/
|
|
303
|
+
formatConnectionError(error) {
|
|
304
|
+
if (!error) {
|
|
305
|
+
return "Failed to connect to TouchDesigner API server (unknown error)";
|
|
306
|
+
}
|
|
307
|
+
// Check for common connection errors
|
|
308
|
+
if (error.includes("ECONNREFUSED") ||
|
|
309
|
+
error.toLowerCase().includes("connect refused")) {
|
|
310
|
+
return `🔌 TouchDesigner Connection Failed
|
|
311
|
+
|
|
312
|
+
Cannot connect to TouchDesigner API server at the configured address.
|
|
313
|
+
|
|
314
|
+
Possible causes:
|
|
315
|
+
1. TouchDesigner is not running
|
|
316
|
+
→ Please start TouchDesigner
|
|
317
|
+
|
|
318
|
+
2. WebServer DAT is not active
|
|
319
|
+
→ Import 'mcp_webserver_base.tox' and ensure it's active
|
|
320
|
+
|
|
321
|
+
3. Wrong port configuration
|
|
322
|
+
→ Default port is 9981, check your configuration
|
|
323
|
+
|
|
324
|
+
For setup instructions, visit:
|
|
325
|
+
https://github.com/8beeeaaat/touchdesigner-mcp/releases/latest
|
|
326
|
+
|
|
327
|
+
Original error: ${error}`;
|
|
328
|
+
}
|
|
329
|
+
if (error.includes("ETIMEDOUT") || error.includes("timeout")) {
|
|
330
|
+
return `⏱️ TouchDesigner Connection Timeout
|
|
331
|
+
|
|
332
|
+
The connection to TouchDesigner timed out.
|
|
333
|
+
|
|
334
|
+
Possible causes:
|
|
335
|
+
1. TouchDesigner is slow to respond
|
|
336
|
+
2. Network issues
|
|
337
|
+
3. WebServer DAT is overloaded
|
|
338
|
+
|
|
339
|
+
Try restarting TouchDesigner or check the network connection.
|
|
340
|
+
|
|
341
|
+
Original error: ${error}`;
|
|
342
|
+
}
|
|
343
|
+
if (error.includes("ENOTFOUND") || error.includes("getaddrinfo")) {
|
|
344
|
+
return `🌐 Invalid Host Configuration
|
|
345
|
+
|
|
346
|
+
Cannot resolve the TouchDesigner API server hostname.
|
|
347
|
+
|
|
348
|
+
Please check your host configuration (default: 127.0.0.1)
|
|
349
|
+
|
|
350
|
+
Original error: ${error}`;
|
|
351
|
+
}
|
|
352
|
+
// Generic error message
|
|
353
|
+
return `Failed to connect to TouchDesigner API server: ${error}`;
|
|
354
|
+
}
|
|
355
|
+
checkVersionCompatibility(mcpVersion, apiVersion) {
|
|
356
|
+
const policyType = getCompatibilityPolicyType({ apiVersion, mcpVersion });
|
|
357
|
+
const policy = getCompatibilityPolicy(policyType);
|
|
358
|
+
const details = {
|
|
359
|
+
apiVersion,
|
|
360
|
+
mcpVersion,
|
|
361
|
+
minRequired: MIN_COMPATIBLE_API_VERSION,
|
|
362
|
+
};
|
|
363
|
+
const message = policy.message(details);
|
|
364
|
+
return {
|
|
365
|
+
compatible: policy.compatible,
|
|
366
|
+
details,
|
|
367
|
+
level: policy.level,
|
|
368
|
+
message,
|
|
369
|
+
};
|
|
149
370
|
}
|
|
150
371
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "touchdesigner-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "MCP server for TouchDesigner",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
"author": "8beeeaaat",
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"mcpName": "io.github.8beeeaaat/touchdesigner-mcp-server",
|
|
16
|
+
"mcpCompatibility": {
|
|
17
|
+
"minApiVersion": "1.3.0"
|
|
18
|
+
},
|
|
16
19
|
"bugs": {
|
|
17
20
|
"url": "https://github.com/8beeeaaat/touchdesigner-mcp/issues"
|
|
18
21
|
},
|
|
@@ -23,30 +26,33 @@
|
|
|
23
26
|
"touchdesigner-mcp-server": "dist/cli.js"
|
|
24
27
|
},
|
|
25
28
|
"dependencies": {
|
|
26
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
29
|
+
"@modelcontextprotocol/sdk": "^1.24.3",
|
|
27
30
|
"@mozilla/readability": "^0.6.0",
|
|
28
31
|
"@types/axios": "^0.14.4",
|
|
29
32
|
"@types/ws": "^8.18.1",
|
|
30
|
-
"@types/yargs": "^17.0.
|
|
31
|
-
"axios": "^1.
|
|
33
|
+
"@types/yargs": "^17.0.35",
|
|
34
|
+
"axios": "^1.13.2",
|
|
32
35
|
"mustache": "^4.2.0",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
36
|
+
"semver": "^7.7.3",
|
|
37
|
+
"yaml": "^2.8.2",
|
|
38
|
+
"zod": "4.1.13"
|
|
35
39
|
},
|
|
36
40
|
"devDependencies": {
|
|
37
|
-
"@biomejs/biome": "2.
|
|
38
|
-
"@openapitools/openapi-generator-cli": "^2.
|
|
39
|
-
"@types/jsdom": "^
|
|
41
|
+
"@biomejs/biome": "2.3.8",
|
|
42
|
+
"@openapitools/openapi-generator-cli": "^2.25.2",
|
|
43
|
+
"@types/jsdom": "^27.0.0",
|
|
40
44
|
"@types/mustache": "^4.2.6",
|
|
41
|
-
"@types/node": "^24.
|
|
42
|
-
"@
|
|
45
|
+
"@types/node": "^24.10.1",
|
|
46
|
+
"@types/semver": "^7.7.1",
|
|
47
|
+
"@vitest/coverage-v8": "^4.0.15",
|
|
43
48
|
"archiver": "^7.0.1",
|
|
44
|
-
"msw": "^2.
|
|
49
|
+
"msw": "^2.12.4",
|
|
45
50
|
"npm-run-all": "^4.1.5",
|
|
46
|
-
"orval": "^7.
|
|
51
|
+
"orval": "^7.17.0",
|
|
52
|
+
"prettier": "^3.7.4",
|
|
47
53
|
"shx": "^0.4.0",
|
|
48
|
-
"typescript": "^5.9.
|
|
49
|
-
"vitest": "^
|
|
54
|
+
"typescript": "^5.9.3",
|
|
55
|
+
"vitest": "^4.0.15"
|
|
50
56
|
},
|
|
51
57
|
"type": "module",
|
|
52
58
|
"exports": {
|
|
@@ -67,12 +73,20 @@
|
|
|
67
73
|
"lint": "run-p lint:*",
|
|
68
74
|
"lint:biome": "biome check",
|
|
69
75
|
"lint:tsc": "tsc --noEmit",
|
|
70
|
-
"
|
|
76
|
+
"lint:python": "ruff check td/",
|
|
77
|
+
"lint:yaml": "prettier --check \"**/*.{yml,yaml}\"",
|
|
78
|
+
"format": "run-p format:*",
|
|
79
|
+
"format:biome": "biome check --fix",
|
|
80
|
+
"format:python": "ruff format td/ && ruff check --fix td/",
|
|
81
|
+
"format:yaml": "prettier --write \"**/*.{yml,yaml}\"",
|
|
71
82
|
"dev": "npx @modelcontextprotocol/inspector node dist/cli.js --stdio",
|
|
72
83
|
"test": "run-p test:*",
|
|
73
84
|
"test:integration": "vitest run ./tests/integration",
|
|
74
85
|
"test:unit": "vitest run ./tests/unit",
|
|
75
86
|
"coverage": "vitest run --coverage",
|
|
87
|
+
"version": "run-p version:*",
|
|
88
|
+
"version:api": "node ./scripts/syncApiServerVersions.ts",
|
|
89
|
+
"version:mcp": "node ./scripts/syncMcpServerVersions.ts",
|
|
76
90
|
"gen": "run-s gen:*",
|
|
77
91
|
"gen:webserver": "openapi-generator-cli generate -i ./src/api/index.yml -g python-flask -o ./td/modules/td_server",
|
|
78
92
|
"gen:handlers": "node td/genHandlers.js",
|
|
@@ -87,6 +101,6 @@
|
|
|
87
101
|
]
|
|
88
102
|
},
|
|
89
103
|
"overrides": {
|
|
90
|
-
"axios": "^1.
|
|
104
|
+
"axios": "^1.13.2"
|
|
91
105
|
}
|
|
92
106
|
}
|