ebay-mcp-remote-edition 2.0.14 → 2.0.15
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/build/auth/kv-store.js +3 -1
- package/build/auth/multi-user-store.js +31 -0
- package/build/server-http.js +43 -3
- package/package.json +1 -1
package/build/auth/kv-store.js
CHANGED
|
@@ -88,7 +88,9 @@ export class CloudflareKVStore {
|
|
|
88
88
|
await this.client.put(`/values/${encodeURIComponent(key)}`, JSON.stringify(value), { params });
|
|
89
89
|
// Keep the in-memory cache consistent with what we wrote.
|
|
90
90
|
// If the KV entry has its own TTL, honour it for the cache as well.
|
|
91
|
-
const cacheTtl = expirationTtl
|
|
91
|
+
const cacheTtl = expirationTtl
|
|
92
|
+
? Math.min(expirationTtl * 1_000, this.cacheTtlMs)
|
|
93
|
+
: this.cacheTtlMs;
|
|
92
94
|
this.cache.set(key, { value, expiresAt: Date.now() + cacheTtl });
|
|
93
95
|
}
|
|
94
96
|
async delete(key) {
|
|
@@ -118,6 +118,37 @@ export class MultiUserAuthStore {
|
|
|
118
118
|
await this.kv.put(`client:${clientId}`, record);
|
|
119
119
|
return record;
|
|
120
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Upserts a client record using a **caller-supplied** `clientId`.
|
|
123
|
+
*
|
|
124
|
+
* Used by the `/authorize` endpoint to auto-register trusted desktop MCP
|
|
125
|
+
* clients (VS Code, Cursor, Windsurf, localhost loopback) that arrive at
|
|
126
|
+
* `/authorize` without a prior `/register` call (e.g. because the in-memory
|
|
127
|
+
* registration was lost between requests, or the client drives `/authorize`
|
|
128
|
+
* directly).
|
|
129
|
+
*
|
|
130
|
+
* An existing record for `clientId` is overwritten only if the supplied
|
|
131
|
+
* `redirectUri` is not already listed (additive merge otherwise).
|
|
132
|
+
*/
|
|
133
|
+
async registerClientWithId(clientId, redirectUris, clientName) {
|
|
134
|
+
const existing = await this.kv.get(`client:${clientId}`);
|
|
135
|
+
const now = new Date().toISOString();
|
|
136
|
+
if (existing) {
|
|
137
|
+
// Merge any new redirect URIs into the existing record
|
|
138
|
+
const merged = Array.from(new Set([...existing.redirectUris, ...redirectUris]));
|
|
139
|
+
const updated = { ...existing, redirectUris: merged };
|
|
140
|
+
await this.kv.put(`client:${clientId}`, updated);
|
|
141
|
+
return updated;
|
|
142
|
+
}
|
|
143
|
+
const record = {
|
|
144
|
+
clientId,
|
|
145
|
+
redirectUris,
|
|
146
|
+
clientName,
|
|
147
|
+
createdAt: now,
|
|
148
|
+
};
|
|
149
|
+
await this.kv.put(`client:${clientId}`, record);
|
|
150
|
+
return record;
|
|
151
|
+
}
|
|
121
152
|
async getClient(clientId) {
|
|
122
153
|
return await this.kv.get(`client:${clientId}`);
|
|
123
154
|
}
|
package/build/server-http.js
CHANGED
|
@@ -61,6 +61,36 @@ function requireOauthStartKey(req, res, next) {
|
|
|
61
61
|
}
|
|
62
62
|
next();
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Returns true when a redirect URI belongs to a well-known desktop / IDE
|
|
66
|
+
* MCP client (VS Code, Cursor, Windsurf) or a localhost loopback.
|
|
67
|
+
*
|
|
68
|
+
* These clients drive the authorize flow directly and cannot always guarantee
|
|
69
|
+
* that their /register request was persisted before /authorize is called.
|
|
70
|
+
* We allow them to self-register on the fly so the flow doesn't hard-fail on
|
|
71
|
+
* a missing client_id when the user's eBay app credentials are already in env.
|
|
72
|
+
*/
|
|
73
|
+
function isTrustedDesktopRedirectUri(redirectUri) {
|
|
74
|
+
try {
|
|
75
|
+
const u = new URL(redirectUri);
|
|
76
|
+
// Desktop IDE callback schemes
|
|
77
|
+
if (u.protocol === 'vscode:' ||
|
|
78
|
+
u.protocol === 'cursor:' ||
|
|
79
|
+
u.protocol === 'windsurf:' ||
|
|
80
|
+
u.protocol === 'claude:') {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
// Localhost loopback (any port)
|
|
84
|
+
if ((u.protocol === 'http:' || u.protocol === 'https:') &&
|
|
85
|
+
(u.hostname === 'localhost' || u.hostname === '127.0.0.1' || u.hostname === '::1')) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// Malformed URI – treat as untrusted
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
64
94
|
async function createUserScopedApi(userId, environment) {
|
|
65
95
|
const api = new EbaySellerApi(getEbayConfig(environment), { userId, environment });
|
|
66
96
|
await api.initialize();
|
|
@@ -161,10 +191,20 @@ function createApp() {
|
|
|
161
191
|
.json({ error: 'invalid_request', error_description: 'client_id is required' });
|
|
162
192
|
return;
|
|
163
193
|
}
|
|
164
|
-
|
|
194
|
+
// Look up the MCP client. If unknown, auto-register it for trusted desktop
|
|
195
|
+
// redirect URIs (VS Code, Cursor, Windsurf, localhost) so that the flow
|
|
196
|
+
// continues even when /register state was not persisted (e.g. memory backend)
|
|
197
|
+
// or when the IDE drives /authorize directly without a prior /register call.
|
|
198
|
+
let client = await authStore.getClient(clientId);
|
|
165
199
|
if (!client) {
|
|
166
|
-
|
|
167
|
-
|
|
200
|
+
if (redirectUri && isTrustedDesktopRedirectUri(redirectUri)) {
|
|
201
|
+
serverLogger.info('[authorize] Auto-registering trusted desktop MCP client (client_id not in store)', { clientId, redirectUri });
|
|
202
|
+
client = await authStore.registerClientWithId(clientId, [redirectUri]);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
res.status(400).json({ error: 'invalid_client', error_description: 'Unknown client_id' });
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
168
208
|
}
|
|
169
209
|
if (!redirectUri || !client.redirectUris.includes(redirectUri)) {
|
|
170
210
|
res.status(400).json({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ebay-mcp-remote-edition",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.15",
|
|
4
4
|
"description": "Remote + Local MCP server for eBay APIs - provides access to eBay developer functionality through MCP (Model Context Protocol)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "build/index.js",
|