better-web-search-mcp 0.4.0 → 0.4.1
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 +72 -2
- package/dist/ranking/passages.d.ts +10 -0
- package/dist/ranking/passages.d.ts.map +1 -1
- package/dist/ranking/passages.js +47 -4
- package/dist/ranking/passages.js.map +1 -1
- package/mcp.json +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -72,15 +72,85 @@ Only escalates when needed. Results carry confidence scores so you know what you
|
|
|
72
72
|
|
|
73
73
|
**Self-learning cache.** The first visit to a domain takes the full path. The second visit skips straight to what worked. Domain profiles and API patterns are remembered.
|
|
74
74
|
|
|
75
|
+
## Token efficiency
|
|
76
|
+
|
|
77
|
+
Doing the web work inside the server, rather than handing pages to the model,
|
|
78
|
+
is the point. The repository ships the benchmark that checks it.
|
|
79
|
+
|
|
80
|
+
Same questions, same pages, two workflows:
|
|
81
|
+
|
|
82
|
+
- **baseline** — the agent drives the tools: one `web_search`, then
|
|
83
|
+
`web_extract` on each of the top 5 results. Every page lands in its context.
|
|
84
|
+
- **research** — one `web_research` call, returning cited passages.
|
|
85
|
+
|
|
86
|
+
12 questions across definition, technical, comparison, troubleshooting and
|
|
87
|
+
research categories, run 2026-09-02 against the live web with the browser tier
|
|
88
|
+
disabled:
|
|
89
|
+
|
|
90
|
+
| | Baseline | `web_research` |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| Payload | 820,229 chars | **110,973 chars** |
|
|
93
|
+
| Tokens (est. at 4 chars) | ~205,000 | **~28,000** |
|
|
94
|
+
| Wall clock | 137.3s | **49.6s** |
|
|
95
|
+
|
|
96
|
+
**86.5% less text overall, 83.8% median**, per-question range 56.8% to 93.4%.
|
|
97
|
+
|
|
98
|
+
Reproduce it yourself:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm run build && npm run bench
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Honest caveats, because these are the ones that matter:
|
|
105
|
+
|
|
106
|
+
- Payload is counted in **characters** — exact and tokenizer-independent. The
|
|
107
|
+
token column is an estimate at 4 chars/token for orientation; the *ratio* is
|
|
108
|
+
the real result and barely moves between tokenizers.
|
|
109
|
+
- **This measures payload, not answer quality.** Deciding whether the retained
|
|
110
|
+
passages still support a correct answer needs a judge model, which this
|
|
111
|
+
harness does not have. A smaller payload is only a win if the right text
|
|
112
|
+
survived; `query_term_coverage` is reported per question as a weak proxy and
|
|
113
|
+
is deliberately not folded into the headline number.
|
|
114
|
+
- Reduction tracks how much page text there was. The 56.8% case had a small
|
|
115
|
+
baseline (~20k chars), where the fixed cost of the response's source list
|
|
116
|
+
dominates.
|
|
117
|
+
- Live-web runs are not bit-reproducible: pages change and DuckDuckGo
|
|
118
|
+
rate-limits scrapers.
|
|
119
|
+
- No comparison against Exa, Tavily's answer endpoint, or hosted web search —
|
|
120
|
+
they cannot be run under identical conditions on the same pages.
|
|
121
|
+
|
|
122
|
+
Method and raw per-question results: [`benchmarks/`](benchmarks/).
|
|
123
|
+
|
|
124
|
+
## Security
|
|
125
|
+
|
|
126
|
+
Page content is attacker-controlled and URLs arrive from the calling agent, so
|
|
127
|
+
both are treated as untrusted.
|
|
128
|
+
|
|
129
|
+
- **SSRF guard.** Non-HTTP schemes are refused; hostnames are resolved and
|
|
130
|
+
private, loopback, link-local, CGNAT, multicast and reserved addresses
|
|
131
|
+
rejected — including IPv4-mapped IPv6 forms like `::ffff:127.0.0.1`.
|
|
132
|
+
Redirects are followed manually so *every hop* is re-checked, capped at 5.
|
|
133
|
+
- **Prompt-injection screening.** Every `web_extract` result carries a
|
|
134
|
+
`security` block marking content untrusted and flagging text that tries to
|
|
135
|
+
issue instructions to an agent, with the matched pattern and its offset.
|
|
136
|
+
Content is never rewritten, so extraction stays faithful to the source.
|
|
137
|
+
- **Source independence.** Pages are clustered by content before citing, so a
|
|
138
|
+
wire story republished by five outlets counts as one account rather than five
|
|
139
|
+
corroborating sources.
|
|
140
|
+
|
|
141
|
+
See [SECURITY.md](.github/SECURITY.md) for the full threat model.
|
|
142
|
+
|
|
75
143
|
## Project structure
|
|
76
144
|
|
|
77
145
|
```
|
|
78
146
|
src/
|
|
79
147
|
providers/ Search backends (DuckDuckGo, Brave, Tavily; SerpApi stubbed)
|
|
80
148
|
extraction/ 3-tier content pipeline (fetch, structured, browser)
|
|
81
|
-
ranking/ Deduplication, domain scoring, reranking
|
|
149
|
+
ranking/ Deduplication, domain scoring, reranking, passage selection,
|
|
150
|
+
source-independence clustering
|
|
82
151
|
tools/ MCP tool definitions (search, research, extract, find, news)
|
|
83
|
-
utils/ Config, caching, retry, query rewriting
|
|
152
|
+
utils/ Config, caching, retry, query rewriting, SSRF guard
|
|
153
|
+
benchmarks/ Token-efficiency harness and results
|
|
84
154
|
```
|
|
85
155
|
|
|
86
156
|
## Configuration
|
|
@@ -28,6 +28,16 @@ export interface Passage {
|
|
|
28
28
|
}
|
|
29
29
|
/** Target passage size in characters; paragraphs are packed up to this. */
|
|
30
30
|
export declare const TARGET_PASSAGE_CHARS = 500;
|
|
31
|
+
/**
|
|
32
|
+
* Hard ceiling on a single passage, in characters.
|
|
33
|
+
*
|
|
34
|
+
* Paragraph splitting alone is not enough: plenty of extracted pages contain
|
|
35
|
+
* no blank lines at all, which made the whole page one passage. A cited
|
|
36
|
+
* "passage" was then the entire document, and `web_research` returned more
|
|
37
|
+
* text than reading the pages directly would have. Anything longer than this
|
|
38
|
+
* is windowed on sentence boundaries.
|
|
39
|
+
*/
|
|
40
|
+
export declare const MAX_PASSAGE_CHARS = 1200;
|
|
31
41
|
/** Lowercase alphanumeric tokens, stop words removed. */
|
|
32
42
|
export declare function tokenize(text: string): string[];
|
|
33
43
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"passages.d.ts","sourceRoot":"","sources":["../../src/ranking/passages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,+CAA+C;AAC/C,MAAM,WAAW,OAAO;IACtB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;CACf;AAMD,2EAA2E;AAC3E,eAAO,MAAM,oBAAoB,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"passages.d.ts","sourceRoot":"","sources":["../../src/ranking/passages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,+CAA+C;AAC/C,MAAM,WAAW,OAAO;IACtB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;CACf;AAMD,2EAA2E;AAC3E,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,OAAQ,CAAC;AAUvC,yDAAyD;AACzD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAG/C;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,EAAE,CAyExD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,KAAK,EAAE,MAAM,GACZ,OAAO,EAAE,CAqDX;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,KAAK,SAAI,GACR,OAAO,EAAE,CAEX"}
|
package/dist/ranking/passages.js
CHANGED
|
@@ -20,6 +20,16 @@ const K1 = 1.5;
|
|
|
20
20
|
const B = 0.75;
|
|
21
21
|
/** Target passage size in characters; paragraphs are packed up to this. */
|
|
22
22
|
export const TARGET_PASSAGE_CHARS = 500;
|
|
23
|
+
/**
|
|
24
|
+
* Hard ceiling on a single passage, in characters.
|
|
25
|
+
*
|
|
26
|
+
* Paragraph splitting alone is not enough: plenty of extracted pages contain
|
|
27
|
+
* no blank lines at all, which made the whole page one passage. A cited
|
|
28
|
+
* "passage" was then the entire document, and `web_research` returned more
|
|
29
|
+
* text than reading the pages directly would have. Anything longer than this
|
|
30
|
+
* is windowed on sentence boundaries.
|
|
31
|
+
*/
|
|
32
|
+
export const MAX_PASSAGE_CHARS = 1_200;
|
|
23
33
|
/** Words carrying no retrieval signal, skipped when scoring. */
|
|
24
34
|
const STOP_WORDS = new Set([
|
|
25
35
|
"a", "an", "and", "are", "as", "at", "be", "but", "by", "for", "from",
|
|
@@ -46,11 +56,44 @@ export function splitPassages(content) {
|
|
|
46
56
|
let bufferStart = -1;
|
|
47
57
|
let bufferEnd = -1;
|
|
48
58
|
let buffer = "";
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
const emit = (text, start, end) => {
|
|
60
|
+
if (text.trim() === "") {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (text.length <= MAX_PASSAGE_CHARS) {
|
|
64
|
+
passages.push({ text: text.trim(), start, end, score: 0 });
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// Window an over-long block on sentence boundaries, keeping offsets
|
|
68
|
+
// accurate by tracking position in the original string.
|
|
69
|
+
let windowStart = 0;
|
|
70
|
+
while (windowStart < text.length) {
|
|
71
|
+
let windowEnd = Math.min(windowStart + MAX_PASSAGE_CHARS, text.length);
|
|
72
|
+
if (windowEnd < text.length) {
|
|
73
|
+
// Prefer the last sentence end inside the window; fall back to a
|
|
74
|
+
// space so words are never cut in half.
|
|
75
|
+
const slice = text.slice(windowStart, windowEnd);
|
|
76
|
+
const sentence = slice.lastIndexOf(". ");
|
|
77
|
+
const space = slice.lastIndexOf(" ");
|
|
78
|
+
const cut = sentence > MAX_PASSAGE_CHARS / 2 ? sentence + 1 : space;
|
|
79
|
+
if (cut > 0) {
|
|
80
|
+
windowEnd = windowStart + cut;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const chunk = text.slice(windowStart, windowEnd);
|
|
84
|
+
if (chunk.trim() !== "") {
|
|
85
|
+
passages.push({
|
|
86
|
+
text: chunk.trim(),
|
|
87
|
+
start: start + windowStart,
|
|
88
|
+
end: start + windowEnd,
|
|
89
|
+
score: 0,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
windowStart = windowEnd;
|
|
53
93
|
}
|
|
94
|
+
};
|
|
95
|
+
const flush = () => {
|
|
96
|
+
emit(buffer, bufferStart, bufferEnd);
|
|
54
97
|
buffer = "";
|
|
55
98
|
bufferStart = -1;
|
|
56
99
|
bufferEnd = -1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"passages.js","sourceRoot":"","sources":["../../src/ranking/passages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAcH,oDAAoD;AACpD,MAAM,EAAE,GAAG,GAAG,CAAC;AACf,MAAM,CAAC,GAAG,IAAI,CAAC;AAEf,2EAA2E;AAC3E,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAExC,gEAAgE;AAChE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC;IACzB,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM;IACrE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG;IACzE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAC5E,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAC5C,CAAC,CAAC;AAEH,yDAAyD;AACzD,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;IAC7D,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,+BAA+B,CAAC;IAEpD,IAAI,WAAW,GAAG,CAAC,CAAC,CAAC;IACrB,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC;IACnB,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,MAAM,KAAK,GAAG,
|
|
1
|
+
{"version":3,"file":"passages.js","sourceRoot":"","sources":["../../src/ranking/passages.ts"],"names":[],"mappings":"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"}
|
package/mcp.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "better-web-search-mcp",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "MCP server for genuinely better web research — keyless-first (DuckDuckGo), 3-tier extraction, deep research. Brave/Tavily optional.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"release:minor": "npm run version:minor && git push --follow-tags",
|
|
52
52
|
"release:major": "npm run version:major && git push --follow-tags",
|
|
53
53
|
"check:publish": "npm pack --dry-run",
|
|
54
|
+
"bench": "node benchmarks/run.mjs",
|
|
54
55
|
"docs:api": "typedoc --options typedoc.json && node scripts/typedoc-postprocess.mjs",
|
|
55
56
|
"docs:changelog": "node scripts/sync-docs-changelog.mjs",
|
|
56
57
|
"docs:build": "npm run docs:api && npm run docs:changelog && hugo --source site --gc --minify",
|