@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.
Files changed (2) hide show
  1. package/dist/index.js +30 -2
  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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scorehub/mcp-server",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "ScoreHub local MCP proxy — OAuth login, token caching, and tool forwarding to remote MCP endpoint",
5
5
  "main": "dist/index.js",
6
6
  "bin": {