ebay-api-mcp-server-node-local 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,214 @@
1
+ # eBay API MCP Server
2
+
3
+ A Model Context Protocol (MCP) server that provides seamless integration with eBay's APIs through AI assistants and development tools.
4
+
5
+ ## Overview
6
+
7
+ This MCP server enables AI assistants (Claude Desktop, Cursor, Cline, VS Code extensions, etc.) to interact with eBay's comprehensive API ecosystem. It provides tools for API document retrieval, endpoint discovery, and direct API invocation, making it easy to integrate eBay marketplace functionality into AI-powered workflows.
8
+
9
+ ### Key Features
10
+
11
+ - **API Discovery**: Automatically discover and explore eBay API endpoints
12
+ - **Dynamic Tool Generation**: Generate tools based on OpenAPI specifications
13
+ - **Multi-Environment Support**: Works with both sandbox and production environments
14
+ - **Comprehensive API Coverage**: Supports eBay's full API ecosystem
15
+ - **Type-Safe Operations**: Built with TypeScript for robust API interactions
16
+ - **MCP Integration**: Compatible with popular MCP hosts and AI assistants
17
+
18
+ ## Prerequisites
19
+
20
+ - **Node.js**: Version 22 or higher
21
+ - **eBay Developer Account**: Required for API access tokens
22
+ - **MCP Host**: Claude Desktop, Cursor, Cline, or other MCP-compatible application
23
+
24
+ ## Installation
25
+
26
+ ### 1. Clone and Setup
27
+
28
+ ```bash
29
+ git clone <repository-url>
30
+ cd ebay-api-mcp-server-node-local
31
+ npm install
32
+ ```
33
+
34
+ ### 2. Build the Project
35
+
36
+ ```bash
37
+ npm run build
38
+ # or
39
+ yarn build
40
+ ```
41
+
42
+ ### 3. Environment Configuration
43
+
44
+ Set the following environment variables:
45
+
46
+ - `EBAY_CLIENT_TOKEN`: Your eBay API access token (required)
47
+ - `EBAY_API_ENV`: API environment - "sandbox" or "production" (default: "production")
48
+
49
+ ## Authentication
50
+
51
+ ### Obtaining an eBay API Token
52
+
53
+ #### Method 1: Using cURL
54
+
55
+ ```bash
56
+ curl -v https://api.ebay.com/identity/v1/oauth2/token \
57
+ -H "Accept: application/json" \
58
+ -H "Accept-Language: en_US" \
59
+ -u "CLIENT_ID:CLIENT_SECRET" \
60
+ -d "grant_type=client_credentials"
61
+ ```
62
+
63
+ For sandbox testing, use `https://api.sandbox.ebay.com/identity/v1/oauth2/token`
64
+
65
+ #### Method 2: Using Postman
66
+
67
+ 1. Create a POST request to `https://api.ebay.com/identity/v1/oauth2/token`
68
+ 2. Set Authorization to Basic Auth with your Client ID and Client Secret
69
+ 3. Add form data: `grant_type=client_credentials`
70
+ 4. Send the request
71
+
72
+ Response format:
73
+ ```json
74
+ {
75
+ "access_token": "your_access_token_here",
76
+ "expires_in": 7200,
77
+ "token_type": "Application Access Token"
78
+ }
79
+ ```
80
+
81
+ ## Usage
82
+
83
+ ### Running the Server
84
+
85
+ #### With Environment Variables Set
86
+
87
+ ```bash
88
+ npm start
89
+ # or
90
+ yarn start
91
+ ```
92
+
93
+ #### With Inline Environment Variables
94
+
95
+ ```bash
96
+ EBAY_CLIENT_TOKEN='your_token_here' EBAY_API_ENV='production' npm start
97
+ ```
98
+
99
+ #### Using npx
100
+
101
+ You can also run the server using `npx` in several ways:
102
+
103
+ **Option 1: Run the built server directly**
104
+ ```bash
105
+ # First build the project
106
+ npm run build
107
+
108
+ # Then run with npx
109
+ npx node dist/index.js
110
+ ```
111
+
112
+ **Option 2: Run with environment variables**
113
+ ```bash
114
+ # Build first
115
+ npm run build
116
+
117
+ # Run with environment variables
118
+ EBAY_CLIENT_TOKEN='your_token_here' EBAY_API_ENV='production' npx node dist/index.js
119
+ ```
120
+
121
+ **Option 3: Use npx to run npm scripts**
122
+ ```bash
123
+ npx npm run build
124
+ npx npm start
125
+ ```
126
+
127
+ **Option 4: Run TypeScript directly (if you have ts-node)**
128
+ ```bash
129
+ npx ts-node src/index.ts
130
+ ```
131
+
132
+ ## MCP Integration
133
+
134
+ ### Configuration for Popular MCP Hosts
135
+
136
+ #### VS Code with MCP Extension
137
+
138
+ 1. Create a `.vscode` folder in your project root
139
+ 2. Create `mcp.json` with the following configuration:
140
+
141
+ ```json
142
+ {
143
+ "servers": {
144
+ "ebay-api-mcp-server": {
145
+ "type": "stdio",
146
+ "command": "node",
147
+ "args": ["./dist/index.js"],
148
+ "env": {
149
+ "EBAY_API_ENV": "production",
150
+ "EBAY_CLIENT_TOKEN": "YOUR_ACCESS_TOKEN"
151
+ }
152
+ }
153
+ }
154
+ }
155
+ ```
156
+
157
+ #### Claude Desktop
158
+
159
+ Add to your Claude Desktop MCP configuration:
160
+
161
+ ```json
162
+ {
163
+ "mcpServers": {
164
+ "ebay-api": {
165
+ "command": "node",
166
+ "args": ["/path/to/ebay-api-mcp-server/dist/index.js"],
167
+ "env": {
168
+ "EBAY_CLIENT_TOKEN": "YOUR_ACCESS_TOKEN",
169
+ "EBAY_API_ENV": "production"
170
+ }
171
+ }
172
+ }
173
+ }
174
+ ```
175
+
176
+ #### Cursor
177
+
178
+ Configure in your Cursor MCP settings with similar JSON structure as above.
179
+
180
+ ### Example Usage
181
+
182
+ Once configured, you can ask your AI assistant to:
183
+
184
+ - "Find an API for marketplace account deletion notifications"
185
+ - "Search for product listing APIs"
186
+ - "Get documentation for the Trading API"
187
+ - "Invoke the getBuyerRequirements endpoint"
188
+
189
+ ## Troubleshooting
190
+
191
+ ### Common Issues
192
+
193
+ **Authentication Errors**
194
+ - Verify your `EBAY_CLIENT_TOKEN` is valid and not expired
195
+ - Ensure you're using the correct environment (sandbox vs production)
196
+ - Check that your eBay developer account has the necessary permissions
197
+
198
+ **MCP Connection Issues**
199
+ - Verify the path to `dist/index.js` in your MCP configuration
200
+ - Ensure Node.js is in your system PATH
201
+ - Check that the server builds successfully with `npm run build`
202
+
203
+ **API Errors**
204
+ - Review eBay API documentation for endpoint-specific requirements
205
+ - Verify your token has the necessary scopes for the APIs you're trying to access
206
+ - Check rate limiting and usage quotas
207
+
208
+
209
+ ## Support
210
+
211
+ For issues related to:
212
+ - **eBay API**: Consult the [eBay Developer Documentation](https://developer.ebay.com/)
213
+ - **MCP Protocol**: Visit the [Model Context Protocol documentation](https://modelcontextprotocol.io/)
214
+ - **This Server**: Open an issue in this repository
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Constants used throughout the application
3
+ */
4
+ /**
5
+ * Environment options for the eBay API
6
+ */
7
+ export var ApiEnvironment;
8
+ (function (ApiEnvironment) {
9
+ ApiEnvironment["SANDBOX"] = "sandbox";
10
+ ApiEnvironment["PRODUCTION"] = "production";
11
+ })(ApiEnvironment || (ApiEnvironment = {}));
12
+ /**
13
+ * Utility to find ApiEnvironment by string value
14
+ * Returns SANDBOX if no match is found
15
+ */
16
+ export function findApiEnvironmentByValue(value) {
17
+ const lowercaseValue = value?.toLowerCase();
18
+ const matchedEnv = Object.entries(ApiEnvironment)
19
+ .find(([_key, val]) => typeof val === "string" && val.toLowerCase() === lowercaseValue);
20
+ return matchedEnv ? matchedEnv[1] : ApiEnvironment.SANDBOX;
21
+ }
22
+ /**
23
+ * Recall apiDoc url by prompt
24
+ */
25
+ export const RECALL_SPEC_BY_PROMPT_URL = "https://ebaypubapimcp3.vip.qa.ebay.com/developer-portal/api/v1/openapi-specs/search?query=%s";
26
+ /**
27
+ * url for query apiSpec with fields such as specTitle、operationId
28
+ */
29
+ export const RECALL_SPEC_WITH_FIELD_URL = "https://ebaypubapimcp3.vip.qa.ebay.com/developer-portal/api/v1/openapi-specs/%s?operationId=%s";
30
+ /**
31
+ * Required environment variable names for the application
32
+ */
33
+ export const REQUIRED_ENV_VARS = ["EBAY_CLIENT_TOKEN", "EBAY_API_ENV"];
34
+ /**
35
+ * API domain name, differentiated by api environment
36
+ */
37
+ export const DOMAIN_NAME = {
38
+ [ApiEnvironment.SANDBOX]: "api.sandbox.ebay.com",
39
+ [ApiEnvironment.PRODUCTION]: "api.ebay.com",
40
+ };
41
+ /**
42
+ * List of supported calling methods, differentiated by api environment
43
+ */
44
+ export const SUPPORTED_CALLING_METHODS = {
45
+ [ApiEnvironment.SANDBOX]: ["get", "put", "post", "delete", "options", "head", "patch", "trace"],
46
+ [ApiEnvironment.PRODUCTION]: ["get"],
47
+ };
48
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constant/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,CAAN,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,qCAAmB,CAAA;IACnB,2CAAyB,CAAA;AAC3B,CAAC,EAHW,cAAc,KAAd,cAAc,QAGzB;AACD;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAAa;IACrD,MAAM,cAAc,GAAG,KAAK,EAAE,WAAW,EAAE,CAAC;IAC5C,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC;SAC9C,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,cAAc,CAAC,CAAC;IAC1F,OAAO,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAmB,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC;AAC/E,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,8FAA8F,CAAC;AACxI;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,gGAAgG,CAAC;AAE3I;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,mBAAmB,EAAE,cAAc,CAAC,CAAC;AAEvE;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,sBAAsB;IAChD,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,cAAc;CAC5C,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;IAC/F,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC;CACrC,CAAC"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Helper functions for HTTP requests
3
+ */
4
+ import axios from "axios";
5
+ import { DOMAIN_NAME, findApiEnvironmentByValue } from "../constant/constants.js";
6
+ const USER_ENVIRONMENT = findApiEnvironmentByValue(process.env.EBAY_API_ENV || "");
7
+ const USER_TOKEN = process.env.EBAY_CLIENT_TOKEN || "";
8
+ const SCHEMA_REQUEST_BODY = "requestBody";
9
+ /**
10
+ * Format axios error message for consistent error output
11
+ */
12
+ export function formatAxiosError(error) {
13
+ let errorMessage = `Error in invokeAPI tool: ${error instanceof Error ? error.message : String(error)}`;
14
+ if (axios.isAxiosError(error)) {
15
+ if (error?.response?.data) {
16
+ errorMessage = JSON.stringify(error.response.data, null, 2);
17
+ }
18
+ }
19
+ return errorMessage;
20
+ }
21
+ /**
22
+ * Build headers from input headers and fill with default headers
23
+ */
24
+ export function buildHeadersFromInput(inputHeaders) {
25
+ const headers = {};
26
+ if (inputHeaders) {
27
+ for (const [key, value] of Object.entries(inputHeaders)) {
28
+ headers[key] = Array.isArray(value) ? value[0] : value;
29
+ }
30
+ }
31
+ // Add default headers
32
+ fillDefaultHeaderInfo(headers);
33
+ return headers;
34
+ }
35
+ export function fillDefaultHeaderInfo(headers) {
36
+ headers["Host"] = DOMAIN_NAME[USER_ENVIRONMENT];
37
+ headers["User-Agent"] = "EBAY-API-MCP-Tool/1.0";
38
+ headers["Authorization"] = `Bearer ${USER_TOKEN}`;
39
+ headers["Content-Type"] = headers["Content-Type"] || "application/json";
40
+ }
41
+ /**
42
+ * Build final URL by replacing path variables with their values
43
+ */
44
+ export function buildFinalUrl(url, urlVariables) {
45
+ if (urlVariables) {
46
+ for (const [key, value] of Object.entries(urlVariables)) {
47
+ url = url.replace(new RegExp(`%7B${key}%7D`, "g"), encodeURIComponent(String(value)));
48
+ }
49
+ }
50
+ return url;
51
+ }
52
+ /**
53
+ * replace url domain name by environment
54
+ */
55
+ export function replaceDomainNameByEnvironment(url) {
56
+ try {
57
+ const urlObj = new URL(url);
58
+ const currentHostname = urlObj.hostname;
59
+ const expectedDomain = DOMAIN_NAME[USER_ENVIRONMENT];
60
+ if (currentHostname !== expectedDomain) {
61
+ urlObj.hostname = expectedDomain;
62
+ return urlObj.toString();
63
+ }
64
+ return url;
65
+ }
66
+ catch (error) {
67
+ // Fallback to string replacement if URL parsing fails
68
+ const expectedDomain = DOMAIN_NAME[USER_ENVIRONMENT];
69
+ for (const [env, domain] of Object.entries(DOMAIN_NAME)) {
70
+ if (env !== USER_ENVIRONMENT && url.includes(domain)) {
71
+ return url.replace(domain, expectedDomain);
72
+ }
73
+ }
74
+ return url;
75
+ }
76
+ }
77
+ /**
78
+ * Build base URL from OpenAPI servers object
79
+ */
80
+ export function buildBaseUrlFromOpenApi(openapi) {
81
+ const serverObj = openapi.servers?.[0] || { url: "" };
82
+ let baseUrl = serverObj.url;
83
+ if (serverObj.variables) {
84
+ for (const [key, value] of Object.entries(serverObj.variables)) {
85
+ baseUrl = baseUrl.replace(`{${key}}`, value.default);
86
+ }
87
+ }
88
+ return replaceDomainNameByEnvironment(baseUrl);
89
+ }
90
+ /**
91
+ * Resolve path variables in a URL pattern
92
+ */
93
+ export function resolvePath(pathPattern, pathVariables) {
94
+ if (!pathVariables) {
95
+ return pathPattern;
96
+ }
97
+ return pathPattern.replace(/{([^}]+)}/g, (match, key) => {
98
+ const value = pathVariables[key];
99
+ if (value === undefined) {
100
+ throw new Error(`Missing path variable: ${key}`);
101
+ }
102
+ return String(value);
103
+ });
104
+ }
105
+ /**
106
+ * Prepare request data
107
+ */
108
+ export function prepareRequestData(input, operation, path) {
109
+ let resolvedPath = path;
110
+ const headers = {};
111
+ const params = {};
112
+ let data = undefined;
113
+ const pathParams = {};
114
+ let prop = input.properties || {};
115
+ Object.entries(prop).forEach(([key, value]) => {
116
+ if (key === SCHEMA_REQUEST_BODY) {
117
+ data = value;
118
+ }
119
+ else {
120
+ const paramDef = operation.parameters?.find(p => !("$ref" in p) && p.name === key);
121
+ if (paramDef) {
122
+ if (paramDef.in === "header") {
123
+ headers[key] = String(value);
124
+ }
125
+ else if (paramDef.in === "query") {
126
+ params[key] = value;
127
+ }
128
+ else if (paramDef.in === "path") {
129
+ pathParams[key] = String(value);
130
+ }
131
+ }
132
+ }
133
+ });
134
+ fillDefaultHeaderInfo(headers);
135
+ if (Object.keys(pathParams).length > 0) {
136
+ resolvedPath = resolvePath(resolvedPath, pathParams);
137
+ }
138
+ return { resolvedPath, headers, params, data };
139
+ }
140
+ //# sourceMappingURL=http-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-helper.js","sourceRoot":"","sources":["../../src/helper/http-helper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * OpenAPI helper functions, including loading OpenAPI documents,
3
+ * parsing OpenAPI specs, building schemas, and converting to Zod schemas.
4
+ */
5
+ import SwaggerParser from "@apidevtools/swagger-parser";
6
+ import * as fs from "fs";
7
+ import axios from "axios";
8
+ import * as yaml from "js-yaml";
9
+ import util from "util";
10
+ import { z } from "zod";
11
+ const SCHEMA_REQUEST_BODY = "requestBody";
12
+ /**
13
+ * Get OpenAPI docs from user config file, which contains urls or paths of OpenAPI specs.
14
+ */
15
+ export async function getOpenApiDocumentsFromConfigFile() {
16
+ const docs = [];
17
+ const urlFile = process.env.EBAY_API_DOC_URL_FILE;
18
+ let urls = [];
19
+ if (urlFile && fs.existsSync(urlFile)) {
20
+ // url or path each line in the file
21
+ urls = fs.readFileSync(urlFile, "utf-8").split(/\r?\n/)
22
+ .map(line => line.trim())
23
+ .filter(line => line.length > 0 && !line.startsWith("#"));
24
+ }
25
+ console.error("Loading OpenAPI specifications from:", urls);
26
+ // parse opebapi doc from url/path
27
+ for (const specPath of urls) {
28
+ try {
29
+ const doc = await SwaggerParser.dereference(specPath);
30
+ docs.push(doc);
31
+ }
32
+ catch (e) {
33
+ console.error(`getOpenApiDocumentsFromConfigFile#[Failed to load OpenAPI doc from the specPath : ${specPath}]`);
34
+ }
35
+ }
36
+ return docs;
37
+ }
38
+ // Helper: remove ignored keys recursively
39
+ export function readSchema2Map(obj) {
40
+ const SCHEMA_IGNORE_KEYS = ["style", "explode", "exampleSetFlag", "types", "in", "required"];
41
+ if (Array.isArray(obj)) {
42
+ return obj.map(readSchema2Map);
43
+ }
44
+ else if (obj && typeof obj === "object") {
45
+ const out = {};
46
+ for (const [k, v] of Object.entries(obj)) {
47
+ if (!SCHEMA_IGNORE_KEYS.includes(k)) {
48
+ out[k] = readSchema2Map(v);
49
+ }
50
+ }
51
+ return out;
52
+ }
53
+ return obj;
54
+ }
55
+ /**
56
+ * Parse OpenAPI document from string (supports both JSON and YAML)
57
+ */
58
+ export async function parseOpenApiDoc(specTitle, operationId, specUrl) {
59
+ const url = util.format(specUrl, specTitle, operationId);
60
+ const apiSpecRes = await axios.get(url, {
61
+ httpsAgent: new (await import("https")).Agent({
62
+ rejectUnauthorized: false,
63
+ })
64
+ });
65
+ const docString = apiSpecRes.data;
66
+ try {
67
+ // Try parsing as JSON first
68
+ return JSON.parse(docString);
69
+ }
70
+ catch (jsonError) {
71
+ try {
72
+ // If JSON fails, try parsing as YAML
73
+ return yaml.load(docString);
74
+ }
75
+ catch (yamlError) {
76
+ const _jsonMsg = jsonError instanceof Error ? jsonError.message : String(jsonError);
77
+ const _yamlMsg = yamlError instanceof Error ? yamlError.message : String(yamlError);
78
+ console.error("failed to parse OpenAPI document !!!");
79
+ return {};
80
+ }
81
+ }
82
+ }
83
+ /**
84
+ * Build schema for an operation's input parameters
85
+ */
86
+ export function buildOperationSchema(operation) {
87
+ const properties = {};
88
+ // handle request param
89
+ (operation.parameters || []).forEach(param => {
90
+ if ("$ref" in param) {
91
+ return;
92
+ }
93
+ const paramSchema = readSchema2Map(param);
94
+ properties[param.name] = paramSchema;
95
+ });
96
+ // handle request body
97
+ if (operation.requestBody && "content" in operation.requestBody &&
98
+ operation.requestBody.content?.["application/json"]?.schema) {
99
+ const requestBodySchema = readSchema2Map(operation.requestBody.content["application/json"].schema);
100
+ properties[SCHEMA_REQUEST_BODY] = requestBodySchema;
101
+ }
102
+ return { properties };
103
+ }
104
+ /**
105
+ * Build Zod validation schema
106
+ */
107
+ export function buildZodSchema(properties) {
108
+ const zodProperties = {};
109
+ Object.keys(properties).forEach(key => {
110
+ zodProperties[key] = z.any();
111
+ });
112
+ return zodProperties;
113
+ }
114
+ //# sourceMappingURL=openapi-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi-helper.js","sourceRoot":"","sources":["../../src/helper/openapi-helper.ts"],"names":[],"mappings":"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"}