wildweb-mcp 0.1.0__tar.gz

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.
Files changed (60) hide show
  1. wildweb_mcp-0.1.0/LICENSE +21 -0
  2. wildweb_mcp-0.1.0/PKG-INFO +429 -0
  3. wildweb_mcp-0.1.0/README.md +398 -0
  4. wildweb_mcp-0.1.0/pyproject.toml +58 -0
  5. wildweb_mcp-0.1.0/setup.cfg +4 -0
  6. wildweb_mcp-0.1.0/src/wildweb/__init__.py +3 -0
  7. wildweb_mcp-0.1.0/src/wildweb/budget.py +345 -0
  8. wildweb_mcp-0.1.0/src/wildweb/cli.py +178 -0
  9. wildweb_mcp-0.1.0/src/wildweb/config.py +431 -0
  10. wildweb_mcp-0.1.0/src/wildweb/extraction.py +67 -0
  11. wildweb_mcp-0.1.0/src/wildweb/logging_setup.py +221 -0
  12. wildweb_mcp-0.1.0/src/wildweb/models.py +147 -0
  13. wildweb_mcp-0.1.0/src/wildweb/scraper/__init__.py +1 -0
  14. wildweb_mcp-0.1.0/src/wildweb/scraper/base.py +163 -0
  15. wildweb_mcp-0.1.0/src/wildweb/scraper/playwright_scraper.py +283 -0
  16. wildweb_mcp-0.1.0/src/wildweb/scraper/registry.py +137 -0
  17. wildweb_mcp-0.1.0/src/wildweb/search/__init__.py +1 -0
  18. wildweb_mcp-0.1.0/src/wildweb/search/base.py +172 -0
  19. wildweb_mcp-0.1.0/src/wildweb/search/duckduckgo_provider.py +236 -0
  20. wildweb_mcp-0.1.0/src/wildweb/search/registry.py +139 -0
  21. wildweb_mcp-0.1.0/src/wildweb/server.py +345 -0
  22. wildweb_mcp-0.1.0/src/wildweb/tools.py +741 -0
  23. wildweb_mcp-0.1.0/src/wildweb/user_agents.py +71 -0
  24. wildweb_mcp-0.1.0/src/wildweb_mcp.egg-info/PKG-INFO +429 -0
  25. wildweb_mcp-0.1.0/src/wildweb_mcp.egg-info/SOURCES.txt +58 -0
  26. wildweb_mcp-0.1.0/src/wildweb_mcp.egg-info/dependency_links.txt +1 -0
  27. wildweb_mcp-0.1.0/src/wildweb_mcp.egg-info/entry_points.txt +2 -0
  28. wildweb_mcp-0.1.0/src/wildweb_mcp.egg-info/requires.txt +11 -0
  29. wildweb_mcp-0.1.0/src/wildweb_mcp.egg-info/top_level.txt +1 -0
  30. wildweb_mcp-0.1.0/tests/test_budget.py +359 -0
  31. wildweb_mcp-0.1.0/tests/test_budget_property_5.py +109 -0
  32. wildweb_mcp-0.1.0/tests/test_budget_property_6.py +115 -0
  33. wildweb_mcp-0.1.0/tests/test_budget_property_7.py +162 -0
  34. wildweb_mcp-0.1.0/tests/test_cli_properties.py +89 -0
  35. wildweb_mcp-0.1.0/tests/test_config.py +230 -0
  36. wildweb_mcp-0.1.0/tests/test_config_properties.py +153 -0
  37. wildweb_mcp-0.1.0/tests/test_config_round_trip_properties.py +190 -0
  38. wildweb_mcp-0.1.0/tests/test_duckduckgo_provider.py +240 -0
  39. wildweb_mcp-0.1.0/tests/test_extraction.py +143 -0
  40. wildweb_mcp-0.1.0/tests/test_extraction_properties.py +176 -0
  41. wildweb_mcp-0.1.0/tests/test_logging_file_handler.py +131 -0
  42. wildweb_mcp-0.1.0/tests/test_logging_level_properties.py +95 -0
  43. wildweb_mcp-0.1.0/tests/test_logging_properties.py +182 -0
  44. wildweb_mcp-0.1.0/tests/test_packaging_lifecycle.py +199 -0
  45. wildweb_mcp-0.1.0/tests/test_playwright_scraper_autoinstall.py +230 -0
  46. wildweb_mcp-0.1.0/tests/test_registry.py +160 -0
  47. wildweb_mcp-0.1.0/tests/test_registry_properties.py +74 -0
  48. wildweb_mcp-0.1.0/tests/test_registry_property_10.py +86 -0
  49. wildweb_mcp-0.1.0/tests/test_registry_property_11.py +95 -0
  50. wildweb_mcp-0.1.0/tests/test_registry_property_9.py +121 -0
  51. wildweb_mcp-0.1.0/tests/test_search_config.py +63 -0
  52. wildweb_mcp-0.1.0/tests/test_search_registry.py +97 -0
  53. wildweb_mcp-0.1.0/tests/test_server_property_1.py +94 -0
  54. wildweb_mcp-0.1.0/tests/test_server_search_registration.py +77 -0
  55. wildweb_mcp-0.1.0/tests/test_tool_descriptions.py +96 -0
  56. wildweb_mcp-0.1.0/tests/test_tools_property_3.py +135 -0
  57. wildweb_mcp-0.1.0/tests/test_tools_property_4.py +144 -0
  58. wildweb_mcp-0.1.0/tests/test_tools_search.py +133 -0
  59. wildweb_mcp-0.1.0/tests/test_tools_timeout.py +49 -0
  60. wildweb_mcp-0.1.0/tests/test_user_agents.py +54 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Carel Wentzel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,429 @@
1
+ Metadata-Version: 2.4
2
+ Name: wildweb-mcp
3
+ Version: 0.1.0
4
+ Summary: An extensible MCP server that exposes web scraping as an MCP tool.
5
+ Author-email: Carel Wentzel <carel.wentzel@gmail.com>
6
+ License-Expression: MIT
7
+ Keywords: mcp,model-context-protocol,web-scraping,playwright,llm-tools
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
16
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
+ Requires-Python: >=3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: mcp==1.13.1
21
+ Requires-Dist: playwright==1.65.0
22
+ Requires-Dist: trafilatura==2.3.1
23
+ Requires-Dist: tiktoken==0.14.0
24
+ Requires-Dist: httpx==0.28.1
25
+ Requires-Dist: lxml==6.1.3
26
+ Requires-Dist: pydantic==2.13.5
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest==7.4.4; extra == "dev"
29
+ Requires-Dist: hypothesis==6.154.1; extra == "dev"
30
+ Dynamic: license-file
31
+
32
+ # wildweb-mcp
33
+
34
+ An extensible [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server, written
35
+ in Python, that exposes web scraping as an MCP tool. It fetches a web page with a headless
36
+ Chromium browser (so client-rendered pages are captured), strips boilerplate (navigation, ads,
37
+ scripts, styles) with `trafilatura`, and returns token-efficient clean markdown to MCP clients.
38
+ No API key or third-party search/scrape API is required — it talks to the open web directly.
39
+
40
+ ## Requirements
41
+
42
+ - Python **3.10+**
43
+ - Chromium browser binary — installed automatically on first run, see below
44
+
45
+ ## Installation
46
+
47
+ Install into a virtualenv rather than system/global Python — it keeps `wildweb-mcp`'s pinned
48
+ dependencies isolated, and (as covered below) MCP clients need this venv's path anyway since they
49
+ launch the server directly, bypassing your shell:
50
+
51
+ ```bash
52
+ python3 -m venv ~/.venvs/wildweb
53
+ ~/.venvs/wildweb/bin/pip install wildweb-mcp
54
+ ```
55
+
56
+ (`.venvs\wildweb\Scripts\pip.exe install wildweb-mcp` on Windows.)
57
+
58
+ ### The Chromium browser
59
+
60
+ `pip install` installs the `playwright` Python package (it's a pinned dependency of
61
+ `wildweb-mcp`) but not the browser binary that Playwright drives.
62
+
63
+ **You don't need to install it yourself.** If Chromium isn't found when the server starts, it
64
+ runs `playwright install chromium` automatically — a one-time download (~300MB) into the shared
65
+ Playwright cache (`~/.cache/ms-playwright` on Linux/macOS,
66
+ `%USERPROFILE%\AppData\Local\ms-playwright` on Windows) — then retries. Every startup after that
67
+ is unaffected, since the binary is already there. This first-run install can take a few minutes
68
+ and needs network access; if it can't finish within 5 minutes (e.g. no network) or fails for
69
+ another reason, the server falls back to the existing clear startup error instead of hanging.
70
+ Progress and any install errors are logged — see [Where logs go](#where-logs-go) below.
71
+
72
+ If you'd rather install it ahead of time (e.g. to avoid the first-run delay, or in an offline/
73
+ sandboxed environment where the server shouldn't attempt a network call on its own), run it
74
+ yourself before starting the server — using the venv path from Installation above:
75
+
76
+ ```bash
77
+ ~/.venvs/wildweb/bin/playwright install chromium
78
+ ```
79
+
80
+ (`~/.venvs/wildweb/Scripts/playwright.exe install chromium` on Windows.)
81
+
82
+ **A bare `playwright install chromium` will not work as a copy-paste pre-setup step** unless you
83
+ first activate that venv (`source ~/.venvs/wildweb/bin/activate`, or on Windows
84
+ `~/.venvs/wildweb/Scripts/activate`) — without either activation or the full path, your shell has
85
+ no `playwright` command on `PATH` at all (it only exists inside the venv you installed
86
+ `wildweb-mcp` into) and the command fails with "command not found." The full-path form above
87
+ works unconditionally, with nothing to activate first.
88
+
89
+ This has to be the `playwright` from the **same environment** `wildweb-mcp` was installed into —
90
+ if you installed globally/user-wide instead (`pip install --user` or system pip) rather than into
91
+ a venv, it lands in pip's script directory instead (e.g. `~/.local/bin` on Linux, your Python
92
+ install's `Scripts`/`bin` folder on macOS/Windows), and a bare `playwright install chromium` works
93
+ directly only if that directory is on `PATH`.
94
+
95
+ On Linux, Chromium may also need OS-level shared libraries. **This is never installed
96
+ automatically** — it requires root/sudo to run a system package manager, which the server will
97
+ not do on its own. If the server's startup error (or a manual `playwright install chromium`)
98
+ warns about missing dependencies, install them yourself:
99
+
100
+ ```bash
101
+ playwright install-deps chromium
102
+ ```
103
+
104
+ ## Configuration
105
+
106
+ The server reads a single JSON configuration file. Copy the sample and edit it as needed:
107
+
108
+ ```bash
109
+ cp config.example.json config.json
110
+ ```
111
+
112
+ ```json
113
+ {
114
+ "request_timeout_ms": 30000,
115
+ "token_budget": 4000,
116
+ "log_level": "INFO",
117
+ "continuation_ttl_seconds": 300,
118
+ "browser": {
119
+ "headless": true,
120
+ "navigation_timeout_ms": 30000,
121
+ "wait_until": "load"
122
+ }
123
+ }
124
+ ```
125
+
126
+ All fields are optional and fall back to documented defaults:
127
+
128
+ | Field | Default | Description |
129
+ | ---------------------------- | --------- | ------------------------------------------------------------------ |
130
+ | `request_timeout_ms` | `30000` | Logical request timeout in milliseconds. |
131
+ | `token_budget` | `null` | Max tokens per tool output; `null` disables budgeting/truncation. |
132
+ | `log_level` | `"INFO"` | One of `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`. |
133
+ | `continuation_ttl_seconds` | `300` | Time-to-live for continuation tokens, in seconds. |
134
+ | `browser.headless` | `true` | Launch Chromium headless. |
135
+ | `browser.navigation_timeout_ms` | `30000` | Playwright navigation timeout; defaults to `request_timeout_ms`. |
136
+ | `browser.wait_until` | `"load"` | One of `load`, `domcontentloaded`, `networkidle`, `commit`. |
137
+ | `search_result_count` | `10` | Number of results the `search` tool returns per query. |
138
+ | `search_timeout_ms` | `10000` | Timeout in milliseconds for a `search` request. |
139
+ | `user_agents` | `null` | Array of User-Agent strings to rotate through; `null` uses the built-in default pool. |
140
+ | `log_file` | `null` | Path to also write logs to, capped at 10MB (see [Where logs go](#where-logs-go)); `null` logs to stderr only. |
141
+
142
+ ### Simulating a modern browser
143
+
144
+ Every outgoing request (Playwright page navigation and the `search` tool's DuckDuckGo
145
+ request) identifies as an ordinary modern desktop browser rather than a generic
146
+ client/library default, since some sites are more likely to serve their normal response
147
+ to a request that looks like one. Requests draw from a rotating pool of real browser
148
+ User-Agent strings (Chrome, Firefox, Safari, Edge) round-robin, one per request, rather
149
+ than reusing a single fixed value.
150
+
151
+ Set `user_agents` to replace the default pool with your own:
152
+
153
+ ```json
154
+ {
155
+ "user_agents": [
156
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
157
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.1 Safari/605.1.15"
158
+ ]
159
+ }
160
+ ```
161
+
162
+ The array must be non-empty; omit the field or set it to `null` to use the default pool.
163
+
164
+ ## Where logs go
165
+
166
+ All server logging — startup messages (including the automatic Chromium install above),
167
+ per-request success/failure entries, and errors — is written to **stderr**, never stdout.
168
+ This is deliberate: stdout is reserved exclusively for the MCP JSON-RPC protocol stream between
169
+ the server and its client, so anything else written there would corrupt that stream.
170
+
171
+ What you see depends on how your MCP client surfaces a subprocess's stderr. Most already capture
172
+ it to their own log file, so check there first:
173
+
174
+ - **Claude Desktop**: `~/Library/Logs/Claude/mcp-server-<name>.log` (macOS),
175
+ `%APPDATA%\Claude\logs\mcp-server-<name>.log` (Windows)
176
+ - **Claude Code**: `claude mcp logs <name>`
177
+ - **Kiro CLI / opencode**: each client's own MCP connection log/output panel — check its docs for
178
+ the exact location
179
+
180
+ Or run `wildweb` directly in a terminal to see log lines interleaved with your own shell.
181
+ `log_level` (see the [Configuration](#configuration) table above) controls verbosity: `DEBUG`
182
+ through `CRITICAL`, defaulting to `INFO`.
183
+
184
+ ### Writing logs to a file too
185
+
186
+ If your client doesn't capture stderr usefully, or you just want one log location regardless of
187
+ which client launched the server, set `log_file` to a path:
188
+
189
+ ```json
190
+ {
191
+ "log_file": "/absolute/path/to/wildweb.log"
192
+ }
193
+ ```
194
+
195
+ This writes the same entries to that file *in addition to* stderr — nothing stops going to
196
+ stderr. The file is capped at 10MB: once it hits that size, it's truncated (overwritten from
197
+ empty) rather than rotated to `.1`/`.2` backups, so it's always exactly one bounded file, never
198
+ growing unbounded across a long-running server process and never leaving old backup files to
199
+ clean up. If the path can't be opened (e.g. its parent directory doesn't exist), the server logs
200
+ a warning and continues with stderr-only logging rather than failing to start.
201
+
202
+ ## Usage
203
+
204
+ A config file is optional. The config file path is resolved with the following
205
+ precedence:
206
+
207
+ 1. `--config <path>` command-line argument (highest precedence)
208
+ 2. `WILDWEB_CONFIG` environment variable
209
+ 3. If neither is provided, the server runs with the built-in defaults listed
210
+ under [Configuration](#configuration) — no config file is required.
211
+
212
+ ```bash
213
+ # with no config at all — runs with built-in defaults
214
+ wildweb
215
+
216
+ # via command-line argument
217
+ wildweb --config config.json
218
+
219
+ # or via environment variable
220
+ WILDWEB_CONFIG=config.json wildweb
221
+ ```
222
+
223
+ MCP clients connect over stdio and discover three tools:
224
+
225
+ - **`scrape`** — fetch a web page by URL and return its main textual content as clean markdown.
226
+ When the content exceeds the configured `token_budget`, the result is truncated and a
227
+ continuation token is returned.
228
+ - **`scrape_continue`** — fetch the next portion of a previously scraped page using a
229
+ continuation token returned by `scrape`.
230
+ - **`search`** — search the web for a query and return a list of results (title, URL, snippet).
231
+ Input: a non-empty text query. Output: up to `search_result_count` ordered results, or an
232
+ error. The `search` tool does **not** fetch or scrape any result's page content — pipe a
233
+ result's `url` into `scrape` for that.
234
+
235
+ ### Search provider caveat
236
+
237
+ The `search` tool is backed by a free, key-free `SearchProvider` implementation
238
+ (`DuckDuckGoSearchProvider`) that fetches and parses DuckDuckGo's public HTML results page
239
+ (`https://html.duckduckgo.com/html/`). This is an **unofficial surface**, not a documented or
240
+ supported API:
241
+
242
+ - DuckDuckGo can change its HTML markup, rate-limit, or block automated requests at any time
243
+ without notice, which will surface as a `search_unavailable` error from the `search` tool.
244
+ - Using it at any significant volume may be subject to DuckDuckGo's Terms of Service; this
245
+ provider is intended for light, personal-scale use.
246
+ - The `SearchProvider` interface (`src/wildweb/search/base.py`) exists specifically so a
247
+ different, officially-supported provider (e.g. a paid search API) can be registered later
248
+ without changing the `search` tool or server wiring — see `src/wildweb/search/registry.py`.
249
+
250
+ ## Adding it to an MCP client
251
+
252
+ Once installed (see [Installation](#installation) above), the `wildweb` console script is what
253
+ MCP clients launch over stdio.
254
+
255
+ ### Point your client at the venv's executable, not a bare command
256
+
257
+ An MCP client launches the server as a plain subprocess using exactly the `command` string in
258
+ its own config — that launch does not go through your shell, so it never activates the virtualenv
259
+ you installed into and often doesn't even inherit your normal shell `PATH`. A bare
260
+ `"command": "wildweb"` only works if `wildweb` happens to resolve on whatever `PATH` that
261
+ client's process has, which is unreliable. The robust fix: give the client the venv's own
262
+ executable path directly, instead of relying on `PATH` resolution — use the venv path from
263
+ Installation in place of the bare `wildweb` shown in the client configs below:
264
+
265
+ ```json
266
+ {
267
+ "command": "/Users/you/.venvs/wildweb/bin/wildweb"
268
+ }
269
+ ```
270
+
271
+ (`...\.venvs\wildweb\Scripts\wildweb.exe` on Windows.) No `args` needed, no `PATH` dependency,
272
+ nothing to activate.
273
+
274
+ ### Config: none, a file, or an environment variable
275
+
276
+ The simplest entry needs no config at all — the server runs with its built-in defaults:
277
+
278
+ ```json
279
+ {
280
+ "command": "wildweb"
281
+ }
282
+ ```
283
+
284
+ To use a config file instead, add `--config` with an absolute path (the client usually
285
+ launches the server from its own working directory, not this project's):
286
+
287
+ ```json
288
+ {
289
+ "command": "wildweb",
290
+ "args": ["--config", "/absolute/path/to/config.json"]
291
+ }
292
+ ```
293
+
294
+ Alternatively, set `WILDWEB_CONFIG` as an environment variable on the entry instead of passing
295
+ `--config`.
296
+
297
+ ### Claude Desktop
298
+
299
+ Add a `wildweb` entry under `mcpServers` in Claude Desktop's config file
300
+ (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS,
301
+ `%APPDATA%\Claude\claude_desktop_config.json` on Windows). No config (built-in defaults):
302
+
303
+ ```json
304
+ {
305
+ "mcpServers": {
306
+ "wildweb": {
307
+ "command": "wildweb"
308
+ }
309
+ }
310
+ }
311
+ ```
312
+
313
+ With a config file:
314
+
315
+ ```json
316
+ {
317
+ "mcpServers": {
318
+ "wildweb": {
319
+ "command": "wildweb",
320
+ "args": ["--config", "/absolute/path/to/config.json"]
321
+ }
322
+ }
323
+ }
324
+ ```
325
+
326
+ Restart Claude Desktop for the change to take effect.
327
+
328
+ ### Claude Code
329
+
330
+ Add it as a user- or project-scoped server with the `claude mcp add` CLI. The first `wildweb` is
331
+ the server's name within Claude Code; the second is the command it runs. No config:
332
+
333
+ ```bash
334
+ claude mcp add wildweb wildweb
335
+ ```
336
+
337
+ With a config file:
338
+
339
+ ```bash
340
+ claude mcp add wildweb wildweb -- --config /absolute/path/to/config.json
341
+ ```
342
+
343
+ Or add the equivalent `mcpServers` block shown above directly to the project's `.mcp.json`.
344
+
345
+ ### Kiro CLI
346
+
347
+ Add a `wildweb` entry under `mcpServers` in Kiro's MCP config file — globally at
348
+ `~/.kiro/settings/mcp.json`, or per-project at `.kiro/settings/mcp.json` (workspace settings
349
+ take precedence when both exist). No config:
350
+
351
+ ```json
352
+ {
353
+ "mcpServers": {
354
+ "wildweb": {
355
+ "command": "wildweb",
356
+ "disabled": false,
357
+ "autoApprove": []
358
+ }
359
+ }
360
+ }
361
+ ```
362
+
363
+ With a config file:
364
+
365
+ ```json
366
+ {
367
+ "mcpServers": {
368
+ "wildweb": {
369
+ "command": "wildweb",
370
+ "args": ["--config", "/absolute/path/to/config.json"],
371
+ "disabled": false,
372
+ "autoApprove": []
373
+ }
374
+ }
375
+ }
376
+ ```
377
+
378
+ Kiro does not inherit your shell's `PATH`, so if `wildweb` isn't resolvable as a bare command,
379
+ use its absolute path instead (e.g. `/path/to/venv/bin/wildweb`). Run `/mcp` inside Kiro CLI to
380
+ confirm the server loaded.
381
+
382
+ ### opencode
383
+
384
+ Add a local server under `mcp` in `opencode.jsonc` (project root) or the global
385
+ `~/.config/opencode/opencode.jsonc`. No config:
386
+
387
+ ```jsonc
388
+ {
389
+ "$schema": "https://opencode.ai/config.json",
390
+ "mcp": {
391
+ "wildweb": {
392
+ "type": "local",
393
+ "command": ["wildweb"]
394
+ }
395
+ }
396
+ }
397
+ ```
398
+
399
+ With a config file:
400
+
401
+ ```jsonc
402
+ {
403
+ "$schema": "https://opencode.ai/config.json",
404
+ "mcp": {
405
+ "wildweb": {
406
+ "type": "local",
407
+ "command": ["wildweb", "--config", "/absolute/path/to/config.json"]
408
+ }
409
+ }
410
+ }
411
+ ```
412
+
413
+ Or add it from the CLI. No config:
414
+
415
+ ```bash
416
+ opencode mcp add wildweb -- wildweb
417
+ ```
418
+
419
+ With a config file:
420
+
421
+ ```bash
422
+ opencode mcp add wildweb -- wildweb --config /absolute/path/to/config.json
423
+ ```
424
+
425
+ ### Other clients
426
+
427
+ Any MCP client that launches servers over stdio (Cursor, Windsurf, etc.) accepts the same
428
+ `command`/`args` shape under whatever key its own config format uses for MCP servers — consult
429
+ that client's docs for the exact file location.