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,300 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { mcpToFunctionTool, createMCPToolStaticFilter } from "../utils";
3
+ import { Context } from "../../context";
4
+ describe("mcpToFunctionTool", () => {
5
+ // Create a mock MCP server
6
+ const createMockServer = () => ({
7
+ id: "mock-server",
8
+ cacheToolsList: false,
9
+ toolFilter: async () => true,
10
+ connect: vi.fn(),
11
+ close: vi.fn(),
12
+ listTools: vi.fn(),
13
+ callTool: vi.fn(),
14
+ invalidateCache: vi.fn(),
15
+ });
16
+ it("should convert MCPTool to FunctionTool correctly", () => {
17
+ const server = createMockServer();
18
+ const mcpTool = {
19
+ name: "test_tool",
20
+ description: "A test tool",
21
+ inputSchema: {
22
+ type: "object",
23
+ properties: {
24
+ arg1: { type: "string" },
25
+ },
26
+ },
27
+ };
28
+ const functionTool = mcpToFunctionTool(server, mcpTool);
29
+ expect(functionTool.id).toBe("test_tool");
30
+ expect(functionTool.name).toBe("test_tool");
31
+ expect(functionTool.description).toBe("A test tool");
32
+ expect(functionTool.parameters).toBeDefined();
33
+ // execute is private, but we can verify the tool has an invoke method
34
+ expect(functionTool.invoke).toBeDefined();
35
+ });
36
+ it("should map tool metadata (name, description, inputSchema)", () => {
37
+ const server = createMockServer();
38
+ const mcpTool = {
39
+ name: "calculator",
40
+ description: "Performs calculations",
41
+ inputSchema: {
42
+ type: "object",
43
+ properties: {
44
+ operation: { type: "string" },
45
+ values: { type: "array" },
46
+ },
47
+ },
48
+ };
49
+ const functionTool = mcpToFunctionTool(server, mcpTool);
50
+ expect(functionTool.id).toBe("calculator");
51
+ expect(functionTool.name).toBe("calculator");
52
+ expect(functionTool.description).toBe("Performs calculations");
53
+ expect(functionTool.parameters).toBeDefined();
54
+ });
55
+ it("should handle tools without inputSchema (undefined parameters)", () => {
56
+ const server = createMockServer();
57
+ // In practice, MCP SDK tools require inputSchema, but our function handles
58
+ // the case where it might not be present. We use 'as any' to test this edge case.
59
+ const mcpTool = {
60
+ name: "no_params",
61
+ description: "Tool without parameters",
62
+ };
63
+ const functionTool = mcpToFunctionTool(server, mcpTool);
64
+ expect(functionTool.id).toBe("no_params");
65
+ expect(functionTool.parameters).toBeUndefined();
66
+ });
67
+ it("should invoke server.callTool with correct params", async () => {
68
+ const server = createMockServer();
69
+ server.callTool = vi
70
+ .fn()
71
+ .mockResolvedValue([{ type: "text", text: "result" }]);
72
+ const mcpTool = {
73
+ name: "test_tool",
74
+ inputSchema: {
75
+ type: "object",
76
+ properties: {
77
+ arg1: { type: "string" },
78
+ },
79
+ },
80
+ };
81
+ const functionTool = mcpToFunctionTool(server, mcpTool);
82
+ const ctx = new Context({});
83
+ const input = { arg1: "value1" };
84
+ await functionTool.invoke(ctx, JSON.stringify(input));
85
+ expect(server.callTool).toHaveBeenCalledWith("test_tool", input);
86
+ expect(server.callTool).toHaveBeenCalledTimes(1);
87
+ });
88
+ it("should return single content item correctly", async () => {
89
+ const server = createMockServer();
90
+ server.callTool = vi
91
+ .fn()
92
+ .mockResolvedValue([{ type: "text", text: "single result" }]);
93
+ const mcpTool = {
94
+ name: "test_tool",
95
+ inputSchema: {
96
+ type: "object",
97
+ properties: {},
98
+ },
99
+ };
100
+ const functionTool = mcpToFunctionTool(server, mcpTool);
101
+ const ctx = new Context({});
102
+ const toolResult = await functionTool.invoke(ctx, JSON.stringify({}));
103
+ expect(toolResult.state).toBe("completed");
104
+ expect(toolResult.result).toEqual({ type: "text", text: "single result" });
105
+ });
106
+ it("should return multiple content items as array", async () => {
107
+ const server = createMockServer();
108
+ const multipleItems = [
109
+ { type: "text", text: "result 1" },
110
+ { type: "text", text: "result 2" },
111
+ { type: "text", text: "result 3" },
112
+ ];
113
+ server.callTool = vi.fn().mockResolvedValue(multipleItems);
114
+ const mcpTool = {
115
+ name: "test_tool",
116
+ inputSchema: {
117
+ type: "object",
118
+ properties: {},
119
+ },
120
+ };
121
+ const functionTool = mcpToFunctionTool(server, mcpTool);
122
+ const ctx = new Context({});
123
+ const toolResult = await functionTool.invoke(ctx, JSON.stringify({}));
124
+ expect(toolResult.state).toBe("completed");
125
+ expect(toolResult.result).toEqual(multipleItems);
126
+ expect(Array.isArray(toolResult.result)).toBe(true);
127
+ expect(toolResult.result).toHaveLength(3);
128
+ });
129
+ it("should preserve tool name in closure", async () => {
130
+ const server = createMockServer();
131
+ server.callTool = vi
132
+ .fn()
133
+ .mockResolvedValue([{ type: "text", text: "result" }]);
134
+ const tool1 = {
135
+ name: "tool1",
136
+ inputSchema: { type: "object", properties: {} },
137
+ };
138
+ const tool2 = {
139
+ name: "tool2",
140
+ inputSchema: { type: "object", properties: {} },
141
+ };
142
+ const functionTool1 = mcpToFunctionTool(server, tool1);
143
+ const functionTool2 = mcpToFunctionTool(server, tool2);
144
+ const ctx = new Context({});
145
+ await functionTool1.invoke(ctx, JSON.stringify({}));
146
+ expect(server.callTool).toHaveBeenCalledWith("tool1", {});
147
+ await functionTool2.invoke(ctx, JSON.stringify({}));
148
+ expect(server.callTool).toHaveBeenCalledWith("tool2", {});
149
+ });
150
+ it("should use correct parameter order (context, params)", async () => {
151
+ const server = createMockServer();
152
+ server.callTool = vi
153
+ .fn()
154
+ .mockResolvedValue([{ type: "text", text: "result" }]);
155
+ const mcpTool = {
156
+ name: "test_tool",
157
+ inputSchema: {
158
+ type: "object",
159
+ properties: {
160
+ foo: { type: "string" },
161
+ },
162
+ },
163
+ };
164
+ const functionTool = mcpToFunctionTool(server, mcpTool);
165
+ // Invoke takes (context, params as JSON string) in that order
166
+ const ctx = new Context({});
167
+ const params = { foo: "bar" };
168
+ await functionTool.invoke(ctx, JSON.stringify(params));
169
+ // Verify the tool was called with the params (not the context)
170
+ expect(server.callTool).toHaveBeenCalledWith("test_tool", params);
171
+ });
172
+ });
173
+ describe("createMCPToolStaticFilter", () => {
174
+ // Helper to create mock filter context
175
+ const createMockFilterContext = () => ({
176
+ context: new Context({}),
177
+ agent: {},
178
+ serverId: "test-server",
179
+ });
180
+ it("should return undefined when no options provided", () => {
181
+ const filter = createMCPToolStaticFilter();
182
+ expect(filter).toBeUndefined();
183
+ });
184
+ it("should return undefined when options is empty object", () => {
185
+ const filter = createMCPToolStaticFilter({});
186
+ expect(filter).toBeUndefined();
187
+ });
188
+ it("should create allowlist filter correctly", async () => {
189
+ const filter = createMCPToolStaticFilter({
190
+ allowed: ["tool1", "tool2"],
191
+ });
192
+ expect(filter).toBeDefined();
193
+ const mockContext = createMockFilterContext();
194
+ const tool1 = {
195
+ name: "tool1",
196
+ inputSchema: { type: "object", properties: {} },
197
+ };
198
+ const tool2 = {
199
+ name: "tool2",
200
+ inputSchema: { type: "object", properties: {} },
201
+ };
202
+ const tool3 = {
203
+ name: "tool3",
204
+ inputSchema: { type: "object", properties: {} },
205
+ };
206
+ expect(await filter(mockContext, tool1)).toBe(true);
207
+ expect(await filter(mockContext, tool2)).toBe(true);
208
+ expect(await filter(mockContext, tool3)).toBe(false);
209
+ });
210
+ it("should create blocklist filter correctly", async () => {
211
+ const filter = createMCPToolStaticFilter({
212
+ blocked: ["dangerous_tool", "risky_tool"],
213
+ });
214
+ expect(filter).toBeDefined();
215
+ const mockContext = createMockFilterContext();
216
+ const safeTool = {
217
+ name: "safe_tool",
218
+ inputSchema: { type: "object", properties: {} },
219
+ };
220
+ const dangerousTool = {
221
+ name: "dangerous_tool",
222
+ inputSchema: { type: "object", properties: {} },
223
+ };
224
+ const riskyTool = {
225
+ name: "risky_tool",
226
+ inputSchema: { type: "object", properties: {} },
227
+ };
228
+ expect(await filter(mockContext, safeTool)).toBe(true);
229
+ expect(await filter(mockContext, dangerousTool)).toBe(false);
230
+ expect(await filter(mockContext, riskyTool)).toBe(false);
231
+ });
232
+ it("should combine allowlist and blocklist", async () => {
233
+ const filter = createMCPToolStaticFilter({
234
+ allowed: ["tool1", "tool2", "tool3"],
235
+ blocked: ["tool2"],
236
+ });
237
+ expect(filter).toBeDefined();
238
+ const mockContext = createMockFilterContext();
239
+ const tool1 = {
240
+ name: "tool1",
241
+ inputSchema: { type: "object", properties: {} },
242
+ };
243
+ const tool2 = {
244
+ name: "tool2",
245
+ inputSchema: { type: "object", properties: {} },
246
+ };
247
+ const tool3 = {
248
+ name: "tool3",
249
+ inputSchema: { type: "object", properties: {} },
250
+ };
251
+ const tool4 = {
252
+ name: "tool4",
253
+ inputSchema: { type: "object", properties: {} },
254
+ };
255
+ expect(await filter(mockContext, tool1)).toBe(true);
256
+ expect(await filter(mockContext, tool2)).toBe(false); // In allowed but blocked
257
+ expect(await filter(mockContext, tool3)).toBe(true);
258
+ expect(await filter(mockContext, tool4)).toBe(false); // Not in allowed list
259
+ });
260
+ it("should default to allow-all when lists empty", async () => {
261
+ const filter = createMCPToolStaticFilter({
262
+ allowed: [],
263
+ blocked: [],
264
+ });
265
+ expect(filter).toBeDefined();
266
+ const mockContext = createMockFilterContext();
267
+ const tool1 = {
268
+ name: "tool1",
269
+ inputSchema: { type: "object", properties: {} },
270
+ };
271
+ const tool2 = {
272
+ name: "tool2",
273
+ inputSchema: { type: "object", properties: {} },
274
+ };
275
+ expect(await filter(mockContext, tool1)).toBe(true);
276
+ expect(await filter(mockContext, tool2)).toBe(true);
277
+ });
278
+ it("should filter based on tool.name property", async () => {
279
+ const filter = createMCPToolStaticFilter({
280
+ allowed: ["exact_name"],
281
+ });
282
+ expect(filter).toBeDefined();
283
+ const mockContext = createMockFilterContext();
284
+ const exactMatch = {
285
+ name: "exact_name",
286
+ inputSchema: { type: "object", properties: {} },
287
+ };
288
+ const partialMatch = {
289
+ name: "exact_name_with_suffix",
290
+ inputSchema: { type: "object", properties: {} },
291
+ };
292
+ const noMatch = {
293
+ name: "different_name",
294
+ inputSchema: { type: "object", properties: {} },
295
+ };
296
+ expect(await filter(mockContext, exactMatch)).toBe(true);
297
+ expect(await filter(mockContext, partialMatch)).toBe(false);
298
+ expect(await filter(mockContext, noMatch)).toBe(false);
299
+ });
300
+ });
@@ -0,0 +1,88 @@
1
+ import { Logger } from "../lib/logger";
2
+ import { MCPTool, MCPToolFilter, CallToolResultContent } from "./types";
3
+ export declare const DEFAULT_STDIO_MCP_CLIENT_LOGGER_NAME = "kernl:stdio-mcp-client";
4
+ export declare const DEFAULT_SSE_MCP_CLIENT_LOGGER_NAME = "kernl:sse-mcp-client";
5
+ export declare const DEFAULT_STREAMABLE_HTTP_MCP_CLIENT_LOGGER_NAME = "kernl:streamable-http-mcp-client";
6
+ /**
7
+ * Interface for MCP server implementations.
8
+ * Provides methods for connecting, listing tools, calling tools, and cleanup.
9
+ */
10
+ export interface MCPServer {
11
+ /**
12
+ * The unique identifier for this MCP server.
13
+ */
14
+ readonly id: string;
15
+ /**
16
+ * Whether to cache the tools list after first fetch.
17
+ */
18
+ cacheToolsList: boolean;
19
+ /**
20
+ * Filter to control which tools are exposed to agents.
21
+ * Always a callable function. Defaults to allowing all tools.
22
+ */
23
+ toolFilter: MCPToolFilter;
24
+ /**
25
+ * Establishes connection to the MCP server.
26
+ */
27
+ connect(): Promise<void>;
28
+ /**
29
+ * Closes the connection and cleans up resources.
30
+ */
31
+ close(): Promise<void>;
32
+ /**
33
+ * Fetches the list of available tools from the server.
34
+ */
35
+ listTools(): Promise<MCPTool[]>;
36
+ /**
37
+ * Executes a tool on the server with the provided arguments.
38
+ */
39
+ callTool(toolName: string, args: Record<string, unknown> | null): Promise<CallToolResultContent>;
40
+ /**
41
+ * Clears any cached tools, forcing a fresh fetch on next request.
42
+ */
43
+ invalidateCache(): Promise<void>;
44
+ }
45
+ /**
46
+ * Base abstract class for MCP server implementations.
47
+ * Provides common caching logic.
48
+ */
49
+ export declare abstract class BaseMCPServer implements MCPServer {
50
+ abstract readonly id: string;
51
+ cacheToolsList: boolean;
52
+ toolFilter: MCPToolFilter;
53
+ protected logger: Logger;
54
+ protected _cachedTools: MCPTool[] | undefined;
55
+ protected _cacheDirty: boolean;
56
+ constructor(options: {
57
+ cacheToolsList?: boolean;
58
+ toolFilter?: MCPToolFilter;
59
+ logger: Logger;
60
+ });
61
+ /**
62
+ * Establishes connection to the MCP server.
63
+ */
64
+ abstract connect(): Promise<void>;
65
+ /**
66
+ * Closes the connection and cleans up resources.
67
+ */
68
+ abstract close(): Promise<void>;
69
+ /**
70
+ * Executes a tool on the server with the provided arguments.
71
+ */
72
+ abstract callTool(toolName: string, args: Record<string, unknown> | null): Promise<CallToolResultContent>;
73
+ /**
74
+ * Fetches the list of available tools from the server.
75
+ * Handles caching and static filtering automatically.
76
+ */
77
+ listTools(): Promise<MCPTool[]>;
78
+ /**
79
+ * Clears any cached tools, forcing a fresh fetch on next request.
80
+ */
81
+ invalidateCache(): Promise<void>;
82
+ /**
83
+ * Internal implementation: Fetches tools from the server (without caching logic).
84
+ * Subclasses implement the transport-specific logic.
85
+ */
86
+ protected abstract _listTools(): Promise<MCPTool[]>;
87
+ }
88
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/mcp/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAExE,eAAO,MAAM,oCAAoC,2BAA2B,CAAC;AAC7E,eAAO,MAAM,kCAAkC,yBAAyB,CAAC;AACzE,eAAO,MAAM,8CAA8C,qCACvB,CAAC;AAoBrC;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,cAAc,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,UAAU,EAAE,aAAa,CAAC;IAE1B;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzB;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;OAEG;IACH,SAAS,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAEhC;;OAEG;IACH,QAAQ,CACN,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACnC,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAElC;;OAEG;IACH,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAED;;;GAGG;AACH,8BAAsB,aAAc,YAAW,SAAS;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,aAAa,CAAC;IACjC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,YAAY,EAAE,OAAO,EAAE,GAAG,SAAS,CAAa;IAC1D,SAAS,CAAC,WAAW,UAAQ;gBAEjB,OAAO,EAAE;QACnB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE,aAAa,CAAC;QAC3B,MAAM,EAAE,MAAM,CAAC;KAChB;IAMD;;OAEG;IACH,QAAQ,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAEjC;;OAEG;IACH,QAAQ,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAE/B;;OAEG;IACH,QAAQ,CAAC,QAAQ,CACf,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACnC,OAAO,CAAC,qBAAqB,CAAC;IAEjC;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IA2BrC;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtC;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;CACpD"}
@@ -0,0 +1,68 @@
1
+ export const DEFAULT_STDIO_MCP_CLIENT_LOGGER_NAME = "kernl:stdio-mcp-client";
2
+ export const DEFAULT_SSE_MCP_CLIENT_LOGGER_NAME = "kernl:sse-mcp-client";
3
+ export const DEFAULT_STREAMABLE_HTTP_MCP_CLIENT_LOGGER_NAME = "kernl:streamable-http-mcp-client";
4
+ /**
5
+ * @example
6
+ *
7
+ * const server = new MCPServerStdio({
8
+ * id: 'Filesystem Server',
9
+ * command: 'npx',
10
+ * args: ['-y', '@modelcontextprotocol/server-filesystem', '/path/to/dir']
11
+ * });
12
+ *
13
+ * await server.connect(); // Establishes connection to the MCP server process
14
+ */
15
+ /**
16
+ * Cache storage for MCP tools by server id.
17
+ * Enables reusing tool definitions across multiple agent executions.
18
+ */
19
+ const _cachedTools = {};
20
+ /**
21
+ * Base abstract class for MCP server implementations.
22
+ * Provides common caching logic.
23
+ */
24
+ export class BaseMCPServer {
25
+ cacheToolsList;
26
+ toolFilter;
27
+ logger;
28
+ _cachedTools = undefined;
29
+ _cacheDirty = true;
30
+ constructor(options) {
31
+ this.logger = options.logger;
32
+ this.cacheToolsList = options.cacheToolsList ?? false;
33
+ this.toolFilter = options.toolFilter ?? (async () => true);
34
+ }
35
+ /**
36
+ * Fetches the list of available tools from the server.
37
+ * Handles caching and static filtering automatically.
38
+ */
39
+ async listTools() {
40
+ if (this.cacheToolsList && !this._cacheDirty && this._cachedTools) {
41
+ return this._cachedTools;
42
+ }
43
+ this._cacheDirty = false;
44
+ let tools = await this._listTools();
45
+ // Apply static server-level filter (without context)
46
+ // This is for static filtering like allowlist/blocklist
47
+ const filteredTools = [];
48
+ for (const tool of tools) {
49
+ // Pass empty context for static filtering
50
+ const allowed = await this.toolFilter({}, tool);
51
+ if (allowed) {
52
+ filteredTools.push(tool);
53
+ }
54
+ }
55
+ tools = filteredTools;
56
+ if (this.cacheToolsList) {
57
+ this._cachedTools = tools;
58
+ }
59
+ return tools;
60
+ }
61
+ /**
62
+ * Clears any cached tools, forcing a fresh fetch on next request.
63
+ */
64
+ async invalidateCache() {
65
+ delete _cachedTools[this.id];
66
+ this._cacheDirty = true;
67
+ }
68
+ }
@@ -0,0 +1,34 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { BaseMCPServer } from "./base";
3
+ import type { MCPTool, CallToolResultContent, MCPServerStreamableHttpOptions, InitializeResult } from "./types";
4
+ /**
5
+ * MCP server client that communicates over streamable HTTP protocol.
6
+ */
7
+ export declare class MCPServerStreamableHttp extends BaseMCPServer {
8
+ readonly id: string;
9
+ protected session: Client | null;
10
+ protected timeout: number;
11
+ protected serverInitializeResult: InitializeResult | null;
12
+ params: MCPServerStreamableHttpOptions;
13
+ private transport;
14
+ constructor(options: MCPServerStreamableHttpOptions);
15
+ /**
16
+ * Establishes connection to the MCP server.
17
+ */
18
+ connect(): Promise<void>;
19
+ /**
20
+ * Closes the connection and cleans up resources.
21
+ */
22
+ close(): Promise<void>;
23
+ /**
24
+ * Internal implementation: Fetches tools from the server.
25
+ *
26
+ * Cached via the abstract base class.
27
+ */
28
+ protected _listTools(): Promise<MCPTool[]>;
29
+ /**
30
+ * Executes a tool on the server with the provided arguments.
31
+ */
32
+ callTool(toolName: string, args: Record<string, unknown> | null): Promise<CallToolResultContent>;
33
+ }
34
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/mcp/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAUnE,OAAO,EACL,aAAa,EAEd,MAAM,QAAQ,CAAC;AAChB,OAAO,KAAK,EACV,OAAO,EACP,qBAAqB,EACrB,8BAA8B,EAC9B,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,aAAa;IACxD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAQ;IACxC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,sBAAsB,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IAEjE,MAAM,EAAE,8BAA8B,CAAC;IACvC,OAAO,CAAC,SAAS,CAAa;gBAElB,OAAO,EAAE,8BAA8B;IAcnD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgC9B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B;;;;OAIG;cACa,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAYhD;;OAEG;IACG,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACnC,OAAO,CAAC,qBAAqB,CAAC;CA2BlC"}
@@ -0,0 +1,100 @@
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 { ListToolsResultSchema, CallToolResultSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import { getLogger } from "../lib/logger";
6
+ import { BaseMCPServer, DEFAULT_STREAMABLE_HTTP_MCP_CLIENT_LOGGER_NAME, } from "./base";
7
+ /**
8
+ * MCP server client that communicates over streamable HTTP protocol.
9
+ */
10
+ export class MCPServerStreamableHttp extends BaseMCPServer {
11
+ id;
12
+ session = null;
13
+ timeout;
14
+ serverInitializeResult = null;
15
+ params;
16
+ transport = null;
17
+ constructor(options) {
18
+ super({
19
+ cacheToolsList: options.cacheToolsList,
20
+ toolFilter: options.toolFilter,
21
+ logger: options.logger ??
22
+ getLogger(DEFAULT_STREAMABLE_HTTP_MCP_CLIENT_LOGGER_NAME),
23
+ });
24
+ this.params = options;
25
+ this.id = options.id || `streamable-http: ${this.params.url}`;
26
+ this.timeout = options.timeout ?? DEFAULT_REQUEST_TIMEOUT_MSEC;
27
+ }
28
+ /**
29
+ * Establishes connection to the MCP server.
30
+ */
31
+ async connect() {
32
+ try {
33
+ this.transport = new StreamableHTTPClientTransport(new URL(this.params.url), {
34
+ authProvider: this.params.authProvider,
35
+ requestInit: this.params.requestInit,
36
+ fetch: this.params.fetch,
37
+ reconnectionOptions: this.params.reconnectionOptions,
38
+ sessionId: this.params.sessionId,
39
+ });
40
+ this.session = new Client({
41
+ name: this.id,
42
+ version: "1.0.0",
43
+ });
44
+ await this.session.connect(this.transport);
45
+ this.serverInitializeResult = {
46
+ serverInfo: { name: this.id, version: "1.0.0" },
47
+ };
48
+ }
49
+ catch (e) {
50
+ this.logger.error("Error initializing MCP server:", e);
51
+ await this.close();
52
+ throw e;
53
+ }
54
+ this.logger.debug(`Connected to MCP server: ${this.id}`);
55
+ }
56
+ /**
57
+ * Closes the connection and cleans up resources.
58
+ */
59
+ async close() {
60
+ if (this.transport) {
61
+ await this.transport.close();
62
+ this.transport = null;
63
+ }
64
+ if (this.session) {
65
+ await this.session.close();
66
+ this.session = null;
67
+ }
68
+ }
69
+ /**
70
+ * Internal implementation: Fetches tools from the server.
71
+ *
72
+ * Cached via the abstract base class.
73
+ */
74
+ async _listTools() {
75
+ if (!this.session) {
76
+ throw new Error("Server not initialized. Make sure you call connect() first.");
77
+ }
78
+ const response = await this.session.listTools();
79
+ this.logger.debug(`Listed tools: ${JSON.stringify(response)}`);
80
+ return ListToolsResultSchema.parse(response).tools;
81
+ }
82
+ /**
83
+ * Executes a tool on the server with the provided arguments.
84
+ */
85
+ async callTool(toolName, args) {
86
+ if (!this.session) {
87
+ throw new Error("Server not initialized. Make sure you call connect() first.");
88
+ }
89
+ const response = await this.session.callTool({
90
+ name: toolName,
91
+ arguments: args ?? {},
92
+ }, undefined, {
93
+ timeout: this.timeout,
94
+ });
95
+ const parsed = CallToolResultSchema.parse(response);
96
+ const result = parsed.content;
97
+ this.logger.debug(`Called tool ${toolName} (args: ${JSON.stringify(args)}, result: ${JSON.stringify(result)})`);
98
+ return result;
99
+ }
100
+ }
@@ -0,0 +1,60 @@
1
+ import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { MCPTool, CallToolResultContent, DefaultMCPServerStdioOptions, InitializeResult, MCPServerSSEOptions, MCPServerStreamableHttpOptions, MCPServerStdioOptions } from "./types";
3
+ export interface SessionMessage {
4
+ message: any;
5
+ }
6
+ export declare class NodeMCPServerStdio extends BaseMCPServerStdio {
7
+ protected session: Client | null;
8
+ protected _cacheDirty: boolean;
9
+ protected _toolsList: any[];
10
+ protected serverInitializeResult: InitializeResult | null;
11
+ protected clientSessionTimeoutSeconds?: number;
12
+ protected timeout: number;
13
+ params: DefaultMCPServerStdioOptions;
14
+ private _name;
15
+ private transport;
16
+ constructor(params: MCPServerStdioOptions);
17
+ connect(): Promise<void>;
18
+ invalidateToolsCache(): Promise<void>;
19
+ listTools(): Promise<MCPTool[]>;
20
+ callTool(toolName: string, args: Record<string, unknown> | null): Promise<CallToolResultContent>;
21
+ get name(): string;
22
+ close(): Promise<void>;
23
+ }
24
+ export declare class NodeMCPServerSSE extends BaseMCPServerSSE {
25
+ protected session: Client | null;
26
+ protected _cacheDirty: boolean;
27
+ protected _toolsList: any[];
28
+ protected serverInitializeResult: InitializeResult | null;
29
+ protected clientSessionTimeoutSeconds?: number;
30
+ protected timeout: number;
31
+ params: MCPServerSSEOptions;
32
+ private _name;
33
+ private transport;
34
+ constructor(params: MCPServerSSEOptions);
35
+ connect(): Promise<void>;
36
+ invalidateToolsCache(): Promise<void>;
37
+ listTools(): Promise<MCPTool[]>;
38
+ callTool(toolName: string, args: Record<string, unknown> | null): Promise<CallToolResultContent>;
39
+ get name(): string;
40
+ close(): Promise<void>;
41
+ }
42
+ export declare class NodeMCPServerStreamableHttp extends BaseMCPServerStreamableHttp {
43
+ protected session: Client | null;
44
+ protected _cacheDirty: boolean;
45
+ protected _toolsList: any[];
46
+ protected serverInitializeResult: InitializeResult | null;
47
+ protected clientSessionTimeoutSeconds?: number;
48
+ protected timeout: number;
49
+ params: MCPServerStreamableHttpOptions;
50
+ private _name;
51
+ private transport;
52
+ constructor(params: MCPServerStreamableHttpOptions);
53
+ connect(): Promise<void>;
54
+ invalidateToolsCache(): Promise<void>;
55
+ listTools(): Promise<MCPTool[]>;
56
+ callTool(toolName: string, args: Record<string, unknown> | null): Promise<CallToolResultContent>;
57
+ get name(): string;
58
+ close(): Promise<void>;
59
+ }
60
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/mcp/node.ts"],"names":[],"mappings":"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"}