@scorehub/mcp-server 0.1.3 → 0.1.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 +37 -27
  2. package/package.json +10 -3
package/dist/index.js CHANGED
@@ -20,18 +20,11 @@ const AUTHORIZE_URL = `${REMOTE_MCP_URL}/authorize`;
20
20
  // ── Auth State ──────────────────────────────────────────────
21
21
  const auth_js_1 = require("./auth.js");
22
22
  const node_child_process_1 = require("node:child_process");
23
+ const node_os_1 = require("node:os");
24
+ const node_path_1 = require("node:path");
25
+ const node_fs_1 = require("node:fs");
23
26
  const HOST = new URL(REMOTE_MCP_URL).host;
24
- let cachedToken = null;
25
- function getStoredToken() {
26
- if (cachedToken)
27
- return cachedToken;
28
- const t = (0, auth_js_1.loadTokens)(HOST);
29
- if (t?.access_token && t.expires_at > Date.now() + 60_000) {
30
- cachedToken = t.access_token;
31
- return cachedToken;
32
- }
33
- return null;
34
- }
27
+ const CLIENT_ID = "scorehub-mcp";
35
28
  // ── Remote Tool Proxy ───────────────────────────────────────
36
29
  async function fetchRemoteTools() {
37
30
  try {
@@ -46,7 +39,7 @@ async function fetchRemoteTools() {
46
39
  return [];
47
40
  }
48
41
  }
49
- async function callRemoteTool(name, args) {
42
+ async function callRemoteTool(name, args, token) {
50
43
  // Map tool names to remote endpoints
51
44
  const toolEndpoints = {
52
45
  search_creators: "/mcp/tools/search-creators",
@@ -63,7 +56,7 @@ async function callRemoteTool(name, args) {
63
56
  method: "POST",
64
57
  headers: {
65
58
  "Content-Type": "application/json",
66
- ...(cachedToken ? { Authorization: `Bearer ${cachedToken}` } : {}),
59
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
67
60
  },
68
61
  body: JSON.stringify(args),
69
62
  });
@@ -117,12 +110,8 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
117
110
  const { name, arguments: args = {} } = request.params;
118
111
  switch (name) {
119
112
  case "authorize": {
120
- const existing = getStoredToken();
121
- if (existing) {
122
- return {
123
- content: [{ type: "text", text: "✅ 已授权,可直接使用工具。" }],
124
- };
125
- }
113
+ // Always force fresh OAuth flow when user explicitly authorizes
114
+ (0, auth_js_1.clearTokens)(HOST);
126
115
  const authUrl = generateAuthUrl();
127
116
  const os = process.platform;
128
117
  const cmd = os === "darwin" ? "open" : os === "win32" ? "start" : "xdg-open";
@@ -152,7 +141,6 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
152
141
  expires_at: Date.now() + (tokenData.expires_in ?? 3600) * 1000,
153
142
  updated_at: new Date().toISOString(),
154
143
  });
155
- cachedToken = tokenData.access_token;
156
144
  return {
157
145
  content: [{ type: "text", text: "✅ 授权成功!可以开始使用工具了。" }],
158
146
  };
@@ -164,14 +152,14 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
164
152
  }
165
153
  }
166
154
  case "status": {
167
- const token = getStoredToken();
155
+ const tokenResult = await (0, auth_js_1.getValidAccessToken)(HOST, TOKEN_ENDPOINT, CLIENT_ID);
168
156
  return {
169
157
  content: [
170
158
  {
171
159
  type: "text",
172
160
  text: JSON.stringify({
173
161
  remote_url: REMOTE_MCP_URL,
174
- authorized: !!token,
162
+ authorized: !!tokenResult,
175
163
  tools_count: remoteTools.length,
176
164
  }, null, 2),
177
165
  },
@@ -179,10 +167,9 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
179
167
  };
180
168
  }
181
169
  default: {
182
- // Check authorization for remote tools
183
- const token = getStoredToken();
184
- cachedToken = token;
185
- if (!cachedToken) {
170
+ // Check authorization for remote tools — re-validates on every call
171
+ const tokenResult = await (0, auth_js_1.getValidAccessToken)(HOST, TOKEN_ENDPOINT, CLIENT_ID);
172
+ if (!tokenResult) {
186
173
  const authUrl = generateAuthUrl();
187
174
  return {
188
175
  content: [
@@ -194,7 +181,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
194
181
  };
195
182
  }
196
183
  try {
197
- const result = await callRemoteTool(name, args);
184
+ const result = await callRemoteTool(name, args, tokenResult.access_token);
198
185
  return { content: [{ type: "text", text: result }] };
199
186
  }
200
187
  catch (e) {
@@ -207,6 +194,29 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
207
194
  });
208
195
  // ── Start ───────────────────────────────────────────────────
209
196
  async function main() {
197
+ // ── Clean up orphaned previous instance ────────────────────
198
+ const pidFile = (0, node_path_1.join)((0, node_os_1.homedir)(), ".scorehub", HOST, "pid");
199
+ try {
200
+ if ((0, node_fs_1.existsSync)(pidFile)) {
201
+ const oldPid = parseInt((0, node_fs_1.readFileSync)(pidFile, "utf-8").trim(), 10);
202
+ if (oldPid && oldPid !== process.pid) {
203
+ try {
204
+ process.kill(oldPid, 0); // check if process exists (cross-platform)
205
+ process.kill(oldPid); // SIGTERM on POSIX, TerminateProcess on Windows
206
+ }
207
+ catch { /* process already dead */ }
208
+ }
209
+ }
210
+ }
211
+ catch { /* ignore PID file read errors */ }
212
+ // Write current PID
213
+ try {
214
+ const dir = (0, node_path_1.dirname)(pidFile);
215
+ if (!(0, node_fs_1.existsSync)(dir))
216
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
217
+ (0, node_fs_1.writeFileSync)(pidFile, String(process.pid), "utf-8");
218
+ }
219
+ catch { /* ignore PID file write errors */ }
210
220
  try {
211
221
  remoteTools = await fetchRemoteTools();
212
222
  }
package/package.json CHANGED
@@ -1,18 +1,25 @@
1
1
  {
2
2
  "name": "@scorehub/mcp-server",
3
- "version": "0.1.3",
3
+ "version": "0.1.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": {
7
7
  "scorehub-mcp": "./dist/index.js"
8
8
  },
9
- "files": ["dist"],
9
+ "files": [
10
+ "dist"
11
+ ],
10
12
  "scripts": {
11
13
  "build": "tsc && node -e \"const fs=require('fs');const f='dist/index.js';fs.writeFileSync(f,'#!/usr/bin/env node\\n'+fs.readFileSync(f,'utf8'));fs.chmodSync(f,0o755)\"",
12
14
  "dev": "tsx src/index.ts",
13
15
  "start": "node dist/index.js"
14
16
  },
15
- "keywords": ["mcp", "scorehub", "tiktok", "oauth"],
17
+ "keywords": [
18
+ "mcp",
19
+ "scorehub",
20
+ "tiktok",
21
+ "oauth"
22
+ ],
16
23
  "license": "MIT",
17
24
  "dependencies": {
18
25
  "@modelcontextprotocol/sdk": "^1.29.0"