@scorehub/mcp-server 0.1.5 → 0.2.0
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 +267 -0
- package/dist/index.js +27 -29
- package/package.json +6 -2
package/README.md
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# @scorehub/mcp-server
|
|
2
|
+
|
|
3
|
+
> Local MCP proxy for ScoreHub — handles OAuth login, token caching, and tool forwarding to the remote ScoreHub MCP endpoint.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@scorehub/mcp-server)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
[](https://nodejs.org/)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
`@scorehub/mcp-server` is a **local MCP (Model Context Protocol) proxy** that sits between your AI agent (Claude Code, Claude Desktop, WorkBuddy, etc.) and the ScoreHub remote MCP endpoint. It handles:
|
|
14
|
+
|
|
15
|
+
- **OAuth authentication** — opens your browser for one-time ScoreHub login, then caches tokens locally
|
|
16
|
+
- **Token lifecycle** — automatic refresh 5 minutes before expiry, no repeated logins
|
|
17
|
+
- **Tool forwarding** — proxies TikTok Shop creator outreach tools to the remote API over Streamable HTTP
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
┌─────────────┐ stdio ┌──────────────────┐ Streamable HTTP ┌─────────────────┐
|
|
21
|
+
│ AI Agent │ ◄────────────► │ @scorehub/ │ ◄─────────────────► │ ScoreHub │
|
|
22
|
+
│ (Claude) │ │ mcp-server │ │ Remote MCP │
|
|
23
|
+
└─────────────┘ └──────────────────┘ └────────┬────────┘
|
|
24
|
+
│
|
|
25
|
+
TikTok Shop
|
|
26
|
+
Partner API
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
**Prerequisites**: Node.js >= 18
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install -g @scorehub/mcp-server
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This installs the `scorehub-mcp` command globally. You can also skip global install and use `npx` directly in your MCP client configuration (see [Quick Start](#quick-start)).
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
Add this to your MCP client configuration file:
|
|
42
|
+
|
|
43
|
+
### Claude Code / Claude Desktop
|
|
44
|
+
|
|
45
|
+
In `claude_desktop_config.json` or `.claude/mcp.json`:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"scorehub": {
|
|
51
|
+
"command": "npx",
|
|
52
|
+
"args": ["-y", "@scorehub/mcp-server"],
|
|
53
|
+
"env": {
|
|
54
|
+
"SCOREHUB_REMOTE_MCP_URL": "https://mcp.scorehub.cn"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### WorkBuddy
|
|
62
|
+
|
|
63
|
+
In `mcp.json`:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"mcpServers": {
|
|
68
|
+
"scorehub": {
|
|
69
|
+
"command": "npx",
|
|
70
|
+
"args": ["-y", "@scorehub/mcp-server"],
|
|
71
|
+
"env": {
|
|
72
|
+
"SCOREHUB_REMOTE_MCP_URL": "https://mcp.scorehub.cn"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### What happens on first run
|
|
80
|
+
|
|
81
|
+
1. The server starts and connects to the remote MCP endpoint
|
|
82
|
+
2. It fetches the list of available tools
|
|
83
|
+
3. The first time you use a remote tool, you'll be prompted to run the `authorize` tool
|
|
84
|
+
4. Your browser opens to the ScoreHub login page
|
|
85
|
+
5. After authorizing, the browser redirects to `localhost:19836` and the token is saved
|
|
86
|
+
6. Subsequent calls use the cached token — no repeated login needed
|
|
87
|
+
|
|
88
|
+
## Configuration
|
|
89
|
+
|
|
90
|
+
### Environment variables
|
|
91
|
+
|
|
92
|
+
| Variable | Required | Default | Description |
|
|
93
|
+
|---|---|---|---|
|
|
94
|
+
| `SCOREHUB_REMOTE_MCP_URL` | No | `https://mcp.scorehub.cn` | Base URL of the remote ScoreHub MCP endpoint |
|
|
95
|
+
|
|
96
|
+
### Token storage
|
|
97
|
+
|
|
98
|
+
OAuth tokens are stored at:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
~/.scorehub/<host>/oauth.json
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The `<host>` is derived from the `SCOREHUB_REMOTE_MCP_URL` (e.g., `mcp.scorehub.cn`). This means you can run staging and production side-by-side by pointing each configuration at a different URL — tokens are isolated per host.
|
|
105
|
+
|
|
106
|
+
**Token file structure:**
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"access_token": "eyJ...",
|
|
111
|
+
"refresh_token": "eyJ...",
|
|
112
|
+
"expires_at": 1710000000000,
|
|
113
|
+
"updated_at": "2026-07-10T08:00:00.000Z"
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
To log out or switch accounts, delete the `~/.scorehub/` directory or just the host-specific subdirectory.
|
|
118
|
+
|
|
119
|
+
## Available Tools
|
|
120
|
+
|
|
121
|
+
### Local tools
|
|
122
|
+
|
|
123
|
+
These tools run locally on your machine — they do not call the remote endpoint.
|
|
124
|
+
|
|
125
|
+
| Tool | Description |
|
|
126
|
+
|---|---|
|
|
127
|
+
| `authorize` | Opens your browser for ScoreHub OAuth login. Forces a fresh authorization flow every time. |
|
|
128
|
+
| `status` | Returns connection status: remote URL, authorization state, and count of available tools. |
|
|
129
|
+
|
|
130
|
+
### Remote tools
|
|
131
|
+
|
|
132
|
+
These tools are **dynamically loaded** from the remote MCP endpoint at startup and forwarded on every call. The current set includes:
|
|
133
|
+
|
|
134
|
+
| Tool | Description |
|
|
135
|
+
|---|---|
|
|
136
|
+
| `search_creators` | Search TikTok Shop creators by keywords, GMV range, sales volume, category, and other filters |
|
|
137
|
+
| `creator_performance` | Analyze creator performance — 30-day GMV, follower demographics, content engagement data |
|
|
138
|
+
| `get_categories` | Fetch available TikTok Shop product categories |
|
|
139
|
+
| `create_conversation` | Create a collaboration conversation thread with a specific creator |
|
|
140
|
+
| `send_message` | Send a collaboration message (text, product card, collaboration invite, sample request, or image) |
|
|
141
|
+
|
|
142
|
+
> **Note**: The remote tool list is fetched at server startup and refreshed on each `ListTools` request. If new tools are added to the remote endpoint, they become available without updating the local package.
|
|
143
|
+
|
|
144
|
+
## Authentication Flow
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
Local mcp-server ScoreHub Remote
|
|
148
|
+
│ │
|
|
149
|
+
├─ tools/call: authorize ──────────┤
|
|
150
|
+
│ (clears any existing token) │
|
|
151
|
+
│ │
|
|
152
|
+
├─ generates random state │
|
|
153
|
+
├─ opens browser → /authorize ────▶│
|
|
154
|
+
│ user logs in + grants access
|
|
155
|
+
│ ◀── redirect to localhost:19836 │
|
|
156
|
+
│ with authorization_code │
|
|
157
|
+
│ │
|
|
158
|
+
├─ POST /token ───────────────────▶│
|
|
159
|
+
│◀── access_token + refresh_token │
|
|
160
|
+
│ │
|
|
161
|
+
├─ saves to ~/.scorehub/<host>/oauth.json
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Token lifecycle
|
|
165
|
+
|
|
166
|
+
| Stage | Behavior |
|
|
167
|
+
|---|---|
|
|
168
|
+
| **First use** | Browser OAuth → callback → write token to local file |
|
|
169
|
+
| **Subsequent calls** | Read cached file → check expiry with 5-minute buffer |
|
|
170
|
+
| **Near expiry** | Auto-refresh with `refresh_token` → write new token back to file |
|
|
171
|
+
| **Refresh fails** | Returns an error message with the authorization URL — call `authorize` again |
|
|
172
|
+
| **Manual logout** | Delete `~/.scorehub/<host>/oauth.json` or the entire `~/.scorehub/` directory |
|
|
173
|
+
|
|
174
|
+
### Headless environments
|
|
175
|
+
|
|
176
|
+
If you're running on a server or in a headless environment where a browser cannot open automatically, the authorization URL will be printed to stderr. Copy it and open it manually in any browser. After login, the callback goes to `http://127.0.0.1:19836/callback` — make sure port 19836 is accessible on the machine running mcp-server.
|
|
177
|
+
|
|
178
|
+
## Architecture
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
┌──────────────────────────────────────────────────────────────────┐
|
|
182
|
+
│ YOUR MACHINE │
|
|
183
|
+
│ │
|
|
184
|
+
│ ┌──────────────┐ stdio ┌─────────────────────┐ │
|
|
185
|
+
│ │ Claude Code │ ◄────────► │ @scorehub/mcp-server │ │
|
|
186
|
+
│ │ WorkBuddy │ │ │ │
|
|
187
|
+
│ │ Codex │ │ • OAuth login │ │
|
|
188
|
+
│ │ (any MCP │ │ • Token cache │ │
|
|
189
|
+
│ │ client) │ │ • Tool forwarding │ │
|
|
190
|
+
│ └──────────────┘ └─────────┬───────────┘ │
|
|
191
|
+
│ │ │
|
|
192
|
+
│ ~/.scorehub/<host>/oauth.json │
|
|
193
|
+
└────────────────────────────────────────┼──────────────────────────┘
|
|
194
|
+
│ Streamable HTTP
|
|
195
|
+
▼
|
|
196
|
+
┌─────────────────────┐
|
|
197
|
+
│ ScoreHub Remote MCP │
|
|
198
|
+
│ (mcp.scorehub.cn) │
|
|
199
|
+
└─────────┬───────────┘
|
|
200
|
+
│
|
|
201
|
+
▼
|
|
202
|
+
┌─────────────────────┐
|
|
203
|
+
│ TikTok Shop │
|
|
204
|
+
│ Partner API │
|
|
205
|
+
└─────────────────────┘
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Why a local proxy?
|
|
209
|
+
|
|
210
|
+
- **Browser-based OAuth** — The OAuth flow requires opening a browser on your machine. A local server can launch your browser, whereas a remote server cannot.
|
|
211
|
+
- **Token stays local** — Your access token never leaves your machine. The remote endpoint only sees it in the `Authorization` header of forwarded requests.
|
|
212
|
+
- **Cross-platform** — Automatically uses `open` (macOS), `start` (Windows), or `xdg-open` (Linux) to launch the browser.
|
|
213
|
+
- **Minimal dependencies** — Only depends on `@modelcontextprotocol/sdk` (~1 MB). No database, no framework, no configuration files.
|
|
214
|
+
|
|
215
|
+
## FAQ
|
|
216
|
+
|
|
217
|
+
### Why do I need this package?
|
|
218
|
+
|
|
219
|
+
If you're using `@scorehub/creator-outreach` (the Tiky agent for TikTok creator outreach), this package is a **required prerequisite**. It provides the MCP tools the agent needs to search creators, analyze performance, and send messages.
|
|
220
|
+
|
|
221
|
+
### Can I use this without @scorehub/creator-outreach?
|
|
222
|
+
|
|
223
|
+
Yes, absolutely. `@scorehub/mcp-server` is a standalone MCP server. Any MCP-compatible client can use its tools directly.
|
|
224
|
+
|
|
225
|
+
### How do I log out?
|
|
226
|
+
|
|
227
|
+
Delete the token file:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
rm ~/.scorehub/mcp.scorehub.cn/oauth.json
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Or delete the entire directory to clear all hosts:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
rm -rf ~/.scorehub/
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### How do I switch between staging and production?
|
|
240
|
+
|
|
241
|
+
Set different `SCOREHUB_REMOTE_MCP_URL` values in separate MCP client configurations. Tokens are isolated per host, so staging and production credentials won't interfere with each other.
|
|
242
|
+
|
|
243
|
+
### What happens if the remote MCP is unreachable?
|
|
244
|
+
|
|
245
|
+
- Local tools (`authorize`, `status`) continue to work
|
|
246
|
+
- Remote tools return an error: `"Warning: Could not fetch remote tools"`
|
|
247
|
+
- The server retries fetching the tool list on each `ListTools` request
|
|
248
|
+
- Once the remote endpoint is reachable again, remote tools become available without restarting
|
|
249
|
+
|
|
250
|
+
### How do I upgrade?
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
npm update -g @scorehub/mcp-server
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Or, if you're using `npx -y`, it will always fetch the latest version automatically.
|
|
257
|
+
|
|
258
|
+
## Related Packages
|
|
259
|
+
|
|
260
|
+
| Package | Description |
|
|
261
|
+
|---|---|
|
|
262
|
+
| [`@scorehub/creator-outreach`](https://www.npmjs.com/package/@scorehub/creator-outreach) | Tiky agent — AI-powered TikTok Shop creator outreach (search, analyze, message) |
|
|
263
|
+
| `scorehub-mcp-remote` | Remote MCP endpoint (private — deployed on ScoreHub servers) |
|
|
264
|
+
|
|
265
|
+
## License
|
|
266
|
+
|
|
267
|
+
[MIT](./LICENSE)
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
14
14
|
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
15
15
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
16
16
|
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
17
|
+
const index_js_2 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
18
|
+
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
17
19
|
const REMOTE_MCP_URL = process.env.SCOREHUB_REMOTE_MCP_URL || "https://mcp.scorehub.cn";
|
|
18
20
|
const TOKEN_ENDPOINT = `${REMOTE_MCP_URL}/token`;
|
|
19
21
|
const AUTHORIZE_URL = `${REMOTE_MCP_URL}/authorize`;
|
|
@@ -25,43 +27,39 @@ const node_path_1 = require("node:path");
|
|
|
25
27
|
const node_fs_1 = require("node:fs");
|
|
26
28
|
const HOST = new URL(REMOTE_MCP_URL).host;
|
|
27
29
|
const CLIENT_ID = "scorehub-mcp";
|
|
28
|
-
// ── Remote Tool Proxy
|
|
29
|
-
async function fetchRemoteTools() {
|
|
30
|
+
// ── Remote Tool Proxy (MCP Streamable HTTP) ─────────────────
|
|
31
|
+
async function fetchRemoteTools(token) {
|
|
30
32
|
try {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
33
|
+
const transport = new streamableHttp_js_1.StreamableHTTPClientTransport(new URL(REMOTE_MCP_URL), {
|
|
34
|
+
requestInit: token ? { headers: { Authorization: `Bearer ${token}` } } : undefined,
|
|
35
|
+
});
|
|
36
|
+
const client = new index_js_2.Client({ name: "scorehub-mcp", version: "0.2.0" }, { capabilities: {} });
|
|
37
|
+
try {
|
|
38
|
+
await client.connect(transport);
|
|
39
|
+
const result = await client.listTools();
|
|
40
|
+
return result.tools;
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
await client.close();
|
|
44
|
+
}
|
|
36
45
|
}
|
|
37
46
|
catch {
|
|
38
|
-
// Return offline message when remote is not available
|
|
39
47
|
return [];
|
|
40
48
|
}
|
|
41
49
|
}
|
|
42
50
|
async function callRemoteTool(name, args, token) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
search_creators: "/mcp/tools/search-creators",
|
|
46
|
-
creator_performance: "/mcp/tools/creator-performance",
|
|
47
|
-
create_conversation: "/mcp/tools/create-conversation",
|
|
48
|
-
send_message: "/mcp/tools/send-message",
|
|
49
|
-
get_categories: "/mcp/tools/get-categories",
|
|
50
|
-
};
|
|
51
|
-
const endpoint = toolEndpoints[name];
|
|
52
|
-
if (!endpoint) {
|
|
53
|
-
return JSON.stringify({ error: `Unknown tool: ${name}` });
|
|
54
|
-
}
|
|
55
|
-
const resp = await fetch(`${REMOTE_MCP_URL}${endpoint}`, {
|
|
56
|
-
method: "POST",
|
|
57
|
-
headers: {
|
|
58
|
-
"Content-Type": "application/json",
|
|
59
|
-
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
60
|
-
},
|
|
61
|
-
body: JSON.stringify(args),
|
|
51
|
+
const transport = new streamableHttp_js_1.StreamableHTTPClientTransport(new URL(REMOTE_MCP_URL), {
|
|
52
|
+
requestInit: { headers: { Authorization: `Bearer ${token}` } },
|
|
62
53
|
});
|
|
63
|
-
const
|
|
64
|
-
|
|
54
|
+
const client = new index_js_2.Client({ name: "scorehub-mcp", version: "0.2.0" }, { capabilities: {} });
|
|
55
|
+
try {
|
|
56
|
+
await client.connect(transport);
|
|
57
|
+
const result = await client.callTool({ name, arguments: args });
|
|
58
|
+
return JSON.stringify(result.content, null, 2);
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
await client.close();
|
|
62
|
+
}
|
|
65
63
|
}
|
|
66
64
|
// ── OAuth authorize helper ──────────────────────────────────
|
|
67
65
|
function generateAuthUrl() {
|
package/package.json
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scorehub/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
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
9
|
"files": [
|
|
10
|
-
"dist"
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md"
|
|
11
12
|
],
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
12
16
|
"scripts": {
|
|
13
17
|
"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)\"",
|
|
14
18
|
"dev": "tsx src/index.ts",
|