mcp-researchpowerpack 6.0.17 → 7.0.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 +101 -51
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-use.json +2 -2
- package/dist/src/clients/jina.js +262 -80
- package/dist/src/clients/jina.js.map +2 -2
- package/dist/src/clients/kernel.js +142 -0
- package/dist/src/clients/kernel.js.map +7 -0
- package/dist/src/clients/reddit.js.map +1 -1
- package/dist/src/config/index.js +17 -7
- package/dist/src/config/index.js.map +2 -2
- package/dist/src/effect/errors.js +58 -0
- package/dist/src/effect/errors.js.map +7 -0
- package/dist/src/effect/runtime.js +15 -0
- package/dist/src/effect/runtime.js.map +7 -0
- package/dist/src/effect/services.js +97 -0
- package/dist/src/effect/services.js.map +7 -0
- package/dist/src/schemas/scrape-links.js +14 -20
- package/dist/src/schemas/scrape-links.js.map +2 -2
- package/dist/src/schemas/start-research.js +2 -2
- package/dist/src/schemas/start-research.js.map +1 -1
- package/dist/src/schemas/web-search.js +17 -63
- package/dist/src/schemas/web-search.js.map +2 -2
- package/dist/src/services/llm-processor.js +22 -14
- package/dist/src/services/llm-processor.js.map +2 -2
- package/dist/src/tools/registry.js +4 -4
- package/dist/src/tools/registry.js.map +2 -2
- package/dist/src/tools/scrape.js +415 -215
- package/dist/src/tools/scrape.js.map +3 -3
- package/dist/src/tools/search.js +193 -142
- package/dist/src/tools/search.js.map +3 -3
- package/dist/src/tools/start-research.js +38 -19
- package/dist/src/tools/start-research.js.map +2 -2
- package/dist/src/utils/content-quality.js +64 -0
- package/dist/src/utils/content-quality.js.map +7 -0
- package/dist/src/utils/query-relax.js.map +1 -1
- package/dist/src/utils/source-type.js.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -2,27 +2,46 @@
|
|
|
2
2
|
|
|
3
3
|
# mcp-researchpowerpack
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
http mcp server for research. five tools, orientation-first, built for agents
|
|
6
|
+
that run multi-pass research loops.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
ships on [`mcp-use`](https://github.com/nicepkg/mcp-use). every external call
|
|
9
|
+
flows through an effect ts service layer for typed concurrency, typed errors,
|
|
10
|
+
and timeouts that actually mean something. no stdio — http only.
|
|
8
11
|
|
|
9
12
|
## tools
|
|
10
13
|
|
|
11
14
|
| tool | what it does | needs |
|
|
12
15
|
|------|-------------|-------|
|
|
13
|
-
| `start-research` | returns a goal-tailored brief: `primary_branch` (reddit / web / both), exact `first_call_sequence`, 25–50 keyword seeds, iteration hints, gaps to watch, stop criteria.
|
|
14
|
-
| `web-search` | parallel
|
|
15
|
-
| `
|
|
16
|
+
| `start-research` | returns a goal-tailored brief: `primary_branch` (reddit / web / both), exact `first_call_sequence`, 25–50 keyword seeds, iteration hints, gaps to watch, stop criteria. call first every session. | `LLM_API_KEY` + `LLM_BASE_URL` + `LLM_MODEL` for the non-degraded brief (optional — server falls back to a static playbook) |
|
|
17
|
+
| `raw-web-search` | parallel search, up to 50 `keywords` per call. serper is primary; jina search is the fallback when serper is missing, fails, or returns empty. returns the raw ranked markdown list directly — no llm pass. use for broad discovery, audit trails, and reddit permalink probes via explicit `site:reddit.com/r/.../comments`. | `SERPER_API_KEY` or `JINA_API_KEY` |
|
|
18
|
+
| `smart-web-search` | parallel search, up to 50 `keywords` per call, plus required `extract`. same provider order as raw. always runs llm classification and returns tiered markdown (HIGHLY_RELEVANT / MAYBE_RELEVANT / OTHER) + grounded synthesis + gaps + refine suggestions. supports `scope: "web" \| "reddit" \| "both"`. | `SERPER_API_KEY` or `JINA_API_KEY` + llm env triple |
|
|
19
|
+
| `raw-scrape-links` | fetch urls in parallel, return full markdown directly. reddit post permalinks route through the reddit api with threaded comments. non-reddit urls hit jina reader first, then jina reader through scrape.do proxy mode, then optional kernel browser rendering for web pages. pdf / docx / pptx / xlsx urls go straight through jina reader. | optional `REDDIT_CLIENT_ID` / `REDDIT_CLIENT_SECRET`, `SCRAPEDO_API_KEY`, `JINA_API_KEY`, `KERNEL_API_KEY` |
|
|
20
|
+
| `smart-scrape-links` | same fetch stack as raw scrape, then per-url llm extraction with required `extract`. returns focused evidence packs with `## Source`, `## Matches`, `## Not found`, and `## Follow-up signals`. | raw scrape providers + llm env triple |
|
|
16
21
|
|
|
17
|
-
|
|
22
|
+
also exposes `/health` (simplified for proxies) and `health://status` (full
|
|
23
|
+
json: planner/extractor reachability, consecutive failure counters, uptime,
|
|
24
|
+
active sessions).
|
|
18
25
|
|
|
19
26
|
## workflow
|
|
20
27
|
|
|
21
|
-
|
|
28
|
+
call `start-research` once per session with your goal. the server returns a
|
|
29
|
+
brief that names the first tool to fire (reddit-first for sentiment/migration,
|
|
30
|
+
web-first for spec/bug/pricing, both when opinion-heavy and you also need
|
|
31
|
+
official sources), the keyword seeds to fan out, and stop criteria.
|
|
22
32
|
|
|
23
|
-
|
|
33
|
+
for search fan-out, think bad → better before calling `raw-web-search` or
|
|
34
|
+
`smart-web-search`. turn broad phrases like `<feature> support`, `<product>
|
|
35
|
+
pricing`, `<library> bug fix`, or `<tool> reviews` into source-aware probes
|
|
36
|
+
like:
|
|
24
37
|
|
|
25
|
-
|
|
38
|
+
- `site:<official-docs-domain> "<feature>" "<platform-or-version>"`
|
|
39
|
+
- `site:<vendor-domain> "<product>" pricing "enterprise" OR "free tier"`
|
|
40
|
+
- `"<exact error text>" "<library-or-package>" "<version>" site:github.com`
|
|
41
|
+
- `site:reddit.com/r/<community>/comments "<tool>" "migration" OR "regression"`
|
|
42
|
+
|
|
43
|
+
pair the server with the [`run-research`](https://github.com/yigitkonur/skills-by-yigitkonur/tree/main/skills/run-research)
|
|
44
|
+
skill for the full agentic playbook:
|
|
26
45
|
|
|
27
46
|
```bash
|
|
28
47
|
npx -y skills add -y -g https://github.com/yigitkonur/skills-by-yigitkonur --skill /run-research
|
|
@@ -40,7 +59,7 @@ cd mcp-researchpowerpack
|
|
|
40
59
|
pnpm install && pnpm dev
|
|
41
60
|
```
|
|
42
61
|
|
|
43
|
-
|
|
62
|
+
point your client at `http://localhost:3000/mcp`:
|
|
44
63
|
|
|
45
64
|
```json
|
|
46
65
|
{
|
|
@@ -52,49 +71,70 @@ Connect your client to `http://localhost:3000/mcp`:
|
|
|
52
71
|
}
|
|
53
72
|
```
|
|
54
73
|
|
|
74
|
+
or skip the install entirely and hit the hosted deployment at
|
|
75
|
+
`https://research.yigitkonur.com/mcp`.
|
|
76
|
+
|
|
55
77
|
## config
|
|
56
78
|
|
|
57
|
-
|
|
79
|
+
copy `.env.example`, set only what you need. missing keys don't crash the
|
|
80
|
+
server — they disable the affected capability with a clear error at call time.
|
|
58
81
|
|
|
59
82
|
### server
|
|
60
83
|
|
|
61
84
|
| var | default | |
|
|
62
85
|
|-----|---------|---|
|
|
63
|
-
| `PORT` | `3000` |
|
|
64
|
-
| `HOST` | `127.0.0.1` | bind address |
|
|
65
|
-
| `ALLOWED_ORIGINS` | unset | comma-separated origins for host validation |
|
|
66
|
-
| `MCP_URL` | unset | fallback public
|
|
86
|
+
| `PORT` | `3000` | http port |
|
|
87
|
+
| `HOST` | `127.0.0.1` | bind address; cloud runtimes that set `PORT` auto-switch to `0.0.0.0` |
|
|
88
|
+
| `ALLOWED_ORIGINS` | unset | comma-separated origins for host validation / cors |
|
|
89
|
+
| `MCP_URL` | unset | fallback public mcp url used by the production origin-protection guard |
|
|
90
|
+
| `NODE_ENV` | unset | set to `production` to enforce `ALLOWED_ORIGINS` or `MCP_URL` (server exits otherwise) |
|
|
91
|
+
| `DEBUG` | unset | `1` or `2` to bump mcp-use debug verbosity |
|
|
67
92
|
|
|
68
93
|
### providers
|
|
69
94
|
|
|
70
95
|
| var | enables |
|
|
71
96
|
|-----|---------|
|
|
72
|
-
| `SERPER_API_KEY` |
|
|
73
|
-
| `SCRAPEDO_API_KEY` |
|
|
74
|
-
| `REDDIT_CLIENT_ID` + `REDDIT_CLIENT_SECRET` |
|
|
75
|
-
| `JINA_API_KEY` |
|
|
76
|
-
| `
|
|
97
|
+
| `SERPER_API_KEY` | primary raw/smart web search provider |
|
|
98
|
+
| `SCRAPEDO_API_KEY` | scrape.do proxy-mode retry for jina reader (`X-Proxy-Url`) |
|
|
99
|
+
| `REDDIT_CLIENT_ID` + `REDDIT_CLIENT_SECRET` | raw/smart scrape for reddit.com permalinks (threaded post + comments) |
|
|
100
|
+
| `JINA_API_KEY` | jina search fallback and authenticated jina reader requests |
|
|
101
|
+
| `KERNEL_API_KEY` | optional kernel browser-render fallback after jina direct + proxy fail |
|
|
102
|
+
| `KERNEL_PROJECT` | optional kernel project scoping header for org-wide api keys |
|
|
103
|
+
| `LLM_API_KEY` + `LLM_BASE_URL` + `LLM_MODEL` | goal-tailored brief, `smart-web-search`, `smart-scrape-links` |
|
|
77
104
|
|
|
78
|
-
### llm
|
|
105
|
+
### llm
|
|
79
106
|
|
|
80
|
-
|
|
107
|
+
any openai-compatible endpoint. `LLM_API_KEY`, `LLM_BASE_URL`, and `LLM_MODEL`
|
|
108
|
+
are required together. reasoning effort is hardcoded to `low`.
|
|
81
109
|
|
|
82
110
|
| var | required? | |
|
|
83
111
|
|-----|-----------|---|
|
|
84
|
-
| `LLM_API_KEY` | yes |
|
|
85
|
-
| `LLM_BASE_URL` | yes | base
|
|
112
|
+
| `LLM_API_KEY` | yes | api key for the endpoint |
|
|
113
|
+
| `LLM_BASE_URL` | yes | base url for the openai-compatible endpoint (e.g. `https://server.up.railway.app/v1`) |
|
|
86
114
|
| `LLM_MODEL` | yes | primary model (e.g. `gpt-5.4-mini`) |
|
|
87
|
-
| `LLM_FALLBACK_MODEL` | no | model to use after primary exhausts
|
|
88
|
-
| `LLM_CONCURRENCY` | no (default `50`) | parallel LLM calls |
|
|
115
|
+
| `LLM_FALLBACK_MODEL` | no | model to use after primary exhausts retries — gets 3 more attempts (e.g. `gpt-5.4`). also receives oversized inputs that exceed the primary's context window |
|
|
89
116
|
|
|
90
|
-
###
|
|
117
|
+
### concurrency
|
|
91
118
|
|
|
92
|
-
|
|
119
|
+
all optional. provider limits are clamped 1–200; kernel is clamped 1–20.
|
|
120
|
+
|
|
121
|
+
| var | default | controls |
|
|
122
|
+
|-----|---------|----------|
|
|
123
|
+
| `CONCURRENCY_SEARCH` | `50` | parallel serper / jina search queries |
|
|
124
|
+
| `CONCURRENCY_SCRAPER` | `50` | parallel scrape.do (proxy mode) requests |
|
|
125
|
+
| `CONCURRENCY_JINA_READER` | `50` | parallel jina reader fetches |
|
|
126
|
+
| `CONCURRENCY_REDDIT` | `50` | parallel reddit api fetches |
|
|
127
|
+
| `CONCURRENCY_KERNEL` | `3` | parallel kernel browser-render fallbacks |
|
|
128
|
+
| `LLM_CONCURRENCY` | `50` | parallel llm extraction / classification calls |
|
|
129
|
+
|
|
130
|
+
### evals
|
|
93
131
|
|
|
94
|
-
|
|
95
|
-
|
|
132
|
+
`pnpm test:evals` writes a json artifact to `test-results/eval-runs/<timestamp>.json`.
|
|
133
|
+
when an openai api key is present, it runs a live responses-api + remote-mcp
|
|
134
|
+
eval. without one, it exits successfully in explicit skip mode and records
|
|
135
|
+
the skip in the artifact.
|
|
96
136
|
|
|
97
|
-
|
|
137
|
+
useful env vars:
|
|
98
138
|
|
|
99
139
|
- `EVAL_MCP_URL`
|
|
100
140
|
- `EVAL_MODEL`
|
|
@@ -113,13 +153,13 @@ pnpm inspect # mcp-use inspector
|
|
|
113
153
|
|
|
114
154
|
## deploy
|
|
115
155
|
|
|
116
|
-
|
|
156
|
+
deploy to manufact cloud via the `mcp-use` cli (github-backed):
|
|
117
157
|
|
|
118
158
|
```bash
|
|
119
159
|
pnpm deploy # runs the package script: mcp-use deploy
|
|
120
160
|
```
|
|
121
161
|
|
|
122
|
-
|
|
162
|
+
or self-host anywhere with node 20.19+ / 22.12+:
|
|
123
163
|
|
|
124
164
|
```bash
|
|
125
165
|
HOST=0.0.0.0 ALLOWED_ORIGINS=https://app.example.com pnpm start
|
|
@@ -131,29 +171,39 @@ HOST=0.0.0.0 ALLOWED_ORIGINS=https://app.example.com pnpm start
|
|
|
131
171
|
index.ts server startup, cors, health, shutdown
|
|
132
172
|
src/
|
|
133
173
|
config/ env parsing, capability detection, lazy proxy config
|
|
134
|
-
|
|
174
|
+
effect/ typed service tags + Live layers; runExternalEffect()
|
|
175
|
+
is the single boundary tool handlers cross to talk
|
|
176
|
+
to the outside world
|
|
177
|
+
clients/ provider api clients (serper, jina, kernel, reddit,
|
|
178
|
+
scrapedo) — wrapped by Live layers in src/effect/
|
|
135
179
|
tools/
|
|
136
|
-
registry.ts registerAllTools() — wires
|
|
137
|
-
start-research.ts goal-tailored brief + static playbook
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
180
|
+
registry.ts registerAllTools() — wires the five tools
|
|
181
|
+
start-research.ts goal-tailored brief + static playbook + planner
|
|
182
|
+
circuit-breaker
|
|
183
|
+
search.ts raw/smart search handlers (ctr ranking + optional
|
|
184
|
+
llm classification)
|
|
185
|
+
scrape.ts raw/smart scrape handlers (reddit api, jina reader,
|
|
186
|
+
scrape.do proxy retry, optional kernel, optional
|
|
187
|
+
llm extraction)
|
|
188
|
+
mcp-helpers.ts markdown response builders
|
|
142
189
|
services/
|
|
143
|
-
llm-processor.ts
|
|
144
|
-
|
|
190
|
+
llm-processor.ts llm extraction, classification, brief generation —
|
|
191
|
+
primary + fallback model, always low reasoning,
|
|
192
|
+
oversized inputs route straight to fallback
|
|
193
|
+
markdown-cleaner.ts html/markdown cleanup (readability + turndown)
|
|
145
194
|
schemas/ zod v4 input validation per tool
|
|
146
|
-
utils/
|
|
147
|
-
|
|
148
|
-
errors.ts structured error codes (retryable classification)
|
|
149
|
-
concurrency.ts pMap/pMapSettled — thin wrappers over p-map@7
|
|
150
|
-
retry.ts exponential backoff with jitter
|
|
151
|
-
url-aggregator.ts CTR-weighted URL ranking for search consensus
|
|
152
|
-
response.ts formatSuccess/formatError/formatBatchHeader
|
|
153
|
-
logger.ts mcpLog() — stderr-only (MCP-safe)
|
|
195
|
+
utils/ errors, retry, ctr aggregator, response builders,
|
|
196
|
+
logger (stderr-only, mcp-safe)
|
|
154
197
|
```
|
|
155
198
|
|
|
156
|
-
|
|
199
|
+
key patterns: capability detection at startup, description-led tool routing
|
|
200
|
+
(no bootstrap gate), markdown-only mcp tool output for search/scrape,
|
|
201
|
+
raw/smart tool split, tiered classified output in `smart-web-search`, reddit
|
|
202
|
+
api routing in scrape tools, jina reader first for non-reddit urls,
|
|
203
|
+
scrape.do proxy-mode retry through `X-Proxy-Url`, optional kernel
|
|
204
|
+
browser-render fallback, bounded concurrency via `Effect.forEach`, ctr-based
|
|
205
|
+
url ranking, tools never throw (always return `toolFailure`), and structured
|
|
206
|
+
errors with retry classification.
|
|
157
207
|
|
|
158
208
|
## license
|
|
159
209
|
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { getLLMHealth } from "./src/services/llm-processor.js";
|
|
|
14
14
|
import { registerAllTools } from "./src/tools/registry.js";
|
|
15
15
|
const DEFAULT_PORT = 3e3;
|
|
16
16
|
const SHUTDOWN_TIMEOUT_MS = 1e4;
|
|
17
|
-
const WEBSITE_URL = "https://github.com/yigitkonur/mcp-researchpowerpack
|
|
17
|
+
const WEBSITE_URL = "https://github.com/yigitkonur/mcp-researchpowerpack";
|
|
18
18
|
const LOCAL_DEFAULT_HOST = "127.0.0.1";
|
|
19
19
|
const startupLogger = Logger.get("startup");
|
|
20
20
|
function parseCsvEnv(value) {
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../index.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n\n// Expand libuv thread pool for parallel DNS lookups (default 4 is too low for 20+ concurrent connections)\nif (!process.env.UV_THREADPOOL_SIZE) {\n process.env.UV_THREADPOOL_SIZE = '8';\n}\n\nimport { Logger } from 'mcp-use';\nimport {\n InMemorySessionStore,\n InMemoryStreamManager,\n MCPServer,\n object,\n type ServerConfig,\n} from 'mcp-use/server';\n\nimport { SERVER } from './src/config/index.js';\nimport { getLLMHealth } from './src/services/llm-processor.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\nfunction buildSessionConfig(): {\n sessionConfig: Pick<ServerConfig, 'sessionStore' | 'streamManager'>;\n cleanupFns: CleanupFn[];\n} {\n return {\n sessionConfig: {\n sessionStore: new InMemorySessionStore(),\n streamManager: new InMemoryStreamManager(),\n },\n cleanupFns: [],\n };\n}\n\nfunction buildHealthPayload(server: MCPServer, startedAt: number) {\n const llm = getLLMHealth();\n // Distinguish \"never probed\" (checkedAt === null) from \"probed and failed\"\n // (checkedAt set, ok=false). The raw `lastPlannerOk` defaults to `false`\n // at startup, which would mislead operators into thinking the LLM is\n // broken before it has been exercised once.\n const plannerOkForHealth = llm.lastPlannerCheckedAt === null ? null : llm.lastPlannerOk;\n const extractorOkForHealth = llm.lastExtractorCheckedAt === null ? null : llm.lastExtractorOk;\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 llm_planner_ok: plannerOkForHealth,\n llm_extractor_ok: extractorOkForHealth,\n llm_planner_checked_at: llm.lastPlannerCheckedAt,\n llm_extractor_checked_at: llm.lastExtractorCheckedAt,\n llm_planner_error: llm.lastPlannerError,\n llm_extractor_error: llm.lastExtractorError,\n planner_configured: llm.plannerConfigured,\n extractor_configured: llm.extractorConfigured,\n // Counter surfacing lets operators diagnose gate behavior from outside\n // the process (see src/tools/start-research.ts for the gate semantics).\n consecutive_planner_failures: llm.consecutivePlannerFailures,\n consecutive_extractor_failures: llm.consecutiveExtractorFailures,\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 } = 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 if (!baseUrl) {\n startupLogger.error(\n 'Production mode requires ALLOWED_ORIGINS or MCP_URL to be set. ' +\n 'Without host validation, the server is vulnerable to DNS rebinding attacks. ' +\n 'Set ALLOWED_ORIGINS to the public deployment URL or custom domain.',\n );\n process.exit(1);\n }\n startupLogger.warn(\n 'Host validation is disabled because ALLOWED_ORIGINS is not set. ' +\n 'MCP_URL is set, so the server will start \u2014 but set ALLOWED_ORIGINS for full origin protection.',\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 // Advertise our LLM-augmentation capability via the MCP `experimental`\n // namespace so capability-aware clients can branch at initialize-time\n // instead of parsing per-call footers. mcp-use creates a fresh native MCP\n // server per session via `getServerForSession()`, so we patch that factory\n // to register our experimental capability on every session. The capability\n // values are read fresh on each session so health flips are observable.\n // See: docs/code-review/context/06-mcp-use-best-practices-primer.md (#3, #6).\n try {\n type Native = { server?: { registerCapabilities?: (caps: Record<string, unknown>) => void } };\n type Patched = { getServerForSession?: (sessionId?: string) => Native };\n const patched = server as unknown as Patched;\n const original = patched.getServerForSession?.bind(server);\n if (original) {\n patched.getServerForSession = (sessionId?: string): Native => {\n const native = original(sessionId);\n try {\n const llm = getLLMHealth();\n native.server?.registerCapabilities?.({\n experimental: {\n research_powerpack: {\n planner_available: llm.plannerConfigured,\n extractor_available: llm.extractorConfigured,\n planner_model: process.env.LLM_MODEL ?? null,\n extractor_model: process.env.LLM_MODEL ?? null,\n },\n },\n });\n } catch {\n // Capability registration is advisory; never block session creation.\n }\n return native;\n };\n }\n } catch (err) {\n startupLogger.warn(`Could not patch session-server factory: ${String(err)}`);\n }\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\n // Some MCP clients (Claude Desktop, Cursor, VS Code) proactively probe\n // /.well-known/oauth-protected-resource before receiving any 401, per the\n // MCP 2025-03-26 spec. Without these routes the server returns 404 and some\n // clients surface a spurious \"authentication required\" error. A minimal PRM\n // response with no authorization_servers field explicitly signals that this\n // server requires no authentication.\n const resourceBaseUrl = baseUrl ?? `http://${host}:${port}`;\n server.get('/.well-known/oauth-protected-resource', (c) =>\n c.json({ resource: resourceBaseUrl }),\n );\n server.get('/.well-known/oauth-protected-resource/mcp', (c) =>\n c.json({ resource: `${resourceBaseUrl}/mcp` }),\n );\n\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"],
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n\n// Expand libuv thread pool for parallel DNS lookups (default 4 is too low for 20+ concurrent connections)\nif (!process.env.UV_THREADPOOL_SIZE) {\n process.env.UV_THREADPOOL_SIZE = '8';\n}\n\nimport { Logger } from 'mcp-use';\nimport {\n InMemorySessionStore,\n InMemoryStreamManager,\n MCPServer,\n object,\n type ServerConfig,\n} from 'mcp-use/server';\n\nimport { SERVER } from './src/config/index.js';\nimport { getLLMHealth } from './src/services/llm-processor.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' 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\nfunction buildSessionConfig(): {\n sessionConfig: Pick<ServerConfig, 'sessionStore' | 'streamManager'>;\n cleanupFns: CleanupFn[];\n} {\n return {\n sessionConfig: {\n sessionStore: new InMemorySessionStore(),\n streamManager: new InMemoryStreamManager(),\n },\n cleanupFns: [],\n };\n}\n\nfunction buildHealthPayload(server: MCPServer, startedAt: number) {\n const llm = getLLMHealth();\n // Distinguish \"never probed\" (checkedAt === null) from \"probed and failed\"\n // (checkedAt set, ok=false). The raw `lastPlannerOk` defaults to `false`\n // at startup, which would mislead operators into thinking the LLM is\n // broken before it has been exercised once.\n const plannerOkForHealth = llm.lastPlannerCheckedAt === null ? null : llm.lastPlannerOk;\n const extractorOkForHealth = llm.lastExtractorCheckedAt === null ? null : llm.lastExtractorOk;\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 llm_planner_ok: plannerOkForHealth,\n llm_extractor_ok: extractorOkForHealth,\n llm_planner_checked_at: llm.lastPlannerCheckedAt,\n llm_extractor_checked_at: llm.lastExtractorCheckedAt,\n llm_planner_error: llm.lastPlannerError,\n llm_extractor_error: llm.lastExtractorError,\n planner_configured: llm.plannerConfigured,\n extractor_configured: llm.extractorConfigured,\n // Counter surfacing lets operators diagnose gate behavior from outside\n // the process (see src/tools/start-research.ts for the gate semantics).\n consecutive_planner_failures: llm.consecutivePlannerFailures,\n consecutive_extractor_failures: llm.consecutiveExtractorFailures,\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 } = 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 if (!baseUrl) {\n startupLogger.error(\n 'Production mode requires ALLOWED_ORIGINS or MCP_URL to be set. ' +\n 'Without host validation, the server is vulnerable to DNS rebinding attacks. ' +\n 'Set ALLOWED_ORIGINS to the public deployment URL or custom domain.',\n );\n process.exit(1);\n }\n startupLogger.warn(\n 'Host validation is disabled because ALLOWED_ORIGINS is not set. ' +\n 'MCP_URL is set, so the server will start \u2014 but set ALLOWED_ORIGINS for full origin protection.',\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 // Advertise our LLM-augmentation capability via the MCP `experimental`\n // namespace so capability-aware clients can branch at initialize-time\n // instead of parsing per-call footers. mcp-use creates a fresh native MCP\n // server per session via `getServerForSession()`, so we patch that factory\n // to register our experimental capability on every session. The capability\n // values are read fresh on each session so health flips are observable.\n // See: docs/code-review/context/06-mcp-use-best-practices-primer.md (#3, #6).\n try {\n type Native = { server?: { registerCapabilities?: (caps: Record<string, unknown>) => void } };\n type Patched = { getServerForSession?: (sessionId?: string) => Native };\n const patched = server as unknown as Patched;\n const original = patched.getServerForSession?.bind(server);\n if (original) {\n patched.getServerForSession = (sessionId?: string): Native => {\n const native = original(sessionId);\n try {\n const llm = getLLMHealth();\n native.server?.registerCapabilities?.({\n experimental: {\n research_powerpack: {\n planner_available: llm.plannerConfigured,\n extractor_available: llm.extractorConfigured,\n planner_model: process.env.LLM_MODEL ?? null,\n extractor_model: process.env.LLM_MODEL ?? null,\n },\n },\n });\n } catch {\n // Capability registration is advisory; never block session creation.\n }\n return native;\n };\n }\n } catch (err) {\n startupLogger.warn(`Could not patch session-server factory: ${String(err)}`);\n }\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\n // Some MCP clients (Claude Desktop, Cursor, VS Code) proactively probe\n // /.well-known/oauth-protected-resource before receiving any 401, per the\n // MCP 2025-03-26 spec. Without these routes the server returns 404 and some\n // clients surface a spurious \"authentication required\" error. A minimal PRM\n // response with no authorization_servers field explicitly signals that this\n // server requires no authentication.\n const resourceBaseUrl = baseUrl ?? `http://${host}:${port}`;\n server.get('/.well-known/oauth-protected-resource', (c) =>\n c.json({ resource: resourceBaseUrl }),\n );\n server.get('/.well-known/oauth-protected-resource/mcp', (c) =>\n c.json({ resource: `${resourceBaseUrl}/mcp` }),\n );\n\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
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/mcp-use.json
CHANGED