ebay-mcp-remote-edition 2.0.12 → 2.0.14
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 +58 -14
- package/build/auth/multi-user-store.js +13 -1
- package/build/server-http.js +4 -0
- package/package.json +1 -1
package/build/auth/kv-store.js
CHANGED
|
@@ -6,25 +6,28 @@ import axios from 'axios';
|
|
|
6
6
|
* All data is lost on process restart.
|
|
7
7
|
*/
|
|
8
8
|
export class InMemoryKVStore {
|
|
9
|
+
backendName = 'InMemoryKVStore';
|
|
9
10
|
store = new Map();
|
|
10
|
-
|
|
11
|
+
get(key) {
|
|
11
12
|
const entry = this.store.get(key);
|
|
12
13
|
if (!entry)
|
|
13
|
-
return null;
|
|
14
|
+
return Promise.resolve(null);
|
|
14
15
|
if (entry.expiresAt !== undefined && Date.now() > entry.expiresAt) {
|
|
15
16
|
this.store.delete(key);
|
|
16
|
-
return null;
|
|
17
|
+
return Promise.resolve(null);
|
|
17
18
|
}
|
|
18
|
-
return entry.value;
|
|
19
|
+
return Promise.resolve(entry.value);
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
+
put(key, value, expirationTtl) {
|
|
21
22
|
this.store.set(key, {
|
|
22
23
|
value,
|
|
23
24
|
expiresAt: expirationTtl !== undefined ? Date.now() + expirationTtl * 1_000 : undefined,
|
|
24
25
|
});
|
|
26
|
+
return Promise.resolve();
|
|
25
27
|
}
|
|
26
|
-
|
|
28
|
+
delete(key) {
|
|
27
29
|
this.store.delete(key);
|
|
30
|
+
return Promise.resolve();
|
|
28
31
|
}
|
|
29
32
|
}
|
|
30
33
|
/**
|
|
@@ -32,6 +35,7 @@ export class InMemoryKVStore {
|
|
|
32
35
|
* Used when EBAY_TOKEN_STORE_BACKEND=cloudflare-kv (the default for hosted deployments).
|
|
33
36
|
*/
|
|
34
37
|
export class CloudflareKVStore {
|
|
38
|
+
backendName = 'CloudflareKVStore';
|
|
35
39
|
client;
|
|
36
40
|
accountId;
|
|
37
41
|
namespaceId;
|
|
@@ -100,10 +104,25 @@ export class CloudflareKVStore {
|
|
|
100
104
|
this.cache.clear();
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
|
-
// ──
|
|
107
|
+
// ── Singleton factory ─────────────────────────────────────────────────────────
|
|
108
|
+
/**
|
|
109
|
+
* Process-level singleton KV store.
|
|
110
|
+
*
|
|
111
|
+
* All callers within the same Node.js process share one backend instance.
|
|
112
|
+
* This is the root cause guard: it makes it impossible for two different
|
|
113
|
+
* MultiUserAuthStore instances to accidentally resolve to different backends
|
|
114
|
+
* (e.g. one reading EBAY_TOKEN_STORE_BACKEND before dotenv runs and one after).
|
|
115
|
+
*
|
|
116
|
+
* The singleton is lazy: it is created on the first call to `createKVStore()`
|
|
117
|
+
* and reused for every subsequent call.
|
|
118
|
+
*
|
|
119
|
+
* For automated tests only, call `resetKVStoreSingleton()` between test cases
|
|
120
|
+
* that need to swap the backend.
|
|
121
|
+
*/
|
|
122
|
+
let _kvStoreSingleton = null;
|
|
104
123
|
/**
|
|
105
|
-
* Returns the
|
|
106
|
-
* environment variable:
|
|
124
|
+
* Returns (or lazily creates) the process-wide KV store singleton based on the
|
|
125
|
+
* EBAY_TOKEN_STORE_BACKEND environment variable:
|
|
107
126
|
*
|
|
108
127
|
* memory → InMemoryKVStore (no external dependencies, data lost on restart)
|
|
109
128
|
* cloudflare-kv → CloudflareKVStore (default; requires CLOUDFLARE_* env vars)
|
|
@@ -112,14 +131,39 @@ export class CloudflareKVStore {
|
|
|
112
131
|
* existing hosted deployments continue to work without any config change.
|
|
113
132
|
*/
|
|
114
133
|
export function createKVStore() {
|
|
115
|
-
|
|
134
|
+
if (_kvStoreSingleton) {
|
|
135
|
+
return _kvStoreSingleton;
|
|
136
|
+
}
|
|
137
|
+
const rawEnv = process.env.EBAY_TOKEN_STORE_BACKEND;
|
|
138
|
+
const backend = (rawEnv ?? 'cloudflare-kv').toLowerCase().trim();
|
|
139
|
+
// Log exactly once, at the point the singleton is first constructed.
|
|
116
140
|
switch (backend) {
|
|
117
141
|
case 'memory':
|
|
118
|
-
case 'in-memory':
|
|
119
|
-
|
|
142
|
+
case 'in-memory': {
|
|
143
|
+
console.log(`[kv-store] EBAY_TOKEN_STORE_BACKEND="${rawEnv ?? ''}" → using InMemoryKVStore (no external KV calls)`);
|
|
144
|
+
_kvStoreSingleton = new InMemoryKVStore();
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
120
147
|
case 'cloudflare-kv':
|
|
121
148
|
case 'cloudflare':
|
|
122
|
-
default:
|
|
123
|
-
|
|
149
|
+
default: {
|
|
150
|
+
console.log(`[kv-store] EBAY_TOKEN_STORE_BACKEND="${rawEnv ?? '(unset)'}" → using CloudflareKVStore (accountId="${process.env.CLOUDFLARE_ACCOUNT_ID ?? '(unset)'}") — set EBAY_TOKEN_STORE_BACKEND=memory to disable`);
|
|
151
|
+
_kvStoreSingleton = new CloudflareKVStore();
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
124
154
|
}
|
|
155
|
+
return _kvStoreSingleton;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* **TEST USE ONLY** – resets (or replaces) the process-wide KV store singleton.
|
|
159
|
+
*
|
|
160
|
+
* Call this in `afterEach`/`beforeEach` when a test needs to control which
|
|
161
|
+
* backend is in use without mutating `process.env.EBAY_TOKEN_STORE_BACKEND`.
|
|
162
|
+
*
|
|
163
|
+
* @param replacement Optional KV store to install as the new singleton.
|
|
164
|
+
* Pass `null` (default) to clear the singleton so that the
|
|
165
|
+
* next `createKVStore()` call rebuilds it from env.
|
|
166
|
+
*/
|
|
167
|
+
export function resetKVStoreSingleton(replacement = null) {
|
|
168
|
+
_kvStoreSingleton = replacement;
|
|
125
169
|
}
|
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
import { randomUUID } from 'crypto';
|
|
2
2
|
import { createKVStore } from '../auth/kv-store.js';
|
|
3
3
|
export class MultiUserAuthStore {
|
|
4
|
-
kv
|
|
4
|
+
kv;
|
|
5
|
+
/**
|
|
6
|
+
* @param kv Optional KV store override. If omitted the process-wide singleton
|
|
7
|
+
* returned by `createKVStore()` is used (the normal production path).
|
|
8
|
+
* Pass an explicit store in unit tests to avoid touching env vars.
|
|
9
|
+
*/
|
|
10
|
+
constructor(kv) {
|
|
11
|
+
this.kv = kv ?? createKVStore();
|
|
12
|
+
}
|
|
13
|
+
/** Returns the backend name of the underlying KV store (e.g. "InMemoryKVStore"). */
|
|
14
|
+
get backendName() {
|
|
15
|
+
return this.kv.backendName;
|
|
16
|
+
}
|
|
5
17
|
/**
|
|
6
18
|
* In-memory map of sessionToken → timestamp of last KV write for touchSession.
|
|
7
19
|
* Prevents a KV PUT on every single authenticated request — we only persist
|
package/build/server-http.js
CHANGED
|
@@ -21,6 +21,10 @@ const CONFIG = {
|
|
|
21
21
|
oauthStartKey: process.env.OAUTH_START_KEY ?? '',
|
|
22
22
|
};
|
|
23
23
|
const authStore = new MultiUserAuthStore();
|
|
24
|
+
// Emit the concrete backend class so logs can never claim "memory" while
|
|
25
|
+
// actually using Cloudflare (or vice-versa). This fires once on startup,
|
|
26
|
+
// after dotenv has already been loaded by the config/environment import.
|
|
27
|
+
console.log(`[auth-store] Active KV backend: ${authStore.backendName}`);
|
|
24
28
|
function getServerBaseUrl() {
|
|
25
29
|
return CONFIG.publicBaseUrl || `http://localhost:${CONFIG.port}`;
|
|
26
30
|
}
|
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.14",
|
|
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",
|