@scorehub/mcp-server 0.2.3 → 0.2.5
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/dist/index.js +30 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28,6 +28,8 @@ const node_http_1 = require("node:http");
|
|
|
28
28
|
const node_child_process_1 = require("node:child_process");
|
|
29
29
|
const HOST = new URL(REMOTE_MCP_URL).host;
|
|
30
30
|
const CLIENT_ID = "scorehub-mcp";
|
|
31
|
+
// Proactively refresh token every 4 hours to prevent expiry during long sessions
|
|
32
|
+
const TOKEN_KEEPALIVE_INTERVAL = 4 * 60 * 60 * 1000;
|
|
31
33
|
// ── Remote Tool Proxy (MCP Streamable HTTP) ─────────────────
|
|
32
34
|
async function fetchRemoteTools(token) {
|
|
33
35
|
try {
|
|
@@ -129,10 +131,16 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
129
131
|
return new Promise((resolve) => {
|
|
130
132
|
let timeoutId;
|
|
131
133
|
const callbackServer = (0, node_http_1.createServer)((req, res) => {
|
|
132
|
-
if (timeoutId)
|
|
133
|
-
clearTimeout(timeoutId);
|
|
134
134
|
const requestUrl = req.url ?? "/";
|
|
135
135
|
const url = new URL(requestUrl, `http://127.0.0.1:${actualPort}`);
|
|
136
|
+
// 只处理 /callback 路径的请求,忽略浏览器探测请求(favicon、安全检查等)
|
|
137
|
+
if (url.pathname !== "/callback") {
|
|
138
|
+
res.writeHead(204);
|
|
139
|
+
res.end();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (timeoutId)
|
|
143
|
+
clearTimeout(timeoutId);
|
|
136
144
|
const code = url.searchParams.get("code");
|
|
137
145
|
if (code) {
|
|
138
146
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -171,6 +179,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
171
179
|
}));
|
|
172
180
|
}
|
|
173
181
|
else {
|
|
182
|
+
// 到达 /callback 但没有 code —— 真正的错误
|
|
174
183
|
res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
|
|
175
184
|
res.end("<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>Authorization Failed</title></head>" +
|
|
176
185
|
"<body style=\"font-family:sans-serif;text-align:center;padding-top:80px;\">" +
|
|
@@ -251,6 +260,24 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
251
260
|
}
|
|
252
261
|
}
|
|
253
262
|
});
|
|
263
|
+
// ── Token Keep-Alive ────────────────────────────────────────
|
|
264
|
+
// Proactively refresh the access token on a fixed interval so long-running
|
|
265
|
+
// sessions never hit an expiry mid-call. Uses timer.unref() so the keep-alive
|
|
266
|
+
// loop does not prevent the process from exiting normally.
|
|
267
|
+
function startTokenKeepAlive() {
|
|
268
|
+
const timer = setInterval(async () => {
|
|
269
|
+
try {
|
|
270
|
+
const result = await (0, auth_js_1.getValidAccessToken)(HOST, TOKEN_ENDPOINT, CLIENT_ID);
|
|
271
|
+
if (result?.source === "refresh") {
|
|
272
|
+
console.error("[keep-alive] access token refreshed proactively");
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
// Non-fatal: will retry on next interval
|
|
277
|
+
}
|
|
278
|
+
}, TOKEN_KEEPALIVE_INTERVAL);
|
|
279
|
+
timer.unref(); // Don't block process exit when no other work remains
|
|
280
|
+
}
|
|
254
281
|
// ── Start ───────────────────────────────────────────────────
|
|
255
282
|
async function main() {
|
|
256
283
|
// Set process title for easy identification in ps/task manager
|
|
@@ -276,6 +303,7 @@ async function main() {
|
|
|
276
303
|
const transport = new stdio_js_1.StdioServerTransport();
|
|
277
304
|
await server.connect(transport);
|
|
278
305
|
console.error(`ScoreHub MCP Server started (remote: ${REMOTE_MCP_URL})`);
|
|
306
|
+
startTokenKeepAlive();
|
|
279
307
|
}
|
|
280
308
|
main().catch((err) => {
|
|
281
309
|
console.error("Fatal:", err);
|