mcp-researchpowerpack-http 3.10.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 +124 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +227 -0
- package/dist/index.js.map +7 -0
- package/dist/mcp-use.json +7 -0
- package/dist/src/clients/github.d.ts +83 -0
- package/dist/src/clients/github.d.ts.map +1 -0
- package/dist/src/clients/github.js +370 -0
- package/dist/src/clients/github.js.map +7 -0
- package/dist/src/clients/reddit.d.ts +60 -0
- package/dist/src/clients/reddit.d.ts.map +1 -0
- package/dist/src/clients/reddit.js +287 -0
- package/dist/src/clients/reddit.js.map +7 -0
- package/dist/src/clients/research.d.ts +67 -0
- package/dist/src/clients/research.d.ts.map +1 -0
- package/dist/src/clients/research.js +282 -0
- package/dist/src/clients/research.js.map +7 -0
- package/dist/src/clients/scraper.d.ts +72 -0
- package/dist/src/clients/scraper.d.ts.map +1 -0
- package/dist/src/clients/scraper.js +327 -0
- package/dist/src/clients/scraper.js.map +7 -0
- package/dist/src/clients/search.d.ts +57 -0
- package/dist/src/clients/search.d.ts.map +1 -0
- package/dist/src/clients/search.js +218 -0
- package/dist/src/clients/search.js.map +7 -0
- package/dist/src/config/index.d.ts +93 -0
- package/dist/src/config/index.d.ts.map +1 -0
- package/dist/src/config/index.js +218 -0
- package/dist/src/config/index.js.map +7 -0
- package/dist/src/schemas/deep-research.d.ts +40 -0
- package/dist/src/schemas/deep-research.d.ts.map +1 -0
- package/dist/src/schemas/deep-research.js +216 -0
- package/dist/src/schemas/deep-research.js.map +7 -0
- package/dist/src/schemas/github-score.d.ts +50 -0
- package/dist/src/schemas/github-score.d.ts.map +1 -0
- package/dist/src/schemas/github-score.js +58 -0
- package/dist/src/schemas/github-score.js.map +7 -0
- package/dist/src/schemas/scrape-links.d.ts +23 -0
- package/dist/src/schemas/scrape-links.d.ts.map +1 -0
- package/dist/src/schemas/scrape-links.js +32 -0
- package/dist/src/schemas/scrape-links.js.map +7 -0
- package/dist/src/schemas/web-search.d.ts +18 -0
- package/dist/src/schemas/web-search.d.ts.map +1 -0
- package/dist/src/schemas/web-search.js +28 -0
- package/dist/src/schemas/web-search.js.map +7 -0
- package/dist/src/scoring/github-quality.d.ts +142 -0
- package/dist/src/scoring/github-quality.d.ts.map +1 -0
- package/dist/src/scoring/github-quality.js +202 -0
- package/dist/src/scoring/github-quality.js.map +7 -0
- package/dist/src/services/file-attachment.d.ts +30 -0
- package/dist/src/services/file-attachment.d.ts.map +1 -0
- package/dist/src/services/file-attachment.js +205 -0
- package/dist/src/services/file-attachment.js.map +7 -0
- package/dist/src/services/llm-processor.d.ts +29 -0
- package/dist/src/services/llm-processor.d.ts.map +1 -0
- package/dist/src/services/llm-processor.js +206 -0
- package/dist/src/services/llm-processor.js.map +7 -0
- package/dist/src/services/markdown-cleaner.d.ts +8 -0
- package/dist/src/services/markdown-cleaner.d.ts.map +1 -0
- package/dist/src/services/markdown-cleaner.js +63 -0
- package/dist/src/services/markdown-cleaner.js.map +7 -0
- package/dist/src/tools/github-score.d.ts +12 -0
- package/dist/src/tools/github-score.d.ts.map +1 -0
- package/dist/src/tools/github-score.js +306 -0
- package/dist/src/tools/github-score.js.map +7 -0
- package/dist/src/tools/mcp-helpers.d.ts +27 -0
- package/dist/src/tools/mcp-helpers.d.ts.map +1 -0
- package/dist/src/tools/mcp-helpers.js +47 -0
- package/dist/src/tools/mcp-helpers.js.map +7 -0
- package/dist/src/tools/reddit.d.ts +54 -0
- package/dist/src/tools/reddit.d.ts.map +1 -0
- package/dist/src/tools/reddit.js +498 -0
- package/dist/src/tools/reddit.js.map +7 -0
- package/dist/src/tools/registry.d.ts +3 -0
- package/dist/src/tools/registry.d.ts.map +1 -0
- package/dist/src/tools/registry.js +17 -0
- package/dist/src/tools/registry.js.map +7 -0
- package/dist/src/tools/research.d.ts +14 -0
- package/dist/src/tools/research.d.ts.map +1 -0
- package/dist/src/tools/research.js +250 -0
- package/dist/src/tools/research.js.map +7 -0
- package/dist/src/tools/scrape.d.ts +14 -0
- package/dist/src/tools/scrape.d.ts.map +1 -0
- package/dist/src/tools/scrape.js +290 -0
- package/dist/src/tools/scrape.js.map +7 -0
- package/dist/src/tools/search.d.ts +10 -0
- package/dist/src/tools/search.d.ts.map +1 -0
- package/dist/src/tools/search.js +197 -0
- package/dist/src/tools/search.js.map +7 -0
- package/dist/src/tools/utils.d.ts +105 -0
- package/dist/src/tools/utils.d.ts.map +1 -0
- package/dist/src/tools/utils.js +96 -0
- package/dist/src/tools/utils.js.map +7 -0
- package/dist/src/utils/concurrency.d.ts +28 -0
- package/dist/src/utils/concurrency.d.ts.map +1 -0
- package/dist/src/utils/concurrency.js +62 -0
- package/dist/src/utils/concurrency.js.map +7 -0
- package/dist/src/utils/errors.d.ts +95 -0
- package/dist/src/utils/errors.d.ts.map +1 -0
- package/dist/src/utils/errors.js +289 -0
- package/dist/src/utils/errors.js.map +7 -0
- package/dist/src/utils/logger.d.ts +33 -0
- package/dist/src/utils/logger.d.ts.map +1 -0
- package/dist/src/utils/logger.js +41 -0
- package/dist/src/utils/logger.js.map +7 -0
- package/dist/src/utils/markdown-formatter.d.ts +5 -0
- package/dist/src/utils/markdown-formatter.d.ts.map +1 -0
- package/dist/src/utils/markdown-formatter.js +15 -0
- package/dist/src/utils/markdown-formatter.js.map +7 -0
- package/dist/src/utils/response.d.ts +83 -0
- package/dist/src/utils/response.d.ts.map +1 -0
- package/dist/src/utils/response.js +109 -0
- package/dist/src/utils/response.js.map +7 -0
- package/dist/src/utils/retry.d.ts +43 -0
- package/dist/src/utils/retry.d.ts.map +1 -0
- package/dist/src/utils/retry.js +37 -0
- package/dist/src/utils/retry.js.map +7 -0
- package/dist/src/utils/url-aggregator.d.ts +92 -0
- package/dist/src/utils/url-aggregator.d.ts.map +1 -0
- package/dist/src/utils/url-aggregator.js +357 -0
- package/dist/src/utils/url-aggregator.js.map +7 -0
- package/dist/src/version.d.ts +28 -0
- package/dist/src/version.d.ts.map +1 -0
- package/dist/src/version.js +32 -0
- package/dist/src/version.js.map +7 -0
- package/package.json +73 -0
package/README.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# mcp-researchpowerpack
|
|
2
|
+
|
|
3
|
+
http mcp server for research. web search, reddit mining, scraping, deep research — all over `/mcp`.
|
|
4
|
+
|
|
5
|
+
built on [mcp-use](https://github.com/nicepkg/mcp-use). no stdio, http only.
|
|
6
|
+
|
|
7
|
+
## tools
|
|
8
|
+
|
|
9
|
+
| tool | what it does | needs |
|
|
10
|
+
|------|-------------|-------|
|
|
11
|
+
| `web-search` | parallel google search across 3–100 keywords, ctr-weighted url ranking | `SERPER_API_KEY` |
|
|
12
|
+
| `search-reddit` | reddit-focused search, 3–50 diverse queries | `SERPER_API_KEY` |
|
|
13
|
+
| `get-reddit-post` | fetch reddit posts + full comment trees, 2–50 urls | `REDDIT_CLIENT_ID` + `REDDIT_CLIENT_SECRET` |
|
|
14
|
+
| `scrape-links` | scrape 1–50 urls with optional ai extraction | `SCRAPEDO_API_KEY` |
|
|
15
|
+
| `deep-research` | multi-question research with optional file attachments | `OPENROUTER_API_KEY` |
|
|
16
|
+
|
|
17
|
+
also exposes `/health` and `health://status` mcp resource.
|
|
18
|
+
|
|
19
|
+
## quickstart
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# from npm
|
|
23
|
+
HOST=127.0.0.1 PORT=3000 npx -y mcp-researchpowerpack-http
|
|
24
|
+
|
|
25
|
+
# from source
|
|
26
|
+
git clone https://github.com/yigitkonur/mcp-researchpowerpack-http.git
|
|
27
|
+
cd mcp-researchpowerpack-http
|
|
28
|
+
pnpm install && pnpm dev
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
connect your client to `http://localhost:3000/mcp`:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"mcpServers": {
|
|
36
|
+
"research-powerpack": {
|
|
37
|
+
"url": "http://localhost:3000/mcp"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## config
|
|
44
|
+
|
|
45
|
+
copy `.env.example`, set only what you need. missing keys don't crash — they disable the tool with a clear error.
|
|
46
|
+
|
|
47
|
+
### server
|
|
48
|
+
|
|
49
|
+
| var | default | |
|
|
50
|
+
|-----|---------|---|
|
|
51
|
+
| `PORT` | `3000` | http port |
|
|
52
|
+
| `HOST` | `127.0.0.1` | bind address |
|
|
53
|
+
| `ALLOWED_ORIGINS` | unset | comma-separated origins for host validation |
|
|
54
|
+
| `REDIS_URL` | unset | redis-backed sessions + distributed sse |
|
|
55
|
+
|
|
56
|
+
### providers
|
|
57
|
+
|
|
58
|
+
| var | enables |
|
|
59
|
+
|-----|---------|
|
|
60
|
+
| `SERPER_API_KEY` | web-search, search-reddit |
|
|
61
|
+
| `REDDIT_CLIENT_ID` + `REDDIT_CLIENT_SECRET` | get-reddit-post |
|
|
62
|
+
| `SCRAPEDO_API_KEY` | scrape-links |
|
|
63
|
+
| `OPENROUTER_API_KEY` | deep-research, ai extraction |
|
|
64
|
+
|
|
65
|
+
optional tuning: `RESEARCH_MODEL`, `RESEARCH_FALLBACK_MODEL`, `LLM_EXTRACTION_MODEL`, `DEFAULT_REASONING_EFFORT`, `API_TIMEOUT_MS`.
|
|
66
|
+
|
|
67
|
+
## dev
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pnpm install
|
|
71
|
+
pnpm dev # watch mode, serves :3000/mcp
|
|
72
|
+
pnpm typecheck # tsc --noEmit
|
|
73
|
+
pnpm test # http integration test
|
|
74
|
+
pnpm build # compile to dist/
|
|
75
|
+
pnpm inspect # mcp-use inspector
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## deploy
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
pnpm build
|
|
82
|
+
pnpm deploy # manufact cloud
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
or self-host anywhere with node 20.19+ / 22.12+:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
HOST=0.0.0.0 ALLOWED_ORIGINS=https://app.example.com pnpm start
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## architecture
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
index.ts server startup, cors, health, shutdown
|
|
95
|
+
src/
|
|
96
|
+
config/ env parsing, capability detection, lazy proxy config
|
|
97
|
+
clients/ provider api clients (serper, reddit, scrapedo, openrouter)
|
|
98
|
+
tools/
|
|
99
|
+
registry.ts registerAllTools() — wires tools to mcp server
|
|
100
|
+
search.ts web-search handler
|
|
101
|
+
reddit.ts search-reddit + get-reddit-post
|
|
102
|
+
scrape.ts scrape-links handler
|
|
103
|
+
research.ts deep-research handler
|
|
104
|
+
mcp-helpers.ts response builders (markdown, error, toolFailure)
|
|
105
|
+
utils.ts shared formatters, token budget allocation
|
|
106
|
+
services/
|
|
107
|
+
llm-processor.ts ai extraction/synthesis via openrouter
|
|
108
|
+
file-attachment.ts local file reads for deep-research context
|
|
109
|
+
markdown-cleaner.ts html/markdown cleanup
|
|
110
|
+
schemas/ zod v4 input validation per tool
|
|
111
|
+
utils/
|
|
112
|
+
errors.ts structured error codes (retryable classification)
|
|
113
|
+
concurrency.ts pMap/pMapSettled — bounded parallel execution
|
|
114
|
+
retry.ts exponential backoff with jitter
|
|
115
|
+
url-aggregator.ts ctr-weighted url ranking for search consensus
|
|
116
|
+
response.ts formatSuccess/formatError/formatBatchHeader
|
|
117
|
+
logger.ts mcpLog() — stderr-only (mcp-safe)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
key patterns: capability detection at startup, lazy config via proxy, bounded concurrency (scraper:30, reddit:10, research:3), 32k token budgets, ctr-based url ranking, tools never throw (always return toolFailure), structured errors with retry classification.
|
|
121
|
+
|
|
122
|
+
## license
|
|
123
|
+
|
|
124
|
+
mit
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Logger } from "mcp-use";
|
|
3
|
+
import {
|
|
4
|
+
InMemorySessionStore,
|
|
5
|
+
InMemoryStreamManager,
|
|
6
|
+
MCPServer,
|
|
7
|
+
RedisSessionStore,
|
|
8
|
+
RedisStreamManager,
|
|
9
|
+
object
|
|
10
|
+
} from "mcp-use/server";
|
|
11
|
+
import { createClient } from "redis";
|
|
12
|
+
import { SERVER } from "./src/config/index.js";
|
|
13
|
+
import { registerAllTools } from "./src/tools/registry.js";
|
|
14
|
+
const DEFAULT_PORT = 3e3;
|
|
15
|
+
const SHUTDOWN_TIMEOUT_MS = 1e4;
|
|
16
|
+
const WEBSITE_URL = "https://github.com/yigitkonur/mcp-researchpowerpack-http";
|
|
17
|
+
const LOCAL_DEFAULT_HOST = "127.0.0.1";
|
|
18
|
+
const startupLogger = Logger.get("startup");
|
|
19
|
+
function parseCsvEnv(value) {
|
|
20
|
+
if (!value) return void 0;
|
|
21
|
+
const parts = value.split(",").map((part) => part.trim()).filter(Boolean);
|
|
22
|
+
return parts.length > 0 ? parts : void 0;
|
|
23
|
+
}
|
|
24
|
+
function parsePort(value, fallback) {
|
|
25
|
+
const parsed = Number.parseInt(value ?? "", 10);
|
|
26
|
+
if (Number.isFinite(parsed) && parsed > 0) {
|
|
27
|
+
return parsed;
|
|
28
|
+
}
|
|
29
|
+
return fallback;
|
|
30
|
+
}
|
|
31
|
+
function resolvePort() {
|
|
32
|
+
const portFlagIndex = process.argv.findIndex((arg) => arg === "--port");
|
|
33
|
+
if (portFlagIndex >= 0) {
|
|
34
|
+
return parsePort(process.argv[portFlagIndex + 1], DEFAULT_PORT);
|
|
35
|
+
}
|
|
36
|
+
return parsePort(process.env.PORT, DEFAULT_PORT);
|
|
37
|
+
}
|
|
38
|
+
function resolveHost() {
|
|
39
|
+
const explicitHost = process.env.HOST?.trim();
|
|
40
|
+
if (explicitHost) {
|
|
41
|
+
return explicitHost;
|
|
42
|
+
}
|
|
43
|
+
if (process.env.PORT?.trim()) {
|
|
44
|
+
return "0.0.0.0";
|
|
45
|
+
}
|
|
46
|
+
return LOCAL_DEFAULT_HOST;
|
|
47
|
+
}
|
|
48
|
+
function buildCors(allowedOrigins) {
|
|
49
|
+
if (!allowedOrigins || allowedOrigins.length === 0) {
|
|
50
|
+
return void 0;
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
origin: allowedOrigins,
|
|
54
|
+
allowMethods: ["GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"],
|
|
55
|
+
allowHeaders: [
|
|
56
|
+
"Content-Type",
|
|
57
|
+
"Accept",
|
|
58
|
+
"Authorization",
|
|
59
|
+
"mcp-protocol-version",
|
|
60
|
+
"mcp-session-id",
|
|
61
|
+
"X-Proxy-Token",
|
|
62
|
+
"X-Target-URL"
|
|
63
|
+
],
|
|
64
|
+
exposeHeaders: ["mcp-session-id"]
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function configureLogging() {
|
|
68
|
+
Logger.configure({
|
|
69
|
+
level: process.env.NODE_ENV === "production" ? "info" : "debug",
|
|
70
|
+
format: "minimal"
|
|
71
|
+
});
|
|
72
|
+
const debug = process.env.DEBUG?.trim();
|
|
73
|
+
if (debug === "2") {
|
|
74
|
+
Logger.setDebug(2);
|
|
75
|
+
} else if (debug) {
|
|
76
|
+
Logger.setDebug(1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function normalizeOrigin(value, envName) {
|
|
80
|
+
try {
|
|
81
|
+
return new URL(value).origin;
|
|
82
|
+
} catch {
|
|
83
|
+
throw new Error(`${envName} must contain absolute URLs with protocol. Received: ${value}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function resolveAllowedOrigins() {
|
|
87
|
+
const explicitOrigins = parseCsvEnv(process.env.ALLOWED_ORIGINS);
|
|
88
|
+
if (explicitOrigins && explicitOrigins.length > 0) {
|
|
89
|
+
return explicitOrigins.map((origin) => normalizeOrigin(origin, "ALLOWED_ORIGINS"));
|
|
90
|
+
}
|
|
91
|
+
return void 0;
|
|
92
|
+
}
|
|
93
|
+
async function buildSessionConfig() {
|
|
94
|
+
const redisUrl = process.env.REDIS_URL?.trim();
|
|
95
|
+
if (!redisUrl) {
|
|
96
|
+
return {
|
|
97
|
+
sessionConfig: {
|
|
98
|
+
sessionStore: new InMemorySessionStore(),
|
|
99
|
+
streamManager: new InMemoryStreamManager()
|
|
100
|
+
},
|
|
101
|
+
cleanupFns: []
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const commandClient = createClient({ url: redisUrl });
|
|
105
|
+
const pubSubClient = commandClient.duplicate();
|
|
106
|
+
await Promise.all([commandClient.connect(), pubSubClient.connect()]);
|
|
107
|
+
return {
|
|
108
|
+
sessionConfig: {
|
|
109
|
+
sessionStore: new RedisSessionStore({
|
|
110
|
+
client: commandClient
|
|
111
|
+
}),
|
|
112
|
+
streamManager: new RedisStreamManager({
|
|
113
|
+
client: commandClient,
|
|
114
|
+
pubSubClient
|
|
115
|
+
})
|
|
116
|
+
},
|
|
117
|
+
cleanupFns: [
|
|
118
|
+
async () => {
|
|
119
|
+
await pubSubClient.quit();
|
|
120
|
+
},
|
|
121
|
+
async () => {
|
|
122
|
+
await commandClient.quit();
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function buildHealthPayload(server, startedAt) {
|
|
128
|
+
return {
|
|
129
|
+
status: "ok",
|
|
130
|
+
name: SERVER.NAME,
|
|
131
|
+
version: SERVER.VERSION,
|
|
132
|
+
transport: "http",
|
|
133
|
+
uptime_seconds: Math.floor((Date.now() - startedAt) / 1e3),
|
|
134
|
+
active_sessions: server.getActiveSessions().length,
|
|
135
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
async function main() {
|
|
139
|
+
configureLogging();
|
|
140
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
141
|
+
const host = resolveHost();
|
|
142
|
+
const port = resolvePort();
|
|
143
|
+
const baseUrl = process.env.MCP_URL?.trim() || void 0;
|
|
144
|
+
const allowedOrigins = resolveAllowedOrigins();
|
|
145
|
+
const { sessionConfig, cleanupFns } = await buildSessionConfig();
|
|
146
|
+
startupLogger.info(`Starting ${SERVER.NAME} v${SERVER.VERSION}`);
|
|
147
|
+
startupLogger.info(`Binding HTTP server to ${host}:${port}`);
|
|
148
|
+
if (allowedOrigins && allowedOrigins.length > 0) {
|
|
149
|
+
startupLogger.info(`Host validation enabled for origins: ${allowedOrigins.join(", ")}`);
|
|
150
|
+
} else if (isProduction) {
|
|
151
|
+
startupLogger.warn(
|
|
152
|
+
"Host validation is disabled because ALLOWED_ORIGINS is not set. Set ALLOWED_ORIGINS to the public deployment URL or custom domain after the first deploy."
|
|
153
|
+
);
|
|
154
|
+
} else {
|
|
155
|
+
startupLogger.info("Host validation disabled for local development");
|
|
156
|
+
}
|
|
157
|
+
const server = new MCPServer({
|
|
158
|
+
name: SERVER.NAME,
|
|
159
|
+
title: "Research Powerpack",
|
|
160
|
+
version: SERVER.VERSION,
|
|
161
|
+
description: SERVER.DESCRIPTION,
|
|
162
|
+
websiteUrl: WEBSITE_URL,
|
|
163
|
+
host,
|
|
164
|
+
baseUrl,
|
|
165
|
+
cors: buildCors(allowedOrigins),
|
|
166
|
+
allowedOrigins,
|
|
167
|
+
...sessionConfig
|
|
168
|
+
});
|
|
169
|
+
registerAllTools(server);
|
|
170
|
+
const startedAt = Date.now();
|
|
171
|
+
server.get("/health", (c) => c.json(buildHealthPayload(server, startedAt)));
|
|
172
|
+
server.get("/healthz", (c) => c.json(buildHealthPayload(server, startedAt)));
|
|
173
|
+
server.resource(
|
|
174
|
+
{
|
|
175
|
+
name: "server-health",
|
|
176
|
+
uri: "health://status",
|
|
177
|
+
description: "Current server health, uptime, and active MCP session count.",
|
|
178
|
+
mimeType: "application/json"
|
|
179
|
+
},
|
|
180
|
+
async () => object(buildHealthPayload(server, startedAt))
|
|
181
|
+
);
|
|
182
|
+
let isShuttingDown = false;
|
|
183
|
+
async function shutdown(signal, exitCode) {
|
|
184
|
+
if (isShuttingDown) return;
|
|
185
|
+
isShuttingDown = true;
|
|
186
|
+
const forceExit = setTimeout(() => {
|
|
187
|
+
startupLogger.error(`Forced exit after ${SHUTDOWN_TIMEOUT_MS}ms (${signal})`);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}, SHUTDOWN_TIMEOUT_MS);
|
|
190
|
+
try {
|
|
191
|
+
startupLogger.warn(`Shutdown signal received: ${signal}`);
|
|
192
|
+
await server.close();
|
|
193
|
+
for (const cleanupFn of cleanupFns) {
|
|
194
|
+
await cleanupFn();
|
|
195
|
+
}
|
|
196
|
+
clearTimeout(forceExit);
|
|
197
|
+
process.exit(exitCode);
|
|
198
|
+
} catch (error) {
|
|
199
|
+
clearTimeout(forceExit);
|
|
200
|
+
const message = error instanceof Error ? error.stack ?? error.message : String(error);
|
|
201
|
+
startupLogger.error(`Error while stopping server: ${message}`);
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
process.on("SIGTERM", () => {
|
|
206
|
+
void shutdown("SIGTERM", 0);
|
|
207
|
+
});
|
|
208
|
+
process.on("SIGINT", () => {
|
|
209
|
+
void shutdown("SIGINT", 0);
|
|
210
|
+
});
|
|
211
|
+
process.on("uncaughtException", (error) => {
|
|
212
|
+
startupLogger.error(`Uncaught exception: ${error.stack ?? error.message}`);
|
|
213
|
+
void shutdown("uncaughtException", 1);
|
|
214
|
+
});
|
|
215
|
+
process.on("unhandledRejection", (reason) => {
|
|
216
|
+
startupLogger.error(`Unhandled rejection: ${String(reason)}`);
|
|
217
|
+
void shutdown("unhandledRejection", 1);
|
|
218
|
+
});
|
|
219
|
+
await server.listen(port);
|
|
220
|
+
startupLogger.info(`${SERVER.NAME} v${SERVER.VERSION} listening on http://${host}:${port}/mcp`);
|
|
221
|
+
}
|
|
222
|
+
void main().catch((error) => {
|
|
223
|
+
const message = error instanceof Error ? error.stack ?? error.message : String(error);
|
|
224
|
+
startupLogger.error(`Server failed to start: ${message}`);
|
|
225
|
+
process.exit(1);
|
|
226
|
+
});
|
|
227
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../index.ts"],
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n\nimport { Logger } from 'mcp-use';\nimport {\n InMemorySessionStore,\n InMemoryStreamManager,\n MCPServer,\n RedisSessionStore,\n RedisStreamManager,\n object,\n type ServerConfig,\n} from 'mcp-use/server';\nimport { createClient, type RedisClientType } from 'redis';\n\nimport { SERVER } from './src/config/index.js';\nimport { registerAllTools } from './src/tools/registry.js';\n\nconst DEFAULT_PORT = 3000 as const;\nconst SHUTDOWN_TIMEOUT_MS = 10_000 as const;\nconst WEBSITE_URL = 'https://github.com/yigitkonur/mcp-researchpowerpack-http' as const;\nconst LOCAL_DEFAULT_HOST = '127.0.0.1' as const;\n\ntype CleanupFn = () => Promise<void>;\n\nconst startupLogger = Logger.get('startup');\n\nfunction parseCsvEnv(value: string | undefined): string[] | undefined {\n if (!value) return undefined;\n\n const parts = value\n .split(',')\n .map((part) => part.trim())\n .filter(Boolean);\n\n return parts.length > 0 ? parts : undefined;\n}\n\nfunction parsePort(value: string | undefined, fallback: number): number {\n const parsed = Number.parseInt(value ?? '', 10);\n if (Number.isFinite(parsed) && parsed > 0) {\n return parsed;\n }\n\n return fallback;\n}\n\nfunction resolvePort(): number {\n const portFlagIndex = process.argv.findIndex((arg) => arg === '--port');\n if (portFlagIndex >= 0) {\n return parsePort(process.argv[portFlagIndex + 1], DEFAULT_PORT);\n }\n\n return parsePort(process.env.PORT, DEFAULT_PORT);\n}\n\nfunction resolveHost(): string {\n const explicitHost = process.env.HOST?.trim();\n if (explicitHost) {\n return explicitHost;\n }\n\n // Cloud runtimes typically inject PORT and expect the process to listen on all interfaces.\n if (process.env.PORT?.trim()) {\n return '0.0.0.0';\n }\n\n return LOCAL_DEFAULT_HOST;\n}\n\nfunction buildCors(allowedOrigins: string[] | undefined): ServerConfig['cors'] {\n if (!allowedOrigins || allowedOrigins.length === 0) {\n return undefined;\n }\n\n return {\n origin: allowedOrigins,\n allowMethods: ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowHeaders: [\n 'Content-Type',\n 'Accept',\n 'Authorization',\n 'mcp-protocol-version',\n 'mcp-session-id',\n 'X-Proxy-Token',\n 'X-Target-URL',\n ],\n exposeHeaders: ['mcp-session-id'],\n };\n}\n\nfunction configureLogging(): void {\n Logger.configure({\n level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',\n format: 'minimal',\n });\n\n const debug = process.env.DEBUG?.trim();\n if (debug === '2') {\n Logger.setDebug(2);\n } else if (debug) {\n Logger.setDebug(1);\n }\n}\n\nfunction normalizeOrigin(value: string, envName: string): string {\n try {\n return new URL(value).origin;\n } catch {\n throw new Error(`${envName} must contain absolute URLs with protocol. Received: ${value}`);\n }\n}\n\nfunction resolveAllowedOrigins(): string[] | undefined {\n const explicitOrigins = parseCsvEnv(process.env.ALLOWED_ORIGINS);\n if (explicitOrigins && explicitOrigins.length > 0) {\n return explicitOrigins.map(origin => normalizeOrigin(origin, 'ALLOWED_ORIGINS'));\n }\n\n return undefined;\n}\n\nasync function buildSessionConfig(): Promise<{\n sessionConfig: Pick<ServerConfig, 'sessionStore' | 'streamManager'>;\n cleanupFns: CleanupFn[];\n}> {\n const redisUrl = process.env.REDIS_URL?.trim();\n\n if (!redisUrl) {\n return {\n sessionConfig: {\n sessionStore: new InMemorySessionStore(),\n streamManager: new InMemoryStreamManager(),\n },\n cleanupFns: [],\n };\n }\n\n const commandClient = createClient({ url: redisUrl });\n const pubSubClient = commandClient.duplicate();\n\n await Promise.all([commandClient.connect(), pubSubClient.connect()]);\n\n return {\n sessionConfig: {\n sessionStore: new RedisSessionStore({\n client: commandClient as RedisClientType,\n }),\n streamManager: new RedisStreamManager({\n client: commandClient as RedisClientType,\n pubSubClient: pubSubClient as RedisClientType,\n }),\n },\n cleanupFns: [\n async () => {\n await pubSubClient.quit();\n },\n async () => {\n await commandClient.quit();\n },\n ],\n };\n}\n\nfunction buildHealthPayload(server: MCPServer, startedAt: number) {\n return {\n status: 'ok',\n name: SERVER.NAME,\n version: SERVER.VERSION,\n transport: 'http',\n uptime_seconds: Math.floor((Date.now() - startedAt) / 1000),\n active_sessions: server.getActiveSessions().length,\n timestamp: new Date().toISOString(),\n };\n}\n\nasync function main(): Promise<void> {\n configureLogging();\n\n const isProduction = process.env.NODE_ENV === 'production';\n const host = resolveHost();\n const port = resolvePort();\n const baseUrl = process.env.MCP_URL?.trim() || undefined;\n const allowedOrigins = resolveAllowedOrigins();\n\n const { sessionConfig, cleanupFns } = await buildSessionConfig();\n\n startupLogger.info(`Starting ${SERVER.NAME} v${SERVER.VERSION}`);\n startupLogger.info(`Binding HTTP server to ${host}:${port}`);\n if (allowedOrigins && allowedOrigins.length > 0) {\n startupLogger.info(`Host validation enabled for origins: ${allowedOrigins.join(', ')}`);\n } else if (isProduction) {\n startupLogger.warn(\n 'Host validation is disabled because ALLOWED_ORIGINS is not set. ' +\n 'Set ALLOWED_ORIGINS to the public deployment URL or custom domain after the first deploy.',\n );\n } else {\n startupLogger.info('Host validation disabled for local development');\n }\n\n const server = new MCPServer({\n name: SERVER.NAME,\n title: 'Research Powerpack',\n version: SERVER.VERSION,\n description: SERVER.DESCRIPTION,\n websiteUrl: WEBSITE_URL,\n host,\n baseUrl,\n cors: buildCors(allowedOrigins),\n allowedOrigins,\n ...sessionConfig,\n });\n\n registerAllTools(server);\n\n const startedAt = Date.now();\n\n server.get('/health', (c) => c.json(buildHealthPayload(server, startedAt)));\n server.get('/healthz', (c) => c.json(buildHealthPayload(server, startedAt)));\n server.resource(\n {\n name: 'server-health',\n uri: 'health://status',\n description: 'Current server health, uptime, and active MCP session count.',\n mimeType: 'application/json',\n },\n async () => object(buildHealthPayload(server, startedAt)),\n );\n\n let isShuttingDown = false;\n\n async function shutdown(signal: string, exitCode: number): Promise<void> {\n if (isShuttingDown) return;\n isShuttingDown = true;\n\n const forceExit = setTimeout(() => {\n startupLogger.error(`Forced exit after ${SHUTDOWN_TIMEOUT_MS}ms (${signal})`);\n process.exit(1);\n }, SHUTDOWN_TIMEOUT_MS);\n\n try {\n startupLogger.warn(`Shutdown signal received: ${signal}`);\n await server.close();\n\n for (const cleanupFn of cleanupFns) {\n await cleanupFn();\n }\n\n clearTimeout(forceExit);\n process.exit(exitCode);\n } catch (error) {\n clearTimeout(forceExit);\n const message = error instanceof Error ? (error.stack ?? error.message) : String(error);\n startupLogger.error(`Error while stopping server: ${message}`);\n process.exit(1);\n }\n }\n\n process.on('SIGTERM', () => {\n void shutdown('SIGTERM', 0);\n });\n\n process.on('SIGINT', () => {\n void shutdown('SIGINT', 0);\n });\n\n process.on('uncaughtException', (error) => {\n startupLogger.error(`Uncaught exception: ${error.stack ?? error.message}`);\n void shutdown('uncaughtException', 1);\n });\n\n process.on('unhandledRejection', (reason) => {\n startupLogger.error(`Unhandled rejection: ${String(reason)}`);\n void shutdown('unhandledRejection', 1);\n });\n\n await server.listen(port);\n\n startupLogger.info(`${SERVER.NAME} v${SERVER.VERSION} listening on http://${host}:${port}/mcp`);\n}\n\nvoid main().catch((error) => {\n const message = error instanceof Error ? (error.stack ?? error.message) : String(error);\n startupLogger.error(`Server failed to start: ${message}`);\n process.exit(1);\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub API Client
|
|
3
|
+
* GraphQL + REST client for fetching repository data for quality scoring.
|
|
4
|
+
* Implements robust error handling that NEVER crashes.
|
|
5
|
+
*/
|
|
6
|
+
import { type StructuredError } from '../utils/errors.js';
|
|
7
|
+
export interface GitHubSearchItem {
|
|
8
|
+
readonly fullName: string;
|
|
9
|
+
readonly owner: string;
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly description: string | null;
|
|
12
|
+
readonly stars: number;
|
|
13
|
+
readonly forks: number;
|
|
14
|
+
readonly language: string | null;
|
|
15
|
+
readonly pushedAt: string;
|
|
16
|
+
readonly url: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ParticipationData {
|
|
19
|
+
readonly all: readonly number[];
|
|
20
|
+
readonly owner: readonly number[];
|
|
21
|
+
}
|
|
22
|
+
export interface ContributorEntry {
|
|
23
|
+
readonly login: string;
|
|
24
|
+
readonly contributions: number;
|
|
25
|
+
}
|
|
26
|
+
export interface RepoGraphQLData {
|
|
27
|
+
readonly stars: number;
|
|
28
|
+
readonly forks: number;
|
|
29
|
+
readonly watchers: number;
|
|
30
|
+
readonly openIssues: number;
|
|
31
|
+
readonly closedIssues: number;
|
|
32
|
+
readonly totalCommits: number;
|
|
33
|
+
readonly totalReleases: number;
|
|
34
|
+
readonly totalPRs: number;
|
|
35
|
+
readonly sizeKb: number;
|
|
36
|
+
readonly language: string | null;
|
|
37
|
+
readonly license: string | null;
|
|
38
|
+
readonly archived: boolean;
|
|
39
|
+
readonly createdAt: string;
|
|
40
|
+
readonly pushedAt: string;
|
|
41
|
+
readonly description: string | null;
|
|
42
|
+
readonly homepage: string | null;
|
|
43
|
+
readonly hasCI: boolean;
|
|
44
|
+
readonly hasContributing: boolean;
|
|
45
|
+
readonly hasIssueTemplate: boolean;
|
|
46
|
+
readonly hasPrTemplate: boolean;
|
|
47
|
+
readonly hasCodeOfConduct: boolean;
|
|
48
|
+
readonly hasTopics: boolean;
|
|
49
|
+
}
|
|
50
|
+
export interface RepoFullData {
|
|
51
|
+
readonly graphql: RepoGraphQLData;
|
|
52
|
+
readonly participation: ParticipationData;
|
|
53
|
+
readonly contributors: readonly ContributorEntry[];
|
|
54
|
+
}
|
|
55
|
+
export declare class GitHubClient {
|
|
56
|
+
private token;
|
|
57
|
+
private apiCallCount;
|
|
58
|
+
constructor(token?: string);
|
|
59
|
+
get apiCalls(): number;
|
|
60
|
+
searchRepos(query: string, sort?: string, perPage?: number): Promise<{
|
|
61
|
+
items: GitHubSearchItem[];
|
|
62
|
+
totalCount: number;
|
|
63
|
+
error?: StructuredError;
|
|
64
|
+
}>;
|
|
65
|
+
fetchRepoDetails(owner: string, name: string): Promise<{
|
|
66
|
+
data?: RepoFullData;
|
|
67
|
+
error?: StructuredError;
|
|
68
|
+
}>;
|
|
69
|
+
fetchMultipleRepoDetails(repos: Array<{
|
|
70
|
+
owner: string;
|
|
71
|
+
name: string;
|
|
72
|
+
}>): Promise<Array<{
|
|
73
|
+
owner: string;
|
|
74
|
+
name: string;
|
|
75
|
+
data?: RepoFullData;
|
|
76
|
+
error?: StructuredError;
|
|
77
|
+
}>>;
|
|
78
|
+
private graphqlQuery;
|
|
79
|
+
private fetchParticipation;
|
|
80
|
+
private fetchContributors;
|
|
81
|
+
private restGet;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../../src/clients/github.ts"],"names":[],"mappings":"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"}
|