@namzu/sdk 25.0.0 → 26.1.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 +182 -0
- package/README.md +1 -1
- package/dist/connector/mcp/index.d.ts +1 -0
- package/dist/connector/mcp/index.d.ts.map +1 -1
- package/dist/connector/mcp/index.js +3 -0
- package/dist/connector/mcp/index.js.map +1 -1
- package/dist/connector/mcp/server-stdio.d.ts +62 -0
- package/dist/connector/mcp/server-stdio.d.ts.map +1 -0
- package/dist/connector/mcp/server-stdio.js +121 -0
- package/dist/connector/mcp/server-stdio.js.map +1 -0
- package/dist/connector/mcp/stdio.d.ts +11 -0
- package/dist/connector/mcp/stdio.d.ts.map +1 -1
- package/dist/connector/mcp/stdio.js +106 -1
- package/dist/connector/mcp/stdio.js.map +1 -1
- package/dist/constants/telemetry/index.d.ts +15 -1
- package/dist/constants/telemetry/index.d.ts.map +1 -1
- package/dist/constants/telemetry/index.js +15 -1
- package/dist/constants/telemetry/index.js.map +1 -1
- package/dist/provider/fallback.d.ts.map +1 -1
- package/dist/provider/fallback.js +8 -2
- package/dist/provider/fallback.js.map +1 -1
- package/dist/provider/retry.d.ts.map +1 -1
- package/dist/provider/retry.js +10 -2
- package/dist/provider/retry.js.map +1 -1
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +12 -0
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/session/workspace/git-worktree.d.ts +15 -0
- package/dist/session/workspace/git-worktree.d.ts.map +1 -1
- package/dist/session/workspace/git-worktree.js +55 -1
- package/dist/session/workspace/git-worktree.js.map +1 -1
- package/dist/tools/builtins/bash.d.ts.map +1 -1
- package/dist/tools/builtins/bash.js +35 -0
- package/dist/tools/builtins/bash.js.map +1 -1
- package/dist/tools/coordinator/agent.d.ts.map +1 -1
- package/dist/tools/coordinator/agent.js +12 -0
- package/dist/tools/coordinator/agent.js.map +1 -1
- package/dist/tools/coordinator/index.d.ts.map +1 -1
- package/dist/tools/coordinator/index.js +134 -6
- package/dist/tools/coordinator/index.js.map +1 -1
- package/dist/types/connector/mcp.d.ts +17 -0
- package/dist/types/connector/mcp.d.ts.map +1 -1
- package/dist/types/provider/interface.d.ts +23 -2
- package/dist/types/provider/interface.d.ts.map +1 -1
- package/dist/types/sandbox/index.d.ts +23 -0
- package/dist/types/sandbox/index.d.ts.map +1 -1
- package/dist/types/sandbox/index.js.map +1 -1
- package/package.json +1 -1
- package/src/connector/mcp/index.ts +3 -0
- package/src/connector/mcp/server-stdio.ts +137 -0
- package/src/connector/mcp/stdio.ts +106 -1
- package/src/constants/telemetry/index.ts +16 -1
- package/src/provider/fallback.ts +8 -2
- package/src/provider/retry.ts +10 -2
- package/src/registry/tool/execute.ts +12 -0
- package/src/session/workspace/git-worktree.ts +55 -1
- package/src/tools/builtins/bash.ts +34 -0
- package/src/tools/coordinator/agent.ts +12 -0
- package/src/tools/coordinator/index.ts +144 -8
- package/src/types/connector/mcp.ts +17 -0
- package/src/types/provider/interface.ts +23 -2
- package/src/types/sandbox/index.ts +23 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,187 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 26.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3f44f0d: A command running in a sandbox now reports progress while it runs
|
|
8
|
+
|
|
9
|
+
Both halves of this existed and neither was connected to the other.
|
|
10
|
+
|
|
11
|
+
Every container worker streams its output a chunk at a time — the wire has always carried `stdout_delta` and `stderr_delta` events — and every backend concatenated those chunks into a string and returned it when the process exited. Separately, `ToolContext.report` exists precisely to answer "is it still working?", is supplied per call by the executor, emits a `tool_progress` event, and is mapped onto the event stream for live consumers. It had **no caller anywhere in the tree**.
|
|
12
|
+
|
|
13
|
+
So a command that ran for eight minutes said nothing for eight minutes, over a transport that had been reporting the whole time.
|
|
14
|
+
|
|
15
|
+
**New:** `SandboxExecOptions.onOutput`, called as output arrives. Optional and additive — a backend that cannot stream never calls it, and `SandboxExecResult.stdout` still carries the complete output either way, so a caller that ignores it behaves exactly as before. Wired through the two container backends that carry the streaming worker protocol.
|
|
16
|
+
|
|
17
|
+
**The `bash` builtin now uses it**, sending the last non-empty line of each chunk to `context.report`. A progress slot renders one line and replaces it, so sending a whole chunk would put a wall of text in a space that shows one line of it.
|
|
18
|
+
|
|
19
|
+
Progress is ephemeral by design — `tool_progress` is excluded from the durable transcript so a tool reporting every file it compiles cannot write thousands of lines into the record. The model is still given `result.stdout`; this is a status signal, not a second copy of the output.
|
|
20
|
+
|
|
21
|
+
- 2737f74: The MCP server has a transport, and a failing post-checkout hook no longer discards a good worktree
|
|
22
|
+
|
|
23
|
+
Two independent gaps, both found by studying how a comparable product solves the same problems. Neither is a port: the code here is namzu's, and in both cases the missing piece was smaller than it looked because the machinery already existed.
|
|
24
|
+
|
|
25
|
+
**`MCPServer` had no way to run.** It is a complete implementation — `initialize`, `tools/list`, `tools/call`, resource and prompt providers — and nothing anywhere constructed one, because every transport in `connector/mcp/` is the _client_ side: they connect this process to somebody else's server. `ServerStdioTransport` is the other end, so somebody else's client can drive namzu.
|
|
26
|
+
|
|
27
|
+
Stdio first, deliberately. The client spawns the server as a child process, so there is no port, no bind address, and no inbound authentication question to answer wrongly. Note that stdout belongs to the protocol on this transport — a stray write corrupts the stream. This repository's logger writes to stderr, which is what makes it safe.
|
|
28
|
+
|
|
29
|
+
**`GitWorktreeDriver.create` trusted the exit code.** `git worktree add` runs the repository's post-checkout hook _after_ the checkout completes, so a hook that fails or is killed by a timeout reports failure over a worktree that is finished and usable. Trusting the status threw that worktree away and leaked it — the path stays registered, so the next attempt fails differently, with "already exists".
|
|
30
|
+
|
|
31
|
+
`create` now checks the repository when the command reports failure, and accepts only a worktree registered under this exact path carrying the branch this call asked for. A registered path alone proves nothing: it can be a half-finished checkout or one somebody else owns, and those two are indistinguishable from here. Any error while checking counts as a failure, because this runs on a path that has already gone wrong once.
|
|
32
|
+
|
|
33
|
+
No behaviour changes for a `create` that succeeds — the check runs only on the failure path.
|
|
34
|
+
|
|
35
|
+
- bac980a: `approve_plan` now advertises a closed model-facing input schema, and its
|
|
36
|
+
string fallback stops turning markup into steps.
|
|
37
|
+
|
|
38
|
+
A model that serialises `steps` instead of building it tends to reach for
|
|
39
|
+
XML. The fallback split that string on newlines, so `<steps>`, `<step>` and
|
|
40
|
+
`</step>` each became a step — and a host numbered them in its approval card
|
|
41
|
+
and asked a person to approve `</steps>`. Observed on a real run.
|
|
42
|
+
|
|
43
|
+
Two changes, in the order they matter:
|
|
44
|
+
|
|
45
|
+
- `modelInputSchema` + `enforceModelInput`, the same instrument
|
|
46
|
+
`ask_user_question` already carries for the same failure. A capable
|
|
47
|
+
provider now constrains generation to the closed shape, so the array is
|
|
48
|
+
not serialised in the first place. The schema stays inside the strict
|
|
49
|
+
subset (`assertStrictSchema` is what would refuse it).
|
|
50
|
+
- The fallback reads the `<description>` blocks the model named when there
|
|
51
|
+
are any, drops tag-only lines when there are not, and yields no steps at
|
|
52
|
+
all for a string carrying no words — rather than inventing one that reads
|
|
53
|
+
`<steps>`.
|
|
54
|
+
|
|
55
|
+
Nothing to do on upgrade. A host that renders `plan.steps` verbatim gets
|
|
56
|
+
sentences where it used to get fragments; a host that already worked around
|
|
57
|
+
this can drop the workaround.
|
|
58
|
+
|
|
59
|
+
### Patch Changes
|
|
60
|
+
|
|
61
|
+
- fcc9a41: The `Agent` tool now bounds a delegated run by the hour, like its twin
|
|
62
|
+
|
|
63
|
+
`buildAgentTool` declared no `timeoutMs`, and declaring nothing is not "no deadline" — it is the executor's `DEFAULT_TOOL_TIMEOUT_MS`, 120 seconds. That is a reasonable bound for a tool call and an absurd one for a call that runs an entire agent to completion and blocks on it.
|
|
64
|
+
|
|
65
|
+
Its twin `create_task`, built by `buildCoordinatorTools` in the sibling module, has declared `DELEGATION_TIMEOUT_MS` (one hour) all along, and the measurement behind that number is recorded in its docblock: three delegated children took 4m21s, 5m58s and 8m04s, and all three parents gave up at 120 seconds. That fix reached one of the two delegation surfaces and never carried to the other.
|
|
66
|
+
|
|
67
|
+
**What changes for you.** A delegated run through the `Agent` tool that takes longer than two minutes now completes instead of being abandoned. If you were relying on the 120-second bound to catch a wedged child, note that the run budget and the iteration ceiling both still apply above this, and a wedged child is still caught — an hour later rather than two minutes later.
|
|
68
|
+
|
|
69
|
+
The two tools are now asserted to agree, so a future change to one deadline fails until it moves the other. That is the assertion, rather than each tool's number separately: drifting apart is the defect, and two independent assertions pass while it happens.
|
|
70
|
+
|
|
71
|
+
## 26.0.0
|
|
72
|
+
|
|
73
|
+
### Major Changes
|
|
74
|
+
|
|
75
|
+
- b902ecb: A stdio server is handed what it was granted, not everything the host holds
|
|
76
|
+
|
|
77
|
+
`StdioTransport` spawned its child with `{ ...process.env, ...config.env }`, so every connected server received every environment variable the host process had. Measured through the real transport: **119 variables on a developer machine, including a secret planted in the parent for the probe.** A server that needs one token was handed all of them, and nothing in its configuration said so — the grant was invisible because it was total.
|
|
78
|
+
|
|
79
|
+
The child now receives process plumbing (`PATH`, `HOME`/`USERPROFILE`, `SystemRoot`, `ComSpec`, `TEMP`, locale, and the rest of that kind), plus whatever the configuration names.
|
|
80
|
+
|
|
81
|
+
**What breaks.** A server that was reading a credential straight out of your environment stops finding it. That is the whole point of the change, and it will look like the server failing to authenticate rather than like a configuration change, so it is worth knowing before the upgrade rather than after.
|
|
82
|
+
|
|
83
|
+
**What to do.** Name what the server may have:
|
|
84
|
+
|
|
85
|
+
```toml
|
|
86
|
+
[mcpServers.issues]
|
|
87
|
+
command = "some-mcp-server"
|
|
88
|
+
inheritEnv = ["GITHUB_TOKEN"]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`inheritEnv` names variables to pass through from your own environment. Prefer it over `env` for anything secret — `env` writes the literal value into the config file, and this leaves the value where it already lives. A named variable the parent does not hold is absent from the child rather than empty, so a server's own `if (!token)` still works; it does not fail the spawn.
|
|
92
|
+
|
|
93
|
+
**Plugin-declared servers get no `inheritEnv`, deliberately.** A plugin that could name the host variables its server receives would be awarding itself a credential grant, which is not a plugin's to award. A plugin-declared server gets plumbing plus the literal `env` in its own manifest; if it needs a host credential, declare that server in `mcpServers` instead, where the operator is the one naming it.
|
|
94
|
+
|
|
95
|
+
The tests assert on the environment the child actually receives, driving a real spawn — not on whether the configuration was accepted. A test of the second kind passes against the version this replaces.
|
|
96
|
+
|
|
97
|
+
- e2506f4: The tool-call id attribute is spelled the way the convention spells it, and something now sets it
|
|
98
|
+
|
|
99
|
+
`GENAI.TOOL_CALL_ID` was `'gen_ai.tool.call_id'` — one underscore where the
|
|
100
|
+
GenAI attribute registry has a dot, and where the two constants beside it in the
|
|
101
|
+
same object (`gen_ai.tool.name`, `gen_ai.tool.type`) already had one. Its value
|
|
102
|
+
is now `'gen_ai.tool.call.id'`.
|
|
103
|
+
|
|
104
|
+
**What breaks.** The exported constant is `as const`, so both its value and its
|
|
105
|
+
literal type change. If you import it and stamp it on your own spans, those
|
|
106
|
+
spans start carrying a different key, and a saved query, dashboard panel or
|
|
107
|
+
alert that groups by `gen_ai.tool.call_id` will match nothing after the upgrade
|
|
108
|
+
— it will read as "no tool calls", not as an error. Anything that pinned the
|
|
109
|
+
old literal as a type (`typeof GENAI.TOOL_CALL_ID`, or a union built from it)
|
|
110
|
+
fails to compile.
|
|
111
|
+
|
|
112
|
+
**What to do.** Repoint anything keyed on `gen_ai.tool.call_id` at
|
|
113
|
+
`gen_ai.tool.call.id`. If you referenced the constant rather than the string,
|
|
114
|
+
there is nothing to change beyond taking the upgrade. Traces already in your
|
|
115
|
+
backend keep the old key; a query that has to span the upgrade needs both for
|
|
116
|
+
as long as the old retention window lasts.
|
|
117
|
+
|
|
118
|
+
There is no deprecation window, and the reason is that no working code needs
|
|
119
|
+
one: nothing in this SDK ever emitted the attribute, under either spelling. The
|
|
120
|
+
constant was exported with no writer at all — `registry/tool/execute.ts` stamped
|
|
121
|
+
the tool name and the tool type onto the span and stopped — so no namzu-produced
|
|
122
|
+
trace has ever carried the old key, and there is nothing to migrate off it.
|
|
123
|
+
|
|
124
|
+
**What is added.** The tool span now stamps the id of the call it is about,
|
|
125
|
+
taken from `ToolContext.toolUseId`, which the run loop already sets per call.
|
|
126
|
+
Before this, a trace showing four tool spans with the same name in one turn
|
|
127
|
+
could not say which span answered which `tool_use` block. The attribute is
|
|
128
|
+
omitted rather than set to `undefined` when there is no call to correlate to —
|
|
129
|
+
a host invoking a tool directly, outside a run.
|
|
130
|
+
|
|
131
|
+
Tool **arguments** and **results** are deliberately still not recorded. They are
|
|
132
|
+
the thing an incident review wants first and they are also where a secret
|
|
133
|
+
travels, so they want a redaction design and a test for it rather than a ride
|
|
134
|
+
along with a spelling fix.
|
|
135
|
+
|
|
136
|
+
### Minor Changes
|
|
137
|
+
|
|
138
|
+
- 1f8aef7: a provider health probe can be told which model to check
|
|
139
|
+
|
|
140
|
+
`LLMProvider.healthCheck` and `LLMProvider.doctorCheck` now take an optional
|
|
141
|
+
`model`. Both were declared no-argument, and that made a model-aware probe
|
|
142
|
+
unreachable: `ProviderRegistry.create()` hands back an `LLMProvider`, not the
|
|
143
|
+
concrete driver, so a driver whose config carries no model had nowhere to get
|
|
144
|
+
one and hardcoded an id instead — which is how one of them came to probe a model
|
|
145
|
+
nobody ran and could not pass at all.
|
|
146
|
+
|
|
147
|
+
**What you do: nothing.** The parameter is optional on an already-optional
|
|
148
|
+
method, so an existing implementation that takes no argument still satisfies the
|
|
149
|
+
interface and an existing call site still compiles. A driver is free to ignore
|
|
150
|
+
the argument — one that probes an endpoint rather than a model has no use for
|
|
151
|
+
it — and passing it is always safe.
|
|
152
|
+
|
|
153
|
+
`doctorCheck` may now return a SUBTYPE of `DoctorCheckResult`, so a driver can
|
|
154
|
+
carry its own machine-readable detail while `runDoctor()` keeps reading
|
|
155
|
+
`status`.
|
|
156
|
+
|
|
157
|
+
`withProviderRetry` and `withProviderFallback` forward the model to the wrapped
|
|
158
|
+
driver. They rebuilt the provider as an object literal and spelled the forwarded
|
|
159
|
+
methods `() => provider.healthCheck?.()`, which would have dropped the argument
|
|
160
|
+
silently: the call still happens, the driver still answers, and the answer is
|
|
161
|
+
"there was nothing to check" — an unusable probe produced by wrapping alone.
|
|
162
|
+
|
|
163
|
+
### Patch Changes
|
|
164
|
+
|
|
165
|
+
- 2458b78: The README no longer promises reranking the retriever does not implement
|
|
166
|
+
|
|
167
|
+
`README.md` described `rag/retriever.ts` as "the retrieval query path with
|
|
168
|
+
configurable top-k, threshold, and reranking". There is no rerank stage and
|
|
169
|
+
never was: no field on `RetrievalConfig`, no member in
|
|
170
|
+
`DEFAULT_RETRIEVAL_CONFIG`, no method on the `Retriever` interface, and no
|
|
171
|
+
stage in `DefaultRetriever.retrieve`, which runs vector, keyword (BM25) or
|
|
172
|
+
hybrid search and slices to `topK`. `rerank` appeared exactly once in the
|
|
173
|
+
repository, in that sentence.
|
|
174
|
+
|
|
175
|
+
Nothing errors when a reader configures for it, because there is no setting to
|
|
176
|
+
set — you simply receive first-stage results and believe they were reranked.
|
|
177
|
+
The line now describes what the file does and says outright that there is no
|
|
178
|
+
rerank stage. This is a documentation fix; no behaviour changes.
|
|
179
|
+
|
|
180
|
+
The capability is a reasonable thing to want and is deliberately not built
|
|
181
|
+
here. Published results include cases where a reranker scores _below_ the
|
|
182
|
+
first stage, so it wants a retrieval eval beside it rather than an assumption
|
|
183
|
+
that adding one is an improvement.
|
|
184
|
+
|
|
3
185
|
## 25.0.0
|
|
4
186
|
|
|
5
187
|
### Major Changes
|
package/README.md
CHANGED
|
@@ -239,7 +239,7 @@ RAG is a full kernel subsystem, not a bolt-on. The pipeline:
|
|
|
239
239
|
- `rag/ingestion.ts` — end-to-end ingest: document → chunks → embeddings → vector store.
|
|
240
240
|
- `rag/vector-store.ts` — the `VectorStore` interface, tenant-scoped via `TenantId`. Bring your own backend (pgvector, Pinecone, an in-memory impl for tests).
|
|
241
241
|
- `rag/knowledge-base.ts` — a named collection of documents with metadata and config.
|
|
242
|
-
- `rag/retriever.ts` — the retrieval query path with configurable top-k
|
|
242
|
+
- `rag/retriever.ts` — the retrieval query path: vector, keyword (BM25) or hybrid, with configurable top-k and score threshold. Hybrid normalises both rankings before blending them by `hybridAlpha`. **There is no rerank stage.** This line used to promise one; there was no rerank stage behind it and no setting to turn it on, so a reader could configure for it and receive nothing.
|
|
243
243
|
- `rag/context-assembler.ts` — turns retrieval hits into prompt-ready context windows.
|
|
244
244
|
- `rag/rag-tool.ts` — a first-class tool your agent can invoke, not an external integration.
|
|
245
245
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { StdioTransport } from './stdio.js';
|
|
2
2
|
export { HttpSseTransport } from './http-sse.js';
|
|
3
3
|
export { StreamableHttpTransport } from './streamable-http.js';
|
|
4
|
+
export { ServerStdioTransport } from './server-stdio.js';
|
|
4
5
|
export { MCPClient } from './client.js';
|
|
5
6
|
export { mcpToolToToolDefinition, toolDefinitionToMCPTool, mcpJsonSchemaToZod, zodToMCPJsonSchema, mcpToolResultToToolResult, toolResultToMCPToolResult, } from './adapter.js';
|
|
6
7
|
export { MCPToolDiscovery } from './discovery.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAG9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC,OAAO,EACN,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,GACzB,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAErF,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAA;AAE1E,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC1D,YAAY,EACX,qBAAqB,EACrB,yBAAyB,EACzB,uBAAuB,GACvB,MAAM,aAAa,CAAA;AAEpB,YAAY,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC9F,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export { StdioTransport } from './stdio.js';
|
|
2
2
|
export { HttpSseTransport } from './http-sse.js';
|
|
3
3
|
export { StreamableHttpTransport } from './streamable-http.js';
|
|
4
|
+
// The server half. The three above connect this process to somebody
|
|
5
|
+
// else's MCP server; this one lets somebody else's client drive ours.
|
|
6
|
+
export { ServerStdioTransport } from './server-stdio.js';
|
|
4
7
|
export { MCPClient } from './client.js';
|
|
5
8
|
export { mcpToolToToolDefinition, toolDefinitionToMCPTool, mcpJsonSchemaToZod, zodToMCPJsonSchema, mcpToolResultToToolResult, toolResultToMCPToolResult, } from './adapter.js';
|
|
6
9
|
export { MCPToolDiscovery } from './discovery.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/connector/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/connector/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAC9D,oEAAoE;AACpE,sEAAsE;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC,OAAO,EACN,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,GACzB,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAErF,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAA;AAE1E,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAQ1D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Readable, Writable } from 'node:stream';
|
|
2
|
+
import type { MCPJsonRpcMessage, MCPTransport } from '../../types/connector/mcp.js';
|
|
3
|
+
/**
|
|
4
|
+
* The server half of stdio, so `MCPServer` has something to run on.
|
|
5
|
+
*
|
|
6
|
+
* `MCPServer` is a complete implementation — `initialize`, `tools/list`,
|
|
7
|
+
* `tools/call`, resource and prompt providers — and nothing anywhere
|
|
8
|
+
* constructed one, because every transport in this directory is the
|
|
9
|
+
* CLIENT side. `StdioTransport` spawns a child and talks to its streams;
|
|
10
|
+
* this reads the streams THIS process was given. Same interface, opposite
|
|
11
|
+
* end of the pipe.
|
|
12
|
+
*
|
|
13
|
+
* Stdio is the first transport rather than an afterthought: a client
|
|
14
|
+
* spawns the server as a child process, so there is no port, no bind
|
|
15
|
+
* address and no inbound authentication question to get wrong. The
|
|
16
|
+
* boundary is the process, and the process was started by the client.
|
|
17
|
+
*
|
|
18
|
+
* **stdout belongs to the protocol.** A single stray `console.log`
|
|
19
|
+
* anywhere in the process corrupts the message stream, and the symptom is
|
|
20
|
+
* a client that reports malformed JSON rather than anything naming the
|
|
21
|
+
* culprit. This repository's logger already writes to stderr, which is
|
|
22
|
+
* what makes this transport safe to add; keep it that way.
|
|
23
|
+
*/
|
|
24
|
+
export declare class ServerStdioTransport implements MCPTransport {
|
|
25
|
+
private readonly input;
|
|
26
|
+
private readonly output;
|
|
27
|
+
private buffer;
|
|
28
|
+
private connected;
|
|
29
|
+
private readonly log;
|
|
30
|
+
private messageHandler?;
|
|
31
|
+
private closeHandler?;
|
|
32
|
+
private errorHandler?;
|
|
33
|
+
private readonly onData;
|
|
34
|
+
private readonly onEnd;
|
|
35
|
+
private readonly onStreamError;
|
|
36
|
+
/**
|
|
37
|
+
* Streams are injected rather than read from `process` directly so a
|
|
38
|
+
* test can drive this without owning the process's own stdio — a test
|
|
39
|
+
* that replaced `process.stdin` would break every other test sharing
|
|
40
|
+
* the runner.
|
|
41
|
+
*/
|
|
42
|
+
constructor(streams?: {
|
|
43
|
+
input?: Readable;
|
|
44
|
+
output?: Writable;
|
|
45
|
+
});
|
|
46
|
+
connect(): Promise<void>;
|
|
47
|
+
close(): Promise<void>;
|
|
48
|
+
send(message: MCPJsonRpcMessage): Promise<void>;
|
|
49
|
+
onMessage(handler: (message: MCPJsonRpcMessage) => void): void;
|
|
50
|
+
onClose(handler: () => void): void;
|
|
51
|
+
onError(handler: (error: Error) => void): void;
|
|
52
|
+
isConnected(): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* A chunk is not a message. Reads arrive at whatever size the pipe
|
|
55
|
+
* hands over, so one read can carry half a message, several messages,
|
|
56
|
+
* or the tail of one and the head of the next. Buffering until a
|
|
57
|
+
* newline is the whole protocol framing.
|
|
58
|
+
*/
|
|
59
|
+
private consume;
|
|
60
|
+
private deliver;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=server-stdio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-stdio.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/server-stdio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAErD,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAGnF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,oBAAqB,YAAW,YAAY;IACxD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAE5B,OAAO,CAAC,cAAc,CAAC,CAAsC;IAC7D,OAAO,CAAC,YAAY,CAAC,CAAY;IACjC,OAAO,CAAC,YAAY,CAAC,CAAwB;IAE7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwD;IAC/E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAGrB;IACD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiD;IAE/E;;;;;OAKG;gBACS,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,QAAQ,CAAC;QAAC,MAAM,CAAC,EAAE,QAAQ,CAAA;KAAE;IAMvD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAUxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAStB,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrD,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI;IAI9D,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI;IAIlC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI9C,WAAW,IAAI,OAAO;IAItB;;;;;OAKG;IACH,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,OAAO;CAmBf"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { getRootLogger } from '../../utils/logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* The server half of stdio, so `MCPServer` has something to run on.
|
|
4
|
+
*
|
|
5
|
+
* `MCPServer` is a complete implementation — `initialize`, `tools/list`,
|
|
6
|
+
* `tools/call`, resource and prompt providers — and nothing anywhere
|
|
7
|
+
* constructed one, because every transport in this directory is the
|
|
8
|
+
* CLIENT side. `StdioTransport` spawns a child and talks to its streams;
|
|
9
|
+
* this reads the streams THIS process was given. Same interface, opposite
|
|
10
|
+
* end of the pipe.
|
|
11
|
+
*
|
|
12
|
+
* Stdio is the first transport rather than an afterthought: a client
|
|
13
|
+
* spawns the server as a child process, so there is no port, no bind
|
|
14
|
+
* address and no inbound authentication question to get wrong. The
|
|
15
|
+
* boundary is the process, and the process was started by the client.
|
|
16
|
+
*
|
|
17
|
+
* **stdout belongs to the protocol.** A single stray `console.log`
|
|
18
|
+
* anywhere in the process corrupts the message stream, and the symptom is
|
|
19
|
+
* a client that reports malformed JSON rather than anything naming the
|
|
20
|
+
* culprit. This repository's logger already writes to stderr, which is
|
|
21
|
+
* what makes this transport safe to add; keep it that way.
|
|
22
|
+
*/
|
|
23
|
+
export class ServerStdioTransport {
|
|
24
|
+
input;
|
|
25
|
+
output;
|
|
26
|
+
buffer = '';
|
|
27
|
+
connected = false;
|
|
28
|
+
log;
|
|
29
|
+
messageHandler;
|
|
30
|
+
closeHandler;
|
|
31
|
+
errorHandler;
|
|
32
|
+
onData = (chunk) => this.consume(chunk);
|
|
33
|
+
onEnd = () => {
|
|
34
|
+
this.connected = false;
|
|
35
|
+
this.closeHandler?.();
|
|
36
|
+
};
|
|
37
|
+
onStreamError = (err) => this.errorHandler?.(err);
|
|
38
|
+
/**
|
|
39
|
+
* Streams are injected rather than read from `process` directly so a
|
|
40
|
+
* test can drive this without owning the process's own stdio — a test
|
|
41
|
+
* that replaced `process.stdin` would break every other test sharing
|
|
42
|
+
* the runner.
|
|
43
|
+
*/
|
|
44
|
+
constructor(streams) {
|
|
45
|
+
this.input = streams?.input ?? process.stdin;
|
|
46
|
+
this.output = streams?.output ?? process.stdout;
|
|
47
|
+
this.log = getRootLogger().child({ component: 'ServerStdioTransport' });
|
|
48
|
+
}
|
|
49
|
+
async connect() {
|
|
50
|
+
if (this.connected)
|
|
51
|
+
return;
|
|
52
|
+
this.input.setEncoding?.('utf8');
|
|
53
|
+
this.input.on('data', this.onData);
|
|
54
|
+
this.input.on('end', this.onEnd);
|
|
55
|
+
this.input.on('error', this.onStreamError);
|
|
56
|
+
this.connected = true;
|
|
57
|
+
this.log.info('MCP stdio server listening on this process');
|
|
58
|
+
}
|
|
59
|
+
async close() {
|
|
60
|
+
if (!this.connected)
|
|
61
|
+
return;
|
|
62
|
+
this.input.off('data', this.onData);
|
|
63
|
+
this.input.off('end', this.onEnd);
|
|
64
|
+
this.input.off('error', this.onStreamError);
|
|
65
|
+
this.connected = false;
|
|
66
|
+
this.closeHandler?.();
|
|
67
|
+
}
|
|
68
|
+
async send(message) {
|
|
69
|
+
// Newline-delimited JSON, one message per line. A message carrying a
|
|
70
|
+
// literal newline would split into two unparseable halves, so it is
|
|
71
|
+
// stripped by `JSON.stringify` escaping rather than by trusting the
|
|
72
|
+
// payload.
|
|
73
|
+
this.output.write(`${JSON.stringify(message)}\n`);
|
|
74
|
+
}
|
|
75
|
+
onMessage(handler) {
|
|
76
|
+
this.messageHandler = handler;
|
|
77
|
+
}
|
|
78
|
+
onClose(handler) {
|
|
79
|
+
this.closeHandler = handler;
|
|
80
|
+
}
|
|
81
|
+
onError(handler) {
|
|
82
|
+
this.errorHandler = handler;
|
|
83
|
+
}
|
|
84
|
+
isConnected() {
|
|
85
|
+
return this.connected;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A chunk is not a message. Reads arrive at whatever size the pipe
|
|
89
|
+
* hands over, so one read can carry half a message, several messages,
|
|
90
|
+
* or the tail of one and the head of the next. Buffering until a
|
|
91
|
+
* newline is the whole protocol framing.
|
|
92
|
+
*/
|
|
93
|
+
consume(chunk) {
|
|
94
|
+
this.buffer += typeof chunk === 'string' ? chunk : chunk.toString('utf8');
|
|
95
|
+
let newline = this.buffer.indexOf('\n');
|
|
96
|
+
while (newline !== -1) {
|
|
97
|
+
const line = this.buffer.slice(0, newline).trim();
|
|
98
|
+
this.buffer = this.buffer.slice(newline + 1);
|
|
99
|
+
if (line)
|
|
100
|
+
this.deliver(line);
|
|
101
|
+
newline = this.buffer.indexOf('\n');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
deliver(line) {
|
|
105
|
+
let message;
|
|
106
|
+
try {
|
|
107
|
+
message = JSON.parse(line);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
// Reported, not thrown, and not fatal. A client that sends one bad
|
|
111
|
+
// line has not ended the session, and killing the transport over it
|
|
112
|
+
// would take down every other conversation on this pipe. The
|
|
113
|
+
// alternative — silence — is worse: a request that vanishes looks
|
|
114
|
+
// to the client exactly like a server that hung.
|
|
115
|
+
this.errorHandler?.(new Error(`MCP stdio server could not parse a message: ${err instanceof Error ? err.message : String(err)}`));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
this.messageHandler?.(message);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=server-stdio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-stdio.js","sourceRoot":"","sources":["../../../src/connector/mcp/server-stdio.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import type { MCPJsonRpcMessage, MCPStdioTransportConfig, MCPTransport } from '../../types/connector/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* What the child is handed: plumbing, then the named inheritances, then the
|
|
4
|
+
* literal values.
|
|
5
|
+
*
|
|
6
|
+
* Later wins, and the order is the precedence an operator would guess: a
|
|
7
|
+
* literal `env` entry overrides an inherited one, and both override the base.
|
|
8
|
+
* Exported for the tests, which assert on the ENV rather than on the spawn —
|
|
9
|
+
* a test that only checked the config was accepted would have passed against
|
|
10
|
+
* the version this replaces.
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildChildEnv(config: Pick<MCPStdioTransportConfig, 'env' | 'inheritEnv'>, source?: NodeJS.ProcessEnv): Record<string, string>;
|
|
2
13
|
export declare class StdioTransport implements MCPTransport {
|
|
3
14
|
private readonly config;
|
|
4
15
|
private process;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/stdio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,MAAM,gCAAgC,CAAA;
|
|
1
|
+
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/stdio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,MAAM,gCAAgC,CAAA;AAqFvC;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC5B,MAAM,EAAE,IAAI,CAAC,uBAAuB,EAAE,KAAK,GAAG,YAAY,CAAC,EAC3D,MAAM,GAAE,MAAM,CAAC,UAAwB,GACrC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAexB;AAED,qBAAa,cAAe,YAAW,YAAY;IAWtC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAVnC,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,eAAe,CAAkD;IACzE,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,SAAS,CAAQ;IACzB,6DAA6D;IAC7D,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,GAAG,CAAQ;gBAEU,MAAM,EAAE,uBAAuB;IAItD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAuCxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkD5B;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAMf,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrD,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI;IAI9D,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI;IAIlC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI9C,WAAW,IAAI,OAAO;IAItB,OAAO,CAAC,aAAa;CAerB"}
|
|
@@ -6,6 +6,111 @@ import { getRootLogger } from '../../utils/logger.js';
|
|
|
6
6
|
* shutdown does not read as a hang.
|
|
7
7
|
*/
|
|
8
8
|
const TERMINATE_GRACE_MS = 2_000;
|
|
9
|
+
/**
|
|
10
|
+
* The variables a child needs in order to be a working process at all.
|
|
11
|
+
*
|
|
12
|
+
* This spawn used to pass `{ ...process.env, ...config.env }`, so a connected
|
|
13
|
+
* server received every credential the host happened to hold — measured at 119
|
|
14
|
+
* variables on a developer machine, including a planted secret the server had
|
|
15
|
+
* no reason to see. A server that needs one token was handed all of them, and
|
|
16
|
+
* nothing in the config said so.
|
|
17
|
+
*
|
|
18
|
+
* The list below is process plumbing, not secrets: where to find executables,
|
|
19
|
+
* where the home and temp directories are, what the locale is. Dropping any of
|
|
20
|
+
* it does not harden anything and does break servers — a child with no `PATH`
|
|
21
|
+
* cannot resolve its own interpreter.
|
|
22
|
+
*
|
|
23
|
+
* Anything else a server needs is now named: `env` gives it a literal value,
|
|
24
|
+
* and `inheritEnv` names a parent variable to pass through. Naming is the
|
|
25
|
+
* point — a grant that has to be written down is a grant somebody can review.
|
|
26
|
+
*
|
|
27
|
+
* Windows spellings are matched case-insensitively, because its environment is
|
|
28
|
+
* case-insensitive and a lookup for `Path` against a key stored as `PATH` would
|
|
29
|
+
* silently drop it — which would present as "the server does not start on
|
|
30
|
+
* Windows" rather than as anything to do with this list.
|
|
31
|
+
*/
|
|
32
|
+
const BASE_ENV_KEYS = [
|
|
33
|
+
// Everywhere.
|
|
34
|
+
'PATH',
|
|
35
|
+
'LANG',
|
|
36
|
+
'LC_ALL',
|
|
37
|
+
'LC_CTYPE',
|
|
38
|
+
'TZ',
|
|
39
|
+
// POSIX.
|
|
40
|
+
'HOME',
|
|
41
|
+
'SHELL',
|
|
42
|
+
'TMPDIR',
|
|
43
|
+
'USER',
|
|
44
|
+
'LOGNAME',
|
|
45
|
+
// Windows. `SystemRoot` and `ComSpec` are load-bearing: without them a
|
|
46
|
+
// child cannot resolve system DLLs or the command interpreter.
|
|
47
|
+
'PATHEXT',
|
|
48
|
+
'SystemRoot',
|
|
49
|
+
'SystemDrive',
|
|
50
|
+
'ComSpec',
|
|
51
|
+
'WINDIR',
|
|
52
|
+
'TEMP',
|
|
53
|
+
'TMP',
|
|
54
|
+
'USERPROFILE',
|
|
55
|
+
'HOMEDRIVE',
|
|
56
|
+
'HOMEPATH',
|
|
57
|
+
'APPDATA',
|
|
58
|
+
'LOCALAPPDATA',
|
|
59
|
+
'PROGRAMDATA',
|
|
60
|
+
'PROGRAMFILES',
|
|
61
|
+
'NUMBER_OF_PROCESSORS',
|
|
62
|
+
'PROCESSOR_ARCHITECTURE',
|
|
63
|
+
];
|
|
64
|
+
/**
|
|
65
|
+
* Read one variable from the parent, honouring the platform's own casing rules.
|
|
66
|
+
*
|
|
67
|
+
* Node exposes `process.env` on Windows through a case-insensitive proxy, so a
|
|
68
|
+
* direct lookup already works there — but the KEY this returns has to be the
|
|
69
|
+
* one the parent actually uses, or a child comparing key names sees a spelling
|
|
70
|
+
* the host never set.
|
|
71
|
+
*/
|
|
72
|
+
function readParentVar(source, name) {
|
|
73
|
+
const direct = source[name];
|
|
74
|
+
if (direct !== undefined)
|
|
75
|
+
return [name, direct];
|
|
76
|
+
if (process.platform !== 'win32')
|
|
77
|
+
return undefined;
|
|
78
|
+
const lowered = name.toLowerCase();
|
|
79
|
+
for (const [key, value] of Object.entries(source)) {
|
|
80
|
+
if (key.toLowerCase() === lowered && value !== undefined)
|
|
81
|
+
return [key, value];
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* What the child is handed: plumbing, then the named inheritances, then the
|
|
87
|
+
* literal values.
|
|
88
|
+
*
|
|
89
|
+
* Later wins, and the order is the precedence an operator would guess: a
|
|
90
|
+
* literal `env` entry overrides an inherited one, and both override the base.
|
|
91
|
+
* Exported for the tests, which assert on the ENV rather than on the spawn —
|
|
92
|
+
* a test that only checked the config was accepted would have passed against
|
|
93
|
+
* the version this replaces.
|
|
94
|
+
*/
|
|
95
|
+
export function buildChildEnv(config, source = process.env) {
|
|
96
|
+
const env = {};
|
|
97
|
+
for (const name of BASE_ENV_KEYS) {
|
|
98
|
+
const found = readParentVar(source, name);
|
|
99
|
+
if (found)
|
|
100
|
+
env[found[0]] = found[1];
|
|
101
|
+
}
|
|
102
|
+
for (const name of config.inheritEnv ?? []) {
|
|
103
|
+
const found = readParentVar(source, name);
|
|
104
|
+
// A named variable the parent does not hold is simply absent. Refusing
|
|
105
|
+
// the spawn would turn an optional credential into a startup failure,
|
|
106
|
+
// and inventing an empty string would tell the server it has one.
|
|
107
|
+
if (found)
|
|
108
|
+
env[found[0]] = found[1];
|
|
109
|
+
}
|
|
110
|
+
for (const [name, value] of Object.entries(config.env ?? {}))
|
|
111
|
+
env[name] = value;
|
|
112
|
+
return env;
|
|
113
|
+
}
|
|
9
114
|
export class StdioTransport {
|
|
10
115
|
config;
|
|
11
116
|
process = null;
|
|
@@ -25,7 +130,7 @@ export class StdioTransport {
|
|
|
25
130
|
if (this.connected)
|
|
26
131
|
return;
|
|
27
132
|
this.process = spawn(this.config.command, this.config.args ?? [], {
|
|
28
|
-
env:
|
|
133
|
+
env: buildChildEnv(this.config),
|
|
29
134
|
cwd: this.config.cwd,
|
|
30
135
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
31
136
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../../src/connector/mcp/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAM7D,OAAO,EAAe,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAElE;;;;GAIG;AACH,MAAM,kBAAkB,GAAG,KAAK,CAAA;AAEhC,MAAM,OAAO,cAAc;IAWG;IAVrB,OAAO,GAAwB,IAAI,CAAA;IACnC,eAAe,GAAgD,EAAE,CAAA;IACjE,aAAa,GAAsB,EAAE,CAAA;IACrC,aAAa,GAAkC,EAAE,CAAA;IACjD,SAAS,GAAG,KAAK,CAAA;IACzB,6DAA6D;IACrD,WAAW,GAAG,KAAK,CAAA;IACnB,MAAM,GAAG,EAAE,CAAA;IACX,GAAG,CAAQ;IAEnB,YAA6B,MAA+B;QAA/B,WAAM,GAAN,MAAM,CAAyB;QAC3D,IAAI,CAAC,GAAG,GAAG,aAAa,EAAE,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC,CAAA;IAClE,CAAC;IAED,KAAK,CAAC,OAAO;QACZ,IAAI,IAAI,CAAC,SAAS;YAAE,OAAM;QAE1B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE;YACjE,GAAG,EAAE,
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../../src/connector/mcp/stdio.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,7 +18,21 @@ export declare const GENAI: {
|
|
|
18
18
|
readonly TOKEN_TYPE: "gen_ai.token.type";
|
|
19
19
|
readonly TOOL_NAME: "gen_ai.tool.name";
|
|
20
20
|
readonly TOOL_TYPE: "gen_ai.tool.type";
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* The id of the tool call this span is about.
|
|
23
|
+
*
|
|
24
|
+
* Spelled `call.id`, matching the registry and matching the two
|
|
25
|
+
* neighbours above — this read `gen_ai.tool.call_id`, one underscore
|
|
26
|
+
* where the convention has a dot, so a consumer grouping by the
|
|
27
|
+
* conventional name found nothing under it. Nothing errored, because a
|
|
28
|
+
* span attribute is a free-form key and a wrong one is simply a key
|
|
29
|
+
* nobody asked for.
|
|
30
|
+
*
|
|
31
|
+
* Pinned by `telemetry/__tests__/tool-call-id-attribute.test.ts`, which
|
|
32
|
+
* also drives the emitter: the spelling was only half the defect, and
|
|
33
|
+
* the constant had no writer at all.
|
|
34
|
+
*/
|
|
35
|
+
readonly TOOL_CALL_ID: "gen_ai.tool.call.id";
|
|
22
36
|
readonly AGENT_NAME: "gen_ai.agent.name";
|
|
23
37
|
readonly AGENT_ID: "gen_ai.agent.id";
|
|
24
38
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/constants/telemetry/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK;;;;;;;;;;;IAejB;;;;;OAKG
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/constants/telemetry/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK;;;;;;;;;;;IAejB;;;;;OAKG;;;;IAMH;;;;;;;;;;;;;OAaG;;;;CAKM,CAAA;AAEV,eAAO,MAAM,KAAK;;;;;;;;;;CAUR,CAAA"}
|