@tpmjs/cli 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.
Files changed (97) hide show
  1. package/README.md +127 -0
  2. package/bin/run.js +5 -0
  3. package/dist/commands/agent/chat.d.ts +23 -0
  4. package/dist/commands/agent/chat.js +608 -0
  5. package/dist/commands/agent/chat.js.map +1 -0
  6. package/dist/commands/agent/create.d.ts +22 -0
  7. package/dist/commands/agent/create.js +549 -0
  8. package/dist/commands/agent/create.js.map +1 -0
  9. package/dist/commands/agent/delete.d.ts +19 -0
  10. package/dist/commands/agent/delete.js +529 -0
  11. package/dist/commands/agent/delete.js.map +1 -0
  12. package/dist/commands/agent/list.d.ts +16 -0
  13. package/dist/commands/agent/list.js +535 -0
  14. package/dist/commands/agent/list.js.map +1 -0
  15. package/dist/commands/agent/update.d.ts +25 -0
  16. package/dist/commands/agent/update.js +547 -0
  17. package/dist/commands/agent/update.js.map +1 -0
  18. package/dist/commands/auth/login.d.ts +21 -0
  19. package/dist/commands/auth/login.js +603 -0
  20. package/dist/commands/auth/login.js.map +1 -0
  21. package/dist/commands/auth/logout.d.ts +13 -0
  22. package/dist/commands/auth/logout.js +227 -0
  23. package/dist/commands/auth/logout.js.map +1 -0
  24. package/dist/commands/auth/status.d.ts +14 -0
  25. package/dist/commands/auth/status.js +542 -0
  26. package/dist/commands/auth/status.js.map +1 -0
  27. package/dist/commands/auth/whoami.d.ts +14 -0
  28. package/dist/commands/auth/whoami.js +500 -0
  29. package/dist/commands/auth/whoami.js.map +1 -0
  30. package/dist/commands/collection/add.d.ts +18 -0
  31. package/dist/commands/collection/add.js +509 -0
  32. package/dist/commands/collection/add.js.map +1 -0
  33. package/dist/commands/collection/create.d.ts +17 -0
  34. package/dist/commands/collection/create.js +521 -0
  35. package/dist/commands/collection/create.js.map +1 -0
  36. package/dist/commands/collection/delete.d.ts +19 -0
  37. package/dist/commands/collection/delete.js +531 -0
  38. package/dist/commands/collection/delete.js.map +1 -0
  39. package/dist/commands/collection/import.d.ts +18 -0
  40. package/dist/commands/collection/import.js +546 -0
  41. package/dist/commands/collection/import.js.map +1 -0
  42. package/dist/commands/collection/list.d.ts +16 -0
  43. package/dist/commands/collection/list.js +531 -0
  44. package/dist/commands/collection/list.js.map +1 -0
  45. package/dist/commands/collection/remove.d.ts +18 -0
  46. package/dist/commands/collection/remove.js +501 -0
  47. package/dist/commands/collection/remove.js.map +1 -0
  48. package/dist/commands/collection/update.d.ts +20 -0
  49. package/dist/commands/collection/update.js +522 -0
  50. package/dist/commands/collection/update.js.map +1 -0
  51. package/dist/commands/doctor.d.ts +14 -0
  52. package/dist/commands/doctor.js +592 -0
  53. package/dist/commands/doctor.js.map +1 -0
  54. package/dist/commands/mcp/config.d.ts +19 -0
  55. package/dist/commands/mcp/config.js +265 -0
  56. package/dist/commands/mcp/config.js.map +1 -0
  57. package/dist/commands/mcp/serve.d.ts +23 -0
  58. package/dist/commands/mcp/serve.js +689 -0
  59. package/dist/commands/mcp/serve.js.map +1 -0
  60. package/dist/commands/playground.d.ts +23 -0
  61. package/dist/commands/playground.js +666 -0
  62. package/dist/commands/playground.js.map +1 -0
  63. package/dist/commands/publish/check.d.ts +17 -0
  64. package/dist/commands/publish/check.js +544 -0
  65. package/dist/commands/publish/check.js.map +1 -0
  66. package/dist/commands/publish/preview.d.ts +19 -0
  67. package/dist/commands/publish/preview.js +291 -0
  68. package/dist/commands/publish/preview.js.map +1 -0
  69. package/dist/commands/tool/execute.d.ts +21 -0
  70. package/dist/commands/tool/execute.js +574 -0
  71. package/dist/commands/tool/execute.js.map +1 -0
  72. package/dist/commands/tool/info.d.ts +18 -0
  73. package/dist/commands/tool/info.js +537 -0
  74. package/dist/commands/tool/info.js.map +1 -0
  75. package/dist/commands/tool/init.d.ts +24 -0
  76. package/dist/commands/tool/init.js +461 -0
  77. package/dist/commands/tool/init.js.map +1 -0
  78. package/dist/commands/tool/search.d.ts +20 -0
  79. package/dist/commands/tool/search.js +566 -0
  80. package/dist/commands/tool/search.js.map +1 -0
  81. package/dist/commands/tool/trending.d.ts +15 -0
  82. package/dist/commands/tool/trending.js +523 -0
  83. package/dist/commands/tool/trending.js.map +1 -0
  84. package/dist/commands/tool/validate.d.ts +15 -0
  85. package/dist/commands/tool/validate.js +555 -0
  86. package/dist/commands/tool/validate.js.map +1 -0
  87. package/dist/commands/update.d.ts +15 -0
  88. package/dist/commands/update.js +228 -0
  89. package/dist/commands/update.js.map +1 -0
  90. package/dist/hooks/init.d.ts +5 -0
  91. package/dist/hooks/init.js +8 -0
  92. package/dist/hooks/init.js.map +1 -0
  93. package/dist/index.d.ts +262 -0
  94. package/dist/index.js +473 -0
  95. package/dist/index.js.map +1 -0
  96. package/oclif.manifest.json +1699 -0
  97. package/package.json +104 -0
@@ -0,0 +1,689 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import * as http from 'http';
3
+ import * as readline from 'readline';
4
+ import Conf from 'conf';
5
+ import * as fs from 'fs';
6
+ import * as os from 'os';
7
+ import * as path from 'path';
8
+ import Table from 'cli-table3';
9
+ import ora from 'ora';
10
+ import pc from 'picocolors';
11
+
12
+ // src/commands/mcp/serve.ts
13
+ var CONFIG_DIR = path.join(os.homedir(), ".tpmjs");
14
+ var CREDENTIALS_FILE = path.join(CONFIG_DIR, "credentials.json");
15
+ path.join(CONFIG_DIR, "history");
16
+ function ensureConfigDir() {
17
+ if (!fs.existsSync(CONFIG_DIR)) {
18
+ fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
19
+ }
20
+ }
21
+ var configStore = new Conf({
22
+ projectName: "tpmjs",
23
+ cwd: CONFIG_DIR,
24
+ configName: "config",
25
+ defaults: {
26
+ apiUrl: "https://tpmjs.com/api",
27
+ defaultOutput: "human",
28
+ verbose: false,
29
+ analytics: false
30
+ }
31
+ });
32
+ function getConfigValue(key) {
33
+ return configStore.get(key);
34
+ }
35
+ function loadCredentials() {
36
+ ensureConfigDir();
37
+ if (!fs.existsSync(CREDENTIALS_FILE)) {
38
+ return null;
39
+ }
40
+ try {
41
+ const content = fs.readFileSync(CREDENTIALS_FILE, "utf-8");
42
+ return JSON.parse(content);
43
+ } catch {
44
+ return null;
45
+ }
46
+ }
47
+ function getApiKey() {
48
+ if (process.env.TPMJS_API_KEY) {
49
+ return process.env.TPMJS_API_KEY;
50
+ }
51
+ const creds = loadCredentials();
52
+ if (creds?.apiKey) {
53
+ return creds.apiKey;
54
+ }
55
+ return void 0;
56
+ }
57
+ function getApiUrl() {
58
+ return process.env.TPMJS_API_URL ?? getConfigValue("apiUrl") ?? "https://tpmjs.com/api";
59
+ }
60
+
61
+ // src/lib/api-client.ts
62
+ var TpmClient = class {
63
+ baseUrl;
64
+ apiKey;
65
+ timeout;
66
+ constructor(options = {}) {
67
+ this.baseUrl = options.baseUrl ?? getApiUrl();
68
+ this.apiKey = options.apiKey ?? getApiKey();
69
+ this.timeout = options.timeout ?? 3e4;
70
+ }
71
+ async request(endpoint, options = {}) {
72
+ const url = `${this.baseUrl}${endpoint}`;
73
+ const headers = {
74
+ "Content-Type": "application/json",
75
+ ...options.headers
76
+ };
77
+ if (this.apiKey) {
78
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
79
+ }
80
+ const controller = new AbortController();
81
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
82
+ try {
83
+ const response = await fetch(url, {
84
+ ...options,
85
+ headers,
86
+ signal: controller.signal
87
+ });
88
+ const data = await response.json();
89
+ if (!response.ok) {
90
+ throw new ApiError(
91
+ data.message || data.error || `HTTP ${response.status}`,
92
+ response.status,
93
+ data
94
+ );
95
+ }
96
+ return data;
97
+ } finally {
98
+ clearTimeout(timeoutId);
99
+ }
100
+ }
101
+ // Health check
102
+ async health() {
103
+ return this.request("/health");
104
+ }
105
+ // Stats
106
+ async getStats() {
107
+ return this.request("/stats");
108
+ }
109
+ // Tools
110
+ async searchTools(options = {}) {
111
+ const params = new URLSearchParams();
112
+ if (options.query) params.set("q", options.query);
113
+ if (options.category) params.set("category", options.category);
114
+ if (options.limit) params.set("limit", String(options.limit));
115
+ if (options.offset) params.set("offset", String(options.offset));
116
+ const queryString = params.toString();
117
+ const endpoint = queryString ? `/tools?${queryString}` : "/tools";
118
+ return this.request(endpoint);
119
+ }
120
+ async getTool(packageName, toolName) {
121
+ return this.request(`/tools/${encodeURIComponent(packageName)}/${encodeURIComponent(toolName)}`);
122
+ }
123
+ async getToolBySlug(slug) {
124
+ const searchResult = await this.searchTools({ query: slug, limit: 1 });
125
+ if (searchResult.data && searchResult.data.length > 0) {
126
+ const tool = searchResult.data.find((t) => t.slug === slug) || searchResult.data[0];
127
+ return { success: true, data: tool };
128
+ }
129
+ return { success: false, error: "Tool not found" };
130
+ }
131
+ async getTrendingTools(options = {}) {
132
+ const params = new URLSearchParams();
133
+ if (options.limit) params.set("limit", String(options.limit));
134
+ if (options.offset) params.set("offset", String(options.offset));
135
+ const queryString = params.toString();
136
+ const endpoint = queryString ? `/tools/trending?${queryString}` : "/tools/trending";
137
+ return this.request(endpoint);
138
+ }
139
+ async validateTpmjsField(field) {
140
+ return this.request("/tools/validate", {
141
+ method: "POST",
142
+ body: JSON.stringify(field)
143
+ });
144
+ }
145
+ async executeTool(slug, params) {
146
+ return this.request(`/tools/${encodeURIComponent(slug)}/execute`, {
147
+ method: "POST",
148
+ body: JSON.stringify(params)
149
+ });
150
+ }
151
+ async *executeToolStream(slug, params) {
152
+ const url = `${this.baseUrl}/tools/${encodeURIComponent(slug)}/execute`;
153
+ const headers = {
154
+ "Content-Type": "application/json",
155
+ "Accept": "text/event-stream"
156
+ };
157
+ if (this.apiKey) {
158
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
159
+ }
160
+ const response = await fetch(url, {
161
+ method: "POST",
162
+ headers,
163
+ body: JSON.stringify({ ...params, stream: true })
164
+ });
165
+ if (!response.ok) {
166
+ const errorText = await response.text();
167
+ throw new ApiError(errorText || `HTTP ${response.status}`, response.status);
168
+ }
169
+ if (!response.body) {
170
+ throw new ApiError("No response body", 0);
171
+ }
172
+ const reader = response.body.getReader();
173
+ const decoder = new TextDecoder();
174
+ let buffer = "";
175
+ try {
176
+ while (true) {
177
+ const { done, value } = await reader.read();
178
+ if (done) {
179
+ yield { type: "done", data: "" };
180
+ break;
181
+ }
182
+ buffer += decoder.decode(value, { stream: true });
183
+ const lines = buffer.split("\n");
184
+ buffer = lines.pop() ?? "";
185
+ for (const line of lines) {
186
+ if (line.startsWith("data: ")) {
187
+ const data = line.slice(6);
188
+ if (data === "[DONE]") {
189
+ yield { type: "done", data: "" };
190
+ return;
191
+ }
192
+ try {
193
+ const parsed = JSON.parse(data);
194
+ yield { type: parsed.type || "text", data: parsed.content || parsed.data || data };
195
+ } catch {
196
+ yield { type: "text", data };
197
+ }
198
+ }
199
+ }
200
+ }
201
+ } finally {
202
+ reader.releaseLock();
203
+ }
204
+ }
205
+ // Agents
206
+ async listAgents(options = {}) {
207
+ const params = new URLSearchParams();
208
+ if (options.limit) params.set("limit", String(options.limit));
209
+ if (options.offset) params.set("offset", String(options.offset));
210
+ const queryString = params.toString();
211
+ const endpoint = queryString ? `/agents?${queryString}` : "/agents";
212
+ return this.request(endpoint);
213
+ }
214
+ async getAgent(id) {
215
+ return this.request(`/agents/${id}`);
216
+ }
217
+ async createAgent(input) {
218
+ return this.request("/agents", {
219
+ method: "POST",
220
+ body: JSON.stringify(input)
221
+ });
222
+ }
223
+ async updateAgent(id, input) {
224
+ return this.request(`/agents/${id}`, {
225
+ method: "PATCH",
226
+ body: JSON.stringify(input)
227
+ });
228
+ }
229
+ async deleteAgent(id) {
230
+ return this.request(`/agents/${id}`, {
231
+ method: "DELETE"
232
+ });
233
+ }
234
+ // Collections
235
+ async listCollections(options = {}) {
236
+ const params = new URLSearchParams();
237
+ if (options.limit) params.set("limit", String(options.limit));
238
+ if (options.offset) params.set("offset", String(options.offset));
239
+ const queryString = params.toString();
240
+ const endpoint = queryString ? `/collections?${queryString}` : "/collections";
241
+ return this.request(endpoint);
242
+ }
243
+ async getCollection(id) {
244
+ return this.request(`/collections/${id}`);
245
+ }
246
+ async createCollection(input) {
247
+ return this.request("/collections", {
248
+ method: "POST",
249
+ body: JSON.stringify(input)
250
+ });
251
+ }
252
+ async updateCollection(id, input) {
253
+ return this.request(`/collections/${id}`, {
254
+ method: "PATCH",
255
+ body: JSON.stringify(input)
256
+ });
257
+ }
258
+ async deleteCollection(id) {
259
+ return this.request(`/collections/${id}`, {
260
+ method: "DELETE"
261
+ });
262
+ }
263
+ async addToolsToCollection(id, toolIds) {
264
+ for (const toolId of toolIds) {
265
+ await this.request(`/collections/${id}/tools/${toolId}`, {
266
+ method: "POST"
267
+ });
268
+ }
269
+ return { success: true };
270
+ }
271
+ async removeToolFromCollection(id, toolId) {
272
+ return this.request(`/collections/${id}/tools/${toolId}`, {
273
+ method: "DELETE"
274
+ });
275
+ }
276
+ // User
277
+ async whoami() {
278
+ return this.request("/user/profile");
279
+ }
280
+ async listApiKeys() {
281
+ return this.request("/user/tpmjs-api-keys");
282
+ }
283
+ // Check if authenticated
284
+ isAuthenticated() {
285
+ return !!this.apiKey;
286
+ }
287
+ };
288
+ var ApiError = class extends Error {
289
+ constructor(message, statusCode, data) {
290
+ super(message);
291
+ this.statusCode = statusCode;
292
+ this.data = data;
293
+ this.name = "ApiError";
294
+ }
295
+ };
296
+ var clientInstance = null;
297
+ function getClient(options) {
298
+ if (!clientInstance || options) {
299
+ clientInstance = new TpmClient(options);
300
+ }
301
+ return clientInstance;
302
+ }
303
+ var OutputFormatter = class {
304
+ options;
305
+ constructor(options = {}) {
306
+ this.options = options;
307
+ }
308
+ // Output as JSON
309
+ json(data) {
310
+ console.log(JSON.stringify(data, null, 2));
311
+ }
312
+ // Output a table
313
+ table(data, columns) {
314
+ if (this.options.json) {
315
+ this.json(data);
316
+ return;
317
+ }
318
+ const table = new Table({
319
+ head: columns.map((col) => pc.bold(col.header)),
320
+ colWidths: columns.map((col) => col.width ?? null),
321
+ style: {
322
+ head: [],
323
+ border: []
324
+ }
325
+ });
326
+ for (const row of data) {
327
+ table.push(columns.map((col) => String(row[col.key] ?? "")));
328
+ }
329
+ console.log(table.toString());
330
+ }
331
+ // Success message
332
+ success(message) {
333
+ if (this.options.json) return;
334
+ console.log(pc.green("\u2713"), message);
335
+ }
336
+ // Error message
337
+ error(message, details) {
338
+ if (this.options.json) {
339
+ this.json({ error: message, details });
340
+ return;
341
+ }
342
+ console.error(pc.red("\u2717"), message);
343
+ if (details && this.options.verbose) {
344
+ console.error(pc.dim(details));
345
+ }
346
+ }
347
+ // Warning message
348
+ warning(message) {
349
+ if (this.options.json) return;
350
+ console.log(pc.yellow("\u26A0"), message);
351
+ }
352
+ // Info message
353
+ info(message) {
354
+ if (this.options.json) return;
355
+ console.log(pc.blue("\u2139"), message);
356
+ }
357
+ // Debug message (only in verbose mode)
358
+ debug(message) {
359
+ if (this.options.json) return;
360
+ if (this.options.verbose) {
361
+ console.log(pc.dim(`[debug] ${message}`));
362
+ }
363
+ }
364
+ // Plain text output
365
+ text(message) {
366
+ if (this.options.json) return;
367
+ console.log(message);
368
+ }
369
+ // Heading
370
+ heading(text) {
371
+ if (this.options.json) return;
372
+ console.log();
373
+ console.log(pc.bold(pc.underline(text)));
374
+ console.log();
375
+ }
376
+ // Subheading
377
+ subheading(text) {
378
+ if (this.options.json) return;
379
+ console.log(pc.bold(text));
380
+ }
381
+ // Key-value pair
382
+ keyValue(key, value) {
383
+ if (this.options.json) return;
384
+ console.log(`${pc.dim(key + ":")} ${value ?? pc.dim("(not set)")}`);
385
+ }
386
+ // List item
387
+ listItem(text, indent = 0) {
388
+ if (this.options.json) return;
389
+ const prefix = " ".repeat(indent) + "\u2022";
390
+ console.log(`${prefix} ${text}`);
391
+ }
392
+ // Spinner
393
+ spinner(message) {
394
+ return ora({
395
+ text: message,
396
+ isSilent: this.options.json
397
+ }).start();
398
+ }
399
+ // Blank line
400
+ newLine() {
401
+ if (this.options.json) return;
402
+ console.log();
403
+ }
404
+ // Horizontal rule
405
+ hr() {
406
+ if (this.options.json) return;
407
+ console.log(pc.dim("\u2500".repeat(50)));
408
+ }
409
+ // Alias for hr
410
+ divider() {
411
+ this.hr();
412
+ }
413
+ // Code block
414
+ code(text, language) {
415
+ if (this.options.json) {
416
+ this.json({ code: text, language });
417
+ return;
418
+ }
419
+ console.log(pc.dim("```" + (language ?? "")));
420
+ console.log(text);
421
+ console.log(pc.dim("```"));
422
+ }
423
+ // Highlight text
424
+ highlight(text) {
425
+ return pc.cyan(text);
426
+ }
427
+ // Dim text
428
+ dim(text) {
429
+ return pc.dim(text);
430
+ }
431
+ // Bold text
432
+ bold(text) {
433
+ return pc.bold(text);
434
+ }
435
+ // Link (just returns text in terminal)
436
+ link(text, url) {
437
+ return `\x1B]8;;${url}\x07${pc.underline(pc.blue(text))}\x1B]8;;\x07`;
438
+ }
439
+ };
440
+ function createOutput(flags) {
441
+ return new OutputFormatter({
442
+ json: flags.json,
443
+ verbose: flags.verbose
444
+ });
445
+ }
446
+
447
+ // src/commands/mcp/serve.ts
448
+ var MCPServe = class _MCPServe extends Command {
449
+ static description = "Run as a local MCP server";
450
+ static examples = [
451
+ "<%= config.bin %> <%= command.id %>",
452
+ "<%= config.bin %> <%= command.id %> --port 8080",
453
+ "<%= config.bin %> <%= command.id %> --stdio",
454
+ "<%= config.bin %> <%= command.id %> --collection my-collection"
455
+ ];
456
+ static flags = {
457
+ port: Flags.integer({
458
+ char: "p",
459
+ description: "Port to run the server on (HTTP mode)",
460
+ default: 3333
461
+ }),
462
+ stdio: Flags.boolean({
463
+ description: "Use stdio transport instead of HTTP",
464
+ default: false
465
+ }),
466
+ collection: Flags.string({
467
+ char: "c",
468
+ description: "Serve tools from a specific collection"
469
+ }),
470
+ tool: Flags.string({
471
+ char: "t",
472
+ description: "Serve specific tools (comma-separated)",
473
+ multiple: true
474
+ }),
475
+ verbose: Flags.boolean({
476
+ char: "v",
477
+ description: "Show verbose output",
478
+ default: false
479
+ })
480
+ };
481
+ client = getClient();
482
+ tools = /* @__PURE__ */ new Map();
483
+ async run() {
484
+ const { flags } = await this.parse(_MCPServe);
485
+ const output = createOutput(flags);
486
+ await this.loadTools(flags, output);
487
+ if (flags.stdio) {
488
+ await this.runStdioServer(output, flags.verbose);
489
+ } else {
490
+ await this.runHttpServer(flags.port, output, flags.verbose);
491
+ }
492
+ }
493
+ async loadTools(flags, output) {
494
+ const spinner = output.spinner("Loading tools...");
495
+ try {
496
+ if (flags.collection) {
497
+ const response = await this.client.getTrendingTools({ limit: 20 });
498
+ if (response.data && response.data.length > 0) {
499
+ for (const tool of response.data) {
500
+ this.tools.set(tool.slug, tool);
501
+ }
502
+ }
503
+ } else if (flags.tool && flags.tool.length > 0) {
504
+ for (const toolId of flags.tool) {
505
+ const response = await this.client.getToolBySlug(toolId);
506
+ if (response.success && response.data) {
507
+ this.tools.set(response.data.slug, response.data);
508
+ }
509
+ }
510
+ } else {
511
+ const response = await this.client.getTrendingTools({ limit: 10 });
512
+ if (response.data && response.data.length > 0) {
513
+ for (const tool of response.data) {
514
+ this.tools.set(tool.slug, tool);
515
+ }
516
+ }
517
+ }
518
+ spinner.stop();
519
+ output.info(`Loaded ${this.tools.size} tool(s)`);
520
+ } catch (error) {
521
+ spinner.fail("Failed to load tools");
522
+ throw error;
523
+ }
524
+ }
525
+ async runStdioServer(output, verbose) {
526
+ output.info("Starting MCP server in stdio mode...");
527
+ output.info("Listening for JSON-RPC messages on stdin");
528
+ const rl = readline.createInterface({
529
+ input: process.stdin,
530
+ output: process.stdout,
531
+ terminal: false
532
+ });
533
+ rl.on("line", async (line) => {
534
+ try {
535
+ const request = JSON.parse(line);
536
+ if (verbose) {
537
+ output.info(`Received: ${request.method}`);
538
+ }
539
+ const response = await this.handleRequest(request);
540
+ console.log(JSON.stringify(response));
541
+ } catch (error) {
542
+ const errorResponse = {
543
+ jsonrpc: "2.0",
544
+ id: 0,
545
+ error: {
546
+ code: -32700,
547
+ message: "Parse error",
548
+ data: error instanceof Error ? error.message : "Unknown error"
549
+ }
550
+ };
551
+ console.log(JSON.stringify(errorResponse));
552
+ }
553
+ });
554
+ await new Promise(() => {
555
+ });
556
+ }
557
+ async runHttpServer(port, output, verbose) {
558
+ const server = http.createServer(async (req, res) => {
559
+ if (req.method === "POST" && req.url === "/mcp") {
560
+ let body = "";
561
+ req.on("data", (chunk) => {
562
+ body += chunk.toString();
563
+ });
564
+ req.on("end", async () => {
565
+ try {
566
+ const request = JSON.parse(body);
567
+ if (verbose) {
568
+ output.info(`Received: ${request.method}`);
569
+ }
570
+ const response = await this.handleRequest(request);
571
+ res.writeHead(200, { "Content-Type": "application/json" });
572
+ res.end(JSON.stringify(response));
573
+ } catch (error) {
574
+ const errorResponse = {
575
+ jsonrpc: "2.0",
576
+ id: 0,
577
+ error: {
578
+ code: -32700,
579
+ message: "Parse error",
580
+ data: error instanceof Error ? error.message : "Unknown error"
581
+ }
582
+ };
583
+ res.writeHead(400, { "Content-Type": "application/json" });
584
+ res.end(JSON.stringify(errorResponse));
585
+ }
586
+ });
587
+ } else if (req.method === "GET" && req.url === "/health") {
588
+ res.writeHead(200, { "Content-Type": "application/json" });
589
+ res.end(JSON.stringify({ status: "ok", tools: this.tools.size }));
590
+ } else {
591
+ res.writeHead(404);
592
+ res.end("Not found");
593
+ }
594
+ });
595
+ server.listen(port, () => {
596
+ output.success(`MCP server running at http://localhost:${port}/mcp`);
597
+ output.info("Health check: GET /health");
598
+ output.info("Press Ctrl+C to stop");
599
+ });
600
+ await new Promise(() => {
601
+ });
602
+ }
603
+ async handleRequest(request) {
604
+ const { id, method, params } = request;
605
+ switch (method) {
606
+ case "initialize":
607
+ return {
608
+ jsonrpc: "2.0",
609
+ id,
610
+ result: {
611
+ protocolVersion: "2024-11-05",
612
+ capabilities: {
613
+ tools: {}
614
+ },
615
+ serverInfo: {
616
+ name: "tpmjs-mcp-server",
617
+ version: "0.1.0"
618
+ }
619
+ }
620
+ };
621
+ case "tools/list":
622
+ return {
623
+ jsonrpc: "2.0",
624
+ id,
625
+ result: {
626
+ tools: Array.from(this.tools.entries()).map(([slug, tool]) => ({
627
+ name: slug,
628
+ description: tool.description || "",
629
+ inputSchema: tool.inputSchema || {
630
+ type: "object",
631
+ properties: {}
632
+ }
633
+ }))
634
+ }
635
+ };
636
+ case "tools/call": {
637
+ const toolName = params?.name;
638
+ const toolArgs = params?.arguments;
639
+ if (!toolName) {
640
+ return {
641
+ jsonrpc: "2.0",
642
+ id,
643
+ error: {
644
+ code: -32602,
645
+ message: "Invalid params: tool name required"
646
+ }
647
+ };
648
+ }
649
+ try {
650
+ const response = await this.client.executeTool(toolName, toolArgs || {});
651
+ return {
652
+ jsonrpc: "2.0",
653
+ id,
654
+ result: {
655
+ content: [
656
+ {
657
+ type: "text",
658
+ text: JSON.stringify(response, null, 2)
659
+ }
660
+ ]
661
+ }
662
+ };
663
+ } catch (error) {
664
+ return {
665
+ jsonrpc: "2.0",
666
+ id,
667
+ error: {
668
+ code: -32e3,
669
+ message: error instanceof Error ? error.message : "Tool execution failed"
670
+ }
671
+ };
672
+ }
673
+ }
674
+ default:
675
+ return {
676
+ jsonrpc: "2.0",
677
+ id,
678
+ error: {
679
+ code: -32601,
680
+ message: `Method not found: ${method}`
681
+ }
682
+ };
683
+ }
684
+ }
685
+ };
686
+
687
+ export { MCPServe as default };
688
+ //# sourceMappingURL=serve.js.map
689
+ //# sourceMappingURL=serve.js.map