@aria-cli/tools 1.0.12 → 1.0.14

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 (233) hide show
  1. package/dist/index.js +378 -70
  2. package/dist/network-runtime/index.js +8 -12
  3. package/dist-cjs/index.js +400 -435
  4. package/dist-cjs/network-runtime/index.js +8 -172
  5. package/package.json +8 -6
  6. package/dist/.tsbuildinfo +0 -1
  7. package/dist/ask-user-interaction.js +0 -22
  8. package/dist/cache/web-cache.js +0 -66
  9. package/dist/definitions/arion.js +0 -104
  10. package/dist/definitions/browser/browser.js +0 -418
  11. package/dist/definitions/browser/index.js +0 -4
  12. package/dist/definitions/browser/pw-downloads.js +0 -114
  13. package/dist/definitions/browser/pw-interactions.js +0 -199
  14. package/dist/definitions/browser/pw-responses.js +0 -76
  15. package/dist/definitions/browser/pw-session.js +0 -310
  16. package/dist/definitions/browser/pw-shared.js +0 -66
  17. package/dist/definitions/browser/pw-snapshot.js +0 -301
  18. package/dist/definitions/browser/pw-state.js +0 -62
  19. package/dist/definitions/browser/types.js +0 -4
  20. package/dist/definitions/code-intelligence.js +0 -470
  21. package/dist/definitions/core.js +0 -109
  22. package/dist/definitions/delegation.js +0 -512
  23. package/dist/definitions/deploy.js +0 -65
  24. package/dist/definitions/filesystem.js +0 -196
  25. package/dist/definitions/frg.js +0 -63
  26. package/dist/definitions/index.js +0 -20
  27. package/dist/definitions/memory.js +0 -123
  28. package/dist/definitions/messaging.js +0 -625
  29. package/dist/definitions/meta.js +0 -349
  30. package/dist/definitions/network.js +0 -159
  31. package/dist/definitions/outlook.js +0 -277
  32. package/dist/definitions/patch/apply-patch.js +0 -184
  33. package/dist/definitions/patch/fuzzy-match.js +0 -166
  34. package/dist/definitions/patch/index.js +0 -1
  35. package/dist/definitions/patch/patch-parser.js +0 -207
  36. package/dist/definitions/patch/sandbox-paths.js +0 -105
  37. package/dist/definitions/process/index.js +0 -4
  38. package/dist/definitions/process/process-registry.js +0 -213
  39. package/dist/definitions/process/process.js +0 -386
  40. package/dist/definitions/process/pty-keys.js +0 -254
  41. package/dist/definitions/process/session-slug.js +0 -142
  42. package/dist/definitions/quip.js +0 -195
  43. package/dist/definitions/search.js +0 -60
  44. package/dist/definitions/session-history.js +0 -69
  45. package/dist/definitions/shell.js +0 -181
  46. package/dist/definitions/slack.js +0 -180
  47. package/dist/definitions/web.js +0 -109
  48. package/dist/executors/apply-patch.js +0 -901
  49. package/dist/executors/arion.js +0 -119
  50. package/dist/executors/code-intelligence.js +0 -882
  51. package/dist/executors/deploy.js +0 -848
  52. package/dist/executors/filesystem.js +0 -1122
  53. package/dist/executors/frg-freshness.js +0 -576
  54. package/dist/executors/frg.js +0 -298
  55. package/dist/executors/index.js +0 -46
  56. package/dist/executors/learning-meta.js +0 -1146
  57. package/dist/executors/lsp-client.js +0 -296
  58. package/dist/executors/memory.js +0 -750
  59. package/dist/executors/meta.js +0 -220
  60. package/dist/executors/process-registry.js +0 -465
  61. package/dist/executors/pty-session-store.js +0 -30
  62. package/dist/executors/pty.js +0 -271
  63. package/dist/executors/restart.js +0 -119
  64. package/dist/executors/search-freshness.js +0 -195
  65. package/dist/executors/search-types.js +0 -52
  66. package/dist/executors/search.js +0 -66
  67. package/dist/executors/self-diagnose.js +0 -398
  68. package/dist/executors/session-history.js +0 -283
  69. package/dist/executors/shell-safety.js +0 -473
  70. package/dist/executors/shell.js +0 -954
  71. package/dist/executors/utils.js +0 -33
  72. package/dist/executors/web.js +0 -542
  73. package/dist/extraction/content-extraction.js +0 -235
  74. package/dist/extraction/index.js +0 -4
  75. package/dist/headless-control-contract.js +0 -967
  76. package/dist/local-control-http-auth.js +0 -2
  77. package/dist/mcp/client.js +0 -181
  78. package/dist/mcp/connection.js +0 -480
  79. package/dist/mcp/index.js +0 -10
  80. package/dist/mcp/jsonrpc.js +0 -144
  81. package/dist/mcp/types.js +0 -7
  82. package/dist/network-control-adapter.js +0 -72
  83. package/dist/network-runtime/address-types.js +0 -165
  84. package/dist/network-runtime/db-owner-fencing.js +0 -69
  85. package/dist/network-runtime/delivery-receipts.js +0 -267
  86. package/dist/network-runtime/direct-endpoint-authority.js +0 -25
  87. package/dist/network-runtime/local-control-contract.js +0 -627
  88. package/dist/network-runtime/node-store-contract.js +0 -34
  89. package/dist/network-runtime/pair-route-contract.js +0 -77
  90. package/dist/network-runtime/peer-capabilities.js +0 -28
  91. package/dist/network-runtime/peer-principal-ref.js +0 -12
  92. package/dist/network-runtime/peer-state-machine.js +0 -121
  93. package/dist/network-runtime/protocol-schemas.js +0 -205
  94. package/dist/network-runtime/runtime-bootstrap-contract.js +0 -60
  95. package/dist/outlook/desktop-session.js +0 -279
  96. package/dist/policy.js +0 -149
  97. package/dist/providers/brave.js +0 -62
  98. package/dist/providers/duckduckgo.js +0 -176
  99. package/dist/providers/exa.js +0 -63
  100. package/dist/providers/firecrawl.js +0 -55
  101. package/dist/providers/index.js +0 -7
  102. package/dist/providers/jina.js +0 -49
  103. package/dist/providers/router.js +0 -96
  104. package/dist/providers/search-provider.js +0 -32
  105. package/dist/providers/tavily.js +0 -54
  106. package/dist/quip/desktop-session.js +0 -317
  107. package/dist/registry/index.js +0 -1
  108. package/dist/registry/registry.js +0 -756
  109. package/dist/runtime-socket-local-control-client.js +0 -330
  110. package/dist/security/dns-normalization.js +0 -19
  111. package/dist/security/dns-pinning.js +0 -123
  112. package/dist/security/external-content.js +0 -91
  113. package/dist/security/ssrf.js +0 -181
  114. package/dist/slack/desktop-session.js +0 -324
  115. package/dist/tool-factory.js +0 -47
  116. package/dist/types.js +0 -7
  117. package/dist/utils/retry.js +0 -132
  118. package/dist/utils/safe-parse-json.js +0 -160
  119. package/dist/utils/url.js +0 -19
  120. package/dist-cjs/.tsbuildinfo +0 -1
  121. package/dist-cjs/ask-user-interaction.js +0 -27
  122. package/dist-cjs/cache/web-cache.js +0 -70
  123. package/dist-cjs/definitions/arion.js +0 -107
  124. package/dist-cjs/definitions/browser/browser.js +0 -421
  125. package/dist-cjs/definitions/browser/index.js +0 -8
  126. package/dist-cjs/definitions/browser/pw-downloads.js +0 -117
  127. package/dist-cjs/definitions/browser/pw-interactions.js +0 -213
  128. package/dist-cjs/definitions/browser/pw-responses.js +0 -84
  129. package/dist-cjs/definitions/browser/pw-session.js +0 -326
  130. package/dist-cjs/definitions/browser/pw-shared.js +0 -72
  131. package/dist-cjs/definitions/browser/pw-snapshot.js +0 -307
  132. package/dist-cjs/definitions/browser/pw-state.js +0 -70
  133. package/dist-cjs/definitions/browser/types.js +0 -5
  134. package/dist-cjs/definitions/code-intelligence.js +0 -473
  135. package/dist-cjs/definitions/core.js +0 -133
  136. package/dist-cjs/definitions/delegation.js +0 -515
  137. package/dist-cjs/definitions/deploy.js +0 -68
  138. package/dist-cjs/definitions/filesystem.js +0 -199
  139. package/dist-cjs/definitions/frg.js +0 -66
  140. package/dist-cjs/definitions/index.js +0 -43
  141. package/dist-cjs/definitions/memory.js +0 -126
  142. package/dist-cjs/definitions/messaging.js +0 -631
  143. package/dist-cjs/definitions/meta.js +0 -352
  144. package/dist-cjs/definitions/network.js +0 -162
  145. package/dist-cjs/definitions/outlook.js +0 -280
  146. package/dist-cjs/definitions/patch/apply-patch.js +0 -191
  147. package/dist-cjs/definitions/patch/fuzzy-match.js +0 -172
  148. package/dist-cjs/definitions/patch/index.js +0 -5
  149. package/dist-cjs/definitions/patch/patch-parser.js +0 -215
  150. package/dist-cjs/definitions/patch/sandbox-paths.js +0 -113
  151. package/dist-cjs/definitions/process/index.js +0 -8
  152. package/dist-cjs/definitions/process/process-registry.js +0 -231
  153. package/dist-cjs/definitions/process/process.js +0 -389
  154. package/dist-cjs/definitions/process/pty-keys.js +0 -259
  155. package/dist-cjs/definitions/process/session-slug.js +0 -145
  156. package/dist-cjs/definitions/quip.js +0 -198
  157. package/dist-cjs/definitions/search.js +0 -63
  158. package/dist-cjs/definitions/session-history.js +0 -72
  159. package/dist-cjs/definitions/shell.js +0 -184
  160. package/dist-cjs/definitions/slack.js +0 -183
  161. package/dist-cjs/definitions/web.js +0 -112
  162. package/dist-cjs/executors/apply-patch.js +0 -938
  163. package/dist-cjs/executors/arion.js +0 -125
  164. package/dist-cjs/executors/code-intelligence.js +0 -925
  165. package/dist-cjs/executors/deploy.js +0 -869
  166. package/dist-cjs/executors/filesystem.js +0 -1167
  167. package/dist-cjs/executors/frg-freshness.js +0 -627
  168. package/dist-cjs/executors/frg.js +0 -334
  169. package/dist-cjs/executors/index.js +0 -143
  170. package/dist-cjs/executors/learning-meta.js +0 -1165
  171. package/dist-cjs/executors/lsp-client.js +0 -310
  172. package/dist-cjs/executors/memory.js +0 -796
  173. package/dist-cjs/executors/meta.js +0 -226
  174. package/dist-cjs/executors/process-registry.js +0 -469
  175. package/dist-cjs/executors/pty-session-store.js +0 -34
  176. package/dist-cjs/executors/pty.js +0 -312
  177. package/dist-cjs/executors/restart.js +0 -155
  178. package/dist-cjs/executors/search-freshness.js +0 -234
  179. package/dist-cjs/executors/search-types.js +0 -56
  180. package/dist-cjs/executors/search.js +0 -102
  181. package/dist-cjs/executors/self-diagnose.js +0 -434
  182. package/dist-cjs/executors/session-history.js +0 -320
  183. package/dist-cjs/executors/shell-safety.js +0 -478
  184. package/dist-cjs/executors/shell.js +0 -1001
  185. package/dist-cjs/executors/utils.js +0 -73
  186. package/dist-cjs/executors/web.js +0 -547
  187. package/dist-cjs/extraction/content-extraction.js +0 -243
  188. package/dist-cjs/extraction/index.js +0 -8
  189. package/dist-cjs/headless-control-contract.js +0 -972
  190. package/dist-cjs/local-control-http-auth.js +0 -5
  191. package/dist-cjs/mcp/client.js +0 -185
  192. package/dist-cjs/mcp/connection.js +0 -484
  193. package/dist-cjs/mcp/index.js +0 -30
  194. package/dist-cjs/mcp/jsonrpc.js +0 -148
  195. package/dist-cjs/mcp/types.js +0 -8
  196. package/dist-cjs/network-control-adapter.js +0 -77
  197. package/dist-cjs/network-runtime/address-types.js +0 -168
  198. package/dist-cjs/network-runtime/db-owner-fencing.js +0 -76
  199. package/dist-cjs/network-runtime/delivery-receipts.js +0 -276
  200. package/dist-cjs/network-runtime/direct-endpoint-authority.js +0 -29
  201. package/dist-cjs/network-runtime/local-control-contract.js +0 -633
  202. package/dist-cjs/network-runtime/node-store-contract.js +0 -38
  203. package/dist-cjs/network-runtime/pair-route-contract.js +0 -80
  204. package/dist-cjs/network-runtime/peer-capabilities.js +0 -37
  205. package/dist-cjs/network-runtime/peer-principal-ref.js +0 -15
  206. package/dist-cjs/network-runtime/peer-state-machine.js +0 -129
  207. package/dist-cjs/network-runtime/protocol-schemas.js +0 -212
  208. package/dist-cjs/network-runtime/runtime-bootstrap-contract.js +0 -63
  209. package/dist-cjs/outlook/desktop-session.js +0 -318
  210. package/dist-cjs/policy.js +0 -155
  211. package/dist-cjs/providers/brave.js +0 -66
  212. package/dist-cjs/providers/duckduckgo.js +0 -180
  213. package/dist-cjs/providers/exa.js +0 -67
  214. package/dist-cjs/providers/firecrawl.js +0 -59
  215. package/dist-cjs/providers/index.js +0 -17
  216. package/dist-cjs/providers/jina.js +0 -53
  217. package/dist-cjs/providers/router.js +0 -100
  218. package/dist-cjs/providers/search-provider.js +0 -36
  219. package/dist-cjs/providers/tavily.js +0 -58
  220. package/dist-cjs/quip/desktop-session.js +0 -353
  221. package/dist-cjs/registry/index.js +0 -6
  222. package/dist-cjs/registry/registry.js +0 -761
  223. package/dist-cjs/runtime-socket-local-control-client.js +0 -367
  224. package/dist-cjs/security/dns-normalization.js +0 -22
  225. package/dist-cjs/security/dns-pinning.js +0 -160
  226. package/dist-cjs/security/external-content.js +0 -95
  227. package/dist-cjs/security/ssrf.js +0 -221
  228. package/dist-cjs/slack/desktop-session.js +0 -366
  229. package/dist-cjs/tool-factory.js +0 -50
  230. package/dist-cjs/types.js +0 -8
  231. package/dist-cjs/utils/retry.js +0 -169
  232. package/dist-cjs/utils/safe-parse-json.js +0 -164
  233. package/dist-cjs/utils/url.js +0 -23
@@ -1,2 +0,0 @@
1
- export const LOCAL_HTTP_CLIENT_ID_HEADER = "x-aria-local-client-id";
2
- export const LOCAL_HTTP_CLIENT_PROOF_HEADER = "x-aria-local-client-proof";
@@ -1,181 +0,0 @@
1
- /**
2
- * MCP Multi-Server Client
3
- *
4
- * Manages connections to multiple MCP servers and aggregates their capabilities.
5
- */
6
- import { EventEmitter } from "events";
7
- import { MCPServerConnection } from "./connection.js";
8
- export class MCPClient extends EventEmitter {
9
- servers = new Map();
10
- serverConfigs = new Map();
11
- reconnectTimers = new Map();
12
- logger;
13
- constructor(options) {
14
- super();
15
- this.logger = options?.logger ?? console;
16
- }
17
- /**
18
- * Connect to an MCP server
19
- */
20
- async connect(config) {
21
- if (this.servers.has(config.name)) {
22
- throw new Error(`Server already connected: ${config.name}`);
23
- }
24
- const connection = new MCPServerConnection(config);
25
- await connection.initialize();
26
- // Forward events
27
- connection.on("tools/list_changed", () => this.emit("toolsChanged", config.name));
28
- connection.on("resources/list_changed", () => this.emit("resourcesChanged", config.name));
29
- connection.on("prompts/list_changed", () => this.emit("promptsChanged", config.name));
30
- connection.on("exit", (code) => {
31
- this.servers.delete(config.name);
32
- this.emit("serverExit", config.name, code);
33
- // Attempt auto-reconnect on unexpected exit
34
- if (code !== 0 && this.serverConfigs.has(config.name)) {
35
- this.reconnect(config.name, config).catch((err) => {
36
- this.logger.warn("[MCPClient] Reconnect failed:", err?.message);
37
- });
38
- }
39
- });
40
- this.servers.set(config.name, connection);
41
- this.serverConfigs.set(config.name, config);
42
- return connection;
43
- }
44
- /**
45
- * Disconnect from a specific server
46
- */
47
- async disconnect(name) {
48
- this.serverConfigs.delete(name);
49
- // Cancel any pending reconnect timer for this server
50
- const timer = this.reconnectTimers.get(name);
51
- if (timer !== undefined) {
52
- clearTimeout(timer);
53
- this.reconnectTimers.delete(name);
54
- }
55
- const conn = this.servers.get(name);
56
- if (conn) {
57
- this.servers.delete(name);
58
- conn.removeAllListeners();
59
- await conn.shutdown();
60
- }
61
- }
62
- /**
63
- * Attempt to reconnect to a server with exponential backoff
64
- */
65
- async reconnect(serverName, config, attempt = 0) {
66
- const maxAttempts = 3;
67
- const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
68
- if (attempt >= maxAttempts)
69
- return;
70
- await new Promise((resolve) => {
71
- const timer = setTimeout(resolve, delay);
72
- this.reconnectTimers.set(serverName, timer);
73
- });
74
- this.reconnectTimers.delete(serverName);
75
- // Bail out if server was disconnected while we were waiting
76
- if (!this.serverConfigs.has(serverName))
77
- return;
78
- // Guard against double-reconnect race: if another reconnect already
79
- // re-established the connection, skip this attempt.
80
- if (this.servers.has(serverName))
81
- return;
82
- try {
83
- await this.connect(config);
84
- }
85
- catch {
86
- await this.reconnect(serverName, config, attempt + 1);
87
- }
88
- }
89
- /**
90
- * Disconnect from all servers
91
- */
92
- async disconnectAll() {
93
- // Collect names from both active connections and pending reconnects
94
- const names = new Set([...this.servers.keys(), ...this.reconnectTimers.keys()]);
95
- await Promise.all([...names].map((name) => this.disconnect(name)));
96
- }
97
- /**
98
- * Get connected server names
99
- */
100
- getConnectedServers() {
101
- return [...this.servers.keys()];
102
- }
103
- // ========== Tools ==========
104
- /**
105
- * List all tools from all connected servers
106
- */
107
- async listAllTools() {
108
- const results = await Promise.all([...this.servers.entries()].map(async ([name, conn]) => {
109
- try {
110
- const tools = await conn.listTools();
111
- return tools.map((t) => ({ ...t, server: name }));
112
- }
113
- catch {
114
- return [];
115
- }
116
- }));
117
- return results.flat();
118
- }
119
- /**
120
- * Call a tool on a specific server
121
- */
122
- async callTool(server, tool, args, abortSignal) {
123
- const conn = this.servers.get(server);
124
- if (!conn) {
125
- return { success: false, message: `Server not connected: ${server}` };
126
- }
127
- return conn.callTool(tool, args, abortSignal);
128
- }
129
- // ========== Resources ==========
130
- /**
131
- * List all resources from all connected servers
132
- */
133
- async listAllResources() {
134
- const results = await Promise.all([...this.servers.entries()].map(async ([name, conn]) => {
135
- try {
136
- const resources = await conn.listResources();
137
- return resources.map((r) => ({ ...r, server: name }));
138
- }
139
- catch {
140
- return [];
141
- }
142
- }));
143
- return results.flat();
144
- }
145
- /**
146
- * Read a resource from a specific server
147
- */
148
- async readResource(server, uri) {
149
- const conn = this.servers.get(server);
150
- if (!conn) {
151
- throw new Error(`Server not connected: ${server}`);
152
- }
153
- return conn.readResource(uri);
154
- }
155
- // ========== Prompts ==========
156
- /**
157
- * List all prompts from all connected servers
158
- */
159
- async listAllPrompts() {
160
- const results = await Promise.all([...this.servers.entries()].map(async ([name, conn]) => {
161
- try {
162
- const prompts = await conn.listPrompts();
163
- return prompts.map((p) => ({ ...p, server: name }));
164
- }
165
- catch {
166
- return [];
167
- }
168
- }));
169
- return results.flat();
170
- }
171
- /**
172
- * Get a prompt from a specific server
173
- */
174
- async getPrompt(server, name, args) {
175
- const conn = this.servers.get(server);
176
- if (!conn) {
177
- throw new Error(`Server not connected: ${server}`);
178
- }
179
- return conn.getPrompt(name, args);
180
- }
181
- }
@@ -1,480 +0,0 @@
1
- /**
2
- * MCP Server Connection
3
- *
4
- * Manages lifecycle and protocol methods for a single MCP server.
5
- */
6
- import { spawn } from "child_process";
7
- import { EventEmitter } from "events";
8
- import { PassThrough, Writable } from "stream";
9
- import { JSONRPCClient } from "./jsonrpc.js";
10
- function sanitizeGitEnv(env = process.env) {
11
- const sanitized = {};
12
- for (const [key, value] of Object.entries(env)) {
13
- if (value === undefined)
14
- continue;
15
- if (key.toUpperCase().startsWith("GIT_"))
16
- continue;
17
- sanitized[key] = value;
18
- }
19
- return sanitized;
20
- }
21
- export class MCPServerConnection extends EventEmitter {
22
- config;
23
- process;
24
- transport = "stdio";
25
- rpc;
26
- capabilities = {};
27
- _initialized = false;
28
- sseAbortController;
29
- sseStreamPromise;
30
- ssePostUrl;
31
- sseSessionId;
32
- sseOutput;
33
- // Auto-reconnect state
34
- _disconnecting = false;
35
- _reconnecting = false;
36
- _reconnectAttempts = 0;
37
- static RECONNECT_BASE_DELAY_MS = 1000;
38
- static RECONNECT_MAX_DELAY_MS = 30000;
39
- static RECONNECT_MAX_ATTEMPTS = 5;
40
- constructor(config) {
41
- super();
42
- this.config = config;
43
- this.rpc = new JSONRPCClient();
44
- }
45
- get name() {
46
- return this.config.name;
47
- }
48
- get initialized() {
49
- return this._initialized;
50
- }
51
- /**
52
- * Initialize connection to MCP server
53
- */
54
- async initialize() {
55
- // Reset disconnecting flag on fresh initialization so auto-reconnect is active.
56
- // During reconnect, attemptReconnect() checks _disconnecting before each attempt.
57
- if (!this._reconnecting) {
58
- this._disconnecting = false;
59
- this._reconnectAttempts = 0;
60
- }
61
- this.transport = this.config.transport ?? "stdio";
62
- try {
63
- if (this.transport === "stdio") {
64
- await this.initializeStdioTransport();
65
- }
66
- else {
67
- await this.initializeSSETransport();
68
- }
69
- // Forward notifications
70
- this.rpc.on("notifications/tools/list_changed", () => this.emit("tools/list_changed"));
71
- this.rpc.on("notifications/resources/list_changed", () => this.emit("resources/list_changed"));
72
- this.rpc.on("notifications/prompts/list_changed", () => this.emit("prompts/list_changed"));
73
- // MCP initialize handshake
74
- const result = await this.rpc.request("initialize", {
75
- protocolVersion: "2024-11-05",
76
- capabilities: {
77
- roots: { listChanged: true },
78
- },
79
- clientInfo: {
80
- name: "aria-cli",
81
- version: "1.0.0",
82
- },
83
- });
84
- this.capabilities = result.capabilities || {};
85
- this._initialized = true;
86
- // Send initialized notification
87
- this.rpc.notify("notifications/initialized", {});
88
- return this.capabilities;
89
- }
90
- catch (error) {
91
- await this.cleanupAfterInitializeFailure();
92
- throw error;
93
- }
94
- }
95
- /**
96
- * Attempt to reconnect with exponential backoff.
97
- * Called when the transport drops unexpectedly (not via explicit shutdown).
98
- */
99
- async attemptReconnect() {
100
- if (this._disconnecting || this._reconnecting) {
101
- return;
102
- }
103
- this._reconnecting = true;
104
- while (this._reconnectAttempts < MCPServerConnection.RECONNECT_MAX_ATTEMPTS &&
105
- !this._disconnecting) {
106
- this._reconnectAttempts++;
107
- const delay = Math.min(MCPServerConnection.RECONNECT_BASE_DELAY_MS * Math.pow(2, this._reconnectAttempts - 1), MCPServerConnection.RECONNECT_MAX_DELAY_MS);
108
- this.emit("log", {
109
- level: "info",
110
- message: `Reconnect attempt ${this._reconnectAttempts}/${MCPServerConnection.RECONNECT_MAX_ATTEMPTS} in ${delay}ms`,
111
- });
112
- await new Promise((resolve) => setTimeout(resolve, delay));
113
- if (this._disconnecting) {
114
- break;
115
- }
116
- try {
117
- // Clean up stale RPC state before reconnecting
118
- this.rpc.close();
119
- this.rpc = new JSONRPCClient();
120
- await this.initialize();
121
- // Success — reset reconnect state
122
- this._reconnectAttempts = 0;
123
- this._reconnecting = false;
124
- this.emit("reconnected");
125
- return;
126
- }
127
- catch (error) {
128
- this.emit("log", {
129
- level: "error",
130
- message: `Reconnect attempt ${this._reconnectAttempts} failed: ${error.message}`,
131
- });
132
- }
133
- }
134
- // All attempts exhausted or disconnecting flag was set
135
- this._reconnecting = false;
136
- if (!this._disconnecting) {
137
- this._initialized = false;
138
- this.emit("error", new Error(`Failed to reconnect after ${MCPServerConnection.RECONNECT_MAX_ATTEMPTS} attempts`));
139
- }
140
- }
141
- async initializeStdioTransport() {
142
- if (!this.config.command) {
143
- throw new Error("Command required for stdio transport");
144
- }
145
- // Spawn server process
146
- this.process = spawn(this.config.command, this.config.args || [], {
147
- env: { ...sanitizeGitEnv(), ...sanitizeGitEnv(this.config.env ?? {}) },
148
- stdio: ["pipe", "pipe", "pipe"],
149
- });
150
- if (!this.process.stdin || !this.process.stdout) {
151
- throw new Error("Failed to create stdio streams");
152
- }
153
- this.rpc.connect(this.process.stdin, this.process.stdout);
154
- // Handle stderr for logging
155
- this.process.stderr?.on("data", (data) => {
156
- this.emit("log", { level: "error", message: data.toString() });
157
- });
158
- this.process.on("exit", (code) => {
159
- this._initialized = false;
160
- this.rpc.close();
161
- this.emit("exit", code);
162
- // Attempt auto-reconnect on unexpected exit
163
- if (!this._disconnecting) {
164
- void this.attemptReconnect();
165
- }
166
- });
167
- }
168
- async initializeSSETransport() {
169
- const url = this.config.url;
170
- if (!url) {
171
- throw new Error("URL required for sse transport");
172
- }
173
- const stdin = new Writable({
174
- write: (chunk, _encoding, callback) => {
175
- const payload = chunk.toString();
176
- this.postSSEMessages(payload)
177
- .then(() => callback())
178
- .catch((err) => callback(err));
179
- },
180
- });
181
- const stdout = new PassThrough();
182
- this.sseOutput = stdout;
183
- this.rpc.connect(stdin, stdout);
184
- this.sseAbortController = new AbortController();
185
- const response = await fetch(url, {
186
- method: "GET",
187
- headers: { Accept: "text/event-stream" },
188
- signal: this.sseAbortController.signal,
189
- });
190
- if (!response.ok || !response.body) {
191
- const errorText = await response.text();
192
- throw new Error(`Failed to connect SSE transport: ${response.status} ${response.statusText} ${errorText}`);
193
- }
194
- this.sseSessionId = response.headers.get("mcp-session-id") ?? undefined;
195
- this.ssePostUrl = url;
196
- this.sseStreamPromise = this.consumeSSE(response.body, url);
197
- }
198
- async postSSEMessages(payload) {
199
- const trimmed = payload.trim();
200
- if (!trimmed) {
201
- return;
202
- }
203
- const endpoint = this.ssePostUrl || this.config.url;
204
- if (!endpoint) {
205
- throw new Error("SSE transport endpoint is not configured");
206
- }
207
- const messages = trimmed
208
- .split("\n")
209
- .map((line) => line.trim())
210
- .filter((line) => line.length > 0);
211
- for (const message of messages) {
212
- const response = await fetch(endpoint, {
213
- method: "POST",
214
- headers: {
215
- "Content-Type": "application/json",
216
- ...(this.sseSessionId ? { "mcp-session-id": this.sseSessionId } : {}),
217
- },
218
- body: message,
219
- });
220
- if (!response.ok) {
221
- const errorText = await response.text();
222
- throw new Error(`SSE transport POST failed: ${response.status} ${response.statusText} ${errorText}`);
223
- }
224
- const responseText = (await response.text()).trim();
225
- if (!responseText || !this.sseOutput) {
226
- continue;
227
- }
228
- // Some servers return direct JSON-RPC responses on POST while others
229
- // publish responses only via SSE. Forward direct JSON replies into RPC.
230
- for (const line of responseText.split("\n")) {
231
- const jsonLine = line.trim();
232
- if (!jsonLine) {
233
- continue;
234
- }
235
- if (jsonLine.startsWith("{") && jsonLine.endsWith("}")) {
236
- this.sseOutput.write(`${jsonLine}\n`);
237
- }
238
- }
239
- }
240
- }
241
- async consumeSSE(body, baseUrl) {
242
- const reader = body.getReader();
243
- const decoder = new TextDecoder();
244
- let buffer = "";
245
- let eventType = "";
246
- let dataLines = [];
247
- const dispatch = () => {
248
- if (dataLines.length === 0) {
249
- eventType = "";
250
- return;
251
- }
252
- const data = dataLines.join("\n").trim();
253
- const event = eventType || "message";
254
- eventType = "";
255
- dataLines = [];
256
- if (!data) {
257
- return;
258
- }
259
- if (event === "endpoint") {
260
- this.ssePostUrl = new URL(data, baseUrl).toString();
261
- return;
262
- }
263
- if (!this.sseOutput) {
264
- return;
265
- }
266
- if (data.startsWith("{") && data.endsWith("}")) {
267
- this.sseOutput.write(`${data}\n`);
268
- }
269
- };
270
- try {
271
- while (true) {
272
- const { done, value } = await reader.read();
273
- if (done) {
274
- dispatch();
275
- break;
276
- }
277
- buffer += decoder.decode(value, { stream: true });
278
- const lines = buffer.split(/\r?\n/);
279
- buffer = lines.pop() || "";
280
- for (const line of lines) {
281
- if (line === "") {
282
- dispatch();
283
- continue;
284
- }
285
- if (line.startsWith("event:")) {
286
- eventType = line.slice(6).trim();
287
- continue;
288
- }
289
- if (line.startsWith("data:")) {
290
- dataLines.push(line.slice(5).trim());
291
- }
292
- }
293
- }
294
- }
295
- catch (error) {
296
- // Ignore abort errors from normal shutdown.
297
- if (!(error instanceof DOMException && error.name === "AbortError")) {
298
- this.emit("log", {
299
- level: "error",
300
- message: `SSE stream error: ${error.message}`,
301
- });
302
- }
303
- }
304
- finally {
305
- if (this._initialized) {
306
- this._initialized = false;
307
- this.rpc.close();
308
- this.emit("exit", 0);
309
- // Attempt auto-reconnect on unexpected SSE stream end
310
- if (!this._disconnecting) {
311
- void this.attemptReconnect();
312
- }
313
- }
314
- }
315
- }
316
- async cleanupAfterInitializeFailure() {
317
- if (this.transport === "stdio") {
318
- if (this.process && !this.process.killed) {
319
- try {
320
- this.process.kill("SIGTERM");
321
- }
322
- catch {
323
- // Ignore kill failures during cleanup.
324
- }
325
- }
326
- this.process = undefined;
327
- }
328
- else {
329
- this.sseAbortController?.abort();
330
- try {
331
- await this.sseStreamPromise;
332
- }
333
- catch {
334
- // Ignore stream errors during cleanup.
335
- }
336
- this.sseOutput?.end();
337
- this.sseOutput = undefined;
338
- }
339
- this.rpc.close();
340
- }
341
- /**
342
- * Gracefully shutdown the connection
343
- */
344
- async shutdown() {
345
- this._disconnecting = true;
346
- if (!this._initialized)
347
- return;
348
- this._initialized = false;
349
- if (this.transport === "sse") {
350
- try {
351
- await this.rpc.request("shutdown", {});
352
- this.rpc.notify("notifications/exit", {});
353
- }
354
- catch {
355
- // Best effort
356
- }
357
- this.sseAbortController?.abort();
358
- try {
359
- await this.sseStreamPromise;
360
- }
361
- catch {
362
- // Ignore stream shutdown errors
363
- }
364
- this.sseOutput?.end();
365
- this.sseOutput = undefined;
366
- this.rpc.close();
367
- return;
368
- }
369
- if (this.process) {
370
- // Send MCP shutdown/exit protocol before killing
371
- try {
372
- await this.rpc.request("shutdown", {});
373
- this.rpc.notify("notifications/exit", {});
374
- // Give process a moment to clean up
375
- await new Promise((resolve) => setTimeout(resolve, 500));
376
- }
377
- catch {
378
- // Process may already be dead, proceed with kill
379
- }
380
- this.process.kill("SIGTERM");
381
- // Await process exit before resolving
382
- await new Promise((resolve) => {
383
- // Escalate to SIGKILL if process doesn't exit within 5s
384
- const killTimeout = setTimeout(() => {
385
- try {
386
- this.process?.kill("SIGKILL");
387
- }
388
- catch {
389
- /* already dead */
390
- }
391
- }, 5000);
392
- this.process.once("exit", () => {
393
- clearTimeout(killTimeout);
394
- this.rpc.close();
395
- resolve();
396
- });
397
- });
398
- }
399
- else {
400
- this.rpc.close();
401
- }
402
- }
403
- // ========== Tools ==========
404
- async listTools() {
405
- const result = await this.rpc.request("tools/list", {});
406
- return result.tools || [];
407
- }
408
- async callTool(name, args, abortSignal) {
409
- // Early abort check before making the RPC call
410
- if (abortSignal?.aborted) {
411
- return { success: false, message: "Tool execution cancelled by user." };
412
- }
413
- try {
414
- // Race the RPC call against the abort signal so user cancel
415
- // doesn't block waiting for a slow MCP server response.
416
- const rpcPromise = this.rpc.request("tools/call", {
417
- name,
418
- arguments: args,
419
- });
420
- let result;
421
- if (abortSignal) {
422
- result = await new Promise((resolve, reject) => {
423
- const onAbort = () => reject(new DOMException("Aborted", "AbortError"));
424
- abortSignal.addEventListener("abort", onAbort, { once: true });
425
- rpcPromise.then((r) => {
426
- abortSignal.removeEventListener("abort", onAbort);
427
- resolve(r);
428
- }, (e) => {
429
- abortSignal.removeEventListener("abort", onAbort);
430
- reject(e);
431
- });
432
- });
433
- }
434
- else {
435
- result = await rpcPromise;
436
- }
437
- const text = result.content
438
- ?.filter((c) => c.type === "text")
439
- .map((c) => c.text)
440
- .join("\n") || "";
441
- return {
442
- success: !result.isError,
443
- message: text,
444
- data: result.content,
445
- };
446
- }
447
- catch (error) {
448
- if (error instanceof DOMException && error.name === "AbortError") {
449
- return { success: false, message: "Tool execution cancelled by user." };
450
- }
451
- return {
452
- success: false,
453
- message: error.message,
454
- };
455
- }
456
- }
457
- // ========== Resources ==========
458
- async listResources() {
459
- const result = await this.rpc.request("resources/list", {});
460
- return result.resources || [];
461
- }
462
- async readResource(uri) {
463
- const result = await this.rpc.request("resources/read", {
464
- uri,
465
- });
466
- return result.contents || [];
467
- }
468
- // ========== Prompts ==========
469
- async listPrompts() {
470
- const result = await this.rpc.request("prompts/list", {});
471
- return result.prompts || [];
472
- }
473
- async getPrompt(name, args) {
474
- const result = await this.rpc.request("prompts/get", {
475
- name,
476
- arguments: args,
477
- });
478
- return result.messages || [];
479
- }
480
- }
package/dist/mcp/index.js DELETED
@@ -1,10 +0,0 @@
1
- /**
2
- * MCP (Model Context Protocol) Module
3
- *
4
- * Provides client implementation for connecting to MCP servers
5
- * and discovering tools, resources, and prompts dynamically.
6
- */
7
- export * from './types.js';
8
- export { JSONRPCClient } from './jsonrpc.js';
9
- export { MCPServerConnection } from './connection.js';
10
- export { MCPClient } from './client.js';