@ppcassist/amazon-ads-mcp 1.0.0 → 1.0.1
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/index.js +25 -3
- package/lib/auth.js +5 -1
- package/lib/proxy.js +15 -3
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -76,13 +76,35 @@ async function handleRequest(proxy, request) {
|
|
|
76
76
|
const result = await proxy.forward(request);
|
|
77
77
|
|
|
78
78
|
if (result.type === "stream") {
|
|
79
|
-
// SSE stream:
|
|
79
|
+
// SSE stream: buffer chunks, extract JSON from "data: ..." lines,
|
|
80
|
+
// and write as newline-delimited JSON-RPC for Claude Desktop
|
|
81
|
+
let sseBuf = "";
|
|
82
|
+
result.stream.setEncoding("utf8");
|
|
83
|
+
|
|
80
84
|
result.stream.on("data", (chunk) => {
|
|
81
|
-
|
|
85
|
+
sseBuf += chunk;
|
|
86
|
+
let lineEnd;
|
|
87
|
+
while ((lineEnd = sseBuf.indexOf("\n")) !== -1) {
|
|
88
|
+
const line = sseBuf.slice(0, lineEnd).trim();
|
|
89
|
+
sseBuf = sseBuf.slice(lineEnd + 1);
|
|
90
|
+
if (line.startsWith("data: ")) {
|
|
91
|
+
const json = line.slice(6);
|
|
92
|
+
if (json) {
|
|
93
|
+
process.stdout.write(json + "\n");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
82
97
|
});
|
|
83
98
|
|
|
84
99
|
result.stream.on("end", () => {
|
|
85
|
-
//
|
|
100
|
+
// Flush any remaining data in buffer
|
|
101
|
+
const remaining = sseBuf.trim();
|
|
102
|
+
if (remaining.startsWith("data: ")) {
|
|
103
|
+
const json = remaining.slice(6);
|
|
104
|
+
if (json) {
|
|
105
|
+
process.stdout.write(json + "\n");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
86
108
|
});
|
|
87
109
|
|
|
88
110
|
result.stream.on("error", (err) => {
|
package/lib/auth.js
CHANGED
|
@@ -14,7 +14,11 @@ class TokenManager {
|
|
|
14
14
|
|
|
15
15
|
async init() {
|
|
16
16
|
await this.refresh();
|
|
17
|
-
this.timer = setInterval(() =>
|
|
17
|
+
this.timer = setInterval(() => {
|
|
18
|
+
this.refresh().catch((err) => {
|
|
19
|
+
process.stderr.write(`[auth] Token refresh failed: ${err.message}\n`);
|
|
20
|
+
});
|
|
21
|
+
}, REFRESH_INTERVAL_MS);
|
|
18
22
|
this.timer.unref(); // don't keep process alive just for refresh
|
|
19
23
|
}
|
|
20
24
|
|
package/lib/proxy.js
CHANGED
|
@@ -19,7 +19,20 @@ class McpProxy {
|
|
|
19
19
|
this.endpoint = new URL(endpoint);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
async forward(jsonRpcRequest) {
|
|
22
|
+
async forward(jsonRpcRequest, _isRetry) {
|
|
23
|
+
const result = await this._doRequest(jsonRpcRequest);
|
|
24
|
+
|
|
25
|
+
// Retry once on 401 (token expired between refreshes)
|
|
26
|
+
if (!_isRetry && result.statusCode === 401) {
|
|
27
|
+
process.stderr.write("[proxy] Got 401, refreshing token and retrying\n");
|
|
28
|
+
await this.tokenManager.refresh();
|
|
29
|
+
return this.forward(jsonRpcRequest, true);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
_doRequest(jsonRpcRequest) {
|
|
23
36
|
const body = JSON.stringify(jsonRpcRequest);
|
|
24
37
|
const token = this.tokenManager.getToken();
|
|
25
38
|
|
|
@@ -51,9 +64,8 @@ class McpProxy {
|
|
|
51
64
|
res.on("end", () => {
|
|
52
65
|
const raw = Buffer.concat(chunks).toString();
|
|
53
66
|
try {
|
|
54
|
-
resolve({ type: "json", data: JSON.parse(raw) });
|
|
67
|
+
resolve({ type: "json", data: JSON.parse(raw), statusCode: res.statusCode });
|
|
55
68
|
} catch {
|
|
56
|
-
// Return raw text if not valid JSON (error pages, etc.)
|
|
57
69
|
resolve({ type: "raw", data: raw, statusCode: res.statusCode });
|
|
58
70
|
}
|
|
59
71
|
});
|
package/package.json
CHANGED