@dobbyai/mcp-external 1.0.4 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (315) hide show
  1. package/README.md +44 -14
  2. package/dist/__tests__/agent-mail-tools.test.d.ts +8 -0
  3. package/dist/__tests__/agent-mail-tools.test.d.ts.map +1 -0
  4. package/dist/__tests__/agent-mail-tools.test.js +255 -0
  5. package/dist/__tests__/agent-mail-tools.test.js.map +1 -0
  6. package/dist/__tests__/annotations.test.d.ts +8 -0
  7. package/dist/__tests__/annotations.test.d.ts.map +1 -0
  8. package/dist/__tests__/annotations.test.js +108 -0
  9. package/dist/__tests__/annotations.test.js.map +1 -0
  10. package/dist/__tests__/auth.test.d.ts +7 -0
  11. package/dist/__tests__/auth.test.d.ts.map +1 -0
  12. package/dist/__tests__/auth.test.js +161 -0
  13. package/dist/__tests__/auth.test.js.map +1 -0
  14. package/dist/__tests__/doctor.test.d.ts +16 -0
  15. package/dist/__tests__/doctor.test.d.ts.map +1 -0
  16. package/dist/__tests__/doctor.test.js +258 -0
  17. package/dist/__tests__/doctor.test.js.map +1 -0
  18. package/dist/__tests__/external-agents-tools.test.d.ts +11 -0
  19. package/dist/__tests__/external-agents-tools.test.d.ts.map +1 -0
  20. package/dist/__tests__/external-agents-tools.test.js +619 -0
  21. package/dist/__tests__/external-agents-tools.test.js.map +1 -0
  22. package/dist/__tests__/gateway-bearer.test.d.ts +12 -0
  23. package/dist/__tests__/gateway-bearer.test.d.ts.map +1 -0
  24. package/dist/__tests__/gateway-bearer.test.js +112 -0
  25. package/dist/__tests__/gateway-bearer.test.js.map +1 -0
  26. package/dist/__tests__/gateway-key-resolver.test.d.ts +10 -0
  27. package/dist/__tests__/gateway-key-resolver.test.d.ts.map +1 -0
  28. package/dist/__tests__/gateway-key-resolver.test.js +125 -0
  29. package/dist/__tests__/gateway-key-resolver.test.js.map +1 -0
  30. package/dist/__tests__/http-concurrency.test.d.ts +20 -0
  31. package/dist/__tests__/http-concurrency.test.d.ts.map +1 -0
  32. package/dist/__tests__/http-concurrency.test.js +254 -0
  33. package/dist/__tests__/http-concurrency.test.js.map +1 -0
  34. package/dist/__tests__/integration/protocol.test.d.ts +8 -0
  35. package/dist/__tests__/integration/protocol.test.d.ts.map +1 -0
  36. package/dist/__tests__/integration/protocol.test.js +110 -0
  37. package/dist/__tests__/integration/protocol.test.js.map +1 -0
  38. package/dist/__tests__/mcp-integrations.test.d.ts +8 -0
  39. package/dist/__tests__/mcp-integrations.test.d.ts.map +1 -0
  40. package/dist/__tests__/mcp-integrations.test.js +365 -0
  41. package/dist/__tests__/mcp-integrations.test.js.map +1 -0
  42. package/dist/__tests__/memory-graph-tools.test.d.ts +8 -0
  43. package/dist/__tests__/memory-graph-tools.test.d.ts.map +1 -0
  44. package/dist/__tests__/memory-graph-tools.test.js +254 -0
  45. package/dist/__tests__/memory-graph-tools.test.js.map +1 -0
  46. package/dist/__tests__/registry-dispatch.test.d.ts +11 -0
  47. package/dist/__tests__/registry-dispatch.test.d.ts.map +1 -0
  48. package/dist/__tests__/registry-dispatch.test.js +30 -0
  49. package/dist/__tests__/registry-dispatch.test.js.map +1 -0
  50. package/dist/__tests__/registry-listing-parity.test.d.ts +2 -0
  51. package/dist/__tests__/registry-listing-parity.test.d.ts.map +1 -0
  52. package/dist/__tests__/registry-listing-parity.test.js +89 -0
  53. package/dist/__tests__/registry-listing-parity.test.js.map +1 -0
  54. package/dist/__tests__/role-cap.test.d.ts +2 -0
  55. package/dist/__tests__/role-cap.test.d.ts.map +1 -0
  56. package/dist/__tests__/role-cap.test.js +113 -0
  57. package/dist/__tests__/role-cap.test.js.map +1 -0
  58. package/dist/__tests__/schedule-tools.test.d.ts +8 -0
  59. package/dist/__tests__/schedule-tools.test.d.ts.map +1 -0
  60. package/dist/__tests__/schedule-tools.test.js +285 -0
  61. package/dist/__tests__/schedule-tools.test.js.map +1 -0
  62. package/dist/__tests__/server-gateway-key.test.d.ts +18 -0
  63. package/dist/__tests__/server-gateway-key.test.d.ts.map +1 -0
  64. package/dist/__tests__/server-gateway-key.test.js +148 -0
  65. package/dist/__tests__/server-gateway-key.test.js.map +1 -0
  66. package/dist/__tests__/server-user-scoped.test.d.ts +34 -0
  67. package/dist/__tests__/server-user-scoped.test.d.ts.map +1 -0
  68. package/dist/__tests__/server-user-scoped.test.js +577 -0
  69. package/dist/__tests__/server-user-scoped.test.js.map +1 -0
  70. package/dist/__tests__/task-id-pattern.test.d.ts +12 -0
  71. package/dist/__tests__/task-id-pattern.test.d.ts.map +1 -0
  72. package/dist/__tests__/task-id-pattern.test.js +43 -0
  73. package/dist/__tests__/task-id-pattern.test.js.map +1 -0
  74. package/dist/__tests__/tiers.test.d.ts +7 -0
  75. package/dist/__tests__/tiers.test.d.ts.map +1 -0
  76. package/dist/__tests__/tiers.test.js +199 -0
  77. package/dist/__tests__/tiers.test.js.map +1 -0
  78. package/dist/__tests__/tools/hosted-agents.test.d.ts +9 -0
  79. package/dist/__tests__/tools/hosted-agents.test.d.ts.map +1 -0
  80. package/dist/__tests__/tools/hosted-agents.test.js +301 -0
  81. package/dist/__tests__/tools/hosted-agents.test.js.map +1 -0
  82. package/dist/__tests__/tools/llm-providers.test.d.ts +10 -0
  83. package/dist/__tests__/tools/llm-providers.test.d.ts.map +1 -0
  84. package/dist/__tests__/tools/llm-providers.test.js +105 -0
  85. package/dist/__tests__/tools/llm-providers.test.js.map +1 -0
  86. package/dist/__tests__/tools/services.test.js +139 -98
  87. package/dist/__tests__/tools/services.test.js.map +1 -1
  88. package/dist/__tests__/tools.test.d.ts +7 -0
  89. package/dist/__tests__/tools.test.d.ts.map +1 -0
  90. package/dist/__tests__/tools.test.js +152 -0
  91. package/dist/__tests__/tools.test.js.map +1 -0
  92. package/dist/__tests__/transport.test.d.ts +7 -0
  93. package/dist/__tests__/transport.test.d.ts.map +1 -0
  94. package/dist/__tests__/transport.test.js +397 -0
  95. package/dist/__tests__/transport.test.js.map +1 -0
  96. package/dist/__tests__/validate-credentials.test.d.ts +9 -0
  97. package/dist/__tests__/validate-credentials.test.d.ts.map +1 -0
  98. package/dist/__tests__/validate-credentials.test.js +172 -0
  99. package/dist/__tests__/validate-credentials.test.js.map +1 -0
  100. package/dist/__tests__/web-eval-tools.test.d.ts +8 -0
  101. package/dist/__tests__/web-eval-tools.test.d.ts.map +1 -0
  102. package/dist/__tests__/web-eval-tools.test.js +241 -0
  103. package/dist/__tests__/web-eval-tools.test.js.map +1 -0
  104. package/dist/__tests__/whoami.test.d.ts +11 -0
  105. package/dist/__tests__/whoami.test.d.ts.map +1 -0
  106. package/dist/__tests__/whoami.test.js +194 -0
  107. package/dist/__tests__/whoami.test.js.map +1 -0
  108. package/dist/__tests__/workflow-tools.test.d.ts +8 -0
  109. package/dist/__tests__/workflow-tools.test.d.ts.map +1 -0
  110. package/dist/__tests__/workflow-tools.test.js +261 -0
  111. package/dist/__tests__/workflow-tools.test.js.map +1 -0
  112. package/dist/__tests__/workloads.test.d.ts +9 -0
  113. package/dist/__tests__/workloads.test.d.ts.map +1 -0
  114. package/dist/__tests__/workloads.test.js +169 -0
  115. package/dist/__tests__/workloads.test.js.map +1 -0
  116. package/dist/auth/oauth-provider.d.ts +34 -0
  117. package/dist/auth/oauth-provider.d.ts.map +1 -0
  118. package/dist/auth/oauth-provider.js +75 -0
  119. package/dist/auth/oauth-provider.js.map +1 -0
  120. package/dist/auth/token-verifier.d.ts +45 -0
  121. package/dist/auth/token-verifier.d.ts.map +1 -0
  122. package/dist/auth/token-verifier.js +160 -0
  123. package/dist/auth/token-verifier.js.map +1 -0
  124. package/dist/connectors/claude-desktop.d.ts.map +1 -1
  125. package/dist/connectors/claude-desktop.js +3 -2
  126. package/dist/connectors/claude-desktop.js.map +1 -1
  127. package/dist/connectors/cursor.d.ts.map +1 -1
  128. package/dist/connectors/cursor.js +3 -2
  129. package/dist/connectors/cursor.js.map +1 -1
  130. package/dist/connectors/setup.d.ts.map +1 -1
  131. package/dist/connectors/setup.js +2 -1
  132. package/dist/connectors/setup.js.map +1 -1
  133. package/dist/connectors/vscode.d.ts.map +1 -1
  134. package/dist/connectors/vscode.js +3 -2
  135. package/dist/connectors/vscode.js.map +1 -1
  136. package/dist/connectors/windsurf.d.ts.map +1 -1
  137. package/dist/connectors/windsurf.js +3 -2
  138. package/dist/connectors/windsurf.js.map +1 -1
  139. package/dist/doctor.d.ts +34 -0
  140. package/dist/doctor.d.ts.map +1 -0
  141. package/dist/doctor.js +134 -0
  142. package/dist/doctor.js.map +1 -0
  143. package/dist/http-server.d.ts +56 -0
  144. package/dist/http-server.d.ts.map +1 -0
  145. package/dist/http-server.js +455 -0
  146. package/dist/http-server.js.map +1 -0
  147. package/dist/index.d.ts +5 -1
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +96 -171
  150. package/dist/index.js.map +1 -1
  151. package/dist/lib/consts.d.ts +21 -0
  152. package/dist/lib/consts.d.ts.map +1 -0
  153. package/dist/lib/consts.js +30 -0
  154. package/dist/lib/consts.js.map +1 -0
  155. package/dist/lib/dobby-client.d.ts +60 -3
  156. package/dist/lib/dobby-client.d.ts.map +1 -1
  157. package/dist/lib/dobby-client.js +145 -44
  158. package/dist/lib/dobby-client.js.map +1 -1
  159. package/dist/lib/gateway-key-resolver.d.ts +38 -0
  160. package/dist/lib/gateway-key-resolver.d.ts.map +1 -0
  161. package/dist/lib/gateway-key-resolver.js +59 -0
  162. package/dist/lib/gateway-key-resolver.js.map +1 -0
  163. package/dist/lib/log.d.ts +25 -0
  164. package/dist/lib/log.d.ts.map +1 -0
  165. package/dist/lib/log.js +36 -0
  166. package/dist/lib/log.js.map +1 -0
  167. package/dist/server.d.ts +175 -0
  168. package/dist/server.d.ts.map +1 -0
  169. package/dist/server.js +1017 -0
  170. package/dist/server.js.map +1 -0
  171. package/dist/tools/agent-mail.d.ts +112 -0
  172. package/dist/tools/agent-mail.d.ts.map +1 -0
  173. package/dist/tools/agent-mail.js +118 -0
  174. package/dist/tools/agent-mail.js.map +1 -0
  175. package/dist/tools/agent-versions.d.ts +93 -0
  176. package/dist/tools/agent-versions.d.ts.map +1 -0
  177. package/dist/tools/agent-versions.js +99 -0
  178. package/dist/tools/agent-versions.js.map +1 -0
  179. package/dist/tools/approvals.d.ts +24 -34
  180. package/dist/tools/approvals.d.ts.map +1 -1
  181. package/dist/tools/approvals.js +24 -81
  182. package/dist/tools/approvals.js.map +1 -1
  183. package/dist/tools/claude-code-sync.d.ts +40 -0
  184. package/dist/tools/claude-code-sync.d.ts.map +1 -0
  185. package/dist/tools/claude-code-sync.js +52 -0
  186. package/dist/tools/claude-code-sync.js.map +1 -0
  187. package/dist/tools/control-plane.d.ts +118 -0
  188. package/dist/tools/control-plane.d.ts.map +1 -0
  189. package/dist/tools/control-plane.js +135 -0
  190. package/dist/tools/control-plane.js.map +1 -0
  191. package/dist/tools/crew-builder.d.ts +24 -66
  192. package/dist/tools/crew-builder.d.ts.map +1 -1
  193. package/dist/tools/crew-builder.js +24 -185
  194. package/dist/tools/crew-builder.js.map +1 -1
  195. package/dist/tools/crewai.d.ts +24 -63
  196. package/dist/tools/crewai.d.ts.map +1 -1
  197. package/dist/tools/crewai.js +24 -145
  198. package/dist/tools/crewai.js.map +1 -1
  199. package/dist/tools/exa.d.ts +126 -0
  200. package/dist/tools/exa.d.ts.map +1 -0
  201. package/dist/tools/exa.js +125 -0
  202. package/dist/tools/exa.js.map +1 -0
  203. package/dist/tools/external-agents.d.ts +440 -0
  204. package/dist/tools/external-agents.d.ts.map +1 -0
  205. package/dist/tools/external-agents.js +386 -0
  206. package/dist/tools/external-agents.js.map +1 -0
  207. package/dist/tools/github-mcp.d.ts +228 -0
  208. package/dist/tools/github-mcp.d.ts.map +1 -0
  209. package/dist/tools/github-mcp.js +235 -0
  210. package/dist/tools/github-mcp.js.map +1 -0
  211. package/dist/tools/governance.d.ts +273 -0
  212. package/dist/tools/governance.d.ts.map +1 -0
  213. package/dist/tools/governance.js +286 -0
  214. package/dist/tools/governance.js.map +1 -0
  215. package/dist/tools/hosted-agents.d.ts +216 -0
  216. package/dist/tools/hosted-agents.d.ts.map +1 -0
  217. package/dist/tools/hosted-agents.js +214 -0
  218. package/dist/tools/hosted-agents.js.map +1 -0
  219. package/dist/tools/index.d.ts +6335 -191
  220. package/dist/tools/index.d.ts.map +1 -1
  221. package/dist/tools/index.js +441 -172
  222. package/dist/tools/index.js.map +1 -1
  223. package/dist/tools/jira.d.ts +60 -176
  224. package/dist/tools/jira.d.ts.map +1 -1
  225. package/dist/tools/jira.js +60 -365
  226. package/dist/tools/jira.js.map +1 -1
  227. package/dist/tools/llm-providers.d.ts +50 -0
  228. package/dist/tools/llm-providers.d.ts.map +1 -0
  229. package/dist/tools/llm-providers.js +41 -0
  230. package/dist/tools/llm-providers.js.map +1 -0
  231. package/dist/tools/mcp-metrics.d.ts +47 -0
  232. package/dist/tools/mcp-metrics.d.ts.map +1 -0
  233. package/dist/tools/mcp-metrics.js +53 -0
  234. package/dist/tools/mcp-metrics.js.map +1 -0
  235. package/dist/tools/mcp-tools.d.ts +12 -29
  236. package/dist/tools/mcp-tools.d.ts.map +1 -1
  237. package/dist/tools/mcp-tools.js +12 -131
  238. package/dist/tools/mcp-tools.js.map +1 -1
  239. package/dist/tools/mem0.d.ts +127 -0
  240. package/dist/tools/mem0.d.ts.map +1 -0
  241. package/dist/tools/mem0.js +155 -0
  242. package/dist/tools/mem0.js.map +1 -0
  243. package/dist/tools/memory-graph.d.ts +151 -0
  244. package/dist/tools/memory-graph.d.ts.map +1 -0
  245. package/dist/tools/memory-graph.js +159 -0
  246. package/dist/tools/memory-graph.js.map +1 -0
  247. package/dist/tools/memory-stores.d.ts +141 -0
  248. package/dist/tools/memory-stores.d.ts.map +1 -0
  249. package/dist/tools/memory-stores.js +147 -0
  250. package/dist/tools/memory-stores.js.map +1 -0
  251. package/dist/tools/messages.d.ts +12 -20
  252. package/dist/tools/messages.d.ts.map +1 -1
  253. package/dist/tools/messages.js +12 -49
  254. package/dist/tools/messages.js.map +1 -1
  255. package/dist/tools/moltbook.d.ts +328 -0
  256. package/dist/tools/moltbook.d.ts.map +1 -0
  257. package/dist/tools/moltbook.js +334 -0
  258. package/dist/tools/moltbook.js.map +1 -0
  259. package/dist/tools/monitoring-attribution.d.ts +71 -0
  260. package/dist/tools/monitoring-attribution.d.ts.map +1 -0
  261. package/dist/tools/monitoring-attribution.js +74 -0
  262. package/dist/tools/monitoring-attribution.js.map +1 -0
  263. package/dist/tools/ops.d.ts +139 -0
  264. package/dist/tools/ops.d.ts.map +1 -0
  265. package/dist/tools/ops.js +151 -0
  266. package/dist/tools/ops.js.map +1 -0
  267. package/dist/tools/orchestrations.d.ts +109 -0
  268. package/dist/tools/orchestrations.d.ts.map +1 -0
  269. package/dist/tools/orchestrations.js +115 -0
  270. package/dist/tools/orchestrations.js.map +1 -0
  271. package/dist/tools/outcomes.d.ts +138 -0
  272. package/dist/tools/outcomes.d.ts.map +1 -0
  273. package/dist/tools/outcomes.js +136 -0
  274. package/dist/tools/outcomes.js.map +1 -0
  275. package/dist/tools/schedules.d.ts +149 -0
  276. package/dist/tools/schedules.d.ts.map +1 -0
  277. package/dist/tools/schedules.js +155 -0
  278. package/dist/tools/schedules.js.map +1 -0
  279. package/dist/tools/services.d.ts +6 -16
  280. package/dist/tools/services.d.ts.map +1 -1
  281. package/dist/tools/services.js +6 -135
  282. package/dist/tools/services.js.map +1 -1
  283. package/dist/tools/sessions.d.ts +124 -0
  284. package/dist/tools/sessions.d.ts.map +1 -0
  285. package/dist/tools/sessions.js +130 -0
  286. package/dist/tools/sessions.js.map +1 -0
  287. package/dist/tools/setup-status.d.ts +29 -0
  288. package/dist/tools/setup-status.d.ts.map +1 -0
  289. package/dist/tools/setup-status.js +35 -0
  290. package/dist/tools/setup-status.js.map +1 -0
  291. package/dist/tools/tasks.d.ts +44 -56
  292. package/dist/tools/tasks.d.ts.map +1 -1
  293. package/dist/tools/tasks.js +48 -212
  294. package/dist/tools/tasks.js.map +1 -1
  295. package/dist/tools/tiers.d.ts +55 -0
  296. package/dist/tools/tiers.d.ts.map +1 -0
  297. package/dist/tools/tiers.js +239 -0
  298. package/dist/tools/tiers.js.map +1 -0
  299. package/dist/tools/unified-agents.d.ts +43 -0
  300. package/dist/tools/unified-agents.d.ts.map +1 -0
  301. package/dist/tools/unified-agents.js +46 -0
  302. package/dist/tools/unified-agents.js.map +1 -0
  303. package/dist/tools/web-eval.d.ts +129 -0
  304. package/dist/tools/web-eval.d.ts.map +1 -0
  305. package/dist/tools/web-eval.js +136 -0
  306. package/dist/tools/web-eval.js.map +1 -0
  307. package/dist/tools/workflow.d.ts +105 -0
  308. package/dist/tools/workflow.d.ts.map +1 -0
  309. package/dist/tools/workflow.js +111 -0
  310. package/dist/tools/workflow.js.map +1 -0
  311. package/dist/tools/workloads.d.ts +81 -0
  312. package/dist/tools/workloads.d.ts.map +1 -0
  313. package/dist/tools/workloads.js +81 -0
  314. package/dist/tools/workloads.js.map +1 -0
  315. package/package.json +13 -7
@@ -0,0 +1,152 @@
1
+ /**
2
+ * MCP Tools Index Tests
3
+ *
4
+ * Verifies tool definitions, routing, and MCP response format.
5
+ */
6
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
7
+ import { allTools, getToolDefinitions, handleToolCall } from '../tools/index.js';
8
+ import { MVP_TOOLS, PRO_TOOLS } from '../tools/tiers.js';
9
+ // Mock DobbyClient
10
+ const mockClient = {
11
+ apiUrl: 'http://localhost:3000',
12
+ apiKey: 'test-key',
13
+ tenantId: 'tenant_test',
14
+ get: vi.fn(),
15
+ post: vi.fn(),
16
+ put: vi.fn(),
17
+ patch: vi.fn(),
18
+ delete: vi.fn(),
19
+ listTasks: vi.fn(),
20
+ };
21
+ const mockContext = {
22
+ client: mockClient,
23
+ userId: 'user_test',
24
+ userName: 'Test User',
25
+ };
26
+ describe('Tools Index', () => {
27
+ beforeEach(() => {
28
+ vi.clearAllMocks();
29
+ });
30
+ describe('allTools', () => {
31
+ it('exports all tools as a flat object', () => {
32
+ expect(typeof allTools).toBe('object');
33
+ expect(Object.keys(allTools).length).toBeGreaterThan(80);
34
+ });
35
+ it('every tool has required MCP fields', () => {
36
+ for (const [name, tool] of Object.entries(allTools)) {
37
+ expect(tool.name, `${name} missing name`).toBe(name);
38
+ expect(typeof tool.description, `${name} missing description`).toBe('string');
39
+ expect(tool.inputSchema, `${name} missing inputSchema`).toBeDefined();
40
+ expect(tool.inputSchema.type, `${name} inputSchema.type not object`).toBe('object');
41
+ }
42
+ });
43
+ it('every tool name is unique', () => {
44
+ const names = Object.keys(allTools);
45
+ expect(new Set(names).size).toBe(names.length);
46
+ });
47
+ it('tool descriptions are non-empty', () => {
48
+ for (const [name, tool] of Object.entries(allTools)) {
49
+ expect(tool.description.length, `${name} has empty description`).toBeGreaterThan(10);
50
+ }
51
+ });
52
+ it('tool inputSchema has properties', () => {
53
+ for (const [name, tool] of Object.entries(allTools)) {
54
+ expect(tool.inputSchema.properties, `${name} missing inputSchema.properties`).toBeDefined();
55
+ }
56
+ });
57
+ });
58
+ describe('getToolDefinitions', () => {
59
+ it('returns tool definitions for enterprise tier (all tools)', () => {
60
+ // "All tools" = the full catalog, reachable by a superadmin. A normal
61
+ // enterprise principal is hidden the 5 superAdminOnly ops tools
62
+ // (capability-core 0.1.2) — see the sibling test below.
63
+ const defs = getToolDefinitions('enterprise', { isSuperAdmin: true });
64
+ expect(defs.length).toBe(Object.keys(allTools).length);
65
+ });
66
+ it('hides the 5 superAdminOnly ops tools from a normal enterprise principal', () => {
67
+ const OPS_SUPERADMIN_ONLY = 5;
68
+ const defs = getToolDefinitions('enterprise');
69
+ expect(defs.length).toBe(Object.keys(allTools).length - OPS_SUPERADMIN_ONLY);
70
+ });
71
+ it('returns tool definitions for mvp tier (full MVP allowlist)', () => {
72
+ // Exact counts are pinned once, in tiers.test.ts ("tier sizes").
73
+ const defs = getToolDefinitions('mvp');
74
+ expect(defs.length).toBe(MVP_TOOLS.length);
75
+ });
76
+ it('returns tool definitions for pro tier (full Pro allowlist)', () => {
77
+ const defs = getToolDefinitions('pro');
78
+ expect(defs.length).toBe(PRO_TOOLS.length);
79
+ });
80
+ it('defaults to enterprise when no tier provided', () => {
81
+ // Default tier is enterprise; as a superadmin that yields the full catalog.
82
+ const defs = getToolDefinitions(undefined, { isSuperAdmin: true });
83
+ expect(defs.length).toBe(Object.keys(allTools).length);
84
+ });
85
+ it('each definition has name, description, inputSchema, annotations', () => {
86
+ const defs = getToolDefinitions('mvp');
87
+ for (const def of defs) {
88
+ expect(def.name).toBeDefined();
89
+ expect(def.description).toBeDefined();
90
+ expect(def.inputSchema).toBeDefined();
91
+ expect(def.annotations).toBeDefined();
92
+ }
93
+ });
94
+ it('mvp definitions only contain mvp tools', () => {
95
+ const defs = getToolDefinitions('mvp');
96
+ const mvpSet = new Set(MVP_TOOLS);
97
+ for (const def of defs) {
98
+ expect(mvpSet.has(def.name), `${def.name} is not an MVP tool`).toBe(true);
99
+ }
100
+ });
101
+ });
102
+ describe('handleToolCall', () => {
103
+ it('returns error for unknown tool', async () => {
104
+ const result = await handleToolCall('nonexistent_tool', {}, mockContext);
105
+ expect(result.isError).toBe(true);
106
+ expect(result.content[0].text).toContain('Unknown tool');
107
+ });
108
+ it('returns denied result when gateway auth fails', async () => {
109
+ const contextWithGateway = {
110
+ ...mockContext,
111
+ gatewayKey: 'gk_test_123',
112
+ gatewayUrl: 'http://localhost:3000',
113
+ };
114
+ // Mock fetch to return auth denied
115
+ global.fetch = vi.fn().mockResolvedValue({
116
+ ok: false,
117
+ json: () => Promise.resolve({ error: 'Insufficient scope' }),
118
+ });
119
+ const result = await handleToolCall('list_tasks', {}, contextWithGateway);
120
+ expect(result.isError).toBe(true);
121
+ expect(result.content[0].text).toContain('denied');
122
+ });
123
+ it('passes through to handler when no gateway configured', async () => {
124
+ mockClient.listTasks.mockResolvedValue([]);
125
+ const result = await handleToolCall('list_tasks', { status: 'open' }, mockContext);
126
+ // Should not error (gateway auth is skipped)
127
+ expect(result).toBeDefined();
128
+ });
129
+ it('catches handler errors and wraps in MCP error format', async () => {
130
+ mockClient.listTasks.mockRejectedValue(new Error('Network error'));
131
+ const result = await handleToolCall('list_tasks', {}, mockContext);
132
+ expect(result.isError).toBe(true);
133
+ expect(result.content[0].text).toContain('Network error');
134
+ });
135
+ it('exposes every tool name in allTools', () => {
136
+ // Structural sanity: the definitions map stays populated. Dispatch
137
+ // coverage lives in the registry alignment/dispatch tests.
138
+ const toolNames = Object.keys(allTools);
139
+ expect(toolNames.length).toBeGreaterThan(80);
140
+ });
141
+ });
142
+ describe('GatewayAuthResult', () => {
143
+ it('allows when no gateway key configured', async () => {
144
+ mockClient.listTasks.mockResolvedValue([]);
145
+ const result = await handleToolCall('list_tasks', {}, mockContext);
146
+ // Should succeed since no gateway auth required
147
+ expect(result).toBeDefined();
148
+ expect(result.isError).toBeUndefined();
149
+ });
150
+ });
151
+ });
152
+ //# sourceMappingURL=tools.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.test.js","sourceRoot":"","sources":["../../src/__tests__/tools.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * MCP Transport Tests
3
+ *
4
+ * Tests for STDIO and HTTP transport initialization.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=transport.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/transport.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,397 @@
1
+ /**
2
+ * MCP Transport Tests
3
+ *
4
+ * Tests for STDIO and HTTP transport initialization.
5
+ */
6
+ import { describe, it, expect } from "vitest";
7
+ import cors from "cors";
8
+ import { corsOptions } from "../http-server.js";
9
+ // We test the HTTP server module's structure and health endpoint behavior
10
+ describe("HTTP Transport", () => {
11
+ it("http-server module exports startHttpServer function", async () => {
12
+ const mod = await import("../http-server.js");
13
+ expect(typeof mod.startHttpServer).toBe("function");
14
+ });
15
+ it("HttpServerConfig interface requires all fields", () => {
16
+ // Structural test — TypeScript enforces this at compile time
17
+ // This test verifies the module is importable
18
+ const config = {
19
+ port: 8080,
20
+ issuerUrl: "https://dobby-ai.com",
21
+ mcpPublicUrl: "https://mcp.dobby-ai.com",
22
+ createMcpServer: async () => ({}),
23
+ };
24
+ expect(config.port).toBe(8080);
25
+ });
26
+ });
27
+ describe("STDIO Transport", () => {
28
+ it("index module exports createServer entry point", async () => {
29
+ // Verify the main entry point can be imported
30
+ const mod = await import("../tools/index.js");
31
+ expect(mod.allTools).toBeDefined();
32
+ expect(mod.getToolDefinitions).toBeDefined();
33
+ expect(mod.handleToolCall).toBeDefined();
34
+ });
35
+ });
36
+ describe("Transport Selection", () => {
37
+ it("CLI supports --transport stdio and http options", () => {
38
+ // Both STDIO (default) and HTTP transport modes are supported.
39
+ // index.ts is the CLI entry point — importing it triggers program.parse()
40
+ // and main(), which is not safe in test environments. Transport behavior
41
+ // is covered by the http-server and tools/index tests above.
42
+ expect(true).toBe(true);
43
+ });
44
+ it("http-server creates Express app with correct routes", async () => {
45
+ // Verify the module structure
46
+ const mod = await import("../http-server.js");
47
+ expect(mod.startHttpServer).toBeDefined();
48
+ });
49
+ it("auth modules are properly structured", async () => {
50
+ const oauth = await import("../auth/oauth-provider.js");
51
+ const verifier = await import("../auth/token-verifier.js");
52
+ expect(oauth.createOAuthProvider).toBeDefined();
53
+ expect(verifier.TokenVerifier).toBeDefined();
54
+ });
55
+ });
56
+ describe("CORS policy", () => {
57
+ // Run the real `cors` middleware against a mock request and capture the
58
+ // response headers it emits — reproduces `curl -H "Origin: ..."` in-process.
59
+ function runCorsHeaders(method, origin) {
60
+ return new Promise((resolve) => {
61
+ const headers = {};
62
+ const req = { method, headers: { origin } };
63
+ const res = {
64
+ statusCode: 200,
65
+ setHeader: (k, v) => {
66
+ headers[k.toLowerCase()] = String(v);
67
+ },
68
+ getHeader: (k) => headers[k.toLowerCase()],
69
+ end: () => resolve(headers),
70
+ };
71
+ cors(corsOptions)(req, res, () => resolve(headers));
72
+ });
73
+ }
74
+ it("disables credentials so reflecting any origin is not exploitable", () => {
75
+ // The dangerous combo is reflect-any-origin + credentials:true. Auth here is
76
+ // header Bearer tokens, never cookies, so credentials must stay off.
77
+ expect(corsOptions.credentials).toBe(false);
78
+ });
79
+ it("never returns access-control-allow-credentials for an evil origin (GET)", async () => {
80
+ const headers = await runCorsHeaders("GET", "https://evil-attacker.com");
81
+ // Origin is still reflected (no legitimate client breaks)...
82
+ expect(headers["access-control-allow-origin"]).toBe("https://evil-attacker.com");
83
+ // ...but credentials are NOT granted — the security-relevant assertion.
84
+ expect(headers["access-control-allow-credentials"]).toBeUndefined();
85
+ });
86
+ it("never returns access-control-allow-credentials on a preflight (OPTIONS)", async () => {
87
+ const headers = await runCorsHeaders("OPTIONS", "https://evil-attacker.com");
88
+ expect(headers["access-control-allow-origin"]).toBe("https://evil-attacker.com");
89
+ expect(headers["access-control-allow-credentials"]).toBeUndefined();
90
+ });
91
+ });
92
+ describe("Session lifecycle (integration)", () => {
93
+ // Regression for the 2026-07-12 prod bug: sessions were stored by checking
94
+ // transport.sessionId right after connect(), but the SDK only assigns it
95
+ // while handleRequest processes the initialize message — so no session was
96
+ // ever registered and every follow-up request 404'd "Session not found".
97
+ // This spins up a stub issuer + the real HTTP server and drives
98
+ // initialize → ping through a real session.
99
+ async function withServers(run, introspection = {}) {
100
+ const express = (await import("express")).default;
101
+ const { Server } = await import("@modelcontextprotocol/sdk/server/index.js");
102
+ const { startHttpServer } = await import("../http-server.js");
103
+ // Stub issuer serving the introspection endpoint the TokenVerifier calls
104
+ const issuer = express();
105
+ issuer.use(express.json());
106
+ issuer.post("/oauth/token/introspect", (_req, res) => {
107
+ res.json({
108
+ active: true,
109
+ user_id: "pu_it",
110
+ org_id: "org_it",
111
+ tenant_id: "tenant_it",
112
+ scope: "mcp:*",
113
+ client_id: "key_it",
114
+ exp: Math.floor(Date.now() / 1000) + 3600,
115
+ ...introspection,
116
+ });
117
+ });
118
+ const issuerServer = issuer.listen(0);
119
+ const issuerPort = issuerServer.address().port;
120
+ const { server, tokenVerifier } = await startHttpServer({
121
+ port: 0,
122
+ issuerUrl: `http://127.0.0.1:${issuerPort}`,
123
+ mcpPublicUrl: "http://127.0.0.1:0",
124
+ createMcpServer: async () => new Server({ name: "it-server", version: "0.0.0" }, { capabilities: { tools: {} } }),
125
+ });
126
+ const mcpPort = server.address().port;
127
+ try {
128
+ await run(`http://127.0.0.1:${mcpPort}/mcp`);
129
+ }
130
+ finally {
131
+ tokenVerifier.clearCache();
132
+ server.close();
133
+ issuerServer.close();
134
+ }
135
+ }
136
+ const rpcHeaders = {
137
+ Authorization: "Bearer sk_live_it_test",
138
+ "Content-Type": "application/json",
139
+ Accept: "application/json, text/event-stream",
140
+ };
141
+ async function initialize(mcpUrl) {
142
+ return fetch(mcpUrl, {
143
+ method: "POST",
144
+ headers: rpcHeaders,
145
+ body: JSON.stringify({
146
+ jsonrpc: "2.0",
147
+ id: 1,
148
+ method: "initialize",
149
+ params: {
150
+ protocolVersion: "2025-03-26",
151
+ capabilities: {},
152
+ clientInfo: { name: "it-probe", version: "0" },
153
+ },
154
+ }),
155
+ });
156
+ }
157
+ it("registers the session during initialize — follow-up requests find it", async () => {
158
+ await withServers(async (mcpUrl) => {
159
+ const initRes = await initialize(mcpUrl);
160
+ expect(initRes.status).toBe(200);
161
+ const sessionId = initRes.headers.get("mcp-session-id");
162
+ expect(sessionId).toBeTruthy();
163
+ // Follow-up on the SAME session must NOT be "Session not found"
164
+ const pingRes = await fetch(mcpUrl, {
165
+ method: "POST",
166
+ headers: { ...rpcHeaders, "Mcp-Session-Id": sessionId },
167
+ body: JSON.stringify({ jsonrpc: "2.0", id: 2, method: "ping" }),
168
+ });
169
+ expect(pingRes.status).toBe(200);
170
+ const text = await pingRes.text();
171
+ expect(text).not.toContain("Session not found");
172
+ });
173
+ });
174
+ it("rejects an unknown session id with 404", async () => {
175
+ await withServers(async (mcpUrl) => {
176
+ const res = await fetch(mcpUrl, {
177
+ method: "POST",
178
+ headers: { ...rpcHeaders, "Mcp-Session-Id": "no-such-session" },
179
+ body: JSON.stringify({ jsonrpc: "2.0", id: 3, method: "ping" }),
180
+ });
181
+ expect(res.status).toBe(404);
182
+ });
183
+ });
184
+ it("rejects a bearer the issuer reports inactive with 401 (not 500)", async () => {
185
+ await withServers(async (mcpUrl) => {
186
+ const res = await initialize(mcpUrl);
187
+ expect(res.status).toBe(401);
188
+ }, { active: false });
189
+ });
190
+ it("serves a landing page at GET / — JSON for clients, HTML for browsers", async () => {
191
+ await withServers(async (mcpUrl) => {
192
+ const rootUrl = new URL("/", mcpUrl).toString();
193
+ // curl-style client (Accept: */*) → JSON info
194
+ const jsonRes = await fetch(rootUrl);
195
+ expect(jsonRes.status).toBe(200);
196
+ expect(jsonRes.headers.get("content-type")).toContain("application/json");
197
+ const info = (await jsonRes.json());
198
+ expect(info.name).toBe("Dobby MCP Server");
199
+ expect(info.endpoint).toMatch(/\/mcp$/);
200
+ expect(info.documentation).toMatch(/\/docs\/mcp$/);
201
+ expect(info.authentication.bearer).toContain("sk_live_");
202
+ // Browser (Accept: text/html) → HTML landing page
203
+ const htmlRes = await fetch(rootUrl, {
204
+ headers: { Accept: "text/html,application/xhtml+xml" },
205
+ });
206
+ expect(htmlRes.status).toBe(200);
207
+ expect(htmlRes.headers.get("content-type")).toContain("text/html");
208
+ const html = await htmlRes.text();
209
+ expect(html).toContain("Dobby");
210
+ expect(html).toContain("/docs/mcp");
211
+ expect(html).toContain("sk_live_");
212
+ });
213
+ });
214
+ // RFC 9728 / MCP 2025-06-18 auth flow: clients discover the authorization
215
+ // server by reading resource_metadata from the WWW-Authenticate header on
216
+ // 401. Both 401 paths (invalid token, missing header) must carry it.
217
+ it("401 for an invalid bearer carries resource_metadata in WWW-Authenticate", async () => {
218
+ await withServers(async (mcpUrl) => {
219
+ const res = await initialize(mcpUrl);
220
+ expect(res.status).toBe(401);
221
+ const wwwAuth = res.headers.get("www-authenticate");
222
+ expect(wwwAuth).toContain('Bearer error="invalid_token"');
223
+ expect(wwwAuth).toContain('resource_metadata="http://127.0.0.1:0/.well-known/oauth-protected-resource"');
224
+ }, { active: false });
225
+ });
226
+ it("401 for a missing Authorization header carries resource_metadata", async () => {
227
+ await withServers(async (mcpUrl) => {
228
+ const res = await fetch(mcpUrl, {
229
+ method: "POST",
230
+ headers: {
231
+ "Content-Type": "application/json",
232
+ Accept: "application/json, text/event-stream",
233
+ },
234
+ body: JSON.stringify({ jsonrpc: "2.0", id: 4, method: "ping" }),
235
+ });
236
+ expect(res.status).toBe(401);
237
+ expect(res.headers.get("www-authenticate")).toContain('resource_metadata="http://127.0.0.1:0/.well-known/oauth-protected-resource"');
238
+ });
239
+ });
240
+ });
241
+ describe("Tool tier enforcement (integration)", () => {
242
+ // End-to-end over the REAL server factory (server.ts): the introspection
243
+ // stub controls the token's effective mcp scope, and we assert that
244
+ // tools/list is filtered AND tools/call is enforced — list filtering
245
+ // without call enforcement is cosmetic.
246
+ /** Spin up a stub issuer + the real HTTP server with the REAL MCP server. */
247
+ async function withRealServer(scope, run, opts = {}) {
248
+ const express = (await import("express")).default;
249
+ const { startHttpServer } = await import("../http-server.js");
250
+ const { createServer } = await import("../server.js");
251
+ const issuer = express();
252
+ issuer.use(express.json());
253
+ issuer.post("/oauth/token/introspect", (_req, res) => {
254
+ res.json({
255
+ active: true,
256
+ user_id: "pu_tier",
257
+ org_id: "org_tier",
258
+ tenant_id: "tenant_tier",
259
+ scope,
260
+ client_id: "key_tier",
261
+ is_super_admin: opts.isSuperAdmin === true,
262
+ exp: Math.floor(Date.now() / 1000) + 3600,
263
+ });
264
+ });
265
+ const issuerServer = issuer.listen(0);
266
+ const issuerPort = issuerServer.address().port;
267
+ const { server, tokenVerifier } = await startHttpServer({
268
+ port: 0,
269
+ issuerUrl: `http://127.0.0.1:${issuerPort}`,
270
+ mcpPublicUrl: "http://127.0.0.1:0",
271
+ createMcpServer: () => createServer({ mode: "http" }),
272
+ });
273
+ const mcpPort = server.address().port;
274
+ const mcpUrl = `http://127.0.0.1:${mcpPort}/mcp`;
275
+ const headers = {
276
+ Authorization: "Bearer sk_live_tier_test",
277
+ "Content-Type": "application/json",
278
+ Accept: "application/json, text/event-stream",
279
+ };
280
+ // Streamable HTTP responses may arrive as SSE — take the last data line.
281
+ const parseRpc = (text) => {
282
+ const dataLines = text
283
+ .split("\n")
284
+ .filter((line) => line.startsWith("data: "));
285
+ if (dataLines.length > 0) {
286
+ return JSON.parse(dataLines[dataLines.length - 1].slice(6));
287
+ }
288
+ return JSON.parse(text);
289
+ };
290
+ try {
291
+ const initRes = await fetch(mcpUrl, {
292
+ method: "POST",
293
+ headers,
294
+ body: JSON.stringify({
295
+ jsonrpc: "2.0",
296
+ id: 1,
297
+ method: "initialize",
298
+ params: {
299
+ protocolVersion: "2025-03-26",
300
+ capabilities: {},
301
+ clientInfo: { name: "tier-probe", version: "0" },
302
+ },
303
+ }),
304
+ });
305
+ expect(initRes.status).toBe(200);
306
+ const sessionId = initRes.headers.get("mcp-session-id");
307
+ const rpc = async (method, params, id) => {
308
+ const res = await fetch(mcpUrl, {
309
+ method: "POST",
310
+ headers: { ...headers, "Mcp-Session-Id": sessionId },
311
+ body: JSON.stringify({ jsonrpc: "2.0", id, method, params }),
312
+ });
313
+ expect(res.status).toBe(200); // enforcement must never surface as 4xx/500
314
+ return parseRpc(await res.text());
315
+ };
316
+ await run(rpc);
317
+ }
318
+ finally {
319
+ tokenVerifier.clearCache();
320
+ server.close();
321
+ issuerServer.close();
322
+ }
323
+ }
324
+ // The synthetic `whoami` + `validate_credentials` tools are appended to EVERY
325
+ // tier's list (always available), so an exact-tier assertion excludes them.
326
+ const SYNTHETIC_TOOLS = ["whoami", "validate_credentials"];
327
+ const tierNames = (data) => data.result.tools.map((t) => t.name).filter((n) => !SYNTHETIC_TOOLS.includes(n));
328
+ it("tools/list for an mvp-scope token returns exactly the MVP tier (+ synthetic)", async () => {
329
+ const { MVP_TOOLS } = await import("../tools/tiers.js");
330
+ await withRealServer("mcp:execute", async (rpc) => {
331
+ const data = await rpc("tools/list", {}, 2);
332
+ const names = data.result.tools.map((t) => t.name);
333
+ expect(names).toEqual(expect.arrayContaining(SYNTHETIC_TOOLS));
334
+ expect(tierNames(data).length).toBe(MVP_TOOLS.length);
335
+ });
336
+ });
337
+ it("tools/list for a pro-scope token returns exactly the Pro tier (+ synthetic)", async () => {
338
+ const { PRO_TOOLS } = await import("../tools/tiers.js");
339
+ await withRealServer("mcp:execute mcp:pro", async (rpc) => {
340
+ const data = await rpc("tools/list", {}, 2);
341
+ const names = data.result.tools.map((t) => t.name);
342
+ expect(names).toEqual(expect.arrayContaining(SYNTHETIC_TOOLS));
343
+ expect(tierNames(data).length).toBe(PRO_TOOLS.length);
344
+ });
345
+ });
346
+ it("tools/list for an enterprise-scope superadmin token returns all tools (+ synthetic)", async () => {
347
+ const { allTools } = await import("../tools/index.js");
348
+ // "All tools" is the FULL catalog — reachable by a superadmin principal.
349
+ // capability-core 0.1.2 hides the 5 superAdminOnly ops tools from every
350
+ // non-superadmin, so a normal enterprise token sees the smaller set
351
+ // (asserted below); the superadmin sees the entire registry.
352
+ await withRealServer("mcp:execute mcp:*", async (rpc) => {
353
+ const data = await rpc("tools/list", {}, 2);
354
+ const names = data.result.tools.map((t) => t.name);
355
+ expect(names).toEqual(expect.arrayContaining(SYNTHETIC_TOOLS));
356
+ expect(tierNames(data).length).toBe(Object.keys(allTools).length);
357
+ }, { isSuperAdmin: true });
358
+ });
359
+ it("tools/list for a non-superadmin enterprise token hides the 5 superAdminOnly ops tools", async () => {
360
+ const { allTools } = await import("../tools/index.js");
361
+ const OPS_SUPERADMIN_ONLY = 5;
362
+ await withRealServer("mcp:execute mcp:*", async (rpc) => {
363
+ const data = await rpc("tools/list", {}, 2);
364
+ const names = data.result.tools.map((t) => t.name);
365
+ expect(names).toEqual(expect.arrayContaining(SYNTHETIC_TOOLS));
366
+ expect(tierNames(data).length).toBe(Object.keys(allTools).length - OPS_SUPERADMIN_ONLY);
367
+ });
368
+ });
369
+ it("tools/list for a read-only token serves only readOnlyHint tools", async () => {
370
+ const { MVP_TOOLS } = await import("../tools/tiers.js");
371
+ await withRealServer("mcp:read", async (rpc) => {
372
+ const data = await rpc("tools/list", {}, 2);
373
+ expect(data.result.tools.length).toBeGreaterThan(0);
374
+ expect(data.result.tools.length).toBeLessThan(MVP_TOOLS.length);
375
+ for (const tool of data.result.tools) {
376
+ expect(tool.annotations?.readOnlyHint, tool.name).toBe(true);
377
+ }
378
+ });
379
+ });
380
+ it("tools/call for an out-of-tier tool returns a clean MCP error, not 500", async () => {
381
+ await withRealServer("mcp:execute", async (rpc) => {
382
+ // jira_search_issues is Pro-tier; the token is mvp
383
+ const data = await rpc("tools/call", { name: "jira_search_issues", arguments: {} }, 3);
384
+ expect(data.result.isError).toBe(true);
385
+ expect(data.result.content[0].text).toContain("not available on your current plan");
386
+ expect(data.result.content[0].text).toContain("pro");
387
+ });
388
+ });
389
+ it("tools/call for a write tool with a read-only token returns a clean MCP error", async () => {
390
+ await withRealServer("mcp:read mcp:*", async (rpc) => {
391
+ const data = await rpc("tools/call", { name: "create_task", arguments: { title: "x" } }, 3);
392
+ expect(data.result.isError).toBe(true);
393
+ expect(data.result.content[0].text).toContain("read-only");
394
+ });
395
+ });
396
+ });
397
+ //# sourceMappingURL=transport.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.test.js","sourceRoot":"","sources":["../../src/__tests__/transport.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Unit tests for the synthetic `validate_credentials` tool.
3
+ *
4
+ * It is the MCP-callable counterpart of `dobby-mcp --doctor`: it confirms the
5
+ * credentials actually work (present / format_ok / authorized) and must NEVER
6
+ * throw — failures are reported as `report.*.authorized=false` + notes.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=validate-credentials.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-credentials.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/validate-credentials.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}