@particle-academy/agent-integrations 0.44.0 → 0.46.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.
Files changed (182) hide show
  1. package/README.md +42 -3
  2. package/dist/bridges/artboard.d.cts +3 -3
  3. package/dist/bridges/artboard.d.ts +3 -3
  4. package/dist/bridges/catalog.d.cts +3 -3
  5. package/dist/bridges/catalog.d.ts +3 -3
  6. package/dist/bridges/charts.d.cts +3 -3
  7. package/dist/bridges/charts.d.ts +3 -3
  8. package/dist/bridges/cms.d.cts +3 -3
  9. package/dist/bridges/cms.d.ts +3 -3
  10. package/dist/bridges/code.d.cts +3 -3
  11. package/dist/bridges/code.d.ts +3 -3
  12. package/dist/bridges/doc.d.cts +3 -3
  13. package/dist/bridges/doc.d.ts +3 -3
  14. package/dist/bridges/features.d.cts +3 -3
  15. package/dist/bridges/features.d.ts +3 -3
  16. package/dist/bridges/files.d.cts +3 -3
  17. package/dist/bridges/files.d.ts +3 -3
  18. package/dist/bridges/flow.d.cts +3 -3
  19. package/dist/bridges/flow.d.ts +3 -3
  20. package/dist/bridges/forms.d.cts +3 -3
  21. package/dist/bridges/forms.d.ts +3 -3
  22. package/dist/bridges/git.d.cts +3 -3
  23. package/dist/bridges/git.d.ts +3 -3
  24. package/dist/bridges/grid.d.cts +3 -3
  25. package/dist/bridges/grid.d.ts +3 -3
  26. package/dist/bridges/map.d.cts +3 -3
  27. package/dist/bridges/map.d.ts +3 -3
  28. package/dist/bridges/passkeys.d.cts +3 -3
  29. package/dist/bridges/passkeys.d.ts +3 -3
  30. package/dist/bridges/scene.d.cts +3 -3
  31. package/dist/bridges/scene.d.ts +3 -3
  32. package/dist/bridges/screens.d.cts +3 -3
  33. package/dist/bridges/screens.d.ts +3 -3
  34. package/dist/bridges/sheets.d.cts +3 -3
  35. package/dist/bridges/sheets.d.ts +3 -3
  36. package/dist/bridges/slides.d.cts +3 -3
  37. package/dist/bridges/slides.d.ts +3 -3
  38. package/dist/bridges/terminal.d.cts +3 -3
  39. package/dist/bridges/terminal.d.ts +3 -3
  40. package/dist/bridges/tui.d.cts +2 -2
  41. package/dist/bridges/tui.d.ts +2 -2
  42. package/dist/bridges/whiteboard.d.cts +3 -3
  43. package/dist/bridges/whiteboard.d.ts +3 -3
  44. package/dist/bridges-artboard.cjs.map +1 -1
  45. package/dist/bridges-artboard.js +2 -2
  46. package/dist/bridges-catalog.cjs.map +1 -1
  47. package/dist/bridges-catalog.js +3 -3
  48. package/dist/bridges-charts.cjs.map +1 -1
  49. package/dist/bridges-charts.js +3 -3
  50. package/dist/bridges-cms.cjs.map +1 -1
  51. package/dist/bridges-cms.js +4 -4
  52. package/dist/bridges-code.cjs.map +1 -1
  53. package/dist/bridges-code.js +3 -3
  54. package/dist/bridges-doc.cjs.map +1 -1
  55. package/dist/bridges-doc.js +3 -3
  56. package/dist/bridges-features.cjs.map +1 -1
  57. package/dist/bridges-features.js +3 -3
  58. package/dist/bridges-files.cjs.map +1 -1
  59. package/dist/bridges-files.js +3 -3
  60. package/dist/bridges-flow.cjs.map +1 -1
  61. package/dist/bridges-flow.js +2 -2
  62. package/dist/bridges-forms.cjs.map +1 -1
  63. package/dist/bridges-forms.js +3 -3
  64. package/dist/bridges-git.cjs.map +1 -1
  65. package/dist/bridges-git.js +3 -3
  66. package/dist/bridges-grid.cjs.map +1 -1
  67. package/dist/bridges-grid.js +3 -3
  68. package/dist/bridges-map.cjs.map +1 -1
  69. package/dist/bridges-map.js +3 -3
  70. package/dist/bridges-passkeys.cjs.map +1 -1
  71. package/dist/bridges-passkeys.js +3 -3
  72. package/dist/bridges-scene.cjs.map +1 -1
  73. package/dist/bridges-scene.js +3 -3
  74. package/dist/bridges-screens.cjs.map +1 -1
  75. package/dist/bridges-screens.js +3 -3
  76. package/dist/bridges-sheets.cjs.map +1 -1
  77. package/dist/bridges-sheets.js +3 -3
  78. package/dist/bridges-slides.cjs.map +1 -1
  79. package/dist/bridges-slides.js +3 -3
  80. package/dist/bridges-terminal.cjs.map +1 -1
  81. package/dist/bridges-terminal.js +3 -3
  82. package/dist/bridges-tui.cjs.map +1 -1
  83. package/dist/bridges-tui.js +2 -2
  84. package/dist/bridges-whiteboard.cjs.map +1 -1
  85. package/dist/bridges-whiteboard.js +3 -3
  86. package/dist/{chunk-5W6YOXLT.js → chunk-36MKPTVD.js} +4 -4
  87. package/dist/{chunk-5W6YOXLT.js.map → chunk-36MKPTVD.js.map} +1 -1
  88. package/dist/{chunk-SXVRIIXW.js → chunk-3HVYUMQF.js} +4 -4
  89. package/dist/{chunk-SXVRIIXW.js.map → chunk-3HVYUMQF.js.map} +1 -1
  90. package/dist/{chunk-MZ74LLDS.js → chunk-3UUF5KKZ.js} +4 -4
  91. package/dist/{chunk-MZ74LLDS.js.map → chunk-3UUF5KKZ.js.map} +1 -1
  92. package/dist/{chunk-WEXMZMJH.js → chunk-3WVXAB3D.js} +3 -3
  93. package/dist/{chunk-WEXMZMJH.js.map → chunk-3WVXAB3D.js.map} +1 -1
  94. package/dist/{chunk-OZBUPO4K.js → chunk-5W34X4EY.js} +263 -58
  95. package/dist/chunk-5W34X4EY.js.map +1 -0
  96. package/dist/{chunk-Z4L2GOAK.js → chunk-5ZWNCHZS.js} +4 -4
  97. package/dist/{chunk-Z4L2GOAK.js.map → chunk-5ZWNCHZS.js.map} +1 -1
  98. package/dist/{chunk-TEB5U6Y5.js → chunk-7NVATRLE.js} +4 -4
  99. package/dist/{chunk-TEB5U6Y5.js.map → chunk-7NVATRLE.js.map} +1 -1
  100. package/dist/{chunk-PUMQDV67.js → chunk-AXWMWYH5.js} +4 -4
  101. package/dist/{chunk-PUMQDV67.js.map → chunk-AXWMWYH5.js.map} +1 -1
  102. package/dist/{chunk-NKAH67JK.js → chunk-CS3CHGYC.js} +4 -4
  103. package/dist/{chunk-NKAH67JK.js.map → chunk-CS3CHGYC.js.map} +1 -1
  104. package/dist/{chunk-QJYRWEXD.js → chunk-CZV3WUW5.js} +35 -8
  105. package/dist/chunk-CZV3WUW5.js.map +1 -0
  106. package/dist/{chunk-PCFRBVKS.js → chunk-FCXSR7I5.js} +4 -4
  107. package/dist/{chunk-PCFRBVKS.js.map → chunk-FCXSR7I5.js.map} +1 -1
  108. package/dist/{chunk-NIFPRC7P.js → chunk-GVTBMJU6.js} +4 -4
  109. package/dist/{chunk-NIFPRC7P.js.map → chunk-GVTBMJU6.js.map} +1 -1
  110. package/dist/{chunk-E2I3YVKC.js → chunk-JLHVQWOV.js} +3 -3
  111. package/dist/{chunk-E2I3YVKC.js.map → chunk-JLHVQWOV.js.map} +1 -1
  112. package/dist/{chunk-2LSU3NFO.js → chunk-LQB42OSA.js} +4 -4
  113. package/dist/{chunk-2LSU3NFO.js.map → chunk-LQB42OSA.js.map} +1 -1
  114. package/dist/{chunk-VJD3Y7E5.js → chunk-MIDZWKIF.js} +4 -4
  115. package/dist/{chunk-VJD3Y7E5.js.map → chunk-MIDZWKIF.js.map} +1 -1
  116. package/dist/{chunk-LOD77NCD.js → chunk-PWYEW6NL.js} +4 -4
  117. package/dist/{chunk-LOD77NCD.js.map → chunk-PWYEW6NL.js.map} +1 -1
  118. package/dist/{chunk-HVDHT7DM.js → chunk-R4XXOGQH.js} +3 -3
  119. package/dist/{chunk-HVDHT7DM.js.map → chunk-R4XXOGQH.js.map} +1 -1
  120. package/dist/{chunk-7LLMILTM.js → chunk-RVMM4BHK.js} +4 -4
  121. package/dist/{chunk-7LLMILTM.js.map → chunk-RVMM4BHK.js.map} +1 -1
  122. package/dist/{chunk-NIXOY473.js → chunk-SWWJUOCY.js} +3 -3
  123. package/dist/{chunk-NIXOY473.js.map → chunk-SWWJUOCY.js.map} +1 -1
  124. package/dist/{chunk-EIBV76IB.js → chunk-VFWFT3OK.js} +4 -4
  125. package/dist/{chunk-EIBV76IB.js.map → chunk-VFWFT3OK.js.map} +1 -1
  126. package/dist/{chunk-2Q4EGZHJ.js → chunk-VMRUW4B4.js} +4 -4
  127. package/dist/{chunk-2Q4EGZHJ.js.map → chunk-VMRUW4B4.js.map} +1 -1
  128. package/dist/{chunk-GT63LSPJ.js → chunk-VOCUGTZB.js} +4 -4
  129. package/dist/{chunk-GT63LSPJ.js.map → chunk-VOCUGTZB.js.map} +1 -1
  130. package/dist/{chunk-N5VOPV64.js → chunk-Z5NL5D4J.js} +4 -4
  131. package/dist/{chunk-N5VOPV64.js.map → chunk-Z5NL5D4J.js.map} +1 -1
  132. package/dist/components-shared-whiteboard.cjs +33 -6
  133. package/dist/components-shared-whiteboard.cjs.map +1 -1
  134. package/dist/components-shared-whiteboard.js +3 -3
  135. package/dist/index.cjs +33 -6
  136. package/dist/index.cjs.map +1 -1
  137. package/dist/index.d.cts +7 -7
  138. package/dist/index.d.ts +7 -7
  139. package/dist/index.js +27 -27
  140. package/dist/mcp/index.d.cts +5 -5
  141. package/dist/mcp/index.d.ts +5 -5
  142. package/dist/mcp/stdio.d.cts +94 -0
  143. package/dist/mcp/stdio.d.ts +94 -0
  144. package/dist/mcp-stdio.cjs +120 -0
  145. package/dist/mcp-stdio.cjs.map +1 -0
  146. package/dist/mcp-stdio.js +117 -0
  147. package/dist/mcp-stdio.js.map +1 -0
  148. package/dist/mcp.cjs +33 -6
  149. package/dist/mcp.cjs.map +1 -1
  150. package/dist/mcp.js +1 -1
  151. package/dist/presence/index.d.cts +1 -1
  152. package/dist/presence/index.d.ts +1 -1
  153. package/dist/relay-server/index.d.cts +110 -26
  154. package/dist/relay-server/index.d.ts +110 -26
  155. package/dist/relay-server-cli.cjs +374 -89
  156. package/dist/relay-server-cli.cjs.map +1 -1
  157. package/dist/relay-server-cli.js +120 -38
  158. package/dist/relay-server-cli.js.map +1 -1
  159. package/dist/relay-server.cjs +255 -51
  160. package/dist/relay-server.cjs.map +1 -1
  161. package/dist/relay-server.js +1 -1
  162. package/dist/{server-BJNF7pQe.d.cts → server-BIcA3ZtK.d.cts} +32 -3
  163. package/dist/{server-Dt97UxuD.d.ts → server-DnUyeavY.d.ts} +32 -3
  164. package/dist/sharing/index.d.cts +3 -3
  165. package/dist/sharing/index.d.ts +3 -3
  166. package/dist/sheets-adapter.d.cts +3 -3
  167. package/dist/sheets-adapter.d.ts +3 -3
  168. package/dist/{tool-host-BpEBqf5u.d.cts → tool-host-LVBgCN5m.d.cts} +1 -1
  169. package/dist/{tool-host-xY5F-eqG.d.ts → tool-host-Wo0pkY83.d.ts} +1 -1
  170. package/dist/{types-DSwsNTBG.d.ts → types-BxNRKSVd.d.ts} +1 -1
  171. package/dist/{types-C58ZXs4K.d.cts → types-C2DtnHIn.d.cts} +25 -1
  172. package/dist/{types-C58ZXs4K.d.ts → types-C2DtnHIn.d.ts} +25 -1
  173. package/dist/{types-C4NaIW6B.d.cts → types-EcElKOlk.d.cts} +1 -1
  174. package/dist/undo/index.d.cts +2 -2
  175. package/dist/undo/index.d.ts +2 -2
  176. package/dist/undo.cjs.map +1 -1
  177. package/dist/undo.js +3 -3
  178. package/docs/relay-protocol.md +41 -5
  179. package/docs/relay-server.md +102 -15
  180. package/package.json +19 -2
  181. package/dist/chunk-OZBUPO4K.js.map +0 -1
  182. package/dist/chunk-QJYRWEXD.js.map +0 -1
package/dist/index.d.cts CHANGED
@@ -1,13 +1,13 @@
1
- import { M as MicroMcpServer } from './server-BJNF7pQe.cjs';
2
- export { a as McpServerOptions, T as Transport, e as errorResult, r as rpcError, t as textResult } from './server-BJNF7pQe.cjs';
3
- import { T as ToolHost } from './tool-host-BpEBqf5u.cjs';
4
- export { a as ToolRegistry } from './tool-host-BpEBqf5u.cjs';
1
+ import { M as MicroMcpServer } from './server-BIcA3ZtK.cjs';
2
+ export { a as McpServerOptions, T as Transport, e as errorResult, r as rpcError, t as textResult } from './server-BIcA3ZtK.cjs';
3
+ import { T as ToolHost } from './tool-host-LVBgCN5m.cjs';
4
+ export { a as ToolRegistry } from './tool-host-LVBgCN5m.cjs';
5
5
  export { InProcessTransport, RelayChannel, RelayTransport, attachInProcess, attachRelay } from './mcp/index.cjs';
6
- export { C as CallToolResult, d as ContentBlock, I as InitializeResult, J as JsonObject, b as JsonRpcMessage, e as JsonRpcNotification, f as JsonRpcRequest, g as JsonValue, M as MCP_PROTOCOL_VERSION, a as ServerCapabilities, S as ServerInfo, h as ToolCallContext, T as ToolDefinition, c as ToolHandler } from './types-C58ZXs4K.cjs';
6
+ export { C as CallToolResult, d as ContentBlock, I as InitializeResult, J as JsonObject, a as JsonRpcMessage, e as JsonRpcNotification, f as JsonRpcRequest, g as JsonValue, M as MCP_PROTOCOL_VERSION, c as ServerCapabilities, S as ServerInfo, h as ToolCallContext, T as ToolDefinition, b as ToolHandler } from './types-C2DtnHIn.cjs';
7
7
  export { HumanPlusDisposition, HumanPlusEvent, HumanPlusEventPage, HumanPlusEventQuery, HumanPlusEventStore, MemoryHumanPlusEventStore, NewHumanPlusEvent } from './human-plus/index.cjs';
8
8
  export { TuiBridgeOptions, TuiSurfaceRegistryLike, registerTuiBridge } from './bridges/tui.cjs';
9
- import { B as Bridge } from './types-C4NaIW6B.cjs';
10
- export { a as BridgeFactory } from './types-C4NaIW6B.cjs';
9
+ import { B as Bridge } from './types-EcElKOlk.cjs';
10
+ export { a as BridgeFactory } from './types-EcElKOlk.cjs';
11
11
  import { FormFieldDescriptor } from './bridges/forms.cjs';
12
12
  export { FormBridgeAdapter, FormBridgeOptions, registerFormBridge } from './bridges/forms.cjs';
13
13
  export { SheetsBridgeAdapter, SheetsBridgeOptions, registerSheetsBridge } from './bridges/sheets.cjs';
package/dist/index.d.ts CHANGED
@@ -1,13 +1,13 @@
1
- import { M as MicroMcpServer } from './server-Dt97UxuD.js';
2
- export { a as McpServerOptions, T as Transport, e as errorResult, r as rpcError, t as textResult } from './server-Dt97UxuD.js';
3
- import { T as ToolHost } from './tool-host-xY5F-eqG.js';
4
- export { a as ToolRegistry } from './tool-host-xY5F-eqG.js';
1
+ import { M as MicroMcpServer } from './server-DnUyeavY.js';
2
+ export { a as McpServerOptions, T as Transport, e as errorResult, r as rpcError, t as textResult } from './server-DnUyeavY.js';
3
+ import { T as ToolHost } from './tool-host-Wo0pkY83.js';
4
+ export { a as ToolRegistry } from './tool-host-Wo0pkY83.js';
5
5
  export { InProcessTransport, RelayChannel, RelayTransport, attachInProcess, attachRelay } from './mcp/index.js';
6
- export { C as CallToolResult, d as ContentBlock, I as InitializeResult, J as JsonObject, b as JsonRpcMessage, e as JsonRpcNotification, f as JsonRpcRequest, g as JsonValue, M as MCP_PROTOCOL_VERSION, a as ServerCapabilities, S as ServerInfo, h as ToolCallContext, T as ToolDefinition, c as ToolHandler } from './types-C58ZXs4K.js';
6
+ export { C as CallToolResult, d as ContentBlock, I as InitializeResult, J as JsonObject, a as JsonRpcMessage, e as JsonRpcNotification, f as JsonRpcRequest, g as JsonValue, M as MCP_PROTOCOL_VERSION, c as ServerCapabilities, S as ServerInfo, h as ToolCallContext, T as ToolDefinition, b as ToolHandler } from './types-C2DtnHIn.js';
7
7
  export { HumanPlusDisposition, HumanPlusEvent, HumanPlusEventPage, HumanPlusEventQuery, HumanPlusEventStore, MemoryHumanPlusEventStore, NewHumanPlusEvent } from './human-plus/index.js';
8
8
  export { TuiBridgeOptions, TuiSurfaceRegistryLike, registerTuiBridge } from './bridges/tui.js';
9
- import { B as Bridge } from './types-DSwsNTBG.js';
10
- export { a as BridgeFactory } from './types-DSwsNTBG.js';
9
+ import { B as Bridge } from './types-BxNRKSVd.js';
10
+ export { a as BridgeFactory } from './types-BxNRKSVd.js';
11
11
  import { FormFieldDescriptor } from './bridges/forms.js';
12
12
  export { FormBridgeAdapter, FormBridgeOptions, registerFormBridge } from './bridges/forms.js';
13
13
  export { SheetsBridgeAdapter, SheetsBridgeOptions, registerSheetsBridge } from './bridges/sheets.js';
package/dist/index.js CHANGED
@@ -1,4 +1,6 @@
1
- export { useUndoStack } from './chunk-WEXMZMJH.js';
1
+ export { attachHeuristicsSink, mapActivityToEvent as mapActivityToHeuristicsEvent } from './chunk-7R6RMROL.js';
2
+ export { useUndoStack } from './chunk-3WVXAB3D.js';
3
+ export { MemoryHumanPlusEventStore } from './chunk-PMI4C5S4.js';
2
4
  export { useSheetsActivityHighlights, useSheetsAdapter } from './chunk-KHKSQEMC.js';
3
5
  import { ConnectorButtons } from './chunk-5HNTNIWY.js';
4
6
  export { CLAUDE_CONNECTORS_URL, CONNECTOR_GLYPHS, CONNECTOR_TARGETS, ClaudeMark, ConnectorButtons, CursorMark, DesktopMark, VscodeMark, WrenchMark, buildCursorDeeplink, buildManualConfig, buildManualConfigSnippet, buildVscodeDeeplink, connectorHref, encodeBase64Json, slugifyServerName } from './chunk-5HNTNIWY.js';
@@ -8,41 +10,39 @@ export { AgentActivityHighlight, AgentCursor, AgentPanel, ShareControls, buildAg
8
10
  import './chunk-IJ6JX5VC.js';
9
11
  import { createSessionDescriptor, attachSseRelay } from './chunk-6TZ5IBRN.js';
10
12
  export { SseRelayTransport, attachSseRelay, buildShareConfig, buildShareUrl, createSessionDescriptor, describeSession, readSessionFromUrl } from './chunk-6TZ5IBRN.js';
11
- export { attachHeuristicsSink, mapActivityToEvent as mapActivityToHeuristicsEvent } from './chunk-7R6RMROL.js';
12
- export { registerTerminalBridge } from './chunk-Z4L2GOAK.js';
13
- export { registerCatalogBridge } from './chunk-NKAH67JK.js';
14
- export { registerFeaturesBridge } from './chunk-NIFPRC7P.js';
15
- export { PASSKEY_BRIDGE_TOOLS, registerPasskeyBridge } from './chunk-LOD77NCD.js';
16
- export { cmsReducer, registerCmsBridge } from './chunk-NIXOY473.js';
17
- import { registerDocBridge } from './chunk-SXVRIIXW.js';
18
- export { registerDocBridge } from './chunk-SXVRIIXW.js';
19
- export { registerTuiBridge } from './chunk-E2I3YVKC.js';
13
+ export { registerFilesBridge } from './chunk-Z5NL5D4J.js';
14
+ export { registerTerminalBridge } from './chunk-5ZWNCHZS.js';
15
+ export { registerCatalogBridge } from './chunk-CS3CHGYC.js';
16
+ export { registerFeaturesBridge } from './chunk-GVTBMJU6.js';
17
+ export { PASSKEY_BRIDGE_TOOLS, registerPasskeyBridge } from './chunk-PWYEW6NL.js';
18
+ export { cmsReducer, registerCmsBridge } from './chunk-SWWJUOCY.js';
19
+ import { registerDocBridge } from './chunk-3HVYUMQF.js';
20
+ export { registerDocBridge } from './chunk-3HVYUMQF.js';
21
+ export { registerTuiBridge } from './chunk-JLHVQWOV.js';
20
22
  import { useAgentActivity } from './chunk-UCKJAUBY.js';
21
23
  export { useAgentActivity, useAgentActivityForScreen } from './chunk-UCKJAUBY.js';
22
- export { MemoryHumanPlusEventStore } from './chunk-PMI4C5S4.js';
23
- export { registerChartsBridge } from './chunk-5W6YOXLT.js';
24
- export { registerGridBridge } from './chunk-VJD3Y7E5.js';
25
- export { registerSceneBridge } from './chunk-7LLMILTM.js';
26
- export { registerScreensBridge } from './chunk-TEB5U6Y5.js';
27
- export { registerSlidesBridge } from './chunk-2Q4EGZHJ.js';
28
- export { registerMapBridge } from './chunk-MZ74LLDS.js';
29
- export { registerGitBridge } from './chunk-PUMQDV67.js';
30
- export { registerFilesBridge } from './chunk-N5VOPV64.js';
24
+ export { registerCodeBridge } from './chunk-FCXSR7I5.js';
25
+ export { registerChartsBridge } from './chunk-36MKPTVD.js';
26
+ export { registerGridBridge } from './chunk-MIDZWKIF.js';
27
+ export { registerSceneBridge } from './chunk-RVMM4BHK.js';
28
+ export { registerScreensBridge } from './chunk-7NVATRLE.js';
29
+ export { registerSlidesBridge } from './chunk-VMRUW4B4.js';
30
+ export { registerMapBridge } from './chunk-3UUF5KKZ.js';
31
+ export { registerGitBridge } from './chunk-AXWMWYH5.js';
31
32
  export { RelayTransport, attachRelay } from './chunk-G6N2TQVO.js';
32
33
  import { attachInProcess } from './chunk-AFUULW5E.js';
33
34
  export { InProcessTransport, attachInProcess } from './chunk-AFUULW5E.js';
34
- import { registerFormBridge } from './chunk-EIBV76IB.js';
35
- export { registerFormBridge } from './chunk-EIBV76IB.js';
36
- export { registerSheetsBridge } from './chunk-GT63LSPJ.js';
37
- export { registerCodeBridge } from './chunk-PCFRBVKS.js';
38
- import { ensureUndoToolsRegistered, pushUndoEntry } from './chunk-HVDHT7DM.js';
39
- export { clearStack as clearUndoStack, ensureUndoToolsRegistered, pushUndoEntry, readHistory as readUndoHistory, redoOne, registerUndoTools, resetAllUndoStacks, undoOne } from './chunk-HVDHT7DM.js';
35
+ import { registerFormBridge } from './chunk-VFWFT3OK.js';
36
+ export { registerFormBridge } from './chunk-VFWFT3OK.js';
37
+ export { registerSheetsBridge } from './chunk-VOCUGTZB.js';
38
+ import { ensureUndoToolsRegistered, pushUndoEntry } from './chunk-R4XXOGQH.js';
39
+ export { clearStack as clearUndoStack, ensureUndoToolsRegistered, pushUndoEntry, readHistory as readUndoHistory, redoOne, registerUndoTools, resetAllUndoStacks, undoOne } from './chunk-R4XXOGQH.js';
40
40
  import { wrapToolWithActivity } from './chunk-2VENWGLZ.js';
41
41
  export { wrapToolWithActivity } from './chunk-2VENWGLZ.js';
42
42
  import { emitActivity, onActivity } from './chunk-C3TYI5TJ.js';
43
43
  export { emitActivity, onActivity, readActivityHistory, resetActivityRegistry } from './chunk-C3TYI5TJ.js';
44
- import { textResult, MicroMcpServer, errorResult } from './chunk-QJYRWEXD.js';
45
- export { MCP_PROTOCOL_VERSION, MicroMcpServer, ToolRegistry, errorResult, rpcError, textResult } from './chunk-QJYRWEXD.js';
44
+ import { textResult, MicroMcpServer, errorResult } from './chunk-CZV3WUW5.js';
45
+ export { MCP_PROTOCOL_VERSION, MicroMcpServer, ToolRegistry, errorResult, rpcError, textResult } from './chunk-CZV3WUW5.js';
46
46
  import { childrenOf, appendOrder } from '@particle-academy/fancy-doc-commons';
47
47
  import { useRef, useState, useEffect, useCallback, useMemo } from 'react';
48
48
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -1,8 +1,8 @@
1
- import { T as Transport, M as MicroMcpServer } from '../server-BJNF7pQe.cjs';
2
- export { a as McpServerOptions, e as errorResult, r as rpcError, t as textResult } from '../server-BJNF7pQe.cjs';
3
- import { b as JsonRpcMessage } from '../types-C58ZXs4K.cjs';
4
- export { C as CallToolResult, d as ContentBlock, I as InitializeResult, i as JSONRPC_INTERNAL_ERROR, j as JSONRPC_INVALID_PARAMS, k as JSONRPC_INVALID_REQUEST, l as JSONRPC_METHOD_NOT_FOUND, m as JSONRPC_PARSE_ERROR, J as JsonObject, n as JsonRpcError, o as JsonRpcId, e as JsonRpcNotification, f as JsonRpcRequest, p as JsonRpcSuccess, g as JsonValue, M as MCP_PROTOCOL_VERSION, R as RegisteredTool, a as ServerCapabilities, S as ServerInfo, h as ToolCallContext, T as ToolDefinition, c as ToolHandler, q as ToolInputSchema } from '../types-C58ZXs4K.cjs';
5
- import '../tool-host-BpEBqf5u.cjs';
1
+ import { T as Transport, M as MicroMcpServer } from '../server-BIcA3ZtK.cjs';
2
+ export { a as McpServerOptions, e as errorResult, r as rpcError, t as textResult } from '../server-BIcA3ZtK.cjs';
3
+ import { a as JsonRpcMessage } from '../types-C2DtnHIn.cjs';
4
+ export { C as CallToolResult, d as ContentBlock, I as InitializeResult, i as JSONRPC_INTERNAL_ERROR, j as JSONRPC_INVALID_PARAMS, k as JSONRPC_INVALID_REQUEST, l as JSONRPC_METHOD_NOT_FOUND, m as JSONRPC_PARSE_ERROR, J as JsonObject, n as JsonRpcError, o as JsonRpcId, e as JsonRpcNotification, f as JsonRpcRequest, p as JsonRpcSuccess, g as JsonValue, M as MCP_PROTOCOL_VERSION, R as RegisteredTool, c as ServerCapabilities, S as ServerInfo, q as ToolAnnotations, h as ToolCallContext, T as ToolDefinition, b as ToolHandler, r as ToolInputSchema } from '../types-C2DtnHIn.cjs';
5
+ import '../tool-host-LVBgCN5m.cjs';
6
6
 
7
7
  /**
8
8
  * InProcessTransport — direct function-call wiring between an in-page MCP
@@ -1,8 +1,8 @@
1
- import { T as Transport, M as MicroMcpServer } from '../server-Dt97UxuD.js';
2
- export { a as McpServerOptions, e as errorResult, r as rpcError, t as textResult } from '../server-Dt97UxuD.js';
3
- import { b as JsonRpcMessage } from '../types-C58ZXs4K.js';
4
- export { C as CallToolResult, d as ContentBlock, I as InitializeResult, i as JSONRPC_INTERNAL_ERROR, j as JSONRPC_INVALID_PARAMS, k as JSONRPC_INVALID_REQUEST, l as JSONRPC_METHOD_NOT_FOUND, m as JSONRPC_PARSE_ERROR, J as JsonObject, n as JsonRpcError, o as JsonRpcId, e as JsonRpcNotification, f as JsonRpcRequest, p as JsonRpcSuccess, g as JsonValue, M as MCP_PROTOCOL_VERSION, R as RegisteredTool, a as ServerCapabilities, S as ServerInfo, h as ToolCallContext, T as ToolDefinition, c as ToolHandler, q as ToolInputSchema } from '../types-C58ZXs4K.js';
5
- import '../tool-host-xY5F-eqG.js';
1
+ import { T as Transport, M as MicroMcpServer } from '../server-DnUyeavY.js';
2
+ export { a as McpServerOptions, e as errorResult, r as rpcError, t as textResult } from '../server-DnUyeavY.js';
3
+ import { a as JsonRpcMessage } from '../types-C2DtnHIn.js';
4
+ export { C as CallToolResult, d as ContentBlock, I as InitializeResult, i as JSONRPC_INTERNAL_ERROR, j as JSONRPC_INVALID_PARAMS, k as JSONRPC_INVALID_REQUEST, l as JSONRPC_METHOD_NOT_FOUND, m as JSONRPC_PARSE_ERROR, J as JsonObject, n as JsonRpcError, o as JsonRpcId, e as JsonRpcNotification, f as JsonRpcRequest, p as JsonRpcSuccess, g as JsonValue, M as MCP_PROTOCOL_VERSION, R as RegisteredTool, c as ServerCapabilities, S as ServerInfo, q as ToolAnnotations, h as ToolCallContext, T as ToolDefinition, b as ToolHandler, r as ToolInputSchema } from '../types-C2DtnHIn.js';
5
+ import '../tool-host-Wo0pkY83.js';
6
6
 
7
7
  /**
8
8
  * InProcessTransport — direct function-call wiring between an in-page MCP
@@ -0,0 +1,94 @@
1
+ import { T as Transport, M as MicroMcpServer } from '../server-BIcA3ZtK.cjs';
2
+ import { a as JsonRpcMessage } from '../types-C2DtnHIn.cjs';
3
+ import '../tool-host-LVBgCN5m.cjs';
4
+
5
+ /**
6
+ * StdioTransport — newline-delimited JSON-RPC over a byte stream pair.
7
+ *
8
+ * This is the framing every MCP client uses when it launches a server as a
9
+ * subprocess (Claude Code, Codex, Cursor, Claude Desktop): one JSON-RPC message
10
+ * per line on stdin, one per line on stdout. Anything else a server wants to say
11
+ * goes to stderr, because a stray write to stdout corrupts the stream and the
12
+ * client sees a parse error instead of a message.
13
+ *
14
+ * NODE ONLY, which is why it is its own subpath (`/mcp/stdio`) rather than part
15
+ * of `/mcp`: browser bundles import `/mcp`, and `node:*` imports there would
16
+ * break them.
17
+ *
18
+ * import { MicroMcpServer } from "@particle-academy/agent-integrations/mcp";
19
+ * import { attachStdio } from "@particle-academy/agent-integrations/mcp/stdio";
20
+ *
21
+ * const server = new MicroMcpServer({ info: { name: "my-server", version: "1.0.0" } });
22
+ * server.registerTool(...);
23
+ * attachStdio(server);
24
+ *
25
+ * What it deliberately does:
26
+ *
27
+ * - **A bad line costs that line, not the session.** A line that is not JSON, or
28
+ * is JSON but not a single JSON-RPC message (a number, `null`, a batch), is
29
+ * reported through `onError` and skipped. No reply is written for it — there
30
+ * is no request id to address one to, and stdout carries protocol frames only.
31
+ * - **Input ending does not drop a reply that is still owed.** `printf
32
+ * '<request>\n' | server` closes stdin straight after the request; replies
33
+ * already in flight are delivered, then the transport closes.
34
+ * - **Bytes, not chunks, are decoded.** A chunk boundary can cut a multi-byte
35
+ * character in half; decoding chunk by chunk would corrupt it.
36
+ */
37
+ /** The readable half. `process.stdin` and any Node `Readable` satisfy it. */
38
+ interface StdioInput {
39
+ on(event: "data", listener: (chunk: unknown) => void): unknown;
40
+ on(event: "end", listener: () => void): unknown;
41
+ on(event: "error", listener: (error: Error) => void): unknown;
42
+ removeListener(event: string, listener: (...args: any[]) => void): unknown;
43
+ pause?(): unknown;
44
+ }
45
+ /** The writable half. `process.stdout` and any Node `Writable` satisfy it. */
46
+ interface StdioOutput {
47
+ write(chunk: string): unknown;
48
+ on?(event: "error", listener: (error: Error) => void): unknown;
49
+ removeListener?(event: string, listener: (...args: any[]) => void): unknown;
50
+ }
51
+ type StdioOptions = {
52
+ /** Defaults to `process.stdin`. */
53
+ input?: StdioInput;
54
+ /** Defaults to `process.stdout`. */
55
+ output?: StdioOutput;
56
+ /**
57
+ * A line that could not be served, or a stream error. Defaults to one line on
58
+ * `process.stderr` — the channel the MCP spec reserves for exactly this.
59
+ */
60
+ onError?: (error: Error) => void;
61
+ /** Called once, when the transport closes (input ended, or `close()`). */
62
+ onClose?: () => void;
63
+ };
64
+ declare class StdioTransport implements Transport {
65
+ private server?;
66
+ private readonly input;
67
+ private readonly output;
68
+ private readonly reportError;
69
+ private readonly onClose?;
70
+ private readonly decoder;
71
+ private buffer;
72
+ private closed;
73
+ private started;
74
+ private readonly inFlight;
75
+ constructor(options?: StdioOptions);
76
+ /** Bind to a server. `attachStdio` does this for you. */
77
+ bindServer(server: MicroMcpServer): void;
78
+ /** Begin reading input. `attachStdio` does this for you. */
79
+ start(): void;
80
+ /** Server → client: one message, one line. `JSON.stringify` escapes every newline inside it. */
81
+ send(message: JsonRpcMessage): void;
82
+ close(): void;
83
+ private readonly onData;
84
+ private readonly onEnd;
85
+ private readonly onStreamError;
86
+ private serve;
87
+ }
88
+ /**
89
+ * Serve `server` over stdio (or the streams you pass). Returns the transport;
90
+ * `server.detach(transport)` or `transport.close()` stops it.
91
+ */
92
+ declare function attachStdio(server: MicroMcpServer, options?: StdioOptions): StdioTransport;
93
+
94
+ export { type StdioInput, type StdioOptions, type StdioOutput, StdioTransport, attachStdio };
@@ -0,0 +1,94 @@
1
+ import { T as Transport, M as MicroMcpServer } from '../server-DnUyeavY.js';
2
+ import { a as JsonRpcMessage } from '../types-C2DtnHIn.js';
3
+ import '../tool-host-Wo0pkY83.js';
4
+
5
+ /**
6
+ * StdioTransport — newline-delimited JSON-RPC over a byte stream pair.
7
+ *
8
+ * This is the framing every MCP client uses when it launches a server as a
9
+ * subprocess (Claude Code, Codex, Cursor, Claude Desktop): one JSON-RPC message
10
+ * per line on stdin, one per line on stdout. Anything else a server wants to say
11
+ * goes to stderr, because a stray write to stdout corrupts the stream and the
12
+ * client sees a parse error instead of a message.
13
+ *
14
+ * NODE ONLY, which is why it is its own subpath (`/mcp/stdio`) rather than part
15
+ * of `/mcp`: browser bundles import `/mcp`, and `node:*` imports there would
16
+ * break them.
17
+ *
18
+ * import { MicroMcpServer } from "@particle-academy/agent-integrations/mcp";
19
+ * import { attachStdio } from "@particle-academy/agent-integrations/mcp/stdio";
20
+ *
21
+ * const server = new MicroMcpServer({ info: { name: "my-server", version: "1.0.0" } });
22
+ * server.registerTool(...);
23
+ * attachStdio(server);
24
+ *
25
+ * What it deliberately does:
26
+ *
27
+ * - **A bad line costs that line, not the session.** A line that is not JSON, or
28
+ * is JSON but not a single JSON-RPC message (a number, `null`, a batch), is
29
+ * reported through `onError` and skipped. No reply is written for it — there
30
+ * is no request id to address one to, and stdout carries protocol frames only.
31
+ * - **Input ending does not drop a reply that is still owed.** `printf
32
+ * '<request>\n' | server` closes stdin straight after the request; replies
33
+ * already in flight are delivered, then the transport closes.
34
+ * - **Bytes, not chunks, are decoded.** A chunk boundary can cut a multi-byte
35
+ * character in half; decoding chunk by chunk would corrupt it.
36
+ */
37
+ /** The readable half. `process.stdin` and any Node `Readable` satisfy it. */
38
+ interface StdioInput {
39
+ on(event: "data", listener: (chunk: unknown) => void): unknown;
40
+ on(event: "end", listener: () => void): unknown;
41
+ on(event: "error", listener: (error: Error) => void): unknown;
42
+ removeListener(event: string, listener: (...args: any[]) => void): unknown;
43
+ pause?(): unknown;
44
+ }
45
+ /** The writable half. `process.stdout` and any Node `Writable` satisfy it. */
46
+ interface StdioOutput {
47
+ write(chunk: string): unknown;
48
+ on?(event: "error", listener: (error: Error) => void): unknown;
49
+ removeListener?(event: string, listener: (...args: any[]) => void): unknown;
50
+ }
51
+ type StdioOptions = {
52
+ /** Defaults to `process.stdin`. */
53
+ input?: StdioInput;
54
+ /** Defaults to `process.stdout`. */
55
+ output?: StdioOutput;
56
+ /**
57
+ * A line that could not be served, or a stream error. Defaults to one line on
58
+ * `process.stderr` — the channel the MCP spec reserves for exactly this.
59
+ */
60
+ onError?: (error: Error) => void;
61
+ /** Called once, when the transport closes (input ended, or `close()`). */
62
+ onClose?: () => void;
63
+ };
64
+ declare class StdioTransport implements Transport {
65
+ private server?;
66
+ private readonly input;
67
+ private readonly output;
68
+ private readonly reportError;
69
+ private readonly onClose?;
70
+ private readonly decoder;
71
+ private buffer;
72
+ private closed;
73
+ private started;
74
+ private readonly inFlight;
75
+ constructor(options?: StdioOptions);
76
+ /** Bind to a server. `attachStdio` does this for you. */
77
+ bindServer(server: MicroMcpServer): void;
78
+ /** Begin reading input. `attachStdio` does this for you. */
79
+ start(): void;
80
+ /** Server → client: one message, one line. `JSON.stringify` escapes every newline inside it. */
81
+ send(message: JsonRpcMessage): void;
82
+ close(): void;
83
+ private readonly onData;
84
+ private readonly onEnd;
85
+ private readonly onStreamError;
86
+ private serve;
87
+ }
88
+ /**
89
+ * Serve `server` over stdio (or the streams you pass). Returns the transport;
90
+ * `server.detach(transport)` or `transport.close()` stops it.
91
+ */
92
+ declare function attachStdio(server: MicroMcpServer, options?: StdioOptions): StdioTransport;
93
+
94
+ export { type StdioInput, type StdioOptions, type StdioOutput, StdioTransport, attachStdio };
@@ -0,0 +1,120 @@
1
+ 'use strict';
2
+
3
+ var process = require('process');
4
+ var string_decoder = require('string_decoder');
5
+
6
+ // src/mcp/stdio.ts
7
+ var StdioTransport = class {
8
+ constructor(options = {}) {
9
+ this.decoder = new string_decoder.StringDecoder("utf8");
10
+ this.buffer = "";
11
+ this.closed = false;
12
+ this.started = false;
13
+ this.inFlight = /* @__PURE__ */ new Set();
14
+ this.onData = (chunk) => {
15
+ if (this.closed) return;
16
+ this.buffer += typeof chunk === "string" ? chunk : this.decoder.write(chunk);
17
+ let newline = this.buffer.indexOf("\n");
18
+ while (newline !== -1) {
19
+ const line = this.buffer.slice(0, newline);
20
+ this.buffer = this.buffer.slice(newline + 1);
21
+ this.serve(line);
22
+ newline = this.buffer.indexOf("\n");
23
+ }
24
+ };
25
+ this.onEnd = () => {
26
+ if (this.closed) return;
27
+ this.buffer += this.decoder.end();
28
+ const last = this.buffer;
29
+ this.buffer = "";
30
+ this.serve(last);
31
+ void Promise.allSettled([...this.inFlight]).then(() => {
32
+ this.server?.detach(this);
33
+ this.close();
34
+ });
35
+ };
36
+ this.onStreamError = (error) => {
37
+ this.reportError(error);
38
+ };
39
+ this.input = options.input ?? process.stdin;
40
+ this.output = options.output ?? process.stdout;
41
+ const onError = options.onError ?? ((error) => process.stderr.write(`[mcp stdio] ${error.message}
42
+ `));
43
+ this.reportError = (error) => {
44
+ try {
45
+ onError(error);
46
+ } catch {
47
+ }
48
+ };
49
+ this.onClose = options.onClose;
50
+ }
51
+ /** Bind to a server. `attachStdio` does this for you. */
52
+ bindServer(server) {
53
+ this.server = server;
54
+ }
55
+ /** Begin reading input. `attachStdio` does this for you. */
56
+ start() {
57
+ if (this.started || this.closed) return;
58
+ this.started = true;
59
+ this.input.on("data", this.onData);
60
+ this.input.on("end", this.onEnd);
61
+ this.input.on("error", this.onStreamError);
62
+ this.output.on?.("error", this.onStreamError);
63
+ }
64
+ /** Server → client: one message, one line. `JSON.stringify` escapes every newline inside it. */
65
+ send(message) {
66
+ if (this.closed) return;
67
+ this.output.write(`${JSON.stringify(message)}
68
+ `);
69
+ }
70
+ close() {
71
+ if (this.closed) return;
72
+ this.closed = true;
73
+ this.input.removeListener("data", this.onData);
74
+ this.input.removeListener("end", this.onEnd);
75
+ this.input.removeListener("error", this.onStreamError);
76
+ this.output.removeListener?.("error", this.onStreamError);
77
+ this.input.pause?.();
78
+ this.onClose?.();
79
+ }
80
+ serve(raw) {
81
+ const line = raw.endsWith("\r") ? raw.slice(0, -1) : raw;
82
+ if (line.trim() === "") return;
83
+ let message;
84
+ try {
85
+ message = JSON.parse(line);
86
+ } catch (error) {
87
+ this.reportError(new Error(`Ignored a line that is not JSON (${error.message}): ${preview(line)}`));
88
+ return;
89
+ }
90
+ if (message === null || typeof message !== "object") {
91
+ this.reportError(new Error(`Ignored a line that is JSON but not a JSON-RPC message: ${preview(line)}`));
92
+ return;
93
+ }
94
+ if (Array.isArray(message)) {
95
+ this.reportError(new Error(`Ignored a JSON-RPC batch; this transport serves one message per line: ${preview(line)}`));
96
+ return;
97
+ }
98
+ if (!this.server) {
99
+ this.reportError(new Error("StdioTransport has no bound server; use attachStdio(server)."));
100
+ return;
101
+ }
102
+ const pending = this.server.receive(this, message).catch((error) => this.reportError(error instanceof Error ? error : new Error(String(error)))).finally(() => this.inFlight.delete(pending));
103
+ this.inFlight.add(pending);
104
+ }
105
+ };
106
+ function preview(line) {
107
+ return line.length > 120 ? `${line.slice(0, 120)}\u2026` : line;
108
+ }
109
+ function attachStdio(server, options = {}) {
110
+ const transport = new StdioTransport(options);
111
+ transport.bindServer(server);
112
+ server.attach(transport);
113
+ transport.start();
114
+ return transport;
115
+ }
116
+
117
+ exports.StdioTransport = StdioTransport;
118
+ exports.attachStdio = attachStdio;
119
+ //# sourceMappingURL=mcp-stdio.cjs.map
120
+ //# sourceMappingURL=mcp-stdio.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp/stdio.ts"],"names":["StringDecoder","stdin","stdout","stderr"],"mappings":"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","file":"mcp-stdio.cjs","sourcesContent":["import { stderr, stdin, stdout } from \"node:process\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport type { MicroMcpServer, Transport } from \"./server\";\nimport type { JsonRpcMessage } from \"./types\";\n\n/**\n * StdioTransport — newline-delimited JSON-RPC over a byte stream pair.\n *\n * This is the framing every MCP client uses when it launches a server as a\n * subprocess (Claude Code, Codex, Cursor, Claude Desktop): one JSON-RPC message\n * per line on stdin, one per line on stdout. Anything else a server wants to say\n * goes to stderr, because a stray write to stdout corrupts the stream and the\n * client sees a parse error instead of a message.\n *\n * NODE ONLY, which is why it is its own subpath (`/mcp/stdio`) rather than part\n * of `/mcp`: browser bundles import `/mcp`, and `node:*` imports there would\n * break them.\n *\n * import { MicroMcpServer } from \"@particle-academy/agent-integrations/mcp\";\n * import { attachStdio } from \"@particle-academy/agent-integrations/mcp/stdio\";\n *\n * const server = new MicroMcpServer({ info: { name: \"my-server\", version: \"1.0.0\" } });\n * server.registerTool(...);\n * attachStdio(server);\n *\n * What it deliberately does:\n *\n * - **A bad line costs that line, not the session.** A line that is not JSON, or\n * is JSON but not a single JSON-RPC message (a number, `null`, a batch), is\n * reported through `onError` and skipped. No reply is written for it — there\n * is no request id to address one to, and stdout carries protocol frames only.\n * - **Input ending does not drop a reply that is still owed.** `printf\n * '<request>\\n' | server` closes stdin straight after the request; replies\n * already in flight are delivered, then the transport closes.\n * - **Bytes, not chunks, are decoded.** A chunk boundary can cut a multi-byte\n * character in half; decoding chunk by chunk would corrupt it.\n */\n\n/** The readable half. `process.stdin` and any Node `Readable` satisfy it. */\nexport interface StdioInput {\n on(event: \"data\", listener: (chunk: unknown) => void): unknown;\n on(event: \"end\", listener: () => void): unknown;\n on(event: \"error\", listener: (error: Error) => void): unknown;\n removeListener(event: string, listener: (...args: any[]) => void): unknown;\n pause?(): unknown;\n}\n\n/** The writable half. `process.stdout` and any Node `Writable` satisfy it. */\nexport interface StdioOutput {\n write(chunk: string): unknown;\n on?(event: \"error\", listener: (error: Error) => void): unknown;\n removeListener?(event: string, listener: (...args: any[]) => void): unknown;\n}\n\nexport type StdioOptions = {\n /** Defaults to `process.stdin`. */\n input?: StdioInput;\n /** Defaults to `process.stdout`. */\n output?: StdioOutput;\n /**\n * A line that could not be served, or a stream error. Defaults to one line on\n * `process.stderr` — the channel the MCP spec reserves for exactly this.\n */\n onError?: (error: Error) => void;\n /** Called once, when the transport closes (input ended, or `close()`). */\n onClose?: () => void;\n};\n\nexport class StdioTransport implements Transport {\n private server?: MicroMcpServer;\n private readonly input: StdioInput;\n private readonly output: StdioOutput;\n private readonly reportError: (error: Error) => void;\n private readonly onClose?: () => void;\n private readonly decoder = new StringDecoder(\"utf8\");\n private buffer = \"\";\n private closed = false;\n private started = false;\n private readonly inFlight = new Set<Promise<void>>();\n\n constructor(options: StdioOptions = {}) {\n this.input = options.input ?? stdin;\n this.output = options.output ?? stdout;\n const onError = options.onError ?? ((error: Error) => stderr.write(`[mcp stdio] ${error.message}\\n`));\n // A host's error handler that throws must not take the session down with\n // it: it runs inside a stream callback, where a throw is an uncaught error.\n this.reportError = (error) => {\n try {\n onError(error);\n } catch {\n /* nothing useful left to report it to */\n }\n };\n this.onClose = options.onClose;\n }\n\n /** Bind to a server. `attachStdio` does this for you. */\n bindServer(server: MicroMcpServer): void {\n this.server = server;\n }\n\n /** Begin reading input. `attachStdio` does this for you. */\n start(): void {\n if (this.started || this.closed) return;\n this.started = true;\n this.input.on(\"data\", this.onData);\n this.input.on(\"end\", this.onEnd);\n this.input.on(\"error\", this.onStreamError);\n this.output.on?.(\"error\", this.onStreamError);\n }\n\n /** Server → client: one message, one line. `JSON.stringify` escapes every newline inside it. */\n send(message: JsonRpcMessage): void {\n if (this.closed) return;\n this.output.write(`${JSON.stringify(message)}\\n`);\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n this.input.removeListener(\"data\", this.onData);\n this.input.removeListener(\"end\", this.onEnd);\n this.input.removeListener(\"error\", this.onStreamError);\n this.output.removeListener?.(\"error\", this.onStreamError);\n // Removing the data listener does not stop a flowing stream by itself, and\n // a flowing stdin keeps the process alive.\n this.input.pause?.();\n this.onClose?.();\n }\n\n private readonly onData = (chunk: unknown): void => {\n if (this.closed) return;\n this.buffer += typeof chunk === \"string\" ? chunk : this.decoder.write(chunk as Uint8Array);\n\n let newline = this.buffer.indexOf(\"\\n\");\n while (newline !== -1) {\n const line = this.buffer.slice(0, newline);\n this.buffer = this.buffer.slice(newline + 1);\n this.serve(line);\n newline = this.buffer.indexOf(\"\\n\");\n }\n };\n\n private readonly onEnd = (): void => {\n if (this.closed) return;\n this.buffer += this.decoder.end();\n const last = this.buffer;\n this.buffer = \"\";\n this.serve(last);\n\n // Deliver what is owed before closing, or a request followed immediately by\n // end-of-input never gets its reply.\n void Promise.allSettled([...this.inFlight]).then(() => {\n this.server?.detach(this);\n this.close();\n });\n };\n\n private readonly onStreamError = (error: Error): void => {\n this.reportError(error);\n };\n\n private serve(raw: string): void {\n const line = raw.endsWith(\"\\r\") ? raw.slice(0, -1) : raw;\n if (line.trim() === \"\") return;\n\n let message: unknown;\n try {\n message = JSON.parse(line);\n } catch (error) {\n this.reportError(new Error(`Ignored a line that is not JSON (${(error as Error).message}): ${preview(line)}`));\n return;\n }\n\n if (message === null || typeof message !== \"object\") {\n this.reportError(new Error(`Ignored a line that is JSON but not a JSON-RPC message: ${preview(line)}`));\n return;\n }\n if (Array.isArray(message)) {\n this.reportError(new Error(`Ignored a JSON-RPC batch; this transport serves one message per line: ${preview(line)}`));\n return;\n }\n if (!this.server) {\n this.reportError(new Error(\"StdioTransport has no bound server; use attachStdio(server).\"));\n return;\n }\n\n const pending: Promise<void> = this.server\n .receive(this, message as JsonRpcMessage)\n .catch((error: unknown) => this.reportError(error instanceof Error ? error : new Error(String(error))))\n .finally(() => this.inFlight.delete(pending));\n this.inFlight.add(pending);\n }\n}\n\nfunction preview(line: string): string {\n return line.length > 120 ? `${line.slice(0, 120)}…` : line;\n}\n\n/**\n * Serve `server` over stdio (or the streams you pass). Returns the transport;\n * `server.detach(transport)` or `transport.close()` stops it.\n */\nexport function attachStdio(server: MicroMcpServer, options: StdioOptions = {}): StdioTransport {\n const transport = new StdioTransport(options);\n transport.bindServer(server);\n server.attach(transport);\n transport.start();\n return transport;\n}\n"]}
@@ -0,0 +1,117 @@
1
+ import { stdin, stdout, stderr } from 'process';
2
+ import { StringDecoder } from 'string_decoder';
3
+
4
+ // src/mcp/stdio.ts
5
+ var StdioTransport = class {
6
+ constructor(options = {}) {
7
+ this.decoder = new StringDecoder("utf8");
8
+ this.buffer = "";
9
+ this.closed = false;
10
+ this.started = false;
11
+ this.inFlight = /* @__PURE__ */ new Set();
12
+ this.onData = (chunk) => {
13
+ if (this.closed) return;
14
+ this.buffer += typeof chunk === "string" ? chunk : this.decoder.write(chunk);
15
+ let newline = this.buffer.indexOf("\n");
16
+ while (newline !== -1) {
17
+ const line = this.buffer.slice(0, newline);
18
+ this.buffer = this.buffer.slice(newline + 1);
19
+ this.serve(line);
20
+ newline = this.buffer.indexOf("\n");
21
+ }
22
+ };
23
+ this.onEnd = () => {
24
+ if (this.closed) return;
25
+ this.buffer += this.decoder.end();
26
+ const last = this.buffer;
27
+ this.buffer = "";
28
+ this.serve(last);
29
+ void Promise.allSettled([...this.inFlight]).then(() => {
30
+ this.server?.detach(this);
31
+ this.close();
32
+ });
33
+ };
34
+ this.onStreamError = (error) => {
35
+ this.reportError(error);
36
+ };
37
+ this.input = options.input ?? stdin;
38
+ this.output = options.output ?? stdout;
39
+ const onError = options.onError ?? ((error) => stderr.write(`[mcp stdio] ${error.message}
40
+ `));
41
+ this.reportError = (error) => {
42
+ try {
43
+ onError(error);
44
+ } catch {
45
+ }
46
+ };
47
+ this.onClose = options.onClose;
48
+ }
49
+ /** Bind to a server. `attachStdio` does this for you. */
50
+ bindServer(server) {
51
+ this.server = server;
52
+ }
53
+ /** Begin reading input. `attachStdio` does this for you. */
54
+ start() {
55
+ if (this.started || this.closed) return;
56
+ this.started = true;
57
+ this.input.on("data", this.onData);
58
+ this.input.on("end", this.onEnd);
59
+ this.input.on("error", this.onStreamError);
60
+ this.output.on?.("error", this.onStreamError);
61
+ }
62
+ /** Server → client: one message, one line. `JSON.stringify` escapes every newline inside it. */
63
+ send(message) {
64
+ if (this.closed) return;
65
+ this.output.write(`${JSON.stringify(message)}
66
+ `);
67
+ }
68
+ close() {
69
+ if (this.closed) return;
70
+ this.closed = true;
71
+ this.input.removeListener("data", this.onData);
72
+ this.input.removeListener("end", this.onEnd);
73
+ this.input.removeListener("error", this.onStreamError);
74
+ this.output.removeListener?.("error", this.onStreamError);
75
+ this.input.pause?.();
76
+ this.onClose?.();
77
+ }
78
+ serve(raw) {
79
+ const line = raw.endsWith("\r") ? raw.slice(0, -1) : raw;
80
+ if (line.trim() === "") return;
81
+ let message;
82
+ try {
83
+ message = JSON.parse(line);
84
+ } catch (error) {
85
+ this.reportError(new Error(`Ignored a line that is not JSON (${error.message}): ${preview(line)}`));
86
+ return;
87
+ }
88
+ if (message === null || typeof message !== "object") {
89
+ this.reportError(new Error(`Ignored a line that is JSON but not a JSON-RPC message: ${preview(line)}`));
90
+ return;
91
+ }
92
+ if (Array.isArray(message)) {
93
+ this.reportError(new Error(`Ignored a JSON-RPC batch; this transport serves one message per line: ${preview(line)}`));
94
+ return;
95
+ }
96
+ if (!this.server) {
97
+ this.reportError(new Error("StdioTransport has no bound server; use attachStdio(server)."));
98
+ return;
99
+ }
100
+ const pending = this.server.receive(this, message).catch((error) => this.reportError(error instanceof Error ? error : new Error(String(error)))).finally(() => this.inFlight.delete(pending));
101
+ this.inFlight.add(pending);
102
+ }
103
+ };
104
+ function preview(line) {
105
+ return line.length > 120 ? `${line.slice(0, 120)}\u2026` : line;
106
+ }
107
+ function attachStdio(server, options = {}) {
108
+ const transport = new StdioTransport(options);
109
+ transport.bindServer(server);
110
+ server.attach(transport);
111
+ transport.start();
112
+ return transport;
113
+ }
114
+
115
+ export { StdioTransport, attachStdio };
116
+ //# sourceMappingURL=mcp-stdio.js.map
117
+ //# sourceMappingURL=mcp-stdio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp/stdio.ts"],"names":[],"mappings":";;;;AAoEO,IAAM,iBAAN,MAA0C;AAAA,EAY/C,WAAA,CAAY,OAAA,GAAwB,EAAC,EAAG;AANxC,IAAA,IAAA,CAAiB,OAAA,GAAU,IAAI,aAAA,CAAc,MAAM,CAAA;AACnD,IAAA,IAAA,CAAQ,MAAA,GAAS,EAAA;AACjB,IAAA,IAAA,CAAQ,MAAA,GAAS,KAAA;AACjB,IAAA,IAAA,CAAQ,OAAA,GAAU,KAAA;AAClB,IAAA,IAAA,CAAiB,QAAA,uBAAe,GAAA,EAAmB;AAoDnD,IAAA,IAAA,CAAiB,MAAA,GAAS,CAAC,KAAA,KAAyB;AAClD,MAAA,IAAI,KAAK,MAAA,EAAQ;AACjB,MAAA,IAAA,CAAK,MAAA,IAAU,OAAO,KAAA,KAAU,QAAA,GAAW,QAAQ,IAAA,CAAK,OAAA,CAAQ,MAAM,KAAmB,CAAA;AAEzF,MAAA,IAAI,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA;AACtC,MAAA,OAAO,YAAY,EAAA,EAAI;AACrB,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,GAAG,OAAO,CAAA;AACzC,QAAA,IAAA,CAAK,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,UAAU,CAAC,CAAA;AAC3C,QAAA,IAAA,CAAK,MAAM,IAAI,CAAA;AACf,QAAA,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA;AAAA,MACpC;AAAA,IACF,CAAA;AAEA,IAAA,IAAA,CAAiB,QAAQ,MAAY;AACnC,MAAA,IAAI,KAAK,MAAA,EAAQ;AACjB,MAAA,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAI;AAChC,MAAA,MAAM,OAAO,IAAA,CAAK,MAAA;AAClB,MAAA,IAAA,CAAK,MAAA,GAAS,EAAA;AACd,MAAA,IAAA,CAAK,MAAM,IAAI,CAAA;AAIf,MAAA,KAAK,OAAA,CAAQ,WAAW,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAA,CAAE,IAAA,CAAK,MAAM;AACrD,QAAA,IAAA,CAAK,MAAA,EAAQ,OAAO,IAAI,CAAA;AACxB,QAAA,IAAA,CAAK,KAAA,EAAM;AAAA,MACb,CAAC,CAAA;AAAA,IACH,CAAA;AAEA,IAAA,IAAA,CAAiB,aAAA,GAAgB,CAAC,KAAA,KAAuB;AACvD,MAAA,IAAA,CAAK,YAAY,KAAK,CAAA;AAAA,IACxB,CAAA;AA/EE,IAAA,IAAA,CAAK,KAAA,GAAQ,QAAQ,KAAA,IAAS,KAAA;AAC9B,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,MAAA,IAAU,MAAA;AAChC,IAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,KAAY,CAAC,UAAiB,MAAA,CAAO,KAAA,CAAM,CAAA,YAAA,EAAe,KAAA,CAAM,OAAO;AAAA,CAAI,CAAA,CAAA;AAGnG,IAAA,IAAA,CAAK,WAAA,GAAc,CAAC,KAAA,KAAU;AAC5B,MAAA,IAAI;AACF,QAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,MACf,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA;AACA,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AAAA,EACzB;AAAA;AAAA,EAGA,WAAW,MAAA,EAA8B;AACvC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA;AAAA,EAGA,KAAA,GAAc;AACZ,IAAA,IAAI,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,MAAA,EAAQ;AACjC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,KAAA,CAAM,EAAA,CAAG,MAAA,EAAQ,IAAA,CAAK,MAAM,CAAA;AACjC,IAAA,IAAA,CAAK,KAAA,CAAM,EAAA,CAAG,KAAA,EAAO,IAAA,CAAK,KAAK,CAAA;AAC/B,IAAA,IAAA,CAAK,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,IAAA,CAAK,aAAa,CAAA;AACzC,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,GAAK,OAAA,EAAS,IAAA,CAAK,aAAa,CAAA;AAAA,EAC9C;AAAA;AAAA,EAGA,KAAK,OAAA,EAA+B;AAClC,IAAA,IAAI,KAAK,MAAA,EAAQ;AACjB,IAAA,IAAA,CAAK,OAAO,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC;AAAA,CAAI,CAAA;AAAA,EAClD;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAI,KAAK,MAAA,EAAQ;AACjB,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AACd,IAAA,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,MAAA,EAAQ,IAAA,CAAK,MAAM,CAAA;AAC7C,IAAA,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,KAAA,EAAO,IAAA,CAAK,KAAK,CAAA;AAC3C,IAAA,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,OAAA,EAAS,IAAA,CAAK,aAAa,CAAA;AACrD,IAAA,IAAA,CAAK,MAAA,CAAO,cAAA,GAAiB,OAAA,EAAS,IAAA,CAAK,aAAa,CAAA;AAGxD,IAAA,IAAA,CAAK,MAAM,KAAA,IAAQ;AACnB,IAAA,IAAA,CAAK,OAAA,IAAU;AAAA,EACjB;AAAA,EAkCQ,MAAM,GAAA,EAAmB;AAC/B,IAAA,MAAM,IAAA,GAAO,IAAI,QAAA,CAAS,IAAI,IAAI,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,GAAA;AACrD,IAAA,IAAI,IAAA,CAAK,IAAA,EAAK,KAAM,EAAA,EAAI;AAExB,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACF,MAAA,OAAA,GAAU,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,IAC3B,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,KAAA,CAAM,CAAA,iCAAA,EAAqC,KAAA,CAAgB,OAAO,CAAA,GAAA,EAAM,OAAA,CAAQ,IAAI,CAAC,CAAA,CAAE,CAAC,CAAA;AAC7G,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,OAAA,KAAY,IAAA,IAAQ,OAAO,OAAA,KAAY,QAAA,EAAU;AACnD,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,KAAA,CAAM,CAAA,wDAAA,EAA2D,QAAQ,IAAI,CAAC,EAAE,CAAC,CAAA;AACtG,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,EAAG;AAC1B,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,KAAA,CAAM,CAAA,sEAAA,EAAyE,QAAQ,IAAI,CAAC,EAAE,CAAC,CAAA;AACpH,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAChB,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,KAAA,CAAM,8DAA8D,CAAC,CAAA;AAC1F,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAyB,IAAA,CAAK,MAAA,CACjC,OAAA,CAAQ,IAAA,EAAM,OAAyB,CAAA,CACvC,KAAA,CAAM,CAAC,KAAA,KAAmB,IAAA,CAAK,WAAA,CAAY,KAAA,YAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAC,CAAC,CAAA,CACrG,OAAA,CAAQ,MAAM,IAAA,CAAK,QAAA,CAAS,MAAA,CAAO,OAAO,CAAC,CAAA;AAC9C,IAAA,IAAA,CAAK,QAAA,CAAS,IAAI,OAAO,CAAA;AAAA,EAC3B;AACF;AAEA,SAAS,QAAQ,IAAA,EAAsB;AACrC,EAAA,OAAO,IAAA,CAAK,SAAS,GAAA,GAAM,CAAA,EAAG,KAAK,KAAA,CAAM,CAAA,EAAG,GAAG,CAAC,CAAA,MAAA,CAAA,GAAM,IAAA;AACxD;AAMO,SAAS,WAAA,CAAY,MAAA,EAAwB,OAAA,GAAwB,EAAC,EAAmB;AAC9F,EAAA,MAAM,SAAA,GAAY,IAAI,cAAA,CAAe,OAAO,CAAA;AAC5C,EAAA,SAAA,CAAU,WAAW,MAAM,CAAA;AAC3B,EAAA,MAAA,CAAO,OAAO,SAAS,CAAA;AACvB,EAAA,SAAA,CAAU,KAAA,EAAM;AAChB,EAAA,OAAO,SAAA;AACT","file":"mcp-stdio.js","sourcesContent":["import { stderr, stdin, stdout } from \"node:process\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport type { MicroMcpServer, Transport } from \"./server\";\nimport type { JsonRpcMessage } from \"./types\";\n\n/**\n * StdioTransport — newline-delimited JSON-RPC over a byte stream pair.\n *\n * This is the framing every MCP client uses when it launches a server as a\n * subprocess (Claude Code, Codex, Cursor, Claude Desktop): one JSON-RPC message\n * per line on stdin, one per line on stdout. Anything else a server wants to say\n * goes to stderr, because a stray write to stdout corrupts the stream and the\n * client sees a parse error instead of a message.\n *\n * NODE ONLY, which is why it is its own subpath (`/mcp/stdio`) rather than part\n * of `/mcp`: browser bundles import `/mcp`, and `node:*` imports there would\n * break them.\n *\n * import { MicroMcpServer } from \"@particle-academy/agent-integrations/mcp\";\n * import { attachStdio } from \"@particle-academy/agent-integrations/mcp/stdio\";\n *\n * const server = new MicroMcpServer({ info: { name: \"my-server\", version: \"1.0.0\" } });\n * server.registerTool(...);\n * attachStdio(server);\n *\n * What it deliberately does:\n *\n * - **A bad line costs that line, not the session.** A line that is not JSON, or\n * is JSON but not a single JSON-RPC message (a number, `null`, a batch), is\n * reported through `onError` and skipped. No reply is written for it — there\n * is no request id to address one to, and stdout carries protocol frames only.\n * - **Input ending does not drop a reply that is still owed.** `printf\n * '<request>\\n' | server` closes stdin straight after the request; replies\n * already in flight are delivered, then the transport closes.\n * - **Bytes, not chunks, are decoded.** A chunk boundary can cut a multi-byte\n * character in half; decoding chunk by chunk would corrupt it.\n */\n\n/** The readable half. `process.stdin` and any Node `Readable` satisfy it. */\nexport interface StdioInput {\n on(event: \"data\", listener: (chunk: unknown) => void): unknown;\n on(event: \"end\", listener: () => void): unknown;\n on(event: \"error\", listener: (error: Error) => void): unknown;\n removeListener(event: string, listener: (...args: any[]) => void): unknown;\n pause?(): unknown;\n}\n\n/** The writable half. `process.stdout` and any Node `Writable` satisfy it. */\nexport interface StdioOutput {\n write(chunk: string): unknown;\n on?(event: \"error\", listener: (error: Error) => void): unknown;\n removeListener?(event: string, listener: (...args: any[]) => void): unknown;\n}\n\nexport type StdioOptions = {\n /** Defaults to `process.stdin`. */\n input?: StdioInput;\n /** Defaults to `process.stdout`. */\n output?: StdioOutput;\n /**\n * A line that could not be served, or a stream error. Defaults to one line on\n * `process.stderr` — the channel the MCP spec reserves for exactly this.\n */\n onError?: (error: Error) => void;\n /** Called once, when the transport closes (input ended, or `close()`). */\n onClose?: () => void;\n};\n\nexport class StdioTransport implements Transport {\n private server?: MicroMcpServer;\n private readonly input: StdioInput;\n private readonly output: StdioOutput;\n private readonly reportError: (error: Error) => void;\n private readonly onClose?: () => void;\n private readonly decoder = new StringDecoder(\"utf8\");\n private buffer = \"\";\n private closed = false;\n private started = false;\n private readonly inFlight = new Set<Promise<void>>();\n\n constructor(options: StdioOptions = {}) {\n this.input = options.input ?? stdin;\n this.output = options.output ?? stdout;\n const onError = options.onError ?? ((error: Error) => stderr.write(`[mcp stdio] ${error.message}\\n`));\n // A host's error handler that throws must not take the session down with\n // it: it runs inside a stream callback, where a throw is an uncaught error.\n this.reportError = (error) => {\n try {\n onError(error);\n } catch {\n /* nothing useful left to report it to */\n }\n };\n this.onClose = options.onClose;\n }\n\n /** Bind to a server. `attachStdio` does this for you. */\n bindServer(server: MicroMcpServer): void {\n this.server = server;\n }\n\n /** Begin reading input. `attachStdio` does this for you. */\n start(): void {\n if (this.started || this.closed) return;\n this.started = true;\n this.input.on(\"data\", this.onData);\n this.input.on(\"end\", this.onEnd);\n this.input.on(\"error\", this.onStreamError);\n this.output.on?.(\"error\", this.onStreamError);\n }\n\n /** Server → client: one message, one line. `JSON.stringify` escapes every newline inside it. */\n send(message: JsonRpcMessage): void {\n if (this.closed) return;\n this.output.write(`${JSON.stringify(message)}\\n`);\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n this.input.removeListener(\"data\", this.onData);\n this.input.removeListener(\"end\", this.onEnd);\n this.input.removeListener(\"error\", this.onStreamError);\n this.output.removeListener?.(\"error\", this.onStreamError);\n // Removing the data listener does not stop a flowing stream by itself, and\n // a flowing stdin keeps the process alive.\n this.input.pause?.();\n this.onClose?.();\n }\n\n private readonly onData = (chunk: unknown): void => {\n if (this.closed) return;\n this.buffer += typeof chunk === \"string\" ? chunk : this.decoder.write(chunk as Uint8Array);\n\n let newline = this.buffer.indexOf(\"\\n\");\n while (newline !== -1) {\n const line = this.buffer.slice(0, newline);\n this.buffer = this.buffer.slice(newline + 1);\n this.serve(line);\n newline = this.buffer.indexOf(\"\\n\");\n }\n };\n\n private readonly onEnd = (): void => {\n if (this.closed) return;\n this.buffer += this.decoder.end();\n const last = this.buffer;\n this.buffer = \"\";\n this.serve(last);\n\n // Deliver what is owed before closing, or a request followed immediately by\n // end-of-input never gets its reply.\n void Promise.allSettled([...this.inFlight]).then(() => {\n this.server?.detach(this);\n this.close();\n });\n };\n\n private readonly onStreamError = (error: Error): void => {\n this.reportError(error);\n };\n\n private serve(raw: string): void {\n const line = raw.endsWith(\"\\r\") ? raw.slice(0, -1) : raw;\n if (line.trim() === \"\") return;\n\n let message: unknown;\n try {\n message = JSON.parse(line);\n } catch (error) {\n this.reportError(new Error(`Ignored a line that is not JSON (${(error as Error).message}): ${preview(line)}`));\n return;\n }\n\n if (message === null || typeof message !== \"object\") {\n this.reportError(new Error(`Ignored a line that is JSON but not a JSON-RPC message: ${preview(line)}`));\n return;\n }\n if (Array.isArray(message)) {\n this.reportError(new Error(`Ignored a JSON-RPC batch; this transport serves one message per line: ${preview(line)}`));\n return;\n }\n if (!this.server) {\n this.reportError(new Error(\"StdioTransport has no bound server; use attachStdio(server).\"));\n return;\n }\n\n const pending: Promise<void> = this.server\n .receive(this, message as JsonRpcMessage)\n .catch((error: unknown) => this.reportError(error instanceof Error ? error : new Error(String(error))))\n .finally(() => this.inFlight.delete(pending));\n this.inFlight.add(pending);\n }\n}\n\nfunction preview(line: string): string {\n return line.length > 120 ? `${line.slice(0, 120)}…` : line;\n}\n\n/**\n * Serve `server` over stdio (or the streams you pass). Returns the transport;\n * `server.detach(transport)` or `transport.close()` stops it.\n */\nexport function attachStdio(server: MicroMcpServer, options: StdioOptions = {}): StdioTransport {\n const transport = new StdioTransport(options);\n transport.bindServer(server);\n server.attach(transport);\n transport.start();\n return transport;\n}\n"]}