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.
- package/LICENSE +21 -0
- package/README.md +755 -0
- package/build/api/account-management/account.js +301 -0
- package/build/api/analytics-and-report/analytics.js +102 -0
- package/build/api/client-trading.js +96 -0
- package/build/api/client.js +173 -0
- package/build/api/communication/feedback.js +119 -0
- package/build/api/communication/message.js +131 -0
- package/build/api/communication/negotiation.js +97 -0
- package/build/api/communication/notification.js +373 -0
- package/build/api/developer/developer.js +81 -0
- package/build/api/index.js +109 -0
- package/build/api/listing-management/inventory.js +640 -0
- package/build/api/listing-metadata/metadata.js +485 -0
- package/build/api/listing-metadata/taxonomy.js +58 -0
- package/build/api/marketing-and-promotions/marketing.js +768 -0
- package/build/api/marketing-and-promotions/recommendation.js +32 -0
- package/build/api/order-management/dispute.js +69 -0
- package/build/api/order-management/fulfillment.js +89 -0
- package/build/api/other/compliance.js +47 -0
- package/build/api/other/edelivery.js +219 -0
- package/build/api/other/identity.js +24 -0
- package/build/api/other/translation.js +22 -0
- package/build/api/other/vero.js +48 -0
- package/build/api/trading/trading.js +78 -0
- package/build/auth/kv-store.js +40 -0
- package/build/auth/multi-user-store.js +120 -0
- package/build/auth/oauth-metadata.js +59 -0
- package/build/auth/oauth-middleware.js +99 -0
- package/build/auth/oauth-types.js +4 -0
- package/build/auth/oauth.js +235 -0
- package/build/auth/scope-utils.js +304 -0
- package/build/auth/token-store.js +46 -0
- package/build/auth/token-verifier.js +172 -0
- package/build/config/environment.js +297 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +129 -0
- package/build/schemas/account-management/account.js +375 -0
- package/build/schemas/analytics/analytics.js +191 -0
- package/build/schemas/communication/messages.js +345 -0
- package/build/schemas/fulfillment/orders.js +338 -0
- package/build/schemas/index.js +68 -0
- package/build/schemas/inventory-management/inventory.js +471 -0
- package/build/schemas/marketing/marketing.js +1103 -0
- package/build/schemas/metadata/metadata.js +618 -0
- package/build/schemas/other/other-apis.js +390 -0
- package/build/schemas/taxonomy/taxonomy.js +575 -0
- package/build/scripts/auto-setup.js +364 -0
- package/build/scripts/dev-sync.js +512 -0
- package/build/scripts/diagnostics.js +301 -0
- package/build/scripts/download-specs.js +116 -0
- package/build/scripts/interactive-setup.js +757 -0
- package/build/scripts/setup.js +1515 -0
- package/build/scripts/update-api-status-doc.js +44 -0
- package/build/server-http.d.ts +1 -0
- package/build/server-http.js +581 -0
- package/build/tools/definitions/account-with-schemas.js +170 -0
- package/build/tools/definitions/account.js +428 -0
- package/build/tools/definitions/analytics.js +66 -0
- package/build/tools/definitions/communication.js +394 -0
- package/build/tools/definitions/developer.js +195 -0
- package/build/tools/definitions/fulfillment.js +326 -0
- package/build/tools/definitions/index.js +41 -0
- package/build/tools/definitions/inventory.js +464 -0
- package/build/tools/definitions/marketing.js +1486 -0
- package/build/tools/definitions/metadata.js +188 -0
- package/build/tools/definitions/other.js +309 -0
- package/build/tools/definitions/taxonomy.js +64 -0
- package/build/tools/definitions/token-management.js +148 -0
- package/build/tools/definitions/trading.js +71 -0
- package/build/tools/index.js +1200 -0
- package/build/tools/schemas.js +667 -0
- package/build/tools/tool-definitions.js +3534 -0
- package/build/types/application-settings/developerAnalyticsV1BetaOas3.js +5 -0
- package/build/types/application-settings/developerClientRegistrationV1Oas3.js +5 -0
- package/build/types/application-settings/developerKeyManagementV1Oas3.js +5 -0
- package/build/types/ebay-enums.js +1330 -0
- package/build/types/ebay.js +123 -0
- package/build/types/index.js +10 -0
- package/build/types/sell-apps/account-management/sellAccountV1Oas3.js +5 -0
- package/build/types/sell-apps/analytics-and-report/sellAnalyticsV1Oas3.js +5 -0
- package/build/types/sell-apps/communication/commerceFeedbackV1BetaOas3.js +5 -0
- package/build/types/sell-apps/communication/commerceMessageV1Oas3.js +5 -0
- package/build/types/sell-apps/communication/commerceNotificationV1Oas3.js +5 -0
- package/build/types/sell-apps/communication/sellNegotiationV1Oas3.js +5 -0
- package/build/types/sell-apps/listing-management/sellInventoryV1Oas3.js +5 -0
- package/build/types/sell-apps/listing-metadata/sellMetadataV1Oas3.js +5 -0
- package/build/types/sell-apps/markeitng-and-promotions/sellMarketingV1Oas3.js +5 -0
- package/build/types/sell-apps/markeitng-and-promotions/sellRecommendationV1Oas3.js +5 -0
- package/build/types/sell-apps/order-management/sellFulfillmentV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/commerceIdentityV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/commerceTranslationV1BetaOas3.js +5 -0
- package/build/types/sell-apps/other-apis/commerceVeroV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/sellComplianceV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/sellEdeliveryInternationalShippingOas3.js +5 -0
- package/build/types/sell-apps/other-apis/sellMarketingV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/sellRecommendationV1Oas3.js +5 -0
- package/build/utils/account-management/account.js +831 -0
- package/build/utils/api-status-feed.js +83 -0
- package/build/utils/communication/feedback.js +216 -0
- package/build/utils/communication/message.js +242 -0
- package/build/utils/communication/negotiation.js +150 -0
- package/build/utils/communication/notification.js +369 -0
- package/build/utils/date-converter.js +160 -0
- package/build/utils/llm-client-detector.js +758 -0
- package/build/utils/logger.js +198 -0
- package/build/utils/oauth-helper.js +315 -0
- package/build/utils/order-management/dispute.js +369 -0
- package/build/utils/order-management/fulfillment.js +205 -0
- package/build/utils/other/compliance.js +76 -0
- package/build/utils/other/edelivery.js +241 -0
- package/build/utils/other/identity.js +13 -0
- package/build/utils/other/translation.js +41 -0
- package/build/utils/other/vero.js +90 -0
- package/build/utils/scope-helper.js +207 -0
- package/build/utils/security-checker.js +248 -0
- package/build/utils/setup-validator.js +305 -0
- package/build/utils/token-utils.js +40 -0
- package/build/utils/version.js +56 -0
- package/docs/auth/production_scopes.json +111 -0
- package/docs/auth/sandbox_scopes.json +142 -0
- package/package.json +122 -0
- package/public/icons/1024x1024.png +0 -0
- package/public/icons/128x128.png +0 -0
- package/public/icons/16x16.png +0 -0
- package/public/icons/256x256.png +0 -0
- package/public/icons/32x32.png +0 -0
- package/public/icons/48x48.png +0 -0
- 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
|
+
});
|