@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.
- package/dist/index.js +37 -27
- 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
|
-
|
|
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
|
-
...(
|
|
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
|
-
|
|
121
|
-
|
|
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
|
|
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: !!
|
|
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
|
|
184
|
-
|
|
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
|
+
"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": [
|
|
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": [
|
|
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"
|