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,198 @@
1
+ import winston from 'winston';
2
+ import { join } from 'path';
3
+ import { existsSync, mkdirSync } from 'fs';
4
+ import { homedir } from 'os';
5
+ /**
6
+ * Log directory for eBay MCP Server
7
+ * Stored in user's home directory under .ebay-mcp-remote-edition/logs
8
+ */
9
+ const LOG_DIR = join(homedir(), '.ebay-mcp-remote-edition', 'logs');
10
+ // Ensure log directory exists
11
+ if (!existsSync(LOG_DIR)) {
12
+ mkdirSync(LOG_DIR, { recursive: true });
13
+ }
14
+ /**
15
+ * Log level from environment variable or default to 'info'
16
+ * Levels: error, warn, info, http, verbose, debug, silly
17
+ */
18
+ const LOG_LEVEL = process.env.EBAY_LOG_LEVEL || 'info';
19
+ /**
20
+ * Whether to enable file logging (disabled in production MCP mode by default)
21
+ */
22
+ const ENABLE_FILE_LOGGING = process.env.EBAY_ENABLE_FILE_LOGGING === 'true';
23
+ /**
24
+ * Custom log format with timestamp and colored output
25
+ */
26
+ const consoleFormat = winston.format.combine(winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.errors({ stack: true }), winston.format.printf(({ level, message, timestamp, stack, ...meta }) => {
27
+ const metaStr = Object.keys(meta).length ? `\n${JSON.stringify(meta, null, 2)}` : '';
28
+ const stackStr = typeof stack === 'string' && stack ? `\n${stack}` : '';
29
+ return `[${timestamp}] [${level.toUpperCase()}] ${message}${metaStr}${stackStr}`;
30
+ }));
31
+ /**
32
+ * File format (no colors, JSON for easier parsing)
33
+ */
34
+ const fileFormat = winston.format.combine(winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.errors({ stack: true }), winston.format.json());
35
+ /**
36
+ * Create Winston logger transports
37
+ */
38
+ const transports = [
39
+ // Console transport - always enabled for MCP stderr output
40
+ new winston.transports.Console({
41
+ format: consoleFormat,
42
+ stderrLevels: ['error', 'warn', 'info', 'http', 'verbose', 'debug', 'silly'],
43
+ }),
44
+ ];
45
+ // Add file transports if enabled
46
+ if (ENABLE_FILE_LOGGING) {
47
+ transports.push(
48
+ // Error log - only errors
49
+ new winston.transports.File({
50
+ filename: join(LOG_DIR, 'error.log'),
51
+ level: 'error',
52
+ format: fileFormat,
53
+ maxsize: 5 * 1024 * 1024, // 5MB
54
+ maxFiles: 5,
55
+ tailable: true,
56
+ }),
57
+ // Combined log - all levels
58
+ new winston.transports.File({
59
+ filename: join(LOG_DIR, 'combined.log'),
60
+ format: fileFormat,
61
+ maxsize: 10 * 1024 * 1024, // 10MB
62
+ maxFiles: 5,
63
+ tailable: true,
64
+ }),
65
+ // Debug log - verbose and debug messages
66
+ new winston.transports.File({
67
+ filename: join(LOG_DIR, 'debug.log'),
68
+ level: 'debug',
69
+ format: fileFormat,
70
+ maxsize: 10 * 1024 * 1024, // 10MB
71
+ maxFiles: 3,
72
+ tailable: true,
73
+ }));
74
+ }
75
+ /**
76
+ * Main Winston logger instance
77
+ */
78
+ const logger = winston.createLogger({
79
+ level: LOG_LEVEL,
80
+ transports,
81
+ exitOnError: false,
82
+ });
83
+ /**
84
+ * Create a child logger for a specific component
85
+ */
86
+ export function createLogger(component) {
87
+ return {
88
+ error: (message, meta) => {
89
+ logger.error(`[${component}] ${message}`, meta);
90
+ },
91
+ warn: (message, meta) => {
92
+ logger.warn(`[${component}] ${message}`, meta);
93
+ },
94
+ info: (message, meta) => {
95
+ logger.info(`[${component}] ${message}`, meta);
96
+ },
97
+ http: (message, meta) => {
98
+ logger.http(`[${component}] ${message}`, meta);
99
+ },
100
+ debug: (message, meta) => {
101
+ logger.debug(`[${component}] ${message}`, meta);
102
+ },
103
+ verbose: (message, meta) => {
104
+ logger.verbose(`[${component}] ${message}`, meta);
105
+ },
106
+ };
107
+ }
108
+ /**
109
+ * Pre-configured loggers for different components
110
+ */
111
+ export const serverLogger = createLogger('Server');
112
+ export const apiLogger = createLogger('API');
113
+ export const authLogger = createLogger('Auth');
114
+ export const toolLogger = createLogger('Tool');
115
+ export const setupLogger = createLogger('Setup');
116
+ /**
117
+ * Log HTTP request details
118
+ */
119
+ export function logRequest(method, url, params, body) {
120
+ apiLogger.http(`Request: ${method.toUpperCase()} ${url}`, {
121
+ params: params && Object.keys(params).length > 0 ? params : undefined,
122
+ body: body ? truncateData(body) : undefined,
123
+ });
124
+ }
125
+ /**
126
+ * Log HTTP response details
127
+ */
128
+ export function logResponse(status, statusText, data, rateLimitRemaining, rateLimitTotal) {
129
+ const meta = {};
130
+ if (rateLimitRemaining && rateLimitTotal) {
131
+ meta.rateLimit = `${rateLimitRemaining}/${rateLimitTotal}`;
132
+ }
133
+ if (data) {
134
+ meta.data = truncateData(data);
135
+ }
136
+ apiLogger.http(`Response: ${status} ${statusText}`, meta);
137
+ }
138
+ /**
139
+ * Log HTTP error response
140
+ */
141
+ export function logErrorResponse(status, statusText, url, errorData) {
142
+ apiLogger.error(`Error Response: ${status || 'N/A'} ${statusText || 'No response'}`, {
143
+ url,
144
+ error: errorData ? truncateData(errorData) : undefined,
145
+ });
146
+ }
147
+ /**
148
+ * Truncate large data objects for logging
149
+ */
150
+ function truncateData(data, maxLength = 1000) {
151
+ const str = JSON.stringify(data);
152
+ if (str.length <= maxLength) {
153
+ return data;
154
+ }
155
+ return `${str.substring(0, maxLength)}... [truncated]`;
156
+ }
157
+ /**
158
+ * Get log file paths for user reference
159
+ */
160
+ export function getLogPaths() {
161
+ return {
162
+ logDir: LOG_DIR,
163
+ errorLog: join(LOG_DIR, 'error.log'),
164
+ combinedLog: join(LOG_DIR, 'combined.log'),
165
+ debugLog: join(LOG_DIR, 'debug.log'),
166
+ };
167
+ }
168
+ /**
169
+ * Enable or disable file logging at runtime
170
+ */
171
+ export function setFileLogging(enabled) {
172
+ if (enabled && !ENABLE_FILE_LOGGING) {
173
+ logger.add(new winston.transports.File({
174
+ filename: join(LOG_DIR, 'error.log'),
175
+ level: 'error',
176
+ format: fileFormat,
177
+ maxsize: 5 * 1024 * 1024,
178
+ maxFiles: 5,
179
+ tailable: true,
180
+ }));
181
+ logger.add(new winston.transports.File({
182
+ filename: join(LOG_DIR, 'combined.log'),
183
+ format: fileFormat,
184
+ maxsize: 10 * 1024 * 1024,
185
+ maxFiles: 5,
186
+ tailable: true,
187
+ }));
188
+ logger.info('File logging enabled');
189
+ }
190
+ }
191
+ /**
192
+ * Set log level at runtime
193
+ */
194
+ export function setLogLevel(level) {
195
+ logger.level = level;
196
+ logger.info(`Log level set to: ${level}`);
197
+ }
198
+ export default logger;
@@ -0,0 +1,315 @@
1
+ /**
2
+ * OAuth Helper - Assists with eBay OAuth token acquisition
3
+ */
4
+ import chalk from 'chalk';
5
+ import { createServer } from 'http';
6
+ import { getOAuthAuthorizationUrl } from '../config/environment.js';
7
+ /**
8
+ * Generate terminal hyperlink (if supported)
9
+ */
10
+ function hyperlink(text, url) {
11
+ return `\u001B]8;;${url}\u0007${text}\u001B]8;;\u0007`;
12
+ }
13
+ /**
14
+ * Generate eBay OAuth authorization URL
15
+ */
16
+ export function generateAuthUrl(clientId, redirectUri, environment, scopes) {
17
+ return getOAuthAuthorizationUrl(clientId, redirectUri, environment, scopes);
18
+ }
19
+ /**
20
+ * Start a local server to capture OAuth callback
21
+ */
22
+ export async function startCallbackServer(port = 3000, timeout = 300000 // 5 minutes
23
+ ) {
24
+ return await new Promise((resolve) => {
25
+ let callbackResolver;
26
+ const codePromise = new Promise((res) => {
27
+ callbackResolver = res;
28
+ });
29
+ const server = createServer((req, res) => {
30
+ if (!req.url) {
31
+ res.writeHead(400);
32
+ res.end('Bad Request');
33
+ return;
34
+ }
35
+ const url = new URL(req.url, `http://localhost:${port}`);
36
+ // Handle OAuth callback
37
+ if (url.pathname === '/oauth/callback') {
38
+ const code = url.searchParams.get('code');
39
+ const error = url.searchParams.get('error');
40
+ const errorDescription = url.searchParams.get('error_description');
41
+ if (code) {
42
+ res.writeHead(200, { 'Content-Type': 'text/html' });
43
+ res.end(`
44
+ <!DOCTYPE html>
45
+ <html>
46
+ <head>
47
+ <title>eBay MCP - Authorization Successful</title>
48
+ <style>
49
+ body {
50
+ font-family: Arial, sans-serif;
51
+ display: flex;
52
+ justify-content: center;
53
+ align-items: center;
54
+ height: 100vh;
55
+ margin: 0;
56
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
57
+ }
58
+ .container {
59
+ background: white;
60
+ padding: 40px;
61
+ border-radius: 10px;
62
+ box-shadow: 0 10px 40px rgba(0,0,0,0.2);
63
+ text-align: center;
64
+ max-width: 500px;
65
+ }
66
+ .success-icon {
67
+ font-size: 64px;
68
+ margin-bottom: 20px;
69
+ }
70
+ h1 {
71
+ color: #4CAF50;
72
+ margin-bottom: 10px;
73
+ }
74
+ p {
75
+ color: #666;
76
+ line-height: 1.6;
77
+ }
78
+ .code {
79
+ background: #f5f5f5;
80
+ padding: 10px;
81
+ border-radius: 5px;
82
+ font-family: monospace;
83
+ word-break: break-all;
84
+ margin: 20px 0;
85
+ }
86
+ </style>
87
+ </head>
88
+ <body>
89
+ <div class="container">
90
+ <div class="success-icon">āœ…</div>
91
+ <h1>Authorization Successful!</h1>
92
+ <p>You have successfully authorized the eBay MCP server.</p>
93
+ <p>You can close this window and return to your terminal.</p>
94
+ <p class="code">Authorization code received</p>
95
+ </div>
96
+ </body>
97
+ </html>
98
+ `);
99
+ callbackResolver({ code });
100
+ }
101
+ else if (error) {
102
+ res.writeHead(400, { 'Content-Type': 'text/html' });
103
+ res.end(`
104
+ <!DOCTYPE html>
105
+ <html>
106
+ <head>
107
+ <title>eBay MCP - Authorization Failed</title>
108
+ <style>
109
+ body {
110
+ font-family: Arial, sans-serif;
111
+ display: flex;
112
+ justify-content: center;
113
+ align-items: center;
114
+ height: 100vh;
115
+ margin: 0;
116
+ background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
117
+ }
118
+ .container {
119
+ background: white;
120
+ padding: 40px;
121
+ border-radius: 10px;
122
+ box-shadow: 0 10px 40px rgba(0,0,0,0.2);
123
+ text-align: center;
124
+ max-width: 500px;
125
+ }
126
+ .error-icon {
127
+ font-size: 64px;
128
+ margin-bottom: 20px;
129
+ }
130
+ h1 {
131
+ color: #f44336;
132
+ margin-bottom: 10px; /* Fix: Changed color to red for error */
133
+ }
134
+ p {
135
+ color: #666;
136
+ line-height: 1.6;
137
+ }
138
+ .error {
139
+ background: #ffebee;
140
+ color: #c62828;
141
+ padding: 10px;
142
+ border-radius: 5px;
143
+ margin: 20px 0;
144
+ }
145
+ </style>
146
+ </head>
147
+ <body>
148
+ <div class="container">
149
+ <div class="error-icon">āŒ</div>
150
+ <h1>Authorization Failed</h1>
151
+ <p>There was an error during authorization.</p>
152
+ <div class="error">${errorDescription ?? error}</div>
153
+ <p>Please return to your terminal and try again.</p>
154
+ </div>
155
+ <script>
156
+ // Close the window after a short delay
157
+ setTimeout(() => window.close(), 5000);
158
+ </script>
159
+ </body>
160
+ </html>
161
+ `);
162
+ callbackResolver({ error, errorDescription: errorDescription ?? undefined });
163
+ }
164
+ }
165
+ else {
166
+ res.writeHead(404);
167
+ res.end('Not Found');
168
+ }
169
+ });
170
+ server.listen(port, () => {
171
+ console.log(chalk.gray(` OAuth callback server listening on http://localhost:${port}`));
172
+ resolve({ server, codePromise });
173
+ });
174
+ // Set timeout
175
+ setTimeout(() => {
176
+ callbackResolver({
177
+ error: 'timeout',
178
+ errorDescription: 'OAuth callback timeout - no response received',
179
+ });
180
+ }, timeout);
181
+ });
182
+ }
183
+ /**
184
+ * Interactive OAuth flow with local callback server
185
+ */
186
+ export async function interactiveOAuthFlow(config, scopes) {
187
+ console.log(chalk.bold.cyan('\nšŸ” Interactive OAuth Flow\n'));
188
+ // Check if redirect URI is localhost
189
+ const redirectUri = config.redirectUri || 'http://localhost:3000/oauth/callback';
190
+ const isLocalhost = redirectUri.includes('localhost') || redirectUri.includes('127.0.0.1');
191
+ if (!isLocalhost) {
192
+ console.log(chalk.yellow('āš ļø Your redirect URI is not localhost. Interactive flow requires localhost callback.\n'));
193
+ return null;
194
+ }
195
+ // Extract port from redirect URI
196
+ const portMatch = /:(\d+)/.exec(redirectUri);
197
+ const port = portMatch ? parseInt(portMatch[1], 10) : 3000;
198
+ // Start callback server
199
+ console.log(chalk.cyan('Starting local OAuth callback server...\n'));
200
+ const { server, codePromise } = await startCallbackServer(port);
201
+ // Generate auth URL
202
+ const authUrl = generateAuthUrl(config.clientId, redirectUri, config.environment, scopes);
203
+ console.log(chalk.bold.white('šŸ“‹ Step 1: Authorize the Application\n'));
204
+ console.log(chalk.gray('Open this URL in your browser:\n'));
205
+ console.log(chalk.blue.underline(hyperlink(authUrl.substring(0, 20) + '...', authUrl)));
206
+ console.log('');
207
+ console.log(chalk.gray('Waiting for authorization...'));
208
+ console.log(chalk.gray('(This window will update automatically after you authorize)\n'));
209
+ // Wait for callback
210
+ const result = await codePromise;
211
+ // Close server
212
+ server.close();
213
+ if (result.error) {
214
+ console.log(chalk.red(`\nāœ— Authorization failed: ${result.errorDescription || result.error}\n`));
215
+ return null;
216
+ }
217
+ if (result.code) {
218
+ console.log(chalk.green('\nāœ“ Authorization successful!\n'));
219
+ return result.code;
220
+ }
221
+ console.log(chalk.yellow('\nāš ļø No authorization code received.\n'));
222
+ return null;
223
+ }
224
+ /**
225
+ * Display manual OAuth instructions
226
+ */
227
+ export function displayManualOAuthInstructions(clientId, redirectUri, environment, scopes) {
228
+ const authUrl = generateAuthUrl(clientId, redirectUri, environment, scopes);
229
+ console.log(chalk.bold.cyan('\nšŸ“– Manual OAuth Token Acquisition Guide\n'));
230
+ console.log(chalk.white('Step 1: Generate Authorization URL\n'));
231
+ console.log(chalk.gray('Copy this URL and open it in your browser:\n'));
232
+ console.log(chalk.blue.underline(authUrl));
233
+ console.log('');
234
+ console.log(chalk.white('\nStep 2: Authorize the Application\n'));
235
+ console.log(chalk.gray(' • Log in to your eBay account'));
236
+ console.log(chalk.gray(' • Review the permissions requested'));
237
+ console.log(chalk.gray(' • Click "Agree" to authorize\n'));
238
+ console.log(chalk.white('Step 3: Get the Authorization Code\n'));
239
+ console.log(chalk.gray(' • After authorization, you will be redirected to your redirect URI'));
240
+ console.log(chalk.gray(' • The URL will contain a "code" parameter'));
241
+ console.log(chalk.gray(' • Example: https://your-redirect-uri?code=v^1.1#i^1...\n'));
242
+ console.log(chalk.white('Step 4: Exchange Code for Tokens\n'));
243
+ console.log(chalk.gray(' • Use the code to get your refresh token'));
244
+ console.log(chalk.gray(' • This can be done through the MCP tool: ebay_exchange_auth_code'));
245
+ console.log(chalk.gray(' • Or paste the code in the setup wizard when prompted\n'));
246
+ }
247
+ /**
248
+ * Get help text for RuName (Redirect URI)
249
+ */
250
+ export function getRuNameHelp() {
251
+ return `
252
+ ${chalk.bold.cyan('What is a RuName (Redirect URI)?')}
253
+
254
+ A RuName (Redirect URL name) is a unique identifier for your OAuth redirect URI.
255
+ It's required for eBay's OAuth flow to know where to send users after authorization.
256
+
257
+ ${chalk.bold.white('How to create a RuName:')}
258
+
259
+ 1. Go to eBay Developer Portal:
260
+ ${chalk.blue.underline('https://developer.ebay.com/my/keys')}
261
+
262
+ 2. Select your application
263
+
264
+ 3. Navigate to "User Tokens" section
265
+
266
+ 4. Click "Add RuName"
267
+
268
+ 5. Enter your redirect URI:
269
+ ${chalk.gray('For local development: http://localhost:3000/oauth/callback')}
270
+ ${chalk.gray('For production: https://your-domain.com/oauth/callback')}
271
+
272
+ 6. Copy the generated RuName and use it in your configuration
273
+
274
+ ${chalk.bold.white('Common RuName formats:')}
275
+
276
+ ${chalk.gray('• For localhost:')} YourCompany-YourApp-LocalTest-RuName
277
+ ${chalk.gray('• For production:')} YourCompany-YourApp-Production-RuName
278
+
279
+ ${chalk.yellow('Note:')} The RuName is NOT the same as the redirect URI itself.
280
+ It's a reference name that eBay associates with your redirect URI.
281
+ `;
282
+ }
283
+ /**
284
+ * Display first-time developer guide
285
+ */
286
+ export function displayFirstTimeDeveloperGuide() {
287
+ console.log(chalk.bold.cyan('\nšŸ†• First-Time eBay Developer Guide\n'));
288
+ console.log(chalk.white("Welcome! Here's how to get started:\n"));
289
+ console.log(chalk.bold.yellow('Step 1: Create eBay Developer Account\n'));
290
+ console.log(chalk.gray(' 1. Visit: ') + chalk.blue.underline('https://developer.ebay.com/'));
291
+ console.log(chalk.gray(' 2. Click "Register" or "Join"'));
292
+ console.log(chalk.gray(' 3. Complete the registration form'));
293
+ console.log(chalk.gray(' 4. Verify your email address\n'));
294
+ console.log(chalk.bold.yellow('Step 2: Create an Application\n'));
295
+ console.log(chalk.gray(' 1. Go to: ') + chalk.blue.underline('https://developer.ebay.com/my/keys'));
296
+ console.log(chalk.gray(' 2. Click "Create Application"'));
297
+ console.log(chalk.gray(' 3. Fill in application details (name, description)'));
298
+ console.log(chalk.gray(' 4. Choose Sandbox environment to start\n'));
299
+ console.log(chalk.bold.yellow('Step 3: Get Your Credentials\n'));
300
+ console.log(chalk.gray(' After creating the app, you will see:'));
301
+ console.log(chalk.gray(' • App ID (Client ID) - Copy this'));
302
+ console.log(chalk.gray(' • Cert ID (Client Secret) - Copy this'));
303
+ console.log(chalk.gray(' • These are needed for the setup wizard\n'));
304
+ console.log(chalk.bold.yellow('Step 4: Create RuName (Redirect URI)\n'));
305
+ console.log(chalk.gray(' 1. In your application settings'));
306
+ console.log(chalk.gray(' 2. Navigate to "User Tokens" section'));
307
+ console.log(chalk.gray(' 3. Click "Add RuName"'));
308
+ console.log(chalk.gray(' 4. Enter: http://localhost:3000/oauth/callback'));
309
+ console.log(chalk.gray(' 5. Save and copy the generated RuName\n'));
310
+ console.log(chalk.bold.yellow('Step 5: Get User Token\n'));
311
+ console.log(chalk.gray(' Option A: Use this setup wizard (recommended)'));
312
+ console.log(chalk.gray(' Option B: Manual OAuth flow through eBay Developer Portal\n'));
313
+ console.log(chalk.green.bold("āœ… Once you have these, you're ready to continue!\n"));
314
+ console.log(chalk.gray('Press Enter to continue when you have your credentials ready...'));
315
+ }