ebay-mcp 1.14.2 → 1.15.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/README.de.md +8 -8
- package/README.es.md +8 -8
- package/README.fr.md +8 -8
- package/README.ja.md +8 -8
- package/README.ko.md +8 -8
- package/README.md +25 -10
- package/README.pt-BR.md +8 -8
- package/README.ru.md +8 -8
- package/README.zh-CN.md +8 -8
- package/build/api/client.js +8 -2
- package/build/api/listing-management/offers.js +78 -23
- package/build/auth/credentialSession.js +55 -8
- package/build/auth/oauth.js +37 -10
- package/build/auth/scopeUtils.js +5 -0
- package/build/config/credentialFile.js +16 -0
- package/build/config/environment.js +2 -1
- package/build/index.js +5 -0
- package/build/mcp/runtime.js +17 -6
- package/build/schemas/inventory-management/inventory.js +21 -2
- package/build/scripts/diagnostics.js +21 -15
- package/build/skills/content.js +5 -6
- package/build/tools/categories/account.js +11 -2
- package/build/tools/categories/inventory.js +25 -8
- package/build/tools/categories/taxonomy.js +2 -2
- package/build/utils/errors.js +84 -0
- package/package.json +5 -5
|
@@ -55,7 +55,7 @@ const productIdentifierSchema = z.object({
|
|
|
55
55
|
ktype: z.string().optional(),
|
|
56
56
|
});
|
|
57
57
|
const productSchema = z.object({
|
|
58
|
-
title: z.string().optional(),
|
|
58
|
+
title: z.string().max(80).optional(),
|
|
59
59
|
aspects: z.record(z.array(z.string())).optional(),
|
|
60
60
|
brand: z.string().optional(),
|
|
61
61
|
description: z.string().optional(),
|
|
@@ -244,7 +244,7 @@ export const offerResponseSchema = offerSchema.extend({
|
|
|
244
244
|
*/
|
|
245
245
|
export const getOffersInputSchema = z.object({
|
|
246
246
|
format: z.string().optional().describe('Filter offers by listing format'),
|
|
247
|
-
sku: z.string().
|
|
247
|
+
sku: z.string().min(1).describe('Seller-defined SKU whose offers to return'),
|
|
248
248
|
marketplaceId: z.nativeEnum(MarketplaceId).optional().describe('Filter offers by marketplace'),
|
|
249
249
|
limit: z.number().optional().describe('Number of offers to return'),
|
|
250
250
|
offset: z.number().optional().describe('Number of offers to skip'),
|
|
@@ -263,6 +263,25 @@ export const getOffersOutputSchema = z.object({
|
|
|
263
263
|
total: z.number().optional(),
|
|
264
264
|
warnings: z.array(errorSchema).optional(),
|
|
265
265
|
});
|
|
266
|
+
/** Validates the aggregate response from the bounded multi-SKU offer lookup. */
|
|
267
|
+
export const getOffersBySkusOutputSchema = z.object({
|
|
268
|
+
requestedSkuCount: z.number(),
|
|
269
|
+
uniqueSkuCount: z.number(),
|
|
270
|
+
successCount: z.number(),
|
|
271
|
+
failureCount: z.number(),
|
|
272
|
+
results: z.array(z.union([
|
|
273
|
+
z.object({
|
|
274
|
+
sku: z.string(),
|
|
275
|
+
status: z.enum(['success']),
|
|
276
|
+
response: getOffersOutputSchema,
|
|
277
|
+
}),
|
|
278
|
+
z.object({
|
|
279
|
+
sku: z.string(),
|
|
280
|
+
status: z.enum(['failure']),
|
|
281
|
+
error: z.object({ type: z.string(), message: z.string() }),
|
|
282
|
+
}),
|
|
283
|
+
])),
|
|
284
|
+
});
|
|
266
285
|
/**
|
|
267
286
|
* Validates the Inventory Management API create offer request payload.
|
|
268
287
|
*/
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Usage:
|
|
5
5
|
* npm run diagnose
|
|
6
|
-
*
|
|
6
|
+
* ebay-mcp diagnose
|
|
7
|
+
* ebay-mcp diagnose --export
|
|
7
8
|
*/
|
|
8
9
|
import chalk from 'chalk';
|
|
9
10
|
import { writeFileSync } from 'fs';
|
|
10
|
-
import { join, dirname } from 'path';
|
|
11
|
+
import { join, dirname, resolve } from 'path';
|
|
11
12
|
import { fileURLToPath } from 'url';
|
|
12
13
|
import { runSecurityChecks, displaySecurityResults } from '../scripts/securityChecker.js';
|
|
13
14
|
import { validateSetup, displayRecommendations } from '../scripts/setupValidator.js';
|
|
@@ -235,7 +236,7 @@ async function generateDiagnosticReport(exportPath) {
|
|
|
235
236
|
/**
|
|
236
237
|
* Main diagnostics function
|
|
237
238
|
*/
|
|
238
|
-
|
|
239
|
+
export const runDiagnostics = async (exportReport = false) => {
|
|
239
240
|
displayHeader();
|
|
240
241
|
displaySystemInfo();
|
|
241
242
|
await displayUpdateStatus();
|
|
@@ -295,16 +296,21 @@ async function runDiagnostics(exportReport = false) {
|
|
|
295
296
|
console.log(chalk.bold.green('✅ Diagnostics complete!\n'));
|
|
296
297
|
console.log(chalk.gray('For more help, visit:'));
|
|
297
298
|
console.log(chalk.blue.underline(' https://github.com/YosefHayim/ebay-mcp#troubleshooting\n'));
|
|
299
|
+
};
|
|
300
|
+
// Direct script entry (`node build/scripts/diagnostics.js` / `npm run diagnose`).
|
|
301
|
+
// Guarded so importing from the bin does not auto-run diagnostics.
|
|
302
|
+
const entryPath = process.argv[1] ? resolve(process.argv[1]) : undefined;
|
|
303
|
+
const modulePath = resolve(fileURLToPath(import.meta.url));
|
|
304
|
+
if (entryPath && modulePath === entryPath) {
|
|
305
|
+
const cliArgs = process.argv.slice(2);
|
|
306
|
+
const exportReport = cliArgs.includes('--export') || cliArgs.includes('-e');
|
|
307
|
+
void Effect.runPromise(Effect.either(Effect.tryPromise({
|
|
308
|
+
try: () => runDiagnostics(exportReport),
|
|
309
|
+
catch: (error) => error,
|
|
310
|
+
}))).then((result) => {
|
|
311
|
+
if (Either.isLeft(result)) {
|
|
312
|
+
console.error(chalk.red('\n❌ Diagnostics failed:'), getErrorMessage(result.left));
|
|
313
|
+
process.exitCode = 1;
|
|
314
|
+
}
|
|
315
|
+
});
|
|
298
316
|
}
|
|
299
|
-
// CLI handler
|
|
300
|
-
const args = process.argv.slice(2);
|
|
301
|
-
const exportReport = args.includes('--export') || args.includes('-e');
|
|
302
|
-
void Effect.runPromise(Effect.either(Effect.tryPromise({
|
|
303
|
-
try: () => runDiagnostics(exportReport),
|
|
304
|
-
catch: (error) => error,
|
|
305
|
-
}))).then((result) => {
|
|
306
|
-
if (Either.isLeft(result)) {
|
|
307
|
-
console.error(chalk.red('\n❌ Diagnostics failed:'), getErrorMessage(result.left));
|
|
308
|
-
process.exitCode = 1;
|
|
309
|
-
}
|
|
310
|
-
});
|
package/build/skills/content.js
CHANGED
|
@@ -40,12 +40,10 @@ export const buildUsingDoc = (snapshot) => ({
|
|
|
40
40
|
body: [
|
|
41
41
|
'**Publish a fixed-price listing (REST Inventory model).**',
|
|
42
42
|
'1. One-time account setup: `ebay_opt_in_to_program` (business-policy management), then `ebay_create_payment_policy`, `ebay_create_return_policy`, `ebay_create_fulfillment_policy` for reusable policy IDs, and `ebay_create_inventory_location` for a `merchantLocationKey`.',
|
|
43
|
-
'2. `
|
|
44
|
-
'3. `
|
|
45
|
-
'4. `
|
|
46
|
-
'',
|
|
47
|
-
'**Pick the right category & required item specifics first.**',
|
|
48
|
-
'`ebay_get_default_category_tree_id` (marketplace) → `ebay_get_category_suggestions` (query) → `ebay_get_item_aspects_for_category` to learn the required aspects to put on the inventory item.',
|
|
43
|
+
'2. Pick the category and fetch its current item-specific requirements: `ebay_get_default_category_tree_id` (marketplace) → `ebay_get_category_suggestions` (query) → `ebay_get_item_aspects_for_category`.',
|
|
44
|
+
'3. Add every required aspect from that response to `ebay_create_or_replace_inventory_item` (SKU + product details + availability). Requirements vary by category and marketplace; do not treat examples from another category as permanent rules.',
|
|
45
|
+
'4. `ebay_create_offer` (SKU, marketplace, price, the policy IDs, location).',
|
|
46
|
+
'5. Check the aspects again when the category changes and before `ebay_get_listing_fees`, then `ebay_publish_offer` (offerId) → a live `listingId`. Use `ebay_bulk_publish_offer` for many at once.',
|
|
49
47
|
'',
|
|
50
48
|
'**Fulfill an order.**',
|
|
51
49
|
'`ebay_get_orders` (filter unfulfilled) → `ebay_get_order` (detail) → `ebay_create_shipping_fulfillment` (tracking number + carrier).',
|
|
@@ -68,6 +66,7 @@ export const buildUsingDoc = (snapshot) => ({
|
|
|
68
66
|
body: [
|
|
69
67
|
'- **Two listing models.** REST Inventory (`inventory_item` → `offer` → `publish`) vs legacy Trading (XML). Pick one per SKU and stay in it.',
|
|
70
68
|
'- **Offers need policies + a location first.** A "policy not found" error usually means the one-time account setup was skipped.',
|
|
69
|
+
'- **Item specifics are category-specific.** Use `ebay_get_item_aspects_for_category` for the selected category instead of relying on a fixed fallback value or requirements learned from another category.',
|
|
71
70
|
'- **`search` and `fetch` are ChatGPT-connector only** — ignore them when driving the Sell API directly.',
|
|
72
71
|
'- **Write actions are real.** `publish`, `issue_refund`, `end_listing`, and any `bulk_*` change live seller data — confirm intent before calling.',
|
|
73
72
|
].join('\n'),
|
|
@@ -63,7 +63,16 @@ export const accountEntries = [
|
|
|
63
63
|
}),
|
|
64
64
|
defineTool({
|
|
65
65
|
name: 'ebay_create_fulfillment_policy',
|
|
66
|
-
description: 'Create a new fulfillment policy.\n\
|
|
66
|
+
description: 'Create a new fulfillment policy.\n\n' +
|
|
67
|
+
'shippingServiceCode must be a marketplace-valid eBay service enum (not a free-form carrier nickname). ' +
|
|
68
|
+
'Invalid codes return "Please select a valid shipping service". eBay may cite DomesticItemShippingService[0] ' +
|
|
69
|
+
'and [1] for a single bad entry — that is remote validation, not client array duplication. ' +
|
|
70
|
+
'Discover valid codes via Trading GeteBayDetails (ShippingServiceDetails). ' +
|
|
71
|
+
'Known-good EBAY_US FLAT_RATE sketch: policy.name, policy.marketplaceId=EBAY_US, ' +
|
|
72
|
+
'policy.categoryTypes=[{name:ALL_EXCLUDING_MOTORS_VEHICLES}], policy.handlingTime={unit:DAY,value:1}, ' +
|
|
73
|
+
'policy.shippingOptions=[{costType:FLAT_RATE,optionType:DOMESTIC,shippingServices:[{shippingServiceCode:USPSPriority,shippingCost:{currency:USD,value:"5.99"}}]}]. ' +
|
|
74
|
+
'Avoid invented codes like USPSPriorityMail. Sandbox may accept a smaller code set than production.\n\n' +
|
|
75
|
+
'Required OAuth Scope: sell.account\nMinimum Scope: https://api.ebay.com/oauth/api_scope/sell.account',
|
|
67
76
|
inputSchema: createFulfillmentPolicyInputSchema.shape,
|
|
68
77
|
outputSchema: zodToJsonSchema(createFulfillmentPolicyOutputSchema, {
|
|
69
78
|
name: 'CreateFulfillmentPolicyResponse',
|
|
@@ -96,7 +105,7 @@ export const accountEntries = [
|
|
|
96
105
|
}),
|
|
97
106
|
defineTool({
|
|
98
107
|
name: 'ebay_update_fulfillment_policy',
|
|
99
|
-
description: 'Update an existing fulfillment policy',
|
|
108
|
+
description: 'Update an existing fulfillment policy.\n\nRequired OAuth Scope: sell.account\nMinimum Scope: https://api.ebay.com/oauth/api_scope/sell.account',
|
|
100
109
|
inputSchema: updateFulfillmentPolicyInputSchema.shape,
|
|
101
110
|
outputSchema: zodToJsonSchema(createFulfillmentPolicyOutputSchema, {
|
|
102
111
|
name: 'UpdateFulfillmentPolicyResponse',
|
|
@@ -4,7 +4,7 @@ import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
|
4
4
|
import { defineTool } from '../../tools/defineTool.js';
|
|
5
5
|
import { mapInventoryItemsToTable, mapInventoryItemToCard, mapLocationsToTable, mapOffersToTable, mapOfferToCard, } from '../../tools/ui/maps.js';
|
|
6
6
|
import { MarketplaceId } from '../../types/ebayEnums.js';
|
|
7
|
-
import { bulkInventoryItemResponseSchema, bulkOfferResponseSchema, bulkPublishResponseSchema, createInventoryItemOutputSchema, createInventoryLocationOutputSchema, createOfferOutputSchema, getInventoryItemGroupOutputSchema, getInventoryItemOutputSchema, getInventoryItemsOutputSchema, getInventoryLocationsOutputSchema, getOffersOutputSchema, getProductCompatibilityOutputSchema, offerResponseSchema, publishOfferOutputSchema, } from '../../schemas/inventory-management/inventory.js';
|
|
7
|
+
import { bulkInventoryItemResponseSchema, bulkOfferResponseSchema, bulkPublishResponseSchema, createInventoryItemOutputSchema, createInventoryLocationOutputSchema, createOfferOutputSchema, getInventoryItemGroupOutputSchema, getInventoryItemOutputSchema, getInventoryItemsOutputSchema, getInventoryLocationsOutputSchema, getOffersInputSchema, getOffersOutputSchema, getOffersBySkusOutputSchema, getProductCompatibilityOutputSchema, inventoryItemSchema, offerResponseSchema, publishOfferOutputSchema, } from '../../schemas/inventory-management/inventory.js';
|
|
8
8
|
const emptyOutputSchema = {
|
|
9
9
|
type: 'object',
|
|
10
10
|
properties: {},
|
|
@@ -23,7 +23,7 @@ const inventoryPaginationInputSchema = z.object({
|
|
|
23
23
|
offset: z.number().optional().describe('Number of records to skip'),
|
|
24
24
|
});
|
|
25
25
|
const createOrReplaceInventoryItemInputSchema = skuInputSchema.extend({
|
|
26
|
-
body:
|
|
26
|
+
body: inventoryItemSchema,
|
|
27
27
|
});
|
|
28
28
|
const bulkCreateOrReplaceInventoryItemInputSchema = z.object({
|
|
29
29
|
body: generatedBodySchema('Generated BulkInventoryItem request body'),
|
|
@@ -52,12 +52,14 @@ const createInventoryLocationInputSchema = merchantLocationKeyInputSchema.extend
|
|
|
52
52
|
const updateInventoryLocationInputSchema = merchantLocationKeyInputSchema.extend({
|
|
53
53
|
body: generatedBodySchema('Generated InventoryLocation request body'),
|
|
54
54
|
});
|
|
55
|
-
const
|
|
55
|
+
const getOffersBySkusInputSchema = z.object({
|
|
56
|
+
skus: z
|
|
57
|
+
.array(z.string().min(1).max(50))
|
|
58
|
+
.min(1)
|
|
59
|
+
.max(25)
|
|
60
|
+
.describe('1-25 seller SKUs; exact duplicates are queried once in first-occurrence order'),
|
|
56
61
|
format: z.string().optional().describe('Filter by listing format'),
|
|
57
|
-
limit: z.number().optional().describe('Number of offers to return'),
|
|
58
62
|
marketplaceId: z.nativeEnum(MarketplaceId).optional().describe('Filter by marketplace ID'),
|
|
59
|
-
offset: z.number().optional().describe('Number of offers to skip'),
|
|
60
|
-
sku: z.string().optional().describe('Filter by SKU'),
|
|
61
63
|
});
|
|
62
64
|
const offerIdInputSchema = z.object({
|
|
63
65
|
offerId: z.string().describe('The offer ID'),
|
|
@@ -145,7 +147,12 @@ export const inventoryEntries = [
|
|
|
145
147
|
name: 'CreateOrReplaceInventoryItemResponse',
|
|
146
148
|
$refStrategy: 'none',
|
|
147
149
|
}),
|
|
148
|
-
handler: (api, args) => Effect.runPromise(api.inventory.createOrReplaceInventoryItem(
|
|
150
|
+
handler: (api, args) => Effect.runPromise(api.inventory.createOrReplaceInventoryItem({
|
|
151
|
+
...args,
|
|
152
|
+
// The generated OpenAPI type incorrectly models `product.aspects` as a
|
|
153
|
+
// string; the endpoint wire contract and validation schema use a map.
|
|
154
|
+
body: args.body,
|
|
155
|
+
})),
|
|
149
156
|
}),
|
|
150
157
|
defineTool({
|
|
151
158
|
name: 'ebay_delete_inventory_item',
|
|
@@ -302,7 +309,7 @@ export const inventoryEntries = [
|
|
|
302
309
|
}),
|
|
303
310
|
defineTool({
|
|
304
311
|
name: 'ebay_get_offers',
|
|
305
|
-
description: 'Get
|
|
312
|
+
description: 'Get offers for one seller-defined SKU. To enumerate offers across SKUs, call ebay_get_inventory_items first, then call this tool once per SKU.',
|
|
306
313
|
inputSchema: getOffersInputSchema.shape,
|
|
307
314
|
outputSchema: zodToJsonSchema(getOffersOutputSchema, {
|
|
308
315
|
name: 'GetOffersResponse',
|
|
@@ -311,6 +318,16 @@ export const inventoryEntries = [
|
|
|
311
318
|
handler: (api, args) => Effect.runPromise(api.inventory.getOffers(args)),
|
|
312
319
|
ui: { archetype: 'table', map: mapOffersToTable },
|
|
313
320
|
}),
|
|
321
|
+
defineTool({
|
|
322
|
+
name: 'ebay_get_offers_by_skus',
|
|
323
|
+
description: 'Get offers for 1-25 SKUs. Exact duplicates are queried once, at most 3 eBay requests run concurrently, and every SKU has its own success or failure result.',
|
|
324
|
+
inputSchema: getOffersBySkusInputSchema.shape,
|
|
325
|
+
outputSchema: zodToJsonSchema(getOffersBySkusOutputSchema, {
|
|
326
|
+
name: 'GetOffersBySkusResponse',
|
|
327
|
+
$refStrategy: 'none',
|
|
328
|
+
}),
|
|
329
|
+
handler: (api, args) => Effect.runPromise(api.inventory.getOffersBySkus(args)),
|
|
330
|
+
}),
|
|
314
331
|
defineTool({
|
|
315
332
|
name: 'ebay_get_offer',
|
|
316
333
|
description: 'Get a specific offer by ID',
|
|
@@ -65,14 +65,14 @@ export const taxonomyEntries = [
|
|
|
65
65
|
}),
|
|
66
66
|
defineTool({
|
|
67
67
|
name: 'ebay_get_item_aspects_for_category',
|
|
68
|
-
description: '
|
|
68
|
+
description: 'Identify required and recommended item specifics for a category before creating an inventory item or checking listing fees',
|
|
69
69
|
inputSchema: getItemAspectsForCategorySchema.shape,
|
|
70
70
|
outputSchema: {
|
|
71
71
|
type: 'object',
|
|
72
72
|
properties: {
|
|
73
73
|
aspects: { type: 'array' },
|
|
74
74
|
},
|
|
75
|
-
description: '
|
|
75
|
+
description: 'Required and recommended item specifics for the category',
|
|
76
76
|
},
|
|
77
77
|
handler: (api, args) => Effect.runPromise(api.taxonomy.getItemAspectsForCategory(args)),
|
|
78
78
|
}),
|
package/build/utils/errors.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Cause, Runtime } from 'effect';
|
|
1
2
|
/**
|
|
2
3
|
* Normalize an unknown thrown value into a human-readable message string.
|
|
3
4
|
*
|
|
@@ -18,3 +19,86 @@
|
|
|
18
19
|
* ```
|
|
19
20
|
*/
|
|
20
21
|
export const getErrorMessage = (error, fallback = 'Unknown error') => error instanceof Error ? error.message : fallback;
|
|
22
|
+
const asRecord = (value) => typeof value === 'object' && value !== null ? value : undefined;
|
|
23
|
+
const nextErrorNode = (node) => {
|
|
24
|
+
const fiberCause = node[Runtime.FiberFailureCauseId];
|
|
25
|
+
if (fiberCause !== undefined) {
|
|
26
|
+
return Cause.squash(fiberCause);
|
|
27
|
+
}
|
|
28
|
+
return node.cause;
|
|
29
|
+
};
|
|
30
|
+
const firstEbayErrorMessage = (errors) => {
|
|
31
|
+
const first = asRecord(errors[0]);
|
|
32
|
+
if (!first) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const detail = first.longMessage ?? first.message;
|
|
36
|
+
return typeof detail === 'string' ? detail : undefined;
|
|
37
|
+
};
|
|
38
|
+
const KIND_IS_GUIDANCE = {
|
|
39
|
+
missingCredentials: true,
|
|
40
|
+
localRateLimit: true,
|
|
41
|
+
tokenAcquisition: true,
|
|
42
|
+
missingAccessToken: true,
|
|
43
|
+
tokenRefresh: true,
|
|
44
|
+
remoteRateLimit: true,
|
|
45
|
+
httpStatus: false,
|
|
46
|
+
transport: false,
|
|
47
|
+
};
|
|
48
|
+
const isGuidanceKind = (kind) => Object.hasOwn(KIND_IS_GUIDANCE, kind) && KIND_IS_GUIDANCE[kind];
|
|
49
|
+
const collectEbayErrorNode = (node, acc) => {
|
|
50
|
+
const message = typeof node.message === 'string' && node.message.length > 0 ? node.message : undefined;
|
|
51
|
+
if (message !== undefined && !acc.messageLocked) {
|
|
52
|
+
acc.message = message;
|
|
53
|
+
if (typeof node.kind === 'string' && isGuidanceKind(node.kind)) {
|
|
54
|
+
acc.messageLocked = true;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (typeof node.status === 'number') {
|
|
58
|
+
acc.status = node.status;
|
|
59
|
+
}
|
|
60
|
+
const data = asRecord(node.data);
|
|
61
|
+
if (data && Array.isArray(data.errors)) {
|
|
62
|
+
acc.errors = data.errors;
|
|
63
|
+
const detail = firstEbayErrorMessage(data.errors);
|
|
64
|
+
if (detail && !acc.messageLocked) {
|
|
65
|
+
acc.message = detail;
|
|
66
|
+
}
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Trading XML failures store their structured entries directly on `cause`.
|
|
70
|
+
if (acc.errors === undefined && Array.isArray(node.cause) && node.cause.length > 0) {
|
|
71
|
+
acc.errors = node.cause;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Recovers status, structured eBay errors, and the best message from nested
|
|
76
|
+
* tagged errors and Effect FiberFailures.
|
|
77
|
+
*
|
|
78
|
+
* @param error - Failure caught at an external boundary.
|
|
79
|
+
* @returns Structured details suitable for an MCP error result.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* const details = getEbayErrorDetails(error);
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export const getEbayErrorDetails = (error) => {
|
|
87
|
+
const acc = { message: getErrorMessage(error) };
|
|
88
|
+
const seen = new Set();
|
|
89
|
+
let current = error;
|
|
90
|
+
while (current !== undefined && current !== null && !seen.has(current)) {
|
|
91
|
+
seen.add(current);
|
|
92
|
+
const node = asRecord(current);
|
|
93
|
+
if (!node) {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
collectEbayErrorNode(node, acc);
|
|
97
|
+
current = nextErrorNode(node);
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
message: acc.message,
|
|
101
|
+
...(acc.status === undefined ? {} : { status: acc.status }),
|
|
102
|
+
...(acc.errors === undefined ? {} : { errors: acc.errors }),
|
|
103
|
+
};
|
|
104
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ebay-mcp",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Model Context Protocol (MCP) server that exposes 100% of eBay's Sell APIs (
|
|
3
|
+
"version": "1.15.0",
|
|
4
|
+
"description": "Model Context Protocol (MCP) server that exposes 100% of eBay's Sell APIs (299 tools across 270 endpoints) to AI assistants like Claude, Cursor, and Cline, covering inventory, order fulfillment, marketing, analytics, and developer tools with OAuth authentication and refresh-token support.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "build/index.js",
|
|
7
7
|
"types": "build/index.d.ts",
|
|
@@ -109,10 +109,10 @@
|
|
|
109
109
|
"test": "vitest run",
|
|
110
110
|
"test:coverage": "vitest run --coverage",
|
|
111
111
|
"test:integration": "vitest run --config vitest.integration.config.cts",
|
|
112
|
-
"setup": "
|
|
113
|
-
"skills": "
|
|
112
|
+
"setup": "node build/scripts/setup.js",
|
|
113
|
+
"skills": "node build/scripts/skills.js",
|
|
114
114
|
"sync": "tsx src/scripts/devSync.ts",
|
|
115
|
-
"diagnose": "
|
|
115
|
+
"diagnose": "node build/scripts/diagnostics.js",
|
|
116
116
|
"typecheck": "tsc --noEmit",
|
|
117
117
|
"typecheck:ui": "tsc -p ui/tsconfig.json --noEmit",
|
|
118
118
|
"check": "tsc --noEmit && tsc -p ui/tsconfig.json --noEmit && biome check \"{src,ui}/**/*.{ts,tsx,js,json,md,css,html}\"",
|