better-web-search-mcp 0.2.1 → 0.2.3
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 +112 -112
- package/dist/index.js +32 -32
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +16 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/utils/cache.d.ts +3 -3
- package/dist/utils/cache.d.ts.map +1 -1
- package/dist/utils/cache.js +36 -11
- package/dist/utils/cache.js.map +1 -1
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +0 -6
- package/dist/utils/config.js.map +1 -1
- package/mcp.json +5 -2
- package/package.json +5 -4
- package/scripts/sync-mcp-version.mjs +31 -0
package/README.md
CHANGED
|
@@ -1,112 +1,112 @@
|
|
|
1
|
-
# BetterWebSearch MCP
|
|
2
|
-
|
|
3
|
-
> Keyless-first web search for AI agents. DuckDuckGo works out of the box. No API keys.
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/better-web-search-mcp)
|
|
6
|
-
[](https://github.com/PhantomPixelDev/BetterWebSearch-MCP/actions)
|
|
7
|
-
[](https://phantompixeldev.github.io/BetterWebSearch-MCP/)
|
|
8
|
-
[](LICENSE)
|
|
9
|
-
[](https://smithery.ai/server/@PhantomPixelDev/better-web-search-mcp)
|
|
10
|
-
|
|
11
|
-
<p align="center">
|
|
12
|
-
<img src="./images/banner.jpg" alt="BetterWebSearch MCP — Smarter Web Search · Better Data Extraction · Flexible & Extensible · Open Source" width="100%">
|
|
13
|
-
</p>
|
|
14
|
-
|
|
15
|
-
## What is this?
|
|
16
|
-
|
|
17
|
-
BetterWebSearch MCP is a [Model Context Protocol](https://modelcontextprotocol.io) server that gives AI assistants genuinely better web research. It works without API keys by default (DuckDuckGo), and optionally adds Brave or Tavily for richer ranking and recency.
|
|
18
|
-
|
|
19
|
-
Built for anyone who wants their AI tools to find things on the web reliably, not just when a paid API key is configured.
|
|
20
|
-
|
|
21
|
-
## Quick start (30 seconds)
|
|
22
|
-
|
|
23
|
-
Add this to your MCP client config (Claude Desktop, Cursor, VS Code Copilot, OpenCode, or any MCP client):
|
|
24
|
-
|
|
25
|
-
```json
|
|
26
|
-
{
|
|
27
|
-
"mcpServers": {
|
|
28
|
-
"better-web-search-mcp": {
|
|
29
|
-
"command": "npx",
|
|
30
|
-
"args": ["-y", "better-web-search-mcp"]
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
That's it. Every search tool works immediately. No `.env`, no API keys, no setup.
|
|
37
|
-
|
|
38
|
-
Or run it directly:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npx -y better-web-search-mcp --help
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## Tools
|
|
45
|
-
|
|
46
|
-
| Tool | What it does |
|
|
47
|
-
|---|---|
|
|
48
|
-
| `web_search` | Aggregated search across providers, deduplicated and reranked |
|
|
49
|
-
| `web_research` | Deep research. Rewrites your question, searches in parallel, extracts top results with citations |
|
|
50
|
-
| `deep_search` | Alias for `web_research` |
|
|
51
|
-
| `web_extract` | Extracts clean content from any URL, using the best method available |
|
|
52
|
-
| `web_find` | Search scoped to a single website |
|
|
53
|
-
| `web_news` | Recent news with timeline and diversity filtering |
|
|
54
|
-
|
|
55
|
-
## How search is better
|
|
56
|
-
|
|
57
|
-
Standard MCP search tools hit one API and return raw results. BetterWebSearch takes a different approach.
|
|
58
|
-
|
|
59
|
-
**Query expansion.** Your single question gets rewritten into 4 to 6 variants, searched in parallel. "Unlimited mobile internet Germany" also searches for "unbegrenztes Datenvolumen Deutschland" and similar phrasings. More coverage without you doing extra work.
|
|
60
|
-
|
|
61
|
-
**Three-tier extraction.** When it fetches a page, it doesn't just grab the HTML and hope for the best:
|
|
62
|
-
|
|
63
|
-
```
|
|
64
|
-
Tier 1: Fast HTTP fetch (< 1s)
|
|
65
|
-
↓ if not enough content
|
|
66
|
-
Tier 2: Structured data (JSON-LD, __NEXT_DATA__, __NUXT__) (1-3s)
|
|
67
|
-
↓ if still not enough
|
|
68
|
-
Tier 3: Playwright browser (full render + API interception) (3-10s)
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Only escalates when needed. Results carry confidence scores so you know what you're getting.
|
|
72
|
-
|
|
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
|
-
|
|
75
|
-
## Project structure
|
|
76
|
-
|
|
77
|
-
```
|
|
78
|
-
src/
|
|
79
|
-
providers/ Search backends (DuckDuckGo, Brave, Tavily; SerpApi stubbed)
|
|
80
|
-
extraction/ 3-tier content pipeline (fetch, structured, browser)
|
|
81
|
-
ranking/ Deduplication, domain scoring, reranking
|
|
82
|
-
tools/ MCP tool definitions (search, research, extract, find, news)
|
|
83
|
-
utils/ Config, caching, retry, query rewriting
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
## Configuration
|
|
87
|
-
|
|
88
|
-
All configuration is optional. DuckDuckGo works with zero setup.
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
# Optional: add more providers
|
|
92
|
-
BRAVE_API_KEY=your_key # Better ranking and recency
|
|
93
|
-
TAVILY_API_KEY=your_key # Alternative provider
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
See the [full configuration reference](https://phantompixeldev.github.io/BetterWebSearch-MCP/docs/configuration/) for all options including cache paths, browser settings, and environment variable names.
|
|
97
|
-
|
|
98
|
-
## Documentation
|
|
99
|
-
|
|
100
|
-
Full guides, API reference, and architecture details live on the docs site:
|
|
101
|
-
|
|
102
|
-
**[phantompixeldev.github.io/BetterWebSearch-MCP](https://phantompixeldev.github.io/BetterWebSearch-MCP/)**
|
|
103
|
-
|
|
104
|
-
- [Installation](https://phantompixeldev.github.io/BetterWebSearch-MCP/docs/installation/) - npx, npm, or from source
|
|
105
|
-
- [Quick Start](https://phantompixeldev.github.io/BetterWebSearch-MCP/docs/quickstart/) - Get running in your first AI client
|
|
106
|
-
- [Configuration](https://phantompixeldev.github.io/BetterWebSearch-MCP/docs/configuration/) - All environment variables and options
|
|
107
|
-
- [Contributing](https://phantompixeldev.github.io/BetterWebSearch-MCP/docs/contributing/) - Development setup and PR process
|
|
108
|
-
- [Changelog](CHANGELOG.md) - Release history and version notes
|
|
109
|
-
|
|
110
|
-
## License
|
|
111
|
-
|
|
112
|
-
MIT
|
|
1
|
+
# BetterWebSearch MCP
|
|
2
|
+
|
|
3
|
+
> Keyless-first web search for AI agents. DuckDuckGo works out of the box. No API keys.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/better-web-search-mcp)
|
|
6
|
+
[](https://github.com/PhantomPixelDev/BetterWebSearch-MCP/actions)
|
|
7
|
+
[](https://phantompixeldev.github.io/BetterWebSearch-MCP/)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://smithery.ai/server/@PhantomPixelDev/better-web-search-mcp)
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<img src="./images/banner.jpg" alt="BetterWebSearch MCP — Smarter Web Search · Better Data Extraction · Flexible & Extensible · Open Source" width="100%">
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
## What is this?
|
|
16
|
+
|
|
17
|
+
BetterWebSearch MCP is a [Model Context Protocol](https://modelcontextprotocol.io) server that gives AI assistants genuinely better web research. It works without API keys by default (DuckDuckGo), and optionally adds Brave or Tavily for richer ranking and recency.
|
|
18
|
+
|
|
19
|
+
Built for anyone who wants their AI tools to find things on the web reliably, not just when a paid API key is configured.
|
|
20
|
+
|
|
21
|
+
## Quick start (30 seconds)
|
|
22
|
+
|
|
23
|
+
Add this to your MCP client config (Claude Desktop, Cursor, VS Code Copilot, OpenCode, or any MCP client):
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"better-web-search-mcp": {
|
|
29
|
+
"command": "npx",
|
|
30
|
+
"args": ["-y", "better-web-search-mcp"]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
That's it. Every search tool works immediately. No `.env`, no API keys, no setup.
|
|
37
|
+
|
|
38
|
+
Or run it directly:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx -y better-web-search-mcp --help
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Tools
|
|
45
|
+
|
|
46
|
+
| Tool | What it does |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `web_search` | Aggregated search across providers, deduplicated and reranked |
|
|
49
|
+
| `web_research` | Deep research. Rewrites your question, searches in parallel, extracts top results with citations |
|
|
50
|
+
| `deep_search` | Alias for `web_research` |
|
|
51
|
+
| `web_extract` | Extracts clean content from any URL, using the best method available |
|
|
52
|
+
| `web_find` | Search scoped to a single website |
|
|
53
|
+
| `web_news` | Recent news with timeline and diversity filtering |
|
|
54
|
+
|
|
55
|
+
## How search is better
|
|
56
|
+
|
|
57
|
+
Standard MCP search tools hit one API and return raw results. BetterWebSearch takes a different approach.
|
|
58
|
+
|
|
59
|
+
**Query expansion.** Your single question gets rewritten into 4 to 6 variants, searched in parallel. "Unlimited mobile internet Germany" also searches for "unbegrenztes Datenvolumen Deutschland" and similar phrasings. More coverage without you doing extra work.
|
|
60
|
+
|
|
61
|
+
**Three-tier extraction.** When it fetches a page, it doesn't just grab the HTML and hope for the best:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
Tier 1: Fast HTTP fetch (< 1s)
|
|
65
|
+
↓ if not enough content
|
|
66
|
+
Tier 2: Structured data (JSON-LD, __NEXT_DATA__, __NUXT__) (1-3s)
|
|
67
|
+
↓ if still not enough
|
|
68
|
+
Tier 3: Playwright browser (full render + API interception) (3-10s)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Only escalates when needed. Results carry confidence scores so you know what you're getting.
|
|
72
|
+
|
|
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
|
+
|
|
75
|
+
## Project structure
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
src/
|
|
79
|
+
providers/ Search backends (DuckDuckGo, Brave, Tavily; SerpApi stubbed)
|
|
80
|
+
extraction/ 3-tier content pipeline (fetch, structured, browser)
|
|
81
|
+
ranking/ Deduplication, domain scoring, reranking
|
|
82
|
+
tools/ MCP tool definitions (search, research, extract, find, news)
|
|
83
|
+
utils/ Config, caching, retry, query rewriting
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Configuration
|
|
87
|
+
|
|
88
|
+
All configuration is optional. DuckDuckGo works with zero setup.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Optional: add more providers
|
|
92
|
+
BRAVE_API_KEY=your_key # Better ranking and recency
|
|
93
|
+
TAVILY_API_KEY=your_key # Alternative provider
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
See the [full configuration reference](https://phantompixeldev.github.io/BetterWebSearch-MCP/docs/configuration/) for all options including cache paths, browser settings, and environment variable names.
|
|
97
|
+
|
|
98
|
+
## Documentation
|
|
99
|
+
|
|
100
|
+
Full guides, API reference, and architecture details live on the docs site:
|
|
101
|
+
|
|
102
|
+
**[phantompixeldev.github.io/BetterWebSearch-MCP](https://phantompixeldev.github.io/BetterWebSearch-MCP/)**
|
|
103
|
+
|
|
104
|
+
- [Installation](https://phantompixeldev.github.io/BetterWebSearch-MCP/docs/installation/) - npx, npm, or from source
|
|
105
|
+
- [Quick Start](https://phantompixeldev.github.io/BetterWebSearch-MCP/docs/quickstart/) - Get running in your first AI client
|
|
106
|
+
- [Configuration](https://phantompixeldev.github.io/BetterWebSearch-MCP/docs/configuration/) - All environment variables and options
|
|
107
|
+
- [Contributing](https://phantompixeldev.github.io/BetterWebSearch-MCP/docs/contributing/) - Development setup and PR process
|
|
108
|
+
- [Changelog](CHANGELOG.md) - Release history and version notes
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -10,38 +10,38 @@ import { formatBanner, loadConfig } from "./utils/config.js";
|
|
|
10
10
|
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
11
11
|
const pkg = JSON.parse(readFileSync(join(currentDir, "..", "package.json"), "utf8"));
|
|
12
12
|
function printHelp() {
|
|
13
|
-
const help = `${pkg.name} v${pkg.version} — BetterWebSearch MCP
|
|
14
|
-
A self-learning web-access engine for AI agents. Keyless by default via DuckDuckGo.
|
|
15
|
-
|
|
16
|
-
Usage:
|
|
17
|
-
better-web-search-mcp [--help] [--version]
|
|
18
|
-
|
|
19
|
-
Tools (6):
|
|
20
|
-
web_search Fast search (keyless by default, Brave/Tavily if keys present)
|
|
21
|
-
web_research Deep multi-query research (rewrites question, ranks, extracts)
|
|
22
|
-
deep_search Alias for web_research
|
|
23
|
-
web_extract Clean article extraction (HTTP → hydration → browser)
|
|
24
|
-
web_find Site-restricted search (site:example.com query)
|
|
25
|
-
web_news Recent news with timeline & source diversity
|
|
26
|
-
|
|
27
|
-
Env (all optional — keyless works out of the box):
|
|
28
|
-
BRAVE_API_KEY / BETTER_WEB_SEARCH_BRAVE_API_KEY Brave Search API key
|
|
29
|
-
TAVILY_API_KEY / BETTER_WEB_SEARCH_TAVILY_API_KEY Tavily API key
|
|
30
|
-
BETTER_WEB_SEARCH_DISABLE_CACHE=true Disable SQLite cache
|
|
31
|
-
BETTER_WEB_SEARCH_CACHE_PATH=./data/cache.db Custom cache path
|
|
32
|
-
BETTER_WEB_SEARCH_DISABLE_BROWSER=true Disable Playwright fallback
|
|
33
|
-
|
|
34
|
-
Examples:
|
|
35
|
-
npx better-web-search-mcp # keyless (DuckDuckGo)
|
|
36
|
-
BRAVE_API_KEY=... npx better-web-search-mcp # with Brave
|
|
37
|
-
better-web-search-mcp --help
|
|
38
|
-
better-web-search-mcp --version
|
|
39
|
-
|
|
40
|
-
MCP config (Claude Desktop / Cursor / VS Code Copilot):
|
|
41
|
-
{"mcpServers":{"better-web-search-mcp":{"command":"npx","args":["-y","better-web-search-mcp"]}}}
|
|
42
|
-
With Brave: {"mcpServers":{"better-web-search-mcp":{"command":"npx","args":["-y","better-web-search-mcp"],"env":{"BRAVE_API_KEY":"..."}}}}
|
|
43
|
-
|
|
44
|
-
See README.md and mcp.json for full client examples.
|
|
13
|
+
const help = `${pkg.name} v${pkg.version} — BetterWebSearch MCP
|
|
14
|
+
A self-learning web-access engine for AI agents. Keyless by default via DuckDuckGo.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
better-web-search-mcp [--help] [--version]
|
|
18
|
+
|
|
19
|
+
Tools (6):
|
|
20
|
+
web_search Fast search (keyless by default, Brave/Tavily if keys present)
|
|
21
|
+
web_research Deep multi-query research (rewrites question, ranks, extracts)
|
|
22
|
+
deep_search Alias for web_research
|
|
23
|
+
web_extract Clean article extraction (HTTP → hydration → browser)
|
|
24
|
+
web_find Site-restricted search (site:example.com query)
|
|
25
|
+
web_news Recent news with timeline & source diversity
|
|
26
|
+
|
|
27
|
+
Env (all optional — keyless works out of the box):
|
|
28
|
+
BRAVE_API_KEY / BETTER_WEB_SEARCH_BRAVE_API_KEY Brave Search API key
|
|
29
|
+
TAVILY_API_KEY / BETTER_WEB_SEARCH_TAVILY_API_KEY Tavily API key
|
|
30
|
+
BETTER_WEB_SEARCH_DISABLE_CACHE=true Disable SQLite cache
|
|
31
|
+
BETTER_WEB_SEARCH_CACHE_PATH=./data/cache.db Custom cache path
|
|
32
|
+
BETTER_WEB_SEARCH_DISABLE_BROWSER=true Disable Playwright fallback
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
npx better-web-search-mcp # keyless (DuckDuckGo)
|
|
36
|
+
BRAVE_API_KEY=... npx better-web-search-mcp # with Brave
|
|
37
|
+
better-web-search-mcp --help
|
|
38
|
+
better-web-search-mcp --version
|
|
39
|
+
|
|
40
|
+
MCP config (Claude Desktop / Cursor / VS Code Copilot):
|
|
41
|
+
{"mcpServers":{"better-web-search-mcp":{"command":"npx","args":["-y","better-web-search-mcp"]}}}
|
|
42
|
+
With Brave: {"mcpServers":{"better-web-search-mcp":{"command":"npx","args":["-y","better-web-search-mcp"],"env":{"BRAVE_API_KEY":"..."}}}}
|
|
43
|
+
|
|
44
|
+
See README.md and mcp.json for full client examples.
|
|
45
45
|
`;
|
|
46
46
|
process.stdout.write(help);
|
|
47
47
|
}
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { Cache } from "../utils/cache.js";
|
|
3
|
+
import { type AppConfig } from "../utils/config.js";
|
|
3
4
|
/**
|
|
4
5
|
* Registers all MCP tools on the given server.
|
|
5
6
|
*
|
|
@@ -7,5 +8,14 @@ import { Cache } from "../utils/cache.js";
|
|
|
7
8
|
* and handler onto the server. A shared cache instance is passed through so
|
|
8
9
|
* search/news/find results are cached across calls.
|
|
9
10
|
*/
|
|
11
|
+
/**
|
|
12
|
+
* Build the shared cache from configuration.
|
|
13
|
+
*
|
|
14
|
+
* `BETTER_WEB_SEARCH_DISABLE_CACHE` and `BETTER_WEB_SEARCH_CACHE_PATH` were
|
|
15
|
+
* parsed by the config loader and printed in the startup banner, but nothing
|
|
16
|
+
* ever passed them to the Cache: the server opened `data/cache.db` no matter
|
|
17
|
+
* what either said. Both are honored here.
|
|
18
|
+
*/
|
|
19
|
+
export declare function cacheFromConfig(cfg?: AppConfig): Cache;
|
|
10
20
|
export declare function registerTools(server: McpServer, cache?: Cache): void;
|
|
11
21
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAOhE;;;;;;GAMG;AAEH;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,SAAwB,GAAG,KAAK,CAKpE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAOpE"}
|
package/dist/tools/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Cache } from "../utils/cache.js";
|
|
2
|
+
import { loadConfig } from "../utils/config.js";
|
|
2
3
|
import { registerSearch } from "./search.js";
|
|
3
4
|
import { registerExtract } from "./extract.js";
|
|
4
5
|
import { registerFind } from "./find.js";
|
|
@@ -11,8 +12,22 @@ import { registerResearch } from "./research.js";
|
|
|
11
12
|
* and handler onto the server. A shared cache instance is passed through so
|
|
12
13
|
* search/news/find results are cached across calls.
|
|
13
14
|
*/
|
|
15
|
+
/**
|
|
16
|
+
* Build the shared cache from configuration.
|
|
17
|
+
*
|
|
18
|
+
* `BETTER_WEB_SEARCH_DISABLE_CACHE` and `BETTER_WEB_SEARCH_CACHE_PATH` were
|
|
19
|
+
* parsed by the config loader and printed in the startup banner, but nothing
|
|
20
|
+
* ever passed them to the Cache: the server opened `data/cache.db` no matter
|
|
21
|
+
* what either said. Both are honored here.
|
|
22
|
+
*/
|
|
23
|
+
export function cacheFromConfig(cfg = loadConfig()) {
|
|
24
|
+
if (!cfg.cacheEnabled) {
|
|
25
|
+
return new Cache({ memory: true });
|
|
26
|
+
}
|
|
27
|
+
return new Cache({ dbPath: cfg.cachePath });
|
|
28
|
+
}
|
|
14
29
|
export function registerTools(server, cache) {
|
|
15
|
-
const sharedCache = cache ??
|
|
30
|
+
const sharedCache = cache ?? cacheFromConfig();
|
|
16
31
|
registerSearch(server, sharedCache);
|
|
17
32
|
registerExtract(server, sharedCache);
|
|
18
33
|
registerFind(server, sharedCache);
|
package/dist/tools/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,MAAiB,EAAE,KAAa;IAC5D,MAAM,WAAW,GAAG,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAkB,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;;;GAMG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,MAAiB,UAAU,EAAE;IAC3D,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACtB,OAAO,IAAI,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAiB,EAAE,KAAa;IAC5D,MAAM,WAAW,GAAG,KAAK,IAAI,eAAe,EAAE,CAAC;IAC/C,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,eAAe,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACrC,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClC,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClC,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AACxC,CAAC"}
|
package/dist/utils/cache.d.ts
CHANGED
|
@@ -14,9 +14,9 @@ export type { ApiPattern, CacheOptions, PageCacheEntry } from "./cacheTypes.js";
|
|
|
14
14
|
* A cache for search results, pages, API patterns, and domain profiles.
|
|
15
15
|
*
|
|
16
16
|
* Prefers a SQLite database at `data/cache.db` (WAL mode, auto-created
|
|
17
|
-
* directory). When better-sqlite3 cannot be loaded,
|
|
18
|
-
*
|
|
19
|
-
* the same TTL semantics.
|
|
17
|
+
* directory). When better-sqlite3 cannot be loaded, when opening the
|
|
18
|
+
* database fails, or when `memory: true` is passed, every method
|
|
19
|
+
* transparently operates on an in-memory Map with the same TTL semantics.
|
|
20
20
|
*/
|
|
21
21
|
export declare class Cache {
|
|
22
22
|
private readonly db;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EACV,UAAU,EACV,YAAY,EACZ,cAAc,EACf,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EACV,UAAU,EACV,YAAY,EACZ,cAAc,EACf,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA6FhF;;;;;;;GAOG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAwB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;gBAEzB,IAAI,GAAE,YAAiB;IAoBnC,qEAAqE;IACrE,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,4DAA4D;IAC5D,KAAK,IAAI,IAAI;IASb,0EAA0E;IAC1E,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;IAgBtC,0EAA0E;IAC1E,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAmB7D,4DAA4D;IAC5D,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAmB3C,gEAAgE;IAChE,OAAO,CACL,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,EACxB,UAAU,EAAE,MAAM,GACjB,IAAI;IAoBP,kEAAkE;IAClE,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;IAazC,0EAA0E;IAC1E,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAkBjD,6DAA6D;IAC7D,aAAa,CACX,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,IAAI;IAcP,mEAAmE;IACnE,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE;IAc5C,0DAA0D;IAC1D,YAAY,IAAI,IAAI;CAarB"}
|
package/dist/utils/cache.js
CHANGED
|
@@ -64,21 +64,52 @@ function loadDatabase() {
|
|
|
64
64
|
return null;
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Open and initialize the SQLite database for a cache instance.
|
|
69
|
+
*
|
|
70
|
+
* Returns `null` whenever the caller should use the in-memory backend
|
|
71
|
+
* instead: `memory: true` was requested, better-sqlite3 could not be loaded,
|
|
72
|
+
* or opening the file failed. That last case matters in production — a
|
|
73
|
+
* locked, corrupt, or unwritable `data/cache.db` used to throw straight out
|
|
74
|
+
* of the constructor and take the whole MCP server down at boot. Directory
|
|
75
|
+
* creation sits inside the guard too, since a read-only or permission-denied
|
|
76
|
+
* path fails there rather than in the driver.
|
|
77
|
+
*/
|
|
78
|
+
function openDatabase(opts) {
|
|
79
|
+
const Database = loadDatabase();
|
|
80
|
+
if (opts.memory === true || Database === null) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
const dbPath = opts.dbPath ?? "data/cache.db";
|
|
84
|
+
try {
|
|
85
|
+
mkdirSync(dirname(dbPath), { recursive: true });
|
|
86
|
+
const db = new Database(dbPath);
|
|
87
|
+
db.pragma("journal_mode = WAL");
|
|
88
|
+
db.pragma("busy_timeout = 5000");
|
|
89
|
+
db.exec(SCHEMA);
|
|
90
|
+
return db;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
94
|
+
console.error(`[cache] SQLite init failed (${reason}); falling back to the in-memory cache`);
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
67
98
|
/**
|
|
68
99
|
* A cache for search results, pages, API patterns, and domain profiles.
|
|
69
100
|
*
|
|
70
101
|
* Prefers a SQLite database at `data/cache.db` (WAL mode, auto-created
|
|
71
|
-
* directory). When better-sqlite3 cannot be loaded,
|
|
72
|
-
*
|
|
73
|
-
* the same TTL semantics.
|
|
102
|
+
* directory). When better-sqlite3 cannot be loaded, when opening the
|
|
103
|
+
* database fails, or when `memory: true` is passed, every method
|
|
104
|
+
* transparently operates on an in-memory Map with the same TTL semantics.
|
|
74
105
|
*/
|
|
75
106
|
export class Cache {
|
|
76
107
|
db;
|
|
77
108
|
memory;
|
|
78
109
|
memoryMode;
|
|
79
110
|
constructor(opts = {}) {
|
|
80
|
-
const
|
|
81
|
-
if (
|
|
111
|
+
const db = openDatabase(opts);
|
|
112
|
+
if (db === null) {
|
|
82
113
|
this.memoryMode = true;
|
|
83
114
|
this.db = null;
|
|
84
115
|
this.memory = new MemoryCache();
|
|
@@ -86,12 +117,6 @@ export class Cache {
|
|
|
86
117
|
}
|
|
87
118
|
this.memoryMode = false;
|
|
88
119
|
this.memory = null;
|
|
89
|
-
const dbPath = opts.dbPath ?? "data/cache.db";
|
|
90
|
-
mkdirSync(dirname(dbPath), { recursive: true });
|
|
91
|
-
const db = new Database(dbPath);
|
|
92
|
-
db.pragma("journal_mode = WAL");
|
|
93
|
-
db.pragma("busy_timeout = 5000");
|
|
94
|
-
db.exec(SCHEMA);
|
|
95
120
|
this.db = db;
|
|
96
121
|
// Best-effort startup prune; empty catch is intentional — never block boot.
|
|
97
122
|
try {
|
package/dist/utils/cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAM/C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG7D,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAO/C,+CAA+C;AAC/C,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8Bd,CAAC;AAEF,2DAA2D;AAC3D,SAAS,YAAY,CAAC,GAAW;IAC/B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,SAAS,YAAY;IACnB,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,gBAAgB,CAAmB,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuBH,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,UAAU,IAAI,SAAS,CA0BtC;AAED,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,SAAS,GAAG,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuBH,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,UAAU,IAAI,SAAS,CA0BtC;AAED,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,SAAS,GAAG,cAAc,EAAE,CAqBjE;AAED,wBAAgB,YAAY,CAC1B,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EACtC,GAAG,EAAE,SAAS,GACb,MAAM,CAgBR"}
|
package/dist/utils/config.js
CHANGED
|
@@ -64,12 +64,6 @@ export function providerStatuses(cfg) {
|
|
|
64
64
|
keyless: false,
|
|
65
65
|
hint: cfg.tavilyApiKey ? "enabled" : "optional — set TAVILY_API_KEY",
|
|
66
66
|
},
|
|
67
|
-
{
|
|
68
|
-
name: "serpapi",
|
|
69
|
-
enabled: false,
|
|
70
|
-
keyless: false,
|
|
71
|
-
hint: "stub — not yet implemented",
|
|
72
|
-
},
|
|
73
67
|
];
|
|
74
68
|
}
|
|
75
69
|
export function formatBanner(pkg, cfg) {
|
package/dist/utils/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,GAA6B;IAC5C,aAAa,EAAE,CAAC,iCAAiC,EAAE,sBAAsB,CAAC;IAC1E,cAAc,EAAE,CAAC,kCAAkC,CAAC;IACpD,WAAW,EAAE,CAAC,+BAA+B,EAAE,cAAc,CAAC;CAC/D,CAAC;AAEF,SAAS,YAAY,CAAC,KAAe;IACnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC/C,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,OAAO,CAAC,SAAiB;IAChC,MAAM,OAAO,GAAG,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IAC7C,OAAO,YAAY,CAAC,CAAC,SAAS,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;AAC/C,CAAC;AAWD,MAAM,UAAU,UAAU;IACxB,MAAM,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAC7C,MAAM,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE1C,MAAM,YAAY,GAChB,CAAC,OAAO,CAAC,GAAG,CAAC,+BAA+B,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM;QAC5E,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC;IAE7D,MAAM,SAAS,GACb,OAAO,CAAC,GAAG,CAAC,4BAA4B;QACxC,OAAO,CAAC,GAAG,CAAC,UAAU;QACtB,eAAe,CAAC;IAElB,MAAM,cAAc,GAClB,CAAC,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM;QAC9E,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC;IAE/D,OAAO;QACL,WAAW;QACX,YAAY;QACZ,UAAU;QACV,YAAY;QACZ,SAAS;QACT,cAAc;KACf,CAAC;AACJ,CAAC;AAUD,MAAM,UAAU,gBAAgB,CAAC,GAAc;IAC7C,OAAO;QACL;YACE,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,WAAW;SAClB;QACD;YACE,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,GAAG,CAAC,WAAW,KAAK,SAAS;YACtC,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,sCAAsC;SAC3E;QACD;YACE,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,GAAG,CAAC,YAAY,KAAK,SAAS;YACvC,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,+BAA+B;SACrE;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
|
package/mcp.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "better-web-search-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "BetterWebSearch MCP — keyless-first web research (DuckDuckGo) with optional Brave/Tavily and 3-tier extraction",
|
|
5
5
|
"mcpServers": {
|
|
6
6
|
"better-web-search-mcp": {
|
|
7
7
|
"command": "npx",
|
|
8
|
-
"args": [
|
|
8
|
+
"args": [
|
|
9
|
+
"-y",
|
|
10
|
+
"better-web-search-mcp"
|
|
11
|
+
],
|
|
9
12
|
"env": {}
|
|
10
13
|
}
|
|
11
14
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "better-web-search-mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
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": {
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"test": "vitest run",
|
|
40
40
|
"lint": "tsc --noEmit",
|
|
41
41
|
"prepare": "npm run build",
|
|
42
|
+
"version": "node scripts/sync-mcp-version.mjs && git add mcp.json",
|
|
42
43
|
"postinstall": "node scripts/check-native.mjs || true",
|
|
43
44
|
"prepublishOnly": "npm run lint && npm test",
|
|
44
45
|
"prepack": "npm run build",
|
|
@@ -46,9 +47,9 @@
|
|
|
46
47
|
"version:patch": "npm version patch -m \"chore(release): %s\"",
|
|
47
48
|
"version:minor": "npm version minor -m \"chore(release): %s\"",
|
|
48
49
|
"version:major": "npm version major -m \"chore(release): %s\"",
|
|
49
|
-
"release:patch": "npm run version:patch &&
|
|
50
|
-
"release:minor": "npm run version:minor &&
|
|
51
|
-
"release:major": "npm run version:major &&
|
|
50
|
+
"release:patch": "npm run version:patch && git push --follow-tags",
|
|
51
|
+
"release:minor": "npm run version:minor && git push --follow-tags",
|
|
52
|
+
"release:major": "npm run version:major && git push --follow-tags",
|
|
52
53
|
"check:publish": "npm pack --dry-run",
|
|
53
54
|
"docs:api": "typedoc --options typedoc.json && node scripts/typedoc-postprocess.mjs",
|
|
54
55
|
"docs:build": "npm run docs:api && hugo --source site --gc --minify",
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Copy the package version into mcp.json.
|
|
4
|
+
*
|
|
5
|
+
* Runs from the `version` lifecycle hook, which npm fires after bumping
|
|
6
|
+
* package.json but before it creates the release commit, so the synced
|
|
7
|
+
* mcp.json lands in that same commit. Without this the manifest silently
|
|
8
|
+
* drifts — it still read 0.1.0 while npm was publishing 0.2.1.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { dirname, join } from "node:path";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
14
|
+
|
|
15
|
+
const root = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
16
|
+
const pkgPath = join(root, "package.json");
|
|
17
|
+
const mcpPath = join(root, "mcp.json");
|
|
18
|
+
|
|
19
|
+
const { version } = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
20
|
+
const raw = readFileSync(mcpPath, "utf8");
|
|
21
|
+
const manifest = JSON.parse(raw);
|
|
22
|
+
|
|
23
|
+
if (manifest.version === version) {
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
manifest.version = version;
|
|
28
|
+
// Preserve the file's existing trailing newline convention.
|
|
29
|
+
const trailing = raw.endsWith("\n") ? "\n" : "";
|
|
30
|
+
writeFileSync(mcpPath, `${JSON.stringify(manifest, null, 2)}${trailing}`);
|
|
31
|
+
process.stdout.write(`mcp.json version -> ${version}\n`);
|