ebay-mcp 1.6.2 → 1.7.2

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.md CHANGED
@@ -11,7 +11,7 @@
11
11
  [![MseeP.ai Security Assessment Badge](https://mseep.net/pr/yosefhayim-ebay-api-mcp-server-badge.png)](https://mseep.ai/app/yosefhayim-ebay-api-mcp-server)
12
12
  <a href="https://www.buymeacoffee.com/yosefhayim" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>
13
13
 
14
- A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server providing AI assistants with comprehensive access to eBay's Sell APIs. Includes **387 tools** for inventory management, order fulfillment, marketing campaigns, analytics, developer tools, and more.
14
+ A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server providing AI assistants with comprehensive access to eBay's Sell APIs. Includes **325 tools** for inventory management, order fulfillment, marketing campaigns, analytics, developer tools, and more.
15
15
 
16
16
  **API Coverage:** 100% (270 unique eBay API endpoints)
17
17
 
@@ -113,7 +113,7 @@ For official eBay API support, please refer to the [eBay Developer Program](http
113
113
 
114
114
  ## Features
115
115
 
116
- - **387 eBay API Tools** - 100% coverage of eBay Sell APIs across inventory, orders, marketing, analytics, developer tools, and more
116
+ - **325 eBay API Tools** - 100% coverage of eBay Sell APIs across inventory, orders, marketing, analytics, developer tools, and more
117
117
  - **9 AI Clients Supported** - Auto-configuration for Claude Desktop, Cursor, Zed, Cline, Continue.dev, Windsurf, Roo Code, Claude Code CLI, and Amazon Q
118
118
  - **OAuth 2.0 Support** - Full user token management with automatic refresh
119
119
  - **Type Safety** - Built with TypeScript, Zod validation, and OpenAPI-generated types
@@ -223,6 +223,8 @@ EBAY_CLIENT_ID=your_client_id
223
223
  EBAY_CLIENT_SECRET=your_client_secret
224
224
  EBAY_ENVIRONMENT=sandbox # or "production"
225
225
  EBAY_REDIRECT_URI=your_runame
226
+ EBAY_MARKETPLACE_ID=EBAY_US # Default marketplace (overridable by many tools)
227
+ EBAY_CONTENT_LANGUAGE=en-US # Default request content language (global)
226
228
  EBAY_USER_REFRESH_TOKEN=your_refresh_token # For higher rate limits
227
229
  ```
228
230
 
@@ -260,7 +262,7 @@ This server supports **9 AI clients** with auto-configuration via `npm run setup
260
262
 
261
263
  ```bash
262
264
  npm install -g ebay-mcp
263
- npx ebay-mcp # Interactive setup wizard - auto-detects installed clients
265
+ npx ebay-mcp setup # Interactive setup wizard - auto-detects installed clients
264
266
  ```
265
267
 
266
268
  The setup wizard will automatically detect which AI clients you have installed and configure them for you.
@@ -310,7 +312,7 @@ Monitor your API usage in the [eBay Developer Portal](https://developer.ebay.com
310
312
 
311
313
  ## Available Tools
312
314
 
313
- The server provides **387 tools** with **100% API coverage** organized into the following categories:
315
+ The server provides **325 tools** with **100% API coverage** organized into the following categories:
314
316
 
315
317
  - **Account Management** - Policies, programs, subscriptions, sales tax
316
318
  - **Inventory Management** - Items, offers, locations, bulk operations, SKU location mapping
@@ -564,7 +566,7 @@ Log files are stored in `~/.ebay-mcp/logs/`:
564
566
 
565
567
  1. Verify you're using the correct environment (sandbox vs production)
566
568
  2. Ensure you have proper permissions/scopes for the operation
567
- 3. Check eBay API status: https://developer.ebay.com/support/api-status
569
+ 3. Check current API status with the `ebay_get_api_status` tool or the [eBay API Status](https://developer.ebay.com/support/api-status) page
568
570
  4. Run `npm run diagnose` to check your configuration
569
571
  5. Review the [eBay API documentation](https://developer.ebay.com/docs) for endpoint requirements
570
572
 
@@ -602,12 +604,20 @@ If you're still experiencing issues:
602
604
 
603
605
  ## Resources
604
606
 
607
+ ### API Status
608
+
609
+ Check current eBay API health, incidents, and fixes:
610
+
611
+ - [eBay API Status](https://developer.ebay.com/support/api-status) - Official status page
612
+ - [API Status RSS feed](https://developer.ebay.com/rss/api-status) - Latest issues and resolutions (XML)
613
+ - **`ebay_get_api_status`** - MCP tool that returns the latest items from this feed (filter by status or API name, optional limit)
614
+ - [Latest snapshot (auto-updated)](docs/API_STATUS.md) - In-repo digest of recent status items
615
+
605
616
  ### Documentation
606
617
 
607
618
  - [eBay Developer Portal](https://developer.ebay.com/) - API documentation and credentials
608
619
  - [eBay API License Agreement](https://developer.ebay.com/join/api-license-agreement) - Terms of use and compliance requirements
609
620
  - [eBay Data Handling Requirements](https://developer.ebay.com/api-docs/static/data-handling-update.html) - Important data protection and privacy guidelines
610
- - [eBay API Status](https://developer.ebay.com/support/api-status) - Real-time API health and status
611
621
  - [MCP Documentation](https://modelcontextprotocol.io/) - Model Context Protocol specification
612
622
  - [OAuth Quick Reference](docs/auth/OAUTH_QUICK_REFERENCE.md) - **Complete OAuth authentication guide with scopes, troubleshooting, and examples**
613
623
  - [OAuth Setup Guide](docs/auth/) - Detailed authentication configuration
@@ -37,6 +37,22 @@ export class EbayApiClient {
37
37
  baseUrl;
38
38
  rateLimitTracker;
39
39
  config;
40
+ /**
41
+ * Build default request headers based on configured marketplace and language.
42
+ */
43
+ getDefaultHeaders() {
44
+ const headers = {
45
+ 'Content-Type': 'application/json',
46
+ Accept: 'application/json',
47
+ };
48
+ if (this.config.contentLanguage) {
49
+ headers['Content-Language'] = this.config.contentLanguage;
50
+ }
51
+ if (this.config.marketplaceId) {
52
+ headers['X-EBAY-C-MARKETPLACE-ID'] = this.config.marketplaceId;
53
+ }
54
+ return headers;
55
+ }
40
56
  constructor(config) {
41
57
  this.config = config;
42
58
  this.authClient = new EbayOAuthClient(config);
@@ -45,10 +61,7 @@ export class EbayApiClient {
45
61
  this.httpClient = axios.create({
46
62
  baseURL: this.baseUrl,
47
63
  timeout: 30000,
48
- headers: {
49
- 'Content-Type': 'application/json',
50
- Accept: 'application/json',
51
- },
64
+ headers: this.getDefaultHeaders(),
52
65
  });
53
66
  // Add request interceptor to inject auth token and check rate limits
54
67
  this.httpClient.interceptors.request.use(async (config) => {
@@ -149,7 +162,9 @@ export class EbayApiClient {
149
162
  attempt: `${retryCount + 1}/3`,
150
163
  delayMs: Math.min(delay, 5000),
151
164
  });
152
- await new Promise((resolve) => setTimeout(resolve, Math.min(delay, 5000)));
165
+ await new Promise((resolve) => {
166
+ setTimeout(resolve, Math.min(delay, 5000));
167
+ });
153
168
  return await this.httpClient.request(config);
154
169
  }
155
170
  }
@@ -168,8 +183,8 @@ export class EbayApiClient {
168
183
  * Validate that access token is available before making API request
169
184
  */
170
185
  validateAccessToken() {
171
- if (!this.authClient.hasUserTokens()) {
172
- throw new Error('Access token is missing. Please provide your access token and refresh token by calling ebay_set_user_tokens tool in order to perform API requests.');
186
+ if (!this.config.clientId || !this.config.clientSecret) {
187
+ throw new Error('Missing required eBay credentials. Please set EBAY_CLIENT_ID and EBAY_CLIENT_SECRET in your .env file.');
173
188
  }
174
189
  }
175
190
  /**
@@ -225,8 +240,8 @@ export class EbayApiClient {
225
240
  /**
226
241
  * Set user access and refresh tokens
227
242
  */
228
- async setUserTokens(accessToken, refreshToken) {
229
- await this.authClient.setUserTokens(accessToken, refreshToken);
243
+ async setUserTokens(accessToken, refreshToken, accessTokenExpiry, refreshTokenExpiry) {
244
+ this.authClient.setUserTokens(accessToken, refreshToken, accessTokenExpiry, refreshTokenExpiry);
230
245
  }
231
246
  /**
232
247
  * Get token information for debugging
@@ -281,8 +296,7 @@ export class EbayApiClient {
281
296
  params,
282
297
  headers: {
283
298
  Authorization: `Bearer ${token}`,
284
- 'Content-Type': 'application/json',
285
- Accept: 'application/json',
299
+ ...this.getDefaultHeaders(),
286
300
  },
287
301
  timeout: 30000,
288
302
  });
@@ -303,8 +317,7 @@ export class EbayApiClient {
303
317
  params,
304
318
  headers: {
305
319
  Authorization: `Bearer ${token}`,
306
- 'Content-Type': 'application/json',
307
- Accept: 'application/json',
320
+ ...this.getDefaultHeaders(),
308
321
  },
309
322
  timeout: 30000,
310
323
  });
@@ -87,8 +87,8 @@ export class EbaySellerApi {
87
87
  /**
88
88
  * Set user access and refresh tokens
89
89
  */
90
- async setUserTokens(accessToken, refreshToken) {
91
- await this.client.setUserTokens(accessToken, refreshToken);
90
+ async setUserTokens(accessToken, refreshToken, accessTokenExpiry, refreshTokenExpiry) {
91
+ await this.client.setUserTokens(accessToken, refreshToken, accessTokenExpiry, refreshTokenExpiry);
92
92
  }
93
93
  /**
94
94
  * Get OAuth client for advanced operations
@@ -60,11 +60,7 @@ export class InventoryApi {
60
60
  throw new Error('inventoryItem is required and must be an object');
61
61
  }
62
62
  try {
63
- return await this.client.put(`${this.basePath}/inventory_item/${sku}`, inventoryItem, {
64
- headers: {
65
- 'Content-Language': 'en-US',
66
- },
67
- });
63
+ return await this.client.put(`${this.basePath}/inventory_item/${sku}`, inventoryItem);
68
64
  }
69
65
  catch (error) {
70
66
  throw new Error(`Failed to create or replace inventory item: ${error instanceof Error ? error.message : 'Unknown error'}`);
@@ -95,11 +91,7 @@ export class InventoryApi {
95
91
  throw new Error('requests is required and must be an object');
96
92
  }
97
93
  try {
98
- return await this.client.post(`${this.basePath}/bulk_create_or_replace_inventory_item`, requests, {
99
- headers: {
100
- 'Content-Language': 'en-US',
101
- },
102
- });
94
+ return await this.client.post(`${this.basePath}/bulk_create_or_replace_inventory_item`, requests);
103
95
  }
104
96
  catch (error) {
105
97
  throw new Error(`Failed to bulk create or replace inventory items: ${error instanceof Error ? error.message : 'Unknown error'}`);
@@ -166,11 +158,7 @@ export class InventoryApi {
166
158
  throw new Error('compatibility is required and must be an object');
167
159
  }
168
160
  try {
169
- return await this.client.put(`${this.basePath}/inventory_item/${sku}/product_compatibility`, compatibility, {
170
- headers: {
171
- 'Content-Language': 'en-US',
172
- },
173
- });
161
+ return await this.client.put(`${this.basePath}/inventory_item/${sku}/product_compatibility`, compatibility);
174
162
  }
175
163
  catch (error) {
176
164
  throw new Error(`Failed to create or replace product compatibility: ${error instanceof Error ? error.message : 'Unknown error'}`);
@@ -221,11 +209,7 @@ export class InventoryApi {
221
209
  throw new Error('inventoryItemGroup is required and must be an object');
222
210
  }
223
211
  try {
224
- return await this.client.put(`${this.basePath}/inventory_item_group/${inventoryItemGroupKey}`, inventoryItemGroup, {
225
- headers: {
226
- 'Content-Language': 'en-US',
227
- },
228
- });
212
+ return await this.client.put(`${this.basePath}/inventory_item_group/${inventoryItemGroupKey}`, inventoryItemGroup);
229
213
  }
230
214
  catch (error) {
231
215
  throw new Error(`Failed to create or replace inventory item group: ${error instanceof Error ? error.message : 'Unknown error'}`);
@@ -431,11 +415,7 @@ export class InventoryApi {
431
415
  throw new Error('offer is required and must be an object');
432
416
  }
433
417
  try {
434
- return await this.client.post(`${this.basePath}/offer`, offer, {
435
- headers: {
436
- 'Content-Language': 'en-US',
437
- },
438
- });
418
+ return await this.client.post(`${this.basePath}/offer`, offer);
439
419
  }
440
420
  catch (error) {
441
421
  throw new Error(`Failed to create offer: ${error instanceof Error ? error.message : 'Unknown error'}`);
@@ -454,11 +434,7 @@ export class InventoryApi {
454
434
  throw new Error('offer is required and must be an object');
455
435
  }
456
436
  try {
457
- return await this.client.put(`${this.basePath}/offer/${offerId}`, offer, {
458
- headers: {
459
- 'Content-Language': 'en-US',
460
- },
461
- });
437
+ return await this.client.put(`${this.basePath}/offer/${offerId}`, offer);
462
438
  }
463
439
  catch (error) {
464
440
  throw new Error(`Failed to update offer: ${error instanceof Error ? error.message : 'Unknown error'}`);
@@ -521,11 +497,7 @@ export class InventoryApi {
521
497
  throw new Error('requests is required and must be an object');
522
498
  }
523
499
  try {
524
- return await this.client.post(`${this.basePath}/bulk_create_offer`, requests, {
525
- headers: {
526
- 'Content-Language': 'en-US',
527
- },
528
- });
500
+ return await this.client.post(`${this.basePath}/bulk_create_offer`, requests);
529
501
  }
530
502
  catch (error) {
531
503
  throw new Error(`Failed to bulk create offers: ${error instanceof Error ? error.message : 'Unknown error'}`);
@@ -18,7 +18,7 @@ export class IdentityApi {
18
18
  async getUser() {
19
19
  const config = this.client.getConfig();
20
20
  const identityBaseUrl = getIdentityBaseUrl(config.environment);
21
- const fullUrl = `${identityBaseUrl}${this.basePath}/user/`;
21
+ const fullUrl = `${identityBaseUrl}${this.basePath}/user`;
22
22
  return await this.client.getWithFullUrl(fullUrl);
23
23
  }
24
24
  }
@@ -1,7 +1,7 @@
1
1
  import axios from 'axios';
2
2
  import { getBaseUrl, getDefaultScopes } from '../config/environment.js';
3
3
  import { LocaleEnum } from '../types/ebay-enums.js';
4
- import { readFileSync, writeFileSync } from 'fs';
4
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
5
5
  import { join } from 'path';
6
6
  import { authLogger } from '../utils/logger.js';
7
7
  /**
@@ -10,7 +10,7 @@ import { authLogger } from '../utils/logger.js';
10
10
  function updateEnvFile(updates) {
11
11
  try {
12
12
  const envPath = join(process.cwd(), '.env');
13
- let envContent = readFileSync(envPath, 'utf-8');
13
+ let envContent = existsSync(envPath) ? readFileSync(envPath, 'utf-8') : '';
14
14
  // Update each key-value pair
15
15
  for (const [key, value] of Object.entries(updates)) {
16
16
  // Match the key with or without value, handling comments
@@ -28,7 +28,7 @@ function updateEnvFile(updates) {
28
28
  writeFileSync(envPath, envContent, 'utf-8');
29
29
  // Tokens updated silently - console output interferes with MCP JSON protocol
30
30
  }
31
- catch (error) {
31
+ catch (_error) {
32
32
  // Silent failure - error logging interferes with MCP JSON protocol
33
33
  // If needed, check .env file manually
34
34
  }
@@ -180,7 +180,7 @@ export class EbayOAuthClient {
180
180
  */
181
181
  async getOrRefreshAppAccessToken() {
182
182
  // Return cached token if still valid
183
- if (this.appAccessToken) {
183
+ if (this.appAccessToken && Date.now() < this.appAccessTokenExpiry) {
184
184
  return this.appAccessToken;
185
185
  }
186
186
  const authUrl = `${getBaseUrl(this.config.environment)}/identity/v1/oauth2/token`;
@@ -1,8 +1,9 @@
1
1
  import { config } from 'dotenv';
2
- import { readFileSync } from 'fs';
2
+ import { existsSync, readFileSync } from 'fs';
3
3
  import { fileURLToPath } from 'url';
4
4
  import { dirname, join } from 'path';
5
5
  import { LocaleEnum } from '../types/ebay-enums.js';
6
+ import { getVersion } from '../utils/version.js';
6
7
  // Load .env silently - suppress dotenv output to keep stdout clean for MCP JSON-RPC
7
8
  config({ quiet: true });
8
9
  // Get the current directory for loading scope files
@@ -58,7 +59,10 @@ function getSandboxScopes() {
58
59
  * Get default scopes for the specified environment
59
60
  */
60
61
  export function getDefaultScopes(environment) {
61
- return environment === 'production' ? getProductionScopes() : getSandboxScopes();
62
+ if (environment === 'production') {
63
+ return getProductionScopes();
64
+ }
65
+ return getSandboxScopes();
62
66
  }
63
67
  /**
64
68
  * Validate scopes against environment and return warnings for invalid scopes
@@ -134,6 +138,9 @@ export function validateEnvironmentConfig() {
134
138
  errors,
135
139
  };
136
140
  }
141
+ /**
142
+ * Build EbayConfig from environment variables with safe defaults.
143
+ */
137
144
  export function getEbayConfig() {
138
145
  const clientId = process.env.EBAY_CLIENT_ID ?? '';
139
146
  const clientSecret = process.env.EBAY_CLIENT_SECRET ?? '';
@@ -141,6 +148,8 @@ export function getEbayConfig() {
141
148
  const accessToken = process.env.EBAY_USER_ACCESS_TOKEN ?? '';
142
149
  const refreshToken = process.env.EBAY_USER_REFRESH_TOKEN ?? '';
143
150
  const appAccessToken = process.env.EBAY_APP_ACCESS_TOKEN ?? '';
151
+ const marketplaceId = (process.env.EBAY_MARKETPLACE_ID ?? '').trim() || 'EBAY_US';
152
+ const contentLanguage = (process.env.EBAY_CONTENT_LANGUAGE ?? '').trim() || 'en-US';
144
153
  // Only require client credentials - tokens can be optional (generated from refresh token)
145
154
  if (clientId === '' || clientSecret === '') {
146
155
  console.error('Missing required eBay credentials. Please set:\n1) EBAY_CLIENT_ID\n2) EBAY_CLIENT_SECRET\nin your .env file at project root');
@@ -149,6 +158,8 @@ export function getEbayConfig() {
149
158
  clientId,
150
159
  clientSecret,
151
160
  redirectUri: process.env.EBAY_REDIRECT_URI,
161
+ marketplaceId,
162
+ contentLanguage,
152
163
  environment,
153
164
  accessToken,
154
165
  refreshToken,
@@ -172,23 +183,23 @@ export function getAuthUrl(clientIdOrEnvironment, redirectUri, environment, loca
172
183
  }
173
184
  // Otherwise, generate the full OAuth authorization URL
174
185
  const clientId = clientIdOrEnvironment;
175
- const env = environment || 'sandbox';
186
+ const env = environment ?? 'sandbox';
176
187
  const scope = getDefaultScopes(env);
177
188
  if (!(clientId && redirectUri)) {
178
189
  console.error('clientId, redirectUri (RuName), and scope are required,please initialize the class properly.');
179
190
  return '';
180
191
  }
181
- const authDomain = env === 'production' ? 'https://auth.ebay.com' : 'https://auth.sandbox.ebay.com';
182
- const params = new URLSearchParams({
192
+ const authBase = env === 'production' ? 'https://auth.ebay.com' : 'https://auth.sandbox.ebay.com';
193
+ const scopeList = scopes?.join('%20') || scope.join('%20');
194
+ const authorizeParams = new URLSearchParams({
183
195
  client_id: clientId,
184
196
  redirect_uri: redirectUri,
185
197
  response_type: responseType,
186
- scope: scopes?.join(' ') || scope.join(' '),
187
198
  prompt,
188
199
  locale,
189
200
  ...(state ? { state } : {}),
190
201
  });
191
- return `${authDomain}/oauth2/authorize?${params.toString()}`;
202
+ return `${authBase}/oauth2/authorize?${authorizeParams.toString()}&scope=${scopeList}`;
192
203
  }
193
204
  /**
194
205
  * Generate the OAuth authorization URL for user consent
@@ -199,62 +210,69 @@ export function getAuthUrl(clientIdOrEnvironment, redirectUri, environment, loca
199
210
  */
200
211
  export function getOAuthAuthorizationUrl(clientId, redirectUri, // MUST be eBay RuName, NOT a URL
201
212
  environment, scopes, locale, state) {
202
- // Build the authorize URL using auth2 endpoint (correct eBay OAuth endpoint)
203
- const authDomain = environment === 'production' ? 'https://auth2.ebay.com' : 'https://auth2.sandbox.ebay.com';
204
- const authorizeEndpoint = `${authDomain}/oauth2/authorize`;
205
- // Build query parameters for the authorize endpoint
206
- const params = new URLSearchParams({
207
- client_id: clientId,
208
- redirect_uri: redirectUri,
209
- });
210
- // Add scopes only if provided (optional - eBay handles automatically if not specified)
213
+ const authBase = environment === 'production' ? 'https://auth.ebay.com' : 'https://auth.sandbox.ebay.com';
214
+ let scopeList;
211
215
  if (scopes && scopes.length > 0) {
212
- params.append('scope', scopes.join(' '));
216
+ scopeList = scopes.join('%20');
213
217
  }
214
218
  else {
215
- // Use default scopes for the environment if no scopes are specified
216
219
  const defaultScopes = getDefaultScopes(environment);
217
- params.append('scope', defaultScopes.join(' '));
220
+ scopeList = defaultScopes.join('%20');
218
221
  }
219
- // Always add state parameter (empty if not provided)
220
- params.append('state', state || '');
221
- // Add response_type
222
- params.append('response_type', 'code');
223
- // Add hd parameter (required by eBay)
224
- params.append('hd', '');
225
- // Build the signin URL that redirects to authorize
226
- const signinDomain = environment === 'production' ? 'https://signin.ebay.com' : 'https://signin.sandbox.ebay.com';
227
- const ruParam = encodeURIComponent(`${authorizeEndpoint}?${params.toString()}`);
228
- return `${signinDomain}/signin?ru=${ruParam}&sgfl=oauth2_login&AppName=${clientId}`;
222
+ const params = new URLSearchParams({
223
+ client_id: clientId,
224
+ redirect_uri: redirectUri,
225
+ response_type: 'code',
226
+ ...(state ? { state } : {}),
227
+ });
228
+ return `${authBase}/oauth2/authorize?${params.toString()}&scope=${scopeList}`;
229
229
  }
230
+ const iconUrl = (size) => {
231
+ const url = new URL(`../../public/icons/${size}.png`, import.meta.url);
232
+ const path = fileURLToPath(url);
233
+ if (!existsSync(path)) {
234
+ console.warn(`[eBay MCP] Icon not found at ${path}. Ensure public/icons is included in the package.`);
235
+ }
236
+ return url.toString();
237
+ };
230
238
  export const mcpConfig = {
231
239
  name: 'eBay API Model Context Protocol Server',
232
- version: '1.4.2',
240
+ version: getVersion(),
233
241
  title: 'eBay API Model Context Protocol Server',
234
- websiteUrl: 'https://github.com/ebay/ebay-mcp-server',
242
+ websiteUrl: 'https://github.com/YosefHayim/ebay-mcp',
235
243
  icons: [
236
244
  {
237
- src: './48x48.png',
245
+ src: iconUrl('16x16'),
246
+ mimeType: 'image/png',
247
+ sizes: ['16x16'],
248
+ },
249
+ {
250
+ src: iconUrl('32x32'),
251
+ mimeType: 'image/png',
252
+ sizes: ['32x32'],
253
+ },
254
+ {
255
+ src: iconUrl('48x48'),
238
256
  mimeType: 'image/png',
239
257
  sizes: ['48x48'],
240
258
  },
241
259
  {
242
- src: './128x128.png',
260
+ src: iconUrl('128x128'),
243
261
  mimeType: 'image/png',
244
262
  sizes: ['128x128'],
245
263
  },
246
264
  {
247
- src: './256x256.png',
265
+ src: iconUrl('256x256'),
248
266
  mimeType: 'image/png',
249
267
  sizes: ['256x256'],
250
268
  },
251
269
  {
252
- src: './512x512.png',
270
+ src: iconUrl('512x512'),
253
271
  mimeType: 'image/png',
254
272
  sizes: ['512x512'],
255
273
  },
256
274
  {
257
- src: './1024x1024.png',
275
+ src: iconUrl('1024x1024'),
258
276
  mimeType: 'image/png',
259
277
  sizes: ['1024x1024'],
260
278
  },
package/build/index.js CHANGED
@@ -5,6 +5,20 @@ import { EbaySellerApi } from './api/index.js';
5
5
  import { getEbayConfig, mcpConfig, validateEnvironmentConfig } from './config/environment.js';
6
6
  import { getToolDefinitions, executeTool } from './tools/index.js';
7
7
  import { serverLogger, toolLogger, getLogPaths } from './utils/logger.js';
8
+ import { checkForUpdates } from './utils/version.js';
9
+ checkForUpdates({ defer: true });
10
+ const args = process.argv.slice(2);
11
+ if (args.includes('setup')) {
12
+ try {
13
+ const { runSetup } = await import('./scripts/setup.js');
14
+ await runSetup();
15
+ process.exit(0);
16
+ }
17
+ catch (error) {
18
+ console.error('Setup failed:', error instanceof Error ? error.message : error);
19
+ process.exit(1);
20
+ }
21
+ }
8
22
  /**
9
23
  * eBay API MCP Server
10
24
  * Provides access to eBay APIs through Model Context Protocol
@@ -135,6 +135,12 @@ function generateMCPServerConfig() {
135
135
  if (process.env.EBAY_REDIRECT_URI) {
136
136
  config.env.EBAY_REDIRECT_URI = process.env.EBAY_REDIRECT_URI;
137
137
  }
138
+ if (process.env.EBAY_MARKETPLACE_ID) {
139
+ config.env.EBAY_MARKETPLACE_ID = process.env.EBAY_MARKETPLACE_ID;
140
+ }
141
+ if (process.env.EBAY_CONTENT_LANGUAGE) {
142
+ config.env.EBAY_CONTENT_LANGUAGE = process.env.EBAY_CONTENT_LANGUAGE;
143
+ }
138
144
  if (process.env.EBAY_USER_ACCESS_TOKEN) {
139
145
  config.env.EBAY_USER_ACCESS_TOKEN = process.env.EBAY_USER_ACCESS_TOKEN;
140
146
  }
@@ -118,6 +118,8 @@ function displayConfigurationStatus(envVars) {
118
118
  { key: 'EBAY_CLIENT_SECRET', label: 'Client Secret', redact: true },
119
119
  { key: 'EBAY_REDIRECT_URI', label: 'Redirect URI', redact: false },
120
120
  { key: 'EBAY_ENVIRONMENT', label: 'Environment', redact: false },
121
+ { key: 'EBAY_MARKETPLACE_ID', label: 'Marketplace ID', redact: false },
122
+ { key: 'EBAY_CONTENT_LANGUAGE', label: 'Content Language', redact: false },
121
123
  { key: 'EBAY_USER_REFRESH_TOKEN', label: 'User Refresh Token', redact: true },
122
124
  { key: 'EBAY_USER_ACCESS_TOKEN', label: 'User Access Token', redact: true },
123
125
  { key: 'EBAY_APP_ACCESS_TOKEN', label: 'App Access Token', redact: true },
@@ -143,6 +143,10 @@ EBAY_REDIRECT_URI=${config.EBAY_REDIRECT_URI || 'http://localhost:3000/oauth/cal
143
143
  # ═══════════════════════════════════════════════════════════════════
144
144
 
145
145
  EBAY_ENVIRONMENT=${config.EBAY_ENVIRONMENT || 'sandbox'}
146
+ # Optional: e.g. EBAY_US, EBAY_DE, EBAY_FR
147
+ EBAY_MARKETPLACE_ID=${config.EBAY_MARKETPLACE_ID || ''}
148
+ # Optional: e.g. en-US, de-DE, fr-FR
149
+ EBAY_CONTENT_LANGUAGE=${config.EBAY_CONTENT_LANGUAGE || ''}
146
150
 
147
151
  # ═══════════════════════════════════════════════════════════════════
148
152
  # User Tokens (Auto-generated from refresh token)
@@ -667,6 +671,8 @@ async function runInteractiveSetup(args) {
667
671
  EBAY_CLIENT_SECRET: credentials.EBAY_CLIENT_SECRET,
668
672
  EBAY_REDIRECT_URI: credentials.EBAY_REDIRECT_URI,
669
673
  EBAY_ENVIRONMENT: environment,
674
+ EBAY_MARKETPLACE_ID: existingConfig.EBAY_MARKETPLACE_ID || '',
675
+ EBAY_CONTENT_LANGUAGE: existingConfig.EBAY_CONTENT_LANGUAGE || '',
670
676
  EBAY_USER_REFRESH_TOKEN: refreshToken,
671
677
  EBAY_USER_ACCESS_TOKEN: '',
672
678
  EBAY_APP_ACCESS_TOKEN: '',