@scorehub/mcp-server 0.2.7 → 0.2.8

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 +71 -4
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -43,6 +43,53 @@ const TOKEN_STORE_KEY = endpointTokenKey(SCOREHUB_BASE_URL);
43
43
  const CLIENT_ID = "scorehub-mcp";
44
44
  // Proactively refresh token every 4 hours to prevent expiry during long sessions
45
45
  const TOKEN_KEEPALIVE_INTERVAL = 4 * 60 * 60 * 1000;
46
+ function isRemoteToolErrorType(value) {
47
+ return value === "oauth_invalid"
48
+ || value === "shop_auth_invalid"
49
+ || value === "rate_limited"
50
+ || value === "quota_exhausted"
51
+ || value === "invalid_input"
52
+ || value === "permission_denied"
53
+ || value === "upstream_error";
54
+ }
55
+ function parseRemoteToolEnvelope(text) {
56
+ try {
57
+ const parsed = JSON.parse(text);
58
+ if (parsed.ok === true && Object.prototype.hasOwnProperty.call(parsed, "data")) {
59
+ return { ok: true, data: parsed.data };
60
+ }
61
+ if (parsed.ok === false
62
+ && isRemoteToolErrorType(parsed.error_type)
63
+ && typeof parsed.user_message === "string"
64
+ && typeof parsed.retryable === "boolean") {
65
+ return {
66
+ ok: false,
67
+ error_type: parsed.error_type,
68
+ user_message: parsed.user_message,
69
+ retryable: parsed.retryable,
70
+ ...(Object.prototype.hasOwnProperty.call(parsed, "upstream") ? { upstream: parsed.upstream } : {}),
71
+ };
72
+ }
73
+ return null;
74
+ }
75
+ catch {
76
+ return null;
77
+ }
78
+ }
79
+ function extractRemoteTextContent(content) {
80
+ if (!Array.isArray(content)) {
81
+ return [];
82
+ }
83
+ return content.flatMap((item) => {
84
+ if (item
85
+ && typeof item === "object"
86
+ && item.type === "text"
87
+ && typeof item.text === "string") {
88
+ return [item.text];
89
+ }
90
+ return [];
91
+ });
92
+ }
46
93
  // ── Remote Tool Proxy (MCP Streamable HTTP) ─────────────────
47
94
  async function fetchRemoteTools(token) {
48
95
  try {
@@ -74,7 +121,15 @@ async function callRemoteTool(name, args, token) {
74
121
  try {
75
122
  await client.connect(transport);
76
123
  const result = await client.callTool({ name, arguments: args });
77
- return JSON.stringify(result.content, null, 2);
124
+ const textBlocks = extractRemoteTextContent(result.content);
125
+ const rawText = textBlocks.length > 0
126
+ ? textBlocks.join("\n\n")
127
+ : JSON.stringify(result.content, null, 2);
128
+ const envelope = textBlocks
129
+ .map((text) => parseRemoteToolEnvelope(text))
130
+ .find((candidate) => candidate !== null)
131
+ ?? parseRemoteToolEnvelope(rawText);
132
+ return { rawText, envelope };
78
133
  }
79
134
  finally {
80
135
  await client.close();
@@ -277,8 +332,20 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
277
332
  };
278
333
  }
279
334
  try {
280
- const result = await callRemoteTool(name, args, tokenResult.access_token);
281
- if (result.includes("ScoreHub OAuth 授权已过期或无效")) {
335
+ const remoteResult = await callRemoteTool(name, args, tokenResult.access_token);
336
+ if (remoteResult.envelope?.ok === false && remoteResult.envelope.error_type === "oauth_invalid") {
337
+ (0, auth_js_1.clearTokens)(TOKEN_STORE_KEY);
338
+ const authUrl = generateAuthUrl();
339
+ return {
340
+ content: [
341
+ {
342
+ type: "text",
343
+ text: `⚠️ 授权已失效,已清除本地缓存。请调用 "authorize" 工具重新登录 ScoreHub。\n授权地址: ${authUrl}`,
344
+ },
345
+ ],
346
+ };
347
+ }
348
+ if (remoteResult.rawText.includes("ScoreHub OAuth 授权已过期或无效")) {
282
349
  (0, auth_js_1.clearTokens)(TOKEN_STORE_KEY);
283
350
  const authUrl = generateAuthUrl();
284
351
  return {
@@ -290,7 +357,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
290
357
  ],
291
358
  };
292
359
  }
293
- return { content: [{ type: "text", text: result }] };
360
+ return { content: [{ type: "text", text: remoteResult.rawText }] };
294
361
  }
295
362
  catch (e) {
296
363
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scorehub/mcp-server",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
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": {