@scorehub/mcp-server 0.2.6 → 0.2.7

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/README.md CHANGED
@@ -116,6 +116,8 @@ The `<endpoint>` is derived from the `SCOREHUB_REMOTE_MCP_URL` host and path (fo
116
116
 
117
117
  To log out or switch accounts, delete the `~/.scorehub/` directory or just the host-specific subdirectory.
118
118
 
119
+ The `authorize` tool reuses cached credentials by default. If the cached access token is still valid, or the refresh token can renew it, `authorize` returns without opening the browser. To force a new browser login, call `authorize` with `force: true`.
120
+
119
121
  ## Available Tools
120
122
 
121
123
  ### Local tools
@@ -124,7 +126,7 @@ These tools run locally on your machine — they do not call the remote endpoint
124
126
 
125
127
  | Tool | Description |
126
128
  |---|---|
127
- | `authorize` | Opens your browser for ScoreHub OAuth login. Forces a fresh authorization flow every time. |
129
+ | `authorize` | Checks ScoreHub OAuth status. Reuses cached credentials by default; pass `force: true` to open the browser for a fresh login. |
128
130
  | `status` | Returns connection status: remote URL, authorization state, and count of available tools. |
129
131
 
130
132
  ### Remote tools
package/dist/auth.js CHANGED
@@ -51,6 +51,9 @@ function clearTokens(host) {
51
51
  (0, node_fs_1.writeFileSync)(file, JSON.stringify({}), "utf-8");
52
52
  }
53
53
  }
54
+ function hasSignedTokenShape(token) {
55
+ return token.split(".").length === 3;
56
+ }
54
57
  // ── Token Exchange ───────────────────────────────────────────
55
58
  function tokenPostRequest(tokenEndpoint, body) {
56
59
  const url = new URL(tokenEndpoint);
@@ -100,7 +103,7 @@ async function refreshAccessToken(tokenEndpoint, refreshToken, clientId) {
100
103
  }
101
104
  async function getValidAccessToken(host, tokenEndpoint, clientId) {
102
105
  const cached = loadTokens(host);
103
- if (cached && cached.access_token && cached.expires_at > Date.now() + 5 * 60 * 1000) {
106
+ if (cached && cached.access_token && hasSignedTokenShape(cached.access_token) && cached.expires_at > Date.now() + 5 * 60 * 1000) {
104
107
  return { access_token: cached.access_token, source: "cache" };
105
108
  }
106
109
  if (cached?.refresh_token) {
package/dist/index.js CHANGED
@@ -108,10 +108,15 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
108
108
  const tools = [
109
109
  {
110
110
  name: "authorize",
111
- description: "通过浏览器 OAuth 登录 ScoreHub。首次连接时自动调用,打开浏览器引导登录。已登录时可直接使用其他工具。",
111
+ description: "检查 ScoreHub OAuth 授权。已有有效授权时直接返回;仅在传入 force=true 时重新打开浏览器登录。",
112
112
  inputSchema: {
113
113
  type: "object",
114
- properties: {},
114
+ properties: {
115
+ force: {
116
+ type: "boolean",
117
+ description: "是否强制清除当前端点的本地 token 并重新登录",
118
+ },
119
+ },
115
120
  required: [],
116
121
  },
117
122
  },
@@ -136,8 +141,18 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
136
141
  const { name, arguments: args = {} } = request.params;
137
142
  switch (name) {
138
143
  case "authorize": {
139
- // Always force fresh OAuth flow when user explicitly authorizes
140
- (0, auth_js_1.clearTokens)(TOKEN_STORE_KEY);
144
+ const force = args.force === true;
145
+ if (!force) {
146
+ const tokenResult = await (0, auth_js_1.getValidAccessToken)(TOKEN_STORE_KEY, TOKEN_ENDPOINT, CLIENT_ID);
147
+ if (tokenResult) {
148
+ return {
149
+ content: [{ type: "text", text: `✅ 已授权(${tokenResult.source === "cache" ? "使用本地缓存" : "已自动刷新"}),可以直接使用 ScoreHub 工具。` }],
150
+ };
151
+ }
152
+ }
153
+ else {
154
+ (0, auth_js_1.clearTokens)(TOKEN_STORE_KEY);
155
+ }
141
156
  // Port 0 lets the OS assign a random available port,
142
157
  // avoiding conflicts when multiple MCP clients run simultaneously
143
158
  let actualPort = 0;
@@ -263,6 +278,18 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
263
278
  }
264
279
  try {
265
280
  const result = await callRemoteTool(name, args, tokenResult.access_token);
281
+ if (result.includes("ScoreHub OAuth 授权已过期或无效")) {
282
+ (0, auth_js_1.clearTokens)(TOKEN_STORE_KEY);
283
+ const authUrl = generateAuthUrl();
284
+ return {
285
+ content: [
286
+ {
287
+ type: "text",
288
+ text: `⚠️ 授权已失效,已清除本地缓存。请调用 "authorize" 工具重新登录 ScoreHub。\n授权地址: ${authUrl}`,
289
+ },
290
+ ],
291
+ };
292
+ }
266
293
  return { content: [{ type: "text", text: result }] };
267
294
  }
268
295
  catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scorehub/mcp-server",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
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": {