@smthrs/mcp 0.0.0-stage → 1.0.0-rc.4

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 (128) hide show
  1. package/CHANGELOG.md +121 -0
  2. package/LICENSE +21 -0
  3. package/README.md +111 -2
  4. package/dist/cjs/Diagnostics.d.ts +46 -0
  5. package/dist/cjs/Diagnostics.d.ts.map +1 -0
  6. package/dist/cjs/Diagnostics.js +29 -0
  7. package/dist/cjs/Diagnostics.js.map +7 -0
  8. package/dist/cjs/McpClient.d.ts +304 -0
  9. package/dist/cjs/McpClient.d.ts.map +1 -0
  10. package/dist/cjs/McpClient.js +622 -0
  11. package/dist/cjs/McpClient.js.map +7 -0
  12. package/dist/cjs/McpError.d.ts +44 -0
  13. package/dist/cjs/McpError.d.ts.map +1 -0
  14. package/dist/cjs/McpError.js +41 -0
  15. package/dist/cjs/McpError.js.map +7 -0
  16. package/dist/cjs/McpFlows.d.ts +113 -0
  17. package/dist/cjs/McpFlows.d.ts.map +1 -0
  18. package/dist/cjs/McpFlows.js +127 -0
  19. package/dist/cjs/McpFlows.js.map +7 -0
  20. package/dist/cjs/index.d.ts +39 -0
  21. package/dist/cjs/index.d.ts.map +1 -0
  22. package/dist/cjs/index.js +41 -0
  23. package/dist/cjs/index.js.map +7 -0
  24. package/dist/cjs/internal/DiagnosticReporter.d.ts +17 -0
  25. package/dist/cjs/internal/DiagnosticReporter.d.ts.map +1 -0
  26. package/dist/cjs/internal/DiagnosticReporter.js +56 -0
  27. package/dist/cjs/internal/DiagnosticReporter.js.map +7 -0
  28. package/dist/cjs/internal/HttpTransport.d.ts +67 -0
  29. package/dist/cjs/internal/HttpTransport.d.ts.map +1 -0
  30. package/dist/cjs/internal/HttpTransport.js +298 -0
  31. package/dist/cjs/internal/HttpTransport.js.map +7 -0
  32. package/dist/cjs/internal/JsonLimits.d.ts +29 -0
  33. package/dist/cjs/internal/JsonLimits.d.ts.map +1 -0
  34. package/dist/cjs/internal/JsonLimits.js +51 -0
  35. package/dist/cjs/internal/JsonLimits.js.map +7 -0
  36. package/dist/cjs/internal/Limits.d.ts +36 -0
  37. package/dist/cjs/internal/Limits.d.ts.map +1 -0
  38. package/dist/cjs/internal/Limits.js +34 -0
  39. package/dist/cjs/internal/Limits.js.map +7 -0
  40. package/dist/cjs/internal/Rpc.d.ts +141 -0
  41. package/dist/cjs/internal/Rpc.d.ts.map +1 -0
  42. package/dist/cjs/internal/Rpc.js +92 -0
  43. package/dist/cjs/internal/Rpc.js.map +7 -0
  44. package/dist/cjs/internal/StdioTransport.d.ts +78 -0
  45. package/dist/cjs/internal/StdioTransport.d.ts.map +1 -0
  46. package/dist/cjs/internal/StdioTransport.js +310 -0
  47. package/dist/cjs/internal/StdioTransport.js.map +7 -0
  48. package/dist/cjs/internal/Transport.d.ts +87 -0
  49. package/dist/cjs/internal/Transport.d.ts.map +1 -0
  50. package/dist/cjs/internal/Transport.js +116 -0
  51. package/dist/cjs/internal/Transport.js.map +7 -0
  52. package/dist/cjs/package.json +1 -0
  53. package/dist/esm/Diagnostics.d.ts +46 -0
  54. package/dist/esm/Diagnostics.d.ts.map +1 -0
  55. package/dist/esm/Diagnostics.js +26 -0
  56. package/dist/esm/Diagnostics.js.map +1 -0
  57. package/dist/esm/McpClient.d.ts +304 -0
  58. package/dist/esm/McpClient.d.ts.map +1 -0
  59. package/dist/esm/McpClient.js +671 -0
  60. package/dist/esm/McpClient.js.map +1 -0
  61. package/dist/esm/McpError.d.ts +44 -0
  62. package/dist/esm/McpError.d.ts.map +1 -0
  63. package/dist/esm/McpError.js +43 -0
  64. package/dist/esm/McpError.js.map +1 -0
  65. package/dist/esm/McpFlows.d.ts +113 -0
  66. package/dist/esm/McpFlows.d.ts.map +1 -0
  67. package/dist/esm/McpFlows.js +168 -0
  68. package/dist/esm/McpFlows.js.map +1 -0
  69. package/dist/esm/index.d.ts +39 -0
  70. package/dist/esm/index.d.ts.map +1 -0
  71. package/dist/esm/index.js +39 -0
  72. package/dist/esm/index.js.map +1 -0
  73. package/dist/esm/internal/DiagnosticReporter.d.ts +17 -0
  74. package/dist/esm/internal/DiagnosticReporter.d.ts.map +1 -0
  75. package/dist/esm/internal/DiagnosticReporter.js +44 -0
  76. package/dist/esm/internal/DiagnosticReporter.js.map +1 -0
  77. package/dist/esm/internal/HttpTransport.d.ts +67 -0
  78. package/dist/esm/internal/HttpTransport.d.ts.map +1 -0
  79. package/dist/esm/internal/HttpTransport.js +266 -0
  80. package/dist/esm/internal/HttpTransport.js.map +1 -0
  81. package/dist/esm/internal/JsonLimits.d.ts +29 -0
  82. package/dist/esm/internal/JsonLimits.d.ts.map +1 -0
  83. package/dist/esm/internal/JsonLimits.js +55 -0
  84. package/dist/esm/internal/JsonLimits.js.map +1 -0
  85. package/dist/esm/internal/Limits.d.ts +36 -0
  86. package/dist/esm/internal/Limits.d.ts.map +1 -0
  87. package/dist/esm/internal/Limits.js +41 -0
  88. package/dist/esm/internal/Limits.js.map +1 -0
  89. package/dist/esm/internal/Rpc.d.ts +141 -0
  90. package/dist/esm/internal/Rpc.d.ts.map +1 -0
  91. package/dist/esm/internal/Rpc.js +129 -0
  92. package/dist/esm/internal/Rpc.js.map +1 -0
  93. package/dist/esm/internal/StdioTransport.d.ts +78 -0
  94. package/dist/esm/internal/StdioTransport.d.ts.map +1 -0
  95. package/dist/esm/internal/StdioTransport.js +332 -0
  96. package/dist/esm/internal/StdioTransport.js.map +1 -0
  97. package/dist/esm/internal/Transport.d.ts +87 -0
  98. package/dist/esm/internal/Transport.d.ts.map +1 -0
  99. package/dist/esm/internal/Transport.js +146 -0
  100. package/dist/esm/internal/Transport.js.map +1 -0
  101. package/docs/README.md +139 -0
  102. package/docs/api.md +469 -0
  103. package/docs/concepts/the-session.md +135 -0
  104. package/docs/concepts/tools-as-flows.md +116 -0
  105. package/docs/guides/bound-an-untrusted-server.md +158 -0
  106. package/docs/guides/configure-servers-for-the-cli.md +167 -0
  107. package/docs/guides/connect-a-server.md +161 -0
  108. package/docs/guides/grant-authority-to-mcp-tools.md +130 -0
  109. package/docs/guides/handle-a-failed-tool-call.md +125 -0
  110. package/docs/guides/select-the-tools-a-run-sees.md +92 -0
  111. package/docs/guides/testing.md +132 -0
  112. package/docs/guides/validate-structured-output.md +103 -0
  113. package/docs/installation.md +117 -0
  114. package/docs/quickstart.md +200 -0
  115. package/docs/troubleshooting.md +316 -0
  116. package/package.json +157 -3
  117. package/src/Diagnostics.ts +47 -0
  118. package/src/McpClient.ts +985 -0
  119. package/src/McpError.ts +52 -0
  120. package/src/McpFlows.ts +211 -0
  121. package/src/index.ts +42 -0
  122. package/src/internal/DiagnosticReporter.ts +47 -0
  123. package/src/internal/HttpTransport.ts +400 -0
  124. package/src/internal/JsonLimits.ts +53 -0
  125. package/src/internal/Limits.ts +48 -0
  126. package/src/internal/Rpc.ts +219 -0
  127. package/src/internal/StdioTransport.ts +491 -0
  128. package/src/internal/Transport.ts +178 -0
@@ -0,0 +1,316 @@
1
+ ---
2
+ title: "Troubleshooting"
3
+ description: "The failures @smthrs/mcp reports, by the message you saw: startup, handshake, catalog, call, argument, limit, and capability problems, each with its cause and fix."
4
+ ---
5
+
6
+ Every failure this package reports is an `McpError` carrying a stable code, the
7
+ server name, and a message. Find the message you saw. The full error schema is
8
+ on the [API reference](./api.md).
9
+
10
+ One failure is not an `McpError` at all, and it is the most common one: see
11
+ [capability_refused](#capability_refused) at the end.
12
+
13
+ ## Failed to start MCP server "..."
14
+
15
+ **Code.** `spawn_failed`.
16
+
17
+ **What happened.** The process could not be started. Raw process details are
18
+ withheld. For local debugging, install a trusted
19
+ [Diagnostics observer](./api.md#diagnostics) before opening the connection.
20
+
21
+ **What to change.** Check that `command` is on the parent process's `PATH`, that
22
+ `cwd` exists, and that the entry file is readable. The child receives `PATH`
23
+ from the bootstrap allowlist even when `env` declares other names, so a wrong
24
+ `command` usually is the cause. For a server started through `npx`, run the same
25
+ command by hand first.
26
+
27
+ ## ... speaks an unsupported protocol version; this client speaks ...
28
+
29
+ **Code.** `protocol_error`.
30
+
31
+ **What happened.** The server answered `initialize` with a revision outside
32
+ `McpClient.supportedProtocolVersions`, which is `2025-06-18`, `2025-03-26`, and
33
+ `2024-11-05`.
34
+
35
+ **What to change.** Upgrade or downgrade the server to a revision on that list.
36
+ The list is frozen: this client decodes the `tools/list` and `tools/call` shapes
37
+ of those three revisions and cannot claim a fourth.
38
+
39
+ ## ... does not serve tools
40
+
41
+ **Code.** `protocol_error`.
42
+
43
+ **What happened.** The server's `initialize` result declared no `tools`
44
+ capability.
45
+
46
+ **What to change.** This package projects tools and nothing else. A server that
47
+ serves only resources, prompts, or sampling has nothing to project, and the
48
+ connection is refused rather than left useless.
49
+
50
+ ## ... returned a malformed initialize result
51
+
52
+ **Code.** `protocol_error`.
53
+
54
+ **What happened.** The handshake result was not an object, its `protocolVersion`
55
+ was not a string, or its `capabilities` was not an object. The message names
56
+ which.
57
+
58
+ **What to change.** Fix the server's `initialize` reply. If it is not your
59
+ server, check whether it is writing something other than JSON-RPC to stdout on
60
+ startup; the reply itself must be one line of JSON.
61
+
62
+ ## ... returned a tools/list result with no tools array
63
+
64
+ **Code.** `invalid_response`.
65
+
66
+ **What happened.** The catalog reply had no `tools` array. The nearby messages
67
+ `returned tools[N], which is not an object` and `returned tools[N] with no name`
68
+ cover the same class of defect one element deeper.
69
+
70
+ **What to change.** Fix the server's `tools/list` reply.
71
+
72
+ ## ... returned a tool whose inputSchema is not a JSON Schema object of type "object"
73
+
74
+ **Code.** `invalid_response`.
75
+
76
+ **What happened.** A catalog entry's `inputSchema` was missing, was not an
77
+ object, or declared a `type` other than `"object"`.
78
+
79
+ **What to change.** Give every tool an `inputSchema` with `"type": "object"`.
80
+ The requirement is not pedantry: that document is disclosed to the model as the
81
+ tool's parameter shape, and a tool without one would be advertised as if it had
82
+ one. `outputSchema`, when present, must also be a JSON object.
83
+
84
+ ## ... returned more than N tools, or more than N tools/list pages
85
+
86
+ **Code.** `invalid_response`.
87
+
88
+ **What happened.** The catalog exceeded `maxTools` (256 by default) or the
89
+ cursor walk exceeded `maxCatalogPages` (32 by default). The related message
90
+ `repeated a tools/list cursor` means the server sent a cursor it had
91
+ already sent, which would loop forever.
92
+
93
+ **What to change.** For a genuinely large server, raise `maxTools` or
94
+ `maxCatalogPages`, and narrow the projection with `include` so the model is not
95
+ shown hundreds of flows. For a repeated cursor, fix the server's paging. A
96
+ catalog is refused rather than truncated on purpose: a silently smaller toolset
97
+ is worse than a failed connection. See
98
+ [Bound an untrusted server](./guides/bound-an-untrusted-server.md).
99
+
100
+ ## ... returned a tool name longer than N bytes, or that is "." or "..", or contains "/" or an invisible or control character
101
+
102
+ **Code.** `invalid_response`.
103
+
104
+ **What happened.** A tool name exceeded `maxToolNameBytes` (128 by default), or
105
+ was `.` or `..`, or contained `/`, a control character (C0, U+007F, C1), a
106
+ format character such as a zero-width or bidi mark, U+2028, U+2029, or a lone
107
+ surrogate.
108
+
109
+ **What to change.** Rename the tool on the server. The name is embedded in the
110
+ flow name `mcp/<server>/<tool>` and in the journal's declaration digest, so `/`
111
+ would make it ambiguous and an invisible or control character would make it
112
+ read as a different tool. `returned a duplicate tool name at catalog index N` is the same class: a duplicate makes the
113
+ flow name ambiguous.
114
+
115
+ ## ... returned a tool description and inputSchema longer than N bytes
116
+
117
+ **Code.** `invalid_response`.
118
+
119
+ **What happened.** One tool's description plus its JSON-encoded `inputSchema`
120
+ exceeded `maxToolDocumentBytes` (65536 by default).
121
+
122
+ **What to change.** Shorten the tool's description or schema on the server, or
123
+ raise `maxToolDocumentBytes` for a server you trust. The text is authored by the
124
+ server and read by a model, so it is bounded like the rest of the catalog.
125
+
126
+ ## ... did not answer METHOD within Nms
127
+
128
+ **Code.** `timeout`.
129
+
130
+ **What happened.** The deadline for that method expired.
131
+ `handshakeTimeoutMs` (10 seconds by default) bounds `initialize` and
132
+ `tools/list`; `requestTimeoutMs` (120 seconds by default) bounds `tools/call`.
133
+ The message indicates when a stderr diagnostic was withheld; it never echoes
134
+ the child's output.
135
+
136
+ **What to change.** For a slow tool, raise `requestTimeoutMs`. For a handshake
137
+ that never completes, inspect the private stderr diagnostic through a trusted
138
+ host observer: a server that reports a crash is not merely slow.
139
+
140
+ If the request was still queued, the writer skips it. If it was already handed
141
+ to the writer, one best-effort `notifications/cancelled` is sent, unless the
142
+ outbound queue is full or the method is `initialize`.
143
+
144
+ ## MCP server "..." connection scope closed, stdout closed, stdin closed, or exited with code N
145
+
146
+ **Code.** `connection_closed`.
147
+
148
+ **What happened.** The session ended. Every request pending at that moment
149
+ failed with this one error, and every later request fails with it too. A clean
150
+ child exit ends stdout successfully, so an ordinary exit reads as "stdout
151
+ closed" or "exited with code N". Closing a healthy connection's scope reports
152
+ "connection scope closed" before I/O teardown can report "stdin closed".
153
+
154
+ **What to change.** "Connection scope closed" is usually the caller's own bug:
155
+ the scope was closed while a call was still running, or a client was used after
156
+ its `Effect.scoped` block returned. Hold the connection for the life of the
157
+ session rather than per call. For a server that exited on its own, inspect the
158
+ private stderr diagnostic through a trusted host observer.
159
+
160
+ ## MCP frame exceeded N bytes
161
+
162
+ **Code.** `protocol_error`.
163
+
164
+ **What happened.** One inbound line exceeded `maxFrameBytes` (1 MiB by default).
165
+ The limit is inclusive and counts UTF-8 bytes, excluding the newline and an
166
+ optional preceding carriage return. Chunk boundaries do not affect the limit.
167
+ The stdout reader retains one bounded partial frame plus at most one pending
168
+ carriage return, so this also fires when a server writes too much output
169
+ without a newline. Each byte is scanned once and each frame is decoded once.
170
+
171
+ **What to change.** For a tool that genuinely returns megabytes, raise
172
+ `maxFrameBytes`. Otherwise check that the server terminates each JSON-RPC
173
+ message with a newline. The mirror message, `tried to send a METHOD frame larger
174
+ than N bytes`, means your own arguments exceeded `maxOutboundFrameBytes`.
175
+
176
+ ## ... sent a malformed JSON-RPC reply
177
+
178
+ **Code.** `protocol_error`.
179
+
180
+ **What happened.** A line that claimed JSON-RPC by carrying a `jsonrpc` property
181
+ was not a valid reply: the wrong version, no id, an invalid id, neither `result`
182
+ nor `error`, both of them, or a malformed error object. This closes the connection.
183
+
184
+ Reply ids must be integers or canonical decimal strings. A valid error reply
185
+ with `id: null` is the exception: its details go to the private diagnostic
186
+ observer as `remote-error`, then it is dropped without closing the connection.
187
+ Pending requests still wait for their own replies or deadlines. A result with
188
+ `id: null` is malformed.
189
+
190
+ **What to change.** Fix the server's framing. Note what does **not** cause this:
191
+ a blank line, invalid JSON, a JSON scalar or array, and any object without a
192
+ `jsonrpc` property are treated as log noise and dropped, so ordinary server
193
+ logging on stdout is safe. Only a message that claims to be protocol traffic is
194
+ held to protocol rules.
195
+
196
+ ## MCP option "..." must be a positive integer
197
+
198
+ **Code.** `protocol_error`.
199
+
200
+ **What happened.** A limit was zero, negative, or fractional. This is raised
201
+ before the process is spawned.
202
+
203
+ **What to change.** Pass a positive integer.
204
+
205
+ ## MCP server "..." option "namePrefix" must not be empty
206
+
207
+ **Code.** `protocol_error`.
208
+
209
+ **What happened.** `McpFlows.connected` was given an empty prefix. This is
210
+ raised before the process is spawned.
211
+
212
+ **What to change.** Pass a non-empty `namePrefix`, or omit it to use
213
+ `mcp/<server>`.
214
+
215
+ ## MCP server "..." has no requested tool
216
+
217
+ **Code.** `tool_not_found`.
218
+
219
+ **What happened.** `callTool` was given a name that is not in the catalog. The
220
+ check runs before any frame is written.
221
+
222
+ **What to change.** Read `client.tools` for the names the server actually
223
+ offers. Remember the catalog is a snapshot taken at connect time: a tool the
224
+ server added afterwards is not there until you reconnect. The variant
225
+ `offers no requested include tool` is the same mistake in
226
+ `ProjectionOptions.include`.
227
+
228
+ ## ... failed tools/call (CODE); remote details withheld
229
+
230
+ **Code.** `tool_failed`, or `tool_not_found`.
231
+
232
+ **What happened.** The server answered the call with a JSON-RPC error rather
233
+ than a result. It becomes `tool_not_found` only when the JSON-RPC code is
234
+ `-32601` or `-32602` **and** the message combines the word `tool` with
235
+ `unknown`, `unrecognized`, `no such`, or `not found`. Everything else, including
236
+ an ordinary invalid-arguments rejection, is `tool_failed`.
237
+
238
+ **What to change.** Read the numeric code. Remote message text and data are
239
+ available only through the private diagnostic observer, not passed through to
240
+ the caller. A `tool_failed` from bad arguments means the model or the caller
241
+ sent a value the tool's `inputSchema` rejects.
242
+
243
+ Do not confuse this with a tool that ran and reported a problem. That comes back
244
+ as a **successful** call with `isError: true`. See
245
+ [Handle a failed tool call](./guides/handle-a-failed-tool-call.md).
246
+
247
+ ## ... was sent a tool argument that is not JSON: REASON; property path withheld
248
+
249
+ **Code.** `protocol_error`.
250
+
251
+ **What happened.** The arguments contained something that cannot cross a JSON
252
+ boundary: a function, a symbol, a bigint, `undefined`, a non-finite number, a
253
+ cyclic reference, an object with a non-plain prototype, an accessor property, a
254
+ symbol-keyed property, or a `toJSON` method. The error names the reason but
255
+ withholds the path and value. A private diagnostic can identify the path without
256
+ re-evaluating an accessor or proxy.
257
+
258
+ **What to change.** Send plain JSON. Accessors are rejected rather than invoked,
259
+ so a getter that would have produced a fine value still fails; compute it before
260
+ the call.
261
+
262
+ ## ... returned structuredContent that its own outputSchema rejects: REASON; property path withheld
263
+
264
+ **Code.** `invalid_response`.
265
+
266
+ **What happened.** The tool declared an `outputSchema` and returned
267
+ `structuredContent` that violates it, checked against the supported keyword
268
+ subset: `type`, `required`, `properties`, single-schema `items`, and `enum`.
269
+
270
+ **What to change.** Fix the server, which is disagreeing with its own published
271
+ contract. Unsupported keywords are ignored rather than enforced, so this is
272
+ never a false positive from a constraint the validator half-implements. See
273
+ [Validate structured output](./guides/validate-structured-output.md).
274
+
275
+ ## ... returned a tools/call result with no content array
276
+
277
+ **Code.** `invalid_response`.
278
+
279
+ **What happened.** The result carried neither `content` nor
280
+ `structuredContent`, or its `content` was not an array.
281
+
282
+ **What to change.** Return at least one of them. A structured-only result is
283
+ valid and comes back with `content: []`.
284
+
285
+ ## capability_refused
286
+
287
+ **Not an McpError.** This is the cell boundary refusing the call, and the tool
288
+ never ran.
289
+
290
+ **What happened.** Every projected flow declares `McpFlows.capabilities`, one
291
+ entry per host action at resource `**`. The refusal names the first declared
292
+ capability the run's envelope does not cover, which under a read-only envelope
293
+ is `fs:write:**`.
294
+
295
+ **What to change.** Do not widen the envelope to `*:*`. Re-declare the source's
296
+ flows under the authority you actually grant this server, and put that same
297
+ string in the run's envelope. The recipe is in
298
+ [Grant authority to MCP tools](./guides/grant-authority-to-mcp-tools.md).
299
+
300
+ ## A duplicate flow name fails catalog composition
301
+
302
+ **Not an McpError.** `FlowBinding.catalog` refuses two sources that offer the
303
+ same flow name, rather than dispatching one descriptor to another
304
+ implementation.
305
+
306
+ **What to change.** The default prefix `mcp/<server>` keeps two servers apart, so
307
+ this usually means two entries share a `server` name, or a custom `namePrefix`
308
+ collides with another source. Give each server a distinct name.
309
+
310
+ ## Recovering from connection setup failure
311
+
312
+ `McpClient.connect` and `McpFlows.connected` release the subprocess and I/O
313
+ fibers before returning a failed or interrupted setup attempt. This includes
314
+ negotiation, catalog, and projection validation failures. Catching failures or
315
+ retrying inside an open scope does not retain failed connections. Successful
316
+ connections remain open until the caller scope closes.
package/package.json CHANGED
@@ -1,6 +1,160 @@
1
1
  {
2
+ "$schema": "https://json.schemastore.org/package.json",
2
3
  "name": "@smthrs/mcp",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
4
+ "type": "module",
5
+ "version": "1.0.0-rc.4",
6
+ "license": "MIT",
7
+ "smthrs": {
8
+ "group": "agent"
9
+ },
10
+ "description": "Model Context Protocol client and flow adapter: projects a remote MCP server's tools as ordinary FlowBinding.Source entries",
11
+ "homepage": "https://github.com/smithersai/smithers",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/smithersai/smithers.git",
15
+ "directory": "packages/smithers/mcp"
16
+ },
17
+ "bugs": {
18
+ "url": "https://github.com/smithersai/smithers/issues"
19
+ },
20
+ "tags": [
21
+ "typescript",
22
+ "effect",
23
+ "mcp",
24
+ "flow-registry"
25
+ ],
26
+ "keywords": [
27
+ "typescript",
28
+ "effect",
29
+ "mcp",
30
+ "flow-registry"
31
+ ],
32
+ "engines": {
33
+ "node": ">=26.4.0"
34
+ },
35
+ "sideEffects": [],
36
+ "exports": {
37
+ "./package.json": "./package.json",
38
+ ".": {
39
+ "import": {
40
+ "types": "./dist/esm/index.d.ts",
41
+ "default": "./dist/esm/index.js"
42
+ },
43
+ "require": {
44
+ "types": "./dist/cjs/index.d.ts",
45
+ "default": "./dist/cjs/index.js"
46
+ }
47
+ },
48
+ "./internal/*": null,
49
+ "./*/index": null,
50
+ "./Diagnostics": {
51
+ "import": {
52
+ "types": "./dist/esm/Diagnostics.d.ts",
53
+ "default": "./dist/esm/Diagnostics.js"
54
+ },
55
+ "require": {
56
+ "types": "./dist/cjs/Diagnostics.d.ts",
57
+ "default": "./dist/cjs/Diagnostics.js"
58
+ }
59
+ },
60
+ "./McpClient": {
61
+ "import": {
62
+ "types": "./dist/esm/McpClient.d.ts",
63
+ "default": "./dist/esm/McpClient.js"
64
+ },
65
+ "require": {
66
+ "types": "./dist/cjs/McpClient.d.ts",
67
+ "default": "./dist/cjs/McpClient.js"
68
+ }
69
+ },
70
+ "./McpError": {
71
+ "import": {
72
+ "types": "./dist/esm/McpError.d.ts",
73
+ "default": "./dist/esm/McpError.js"
74
+ },
75
+ "require": {
76
+ "types": "./dist/cjs/McpError.d.ts",
77
+ "default": "./dist/cjs/McpError.js"
78
+ }
79
+ },
80
+ "./McpFlows": {
81
+ "import": {
82
+ "types": "./dist/esm/McpFlows.d.ts",
83
+ "default": "./dist/esm/McpFlows.js"
84
+ },
85
+ "require": {
86
+ "types": "./dist/cjs/McpFlows.d.ts",
87
+ "default": "./dist/cjs/McpFlows.js"
88
+ }
89
+ },
90
+ "./index": {
91
+ "import": {
92
+ "types": "./dist/esm/index.d.ts",
93
+ "default": "./dist/esm/index.js"
94
+ },
95
+ "require": {
96
+ "types": "./dist/cjs/index.d.ts",
97
+ "default": "./dist/cjs/index.js"
98
+ }
99
+ }
100
+ },
101
+ "files": [
102
+ "src/**/*.ts",
103
+ "dist/**/*.js",
104
+ "dist/**/*.js.map",
105
+ "dist/**/*.d.ts",
106
+ "dist/**/*.d.ts.map",
107
+ "dist/**/package.json",
108
+ "LICENSE",
109
+ "README.md",
110
+ "CHANGELOG.md",
111
+ "docs/"
112
+ ],
113
+ "publishConfig": {
114
+ "access": "public",
115
+ "provenance": true,
116
+ "tag": "next"
117
+ },
118
+ "dependencies": {
119
+ "@smthrs/canonical": "1.0.0-rc.4",
120
+ "@smthrs/capability": "1.0.0-rc.4",
121
+ "@smthrs/core": "1.0.0-rc.4",
122
+ "@smthrs/harness": "1.0.0-rc.4",
123
+ "@smthrs/journal": "1.0.0-rc.4",
124
+ "@smthrs/kernel": "1.0.0-rc.4"
125
+ },
126
+ "devDependencies": {
127
+ "@effect/language-service": "0.87.2",
128
+ "@effect/platform-node": "4.0.0-rc.115",
129
+ "@effect/vitest": "4.0.0-rc.115",
130
+ "@eslint/js": "9.39.5",
131
+ "@smthrs/model": "1.0.0-rc.4",
132
+ "@smthrs/registry": "1.0.0-rc.4",
133
+ "@types/node": "26.4.1",
134
+ "@vitest/coverage-v8": "5.0.0",
135
+ "dprint": "0.57.1",
136
+ "effect": "4.0.0-rc.115",
137
+ "esbuild": "0.28.2",
138
+ "eslint": "9.39.5",
139
+ "eslint-import-resolver-typescript": "4.4.5",
140
+ "eslint-plugin-import": "2.32.0",
141
+ "eslint-plugin-jsdoc": "64.3.4",
142
+ "eslint-plugin-unicorn": "65.0.0",
143
+ "madge": "8.0.0",
144
+ "typescript": "5.9.3",
145
+ "typescript-eslint": "8.69.0",
146
+ "vitest": "5.0.0"
147
+ },
148
+ "peerDependencies": {
149
+ "effect": "4.0.0-rc.115"
150
+ },
151
+ "scripts": {
152
+ "lint": "eslint src --max-warnings=0 && dprint check",
153
+ "format": "dprint fmt",
154
+ "build": "node scripts/build.mjs",
155
+ "check": "tsc -b tsconfig.json && tsc -p tsconfig.test.json --noEmit",
156
+ "circular": "node scripts/circular.mjs",
157
+ "test": "vitest",
158
+ "coverage": "vitest --coverage"
159
+ }
6
160
  }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Host-only access to untrusted MCP diagnostics, separate from model-facing
3
+ * errors. Merely logging or JSON-encoding an event cannot expose its detail.
4
+ *
5
+ * @since 1.0.0-rc.0
6
+ */
7
+
8
+ import { Context, Layer } from "effect"
9
+ import type { Redacted } from "effect"
10
+
11
+ /**
12
+ * One bounded diagnostic from a connection. Detail can contain credentials,
13
+ * private tool arguments, or arbitrary server text. Only an explicitly trusted
14
+ * local host should unwrap it; never forward it to agents, journals, or logs.
15
+ *
16
+ * @category models
17
+ * @since 1.0.0-rc.0
18
+ */
19
+ export interface Event {
20
+ readonly server: string
21
+ readonly source: "spawn" | "stderr" | "transport" | "remote-error" | "invalid-response" | "invalid-arguments"
22
+ /** At most 16 KiB of UTF-8 text; never the original unbounded value. */
23
+ readonly detail: Redacted.Redacted<string>
24
+ readonly truncated: boolean
25
+ }
26
+
27
+ /**
28
+ * Optional diagnostic observer, captured when a connection is opened. The
29
+ * synchronous callback must not block; throws are isolated from the protocol.
30
+ * Absent this service, raw diagnostics are discarded, not logged implicitly.
31
+ *
32
+ * @category services
33
+ * @since 1.0.0-rc.0
34
+ */
35
+ export class Diagnostics extends Context.Service<Diagnostics, {
36
+ readonly report: (event: Event) => void
37
+ }>()("@smthrs/mcp/Diagnostics") {}
38
+
39
+ /**
40
+ * Installs a trusted host observer. Inspecting detail requires an explicit
41
+ * `Redacted.value` call and responsibility for its destination and retention.
42
+ *
43
+ * @category layers
44
+ * @since 1.0.0-rc.0
45
+ */
46
+ export const layer = (report: (event: Event) => void): Layer.Layer<Diagnostics> =>
47
+ Layer.succeed(Diagnostics)({ report })