ebay-mcp 1.13.2 → 1.14.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 +3 -3
- package/README.es.md +3 -3
- package/README.fr.md +3 -3
- package/README.ja.md +3 -3
- package/README.ko.md +3 -3
- package/README.md +163 -41
- package/README.pt-BR.md +3 -3
- package/README.ru.md +3 -3
- package/README.zh-CN.md +3 -3
- package/build/api/account-management/account.js +633 -297
- package/build/api/analytics-and-report/analytics.js +111 -65
- package/build/api/client.js +199 -140
- package/build/api/clientRequestError.js +23 -0
- package/build/api/clientTrading.js +213 -0
- package/build/api/clientTradingError.js +4 -0
- package/build/api/communication/feedback.js +147 -59
- package/build/api/communication/message.js +134 -81
- package/build/api/communication/negotiation.js +65 -53
- package/build/api/communication/notification.js +458 -164
- package/build/api/developer/developer.js +99 -45
- package/build/api/index.js +23 -8
- package/build/api/listing-management/inventory.js +884 -338
- package/build/api/listing-metadata/metadata.js +416 -170
- package/build/api/listing-metadata/taxonomy.js +187 -42
- package/build/api/marketing-and-promotions/marketing.js +1392 -598
- package/build/api/marketing-and-promotions/recommendation.js +49 -24
- package/build/api/order-management/dispute.js +226 -45
- package/build/api/order-management/fulfillment.js +144 -71
- package/build/api/order-management/orderIssueHelpers.js +61 -0
- package/build/api/other/compliance.js +50 -38
- package/build/api/other/edelivery.js +603 -159
- package/build/api/other/finding.js +280 -0
- package/build/api/other/identity.js +30 -15
- package/build/api/other/translation.js +29 -14
- package/build/api/other/vero.js +113 -27
- package/build/api/rateLimitTracker.js +55 -0
- package/build/api/shared/request.js +189 -98
- package/build/api/trading/trading.js +154 -87
- package/build/auth/credentialSession.js +250 -0
- package/build/auth/oauth.js +298 -171
- package/build/auth/{oauth-metadata.js → oauthMetadata.js} +22 -6
- package/build/auth/oauthMiddleware.js +104 -0
- package/build/auth/{scope-utils.js → scopeUtils.js} +101 -28
- package/build/auth/tokenVerifier.js +243 -0
- package/build/auth/tokenVerifierError.js +21 -0
- package/build/config/environment.js +148 -113
- package/build/config/{tool-families.js → toolFamilies.js} +30 -14
- package/build/index.js +25 -19
- package/build/mcp/{http-transport.js → httpTransport.js} +102 -52
- package/build/mcp/readOnlyFilter.js +67 -0
- package/build/mcp/runtime.js +31 -13
- package/build/mcp/{tool-gating.js → toolGating.js} +77 -49
- package/build/mcp/{ui-bridge.js → uiBridge.js} +80 -23
- package/build/schemas/account-management/account.js +144 -6
- package/build/schemas/analytics/analytics.js +33 -19
- package/build/schemas/communication/messages.js +12 -42
- package/build/schemas/developer/developer.js +135 -0
- package/build/schemas/fulfillment/orders.js +183 -21
- package/build/schemas/index.js +27 -19
- package/build/schemas/inventory-management/inventory.js +17 -9
- package/build/schemas/marketing/marketing.js +480 -25
- package/build/schemas/metadata/metadata.js +11 -6
- package/build/schemas/other/finding.js +27 -0
- package/build/schemas/other/otherApis.js +424 -0
- package/build/schemas/taxonomy/taxonomy.js +11 -5
- package/build/scripts/{auto-setup.js → autoSetup.js} +87 -74
- package/build/scripts/{build-ui.js → buildUi.js} +6 -1
- package/build/scripts/{dev-sync.js → devSync.js} +169 -110
- package/build/scripts/diagnostics.js +52 -44
- package/build/scripts/{download-specs.js → downloadSpecs.js} +29 -21
- package/build/scripts/{interactive-setup.js → interactiveSetup.js} +84 -78
- package/build/scripts/setup.js +241 -178
- package/build/scripts/{setup-shared.js → setupShared.js} +29 -7
- package/build/scripts/skills.js +35 -27
- package/build/scripts/updateApiStatusDoc.js +71 -0
- package/build/serverHttp.js +90 -0
- package/build/skills/content.js +124 -118
- package/build/skills/index.js +22 -10
- package/build/skills/install.js +21 -10
- package/build/skills/markers.js +50 -15
- package/build/skills/{registry-snapshot.js → registrySnapshot.js} +8 -2
- package/build/skills/render.js +41 -14
- package/build/skills/targets.js +49 -17
- package/build/tools/categories/account.js +166 -264
- package/build/tools/categories/analytics.js +11 -22
- package/build/tools/categories/browse.js +17 -0
- package/build/tools/categories/communication.js +124 -399
- package/build/tools/categories/connector.js +23 -20
- package/build/tools/categories/developer.js +46 -159
- package/build/tools/categories/fulfillment.js +84 -215
- package/build/tools/categories/index.js +6 -14
- package/build/tools/categories/inventory.js +238 -293
- package/build/tools/categories/marketing.js +677 -39
- package/build/tools/categories/metadata.js +190 -117
- package/build/tools/categories/other.js +81 -208
- package/build/tools/categories/taxonomy.js +29 -20
- package/build/tools/categories/{token-management.js → tokenManagement.js} +187 -192
- package/build/tools/categories/trading.js +16 -47
- package/build/tools/contracts.js +34 -24
- package/build/tools/{define-tool.js → defineTool.js} +44 -29
- package/build/tools/registry.js +87 -29
- package/build/tools/schemas.js +3 -57
- package/build/tools/ui/archetypes.js +1 -0
- package/build/tools/ui/{map-helpers.js → mapHelpers.js} +69 -19
- package/build/tools/ui/maps.js +294 -80
- package/build/types/index.js +1 -1
- package/build/ui/card.html +14 -14
- package/build/ui/chart.html +14 -14
- package/build/ui/stat.html +87 -0
- package/build/ui/table.html +14 -14
- package/build/utils/apiStatusFeed.js +95 -0
- package/build/utils/cliOutput.js +15 -0
- package/build/utils/cliUi.js +108 -0
- package/build/utils/communication/feedback.js +57 -77
- package/build/utils/communication/message.js +69 -98
- package/build/utils/communication/negotiation.js +30 -57
- package/build/utils/communication/notification.js +112 -252
- package/build/utils/{date-converter.js → dateConverter.js} +62 -30
- package/build/utils/effectSchema.js +203 -0
- package/build/utils/effectSchemaAdapter.js +121 -0
- package/build/utils/effectSchemaChainMethods.js +146 -0
- package/build/utils/effectSchemaRefinements.js +104 -0
- package/build/utils/effectSchemaStringMethods.js +63 -0
- package/build/utils/effectSchemaTypes.js +47 -0
- package/build/utils/{env-parser.js → envParser.js} +10 -2
- package/build/utils/errors.js +7 -3
- package/build/utils/http.js +148 -89
- package/build/utils/{llm-client-detector.js → llmClientDetector.js} +295 -274
- package/build/utils/logger.js +127 -51
- package/build/utils/{oauth-helper.js → oauthHelper.js} +127 -90
- package/build/utils/other/compliance.js +18 -38
- package/build/utils/other/identity.js +2 -2
- package/build/utils/other/translation.js +4 -4
- package/build/utils/other/vero.js +36 -20
- package/build/utils/schemaHelpers.js +22 -0
- package/build/utils/scopeHelper.js +270 -0
- package/build/utils/securityChecker.js +316 -0
- package/build/utils/{setup-validator.js → setupValidator.js} +113 -94
- package/build/utils/{setup-wizard.js → setupWizard.js} +57 -46
- package/build/utils/{token-utils.js → tokenUtils.js} +2 -2
- package/build/utils/trading/trading.js +35 -0
- package/build/utils/typeGuards.js +12 -0
- package/build/utils/version.js +65 -29
- package/package.json +10 -8
- package/build/api/client-trading.js +0 -124
- package/build/api/communication/shared.js +0 -59
- package/build/api/shared/query-params.js +0 -16
- package/build/auth/credential-session.js +0 -166
- package/build/auth/oauth-middleware.js +0 -100
- package/build/auth/token-verifier.js +0 -186
- package/build/schemas/other/other-apis.js +0 -390
- package/build/scripts/update-api-status-doc.js +0 -44
- package/build/server-http.js +0 -85
- package/build/tools/definitions/marketing.js +0 -1381
- package/build/tools/tool-handlers/marketing.js +0 -312
- package/build/utils/account-management/account.js +0 -818
- package/build/utils/api-status-feed.js +0 -84
- package/build/utils/cli-ui.js +0 -47
- package/build/utils/order-management/dispute.js +0 -369
- package/build/utils/order-management/fulfillment.js +0 -205
- package/build/utils/other/edelivery.js +0 -235
- package/build/utils/schema-helpers.js +0 -13
- package/build/utils/scope-helper.js +0 -207
- package/build/utils/security-checker.js +0 -248
- package/build/utils/type-guards.js +0 -6
- /package/build/auth/{oauth-types.js → oauthTypes.js} +0 -0
- /package/build/{server-http.d.ts → serverHttp.d.ts} +0 -0
- /package/build/tools/ui/{view-models.js → viewModels.js} +0 -0
- /package/build/types/{ebay-enums.js → ebayEnums.js} +0 -0
|
@@ -9,8 +9,16 @@ import dotenv from 'dotenv';
|
|
|
9
9
|
* `v^1.1#i^1#...`, and a naive parser either keeps stray quotes or trips over
|
|
10
10
|
* the `#`. Placeholder values (e.g. `your-client-id_here`) are skipped so the
|
|
11
11
|
* wizard treats them as unset.
|
|
12
|
+
*
|
|
13
|
+
* @param projectRoot - Project root containing the `.env` file.
|
|
14
|
+
* @returns Parsed config values with placeholders removed.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const config = loadExistingConfig(process.cwd());
|
|
19
|
+
* ```
|
|
12
20
|
*/
|
|
13
|
-
export
|
|
21
|
+
export const loadExistingConfig = (projectRoot) => {
|
|
14
22
|
const envPath = join(projectRoot, '.env');
|
|
15
23
|
if (!existsSync(envPath)) {
|
|
16
24
|
return {};
|
|
@@ -23,7 +31,7 @@ export function loadExistingConfig(projectRoot) {
|
|
|
23
31
|
}
|
|
24
32
|
}
|
|
25
33
|
return envConfig;
|
|
26
|
-
}
|
|
34
|
+
};
|
|
27
35
|
/**
|
|
28
36
|
* Quote a value for safe inclusion in a `.env` line.
|
|
29
37
|
*
|
|
@@ -34,16 +42,30 @@ export function loadExistingConfig(projectRoot) {
|
|
|
34
42
|
* embedded backslashes and double quotes) so dotenv restores it verbatim. This
|
|
35
43
|
* mirrors the quoting `dotenv-stringify` already applies in the runtime
|
|
36
44
|
* credential store, keeping both `.env` writers consistent.
|
|
45
|
+
*
|
|
46
|
+
* @param value - Raw environment value to serialize.
|
|
47
|
+
* @returns A dotenv-safe value string.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* const line = `EBAY_USER_REFRESH_TOKEN=${quoteEnvValue(token)}`;
|
|
52
|
+
* ```
|
|
37
53
|
*/
|
|
38
|
-
export
|
|
54
|
+
export const quoteEnvValue = (value) => {
|
|
39
55
|
if (value === '' || !/[#\s"'`]/.test(value)) {
|
|
40
56
|
return value;
|
|
41
57
|
}
|
|
42
58
|
return `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
43
|
-
}
|
|
59
|
+
};
|
|
44
60
|
/**
|
|
45
61
|
* Parse environment with safe sandbox default.
|
|
62
|
+
*
|
|
63
|
+
* @param value - Optional environment value from config or user input.
|
|
64
|
+
* @returns `production` only for an exact production value; otherwise `sandbox`.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* const environment = readEnvironment(config.EBAY_ENVIRONMENT);
|
|
69
|
+
* ```
|
|
46
70
|
*/
|
|
47
|
-
export
|
|
48
|
-
return value === 'production' ? 'production' : 'sandbox';
|
|
49
|
-
}
|
|
71
|
+
export const readEnvironment = (value) => value === 'production' ? 'production' : 'sandbox';
|
package/build/scripts/skills.js
CHANGED
|
@@ -3,27 +3,27 @@ import { resolve } from 'path';
|
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import prompts from 'prompts';
|
|
5
5
|
import { ALL_PROVIDERS, applyWrite, buildRegistrySnapshot, detectProvider, planWrite, providerLabel, renderSkillTargets, } from '../skills/index.js';
|
|
6
|
-
import { ebayPalette, printHeading, printInfo, printRule, printSuccess, printWarning, ui, } from '../utils/
|
|
6
|
+
import { ebayPalette, printHeading, printInfo, printRule, printSuccess, printWarning, ui, } from '../utils/cliUi.js';
|
|
7
|
+
import { getErrorMessage } from '../utils/errors.js';
|
|
8
|
+
import { Effect, Either } from 'effect';
|
|
9
|
+
import process from 'node:process';
|
|
7
10
|
const ALL_LAYERS = ['using', 'contributing'];
|
|
8
11
|
/** Splits a comma list flag value into trimmed, non-empty tokens. */
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
.filter(Boolean);
|
|
14
|
-
}
|
|
12
|
+
const parseList = (value) => (value ?? '')
|
|
13
|
+
.split(',')
|
|
14
|
+
.map((token) => token.trim())
|
|
15
|
+
.filter(Boolean);
|
|
15
16
|
/** Reads the value after a `--flag value` or `--flag=value` argument. */
|
|
16
|
-
|
|
17
|
+
const readFlagValue = (argv, flag) => {
|
|
17
18
|
const inline = argv.find((arg) => arg.startsWith(`${flag}=`));
|
|
18
19
|
if (inline)
|
|
19
20
|
return inline.slice(flag.length + 1);
|
|
20
21
|
const index = argv.indexOf(flag);
|
|
21
22
|
if (index !== -1 && index + 1 < argv.length)
|
|
22
23
|
return argv[index + 1];
|
|
23
|
-
|
|
24
|
-
}
|
|
24
|
+
};
|
|
25
25
|
/** Parses skills CLI flags, ignoring the leading `skills` subcommand token. */
|
|
26
|
-
|
|
26
|
+
const parseFlags = (argv) => {
|
|
27
27
|
const args = argv.filter((arg) => arg !== 'skills');
|
|
28
28
|
const providers = parseList(readFlagValue(args, '--providers')).filter((value) => ALL_PROVIDERS.includes(value));
|
|
29
29
|
const layers = parseList(readFlagValue(args, '--layer') ?? readFlagValue(args, '--layers')).filter((value) => ALL_LAYERS.includes(value));
|
|
@@ -36,9 +36,9 @@ function parseFlags(argv) {
|
|
|
36
36
|
providers: providers.length > 0 ? providers : undefined,
|
|
37
37
|
layers: layers.length > 0 ? layers : undefined,
|
|
38
38
|
};
|
|
39
|
-
}
|
|
39
|
+
};
|
|
40
40
|
/** One-line summary of what an action means, for the preview. */
|
|
41
|
-
|
|
41
|
+
const actionLabel = (action) => {
|
|
42
42
|
switch (action) {
|
|
43
43
|
case 'create':
|
|
44
44
|
return ui.success('create');
|
|
@@ -49,9 +49,9 @@ function actionLabel(action) {
|
|
|
49
49
|
case 'skip-foreign':
|
|
50
50
|
return ui.warning('skip (foreign file)');
|
|
51
51
|
}
|
|
52
|
-
}
|
|
52
|
+
};
|
|
53
53
|
/** Prints the planned writes so the user can review before anything is written. */
|
|
54
|
-
|
|
54
|
+
const printPreview = (plans) => {
|
|
55
55
|
printHeading('Planned changes');
|
|
56
56
|
printRule();
|
|
57
57
|
for (const plan of plans) {
|
|
@@ -60,9 +60,9 @@ function printPreview(plans) {
|
|
|
60
60
|
console.log(` ${ui.dim('→ ' + plan.target.path)}`);
|
|
61
61
|
}
|
|
62
62
|
printRule();
|
|
63
|
-
}
|
|
63
|
+
};
|
|
64
64
|
/** Prints CLI usage. */
|
|
65
|
-
|
|
65
|
+
const printHelp = () => {
|
|
66
66
|
console.log(`
|
|
67
67
|
${ui.bold('ebay-mcp skills')} ${ui.dim('install AI skills for Codex, Claude Code, and Cursor')}
|
|
68
68
|
|
|
@@ -84,11 +84,9 @@ ${ui.bold('Examples:')}
|
|
|
84
84
|
ebay-mcp skills --providers cursor,codex --layer using --dry-run
|
|
85
85
|
ebay-mcp skills --yes
|
|
86
86
|
`);
|
|
87
|
-
}
|
|
87
|
+
};
|
|
88
88
|
/** Resolves the providers to use, preferring flags, else detection at the scope. */
|
|
89
|
-
|
|
90
|
-
return ALL_PROVIDERS.filter((provider) => detectProvider(provider, scope, cwd, home));
|
|
91
|
-
}
|
|
89
|
+
const resolveDefaultProviders = (scope, cwd, home) => ALL_PROVIDERS.filter((provider) => detectProvider(provider, scope, cwd, home));
|
|
92
90
|
/**
|
|
93
91
|
* Runs the skills installer end to end: detect → choose providers/layers/scope →
|
|
94
92
|
* preview → confirm → write. Interactive by default; non-interactive when `--yes`
|
|
@@ -97,9 +95,14 @@ function resolveDefaultProviders(scope, cwd, home) {
|
|
|
97
95
|
* Shared by the `ebay-mcp skills` subcommand, `npm run skills`, and the optional
|
|
98
96
|
* step at the end of `npm run setup`.
|
|
99
97
|
*
|
|
100
|
-
* @param options
|
|
98
|
+
* @param options Runtime overrides for arguments and setup embedding.
|
|
99
|
+
* @returns A promise that resolves after the installer exits or writes files.
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* await runSkillsWizard({ argv: ['--providers', 'codex', '--yes'] });
|
|
103
|
+
* ```
|
|
101
104
|
*/
|
|
102
|
-
export async
|
|
105
|
+
export const runSkillsWizard = async (options = {}) => {
|
|
103
106
|
const flags = parseFlags(options.argv ?? process.argv.slice(2));
|
|
104
107
|
if (flags.help) {
|
|
105
108
|
printHelp();
|
|
@@ -227,12 +230,17 @@ export async function runSkillsWizard(options = {}) {
|
|
|
227
230
|
}
|
|
228
231
|
printHeading('Done');
|
|
229
232
|
printInfo(`${written} file(s) written. Restart your AI tool so it picks up the new skills.`);
|
|
230
|
-
}
|
|
233
|
+
};
|
|
231
234
|
const entryPath = process.argv[1] ? resolve(process.argv[1]) : undefined;
|
|
232
235
|
const modulePath = resolve(fileURLToPath(import.meta.url));
|
|
233
236
|
if (entryPath && modulePath === entryPath) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
+
void Effect.runPromise(Effect.either(Effect.tryPromise({
|
|
238
|
+
try: () => runSkillsWizard(),
|
|
239
|
+
catch: (error) => error,
|
|
240
|
+
}))).then((result) => {
|
|
241
|
+
if (Either.isLeft(result)) {
|
|
242
|
+
console.error(ui.error('\n Skills install failed:'), getErrorMessage(result.left));
|
|
243
|
+
process.exitCode = 1;
|
|
244
|
+
}
|
|
237
245
|
});
|
|
238
246
|
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches the eBay API Status RSS feed and writes the latest items to docs/API_STATUS.md.
|
|
3
|
+
* Used by the GitHub Action to keep an in-repo snapshot. Run with: npx tsx src/scripts/updateApiStatusDoc.ts
|
|
4
|
+
*/
|
|
5
|
+
import { writeFileSync } from 'node:fs';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { getApiStatusFeed } from '../utils/apiStatusFeed.js';
|
|
8
|
+
import { getErrorMessage } from '../utils/errors.js';
|
|
9
|
+
import { Data, Effect, Either } from 'effect';
|
|
10
|
+
import process from 'node:process';
|
|
11
|
+
const DEFAULT_LIMIT = 15;
|
|
12
|
+
const OUT_PATH = join(process.cwd(), 'docs', 'API_STATUS.md');
|
|
13
|
+
/** Tagged failure raised while updating the checked-in API status snapshot. */
|
|
14
|
+
class ApiStatusDocUpdateError extends Data.TaggedError('ApiStatusDocUpdateError') {
|
|
15
|
+
}
|
|
16
|
+
function escapeCell(s) {
|
|
17
|
+
return s.replace(/\|/g, '\\|').replace(/\n/g, ' ');
|
|
18
|
+
}
|
|
19
|
+
function buildMarkdown(items) {
|
|
20
|
+
const lines = [
|
|
21
|
+
'# eBay API Status (latest)',
|
|
22
|
+
'',
|
|
23
|
+
'Auto-updated snapshot from the [eBay API Status RSS feed](https://developer.ebay.com/rss/api-status).',
|
|
24
|
+
'Full list: [developer.ebay.com/support/api-status](https://developer.ebay.com/support/api-status).',
|
|
25
|
+
'',
|
|
26
|
+
`*Last updated: ${new Date().toISOString()}*`,
|
|
27
|
+
'',
|
|
28
|
+
'| Title | API | Site | Status | Last updated | Link |',
|
|
29
|
+
'|-------|-----|------|--------|--------------|------|',
|
|
30
|
+
];
|
|
31
|
+
for (const item of items) {
|
|
32
|
+
const link = item.link ? `[Details](${item.link})` : '';
|
|
33
|
+
lines.push(`| ${escapeCell(item.title)} | ${escapeCell(item.api)} | ${escapeCell(item.site)} | ${escapeCell(item.status)} | ${escapeCell(item.lastUpdated)} | ${link} |`);
|
|
34
|
+
}
|
|
35
|
+
lines.push('', '---', '', '*Generated by [ebay-mcp](https://github.com/YosefHayim/ebay-mcp) API status sync.*');
|
|
36
|
+
return lines.join('\n');
|
|
37
|
+
}
|
|
38
|
+
const updateApiStatusDoc = () => Effect.gen(function* () {
|
|
39
|
+
const { items, error } = yield* getApiStatusFeed({ limit: DEFAULT_LIMIT }).pipe(Effect.mapError((cause) => new ApiStatusDocUpdateError({
|
|
40
|
+
message: 'Failed to fetch API status feed',
|
|
41
|
+
cause,
|
|
42
|
+
})));
|
|
43
|
+
if (error && items.length === 0) {
|
|
44
|
+
return yield* Effect.fail(new ApiStatusDocUpdateError({
|
|
45
|
+
message: `Failed to fetch API status feed: ${error}`,
|
|
46
|
+
cause: error,
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
const markdown = buildMarkdown(items);
|
|
50
|
+
yield* Effect.try({
|
|
51
|
+
try: () => writeFileSync(OUT_PATH, markdown, 'utf8'),
|
|
52
|
+
catch: (cause) => new ApiStatusDocUpdateError({
|
|
53
|
+
message: `Failed to write API status doc to ${OUT_PATH}`,
|
|
54
|
+
cause,
|
|
55
|
+
}),
|
|
56
|
+
});
|
|
57
|
+
return items.length;
|
|
58
|
+
});
|
|
59
|
+
async function main() {
|
|
60
|
+
const count = await Effect.runPromise(updateApiStatusDoc());
|
|
61
|
+
console.log(`Wrote ${count} items to ${OUT_PATH}`);
|
|
62
|
+
}
|
|
63
|
+
void Effect.runPromise(Effect.either(Effect.tryPromise({
|
|
64
|
+
try: main,
|
|
65
|
+
catch: (error) => error,
|
|
66
|
+
}))).then((result) => {
|
|
67
|
+
if (Either.isLeft(result)) {
|
|
68
|
+
console.error(getErrorMessage(result.left, String(result.left)));
|
|
69
|
+
process.exitCode = 1;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* eBay API MCP Server with HTTP Transport and OAuth 2.1 Authorization.
|
|
3
|
+
*/
|
|
4
|
+
import { resolve } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import { validateEnvironmentConfig } from './config/environment.js';
|
|
7
|
+
import { createHttpMcpApp, createHttpTransportConfigFromEnv, getHttpServerUrl, } from './mcp/httpTransport.js';
|
|
8
|
+
import { getErrorMessage } from './utils/errors.js';
|
|
9
|
+
import { serverLogger } from './utils/logger.js';
|
|
10
|
+
import { Effect, Either } from 'effect';
|
|
11
|
+
import process from 'node:process';
|
|
12
|
+
const CONFIG = createHttpTransportConfigFromEnv(process.env);
|
|
13
|
+
function logEnvironmentValidation() {
|
|
14
|
+
const validation = validateEnvironmentConfig();
|
|
15
|
+
validation.infos.forEach((info) => {
|
|
16
|
+
serverLogger.info(info);
|
|
17
|
+
});
|
|
18
|
+
if (validation.warnings.length > 0) {
|
|
19
|
+
serverLogger.warn('Environment Configuration Warnings:');
|
|
20
|
+
validation.warnings.forEach((warning) => {
|
|
21
|
+
serverLogger.warn(warning);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
if (!validation.isValid) {
|
|
25
|
+
serverLogger.error('Environment Configuration Errors:');
|
|
26
|
+
validation.errors.forEach((error) => {
|
|
27
|
+
serverLogger.error(error);
|
|
28
|
+
});
|
|
29
|
+
serverLogger.error('Please fix the configuration errors and restart the server.');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function logConfiguration() {
|
|
34
|
+
serverLogger.info('Configuration:');
|
|
35
|
+
serverLogger.info(`Host: ${CONFIG.host}`);
|
|
36
|
+
serverLogger.info(`Port: ${CONFIG.port}`);
|
|
37
|
+
serverLogger.info(`OAuth Enabled: ${CONFIG.authEnabled}`);
|
|
38
|
+
if (CONFIG.authEnabled) {
|
|
39
|
+
serverLogger.info(`Auth Server: ${CONFIG.oauth.authServerUrl}`);
|
|
40
|
+
serverLogger.info(`Required Scopes: ${CONFIG.oauth.requiredScopes.join(', ')}`);
|
|
41
|
+
serverLogger.info(`Verification Method: ${CONFIG.oauth.useIntrospection ? 'Introspection' : 'JWT'}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function logStartupUrls(serverUrl) {
|
|
45
|
+
serverLogger.info('Server is running!');
|
|
46
|
+
serverLogger.info(`MCP endpoint: ${serverUrl}/`);
|
|
47
|
+
serverLogger.info(`Protected Resource Metadata: ${serverUrl}/.well-known/oauth-protected-resource`);
|
|
48
|
+
serverLogger.info(`Health check: ${serverUrl}/health`);
|
|
49
|
+
if (CONFIG.authEnabled) {
|
|
50
|
+
serverLogger.info('Authorization is ENABLED');
|
|
51
|
+
serverLogger.info('Clients must provide valid Bearer tokens to access MCP endpoints');
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
serverLogger.warn('Authorization is DISABLED');
|
|
55
|
+
serverLogger.warn('Set OAUTH_ENABLED=true (or remove OAUTH_ENABLED=false) to enable OAuth protection');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function main() {
|
|
59
|
+
const started = await Effect.runPromise(Effect.either(Effect.gen(function* () {
|
|
60
|
+
serverLogger.info('Starting eBay API MCP Server (HTTP + OAuth)...');
|
|
61
|
+
logEnvironmentValidation();
|
|
62
|
+
logConfiguration();
|
|
63
|
+
const app = yield* Effect.tryPromise({
|
|
64
|
+
try: () => createHttpMcpApp(CONFIG),
|
|
65
|
+
catch: (error) => error,
|
|
66
|
+
});
|
|
67
|
+
const serverUrl = getHttpServerUrl(CONFIG);
|
|
68
|
+
const server = app.listen(CONFIG.port, CONFIG.host, () => {
|
|
69
|
+
logStartupUrls(serverUrl);
|
|
70
|
+
});
|
|
71
|
+
process.on('SIGINT', () => {
|
|
72
|
+
serverLogger.info('Shutting down...');
|
|
73
|
+
server.close(() => {
|
|
74
|
+
serverLogger.info('Server closed');
|
|
75
|
+
process.exit(0);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
})));
|
|
79
|
+
if (Either.isLeft(started)) {
|
|
80
|
+
serverLogger.error('Fatal error starting server', {
|
|
81
|
+
error: getErrorMessage(started.left, String(started.left)),
|
|
82
|
+
});
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const entryPath = process.argv[1] ? resolve(process.argv[1]) : undefined;
|
|
87
|
+
const modulePath = resolve(fileURLToPath(import.meta.url));
|
|
88
|
+
if (entryPath && modulePath === entryPath) {
|
|
89
|
+
await main();
|
|
90
|
+
}
|
package/build/skills/content.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/** Renders the live family index as a Markdown table. */
|
|
2
|
-
|
|
2
|
+
const familyTable = (snapshot) => {
|
|
3
3
|
const rows = snapshot.families
|
|
4
4
|
.map((family) => `| ${family.title} | ${family.count} | ${family.blurb} |`)
|
|
5
5
|
.join('\n');
|
|
6
6
|
return ['| Family | Tools | Covers |', '| --- | --- | --- |', rows].join('\n');
|
|
7
|
-
}
|
|
7
|
+
};
|
|
8
8
|
/**
|
|
9
9
|
* Builds the "using" skill: how a developer's AI should drive the eBay MCP
|
|
10
10
|
* tools. Workflow-first and lean — the per-tool schemas are already visible via
|
|
@@ -14,67 +14,70 @@ function familyTable(snapshot) {
|
|
|
14
14
|
*
|
|
15
15
|
* @param snapshot Live tool count and family index.
|
|
16
16
|
* @returns The provider-neutral skill document.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const doc = buildUsingDoc(snapshot);
|
|
21
|
+
* ```
|
|
17
22
|
*/
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
{
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
};
|
|
77
|
-
}
|
|
23
|
+
export const buildUsingDoc = (snapshot) => ({
|
|
24
|
+
slug: 'ebay-mcp-using',
|
|
25
|
+
title: 'Using the eBay MCP tools',
|
|
26
|
+
description: `Drive eBay's Sell APIs through the ebay-mcp server: ${snapshot.toolCount} tools for listings, orders, marketing, and analytics. Use when creating or revising listings, fulfilling orders, issuing refunds, running Promoted Listings campaigns, or debugging eBay auth/rate-limit errors.`,
|
|
27
|
+
intro: `The \`ebay-mcp\` server exposes **${snapshot.toolCount} tools across 100% of eBay's Sell APIs**, running locally over MCP. Every tool is named \`ebay_<verb>_<noun>\` (plus two ChatGPT-connector tools, \`search\`/\`fetch\`). You already see each tool's input schema via \`tools/list\` — this skill covers what discovery can't: which tools to chain, what eBay requires first, and how to read its errors.`,
|
|
28
|
+
sections: [
|
|
29
|
+
{
|
|
30
|
+
heading: 'Authentication & environment',
|
|
31
|
+
body: [
|
|
32
|
+
'- **Two auth tiers.** An app token allows ≈1,000 requests/day; user OAuth allows ≈10k–50k/day. Most write operations require user OAuth.',
|
|
33
|
+
'- **A 401 / "access denied" is almost always a scope or environment problem**, not a malformed request. Check `ebay_get_token_status`, then re-run `npm run setup` if a scope is missing.',
|
|
34
|
+
'- **Sandbox and production are separate worlds** — separate credentials and separate data. Confirm `EBAY_ENVIRONMENT` before investigating "missing" data.',
|
|
35
|
+
'- **Marketplace & language headers matter.** Calls honor `EBAY_MARKETPLACE_ID` (e.g. `EBAY_US`) and `Content-Language` (e.g. `en-US`); a wrong pair causes empty or rejected results.',
|
|
36
|
+
].join('\n'),
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
heading: 'Core workflows',
|
|
40
|
+
body: [
|
|
41
|
+
'**Publish a fixed-price listing (REST Inventory model).**',
|
|
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. `ebay_create_or_replace_inventory_item` (SKU + product details + availability).',
|
|
44
|
+
'3. `ebay_create_offer` (SKU, marketplace, price, the policy IDs, location).',
|
|
45
|
+
'4. `ebay_publish_offer` (offerId) → a live `listingId`. Use `ebay_bulk_publish_offer` for many at once.',
|
|
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.',
|
|
49
|
+
'',
|
|
50
|
+
'**Fulfill an order.**',
|
|
51
|
+
'`ebay_get_orders` (filter unfulfilled) → `ebay_get_order` (detail) → `ebay_create_shipping_fulfillment` (tracking number + carrier).',
|
|
52
|
+
'',
|
|
53
|
+
'**Refund or handle a payment dispute.**',
|
|
54
|
+
'Voluntary refund: `ebay_issue_refund`. Disputes: `ebay_get_payment_dispute_summaries` → `ebay_get_payment_dispute` → `ebay_accept_payment_dispute` (or contest it).',
|
|
55
|
+
'',
|
|
56
|
+
'**Promote listings (Promoted Listings).**',
|
|
57
|
+
'`ebay_create_campaign` → `ebay_bulk_create_ads_by_inventory_reference`. The Marketing family also covers promotions and reports.',
|
|
58
|
+
'',
|
|
59
|
+
'**Legacy XML path (Trading API).**',
|
|
60
|
+
'`ebay_create_listing` / `ebay_revise_listing` / `ebay_relist_item` / `ebay_end_listing`, list via `ebay_get_active_listings`. Use only when you specifically need the legacy flow — do not mix it with the REST Inventory model for the same SKU.',
|
|
61
|
+
'',
|
|
62
|
+
'**Diagnose failing calls.**',
|
|
63
|
+
'`ebay_get_token_status` (auth valid/expiring?) → `ebay_get_rate_limits` / `ebay_get_user_rate_limits` (quota hit?) → `ebay_get_api_status` (eBay-side outage?).',
|
|
64
|
+
].join('\n'),
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
heading: 'Gotchas & disambiguation',
|
|
68
|
+
body: [
|
|
69
|
+
'- **Two listing models.** REST Inventory (`inventory_item` → `offer` → `publish`) vs legacy Trading (XML). Pick one per SKU and stay in it.',
|
|
70
|
+
'- **Offers need policies + a location first.** A "policy not found" error usually means the one-time account setup was skipped.',
|
|
71
|
+
'- **`search` and `fetch` are ChatGPT-connector only** — ignore them when driving the Sell API directly.',
|
|
72
|
+
'- **Write actions are real.** `publish`, `issue_refund`, `end_listing`, and any `bulk_*` change live seller data — confirm intent before calling.',
|
|
73
|
+
].join('\n'),
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
heading: `Tool families (${snapshot.toolCount} tools)`,
|
|
77
|
+
body: familyTable(snapshot),
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
});
|
|
78
81
|
/**
|
|
79
82
|
* Builds the "contributing" skill: how an AI working on the ebay-mcp repo should
|
|
80
83
|
* operate. Mirrors AGENTS.md (validation commands, module map, the add-a-tool
|
|
@@ -82,60 +85,63 @@ export function buildUsingDoc(snapshot) {
|
|
|
82
85
|
*
|
|
83
86
|
* @param snapshot Live tool count and family index.
|
|
84
87
|
* @returns The provider-neutral skill document.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* const doc = buildContributingDoc(snapshot);
|
|
92
|
+
* ```
|
|
85
93
|
*/
|
|
86
|
-
export
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
};
|
|
141
|
-
}
|
|
94
|
+
export const buildContributingDoc = (snapshot) => ({
|
|
95
|
+
slug: 'ebay-mcp-contributing',
|
|
96
|
+
title: 'Contributing to ebay-mcp',
|
|
97
|
+
description: `Work on the ebay-mcp server itself: ${snapshot.toolCount} tools across eBay's Sell APIs (TypeScript/ESM, Effect-backed validation, OpenAPI-generated types). Use when adding or changing eBay tools/endpoints, wiring the registry, or running the project's checks.`,
|
|
98
|
+
intro: `A local MCP server exposing **${snapshot.toolCount} tools across 100% of eBay's Sell APIs** — TypeScript/Node.js (ESM), \`@modelcontextprotocol/sdk\`, Effect-backed validation, OpenAPI-generated types. Entry points: \`src/index.ts\` (STDIO) and \`src/serverHttp.ts\` (HTTP).`,
|
|
99
|
+
sections: [
|
|
100
|
+
{
|
|
101
|
+
heading: 'Validation (run before a PR)',
|
|
102
|
+
body: [
|
|
103
|
+
'```bash',
|
|
104
|
+
'npm run check # tsc --noEmit + eslint + prettier --check (must pass)',
|
|
105
|
+
'npm test # vitest run',
|
|
106
|
+
'npm run build # tsc + tsc-alias → build/',
|
|
107
|
+
'```',
|
|
108
|
+
].join('\n'),
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
heading: 'Module map (`src/`)',
|
|
112
|
+
body: [
|
|
113
|
+
'| Path | Owns |',
|
|
114
|
+
'| --- | --- |',
|
|
115
|
+
'| `index.ts` / `serverHttp.ts` | MCP entry points (STDIO / HTTP) |',
|
|
116
|
+
'| `api/` | eBay API client implementations (one area per file) |',
|
|
117
|
+
'| `auth/` | OAuth 2.0 flow and token management |',
|
|
118
|
+
'| `config/` | Environment loading, constants, marketplace defaults |',
|
|
119
|
+
'| `tools/` | Tool wiring — `registry.ts`, `contracts.ts`, `defineTool.ts`, and `categories/` (13 family files that co-locate each tool definition with its handler via `defineTool`) |',
|
|
120
|
+
"| `skills/` | Agent-skills generator (this skill's source) |",
|
|
121
|
+
'| `schemas/` | Shared Effect-backed schemas |',
|
|
122
|
+
"| `types/` | TypeScript types — **auto-generated** from OpenAPI specs (don't hand-edit) |",
|
|
123
|
+
'| `scripts/` | CLI tooling: `setup.ts`, `skills.ts`, `devSync.ts`, `diagnostics.ts` |',
|
|
124
|
+
'| `utils/` | Shared utilities (logging, http, errors) |',
|
|
125
|
+
].join('\n'),
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
heading: 'Add a tool or endpoint',
|
|
129
|
+
body: [
|
|
130
|
+
'1. `npm run sync` — download the latest eBay specs, regenerate types, report missing endpoints.',
|
|
131
|
+
'2. Add the API method in `src/api/`.',
|
|
132
|
+
'3. Add a `defineTool({ ... handler })` entry in the matching `src/tools/categories/<family>.ts` — definition and handler live together; `registry.ts` derives everything from `categories/index.ts`.',
|
|
133
|
+
'4. Add tests in `tests/`.',
|
|
134
|
+
'5. `npm run check && npm test`.',
|
|
135
|
+
].join('\n'),
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
heading: 'Conventions',
|
|
139
|
+
body: [
|
|
140
|
+
'- **No `any`** — specific types; prefer narrowing over assertions. `types/` is generated, so model new shapes from the specs.',
|
|
141
|
+
'- Validate tool inputs with Effect-backed schemas from `@/utils/effectSchema.js`; derive related schemas rather than duplicating fields.',
|
|
142
|
+
'- Commit with Conventional Commits (releases are changeset-driven).',
|
|
143
|
+
'- Logs go to **stderr** only — stdout is reserved for the MCP protocol.',
|
|
144
|
+
].join('\n'),
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
});
|