@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,161 @@
1
+ /**
2
+ * MCP Auth Tests
3
+ *
4
+ * Tests for OAuth proxy provider and token verifier.
5
+ */
6
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
+ import { InvalidTokenError, ServerError, } from '@modelcontextprotocol/sdk/server/auth/errors.js';
8
+ import { TokenVerifier } from '../auth/token-verifier.js';
9
+ import { createOAuthProvider } from '../auth/oauth-provider.js';
10
+ describe('TokenVerifier', () => {
11
+ let verifier;
12
+ beforeEach(() => {
13
+ verifier = new TokenVerifier('https://dobby-ai.com');
14
+ vi.restoreAllMocks();
15
+ });
16
+ afterEach(() => {
17
+ verifier.clearCache();
18
+ });
19
+ const validTokenResponse = {
20
+ active: true,
21
+ user_id: 'pu_user123',
22
+ org_id: 'org_abc',
23
+ tenant_id: 'tenant_xyz',
24
+ scope: 'mcp:read mcp:execute',
25
+ client_id: 'mcp_client1',
26
+ exp: Math.floor(Date.now() / 1000) + 3600,
27
+ };
28
+ it('validates a valid token against remote endpoint', async () => {
29
+ global.fetch = vi.fn().mockResolvedValue({
30
+ ok: true,
31
+ json: () => Promise.resolve(validTokenResponse),
32
+ });
33
+ const authInfo = await verifier.verifyAccessToken('dobby_at_valid_token');
34
+ expect(authInfo.token).toBe('dobby_at_valid_token');
35
+ expect(authInfo.clientId).toBe('mcp_client1');
36
+ expect(authInfo.scopes).toEqual(['mcp:read', 'mcp:execute']);
37
+ expect(authInfo.extra?.org_id).toBe('org_abc');
38
+ expect(authInfo.extra?.tenant_id).toBe('tenant_xyz');
39
+ });
40
+ it('caches token verification results', async () => {
41
+ global.fetch = vi.fn().mockResolvedValue({
42
+ ok: true,
43
+ json: () => Promise.resolve(validTokenResponse),
44
+ });
45
+ // First call hits remote
46
+ await verifier.verifyAccessToken('dobby_at_cached_token');
47
+ expect(fetch).toHaveBeenCalledTimes(1);
48
+ // Second call uses cache
49
+ await verifier.verifyAccessToken('dobby_at_cached_token');
50
+ expect(fetch).toHaveBeenCalledTimes(1);
51
+ });
52
+ it('throws InvalidTokenError on invalid/expired token (401) — maps to HTTP 401, not 500', async () => {
53
+ global.fetch = vi.fn().mockResolvedValue({
54
+ ok: false,
55
+ status: 401,
56
+ });
57
+ await expect(verifier.verifyAccessToken('dobby_at_bad'))
58
+ .rejects.toThrow('Invalid or expired access token');
59
+ await expect(verifier.verifyAccessToken('dobby_at_bad'))
60
+ .rejects.toBeInstanceOf(InvalidTokenError);
61
+ });
62
+ it('throws InvalidTokenError on inactive token (RFC 7662 active:false)', async () => {
63
+ global.fetch = vi.fn().mockResolvedValue({
64
+ ok: true,
65
+ json: () => Promise.resolve({ active: false }),
66
+ });
67
+ await expect(verifier.verifyAccessToken('dobby_at_inactive'))
68
+ .rejects.toThrow('Invalid or expired access token');
69
+ await expect(verifier.verifyAccessToken('dobby_at_inactive'))
70
+ .rejects.toBeInstanceOf(InvalidTokenError);
71
+ });
72
+ it('throws InvalidTokenError when token missing org_id or tenant_id', async () => {
73
+ global.fetch = vi.fn().mockResolvedValue({
74
+ ok: true,
75
+ json: () => Promise.resolve({ active: true, user_id: 'u1' }),
76
+ });
77
+ await expect(verifier.verifyAccessToken('dobby_at_no_context'))
78
+ .rejects.toThrow('not bound to a tenant');
79
+ await expect(verifier.verifyAccessToken('dobby_at_no_context'))
80
+ .rejects.toBeInstanceOf(InvalidTokenError);
81
+ });
82
+ it('accepts a user-scoped PAT with no tenant/org pin (ADR-020) and carries the aggregate role', async () => {
83
+ global.fetch = vi.fn().mockResolvedValue({
84
+ ok: true,
85
+ json: () => Promise.resolve({
86
+ active: true,
87
+ user_id: 'pu_pat_user',
88
+ org_id: null,
89
+ tenant_id: null,
90
+ user_scoped: true,
91
+ scope: 'mcp:read mcp:execute mcp:*',
92
+ client_id: 'key_pat1',
93
+ exp: Math.floor(Date.now() / 1000) + 3600,
94
+ // aggregate (max) role across all memberships
95
+ tenant_role: 'tenant_owner',
96
+ org_role: 'org_owner',
97
+ is_super_admin: false,
98
+ }),
99
+ });
100
+ const authInfo = await verifier.verifyAccessToken('dobby_pat_usertoken');
101
+ // The tenant-less token is admitted BECAUSE it is user_scoped.
102
+ expect(authInfo.extra?.user_scoped).toBe(true);
103
+ expect(authInfo.extra?.tenant_id).toBeNull();
104
+ expect(authInfo.extra?.org_id).toBeNull();
105
+ // Aggregate role flows through the SAME extra.tenant_role plumbing that
106
+ // ListTools/CallTool gating already reads — no ListTools change needed.
107
+ expect(authInfo.extra?.tenant_role).toBe('tenant_owner');
108
+ expect(authInfo.extra?.is_super_admin).toBe(false);
109
+ });
110
+ it('throws ServerError on unexpected introspection failure (e.g. 500)', async () => {
111
+ global.fetch = vi.fn().mockResolvedValue({
112
+ ok: false,
113
+ status: 500,
114
+ });
115
+ await expect(verifier.verifyAccessToken('dobby_at_backend_down'))
116
+ .rejects.toThrow('Token validation failed (500)');
117
+ await expect(verifier.verifyAccessToken('dobby_at_backend_down'))
118
+ .rejects.toBeInstanceOf(ServerError);
119
+ });
120
+ it('evicts oldest entry when cache exceeds max size', async () => {
121
+ global.fetch = vi.fn().mockResolvedValue({
122
+ ok: true,
123
+ json: () => Promise.resolve(validTokenResponse),
124
+ });
125
+ // Fill cache beyond max (1000) — simplified test with a few entries
126
+ for (let i = 0; i < 5; i++) {
127
+ await verifier.verifyAccessToken(`dobby_at_token_${i}`);
128
+ }
129
+ expect(verifier.cacheSize).toBe(5);
130
+ });
131
+ it('calls correct introspection URL', async () => {
132
+ global.fetch = vi.fn().mockResolvedValue({
133
+ ok: true,
134
+ json: () => Promise.resolve(validTokenResponse),
135
+ });
136
+ await verifier.verifyAccessToken('dobby_at_url_test');
137
+ expect(fetch).toHaveBeenCalledWith('https://dobby-ai.com/oauth/token/introspect', expect.objectContaining({
138
+ method: 'POST',
139
+ headers: expect.objectContaining({
140
+ 'Authorization': 'Bearer dobby_at_url_test',
141
+ }),
142
+ }));
143
+ });
144
+ it('strips trailing slash from issuer URL', () => {
145
+ const v = new TokenVerifier('https://dobby-ai.com/');
146
+ // The verifier should store the URL without trailing slash
147
+ expect(v.issuerUrl).toBe('https://dobby-ai.com');
148
+ });
149
+ });
150
+ describe('createOAuthProvider', () => {
151
+ it('returns provider and tokenVerifier', () => {
152
+ const result = createOAuthProvider({
153
+ issuerUrl: 'https://dobby-ai.com',
154
+ mcpPublicUrl: 'https://mcp.dobby-ai.com',
155
+ });
156
+ expect(result.provider).toBeDefined();
157
+ expect(result.tokenVerifier).toBeDefined();
158
+ expect(result.tokenVerifier).toBeInstanceOf(TokenVerifier);
159
+ });
160
+ });
161
+ //# sourceMappingURL=auth.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.test.js","sourceRoot":"","sources":["../../src/__tests__/auth.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * dobby-mcp doctor — preflight credential/transport diagnosis tests.
3
+ *
4
+ * classifyApiKey is a PURE prefix classifier (no I/O) — tested directly, with a
5
+ * hard assertion that it never leaks more than the first 8 chars of the key.
6
+ *
7
+ * runDoctor orchestrates the live checks: it mocks createDobbyClient (health)
8
+ * and resolveGatewayKey (client-side gateway-key resolution) so we can drive
9
+ * every branch — blocked vs ready, health skipped vs called, and the
10
+ * transport-dependent gateway-tools messaging (http mints per request, stdio
11
+ * needs a static gk_ key). Env (DOBBY_API_KEY / DOBBY_TENANT_ID /
12
+ * DOBBY_GATEWAY_KEY) is reset around every test so a stray shell/CI value can't
13
+ * bleed into a case.
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=doctor.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/doctor.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
@@ -0,0 +1,258 @@
1
+ /**
2
+ * dobby-mcp doctor — preflight credential/transport diagnosis tests.
3
+ *
4
+ * classifyApiKey is a PURE prefix classifier (no I/O) — tested directly, with a
5
+ * hard assertion that it never leaks more than the first 8 chars of the key.
6
+ *
7
+ * runDoctor orchestrates the live checks: it mocks createDobbyClient (health)
8
+ * and resolveGatewayKey (client-side gateway-key resolution) so we can drive
9
+ * every branch — blocked vs ready, health skipped vs called, and the
10
+ * transport-dependent gateway-tools messaging (http mints per request, stdio
11
+ * needs a static gk_ key). Env (DOBBY_API_KEY / DOBBY_TENANT_ID /
12
+ * DOBBY_GATEWAY_KEY) is reset around every test so a stray shell/CI value can't
13
+ * bleed into a case.
14
+ */
15
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
16
+ const { checkHealthMock, createDobbyClientMock, resolveGatewayKeyMock } = vi.hoisted(() => ({
17
+ checkHealthMock: vi.fn(),
18
+ createDobbyClientMock: vi.fn(),
19
+ resolveGatewayKeyMock: vi.fn(),
20
+ }));
21
+ vi.mock("../lib/dobby-client.js", () => ({
22
+ createDobbyClient: createDobbyClientMock,
23
+ }));
24
+ vi.mock("../server.js", () => ({
25
+ resolveGatewayKey: resolveGatewayKeyMock,
26
+ }));
27
+ import { classifyApiKey, runDoctor, formatDoctorReport, } from "../doctor.js";
28
+ // ── env isolation ─────────────────────────────────────────────────────────
29
+ const ENV_KEYS = [
30
+ "DOBBY_API_KEY",
31
+ "DOBBY_TENANT_ID",
32
+ "DOBBY_GATEWAY_KEY",
33
+ "DOBBY_API_URL",
34
+ ];
35
+ let savedEnv;
36
+ beforeEach(() => {
37
+ savedEnv = {};
38
+ for (const k of ENV_KEYS) {
39
+ savedEnv[k] = process.env[k];
40
+ delete process.env[k];
41
+ }
42
+ vi.clearAllMocks();
43
+ // Re-establish defaults after clearAllMocks (it zeroes mockResolvedValue too).
44
+ checkHealthMock.mockResolvedValue(true);
45
+ createDobbyClientMock.mockReturnValue({ checkHealth: checkHealthMock });
46
+ // Default: no gateway key resolves (each case overrides as needed).
47
+ resolveGatewayKeyMock.mockReturnValue(undefined);
48
+ });
49
+ afterEach(() => {
50
+ for (const k of ENV_KEYS) {
51
+ if (savedEnv[k] === undefined)
52
+ delete process.env[k];
53
+ else
54
+ process.env[k] = savedEnv[k];
55
+ }
56
+ });
57
+ // Helper: find a check by name in a report.
58
+ function check(report, name) {
59
+ const c = report.checks.find((x) => x.name === name);
60
+ if (!c)
61
+ throw new Error(`no check named "${name}" in report`);
62
+ return c;
63
+ }
64
+ // ============================================
65
+ // classifyApiKey — pure prefix classification
66
+ // ============================================
67
+ describe("classifyApiKey", () => {
68
+ it("undefined key → fail", () => {
69
+ const c = classifyApiKey(undefined);
70
+ expect(c.name).toBe("API key");
71
+ expect(c.status).toBe("fail");
72
+ expect(c.detail).toMatch(/DOBBY_API_KEY/);
73
+ });
74
+ it("empty-string key → fail", () => {
75
+ const c = classifyApiKey("");
76
+ expect(c.status).toBe("fail");
77
+ });
78
+ it.each(["gk_user_abc", "gk_svc_x", "gk_tmp_x"])("gateway key %s → ok, detail mentions BOTH read and gateway", (key) => {
79
+ const c = classifyApiKey(key);
80
+ expect(c.status).toBe("ok");
81
+ // "read/tenant AND gateway/execute" — assert both concepts appear.
82
+ expect(c.detail.toLowerCase()).toMatch(/read/);
83
+ expect(c.detail.toLowerCase()).toMatch(/gateway/);
84
+ });
85
+ it("sk_live_ tenant key → ok, detail says gateway needs a gk_ key", () => {
86
+ const c = classifyApiKey("sk_live_x");
87
+ expect(c.status).toBe("ok");
88
+ expect(c.detail.toLowerCase()).toMatch(/gateway/);
89
+ expect(c.detail).toMatch(/gk_/);
90
+ });
91
+ it("dobby_pat_ token → warn, detail mentions STDIO and remote", () => {
92
+ const c = classifyApiKey("dobby_pat_x");
93
+ expect(c.status).toBe("warn");
94
+ expect(c.detail).toMatch(/STDIO/);
95
+ expect(c.detail.toLowerCase()).toMatch(/remote/);
96
+ });
97
+ it("unrecognized prefix (dk_x) → warn, detail mentions placeholders + valid prefixes", () => {
98
+ const c = classifyApiKey("dk_x");
99
+ expect(c.status).toBe("warn");
100
+ expect(c.detail.toLowerCase()).toMatch(/placeholder/);
101
+ // Points at the valid gateway/tenant prefixes.
102
+ expect(c.detail).toMatch(/gk_user_|gk_svc_|gk_tmp_/);
103
+ expect(c.detail).toMatch(/sk_live_/);
104
+ });
105
+ it("NEVER leaks more than the first 8 chars of the key in detail (no full-key leak)", () => {
106
+ // A long, distinctive secret. Only the first 8 chars may appear.
107
+ const secretTail = "SUPERSECRETTAIL9999";
108
+ const cases = [
109
+ `gk_user_${secretTail}`,
110
+ `gk_svc_${secretTail}`,
111
+ `gk_tmp_${secretTail}`,
112
+ `sk_live_${secretTail}`,
113
+ `dobby_pat_${secretTail}`,
114
+ `dk_${secretTail}`,
115
+ ];
116
+ for (const key of cases) {
117
+ const c = classifyApiKey(key);
118
+ // The unique tail must NOT appear anywhere in the detail.
119
+ expect(c.detail).not.toContain(secretTail);
120
+ // And nothing beyond the first 8 chars of the key should appear.
121
+ const beyond8 = key.slice(8);
122
+ if (beyond8.length > 0) {
123
+ expect(c.detail).not.toContain(beyond8);
124
+ }
125
+ }
126
+ });
127
+ });
128
+ // ============================================
129
+ // runDoctor — orchestration
130
+ // ============================================
131
+ describe("runDoctor", () => {
132
+ it('(a) no apiKey → blocked=true AND "API key" check status=fail', async () => {
133
+ const report = await runDoctor({ transport: "stdio" });
134
+ expect(report.blocked).toBe(true);
135
+ expect(check(report, "API key").status).toBe("fail");
136
+ });
137
+ it('(b) apiKey gk_user_ + tenantId + resolved gateway key + healthy → blocked=false AND "Gateway tools" ok', async () => {
138
+ resolveGatewayKeyMock.mockReturnValue("gk_user_resolved123");
139
+ checkHealthMock.mockResolvedValue(true);
140
+ const report = await runDoctor({
141
+ apiKey: "gk_user_x",
142
+ tenantId: "tenant_abc",
143
+ transport: "stdio",
144
+ });
145
+ expect(report.blocked).toBe(false);
146
+ expect(check(report, "Gateway tools").status).toBe("ok");
147
+ // Health WAS run and succeeded.
148
+ expect(checkHealthMock).toHaveBeenCalledTimes(1);
149
+ expect(check(report, "API reachable").status).toBe("ok");
150
+ });
151
+ it('(c) apiKey present but tenantId missing → "API reachable" warn + "Skipped", health NOT called', async () => {
152
+ const report = await runDoctor({ apiKey: "gk_user_x", transport: "stdio" });
153
+ const reachable = check(report, "API reachable");
154
+ expect(reachable.status).toBe("warn");
155
+ expect(reachable.detail).toMatch(/Skipped/);
156
+ expect(checkHealthMock).not.toHaveBeenCalled();
157
+ expect(createDobbyClientMock).not.toHaveBeenCalled();
158
+ });
159
+ it('(c) tenantId present but apiKey missing → "API reachable" warn + "Skipped", health NOT called', async () => {
160
+ const report = await runDoctor({
161
+ tenantId: "tenant_abc",
162
+ transport: "stdio",
163
+ });
164
+ const reachable = check(report, "API reachable");
165
+ expect(reachable.status).toBe("warn");
166
+ expect(reachable.detail).toMatch(/Skipped/);
167
+ expect(checkHealthMock).not.toHaveBeenCalled();
168
+ });
169
+ it('(d) resolveGatewayKey undefined + transport=http → "Gateway tools" warn, detail mentions per-request minting', async () => {
170
+ resolveGatewayKeyMock.mockReturnValue(undefined);
171
+ const report = await runDoctor({
172
+ apiKey: "sk_live_x",
173
+ tenantId: "tenant_abc",
174
+ transport: "http",
175
+ });
176
+ const gw = check(report, "Gateway tools");
177
+ expect(gw.status).toBe("warn");
178
+ // http branch: a gk_tmp_ is minted per request.
179
+ expect(gw.detail.toLowerCase()).toMatch(/per request|minted/);
180
+ expect(gw.detail).not.toMatch(/DOBBY_GATEWAY_KEY/);
181
+ });
182
+ it('(d) resolveGatewayKey undefined + transport=stdio → "Gateway tools" warn, detail mentions DOBBY_GATEWAY_KEY / does NOT', async () => {
183
+ resolveGatewayKeyMock.mockReturnValue(undefined);
184
+ const report = await runDoctor({
185
+ apiKey: "sk_live_x",
186
+ tenantId: "tenant_abc",
187
+ transport: "stdio",
188
+ });
189
+ const gw = check(report, "Gateway tools");
190
+ expect(gw.status).toBe("warn");
191
+ // stdio branch: needs a static key; mentions DOBBY_GATEWAY_KEY + "does NOT".
192
+ expect(gw.detail).toMatch(/DOBBY_GATEWAY_KEY/);
193
+ expect(gw.detail).toMatch(/does NOT/);
194
+ });
195
+ it('(d) the http vs stdio "Gateway tools" details actually DIFFER for the same missing-key input', async () => {
196
+ resolveGatewayKeyMock.mockReturnValue(undefined);
197
+ const httpReport = await runDoctor({
198
+ apiKey: "sk_live_x",
199
+ tenantId: "tenant_abc",
200
+ transport: "http",
201
+ });
202
+ const stdioReport = await runDoctor({
203
+ apiKey: "sk_live_x",
204
+ tenantId: "tenant_abc",
205
+ transport: "stdio",
206
+ });
207
+ expect(check(httpReport, "Gateway tools").detail).not.toBe(check(stdioReport, "Gateway tools").detail);
208
+ });
209
+ it('a health check that returns false surfaces "API reachable" fail (and blocks)', async () => {
210
+ checkHealthMock.mockResolvedValue(false);
211
+ const report = await runDoctor({
212
+ apiKey: "gk_user_x",
213
+ tenantId: "tenant_abc",
214
+ transport: "stdio",
215
+ });
216
+ expect(check(report, "API reachable").status).toBe("fail");
217
+ expect(report.blocked).toBe(true);
218
+ });
219
+ it("reads creds from process.env when opts omit them (env-driven STDIO path)", async () => {
220
+ process.env.DOBBY_API_KEY = "gk_user_fromenv";
221
+ process.env.DOBBY_TENANT_ID = "tenant_fromenv";
222
+ resolveGatewayKeyMock.mockReturnValue("gk_user_fromenv");
223
+ const report = await runDoctor({ transport: "stdio" });
224
+ // classify picked up the env key.
225
+ expect(check(report, "API key").status).toBe("ok");
226
+ expect(check(report, "Tenant ID").detail).toBe("tenant_fromenv");
227
+ expect(checkHealthMock).toHaveBeenCalledTimes(1);
228
+ });
229
+ });
230
+ // ============================================
231
+ // formatDoctorReport — rendering
232
+ // ============================================
233
+ describe("formatDoctorReport", () => {
234
+ const sampleReport = {
235
+ checks: [
236
+ { name: "API URL", status: "ok", detail: "https://dobby-ai.com" },
237
+ { name: "API key", status: "warn", detail: "Tenant key" },
238
+ ],
239
+ blocked: false,
240
+ };
241
+ it("renders a line per check (each check name appears)", () => {
242
+ const out = formatDoctorReport(sampleReport);
243
+ for (const c of sampleReport.checks) {
244
+ expect(out).toContain(c.name);
245
+ expect(out).toContain(c.detail);
246
+ }
247
+ });
248
+ it("not blocked → footer says Ready", () => {
249
+ const out = formatDoctorReport({ ...sampleReport, blocked: false });
250
+ expect(out).toMatch(/Ready/);
251
+ expect(out).not.toMatch(/Blocked/);
252
+ });
253
+ it("blocked → footer says Blocked", () => {
254
+ const out = formatDoctorReport({ ...sampleReport, blocked: true });
255
+ expect(out).toMatch(/Blocked/);
256
+ });
257
+ });
258
+ //# sourceMappingURL=doctor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.test.js","sourceRoot":"","sources":["../../src/__tests__/doctor.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEzE,MAAM,EAAE,eAAe,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,GACrE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAChB,eAAe,EAAE,EAAE,CAAC,EAAE,EAAE;IACxB,qBAAqB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC9B,qBAAqB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC/B,CAAC,CAAC,CAAC;AAEN,EAAE,CAAC,IAAI,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC;IACvC,iBAAiB,EAAE,qBAAqB;CACzC,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7B,iBAAiB,EAAE,qBAAqB;CACzC,CAAC,CAAC,CAAC;AAEJ,OAAO,EACL,cAAc,EACd,SAAS,EACT,kBAAkB,GAEnB,MAAM,cAAc,CAAC;AAEtB,6EAA6E;AAC7E,MAAM,QAAQ,GAAG;IACf,eAAe;IACf,iBAAiB;IACjB,mBAAmB;IACnB,eAAe;CACP,CAAC;AAEX,IAAI,QAA4C,CAAC;AAEjD,UAAU,CAAC,GAAG,EAAE;IACd,QAAQ,GAAG,EAAE,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC7B,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;IACD,EAAE,CAAC,aAAa,EAAE,CAAC;IACnB,+EAA+E;IAC/E,eAAe,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACxC,qBAAqB,CAAC,eAAe,CAAC,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC;IACxE,oEAAoE;IACpE,qBAAqB,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACb,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;;YAChD,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,4CAA4C;AAC5C,SAAS,KAAK,CAAC,MAAoB,EAAE,IAAY;IAC/C,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACrD,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,aAAa,CAAC,CAAC;IAC9D,OAAO,CAAC,CAAC;AACX,CAAC;AAED,+CAA+C;AAC/C,8CAA8C;AAC9C,+CAA+C;AAE/C,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;QAC7B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAC9C,4DAA4D,EAC5D,CAAC,GAAG,EAAE,EAAE;QACN,MAAM,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,mEAAmE;QACnE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC,CACF,CAAC;IAEF,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,CAAC,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;QACtC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAClD,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,CAAC,GAAG,cAAc,CAAC,aAAa,CAAC,CAAC;QACxC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QAC1F,MAAM,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QACtD,+CAA+C;QAC/C,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;QACrD,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iFAAiF,EAAE,GAAG,EAAE;QACzF,iEAAiE;QACjE,MAAM,UAAU,GAAG,qBAAqB,CAAC;QACzC,MAAM,KAAK,GAAG;YACZ,WAAW,UAAU,EAAE;YACvB,UAAU,UAAU,EAAE;YACtB,UAAU,UAAU,EAAE;YACtB,WAAW,UAAU,EAAE;YACvB,aAAa,UAAU,EAAE;YACzB,MAAM,UAAU,EAAE;SACnB,CAAC;QACF,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;YAC9B,0DAA0D;YAC1D,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YAC3C,iEAAiE;YACjE,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC7B,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,+CAA+C;AAC/C,4BAA4B;AAC5B,+CAA+C;AAE/C,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC5E,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;QAEvD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wGAAwG,EAAE,KAAK,IAAI,EAAE;QACtH,qBAAqB,CAAC,eAAe,CAAC,qBAAqB,CAAC,CAAC;QAC7D,eAAe,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAExC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC;YAC7B,MAAM,EAAE,WAAW;YACnB,QAAQ,EAAE,YAAY;YACtB,SAAS,EAAE,OAAO;SACnB,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,gCAAgC;QAChC,MAAM,CAAC,eAAe,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+FAA+F,EAAE,KAAK,IAAI,EAAE;QAC7G,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;QAE5E,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QACjD,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC5C,MAAM,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAC/C,MAAM,CAAC,qBAAqB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+FAA+F,EAAE,KAAK,IAAI,EAAE;QAC7G,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC;YAC7B,QAAQ,EAAE,YAAY;YACtB,SAAS,EAAE,OAAO;SACnB,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QACjD,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC5C,MAAM,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8GAA8G,EAAE,KAAK,IAAI,EAAE;QAC5H,qBAAqB,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAEjD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC;YAC7B,MAAM,EAAE,WAAW;YACnB,QAAQ,EAAE,YAAY;YACtB,SAAS,EAAE,MAAM;SAClB,CAAC,CAAC;QAEH,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QAC1C,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/B,gDAAgD;QAChD,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAC9D,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wHAAwH,EAAE,KAAK,IAAI,EAAE;QACtI,qBAAqB,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAEjD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC;YAC7B,MAAM,EAAE,WAAW;YACnB,QAAQ,EAAE,YAAY;YACtB,SAAS,EAAE,OAAO;SACnB,CAAC,CAAC;QAEH,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QAC1C,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/B,6EAA6E;QAC7E,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAC/C,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8FAA8F,EAAE,KAAK,IAAI,EAAE;QAC5G,qBAAqB,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAEjD,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC;YACjC,MAAM,EAAE,WAAW;YACnB,QAAQ,EAAE,YAAY;YACtB,SAAS,EAAE,MAAM;SAClB,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC;YAClC,MAAM,EAAE,WAAW;YACnB,QAAQ,EAAE,YAAY;YACtB,SAAS,EAAE,OAAO;SACnB,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CACxD,KAAK,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,MAAM,CAC3C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;QAC5F,eAAe,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAEzC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC;YAC7B,MAAM,EAAE,WAAW;YACnB,QAAQ,EAAE,YAAY;YACtB,SAAS,EAAE,OAAO;SACnB,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,iBAAiB,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,gBAAgB,CAAC;QAC/C,qBAAqB,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC;QAEzD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;QAEvD,kCAAkC;QAClC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACjE,MAAM,CAAC,eAAe,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,+CAA+C;AAC/C,iCAAiC;AACjC,+CAA+C;AAE/C,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,MAAM,YAAY,GAAiB;QACjC,MAAM,EAAE;YACN,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,sBAAsB,EAAE;YACjE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE;SAC1D;QACD,OAAO,EAAE,KAAK;KACf,CAAC;IAEF,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,GAAG,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC;QAC7C,KAAK,MAAM,CAAC,IAAI,YAAY,CAAC,MAAM,EAAE,CAAC;YACpC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC9B,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,GAAG,GAAG,kBAAkB,CAAC,EAAE,GAAG,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACpE,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7B,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,GAAG,GAAG,kBAAkB,CAAC,EAAE,GAAG,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * External Agents MCP Tools Tests
3
+ *
4
+ * Tests the 10 MCP tools that wrap /api/v1/gateway/external-agents/* endpoints:
5
+ * register/list/get/update/deregister
6
+ * trigger/get_triggers
7
+ * create_schedule/delete_schedule
8
+ * get_costs
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=external-agents-tools.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-agents-tools.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/external-agents-tools.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}