ebay-mcp-remote-edition 1.0.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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +755 -0
  3. package/build/api/account-management/account.js +301 -0
  4. package/build/api/analytics-and-report/analytics.js +102 -0
  5. package/build/api/client-trading.js +96 -0
  6. package/build/api/client.js +173 -0
  7. package/build/api/communication/feedback.js +119 -0
  8. package/build/api/communication/message.js +131 -0
  9. package/build/api/communication/negotiation.js +97 -0
  10. package/build/api/communication/notification.js +373 -0
  11. package/build/api/developer/developer.js +81 -0
  12. package/build/api/index.js +109 -0
  13. package/build/api/listing-management/inventory.js +640 -0
  14. package/build/api/listing-metadata/metadata.js +485 -0
  15. package/build/api/listing-metadata/taxonomy.js +58 -0
  16. package/build/api/marketing-and-promotions/marketing.js +768 -0
  17. package/build/api/marketing-and-promotions/recommendation.js +32 -0
  18. package/build/api/order-management/dispute.js +69 -0
  19. package/build/api/order-management/fulfillment.js +89 -0
  20. package/build/api/other/compliance.js +47 -0
  21. package/build/api/other/edelivery.js +219 -0
  22. package/build/api/other/identity.js +24 -0
  23. package/build/api/other/translation.js +22 -0
  24. package/build/api/other/vero.js +48 -0
  25. package/build/api/trading/trading.js +78 -0
  26. package/build/auth/kv-store.js +40 -0
  27. package/build/auth/multi-user-store.js +120 -0
  28. package/build/auth/oauth-metadata.js +59 -0
  29. package/build/auth/oauth-middleware.js +99 -0
  30. package/build/auth/oauth-types.js +4 -0
  31. package/build/auth/oauth.js +235 -0
  32. package/build/auth/scope-utils.js +304 -0
  33. package/build/auth/token-store.js +46 -0
  34. package/build/auth/token-verifier.js +172 -0
  35. package/build/config/environment.js +297 -0
  36. package/build/index.d.ts +1 -0
  37. package/build/index.js +129 -0
  38. package/build/schemas/account-management/account.js +375 -0
  39. package/build/schemas/analytics/analytics.js +191 -0
  40. package/build/schemas/communication/messages.js +345 -0
  41. package/build/schemas/fulfillment/orders.js +338 -0
  42. package/build/schemas/index.js +68 -0
  43. package/build/schemas/inventory-management/inventory.js +471 -0
  44. package/build/schemas/marketing/marketing.js +1103 -0
  45. package/build/schemas/metadata/metadata.js +618 -0
  46. package/build/schemas/other/other-apis.js +390 -0
  47. package/build/schemas/taxonomy/taxonomy.js +575 -0
  48. package/build/scripts/auto-setup.js +364 -0
  49. package/build/scripts/dev-sync.js +512 -0
  50. package/build/scripts/diagnostics.js +301 -0
  51. package/build/scripts/download-specs.js +116 -0
  52. package/build/scripts/interactive-setup.js +757 -0
  53. package/build/scripts/setup.js +1515 -0
  54. package/build/scripts/update-api-status-doc.js +44 -0
  55. package/build/server-http.d.ts +1 -0
  56. package/build/server-http.js +581 -0
  57. package/build/tools/definitions/account-with-schemas.js +170 -0
  58. package/build/tools/definitions/account.js +428 -0
  59. package/build/tools/definitions/analytics.js +66 -0
  60. package/build/tools/definitions/communication.js +394 -0
  61. package/build/tools/definitions/developer.js +195 -0
  62. package/build/tools/definitions/fulfillment.js +326 -0
  63. package/build/tools/definitions/index.js +41 -0
  64. package/build/tools/definitions/inventory.js +464 -0
  65. package/build/tools/definitions/marketing.js +1486 -0
  66. package/build/tools/definitions/metadata.js +188 -0
  67. package/build/tools/definitions/other.js +309 -0
  68. package/build/tools/definitions/taxonomy.js +64 -0
  69. package/build/tools/definitions/token-management.js +148 -0
  70. package/build/tools/definitions/trading.js +71 -0
  71. package/build/tools/index.js +1200 -0
  72. package/build/tools/schemas.js +667 -0
  73. package/build/tools/tool-definitions.js +3534 -0
  74. package/build/types/application-settings/developerAnalyticsV1BetaOas3.js +5 -0
  75. package/build/types/application-settings/developerClientRegistrationV1Oas3.js +5 -0
  76. package/build/types/application-settings/developerKeyManagementV1Oas3.js +5 -0
  77. package/build/types/ebay-enums.js +1330 -0
  78. package/build/types/ebay.js +123 -0
  79. package/build/types/index.js +10 -0
  80. package/build/types/sell-apps/account-management/sellAccountV1Oas3.js +5 -0
  81. package/build/types/sell-apps/analytics-and-report/sellAnalyticsV1Oas3.js +5 -0
  82. package/build/types/sell-apps/communication/commerceFeedbackV1BetaOas3.js +5 -0
  83. package/build/types/sell-apps/communication/commerceMessageV1Oas3.js +5 -0
  84. package/build/types/sell-apps/communication/commerceNotificationV1Oas3.js +5 -0
  85. package/build/types/sell-apps/communication/sellNegotiationV1Oas3.js +5 -0
  86. package/build/types/sell-apps/listing-management/sellInventoryV1Oas3.js +5 -0
  87. package/build/types/sell-apps/listing-metadata/sellMetadataV1Oas3.js +5 -0
  88. package/build/types/sell-apps/markeitng-and-promotions/sellMarketingV1Oas3.js +5 -0
  89. package/build/types/sell-apps/markeitng-and-promotions/sellRecommendationV1Oas3.js +5 -0
  90. package/build/types/sell-apps/order-management/sellFulfillmentV1Oas3.js +5 -0
  91. package/build/types/sell-apps/other-apis/commerceIdentityV1Oas3.js +5 -0
  92. package/build/types/sell-apps/other-apis/commerceTranslationV1BetaOas3.js +5 -0
  93. package/build/types/sell-apps/other-apis/commerceVeroV1Oas3.js +5 -0
  94. package/build/types/sell-apps/other-apis/sellComplianceV1Oas3.js +5 -0
  95. package/build/types/sell-apps/other-apis/sellEdeliveryInternationalShippingOas3.js +5 -0
  96. package/build/types/sell-apps/other-apis/sellMarketingV1Oas3.js +5 -0
  97. package/build/types/sell-apps/other-apis/sellRecommendationV1Oas3.js +5 -0
  98. package/build/utils/account-management/account.js +831 -0
  99. package/build/utils/api-status-feed.js +83 -0
  100. package/build/utils/communication/feedback.js +216 -0
  101. package/build/utils/communication/message.js +242 -0
  102. package/build/utils/communication/negotiation.js +150 -0
  103. package/build/utils/communication/notification.js +369 -0
  104. package/build/utils/date-converter.js +160 -0
  105. package/build/utils/llm-client-detector.js +758 -0
  106. package/build/utils/logger.js +198 -0
  107. package/build/utils/oauth-helper.js +315 -0
  108. package/build/utils/order-management/dispute.js +369 -0
  109. package/build/utils/order-management/fulfillment.js +205 -0
  110. package/build/utils/other/compliance.js +76 -0
  111. package/build/utils/other/edelivery.js +241 -0
  112. package/build/utils/other/identity.js +13 -0
  113. package/build/utils/other/translation.js +41 -0
  114. package/build/utils/other/vero.js +90 -0
  115. package/build/utils/scope-helper.js +207 -0
  116. package/build/utils/security-checker.js +248 -0
  117. package/build/utils/setup-validator.js +305 -0
  118. package/build/utils/token-utils.js +40 -0
  119. package/build/utils/version.js +56 -0
  120. package/docs/auth/production_scopes.json +111 -0
  121. package/docs/auth/sandbox_scopes.json +142 -0
  122. package/package.json +122 -0
  123. package/public/icons/1024x1024.png +0 -0
  124. package/public/icons/128x128.png +0 -0
  125. package/public/icons/16x16.png +0 -0
  126. package/public/icons/256x256.png +0 -0
  127. package/public/icons/32x32.png +0 -0
  128. package/public/icons/48x48.png +0 -0
  129. package/public/icons/512x512.png +0 -0
@@ -0,0 +1,512 @@
1
+ import axios from 'axios';
2
+ import chalk from 'chalk';
3
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from 'fs';
4
+ import { join, dirname, basename } from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import { execSync } from 'child_process';
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+ const PROJECT_ROOT = join(__dirname, '../..');
10
+ const DOCS_DIR = join(PROJECT_ROOT, 'docs');
11
+ const TYPES_DIR = join(PROJECT_ROOT, 'src/types');
12
+ const TOOLS_DIR = join(PROJECT_ROOT, 'src/tools/definitions');
13
+ const ui = {
14
+ success: chalk.green,
15
+ warning: chalk.yellow,
16
+ error: chalk.red,
17
+ info: chalk.cyan,
18
+ dim: chalk.dim,
19
+ bold: chalk.bold,
20
+ };
21
+ function showSpinner(message) {
22
+ const frames = ['ā ‹', 'ā ™', 'ā ¹', 'ā ø', 'ā ¼', 'ā “', 'ā ¦', 'ā §', 'ā ‡', 'ā '];
23
+ let i = 0;
24
+ process.stdout.write(` ${ui.info(frames[0])} ${message}`);
25
+ const interval = setInterval(() => {
26
+ i = (i + 1) % frames.length;
27
+ process.stdout.write(`\r ${ui.info(frames[i])} ${message}`);
28
+ }, 80);
29
+ return () => {
30
+ clearInterval(interval);
31
+ process.stdout.write('\r' + ' '.repeat(message.length + 10) + '\r');
32
+ };
33
+ }
34
+ const SPEC_FOLDER_MAP = {
35
+ 'developer_analytics_v1_beta_oas3.json': 'application-settings',
36
+ 'developer_key_management_v1_oas3.json': 'application-settings',
37
+ 'developer_client_registration_v1_oas3.json': 'application-settings',
38
+ 'sell_inventory_v1_oas3.json': 'sell-apps/listing-management',
39
+ 'sell_feed_v1_oas3.json': 'sell-apps/listing-management',
40
+ 'commerce_media_v1_beta_oas3.json': 'sell-apps/listing-management',
41
+ 'sell_stores_v1_oas3.json': 'sell-apps/listing-management',
42
+ 'sell_metadata_v1_oas3.json': 'sell-apps/listing-metadata',
43
+ 'commerce_taxonomy_v1_oas3.json': 'sell-apps/listing-metadata',
44
+ 'commerce_charity_v1_oas3.json': 'sell-apps/listing-metadata',
45
+ 'sell_account_v1_oas3.json': 'sell-apps/account-management',
46
+ 'sell_account_v2_oas3.json': 'sell-apps/account-management',
47
+ 'sell_finances_v1_oas3.json': 'sell-apps/account-management',
48
+ 'commerce_message_v1_oas3.json': 'sell-apps/communication',
49
+ 'commerce_notification_v1_oas3.json': 'sell-apps/communication',
50
+ 'sell_negotiation_v1_oas3.json': 'sell-apps/communication',
51
+ 'commerce_feedback_v1_beta_oas3.json': 'sell-apps/communication',
52
+ 'sell_fulfillment_v1_oas3.json': 'sell-apps/order-management',
53
+ 'sell_logistics_v1_oas3.json': 'sell-apps/order-management',
54
+ 'sell_marketing_v1_oas3.json': 'sell-apps/marketing-and-promotions',
55
+ 'sell_recommendation_v1_oas3.json': 'sell-apps/marketing-and-promotions',
56
+ 'sell_analytics_v1_oas3.json': 'sell-apps/analytics-and-report',
57
+ 'commerce_translation_v1_beta_oas3.json': 'sell-apps/other-apis',
58
+ 'sell_compliance_v1_oas3.json': 'sell-apps/other-apis',
59
+ 'commerce_identity_v1_oas3.json': 'sell-apps/other-apis',
60
+ 'sell_edelivery_international_shipping_oas3.json': 'sell-apps/other-apis',
61
+ 'commerce_vero_v1_oas3.json': 'sell-apps/other-apis',
62
+ 'buy_browse_v1_oas3.json': 'buy-apps/inventory-discovery',
63
+ 'buy_feed_v1_beta_oas3.json': 'buy-apps/inventory-discovery',
64
+ 'buy_feed_v1_oas3.json': 'buy-apps/inventory-discovery',
65
+ 'buy_deal_v1_oas3.json': 'buy-apps/marketing-and-discounts',
66
+ 'buy_marketing_v1_beta_oas3.json': 'buy-apps/marketing-and-discounts',
67
+ 'commerce_catalog_v1_beta_oas3.json': 'buy-apps/marketplace-metadata',
68
+ 'buy_order_v2_oas3.json': 'buy-apps/checkout-and-bidding',
69
+ 'buy_offer_v1_beta_oas3.json': 'buy-apps/checkout-and-bidding',
70
+ };
71
+ async function downloadSpecs() {
72
+ console.log(ui.bold('\nšŸ“„ Downloading OpenAPI Specifications\n'));
73
+ const readmePath = join(DOCS_DIR, 'sell-apps/README.md');
74
+ if (!existsSync(readmePath)) {
75
+ console.log(ui.warning(` ⚠ README not found at ${readmePath}`));
76
+ console.log(ui.dim(' Create docs/sell-apps/README.md with spec URLs'));
77
+ return 0;
78
+ }
79
+ const readmeContent = readFileSync(readmePath, 'utf-8');
80
+ const urlRegex = /(https:\/\/[^\s)]+\.json)/g;
81
+ const urls = Array.from(readmeContent.matchAll(urlRegex)).map((m) => m[1]);
82
+ if (urls.length === 0) {
83
+ console.log(ui.warning(' ⚠ No spec URLs found in README'));
84
+ return 0;
85
+ }
86
+ console.log(ui.dim(` Found ${urls.length} spec URLs\n`));
87
+ let downloaded = 0;
88
+ for (const url of urls) {
89
+ const fileName = basename(url);
90
+ const folderName = SPEC_FOLDER_MAP[fileName] || 'other-apis';
91
+ const folderPath = join(DOCS_DIR, folderName);
92
+ const filePath = join(folderPath, fileName);
93
+ try {
94
+ mkdirSync(folderPath, { recursive: true });
95
+ const stopSpinner = showSpinner(`Downloading ${fileName}...`);
96
+ const response = await axios.get(url, { responseType: 'arraybuffer' });
97
+ stopSpinner();
98
+ writeFileSync(filePath, response.data);
99
+ console.log(` ${ui.success('āœ“')} ${fileName}`);
100
+ downloaded++;
101
+ }
102
+ catch (error) {
103
+ console.log(` ${ui.error('āœ—')} ${fileName}: ${error.message}`);
104
+ }
105
+ }
106
+ return downloaded;
107
+ }
108
+ function generateTypes() {
109
+ console.log(ui.bold('\nšŸ”§ Generating TypeScript Types\n'));
110
+ let generated = 0;
111
+ let skipped = 0;
112
+ function processDirectory(dir) {
113
+ if (!existsSync(dir))
114
+ return;
115
+ const entries = readdirSync(dir, { withFileTypes: true });
116
+ for (const entry of entries) {
117
+ const fullPath = join(dir, entry.name);
118
+ if (entry.isDirectory()) {
119
+ processDirectory(fullPath);
120
+ }
121
+ else if (entry.name.endsWith('.json')) {
122
+ try {
123
+ const content = readFileSync(fullPath, 'utf-8');
124
+ if (!content.includes('"openapi"') && !content.includes('"swagger"')) {
125
+ skipped++;
126
+ continue;
127
+ }
128
+ const relativePath = fullPath.replace(DOCS_DIR + '/', '');
129
+ const outputDir = join(TYPES_DIR, dirname(relativePath));
130
+ mkdirSync(outputDir, { recursive: true });
131
+ const baseFileName = basename(entry.name, '.json');
132
+ const camelCaseName = baseFileName
133
+ .split(/[_.-]/)
134
+ .map((part, i) => i === 0
135
+ ? part.toLowerCase()
136
+ : part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
137
+ .join('');
138
+ const outputPath = join(outputDir, `${camelCaseName}.ts`);
139
+ try {
140
+ execSync(`npx openapi-typescript "${fullPath}" -o "${outputPath}" --silent`, {
141
+ stdio: 'pipe',
142
+ cwd: PROJECT_ROOT,
143
+ });
144
+ console.log(` ${ui.success('āœ“')} ${camelCaseName}.ts`);
145
+ generated++;
146
+ }
147
+ catch {
148
+ console.log(` ${ui.error('āœ—')} ${camelCaseName}.ts (generation failed)`);
149
+ }
150
+ }
151
+ catch {
152
+ skipped++;
153
+ }
154
+ }
155
+ }
156
+ }
157
+ processDirectory(DOCS_DIR);
158
+ console.log(ui.dim(`\n Generated: ${generated}, Skipped: ${skipped}`));
159
+ return generated;
160
+ }
161
+ function extractEndpointsFromSpecs() {
162
+ const endpoints = [];
163
+ function processDirectory(dir) {
164
+ if (!existsSync(dir))
165
+ return;
166
+ const entries = readdirSync(dir, { withFileTypes: true });
167
+ for (const entry of entries) {
168
+ const fullPath = join(dir, entry.name);
169
+ if (entry.isDirectory()) {
170
+ processDirectory(fullPath);
171
+ }
172
+ else if (entry.name.endsWith('.json')) {
173
+ try {
174
+ const content = readFileSync(fullPath, 'utf-8');
175
+ const spec = JSON.parse(content);
176
+ if (!spec.paths)
177
+ continue;
178
+ for (const [path, methods] of Object.entries(spec.paths)) {
179
+ for (const [method, details] of Object.entries(methods)) {
180
+ if (['get', 'post', 'put', 'delete', 'patch'].includes(method.toLowerCase())) {
181
+ endpoints.push({
182
+ path,
183
+ method: method.toUpperCase(),
184
+ operationId: details.operationId || `${method}_${path}`,
185
+ summary: details.summary || '',
186
+ });
187
+ }
188
+ }
189
+ }
190
+ }
191
+ catch {
192
+ continue;
193
+ }
194
+ }
195
+ }
196
+ }
197
+ processDirectory(DOCS_DIR);
198
+ return endpoints;
199
+ }
200
+ function getImplementedTools() {
201
+ const tools = new Set();
202
+ if (!existsSync(TOOLS_DIR))
203
+ return tools;
204
+ const files = readdirSync(TOOLS_DIR, { withFileTypes: true });
205
+ for (const file of files) {
206
+ if (file.isFile() && file.name.endsWith('.ts')) {
207
+ const content = readFileSync(join(TOOLS_DIR, file.name), 'utf-8');
208
+ const nameMatches = content.matchAll(/name:\s*['"`]([^'"`]+)['"`]/g);
209
+ for (const match of nameMatches) {
210
+ tools.add(match[1]);
211
+ }
212
+ }
213
+ }
214
+ return tools;
215
+ }
216
+ function camelToSnake(str) {
217
+ return str
218
+ .replace(/([A-Z])/g, '_$1')
219
+ .toLowerCase()
220
+ .replace(/^_/, '');
221
+ }
222
+ function normalizeForMatching(name) {
223
+ return name.toLowerCase().replace(/[^a-z0-9]/g, '');
224
+ }
225
+ /**
226
+ * Known mappings from OpenAPI operationId to our tool names
227
+ * This handles cases where naming conventions differ significantly
228
+ */
229
+ const KNOWN_OPERATION_MAPPINGS = {
230
+ // Feedback API
231
+ getitemsawaitingfeedback: ['ebay_get_awaiting_feedback'],
232
+ leavefeedback: ['ebay_leave_feedback_for_buyer'],
233
+ // Notification API
234
+ getconfig: ['ebay_get_notification_config'],
235
+ updateconfig: ['ebay_update_notification_config'],
236
+ getdestinations: ['ebay_get_destinations'],
237
+ createdestination: ['ebay_create_destination'],
238
+ getdestination: ['ebay_get_destination'],
239
+ updatedestination: ['ebay_update_destination'],
240
+ deletedestination: ['ebay_delete_destination'],
241
+ getsubscriptions: ['ebay_get_subscriptions'],
242
+ createsubscription: ['ebay_create_subscription'],
243
+ getsubscription: ['ebay_get_subscription'],
244
+ updatesubscription: ['ebay_update_subscription'],
245
+ deletesubscription: ['ebay_delete_subscription'],
246
+ disablesubscription: ['ebay_disable_subscription'],
247
+ enablesubscription: ['ebay_enable_subscription'],
248
+ testsubscription: ['ebay_test_subscription'],
249
+ createsubscriptionfilter: ['ebay_create_subscription_filter'],
250
+ getsubscriptionfilter: ['ebay_get_subscription_filter'],
251
+ deletesubscriptionfilter: ['ebay_delete_subscription_filter'],
252
+ gettopic: ['ebay_get_topic'],
253
+ gettopics: ['ebay_get_topics'],
254
+ getpublickey: ['ebay_get_public_key'],
255
+ // Negotiation API
256
+ findeligibleitems: ['ebay_find_eligible_items'],
257
+ // Inventory API
258
+ createorreplaceinventoryitem: [
259
+ 'ebay_create_or_update_inventory_item',
260
+ 'ebay_create_inventory_item',
261
+ ],
262
+ getskulocationmapping: ['ebay_get_listing_locations'],
263
+ createinventorylocation: [
264
+ 'ebay_create_or_replace_inventory_location',
265
+ 'ebay_create_inventory_location',
266
+ ],
267
+ updateinventorylocation: ['ebay_update_location_details'],
268
+ // Marketing API
269
+ createadbylistingid: ['ebay_create_ad'],
270
+ updatebid: ['ebay_update_bid', 'ebay_update_bidding_strategy'],
271
+ bulkcreatekeyword: ['ebay_bulk_create_keywords'],
272
+ bulkupdatekeyword: ['ebay_bulk_update_keyword_bids'],
273
+ bulkcreatenegativekeyword: ['ebay_bulk_create_negative_keywords'],
274
+ bulkupdatenegativekeyword: ['ebay_bulk_update_negative_keywords'],
275
+ getnegativekeywords: ['ebay_get_negative_keywords'],
276
+ createnegativekeyword: ['ebay_create_negative_keyword'],
277
+ getnegativekeyword: ['ebay_get_negative_keyword'],
278
+ updatenegativekeyword: ['ebay_update_negative_keyword'],
279
+ getreportmetadata: ['ebay_get_ad_report_metadata'],
280
+ getreportmetadataforreporttype: [
281
+ 'ebay_get_ad_report_metadata_for_report_type',
282
+ 'ebay_get_ad_report_metadata_for_type',
283
+ ],
284
+ getpromotionreports: ['ebay_get_promotion_report', 'ebay_get_promotion_reports'],
285
+ getaudiences: ['ebay_get_audiences'],
286
+ // Dispute/Fulfillment API
287
+ fetchevidencecontent: ['ebay_fetch_evidence_content'],
288
+ getactivities: ['ebay_get_payment_dispute_activities', 'ebay_get_activities'],
289
+ uploadevidencefile: ['ebay_upload_evidence_file'],
290
+ addevidence: ['ebay_add_evidence'],
291
+ updateevidence: ['ebay_update_evidence'],
292
+ // Logistics/eDelivery API
293
+ getpackagesbylineitemid: ['ebay_get_package_by_order_line_item'],
294
+ getservices: ['ebay_get_shipping_services', 'ebay_get_services'],
295
+ };
296
+ /**
297
+ * Get all implemented API methods from source files
298
+ */
299
+ function getImplementedApiMethods() {
300
+ const methods = new Set();
301
+ const apiDir = join(PROJECT_ROOT, 'src/api');
302
+ function processDirectory(dir) {
303
+ if (!existsSync(dir))
304
+ return;
305
+ const entries = readdirSync(dir, { withFileTypes: true });
306
+ for (const entry of entries) {
307
+ const fullPath = join(dir, entry.name);
308
+ if (entry.isDirectory()) {
309
+ processDirectory(fullPath);
310
+ }
311
+ else if (entry.name.endsWith('.ts')) {
312
+ try {
313
+ const content = readFileSync(fullPath, 'utf-8');
314
+ // Match async method definitions
315
+ const methodMatches = content.matchAll(/async\s+(\w+)\s*\(/g);
316
+ for (const match of methodMatches) {
317
+ methods.add(normalizeForMatching(match[1]));
318
+ }
319
+ }
320
+ catch {
321
+ continue;
322
+ }
323
+ }
324
+ }
325
+ }
326
+ processDirectory(apiDir);
327
+ return methods;
328
+ }
329
+ /**
330
+ * Generate all possible name variations for an operationId
331
+ */
332
+ function generateNameVariations(opId) {
333
+ const variations = [];
334
+ const normalized = normalizeForMatching(opId);
335
+ // Direct variations
336
+ variations.push(normalized);
337
+ variations.push(`ebay${normalized}`);
338
+ variations.push(normalizeForMatching(`ebay_${camelToSnake(opId)}`));
339
+ variations.push(normalizeForMatching(camelToSnake(opId)));
340
+ // Remove common suffixes/prefixes that might differ
341
+ const withoutItems = normalized.replace(/items?$/, '');
342
+ if (withoutItems !== normalized) {
343
+ variations.push(withoutItems);
344
+ variations.push(`ebay${withoutItems}`);
345
+ }
346
+ // Handle "ByX" patterns -> remove them
347
+ const withoutBy = normalized.replace(/by\w+$/, '');
348
+ if (withoutBy !== normalized) {
349
+ variations.push(withoutBy);
350
+ variations.push(`ebay${withoutBy}`);
351
+ }
352
+ // Handle "ForX" patterns -> remove them
353
+ const withoutFor = normalized.replace(/for\w+$/, '');
354
+ if (withoutFor !== normalized) {
355
+ variations.push(withoutFor);
356
+ variations.push(`ebay${withoutFor}`);
357
+ }
358
+ // Handle plural/singular
359
+ if (normalized.endsWith('s') && !normalized.endsWith('ss')) {
360
+ const singular = normalized.slice(0, -1);
361
+ variations.push(singular);
362
+ variations.push(`ebay${singular}`);
363
+ }
364
+ else {
365
+ const plural = normalized + 's';
366
+ variations.push(plural);
367
+ variations.push(`ebay${plural}`);
368
+ }
369
+ // Check known mappings
370
+ if (KNOWN_OPERATION_MAPPINGS[normalized]) {
371
+ for (const mapped of KNOWN_OPERATION_MAPPINGS[normalized]) {
372
+ variations.push(normalizeForMatching(mapped));
373
+ }
374
+ }
375
+ return [...new Set(variations)];
376
+ }
377
+ function analyzeEndpoints() {
378
+ console.log(ui.bold('\nšŸ“Š Analyzing API Coverage\n'));
379
+ const specEndpoints = extractEndpointsFromSpecs();
380
+ const implementedTools = getImplementedTools();
381
+ const implementedApiMethods = getImplementedApiMethods();
382
+ // Normalize all tool names
383
+ const normalizedTools = new Set(Array.from(implementedTools).map((t) => normalizeForMatching(t)));
384
+ // Combine tools and API methods for matching
385
+ const allImplemented = new Set([...normalizedTools, ...implementedApiMethods]);
386
+ // Track unique endpoints (dedupe by operationId)
387
+ const seenOperationIds = new Set();
388
+ const uniqueEndpoints = [];
389
+ for (const endpoint of specEndpoints) {
390
+ const normalizedOpId = normalizeForMatching(endpoint.operationId);
391
+ if (!seenOperationIds.has(normalizedOpId)) {
392
+ seenOperationIds.add(normalizedOpId);
393
+ uniqueEndpoints.push(endpoint);
394
+ }
395
+ }
396
+ const missing = [];
397
+ let matchedCount = 0;
398
+ for (const endpoint of uniqueEndpoints) {
399
+ const opId = endpoint.operationId;
400
+ const variations = generateNameVariations(opId);
401
+ const isImplemented = variations.some((name) => allImplemented.has(name));
402
+ if (isImplemented) {
403
+ matchedCount++;
404
+ }
405
+ else {
406
+ missing.push(endpoint);
407
+ }
408
+ }
409
+ const coveragePercent = uniqueEndpoints.length > 0 ? ((matchedCount / uniqueEndpoints.length) * 100).toFixed(1) : '0';
410
+ console.log(` ${ui.info('Total unique endpoints in specs:')} ${uniqueEndpoints.length}`);
411
+ console.log(` ${ui.info('(Raw count with duplicates:')} ${specEndpoints.length}${ui.info(')')}`);
412
+ console.log(` ${ui.success('Tools implemented:')} ${implementedTools.size}`);
413
+ console.log(` ${ui.success('API methods found:')} ${implementedApiMethods.size}`);
414
+ console.log(` ${ui.success('Endpoints covered:')} ${matchedCount} (${coveragePercent}%)`);
415
+ console.log(` ${ui.warning('Potentially missing:')} ${missing.length}`);
416
+ return {
417
+ total: uniqueEndpoints.length,
418
+ implemented: matchedCount,
419
+ missing,
420
+ };
421
+ }
422
+ function showMissingEndpoints(missing) {
423
+ if (missing.length === 0) {
424
+ console.log(ui.success('\n āœ“ All endpoints appear to be implemented!\n'));
425
+ return;
426
+ }
427
+ console.log(ui.bold('\nšŸ“‹ Potentially Missing Endpoints\n'));
428
+ console.log(ui.dim(' These endpoints were found in specs but may not have corresponding tools:\n'));
429
+ const grouped = missing.reduce((acc, ep) => {
430
+ const key = ep.path.split('/')[1] || 'other';
431
+ if (!acc[key])
432
+ acc[key] = [];
433
+ acc[key].push(ep);
434
+ return acc;
435
+ }, {});
436
+ for (const [group, endpoints] of Object.entries(grouped).slice(0, 10)) {
437
+ console.log(` ${ui.bold(group)}`);
438
+ for (const ep of endpoints.slice(0, 5)) {
439
+ console.log(` ${ui.dim(ep.method.padEnd(6))} ${ep.path}`);
440
+ if (ep.summary) {
441
+ console.log(` ${ui.dim(ep.summary.slice(0, 50))}`);
442
+ }
443
+ }
444
+ if (endpoints.length > 5) {
445
+ console.log(` ${ui.dim(`... and ${endpoints.length - 5} more`)}`);
446
+ }
447
+ console.log('');
448
+ }
449
+ if (Object.keys(grouped).length > 10) {
450
+ console.log(ui.dim(` ... and ${Object.keys(grouped).length - 10} more API groups\n`));
451
+ }
452
+ }
453
+ function generateReport(report) {
454
+ const reportPath = join(PROJECT_ROOT, 'dev-sync-report.json');
455
+ writeFileSync(reportPath, JSON.stringify(report, null, 2));
456
+ console.log(ui.dim(`\n Report saved to: ${reportPath}\n`));
457
+ }
458
+ async function main() {
459
+ console.clear();
460
+ console.log(ui.bold.cyan(`
461
+ ╔════════════════════════════════════════════════════════════╗
462
+ ā•‘ eBay MCP Server - Developer Sync Tool ā•‘
463
+ ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•
464
+ `));
465
+ const args = process.argv.slice(2);
466
+ const skipDownload = args.includes('--skip-download');
467
+ const skipTypes = args.includes('--skip-types');
468
+ const reportOnly = args.includes('--report');
469
+ if (args.includes('--help') || args.includes('-h')) {
470
+ console.log(`
471
+ ${ui.bold('Usage:')}
472
+ npm run sync [options]
473
+
474
+ ${ui.bold('Options:')}
475
+ --skip-download Skip downloading OpenAPI specs
476
+ --skip-types Skip generating TypeScript types
477
+ --report Only generate coverage report
478
+ --help, -h Show this help
479
+
480
+ ${ui.bold('What this does:')}
481
+ 1. Downloads latest OpenAPI specs from eBay
482
+ 2. Generates TypeScript types from specs
483
+ 3. Analyzes which endpoints are implemented
484
+ 4. Reports missing endpoints to implement
485
+ `);
486
+ process.exit(0);
487
+ }
488
+ const report = {
489
+ specsDownloaded: 0,
490
+ typesGenerated: 0,
491
+ endpointsInSpecs: 0,
492
+ toolsImplemented: 0,
493
+ missingEndpoints: [],
494
+ };
495
+ if (!reportOnly && !skipDownload) {
496
+ report.specsDownloaded = await downloadSpecs();
497
+ }
498
+ if (!reportOnly && !skipTypes) {
499
+ report.typesGenerated = generateTypes();
500
+ }
501
+ const analysis = analyzeEndpoints();
502
+ report.endpointsInSpecs = analysis.total;
503
+ report.toolsImplemented = analysis.implemented;
504
+ report.missingEndpoints = analysis.missing;
505
+ showMissingEndpoints(analysis.missing);
506
+ generateReport(report);
507
+ console.log(ui.bold.green('āœ“ Sync complete!\n'));
508
+ }
509
+ main().catch((error) => {
510
+ console.error(ui.error('\n Sync failed:'), error);
511
+ process.exit(1);
512
+ });