@trace.market/types 0.1.0

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.
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@trace.market/types-mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for managing Trace Market type definitions",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "tm-types-mcp": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "start": "node dist/index.js"
14
+ },
15
+ "dependencies": {
16
+ "@modelcontextprotocol/sdk": "^1.0.4",
17
+ "zod": "^3.23.8",
18
+ "typescript": "^5.3.3",
19
+ "jsonwebtoken": "^9.0.2",
20
+ "dotenv": "^16.4.5"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^22.10.2",
24
+ "@types/jsonwebtoken": "^9.0.7"
25
+ }
26
+ }
@@ -0,0 +1,516 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import {
6
+ CallToolRequestSchema,
7
+ ListToolsRequestSchema,
8
+ Tool,
9
+ } from "@modelcontextprotocol/sdk/types.js";
10
+ import { z } from "zod";
11
+ import { readFileSync, writeFileSync, existsSync } from "fs";
12
+ import { join, dirname } from "path";
13
+ import { fileURLToPath } from "url";
14
+ import jwt from "jsonwebtoken";
15
+ import * as dotenv from "dotenv";
16
+
17
+ dotenv.config();
18
+
19
+ const __filename = fileURLToPath(import.meta.url);
20
+ const __dirname = dirname(__filename);
21
+
22
+ // Path to types definition file
23
+ const TYPES_PATH = join(__dirname, "../../../src/index.d.ts");
24
+ const JWT_SECRET = process.env.JWT_SECRET || "your-secret-key-change-in-production";
25
+
26
+ interface AuthContext {
27
+ userId?: string;
28
+ role?: "admin" | "user" | "anonymous";
29
+ }
30
+
31
+ // Authentication helper
32
+ function verifyAuth(token?: string): AuthContext {
33
+ if (!token) {
34
+ return { role: "anonymous" };
35
+ }
36
+
37
+ try {
38
+ const decoded = jwt.verify(token, JWT_SECRET) as any;
39
+ return {
40
+ userId: decoded.userId,
41
+ role: decoded.role || "user",
42
+ };
43
+ } catch (error) {
44
+ return { role: "anonymous" };
45
+ }
46
+ }
47
+
48
+ // Read current types
49
+ function readTypes(): string {
50
+ if (!existsSync(TYPES_PATH)) {
51
+ throw new Error("Types file not found");
52
+ }
53
+ return readFileSync(TYPES_PATH, "utf-8");
54
+ }
55
+
56
+ // Write types (only for authenticated users)
57
+ function writeTypes(content: string, auth: AuthContext): void {
58
+ if (auth.role === "anonymous") {
59
+ throw new Error("Authentication required to modify types");
60
+ }
61
+ writeFileSync(TYPES_PATH, content, "utf-8");
62
+ }
63
+
64
+ // Parse type definition to extract metadata
65
+ function parseTypeDefinitions(content: string) {
66
+ const interfacePattern = /export\s+interface\s+(\w+)(?:\s+extends\s+(\w+))?\s*\{([^}]+)\}/g;
67
+ const typePattern = /export\s+type\s+(\w+)\s*=\s*([^;]+);/g;
68
+
69
+ const interfaces: any[] = [];
70
+ const types: any[] = [];
71
+
72
+ let match;
73
+ while ((match = interfacePattern.exec(content)) !== null) {
74
+ const [, name, extendsFrom, body] = match;
75
+ const fields = body
76
+ .split("\n")
77
+ .map((line) => line.trim())
78
+ .filter((line) => line && !line.startsWith("//") && !line.startsWith("/*"))
79
+ .map((line) => {
80
+ const fieldMatch = line.match(/(\w+)(\?)?:\s*([^;]+);?/);
81
+ if (fieldMatch) {
82
+ const [, fieldName, optional, fieldType] = fieldMatch;
83
+ return {
84
+ name: fieldName,
85
+ type: fieldType.trim(),
86
+ optional: !!optional,
87
+ };
88
+ }
89
+ return null;
90
+ })
91
+ .filter(Boolean);
92
+
93
+ interfaces.push({
94
+ kind: "interface",
95
+ name,
96
+ extends: extendsFrom || null,
97
+ fields,
98
+ });
99
+ }
100
+
101
+ while ((match = typePattern.exec(content)) !== null) {
102
+ const [, name, definition] = match;
103
+ types.push({
104
+ kind: "type",
105
+ name,
106
+ definition: definition.trim(),
107
+ });
108
+ }
109
+
110
+ return { interfaces, types };
111
+ }
112
+
113
+ // Generate TypeScript type from natural language
114
+ async function generateTypeFromNL(description: string, existingTypes: string): Promise<string> {
115
+ // This is a simplified version - in production, you'd use an LLM API
116
+ // For now, we'll return a template that needs to be filled
117
+ const typeName = description
118
+ .split(" ")
119
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
120
+ .join("")
121
+ .replace(/[^a-zA-Z0-9]/g, "");
122
+
123
+ return `
124
+ // Generated from: ${description}
125
+ export interface ${typeName} {
126
+ // TODO: Fill in fields based on description
127
+ id: string;
128
+ createdAt: number;
129
+ }
130
+ `.trim();
131
+ }
132
+
133
+ // Define MCP tools
134
+ const tools: Tool[] = [
135
+ {
136
+ name: "list_types",
137
+ description: "List all available type definitions (interfaces and types). No authentication required.",
138
+ inputSchema: {
139
+ type: "object",
140
+ properties: {
141
+ filter: {
142
+ type: "string",
143
+ description: "Optional filter to search type names",
144
+ },
145
+ },
146
+ },
147
+ },
148
+ {
149
+ name: "get_type_definition",
150
+ description: "Get detailed definition of a specific type. No authentication required.",
151
+ inputSchema: {
152
+ type: "object",
153
+ properties: {
154
+ typeName: {
155
+ type: "string",
156
+ description: "Name of the type to retrieve",
157
+ },
158
+ },
159
+ required: ["typeName"],
160
+ },
161
+ },
162
+ {
163
+ name: "validate_data",
164
+ description: "Validate data against a type definition. No authentication required.",
165
+ inputSchema: {
166
+ type: "object",
167
+ properties: {
168
+ typeName: {
169
+ type: "string",
170
+ description: "Name of the type to validate against",
171
+ },
172
+ data: {
173
+ type: "object",
174
+ description: "Data object to validate",
175
+ },
176
+ },
177
+ required: ["typeName", "data"],
178
+ },
179
+ },
180
+ {
181
+ name: "create_type_from_description",
182
+ description: "Create a new type definition from a natural language description. Requires authentication (admin or user role).",
183
+ inputSchema: {
184
+ type: "object",
185
+ properties: {
186
+ description: {
187
+ type: "string",
188
+ description: "Natural language description of the type to create",
189
+ },
190
+ authToken: {
191
+ type: "string",
192
+ description: "JWT authentication token",
193
+ },
194
+ },
195
+ required: ["description", "authToken"],
196
+ },
197
+ },
198
+ {
199
+ name: "add_type_definition",
200
+ description: "Add a new type definition (TypeScript code). Requires authentication (admin or user role).",
201
+ inputSchema: {
202
+ type: "object",
203
+ properties: {
204
+ typeDefinition: {
205
+ type: "string",
206
+ description: "TypeScript type definition to add",
207
+ },
208
+ authToken: {
209
+ type: "string",
210
+ description: "JWT authentication token",
211
+ },
212
+ },
213
+ required: ["typeDefinition", "authToken"],
214
+ },
215
+ },
216
+ {
217
+ name: "query_data",
218
+ description: "Query and filter data based on type structure. No authentication required.",
219
+ inputSchema: {
220
+ type: "object",
221
+ properties: {
222
+ typeName: {
223
+ type: "string",
224
+ description: "Type to query",
225
+ },
226
+ query: {
227
+ type: "object",
228
+ description: "Query filters (field: value pairs)",
229
+ },
230
+ },
231
+ required: ["typeName"],
232
+ },
233
+ },
234
+ {
235
+ name: "generate_report",
236
+ description: "Generate a custom report from type data. No authentication required.",
237
+ inputSchema: {
238
+ type: "object",
239
+ properties: {
240
+ reportType: {
241
+ type: "string",
242
+ description: "Type of report to generate (e.g., 'summary', 'detailed', 'impact')",
243
+ },
244
+ data: {
245
+ type: "object",
246
+ description: "Data to include in report",
247
+ },
248
+ format: {
249
+ type: "string",
250
+ enum: ["json", "markdown", "html"],
251
+ description: "Output format",
252
+ },
253
+ },
254
+ required: ["reportType", "data"],
255
+ },
256
+ },
257
+ ];
258
+
259
+ // Create server instance
260
+ const server = new Server(
261
+ {
262
+ name: "tm-types-mcp-server",
263
+ version: "0.1.0",
264
+ },
265
+ {
266
+ capabilities: {
267
+ tools: {},
268
+ },
269
+ }
270
+ );
271
+
272
+ // List tools handler
273
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
274
+ return { tools };
275
+ });
276
+
277
+ // Call tool handler
278
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
279
+ const { name, arguments: args } = request.params;
280
+
281
+ try {
282
+ switch (name) {
283
+ case "list_types": {
284
+ const content = readTypes();
285
+ const { interfaces, types } = parseTypeDefinitions(content);
286
+ const filter = (args as any).filter?.toLowerCase();
287
+
288
+ const filteredInterfaces = filter
289
+ ? interfaces.filter((i) => i.name.toLowerCase().includes(filter))
290
+ : interfaces;
291
+ const filteredTypes = filter
292
+ ? types.filter((t) => t.name.toLowerCase().includes(filter))
293
+ : types;
294
+
295
+ return {
296
+ content: [
297
+ {
298
+ type: "text",
299
+ text: JSON.stringify(
300
+ {
301
+ interfaces: filteredInterfaces.map((i) => ({
302
+ name: i.name,
303
+ extends: i.extends,
304
+ fieldCount: i.fields.length,
305
+ })),
306
+ types: filteredTypes.map((t) => ({
307
+ name: t.name,
308
+ definition: t.definition,
309
+ })),
310
+ },
311
+ null,
312
+ 2
313
+ ),
314
+ },
315
+ ],
316
+ };
317
+ }
318
+
319
+ case "get_type_definition": {
320
+ const { typeName } = args as any;
321
+ const content = readTypes();
322
+ const { interfaces, types } = parseTypeDefinitions(content);
323
+
324
+ const interfaceDef = interfaces.find((i) => i.name === typeName);
325
+ const typeDef = types.find((t) => t.name === typeName);
326
+
327
+ if (!interfaceDef && !typeDef) {
328
+ return {
329
+ content: [
330
+ {
331
+ type: "text",
332
+ text: JSON.stringify({ error: `Type '${typeName}' not found` }),
333
+ },
334
+ ],
335
+ isError: true,
336
+ };
337
+ }
338
+
339
+ return {
340
+ content: [
341
+ {
342
+ type: "text",
343
+ text: JSON.stringify(interfaceDef || typeDef, null, 2),
344
+ },
345
+ ],
346
+ };
347
+ }
348
+
349
+ case "validate_data": {
350
+ const { typeName, data } = args as any;
351
+ const content = readTypes();
352
+ const { interfaces } = parseTypeDefinitions(content);
353
+
354
+ const typeDef = interfaces.find((i) => i.name === typeName);
355
+ if (!typeDef) {
356
+ return {
357
+ content: [
358
+ {
359
+ type: "text",
360
+ text: JSON.stringify({ error: `Type '${typeName}' not found` }),
361
+ },
362
+ ],
363
+ isError: true,
364
+ };
365
+ }
366
+
367
+ // Simple validation - check required fields
368
+ const errors: string[] = [];
369
+ for (const field of typeDef.fields) {
370
+ if (!field.optional && !(field.name in data)) {
371
+ errors.push(`Missing required field: ${field.name}`);
372
+ }
373
+ }
374
+
375
+ return {
376
+ content: [
377
+ {
378
+ type: "text",
379
+ text: JSON.stringify({
380
+ valid: errors.length === 0,
381
+ errors,
382
+ typeName,
383
+ }, null, 2),
384
+ },
385
+ ],
386
+ };
387
+ }
388
+
389
+ case "create_type_from_description": {
390
+ const { description, authToken } = args as any;
391
+ const auth = verifyAuth(authToken);
392
+
393
+ if (auth.role === "anonymous") {
394
+ return {
395
+ content: [
396
+ {
397
+ type: "text",
398
+ text: JSON.stringify({ error: "Authentication required" }),
399
+ },
400
+ ],
401
+ isError: true,
402
+ };
403
+ }
404
+
405
+ const content = readTypes();
406
+ const newType = await generateTypeFromNL(description, content);
407
+
408
+ return {
409
+ content: [
410
+ {
411
+ type: "text",
412
+ text: JSON.stringify({
413
+ message: "Type generated successfully. Review and use 'add_type_definition' to add it.",
414
+ generatedType: newType,
415
+ }, null, 2),
416
+ },
417
+ ],
418
+ };
419
+ }
420
+
421
+ case "add_type_definition": {
422
+ const { typeDefinition, authToken } = args as any;
423
+ const auth = verifyAuth(authToken);
424
+
425
+ const content = readTypes();
426
+ const newContent = `${content}\n\n${typeDefinition}\n`;
427
+ writeTypes(newContent, auth);
428
+
429
+ return {
430
+ content: [
431
+ {
432
+ type: "text",
433
+ text: JSON.stringify({
434
+ message: "Type definition added successfully",
435
+ userId: auth.userId,
436
+ }),
437
+ },
438
+ ],
439
+ };
440
+ }
441
+
442
+ case "query_data": {
443
+ const { typeName, query } = args as any;
444
+ // This would integrate with your actual data storage
445
+ return {
446
+ content: [
447
+ {
448
+ type: "text",
449
+ text: JSON.stringify({
450
+ message: "Query functionality - integrate with your data store",
451
+ typeName,
452
+ query,
453
+ }, null, 2),
454
+ },
455
+ ],
456
+ };
457
+ }
458
+
459
+ case "generate_report": {
460
+ const { reportType, data, format = "json" } = args as any;
461
+
462
+ // Simple report generation
463
+ let report: string;
464
+ if (format === "markdown") {
465
+ report = `# ${reportType.toUpperCase()} Report\n\n${JSON.stringify(data, null, 2)}`;
466
+ } else if (format === "html") {
467
+ report = `<html><body><h1>${reportType} Report</h1><pre>${JSON.stringify(data, null, 2)}</pre></body></html>`;
468
+ } else {
469
+ report = JSON.stringify({ reportType, data }, null, 2);
470
+ }
471
+
472
+ return {
473
+ content: [
474
+ {
475
+ type: "text",
476
+ text: report,
477
+ },
478
+ ],
479
+ };
480
+ }
481
+
482
+ default:
483
+ return {
484
+ content: [
485
+ {
486
+ type: "text",
487
+ text: JSON.stringify({ error: `Unknown tool: ${name}` }),
488
+ },
489
+ ],
490
+ isError: true,
491
+ };
492
+ }
493
+ } catch (error: any) {
494
+ return {
495
+ content: [
496
+ {
497
+ type: "text",
498
+ text: JSON.stringify({ error: error.message }),
499
+ },
500
+ ],
501
+ isError: true,
502
+ };
503
+ }
504
+ });
505
+
506
+ // Start server
507
+ async function main() {
508
+ const transport = new StdioServerTransport();
509
+ await server.connect(transport);
510
+ console.error("Trace Market Types MCP Server running on stdio");
511
+ }
512
+
513
+ main().catch((error) => {
514
+ console.error("Fatal error:", error);
515
+ process.exit(1);
516
+ });
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@trace.market/types",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript type definitions for Trace Market food supply chain data",
5
+ "author": "Trace Market Team",
6
+ "license": "MIT",
7
+ "types": "src/index.d.ts",
8
+ "main": "src/index.d.ts",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/entin-hun/tm-types.git"
12
+ },
13
+ "keywords": [
14
+ "typescript",
15
+ "types",
16
+ "food",
17
+ "supply-chain",
18
+ "traceability",
19
+ "blockchain"
20
+ ],
21
+ "scripts": {
22
+ "prepublishOnly": "npm run validate",
23
+ "validate": "tsc --noEmit",
24
+ "version": "git add -A",
25
+ "postversion": "git push && git push --tags"
26
+ },
27
+ "devDependencies": {
28
+ "@types/geojson": "^7946.0.11",
29
+ "typescript": "^5.3.3"
30
+ }
31
+ }