kernl 0.1.1

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 (257) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/CHANGELOG.md +53 -0
  3. package/LICENSE +201 -0
  4. package/dist/agent.d.ts +43 -0
  5. package/dist/agent.d.ts.map +1 -0
  6. package/dist/agent.js +130 -0
  7. package/dist/context.d.ts +70 -0
  8. package/dist/context.d.ts.map +1 -0
  9. package/dist/context.js +111 -0
  10. package/dist/env.d.ts +45 -0
  11. package/dist/env.d.ts.map +1 -0
  12. package/dist/env.js +31 -0
  13. package/dist/error.d.ts +1 -0
  14. package/dist/error.d.ts.map +1 -0
  15. package/dist/error.js +1 -0
  16. package/dist/guardrail.d.ts +178 -0
  17. package/dist/guardrail.d.ts.map +1 -0
  18. package/dist/guardrail.js +34 -0
  19. package/dist/index.d.ts +4 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +2 -0
  22. package/dist/kernel.d.ts +7 -0
  23. package/dist/kernel.d.ts.map +1 -0
  24. package/dist/kernel.js +7 -0
  25. package/dist/kernl.d.ts +18 -0
  26. package/dist/kernl.d.ts.map +1 -0
  27. package/dist/kernl.js +16 -0
  28. package/dist/lib/env.d.ts +43 -0
  29. package/dist/lib/env.d.ts.map +1 -0
  30. package/dist/lib/env.js +29 -0
  31. package/dist/lib/error.d.ts +88 -0
  32. package/dist/lib/error.d.ts.map +1 -0
  33. package/dist/lib/error.js +117 -0
  34. package/dist/lib/logger.d.ts +36 -0
  35. package/dist/lib/logger.d.ts.map +1 -0
  36. package/dist/lib/logger.js +43 -0
  37. package/dist/lib/serde/__tests__/codec.test.d.ts +2 -0
  38. package/dist/lib/serde/__tests__/codec.test.d.ts.map +1 -0
  39. package/dist/lib/serde/__tests__/codec.test.js +75 -0
  40. package/dist/lib/serde/codec.d.ts +12 -0
  41. package/dist/lib/serde/codec.d.ts.map +1 -0
  42. package/dist/lib/serde/codec.js +54 -0
  43. package/dist/lib/serde/json.d.ts +8 -0
  44. package/dist/lib/serde/json.d.ts.map +1 -0
  45. package/dist/lib/serde/json.js +13 -0
  46. package/dist/lib/serde/thread.d.ts +1 -0
  47. package/dist/lib/serde/thread.d.ts.map +1 -0
  48. package/dist/lib/serde/thread.js +172 -0
  49. package/dist/lib/serde/tool.d.ts +36 -0
  50. package/dist/lib/serde/tool.d.ts.map +1 -0
  51. package/dist/lib/serde/tool.js +1 -0
  52. package/dist/lib/utils.d.ts +19 -0
  53. package/dist/lib/utils.d.ts.map +1 -0
  54. package/dist/lib/utils.js +41 -0
  55. package/dist/lifecycle.d.ts +133 -0
  56. package/dist/lifecycle.d.ts.map +1 -0
  57. package/dist/lifecycle.js +29 -0
  58. package/dist/logger.d.ts +36 -0
  59. package/dist/logger.d.ts.map +1 -0
  60. package/dist/logger.js +43 -0
  61. package/dist/mcp/__tests__/base.test.d.ts +2 -0
  62. package/dist/mcp/__tests__/base.test.d.ts.map +1 -0
  63. package/dist/mcp/__tests__/base.test.js +268 -0
  64. package/dist/mcp/__tests__/fixtures/echo-server.d.ts +3 -0
  65. package/dist/mcp/__tests__/fixtures/echo-server.d.ts.map +1 -0
  66. package/dist/mcp/__tests__/fixtures/echo-server.js +92 -0
  67. package/dist/mcp/__tests__/fixtures/math-server.d.ts +3 -0
  68. package/dist/mcp/__tests__/fixtures/math-server.d.ts.map +1 -0
  69. package/dist/mcp/__tests__/fixtures/math-server.js +98 -0
  70. package/dist/mcp/__tests__/fixtures/server.d.ts +3 -0
  71. package/dist/mcp/__tests__/fixtures/server.d.ts.map +1 -0
  72. package/dist/mcp/__tests__/fixtures/server.js +162 -0
  73. package/dist/mcp/__tests__/fixtures/test-server.d.ts +3 -0
  74. package/dist/mcp/__tests__/fixtures/test-server.d.ts.map +1 -0
  75. package/dist/mcp/__tests__/fixtures/test-server.js +163 -0
  76. package/dist/mcp/__tests__/fixtures/utils.d.ts +17 -0
  77. package/dist/mcp/__tests__/fixtures/utils.d.ts.map +1 -0
  78. package/dist/mcp/__tests__/fixtures/utils.js +42 -0
  79. package/dist/mcp/__tests__/integration.test.d.ts +2 -0
  80. package/dist/mcp/__tests__/integration.test.d.ts.map +1 -0
  81. package/dist/mcp/__tests__/integration.test.js +360 -0
  82. package/dist/mcp/__tests__/stdio.test.d.ts +2 -0
  83. package/dist/mcp/__tests__/stdio.test.d.ts.map +1 -0
  84. package/dist/mcp/__tests__/stdio.test.js +180 -0
  85. package/dist/mcp/__tests__/test-utils.d.ts +17 -0
  86. package/dist/mcp/__tests__/test-utils.d.ts.map +1 -0
  87. package/dist/mcp/__tests__/test-utils.js +42 -0
  88. package/dist/mcp/__tests__/utils.test.d.ts +2 -0
  89. package/dist/mcp/__tests__/utils.test.d.ts.map +1 -0
  90. package/dist/mcp/__tests__/utils.test.js +300 -0
  91. package/dist/mcp/base.d.ts +88 -0
  92. package/dist/mcp/base.d.ts.map +1 -0
  93. package/dist/mcp/base.js +68 -0
  94. package/dist/mcp/http.d.ts +34 -0
  95. package/dist/mcp/http.d.ts.map +1 -0
  96. package/dist/mcp/http.js +100 -0
  97. package/dist/mcp/node.d.ts +60 -0
  98. package/dist/mcp/node.d.ts.map +1 -0
  99. package/dist/mcp/node.js +297 -0
  100. package/dist/mcp/sse.d.ts +34 -0
  101. package/dist/mcp/sse.d.ts.map +1 -0
  102. package/dist/mcp/sse.js +97 -0
  103. package/dist/mcp/stdio.d.ts +32 -0
  104. package/dist/mcp/stdio.d.ts.map +1 -0
  105. package/dist/mcp/stdio.js +96 -0
  106. package/dist/mcp/types.d.ts +172 -0
  107. package/dist/mcp/types.d.ts.map +1 -0
  108. package/dist/mcp/types.js +16 -0
  109. package/dist/mcp/utils.d.ts +23 -0
  110. package/dist/mcp/utils.d.ts.map +1 -0
  111. package/dist/mcp/utils.js +44 -0
  112. package/dist/model.d.ts +175 -0
  113. package/dist/model.d.ts.map +1 -0
  114. package/dist/model.js +1 -0
  115. package/dist/providers/ai.d.ts +1 -0
  116. package/dist/providers/ai.d.ts.map +1 -0
  117. package/dist/providers/ai.js +1 -0
  118. package/dist/providers/default.d.ts +16 -0
  119. package/dist/providers/default.d.ts.map +1 -0
  120. package/dist/providers/default.js +17 -0
  121. package/dist/providers/registry.d.ts +1 -0
  122. package/dist/providers/registry.d.ts.map +1 -0
  123. package/dist/providers/registry.js +1 -0
  124. package/dist/sched/scheduler.d.ts +20 -0
  125. package/dist/sched/scheduler.d.ts.map +1 -0
  126. package/dist/sched/scheduler.js +1 -0
  127. package/dist/sched/task.d.ts +92 -0
  128. package/dist/sched/task.d.ts.map +1 -0
  129. package/dist/sched/task.js +102 -0
  130. package/dist/serde/__tests__/codec.test.d.ts +2 -0
  131. package/dist/serde/__tests__/codec.test.d.ts.map +1 -0
  132. package/dist/serde/__tests__/codec.test.js +75 -0
  133. package/dist/serde/codec.d.ts +12 -0
  134. package/dist/serde/codec.d.ts.map +1 -0
  135. package/dist/serde/codec.js +54 -0
  136. package/dist/serde/json.d.ts +8 -0
  137. package/dist/serde/json.d.ts.map +1 -0
  138. package/dist/serde/json.js +13 -0
  139. package/dist/serde/thread.d.ts +687 -0
  140. package/dist/serde/thread.d.ts.map +1 -0
  141. package/dist/serde/thread.js +158 -0
  142. package/dist/serde/tool.d.ts +36 -0
  143. package/dist/serde/tool.d.ts.map +1 -0
  144. package/dist/serde/tool.js +1 -0
  145. package/dist/session.d.ts +1 -0
  146. package/dist/session.d.ts.map +1 -0
  147. package/dist/session.js +1 -0
  148. package/dist/task.d.ts +87 -0
  149. package/dist/task.d.ts.map +1 -0
  150. package/dist/task.js +97 -0
  151. package/dist/thread/__tests__/mock.d.ts +28 -0
  152. package/dist/thread/__tests__/mock.d.ts.map +1 -0
  153. package/dist/thread/__tests__/mock.js +74 -0
  154. package/dist/thread/__tests__/thread.test.d.ts +2 -0
  155. package/dist/thread/__tests__/thread.test.d.ts.map +1 -0
  156. package/dist/thread/__tests__/thread.test.js +1412 -0
  157. package/dist/thread/index.d.ts +2 -0
  158. package/dist/thread/index.d.ts.map +1 -0
  159. package/dist/thread/index.js +1 -0
  160. package/dist/thread/thread.d.ts +66 -0
  161. package/dist/thread/thread.d.ts.map +1 -0
  162. package/dist/thread/thread.js +472 -0
  163. package/dist/thread/utils.d.ts +19 -0
  164. package/dist/thread/utils.d.ts.map +1 -0
  165. package/dist/thread/utils.js +50 -0
  166. package/dist/tool/__tests__/fixtures.d.ts +45 -0
  167. package/dist/tool/__tests__/fixtures.d.ts.map +1 -0
  168. package/dist/tool/__tests__/fixtures.js +97 -0
  169. package/dist/tool/__tests__/tool.test.d.ts +2 -0
  170. package/dist/tool/__tests__/tool.test.d.ts.map +1 -0
  171. package/dist/tool/__tests__/tool.test.js +172 -0
  172. package/dist/tool/__tests__/toolkit.test.d.ts +2 -0
  173. package/dist/tool/__tests__/toolkit.test.d.ts.map +1 -0
  174. package/dist/tool/__tests__/toolkit.test.js +134 -0
  175. package/dist/tool/index.d.ts +4 -0
  176. package/dist/tool/index.d.ts.map +1 -0
  177. package/dist/tool/index.js +2 -0
  178. package/dist/tool/mcp.d.ts +75 -0
  179. package/dist/tool/mcp.d.ts.map +1 -0
  180. package/dist/tool/mcp.js +111 -0
  181. package/dist/tool/tool.d.ts +95 -0
  182. package/dist/tool/tool.d.ts.map +1 -0
  183. package/dist/tool/tool.js +176 -0
  184. package/dist/tool/toolkit.d.ts +121 -0
  185. package/dist/tool/toolkit.d.ts.map +1 -0
  186. package/dist/tool/toolkit.js +180 -0
  187. package/dist/tool/types.d.ts +187 -0
  188. package/dist/tool/types.d.ts.map +1 -0
  189. package/dist/tool/types.js +1 -0
  190. package/dist/tools.d.ts +362 -0
  191. package/dist/tools.d.ts.map +1 -0
  192. package/dist/tools.js +220 -0
  193. package/dist/trace/processor.d.ts +1 -0
  194. package/dist/trace/processor.d.ts.map +1 -0
  195. package/dist/trace/processor.js +1 -0
  196. package/dist/trace/traces.d.ts +1 -0
  197. package/dist/trace/traces.d.ts.map +1 -0
  198. package/dist/trace/traces.js +73 -0
  199. package/dist/trace/utils.d.ts +22 -0
  200. package/dist/trace/utils.d.ts.map +1 -0
  201. package/dist/trace/utils.js +30 -0
  202. package/dist/types/agent.d.ts +91 -0
  203. package/dist/types/agent.d.ts.map +1 -0
  204. package/dist/types/agent.js +1 -0
  205. package/dist/types/proto.d.ts +1551 -0
  206. package/dist/types/proto.d.ts.map +1 -0
  207. package/dist/types/proto.js +531 -0
  208. package/dist/types/thread.d.ts +71 -0
  209. package/dist/types/thread.d.ts.map +1 -0
  210. package/dist/types/thread.js +5 -0
  211. package/dist/usage.d.ts +43 -0
  212. package/dist/usage.d.ts.map +1 -0
  213. package/dist/usage.js +61 -0
  214. package/package.json +52 -0
  215. package/src/agent.ts +203 -0
  216. package/src/context.ts +265 -0
  217. package/src/guardrail.ts +277 -0
  218. package/src/index.ts +3 -0
  219. package/src/kernl.ts +22 -0
  220. package/src/lib/env.ts +36 -0
  221. package/src/lib/error.ts +158 -0
  222. package/src/lib/logger.ts +78 -0
  223. package/src/lib/serde/json.ts +18 -0
  224. package/src/lib/serde/thread.ts +188 -0
  225. package/src/lifecycle.ts +181 -0
  226. package/src/mcp/__tests__/base.test.ts +344 -0
  227. package/src/mcp/__tests__/fixtures/server.ts +179 -0
  228. package/src/mcp/__tests__/fixtures/utils.ts +58 -0
  229. package/src/mcp/__tests__/integration.test.ts +447 -0
  230. package/src/mcp/__tests__/stdio.test.ts +236 -0
  231. package/src/mcp/__tests__/utils.test.ts +360 -0
  232. package/src/mcp/base.ts +162 -0
  233. package/src/mcp/http.ts +147 -0
  234. package/src/mcp/sse.ts +137 -0
  235. package/src/mcp/stdio.ts +136 -0
  236. package/src/mcp/types.ts +202 -0
  237. package/src/mcp/utils.ts +62 -0
  238. package/src/task.ts +119 -0
  239. package/src/thread/__tests__/mock.ts +95 -0
  240. package/src/thread/__tests__/thread.test.ts +1574 -0
  241. package/src/thread/index.ts +1 -0
  242. package/src/thread/thread.ts +611 -0
  243. package/src/thread/utils.ts +67 -0
  244. package/src/tool/__tests__/fixtures.ts +106 -0
  245. package/src/tool/__tests__/tool.test.ts +235 -0
  246. package/src/tool/__tests__/toolkit.test.ts +174 -0
  247. package/src/tool/index.ts +10 -0
  248. package/src/tool/tool.ts +264 -0
  249. package/src/tool/toolkit.ts +234 -0
  250. package/src/tool/types.ts +243 -0
  251. package/src/trace/processor.ts +0 -0
  252. package/src/trace/traces.ts +86 -0
  253. package/src/trace/utils.ts +38 -0
  254. package/src/types/agent.ts +145 -0
  255. package/src/types/thread.ts +86 -0
  256. package/tsconfig.json +13 -0
  257. package/vitest.config.ts +14 -0
@@ -0,0 +1,162 @@
1
+ import { Logger } from "@/lib/logger";
2
+
3
+ import { MCPTool, MCPToolFilter, CallToolResultContent } from "./types";
4
+
5
+ export const DEFAULT_STDIO_MCP_CLIENT_LOGGER_NAME = "kernl:stdio-mcp-client";
6
+ export const DEFAULT_SSE_MCP_CLIENT_LOGGER_NAME = "kernl:sse-mcp-client";
7
+ export const DEFAULT_STREAMABLE_HTTP_MCP_CLIENT_LOGGER_NAME =
8
+ "kernl:streamable-http-mcp-client";
9
+
10
+ /**
11
+ * @example
12
+ *
13
+ * const server = new MCPServerStdio({
14
+ * id: 'Filesystem Server',
15
+ * command: 'npx',
16
+ * args: ['-y', '@modelcontextprotocol/server-filesystem', '/path/to/dir']
17
+ * });
18
+ *
19
+ * await server.connect(); // Establishes connection to the MCP server process
20
+ */
21
+
22
+ /**
23
+ * Cache storage for MCP tools by server id.
24
+ * Enables reusing tool definitions across multiple agent executions.
25
+ */
26
+ const _cachedTools: Record<string, MCPTool[]> = {};
27
+
28
+ /**
29
+ * Interface for MCP server implementations.
30
+ * Provides methods for connecting, listing tools, calling tools, and cleanup.
31
+ */
32
+ export interface MCPServer {
33
+ /**
34
+ * The unique identifier for this MCP server.
35
+ */
36
+ readonly id: string;
37
+
38
+ /**
39
+ * Whether to cache the tools list after first fetch.
40
+ */
41
+ cacheToolsList: boolean;
42
+
43
+ /**
44
+ * Filter to control which tools are exposed to agents.
45
+ * Always a callable function. Defaults to allowing all tools.
46
+ */
47
+ toolFilter: MCPToolFilter;
48
+
49
+ /**
50
+ * Establishes connection to the MCP server.
51
+ */
52
+ connect(): Promise<void>;
53
+
54
+ /**
55
+ * Closes the connection and cleans up resources.
56
+ */
57
+ close(): Promise<void>;
58
+
59
+ /**
60
+ * Fetches the list of available tools from the server.
61
+ */
62
+ listTools(): Promise<MCPTool[]>;
63
+
64
+ /**
65
+ * Executes a tool on the server with the provided arguments.
66
+ */
67
+ callTool(
68
+ toolName: string,
69
+ args: Record<string, unknown> | null,
70
+ ): Promise<CallToolResultContent>;
71
+
72
+ /**
73
+ * Clears any cached tools, forcing a fresh fetch on next request.
74
+ */
75
+ invalidateCache(): Promise<void>;
76
+ }
77
+
78
+ /**
79
+ * Base abstract class for MCP server implementations.
80
+ * Provides common caching logic.
81
+ */
82
+ export abstract class BaseMCPServer implements MCPServer {
83
+ abstract readonly id: string;
84
+ public cacheToolsList: boolean;
85
+ public toolFilter: MCPToolFilter;
86
+ protected logger: Logger;
87
+ protected _cachedTools: MCPTool[] | undefined = undefined;
88
+ protected _cacheDirty = true;
89
+
90
+ constructor(options: {
91
+ cacheToolsList?: boolean;
92
+ toolFilter?: MCPToolFilter;
93
+ logger: Logger;
94
+ }) {
95
+ this.logger = options.logger;
96
+ this.cacheToolsList = options.cacheToolsList ?? false;
97
+ this.toolFilter = options.toolFilter ?? (async () => true);
98
+ }
99
+
100
+ /**
101
+ * Establishes connection to the MCP server.
102
+ */
103
+ abstract connect(): Promise<void>;
104
+
105
+ /**
106
+ * Closes the connection and cleans up resources.
107
+ */
108
+ abstract close(): Promise<void>;
109
+
110
+ /**
111
+ * Executes a tool on the server with the provided arguments.
112
+ */
113
+ abstract callTool(
114
+ toolName: string,
115
+ args: Record<string, unknown> | null,
116
+ ): Promise<CallToolResultContent>;
117
+
118
+ /**
119
+ * Fetches the list of available tools from the server.
120
+ * Handles caching and static filtering automatically.
121
+ */
122
+ async listTools(): Promise<MCPTool[]> {
123
+ if (this.cacheToolsList && !this._cacheDirty && this._cachedTools) {
124
+ return this._cachedTools;
125
+ }
126
+
127
+ this._cacheDirty = false;
128
+ let tools = await this._listTools();
129
+
130
+ // Apply static server-level filter (without context)
131
+ // This is for static filtering like allowlist/blocklist
132
+ const filteredTools: MCPTool[] = [];
133
+ for (const tool of tools) {
134
+ // Pass empty context for static filtering
135
+ const allowed = await this.toolFilter({} as any, tool);
136
+ if (allowed) {
137
+ filteredTools.push(tool);
138
+ }
139
+ }
140
+ tools = filteredTools;
141
+
142
+ if (this.cacheToolsList) {
143
+ this._cachedTools = tools;
144
+ }
145
+
146
+ return tools;
147
+ }
148
+
149
+ /**
150
+ * Clears any cached tools, forcing a fresh fetch on next request.
151
+ */
152
+ async invalidateCache(): Promise<void> {
153
+ delete _cachedTools[this.id];
154
+ this._cacheDirty = true;
155
+ }
156
+
157
+ /**
158
+ * Internal implementation: Fetches tools from the server (without caching logic).
159
+ * Subclasses implement the transport-specific logic.
160
+ */
161
+ protected abstract _listTools(): Promise<MCPTool[]>;
162
+ }
@@ -0,0 +1,147 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
3
+ import { DEFAULT_REQUEST_TIMEOUT_MSEC } from "@modelcontextprotocol/sdk/shared/protocol.js";
4
+ import {
5
+ ListToolsResultSchema,
6
+ CallToolResultSchema,
7
+ } from "@modelcontextprotocol/sdk/types.js";
8
+
9
+ import { getLogger } from "@/lib/logger";
10
+
11
+ import {
12
+ BaseMCPServer,
13
+ DEFAULT_STREAMABLE_HTTP_MCP_CLIENT_LOGGER_NAME,
14
+ } from "./base";
15
+ import type {
16
+ MCPTool,
17
+ CallToolResultContent,
18
+ MCPServerStreamableHttpOptions,
19
+ InitializeResult,
20
+ } from "./types";
21
+
22
+ /**
23
+ * MCP server client that communicates over streamable HTTP protocol.
24
+ */
25
+ export class MCPServerStreamableHttp extends BaseMCPServer {
26
+ readonly id: string;
27
+ protected session: Client | null = null;
28
+ protected timeout: number;
29
+ protected serverInitializeResult: InitializeResult | null = null;
30
+
31
+ params: MCPServerStreamableHttpOptions;
32
+ private transport: any = null;
33
+
34
+ constructor(options: MCPServerStreamableHttpOptions) {
35
+ super({
36
+ cacheToolsList: options.cacheToolsList,
37
+ toolFilter: options.toolFilter,
38
+ logger:
39
+ options.logger ??
40
+ getLogger(DEFAULT_STREAMABLE_HTTP_MCP_CLIENT_LOGGER_NAME),
41
+ });
42
+
43
+ this.params = options;
44
+ this.id = options.id || `streamable-http: ${this.params.url}`;
45
+ this.timeout = options.timeout ?? DEFAULT_REQUEST_TIMEOUT_MSEC;
46
+ }
47
+
48
+ /**
49
+ * Establishes connection to the MCP server.
50
+ */
51
+ async connect(): Promise<void> {
52
+ try {
53
+ this.transport = new StreamableHTTPClientTransport(
54
+ new URL(this.params.url),
55
+ {
56
+ authProvider: this.params.authProvider,
57
+ requestInit: this.params.requestInit,
58
+ fetch: this.params.fetch,
59
+ reconnectionOptions: this.params.reconnectionOptions,
60
+ sessionId: this.params.sessionId,
61
+ },
62
+ );
63
+
64
+ this.session = new Client({
65
+ name: this.id,
66
+ version: "1.0.0",
67
+ });
68
+
69
+ await this.session.connect(this.transport);
70
+
71
+ this.serverInitializeResult = {
72
+ serverInfo: { name: this.id, version: "1.0.0" },
73
+ } as InitializeResult;
74
+ } catch (e) {
75
+ this.logger.error("Error initializing MCP server:", e);
76
+ await this.close();
77
+ throw e;
78
+ }
79
+
80
+ this.logger.debug(`Connected to MCP server: ${this.id}`);
81
+ }
82
+
83
+ /**
84
+ * Closes the connection and cleans up resources.
85
+ */
86
+ async close(): Promise<void> {
87
+ if (this.transport) {
88
+ await this.transport.close();
89
+ this.transport = null;
90
+ }
91
+ if (this.session) {
92
+ await this.session.close();
93
+ this.session = null;
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Internal implementation: Fetches tools from the server.
99
+ *
100
+ * Cached via the abstract base class.
101
+ */
102
+ protected async _listTools(): Promise<MCPTool[]> {
103
+ if (!this.session) {
104
+ throw new Error(
105
+ "Server not initialized. Make sure you call connect() first.",
106
+ );
107
+ }
108
+
109
+ const response = await this.session.listTools();
110
+ this.logger.debug(`Listed tools: ${JSON.stringify(response)}`);
111
+ return ListToolsResultSchema.parse(response).tools;
112
+ }
113
+
114
+ /**
115
+ * Executes a tool on the server with the provided arguments.
116
+ */
117
+ async callTool(
118
+ toolName: string,
119
+ args: Record<string, unknown> | null,
120
+ ): Promise<CallToolResultContent> {
121
+ if (!this.session) {
122
+ throw new Error(
123
+ "Server not initialized. Make sure you call connect() first.",
124
+ );
125
+ }
126
+
127
+ const response = await this.session.callTool(
128
+ {
129
+ name: toolName,
130
+ arguments: args ?? {},
131
+ },
132
+ undefined,
133
+ {
134
+ timeout: this.timeout,
135
+ },
136
+ );
137
+
138
+ const parsed = CallToolResultSchema.parse(response);
139
+ const result = parsed.content;
140
+
141
+ this.logger.debug(
142
+ `Called tool ${toolName} (args: ${JSON.stringify(args)}, result: ${JSON.stringify(result)})`,
143
+ );
144
+
145
+ return result as CallToolResultContent;
146
+ }
147
+ }
package/src/mcp/sse.ts ADDED
@@ -0,0 +1,137 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
3
+ import { DEFAULT_REQUEST_TIMEOUT_MSEC } from "@modelcontextprotocol/sdk/shared/protocol.js";
4
+ import {
5
+ ListToolsResultSchema,
6
+ CallToolResultSchema,
7
+ } from "@modelcontextprotocol/sdk/types.js";
8
+
9
+ import { getLogger } from "@/lib/logger";
10
+
11
+ import { BaseMCPServer, DEFAULT_SSE_MCP_CLIENT_LOGGER_NAME } from "./base";
12
+ import type {
13
+ MCPTool,
14
+ CallToolResultContent,
15
+ MCPServerSSEOptions,
16
+ InitializeResult,
17
+ } from "./types";
18
+
19
+ /**
20
+ * MCP server client that communicates over Server-Sent Events (SSE).
21
+ */
22
+ export class MCPServerSSE extends BaseMCPServer {
23
+ readonly id: string;
24
+ protected session: Client | null = null;
25
+ protected timeout: number;
26
+ protected serverInitializeResult: InitializeResult | null = null;
27
+
28
+ params: MCPServerSSEOptions;
29
+ private transport: any = null;
30
+
31
+ constructor(options: MCPServerSSEOptions) {
32
+ super({
33
+ cacheToolsList: options.cacheToolsList,
34
+ toolFilter: options.toolFilter,
35
+ logger: options.logger ?? getLogger(DEFAULT_SSE_MCP_CLIENT_LOGGER_NAME),
36
+ });
37
+
38
+ this.params = options;
39
+ this.id = options.id || `sse: ${this.params.url}`;
40
+ this.timeout = options.timeout ?? DEFAULT_REQUEST_TIMEOUT_MSEC;
41
+ }
42
+
43
+ /**
44
+ * Establishes connection to the MCP server.
45
+ */
46
+ async connect(): Promise<void> {
47
+ try {
48
+ this.transport = new SSEClientTransport(new URL(this.params.url), {
49
+ authProvider: this.params.authProvider,
50
+ requestInit: this.params.requestInit,
51
+ eventSourceInit: this.params.eventSourceInit,
52
+ });
53
+
54
+ this.session = new Client({
55
+ name: this.id,
56
+ version: "1.0.0",
57
+ });
58
+
59
+ await this.session.connect(this.transport);
60
+
61
+ this.serverInitializeResult = {
62
+ serverInfo: { name: this.id, version: "1.0.0" },
63
+ } as InitializeResult;
64
+ } catch (e) {
65
+ this.logger.error("Error initializing MCP server:", e);
66
+ await this.close();
67
+ throw e;
68
+ }
69
+
70
+ this.logger.debug(`Connected to MCP server: ${this.id}`);
71
+ }
72
+
73
+ /**
74
+ * Internal implementation: Fetches tools from the server.
75
+ *
76
+ * Cached via the BaseMCPServer class.
77
+ */
78
+ protected async _listTools(): Promise<MCPTool[]> {
79
+ if (!this.session) {
80
+ throw new Error(
81
+ "Server not initialized. Make sure you call connect() first.",
82
+ );
83
+ }
84
+
85
+ const response = await this.session.listTools();
86
+ this.logger.debug(`Listed tools: ${JSON.stringify(response)}`);
87
+ return ListToolsResultSchema.parse(response).tools;
88
+ }
89
+
90
+ /**
91
+ * Executes a tool on the server with the provided arguments.
92
+ */
93
+ async callTool(
94
+ toolName: string,
95
+ args: Record<string, unknown> | null,
96
+ ): Promise<CallToolResultContent> {
97
+ if (!this.session) {
98
+ throw new Error(
99
+ "Server not initialized. Make sure you call connect() first.",
100
+ );
101
+ }
102
+
103
+ const response = await this.session.callTool(
104
+ {
105
+ name: toolName,
106
+ arguments: args ?? {},
107
+ },
108
+ undefined,
109
+ {
110
+ timeout: this.timeout,
111
+ },
112
+ );
113
+
114
+ const parsed = CallToolResultSchema.parse(response);
115
+ const result = parsed.content;
116
+
117
+ this.logger.debug(
118
+ `Called tool ${toolName} (args: ${JSON.stringify(args)}, result: ${JSON.stringify(result)})`,
119
+ );
120
+
121
+ return result as CallToolResultContent;
122
+ }
123
+
124
+ /**
125
+ * Closes the connection and cleans up resources.
126
+ */
127
+ async close(): Promise<void> {
128
+ if (this.transport) {
129
+ await this.transport.close();
130
+ this.transport = null;
131
+ }
132
+ if (this.session) {
133
+ await this.session.close();
134
+ this.session = null;
135
+ }
136
+ }
137
+ }
@@ -0,0 +1,136 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
3
+ import { DEFAULT_REQUEST_TIMEOUT_MSEC } from "@modelcontextprotocol/sdk/shared/protocol.js";
4
+ import {
5
+ ListToolsResultSchema,
6
+ CallToolResultSchema,
7
+ } from "@modelcontextprotocol/sdk/types.js";
8
+
9
+ import { getLogger } from "@/lib/logger";
10
+
11
+ import { BaseMCPServer, DEFAULT_STDIO_MCP_CLIENT_LOGGER_NAME } from "./base";
12
+ import type {
13
+ MCPTool,
14
+ CallToolResultContent,
15
+ MCPServerStdioOptions,
16
+ InitializeResult,
17
+ } from "./types";
18
+
19
+ /**
20
+ * MCP server client that communicates over stdio (standard input/output).
21
+ */
22
+ export class MCPServerStdio extends BaseMCPServer {
23
+ readonly id: string;
24
+ protected session: Client | null = null;
25
+ protected timeout: number;
26
+ protected serverInitializeResult: InitializeResult | null = null;
27
+
28
+ private params: MCPServerStdioOptions;
29
+ private transport: any = null;
30
+
31
+ constructor(options: MCPServerStdioOptions) {
32
+ super({
33
+ cacheToolsList: options.cacheToolsList,
34
+ toolFilter: options.toolFilter,
35
+ logger: options.logger ?? getLogger(DEFAULT_STDIO_MCP_CLIENT_LOGGER_NAME),
36
+ });
37
+
38
+ this.timeout = options.timeout ?? DEFAULT_REQUEST_TIMEOUT_MSEC;
39
+ this.params = options;
40
+ this.id = options.id || `stdio: ${this.params.command}`;
41
+ }
42
+
43
+ /**
44
+ * Establishes connection to the MCP server.
45
+ */
46
+ async connect(): Promise<void> {
47
+ try {
48
+ this.transport = new StdioClientTransport({
49
+ command: this.params.command,
50
+ args: this.params.args,
51
+ env: this.params.env,
52
+ cwd: this.params.cwd,
53
+ });
54
+
55
+ this.session = new Client({
56
+ name: this.id,
57
+ version: "1.0.0",
58
+ });
59
+
60
+ await this.session.connect(this.transport);
61
+
62
+ this.serverInitializeResult = {
63
+ serverInfo: { name: this.id, version: "1.0.0" },
64
+ } as InitializeResult;
65
+
66
+ this.logger.debug(`Connected to MCP server: ${this.id}`);
67
+ } catch (e) {
68
+ this.logger.error("Error initializing MCP server:", e);
69
+ await this.close();
70
+ throw e;
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Internal implementation: Fetches tools from the server.
76
+ */
77
+ protected async _listTools(): Promise<MCPTool[]> {
78
+ if (!this.session) {
79
+ throw new Error(
80
+ "Server not initialized. Make sure you call connect() first.",
81
+ );
82
+ }
83
+
84
+ const response = await this.session.listTools();
85
+ this.logger.debug(`Listed tools: ${JSON.stringify(response)}`);
86
+ return ListToolsResultSchema.parse(response).tools;
87
+ }
88
+
89
+ /**
90
+ * Executes a tool on the server with the provided arguments.
91
+ */
92
+ async callTool(
93
+ toolName: string,
94
+ args: Record<string, unknown> | null,
95
+ ): Promise<CallToolResultContent> {
96
+ if (!this.session) {
97
+ throw new Error(
98
+ "Server not initialized. Make sure you call connect() first.",
99
+ );
100
+ }
101
+
102
+ const response = await this.session.callTool(
103
+ {
104
+ name: toolName,
105
+ arguments: args ?? {},
106
+ },
107
+ undefined,
108
+ {
109
+ timeout: this.timeout,
110
+ },
111
+ );
112
+
113
+ const parsed = CallToolResultSchema.parse(response);
114
+ const result = parsed.content;
115
+
116
+ this.logger.debug(
117
+ `Called tool ${toolName} (args: ${JSON.stringify(args)}, result: ${JSON.stringify(result)})`,
118
+ );
119
+
120
+ return result as CallToolResultContent;
121
+ }
122
+
123
+ /**
124
+ * Closes the connection and cleans up resources.
125
+ */
126
+ async close(): Promise<void> {
127
+ if (this.transport) {
128
+ await this.transport.close();
129
+ this.transport = null;
130
+ }
131
+ if (this.session) {
132
+ await this.session.close();
133
+ this.session = null;
134
+ }
135
+ }
136
+ }