deepseek-web-retrieval 0.6.0 → 0.8.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/CHANGELOG.md +23 -1
- package/README.md +113 -53
- package/dist/cli.js +2427 -1813
- package/docs/adr/0002-shared-config-base-layer.md +43 -0
- package/docs/agents/claude-code.md +273 -0
- package/docs/agents/codex.md +50 -27
- package/docs/agents/opencode-v2.md +59 -33
- package/docs/agents/pi.md +50 -27
- package/docs/configuration.md +109 -0
- package/docs/design/config-layering-design.md +180 -0
- package/docs/design/installer-design.md +24 -13
- package/docs/hosts.jsonc +5 -1
- package/docs/integration.md +15 -9
- package/docs/research/control-matrix.md +49 -11
- package/docs/research/mcp-compatibility.md +6 -3
- package/docs/research/ori-question-sourcing.md +336 -0
- package/docs/research/result-quality-passthrough.md +159 -0
- package/docs/research/search-api-defaults.md +18 -2
- package/docs/research/search-inline-content.md +244 -0
- package/examples/opencode.global.jsonc +3 -2
- package/package.json +2 -1
- package/src/core/auth.ts +3 -0
- package/src/core/client.ts +26 -4
- package/src/core/config-file.ts +168 -0
- package/src/core/config-summary.ts +82 -0
- package/src/core/constants.ts +15 -1
- package/src/core/descriptions.ts +6 -2
- package/src/core/env.ts +102 -32
- package/src/core/format.ts +19 -1
- package/src/core/options.ts +22 -2
- package/src/core/search.ts +6 -0
- package/src/core/types.ts +11 -0
- package/src/installer/cli.ts +50 -16
- package/src/installer/config-command.ts +116 -0
- package/src/installer/hosts/claude-code.ts +325 -0
- package/src/installer/hosts/codex.ts +9 -4
- package/src/installer/hosts/index.ts +3 -0
- package/src/installer/hosts/opencode.ts +9 -5
- package/src/installer/hosts/pi.ts +34 -9
- package/src/installer/ownership.ts +54 -1
- package/src/installer/paths.ts +7 -1
- package/src/installer/state.ts +73 -20
- package/src/installer/types.ts +11 -1
- package/src/installer/uninstall.ts +4 -1
- package/src/mcp/auth.ts +2 -3
- package/src/mcp/cli.ts +4 -3
- package/src/mcp/serve.ts +10 -1
- package/src/mcp/server.ts +7 -2
- package/src/opencode/plugin.ts +22 -2
- package/src/pi/extension.ts +78 -9
|
@@ -71,8 +71,9 @@ Reading notes:
|
|
|
71
71
|
One section per host, in hosts.jsonc order. Each carries what an install needs beyond the
|
|
72
72
|
matrix: the built-in competitors, their kill switches, how the MCP server is registered,
|
|
73
73
|
and which rules files steer preference. The `init` CLI implements these tiers for
|
|
74
|
-
OpenCode, Pi, and
|
|
75
|
-
paths imply the available
|
|
74
|
+
OpenCode, Pi, Codex, and Claude Code (see
|
|
75
|
+
[installer design](../design/installer-design.md)). Config paths imply the available
|
|
76
|
+
scopes; keys locked to a single scope are enumerated in the
|
|
76
77
|
[installer design](../design/installer-design.md#scope).
|
|
77
78
|
|
|
78
79
|
### Cline
|
|
@@ -118,7 +119,11 @@ paths imply the available scopes; keys locked to a single scope are enumerated i
|
|
|
118
119
|
([rmcp_client.rs at rust-v0.163.0](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/codex-mcp/src/rmcp_client.rs));
|
|
119
120
|
`enabled_tools`/`disabled_tools` (verbatim raw tool-name match, filtered before
|
|
120
121
|
registration so the model never sees a disabled tool; an empty `enabled_tools` allow-list
|
|
121
|
-
exposes nothing), per-tool approval modes, and output limits
|
|
122
|
+
exposes nothing), per-tool approval modes, and output limits: MCP tool output can be
|
|
123
|
+
capped per tool via `output_token_limit` ("Token budget for one MCP tool's output,
|
|
124
|
+
before the standard 20% serialization allowance"; the default cap is not published
|
|
125
|
+
there)
|
|
126
|
+
([mcp_types.rs at rust-v0.163.0](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/config/src/mcp_types.rs)).
|
|
122
127
|
stdio children do not inherit the parent environment (only `HOME`, `PATH`, and explicit
|
|
123
128
|
`env`), so `DEEPSEEK_API_KEY` must be passed explicitly. When a tool result has
|
|
124
129
|
`structuredContent`, Codex replaces the content blocks with the serialized JSON. No SSE.
|
|
@@ -146,6 +151,13 @@ paths imply the available scopes; keys locked to a single scope are enumerated i
|
|
|
146
151
|
tool from model requests entirely; `webfetch` has no disable config key at 2.0.32 — the
|
|
147
152
|
deterministic paths are a permissions deny (`action: "webfetch"`) or a plugin
|
|
148
153
|
tool-transform removal, the latter being what `fetchOverrideWebfetch` does.
|
|
154
|
+
- **Tool output caps** — plugin tool results truncate at 2,000 lines / 50 KiB: every
|
|
155
|
+
tool result passes through `ToolOutput.truncate` (`MAX_LINES = 2000`,
|
|
156
|
+
`MAX_BYTES = 50 KiB`), with the full output retained to a `tool-output/` file for
|
|
157
|
+
7 days
|
|
158
|
+
([tool-output.ts at v2.0.32](https://github.com/anomalyco/opencode/blob/v2.0.32/packages/core/src/tool-output.ts));
|
|
159
|
+
caps and model-channel behavior recorded in
|
|
160
|
+
[result-quality-passthrough.md](result-quality-passthrough.md).
|
|
149
161
|
- **MCP registration** — out of scope for this host: the shipped path is the plugin
|
|
150
162
|
adapter, and OpenCode's MCP support is not part of it.
|
|
151
163
|
- **Rules** — `AGENTS.md` only (no CLAUDE.md fallback in v2): global
|
|
@@ -170,7 +182,9 @@ paths imply the available scopes; keys locked to a single scope are enumerated i
|
|
|
170
182
|
`process.env` (no forwarding), and results bypass the MCP layer entirely, so neither the
|
|
171
183
|
20 KB truncation nor the 60 s request timeout applies. There is no per-extension options
|
|
172
184
|
channel: the runtime config surface is the `DEEPSEEK_*` environment (the same pipeline as
|
|
173
|
-
the MCP server)
|
|
185
|
+
the MCP server), the shared config file
|
|
186
|
+
(`~/.config/deepseek-web-retrieval/config.json`, layered under the environment), plus a
|
|
187
|
+
`deepseekWebRetrieval` settings namespace the installer writes for
|
|
174
188
|
the off tier — Pi preserves unknown settings keys on read and on its own rewrites
|
|
175
189
|
(`pi install`), verified at 1.3.0. Action methods such as `getSettings()` cannot be
|
|
176
190
|
called during extension loading, so the adapter reads the settings files itself.
|
|
@@ -196,15 +210,31 @@ paths imply the available scopes; keys locked to a single scope are enumerated i
|
|
|
196
210
|
- **Built-in web tools** — `WebSearch` and `WebFetch`. Kill switch: bare deny rules —
|
|
197
211
|
`"permissions": {"deny": ["WebSearch", "WebFetch"]}` — remove the tools from the model's
|
|
198
212
|
context entirely; deny outranks allow at every settings level and cannot be carved out.
|
|
199
|
-
|
|
200
|
-
|
|
213
|
+
Permission rules live in the settings file of each level: managed
|
|
214
|
+
`managed-settings.json` (Linux `/etc/claude-code/`, macOS
|
|
215
|
+
`/Library/Application Support/ClaudeCode/`, Windows
|
|
216
|
+
`C:\Program Files\ClaudeCode\` — the legacy `C:\ProgramData\ClaudeCode\` path
|
|
217
|
+
is not read) →
|
|
218
|
+
user `~/.claude/settings.json` → project `.claude/settings.json` → local
|
|
219
|
+
`.claude/settings.local.json`; the installer writes the chosen scope's settings file
|
|
220
|
+
and reports an existing managed layer. A bare `mcp__<server>` rule denies every tool
|
|
221
|
+
of one MCP server — the per-server kill switch the installer uses for web-capable
|
|
222
|
+
competitors under the forced tier. `--disallowedTools` is the flag form.
|
|
223
|
+
`CLAUDE_CODE_DISABLE_WEB_FETCH=1` (2.1.285+) kills WebFetch only; there is no env
|
|
224
|
+
equivalent for WebSearch
|
|
201
225
|
([tools](https://code.claude.com/docs/en/tools),
|
|
202
|
-
[permissions](https://code.claude.com/docs/en/permissions)
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
226
|
+
[permissions](https://code.claude.com/docs/en/permissions),
|
|
227
|
+
[settings](https://code.claude.com/docs/en/settings)).
|
|
228
|
+
- **MCP registration** — three scopes across two files: project `.mcp.json` at the
|
|
229
|
+
project root (team-shared, first-use approval prompt per project), local scope under
|
|
230
|
+
the project's entry in `~/.claude.json` (private, the `claude mcp add` default), and
|
|
231
|
+
user scope at the top-level `mcpServers` key of `~/.claude.json` (`--scope user`).
|
|
232
|
+
Entries take `mcpServers` with `command`/`args`/`env`, or `type: "http"` + `url`;
|
|
233
|
+
`${VAR}` expansion in `command`/`args`/`env`/`url`/`headers`. Tool permission rules
|
|
234
|
+
use `mcp__<server>__<tool>`. Tool descriptions are capped at 4,096
|
|
206
235
|
chars (2.1.296+) and tool output at 25k tokens by default (`MAX_MCP_OUTPUT_TOKENS`),
|
|
207
|
-
with oversized text saved to a file; 16 MiB message cap on HTTP transports
|
|
236
|
+
with oversized text saved to a file; 16 MiB message cap on HTTP transports
|
|
237
|
+
([MCP quickstart](https://code.claude.com/docs/en/mcp-quickstart)).
|
|
208
238
|
- **Rules** — `CLAUDE.md` hierarchy (managed → user `~/.claude/CLAUDE.md` → project →
|
|
209
239
|
`CLAUDE.local.md`) with `@import`; `AGENTS.md` is read instead only when no CLAUDE.md
|
|
210
240
|
exists anywhere above the cwd (since 2.1.277)
|
|
@@ -290,3 +320,11 @@ paths imply the available scopes; keys locked to a single scope are enumerated i
|
|
|
290
320
|
`toolPolicies`). Codex's docs location and Copilot's `GEMINI.md` dating were re-verified
|
|
291
321
|
2026-10-21 and are settled in their sections above. Protocol-revision evidence for every
|
|
292
322
|
host lives in [mcp-compatibility.md](mcp-compatibility.md).
|
|
323
|
+
- **Claude Code forward-compat anchors (checked at the 2.1.303 lock):** the headless docs
|
|
324
|
+
pre-announce `--bare` becoming the default for `-p`, and bare mode never reads
|
|
325
|
+
`.mcp.json` — the billed e2e scenario and the project-scope install story both need
|
|
326
|
+
re-checking when that lands. `${VAR}` expansion in the `env` block of a user-scope
|
|
327
|
+
`~/.claude.json` entry is supported but only indirectly documented (the docs spell out
|
|
328
|
+
`.mcp.json` and `command`/`args`; the e2e's `hasCompletedOnboarding` flag and the
|
|
329
|
+
redundant `enableAllProjectMcpServers` belt-and-suspenders are undocumented), so a
|
|
330
|
+
baseline bump should re-verify all three against the then-current docs.
|
|
@@ -82,7 +82,7 @@ host facts; each row below was verified against that lock on the research baseli
|
|
|
82
82
|
| Cline | `2024-11-05` | stdio, Streamable HTTP, SSE | Custom client (no official SDK); `protocolVersion "2024-11-05"` extracted from the platform binary; source repo not public |
|
|
83
83
|
| Codex | `2025-06-18`; `mcp_2026_07_28` feature flag opts into `2026-07-28` | stdio, Streamable HTTP (no SSE) | Git tag `rust-v0.163.0`: rmcp 3.5.1 pinned; initialize sends `V_2025_06_18` |
|
|
84
84
|
| Pi | `2025-11-25` | stdio, Streamable HTTP (SSE rejected) | Git tag: own `@earendil-works/pi-mcp` client, `LATEST_PROTOCOL_VERSION "2025-11-25"` |
|
|
85
|
-
| Claude Code | `2026-07-28` by default (`MCP_PROTOCOL_NEGOTIATION=legacy` opt-out) | stdio, Streamable HTTP, SSE, ws |
|
|
85
|
+
| Claude Code | `2026-07-28` by default (`MCP_PROTOCOL_NEGOTIATION=legacy` opt-out) | stdio, Streamable HTTP, SSE, ws | Docs: the v2 runtime (TS SDK 2.0) defaults from 2.1.274+ without flag fetching and "asks stdio servers for that revision by default"; changelog 2.1.299 extended the default to cloud session and Remote Control connectors |
|
|
86
86
|
| Cursor | Unpinnable from primary sources (docs show ≥ `2025-06-18` features) | stdio, Streamable HTTP, SSE | Docs feature set only; no revision stated in docs or changelog |
|
|
87
87
|
| Devin | `2026-07-28` | stdio, Streamable HTTP (SSE fallback), SSE | Changelog for the locked release itself: "Support for MCP protocol revision 2026-07-28" |
|
|
88
88
|
| GitHub Copilot | `2026-07-28` | stdio (`type: "local"`), Streamable HTTP, SSE | Changelog 1.0.81: "Ship MCP 2026-07-28 support to CLI, SDK, IDE, and in-memory clients" |
|
|
@@ -117,7 +117,10 @@ differences:
|
|
|
117
117
|
content-first, falling back to `structuredContent` only when a result has no content
|
|
118
118
|
blocks (verified in `tools.ts` at v1.3.0). No `outputSchema` is declared: the SDK
|
|
119
119
|
rejects text-only results for a tool with a declared schema, and no host in the
|
|
120
|
-
matrix validates the schema anyway.
|
|
120
|
+
matrix validates the schema anyway. The per-host model-channel facts behind this —
|
|
121
|
+
which of `content`/`structuredContent` provably reaches the model on each host,
|
|
122
|
+
native adapter paths included — are recorded in
|
|
123
|
+
[result-quality-passthrough.md](result-quality-passthrough.md).
|
|
121
124
|
2. **stdio is the universal transport.** Every host in the matrix launches stdio servers
|
|
122
125
|
with the same conceptual JSON (`mcpServers` → `command`/`args`/`env`), differing only in
|
|
123
126
|
file location and cosmetic field names. stdio needs no OAuth and no URL config, and the
|
|
@@ -125,7 +128,7 @@ differences:
|
|
|
125
128
|
Codex and Pi reject it anyway.
|
|
126
129
|
3. **Build on the official SDK v2 dual-era serving.** One build then serves the full range:
|
|
127
130
|
the `2024-11-05` floor set by Cline (v2 legacy support spans `2024-10-07`–`2025-11-25`)
|
|
128
|
-
up to the `2026-07-28` negotiators (Claude Code 2.1.
|
|
131
|
+
up to the `2026-07-28` negotiators (Claude Code 2.1.274+, Devin 3000.11.92, Copilot CLI
|
|
129
132
|
1.0.81+). A v1.x-built server still works today — modern clients fall back to the legacy
|
|
130
133
|
handshake — but it can never offer the stateless era; v2 serves both from one entry
|
|
131
134
|
point.
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# Sourcing `ori_question` across hosts
|
|
2
|
+
|
|
3
|
+
This note answers one question: through what channel could each host in the
|
|
4
|
+
[support matrix](../integration.md) supply a value for the DeepSeek Search API's optional
|
|
5
|
+
`ori_question` request parameter — "触发搜索的用户原始问题,1~128 个字符,有助于更好地理解搜索意图" (the
|
|
6
|
+
user's original question that triggered the search;
|
|
7
|
+
[API guide](https://api-docs.deepseek.com/guides/search), parameter table reproduced in
|
|
8
|
+
[search-api-defaults.md](search-api-defaults.md))? Two candidate channels are examined per host:
|
|
9
|
+
**(A)** a model-filled optional tool input parameter (e.g. an optional `original_question` string in
|
|
10
|
+
the tool's input schema), and **(B)** the adapter itself reading the surrounding session/task
|
|
11
|
+
context at tool-call time. At the research baseline the repo never sent the parameter; it is
|
|
12
|
+
now sent on the MCP path (channel A) and the Pi path (A plus B as a blank-input fallback),
|
|
13
|
+
while OpenCode's websearch provider path has no channel at 2.0.32 (below).
|
|
14
|
+
|
|
15
|
+
**Research baseline:** 2026-10-23, using the same version locks as
|
|
16
|
+
[hosts.jsonc](../hosts.jsonc) (baseline 2026-10-19): Cline 0.0.13, Codex 0.163.0
|
|
17
|
+
(rust-v0.163.0, rmcp 3.5.1), OpenCode 2.0.32, Pi 1.3.0, Claude Code 2.1.303, Cursor 2026.10.08,
|
|
18
|
+
Devin 3000.11.92, GitHub Copilot 1.0.98. Claims are cited to primary sources only: the MCP
|
|
19
|
+
specification, host source code at exact git tags, npm tarballs at the locked versions, and
|
|
20
|
+
official docs/changelogs. Where no primary source pins a fact, that is stated rather than guessed.
|
|
21
|
+
Protocol-revision facts per host are inherited from
|
|
22
|
+
[mcp-compatibility.md](mcp-compatibility.md) and not re-derived.
|
|
23
|
+
|
|
24
|
+
## What the protocol offers
|
|
25
|
+
|
|
26
|
+
MCP never carries conversation context to a server. The facts, per revision:
|
|
27
|
+
|
|
28
|
+
- **`tools/call` params are `name` + `arguments` (+ `_meta`).** The 2025-06-18 schema defines the
|
|
29
|
+
params as `name` (required, string) and `arguments` (optional, free-form object with
|
|
30
|
+
`additionalProperties: {}`) — the concrete `CallToolRequest` does not even enumerate `_meta`
|
|
31
|
+
([schema.json](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/2025-06-18/schema.json));
|
|
32
|
+
the same shape holds in 2024-11-05 and 2025-11-25
|
|
33
|
+
([tools pages](https://modelcontextprotocol.io/specification/2025-11-25/server/tools)). 2025-11-25
|
|
34
|
+
adds an optional `task` field (task augmentation) and 2026-07-28 adds `inputResponses` /
|
|
35
|
+
`requestState` for multi round-trip retries plus required per-request `_meta` protocol fields
|
|
36
|
+
([2026-07-28 tools](https://modelcontextprotocol.io/specification/2026-07-28/server/tools),
|
|
37
|
+
[_meta](https://modelcontextprotocol.io/specification/2026-07-28/basic/index#meta)) — none of
|
|
38
|
+
these carry user or conversation data.
|
|
39
|
+
- **The spec assigns input validation to servers, not clients.** "Servers **MUST**: Validate all
|
|
40
|
+
tool inputs"; the client-side SHOULDs cover validating *results* and showing inputs to the user —
|
|
41
|
+
no revision obliges (or forbids) a client to validate model arguments against `inputSchema`
|
|
42
|
+
([security considerations](https://modelcontextprotocol.io/specification/2025-06-18/server/tools),
|
|
43
|
+
all revisions). `inputSchema` is "JSON Schema defining expected parameters", defaulting to the
|
|
44
|
+
2020-12 dialect from 2025-11-25 on. This makes an optional declared property the spec-sanctioned
|
|
45
|
+
way for a model to convey extra intent.
|
|
46
|
+
- **"MCP has no protocol-level session."** The 2026-07-28 spec says it directly: "a server cannot
|
|
47
|
+
rely on implicit per-connection state to relate one tool call to the next"
|
|
48
|
+
([Stateful Tools](https://modelcontextprotocol.io/specification/2026-07-28/server/tools#stateful-tools)),
|
|
49
|
+
and the statelessness rules forbid inferring context from prior requests
|
|
50
|
+
([Statelessness](https://modelcontextprotocol.io/specification/2026-07-28/basic/index#statelessness)).
|
|
51
|
+
- **Sampling cannot be abused to obtain the context.** `sampling/createMessage` is
|
|
52
|
+
server-initiated with server-authored `messages`; `includeContext: "thisServer"/"allServers"`
|
|
53
|
+
(soft-deprecated) includes *MCP-server* context, not the host conversation, and requests are
|
|
54
|
+
human-reviewed
|
|
55
|
+
([sampling](https://modelcontextprotocol.io/specification/2025-11-25/client/sampling)). A server
|
|
56
|
+
could only ask a model to *guess* intent — not obtain the user's question.
|
|
57
|
+
- **Elicititation is interactive, not derivation.** `elicitation/create` asks the user a form/choice
|
|
58
|
+
question and waits ([2025-06-18+](https://modelcontextprotocol.io/specification/2025-06-18/client/elicitation));
|
|
59
|
+
it requires client capability (only Codex in this matrix has it, per
|
|
60
|
+
[mcp-compatibility.md](mcp-compatibility.md)) and an explicit round trip.
|
|
61
|
+
- **Tasks are state machines, not context.** The experimental 2025-11-25 `Task` object is
|
|
62
|
+
`taskId`/`status`/timestamps/`ttl`/`pollInterval` — no user data
|
|
63
|
+
([tasks](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks)).
|
|
64
|
+
- **`_meta` has no context convention.** Reserved keys are enumerated; vendors may add prefixed
|
|
65
|
+
keys, but no host documents sending conversation context there
|
|
66
|
+
([_meta](https://modelcontextprotocol.io/specification/2026-07-28/basic/index#meta)). Codex is the
|
|
67
|
+
one host observed adding its own key — `openai/entitlementContext`, carrying entitlement status
|
|
68
|
+
for zero-argument read-only plugin tools
|
|
69
|
+
([trusted_access.rs](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/codex-mcp/src/trusted_access.rs))
|
|
70
|
+
— not user context.
|
|
71
|
+
|
|
72
|
+
Conclusion: **for an MCP-connected host, channel A (the tool's input schema) is the only spec-borne
|
|
73
|
+
channel; channel B does not exist at the protocol layer.** Whether A works in practice depends on
|
|
74
|
+
each host's client, below.
|
|
75
|
+
|
|
76
|
+
## Open-source hosts, from source at the lock
|
|
77
|
+
|
|
78
|
+
### Codex 0.163.0 (rust-v0.163.0)
|
|
79
|
+
|
|
80
|
+
- **No client-side argument validation.** The model's `arguments` string is parsed as JSON (empty
|
|
81
|
+
allowed; invalid JSON becomes an error result) and the resulting `serde_json::Value` flows
|
|
82
|
+
unchanged to rmcp's `call_tool`
|
|
83
|
+
([mcp_tool_call.rs](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/core/src/mcp_tool_call.rs),
|
|
84
|
+
[connection_manager.rs](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/codex-mcp/src/connection_manager.rs)).
|
|
85
|
+
No JSON-Schema validator exists in the tree (only `schemars`, used to *generate* schemas for
|
|
86
|
+
built-in tools; codex-rs/Cargo.toml at the tag).
|
|
87
|
+
- **Input schemas reach the model essentially verbatim.** `mcp_tool_to_responses_api_tool` forwards
|
|
88
|
+
the server's `inputSchema` as the tool's `parameters`
|
|
89
|
+
([responses_api.rs](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/tools/src/responses_api.rs));
|
|
90
|
+
the only transformations are inserting an empty `properties` object when missing, sanitizing
|
|
91
|
+
boolean schemas, and a default 5,000-byte budget: over-budget schemas are progressively
|
|
92
|
+
compacted (strip descriptions → drop definitions → collapse deep objects → prune compositions)
|
|
93
|
+
([mcp_tool.rs](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/tools/src/mcp_tool.rs),
|
|
94
|
+
[json_schema.rs](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/tools/src/json_schema.rs),
|
|
95
|
+
[compaction.rs](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/tools/src/json_schema/compaction.rs)).
|
|
96
|
+
A small schema with one optional string property stays intact.
|
|
97
|
+
- **Channel B: none.** Codex's third-party integration surface at this tag is MCP servers; there is
|
|
98
|
+
no session/context API a server can call.
|
|
99
|
+
|
|
100
|
+
Verdict: **A feasible (nothing validates or strips arguments; schema forwarded), B impossible.**
|
|
101
|
+
|
|
102
|
+
### Pi 1.3.0 (v1.3.0)
|
|
103
|
+
|
|
104
|
+
- **The agent loop validates arguments against the tool's parameter schema before `execute`.**
|
|
105
|
+
`validateToolArguments` clones the arguments, normalizes `null` for optional properties, coerces
|
|
106
|
+
types (`Value.Convert`, plus JSON-Schema coercion for plain JSON-Schema tools), then runs a
|
|
107
|
+
TypeBox `Check`; failures come back to the model as `Validation failed for tool …` error results
|
|
108
|
+
([validation.ts](https://github.com/earendil-works/pi/blob/v1.3.0/packages/ai/src/utils/validation.ts),
|
|
109
|
+
[agent-loop.ts](https://github.com/earendil-works/pi/blob/v1.3.0/packages/agent/src/agent-loop.ts)).
|
|
110
|
+
A *declared optional* property therefore passes and reaches the tool; undeclared fields pass only
|
|
111
|
+
when the schema itself permits them.
|
|
112
|
+
- **MCP tools: schema forwarded, params passed through.** The adapter spreads the server's
|
|
113
|
+
`inputSchema` into the model-facing parameters (adding only `type: "object"` and an empty
|
|
114
|
+
`properties` when missing) and passes the validated `params` to the client's `callTool`, which
|
|
115
|
+
sends `{ name, arguments }` verbatim (a `_meta.progressToken` is added only when progress
|
|
116
|
+
reporting is on)
|
|
117
|
+
([tools.ts](https://github.com/earendil-works/pi/blob/v1.3.0/packages/coding-agent/src/extensions/mcp/tools.ts),
|
|
118
|
+
[client.ts](https://github.com/earendil-works/pi/blob/v1.3.0/packages/mcp/src/client.ts)).
|
|
119
|
+
- **Extension tools receive session access as a fifth `execute` argument.** At v1.3.0 the signature
|
|
120
|
+
is `execute(toolCallId, params, signal, onUpdate, ctx: ExtensionToolContext)`
|
|
121
|
+
([types.ts](https://github.com/earendil-works/pi/blob/v1.3.0/packages/coding-agent/src/core/extensions/types.ts)).
|
|
122
|
+
`ExtensionToolContext` extends `ExtensionContext`, whose `sessionManager` is a
|
|
123
|
+
`ReadonlySessionManager` exposing `buildSessionProjection()` — returning the model-visible
|
|
124
|
+
`messages: AgentMessage[]` (user messages included), plus `getEntries`/`getTree`/`getBranch`
|
|
125
|
+
([session-manager.ts](https://github.com/earendil-works/pi/blob/v1.3.0/packages/coding-agent/src/core/session-manager.ts)).
|
|
126
|
+
The extension docs at the tag document `ctx` for tools (`ctx.executeTool`, `ctx.sessionManager`)
|
|
127
|
+
([extensions.md](https://github.com/earendil-works/pi/blob/v1.3.0/packages/coding-agent/docs/extensions.md)).
|
|
128
|
+
The `ExtensionAPI` event surface (`input`, `message_end`, `tool_execution_*`) additionally lets an
|
|
129
|
+
extension track the user prompt as it arrives.
|
|
130
|
+
|
|
131
|
+
Verdict: **A feasible on both paths (declared optional TypeBox property; validated, then passed
|
|
132
|
+
through). B feasible on the extension path via the fifth `execute` argument — the handler can read
|
|
133
|
+
the session's user messages at call time. B impossible via MCP** (separate process, no session
|
|
134
|
+
API).
|
|
135
|
+
|
|
136
|
+
### OpenCode 2.0.32
|
|
137
|
+
|
|
138
|
+
Repo provenance first: `@opencode/cli@2.0.32`'s manifest points at
|
|
139
|
+
[github.com/anomalyco/opencode](https://github.com/anomalyco/opencode), which has the `v2.0.32`
|
|
140
|
+
tag (commit `843a6c5`); the `opencode-ai/opencode` repository's tags stop at `v0.0.x` and hold no
|
|
141
|
+
2.x tag. Facts below are from the tag plus the npm tarballs at 2.0.32
|
|
142
|
+
(`@opencode/plugin`, `@opencode/schema`, `@opencode/client`).
|
|
143
|
+
|
|
144
|
+
- **The tool runtime validates arguments against the tool's declared input schema before
|
|
145
|
+
`execute`.** `Tool.runtime.execute` decodes the model's input first: raw JSON-Schema inputs are
|
|
146
|
+
converted to an Effect codec and validated; failures return `Invalid arguments for tool "…":
|
|
147
|
+
… Update the arguments and call the tool again.`
|
|
148
|
+
([runtime.ts](https://github.com/anomalyco/opencode/blob/v2.0.32/packages/core/src/tool/runtime.ts)).
|
|
149
|
+
A plugin tool's plain JSON Schema `input` is forwarded to the model **as-is** (`inputJsonSchema`
|
|
150
|
+
returns it unchanged), so a declared optional parameter is both model-visible and validated.
|
|
151
|
+
- **`ToolContext` carries IDs only**: `sessionID`, `agent`, `messageID`, call `id`, `signal`,
|
|
152
|
+
`progress` ([tool.d.ts in @opencode/schema 2.0.32](https://registry.npmjs.org/@opencode/schema/2.0.32);
|
|
153
|
+
[tool.d.ts in @opencode/plugin 2.0.32](https://registry.npmjs.org/@opencode/plugin/2.0.32)).
|
|
154
|
+
- **But the plugin `Context.session` domain can read the conversation.** The picked `SessionDomain`
|
|
155
|
+
includes `context({ sessionID }) → SessionMessageInfo[]`, and `SessionMessageUser` has
|
|
156
|
+
`text: string` — the user's prompt text — plus attachments
|
|
157
|
+
([session.d.ts](https://registry.npmjs.org/@opencode/plugin/2.0.32),
|
|
158
|
+
[client types](https://registry.npmjs.org/@opencode/client/2.0.32)). Session hooks round it out:
|
|
159
|
+
`"prompt"` fires with the prompt itself, `"generate"`/`"context"` with `messages: Array<Message>`
|
|
160
|
+
([session.d.ts at 2.0.32](https://registry.npmjs.org/@opencode/plugin/2.0.32)). So a tool's
|
|
161
|
+
`execute` can call `ctx.session.context({ sessionID: context.sessionID })` at call time.
|
|
162
|
+
- **The native websearch provider interface carries only the query.**
|
|
163
|
+
`WebSearch.ProviderInput = Pick<Input, "query">`, the provider context is `{ signal }`, and core
|
|
164
|
+
invokes providers as `.execute({ query: input.query })`
|
|
165
|
+
([websearch.ts](https://github.com/anomalyco/opencode/blob/v2.0.32/packages/core/src/websearch.ts),
|
|
166
|
+
[websearch.d.ts](https://registry.npmjs.org/@opencode/schema/2.0.32)). The model-facing
|
|
167
|
+
`websearch` tool's input schema is fixed in host source to `query` alone
|
|
168
|
+
([tool/plugin/websearch.ts](https://github.com/anomalyco/opencode/blob/v2.0.32/packages/core/src/tool/plugin/websearch.ts)).
|
|
169
|
+
A provider gets no sessionID, so session auto-derivation on this path is not directly possible —
|
|
170
|
+
only heuristic correlation via the session hooks (which fire per model request with the
|
|
171
|
+
sessionID, but no API contract binds a provider call to a session).
|
|
172
|
+
|
|
173
|
+
Verdict: **tool path (`deepseek_fetch` / the `webfetch` override): A feasible (validated against
|
|
174
|
+
the declared schema; raw JSON Schema forwarded verbatim) and B feasible
|
|
175
|
+
(`ctx.session.context`). Websearch provider path (the search replacement this repo ships): neither
|
|
176
|
+
— the input schema is host-fixed to `query`, and the provider context has no session handle.**
|
|
177
|
+
|
|
178
|
+
### Cline 0.0.13
|
|
179
|
+
|
|
180
|
+
Closed source; the platform binary
|
|
181
|
+
([@cline/cli-linux-x64 0.0.13](https://registry.npmjs.org/@cline/cli-linux-x64/0.0.13), ~119 MB)
|
|
182
|
+
yielded the protocol facts already recorded — custom client negotiating `2024-11-05`,
|
|
183
|
+
text-content-only results ([mcp-compatibility.md](mcp-compatibility.md)). No primary source
|
|
184
|
+
documents whether the client validates tool arguments against `inputSchema` or mangles schemas;
|
|
185
|
+
strings cannot prove a runtime behavior either way, so this is **undeterminable at the lock**. The
|
|
186
|
+
2024-11-05 revision itself puts no validation obligation on clients and defines `arguments` as a
|
|
187
|
+
free-form object, so there is no protocol-level obstacle to channel A — merely no evidence for or
|
|
188
|
+
against host behavior. Channel B: none (MCP only, `paths` in hosts.jsonc).
|
|
189
|
+
|
|
190
|
+
## Proprietary hosts
|
|
191
|
+
|
|
192
|
+
No proprietary host documents a context channel; the question is whether anything documents
|
|
193
|
+
input-schema handling that would break an optional parameter.
|
|
194
|
+
|
|
195
|
+
- **Claude Code 2.1.303.** The [MCP docs](https://code.claude.com/docs/en/mcp) say nothing about
|
|
196
|
+
input schemas or argument validation. The
|
|
197
|
+
[changelog](https://raw.githubusercontent.com/anthropics/claude-code/main/CHANGELOG.md) documents
|
|
198
|
+
the mechanics indirectly, all at or before the lock: 2.1.300 — "Fixed a conversation failing on
|
|
199
|
+
every turn with a 400 error when the API rejected an MCP tool's input schema; Claude Code now
|
|
200
|
+
sends that tool without parameters for the rest of the conversation"; 2.1.246 — "Fixed MCP tool
|
|
201
|
+
arguments being sent as JSON strings when the parameter's schema is empty (`{}`)"; 2.1.30 —
|
|
202
|
+
prompt-cache invalidation "when tool descriptions or input schemas changed"; 2.0.50 — "bug
|
|
203
|
+
preventing calling MCP tools that have nested references in their input schemas". Together these
|
|
204
|
+
show the server's `inputSchema` is what the model provider sees and that arguments follow it;
|
|
205
|
+
no host-side validation is ever mentioned. **A feasible by this evidence; B none.**
|
|
206
|
+
- **Cursor 2026.10.08.** The [MCP docs](https://cursor.com/docs/mcp) describe tools only as
|
|
207
|
+
"Functions for the AI model to execute" and say nothing about input schemas, validation, or
|
|
208
|
+
context — and the protocol revision itself is unpinnable from primary sources
|
|
209
|
+
([mcp-compatibility.md](mcp-compatibility.md)). **No primary source either way for A; B none.**
|
|
210
|
+
- **Devin 3000.11.92.** The [MCP docs](https://docs.devin.ai/cli/extensibility/mcp/overview) and
|
|
211
|
+
[changelog](https://docs.devin.ai/cli/changelog) cover transport, OAuth, permissions, and
|
|
212
|
+
tool-level gating (`disabled_tools`, `mcp__server__tool` patterns) but nothing on input schemas
|
|
213
|
+
or argument validation; the nearest mechanisms (`PostToolUse` hooks, positional prompt arguments)
|
|
214
|
+
are not tool-input channels. **No primary source either way for A; B none.**
|
|
215
|
+
- **GitHub Copilot 1.0.98.** The
|
|
216
|
+
[MCP docs](https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-mcp-servers)
|
|
217
|
+
document per-server `tools` filtering only. The
|
|
218
|
+
[changelog](https://raw.githubusercontent.com/github/copilot-cli/main/changelog.md) shows MCP tool
|
|
219
|
+
schemas are forwarded to model providers verbatim enough that *provider-side* schema validation
|
|
220
|
+
fires, at or before the lock: 1.0.89 — "Gemini models no longer fail every request with 400
|
|
221
|
+
invalid request body when an MCP server exposes a tool whose schema puts a type or properties
|
|
222
|
+
beside anyOf"; 1.0.85 — "MCP tools with boolean property or array-item schemas work with Gemini
|
|
223
|
+
instead of causing a 400 error"; 1.0.61 — "Gemini models work correctly with MCP tools that use
|
|
224
|
+
nullable schema types". No host-side argument validation is mentioned. **A feasible by this
|
|
225
|
+
evidence; B none.**
|
|
226
|
+
|
|
227
|
+
## Verdicts at a glance
|
|
228
|
+
|
|
229
|
+
| Host | (A) model-filled optional param | (B) session auto-derivation | Load-bearing fact |
|
|
230
|
+
| --- | --- | --- | --- |
|
|
231
|
+
| Codex | Yes | No | No argument validation anywhere in the tool-call path; schema forwarded (compaction only above 5 KB) |
|
|
232
|
+
| Pi | Yes (extension and MCP paths) | Yes — extension path only | 5th `execute` arg exposes `sessionManager.buildSessionProjection()`; MCP path validated against the server's own schema |
|
|
233
|
+
| OpenCode | Yes — tool path; **no** — websearch provider | Yes — tool path; not directly — provider | Runtime validates against the declared schema and forwards raw JSON Schemas verbatim; `ctx.session.context` reads user text; provider input is host-fixed to `query` |
|
|
234
|
+
| Cline | Undeterminable (no primary source) | No | 2024-11-05 client; behavior not documented |
|
|
235
|
+
| Claude Code | Yes (changelog evidence) | No | Input schemas demonstrably reach the model API |
|
|
236
|
+
| Cursor | No primary source | No | Docs silent |
|
|
237
|
+
| Devin | No primary source | No | Docs/changelog silent |
|
|
238
|
+
| Copilot | Yes (changelog evidence) | No | Provider-side 400s driven by MCP schema shapes prove forwarding |
|
|
239
|
+
|
|
240
|
+
For every MCP-only host, channel A is the only candidate; where no primary source pins the
|
|
241
|
+
behavior (Cline, Cursor, Devin), an optional declared parameter is still spec-conformant on every
|
|
242
|
+
negotiated revision in the matrix.
|
|
243
|
+
|
|
244
|
+
## What this means for this repo
|
|
245
|
+
|
|
246
|
+
- **MCP server (`src/mcp/server.ts`).** The tool `inputSchema` is the only channel any MCP host
|
|
247
|
+
offers. The server declares its inputs as zod objects (`z.object({ query, original_question })`,
|
|
248
|
+
`z.object({ url })`) through SDK v2's `registerTool`; zod's default behavior strips undeclared
|
|
249
|
+
keys server-side, so a host-side pre-filled undeclared field would be dropped — whatever a host
|
|
250
|
+
sends must be *declared* in the schema to arrive in the handler. The declared optional string
|
|
251
|
+
surfaces in the JSON Schema every host in this note forwards (Codex and Pi verbatim-small,
|
|
252
|
+
OpenCode verbatim, Claude Code and Copilot per changelog evidence; Cline, Cursor, Devin
|
|
253
|
+
unproven but spec-conformant) — exactly the channel the shipped `original_question` rides.
|
|
254
|
+
- **OpenCode plugin (`src/opencode/plugin.ts`).** The fetch tools' `execute` receives a
|
|
255
|
+
`ToolContext` with `sessionID`, and the plugin `Context` can read
|
|
256
|
+
`ctx.session.context({ sessionID })` — user messages with their `text` — at call time, so
|
|
257
|
+
channel B exists here without touching schemas. The `websearch` provider replacement — the path
|
|
258
|
+
this repo uses for search — has neither channel at 2.0.32: its model-facing input schema is
|
|
259
|
+
fixed in host source to `query`, and its provider context is `{ signal }` only. Note also that
|
|
260
|
+
`FETCH_INPUT` sets `additionalProperties: false`, which matters if a parameter is ever added on
|
|
261
|
+
channel A: an undeclared field would be rejected by OpenCode's runtime validation with a
|
|
262
|
+
retryable error.
|
|
263
|
+
- **Pi extension (`src/pi/extension.ts`).** The search handler reads the fifth `execute`
|
|
264
|
+
argument (`ExtensionToolContext`), whose `sessionManager.buildSessionProjection()` returns the
|
|
265
|
+
model-visible messages, user prompts included — readable synchronously at call time, so channel
|
|
266
|
+
B exists on this path; the shipped adapter uses it as the blank-input fallback. Channel A is
|
|
267
|
+
equally open: the TypeBox `parameters` are what the agent loop validates against, and
|
|
268
|
+
`Type.Optional(Type.String(...))` properties pass validation when the model fills them. The
|
|
269
|
+
extension runs in-process, so B does not pay the MCP detour.
|
|
270
|
+
|
|
271
|
+
## Sources
|
|
272
|
+
|
|
273
|
+
### Specification
|
|
274
|
+
|
|
275
|
+
- MCP tools: [2024-11-05](https://modelcontextprotocol.io/specification/2024-11-05/server/tools) ·
|
|
276
|
+
[2025-06-18](https://modelcontextprotocol.io/specification/2025-06-18/server/tools) ·
|
|
277
|
+
[2025-11-25](https://modelcontextprotocol.io/specification/2025-11-25/server/tools) ·
|
|
278
|
+
[2026-07-28](https://modelcontextprotocol.io/specification/2026-07-28/server/tools)
|
|
279
|
+
(Stateful Tools, MRTR retry params, `x-mcp-header`)
|
|
280
|
+
- [2025-06-18 schema.json (CallToolRequest)](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/2025-06-18/schema.json)
|
|
281
|
+
- [2025-11-25 sampling](https://modelcontextprotocol.io/specification/2025-11-25/client/sampling) ·
|
|
282
|
+
[2025-11-25 tasks (experimental)](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks)
|
|
283
|
+
- [2026-07-28 overview (`_meta`, statelessness)](https://modelcontextprotocol.io/specification/2026-07-28/basic/index)
|
|
284
|
+
|
|
285
|
+
### Open-source hosts
|
|
286
|
+
|
|
287
|
+
- Codex: [rust-v0.163.0 tag](https://github.com/openai/codex/tree/rust-v0.163.0) —
|
|
288
|
+
[mcp_tool_call.rs (argument parsing, no validation)](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/core/src/mcp_tool_call.rs),
|
|
289
|
+
[connection_manager.rs (call_tool passthrough)](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/codex-mcp/src/connection_manager.rs),
|
|
290
|
+
[responses_api.rs](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/tools/src/responses_api.rs),
|
|
291
|
+
[mcp_tool.rs](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/tools/src/mcp_tool.rs),
|
|
292
|
+
[json_schema.rs](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/tools/src/json_schema.rs),
|
|
293
|
+
[compaction.rs (5 KB default budget)](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/tools/src/json_schema/compaction.rs),
|
|
294
|
+
[trusted_access.rs (openai/entitlementContext)](https://github.com/openai/codex/blob/rust-v0.163.0/codex-rs/codex-mcp/src/trusted_access.rs)
|
|
295
|
+
- Pi: [v1.3.0 tag](https://github.com/earendil-works/pi/tree/v1.3.0) —
|
|
296
|
+
[extensions/mcp/tools.ts (toParameters, execute passthrough)](https://github.com/earendil-works/pi/blob/v1.3.0/packages/coding-agent/src/extensions/mcp/tools.ts),
|
|
297
|
+
[agent-loop.ts (prepare/validate/execute)](https://github.com/earendil-works/pi/blob/v1.3.0/packages/agent/src/agent-loop.ts),
|
|
298
|
+
[validation.ts (validateToolArguments)](https://github.com/earendil-works/pi/blob/v1.3.0/packages/ai/src/utils/validation.ts),
|
|
299
|
+
[mcp/client.ts (callTool)](https://github.com/earendil-works/pi/blob/v1.3.0/packages/mcp/src/client.ts),
|
|
300
|
+
[extensions/types.ts (ToolDefinition.execute 5th arg, ExtensionAPI)](https://github.com/earendil-works/pi/blob/v1.3.0/packages/coding-agent/src/core/extensions/types.ts),
|
|
301
|
+
[session-manager.ts (ReadonlySessionManager)](https://github.com/earendil-works/pi/blob/v1.3.0/packages/coding-agent/src/core/session-manager.ts),
|
|
302
|
+
[extensions.md at the tag](https://github.com/earendil-works/pi/blob/v1.3.0/packages/coding-agent/docs/extensions.md)
|
|
303
|
+
- OpenCode: [anomalyco/opencode v2.0.32 tag](https://github.com/anomalyco/opencode/tree/v2.0.32)
|
|
304
|
+
(repository URL from
|
|
305
|
+
[@opencode/cli 2.0.32](https://registry.npmjs.org/@opencode/cli/2.0.32)) —
|
|
306
|
+
[tool/runtime.ts (input validation, schema forwarding)](https://github.com/anomalyco/opencode/blob/v2.0.32/packages/core/src/tool/runtime.ts),
|
|
307
|
+
[websearch.ts (ProviderInput, execute({query}))](https://github.com/anomalyco/opencode/blob/v2.0.32/packages/core/src/websearch.ts),
|
|
308
|
+
[tool/plugin/websearch.ts (fixed query schema)](https://github.com/anomalyco/opencode/blob/v2.0.32/packages/core/src/tool/plugin/websearch.ts);
|
|
309
|
+
npm tarballs at 2.0.32:
|
|
310
|
+
[@opencode/plugin](https://registry.npmjs.org/@opencode/plugin/2.0.32)
|
|
311
|
+
(ToolContext, Context, SessionDomain hooks),
|
|
312
|
+
[@opencode/schema](https://registry.npmjs.org/@opencode/schema/2.0.32)
|
|
313
|
+
(Tool.Context, WebSearch.ProviderInput),
|
|
314
|
+
[@opencode/client](https://registry.npmjs.org/@opencode/client/2.0.32)
|
|
315
|
+
(session.context → SessionMessageInfo[], SessionMessageUser.text)
|
|
316
|
+
- Cline: [@cline/cli-linux-x64 0.0.13](https://registry.npmjs.org/@cline/cli-linux-x64/0.0.13)
|
|
317
|
+
(manifest only; behavior undeterminable) and prior binary analysis recorded in
|
|
318
|
+
[mcp-compatibility.md](mcp-compatibility.md)
|
|
319
|
+
|
|
320
|
+
### Proprietary hosts
|
|
321
|
+
|
|
322
|
+
- Claude Code: [changelog](https://raw.githubusercontent.com/anthropics/claude-code/main/CHANGELOG.md)
|
|
323
|
+
(entries 2.0.50, 2.1.30, 2.1.246, 2.1.300 — all ≤ the 2.1.303 lock),
|
|
324
|
+
[MCP docs](https://code.claude.com/docs/en/mcp)
|
|
325
|
+
- Cursor: [MCP docs](https://cursor.com/docs/mcp) (silent on the question)
|
|
326
|
+
- Devin: [MCP overview](https://docs.devin.ai/cli/extensibility/mcp/overview),
|
|
327
|
+
[changelog](https://docs.devin.ai/cli/changelog) (silent on the question)
|
|
328
|
+
- GitHub Copilot: [changelog](https://raw.githubusercontent.com/github/copilot-cli/main/changelog.md)
|
|
329
|
+
(entries 1.0.61, 1.0.85, 1.0.89 — all ≤ the 1.0.98 lock),
|
|
330
|
+
[MCP docs](https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-mcp-servers)
|
|
331
|
+
|
|
332
|
+
### DeepSeek API
|
|
333
|
+
|
|
334
|
+
- [Search & Fetch guide](https://api-docs.deepseek.com/guides/search) (`ori_question` optional,
|
|
335
|
+
1–128 chars; parameter table transcribed in
|
|
336
|
+
[search-api-defaults.md](search-api-defaults.md))
|