@mondaydotcomorg/atp-server 0.17.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. package/README.md +489 -0
  2. package/dist/aggregator/index.d.ts +59 -0
  3. package/dist/aggregator/index.d.ts.map +1 -0
  4. package/dist/aggregator/index.js +171 -0
  5. package/dist/aggregator/index.js.map +1 -0
  6. package/dist/callback/index.d.ts +98 -0
  7. package/dist/callback/index.d.ts.map +1 -0
  8. package/dist/callback/index.js +136 -0
  9. package/dist/callback/index.js.map +1 -0
  10. package/dist/client-sessions.d.ts +82 -0
  11. package/dist/client-sessions.d.ts.map +1 -0
  12. package/dist/client-sessions.js +174 -0
  13. package/dist/client-sessions.js.map +1 -0
  14. package/dist/controllers/definitions.controller.d.ts +4 -0
  15. package/dist/controllers/definitions.controller.d.ts.map +1 -0
  16. package/dist/controllers/definitions.controller.js +11 -0
  17. package/dist/controllers/definitions.controller.js.map +1 -0
  18. package/dist/controllers/execute.controller.d.ts +18 -0
  19. package/dist/controllers/execute.controller.d.ts.map +1 -0
  20. package/dist/controllers/execute.controller.js +122 -0
  21. package/dist/controllers/execute.controller.js.map +1 -0
  22. package/dist/controllers/info.controller.d.ts +3 -0
  23. package/dist/controllers/info.controller.d.ts.map +1 -0
  24. package/dist/controllers/info.controller.js +13 -0
  25. package/dist/controllers/info.controller.js.map +1 -0
  26. package/dist/controllers/resume.controller.d.ts +11 -0
  27. package/dist/controllers/resume.controller.d.ts.map +1 -0
  28. package/dist/controllers/resume.controller.js +61 -0
  29. package/dist/controllers/resume.controller.js.map +1 -0
  30. package/dist/controllers/search.controller.d.ts +4 -0
  31. package/dist/controllers/search.controller.d.ts.map +1 -0
  32. package/dist/controllers/search.controller.js +7 -0
  33. package/dist/controllers/search.controller.js.map +1 -0
  34. package/dist/controllers/stream.controller.d.ts +19 -0
  35. package/dist/controllers/stream.controller.d.ts.map +1 -0
  36. package/dist/controllers/stream.controller.js +141 -0
  37. package/dist/controllers/stream.controller.js.map +1 -0
  38. package/dist/core/config.d.ts +161 -0
  39. package/dist/core/config.d.ts.map +1 -0
  40. package/dist/core/config.js +7 -0
  41. package/dist/core/config.js.map +1 -0
  42. package/dist/core/http.d.ts +4 -0
  43. package/dist/core/http.d.ts.map +1 -0
  44. package/dist/core/http.js +17 -0
  45. package/dist/core/http.js.map +1 -0
  46. package/dist/create-server.d.ts +120 -0
  47. package/dist/create-server.d.ts.map +1 -0
  48. package/dist/create-server.js +423 -0
  49. package/dist/create-server.js.map +1 -0
  50. package/dist/execution-state/index.d.ts +95 -0
  51. package/dist/execution-state/index.d.ts.map +1 -0
  52. package/dist/execution-state/index.js +128 -0
  53. package/dist/execution-state/index.js.map +1 -0
  54. package/dist/executor/ast-provenance-bridge.d.ts +12 -0
  55. package/dist/executor/ast-provenance-bridge.d.ts.map +1 -0
  56. package/dist/executor/ast-provenance-bridge.js +66 -0
  57. package/dist/executor/ast-provenance-bridge.js.map +1 -0
  58. package/dist/executor/ast-tracking-runtime.d.ts +7 -0
  59. package/dist/executor/ast-tracking-runtime.d.ts.map +1 -0
  60. package/dist/executor/ast-tracking-runtime.js +559 -0
  61. package/dist/executor/ast-tracking-runtime.js.map +1 -0
  62. package/dist/executor/bootstrap-generated.d.ts +32 -0
  63. package/dist/executor/bootstrap-generated.d.ts.map +1 -0
  64. package/dist/executor/bootstrap-generated.js +90 -0
  65. package/dist/executor/bootstrap-generated.js.map +1 -0
  66. package/dist/executor/compiler-config.d.ts +32 -0
  67. package/dist/executor/compiler-config.d.ts.map +1 -0
  68. package/dist/executor/compiler-config.js +99 -0
  69. package/dist/executor/compiler-config.js.map +1 -0
  70. package/dist/executor/constants.d.ts +4 -0
  71. package/dist/executor/constants.d.ts.map +1 -0
  72. package/dist/executor/constants.js +4 -0
  73. package/dist/executor/constants.js.map +1 -0
  74. package/dist/executor/error-handler.d.ts +9 -0
  75. package/dist/executor/error-handler.d.ts.map +1 -0
  76. package/dist/executor/error-handler.js +95 -0
  77. package/dist/executor/error-handler.js.map +1 -0
  78. package/dist/executor/execution-error-handler.d.ts +7 -0
  79. package/dist/executor/execution-error-handler.d.ts.map +1 -0
  80. package/dist/executor/execution-error-handler.js +136 -0
  81. package/dist/executor/execution-error-handler.js.map +1 -0
  82. package/dist/executor/executor.d.ts +20 -0
  83. package/dist/executor/executor.d.ts.map +1 -0
  84. package/dist/executor/executor.js +452 -0
  85. package/dist/executor/executor.js.map +1 -0
  86. package/dist/executor/index.d.ts +4 -0
  87. package/dist/executor/index.d.ts.map +1 -0
  88. package/dist/executor/index.js +3 -0
  89. package/dist/executor/index.js.map +1 -0
  90. package/dist/executor/resume-handler.d.ts +9 -0
  91. package/dist/executor/resume-handler.d.ts.map +1 -0
  92. package/dist/executor/resume-handler.js +22 -0
  93. package/dist/executor/resume-handler.js.map +1 -0
  94. package/dist/executor/sandbox-builder.d.ts +29 -0
  95. package/dist/executor/sandbox-builder.d.ts.map +1 -0
  96. package/dist/executor/sandbox-builder.js +538 -0
  97. package/dist/executor/sandbox-builder.js.map +1 -0
  98. package/dist/executor/sandbox-injector.d.ts +7 -0
  99. package/dist/executor/sandbox-injector.d.ts.map +1 -0
  100. package/dist/executor/sandbox-injector.js +293 -0
  101. package/dist/executor/sandbox-injector.js.map +1 -0
  102. package/dist/executor/types.d.ts +21 -0
  103. package/dist/executor/types.d.ts.map +1 -0
  104. package/dist/executor/types.js +2 -0
  105. package/dist/executor/types.js.map +1 -0
  106. package/dist/explorer/index.d.ts +69 -0
  107. package/dist/explorer/index.d.ts.map +1 -0
  108. package/dist/explorer/index.js +228 -0
  109. package/dist/explorer/index.js.map +1 -0
  110. package/dist/handlers/definitions.handler.d.ts +3 -0
  111. package/dist/handlers/definitions.handler.d.ts.map +1 -0
  112. package/dist/handlers/definitions.handler.js +11 -0
  113. package/dist/handlers/definitions.handler.js.map +1 -0
  114. package/dist/handlers/execute.handler.d.ts +7 -0
  115. package/dist/handlers/execute.handler.d.ts.map +1 -0
  116. package/dist/handlers/execute.handler.js +225 -0
  117. package/dist/handlers/execute.handler.js.map +1 -0
  118. package/dist/handlers/explorer.handler.d.ts +4 -0
  119. package/dist/handlers/explorer.handler.d.ts.map +1 -0
  120. package/dist/handlers/explorer.handler.js +10 -0
  121. package/dist/handlers/explorer.handler.js.map +1 -0
  122. package/dist/handlers/init.handler.d.ts +5 -0
  123. package/dist/handlers/init.handler.d.ts.map +1 -0
  124. package/dist/handlers/init.handler.js +41 -0
  125. package/dist/handlers/init.handler.js.map +1 -0
  126. package/dist/handlers/resume.handler.d.ts +6 -0
  127. package/dist/handlers/resume.handler.d.ts.map +1 -0
  128. package/dist/handlers/resume.handler.js +256 -0
  129. package/dist/handlers/resume.handler.js.map +1 -0
  130. package/dist/handlers/search.handler.d.ts +5 -0
  131. package/dist/handlers/search.handler.d.ts.map +1 -0
  132. package/dist/handlers/search.handler.js +11 -0
  133. package/dist/handlers/search.handler.js.map +1 -0
  134. package/dist/http/request-handler.d.ts +15 -0
  135. package/dist/http/request-handler.d.ts.map +1 -0
  136. package/dist/http/request-handler.js +94 -0
  137. package/dist/http/request-handler.js.map +1 -0
  138. package/dist/http/router.d.ts +4 -0
  139. package/dist/http/router.d.ts.map +1 -0
  140. package/dist/http/router.js +32 -0
  141. package/dist/http/router.js.map +1 -0
  142. package/dist/index.d.ts +10 -0
  143. package/dist/index.d.ts.map +1 -0
  144. package/dist/index.js +8 -0
  145. package/dist/index.js.map +1 -0
  146. package/dist/instrumentation/index.d.ts +5 -0
  147. package/dist/instrumentation/index.d.ts.map +1 -0
  148. package/dist/instrumentation/index.js +5 -0
  149. package/dist/instrumentation/index.js.map +1 -0
  150. package/dist/instrumentation/serializer.d.ts +61 -0
  151. package/dist/instrumentation/serializer.d.ts.map +1 -0
  152. package/dist/instrumentation/serializer.js +334 -0
  153. package/dist/instrumentation/serializer.js.map +1 -0
  154. package/dist/instrumentation/state-manager.d.ts +61 -0
  155. package/dist/instrumentation/state-manager.d.ts.map +1 -0
  156. package/dist/instrumentation/state-manager.js +205 -0
  157. package/dist/instrumentation/state-manager.js.map +1 -0
  158. package/dist/instrumentation/transformer.d.ts +9 -0
  159. package/dist/instrumentation/transformer.d.ts.map +1 -0
  160. package/dist/instrumentation/transformer.js +70 -0
  161. package/dist/instrumentation/transformer.js.map +1 -0
  162. package/dist/instrumentation/types.d.ts +59 -0
  163. package/dist/instrumentation/types.d.ts.map +1 -0
  164. package/dist/instrumentation/types.js +5 -0
  165. package/dist/instrumentation/types.js.map +1 -0
  166. package/dist/middleware/audit.d.ts +18 -0
  167. package/dist/middleware/audit.d.ts.map +1 -0
  168. package/dist/middleware/audit.js +76 -0
  169. package/dist/middleware/audit.js.map +1 -0
  170. package/dist/openapi/index.d.ts +133 -0
  171. package/dist/openapi/index.d.ts.map +1 -0
  172. package/dist/openapi/index.js +235 -0
  173. package/dist/openapi/index.js.map +1 -0
  174. package/dist/openapi-loader.d.ts +87 -0
  175. package/dist/openapi-loader.d.ts.map +1 -0
  176. package/dist/openapi-loader.js +491 -0
  177. package/dist/openapi-loader.js.map +1 -0
  178. package/dist/routes/index.d.ts +21 -0
  179. package/dist/routes/index.d.ts.map +1 -0
  180. package/dist/routes/index.js +47 -0
  181. package/dist/routes/index.js.map +1 -0
  182. package/dist/search/index.d.ts +48 -0
  183. package/dist/search/index.d.ts.map +1 -0
  184. package/dist/search/index.js +156 -0
  185. package/dist/search/index.js.map +1 -0
  186. package/dist/security/index.d.ts +2 -0
  187. package/dist/security/index.d.ts.map +1 -0
  188. package/dist/security/index.js +2 -0
  189. package/dist/security/index.js.map +1 -0
  190. package/dist/shutdown.d.ts +19 -0
  191. package/dist/shutdown.d.ts.map +1 -0
  192. package/dist/shutdown.js +87 -0
  193. package/dist/shutdown.js.map +1 -0
  194. package/dist/utils/banner.d.ts +12 -0
  195. package/dist/utils/banner.d.ts.map +1 -0
  196. package/dist/utils/banner.js +18 -0
  197. package/dist/utils/banner.js.map +1 -0
  198. package/dist/utils/context.d.ts +16 -0
  199. package/dist/utils/context.d.ts.map +1 -0
  200. package/dist/utils/context.js +44 -0
  201. package/dist/utils/context.js.map +1 -0
  202. package/dist/utils/error.d.ts +8 -0
  203. package/dist/utils/error.d.ts.map +1 -0
  204. package/dist/utils/error.js +17 -0
  205. package/dist/utils/error.js.map +1 -0
  206. package/dist/utils/hint-based-instrumentation.d.ts +14 -0
  207. package/dist/utils/hint-based-instrumentation.d.ts.map +1 -0
  208. package/dist/utils/hint-based-instrumentation.js +84 -0
  209. package/dist/utils/hint-based-instrumentation.js.map +1 -0
  210. package/dist/utils/index.d.ts +8 -0
  211. package/dist/utils/index.d.ts.map +1 -0
  212. package/dist/utils/index.js +8 -0
  213. package/dist/utils/index.js.map +1 -0
  214. package/dist/utils/info.d.ts +20 -0
  215. package/dist/utils/info.d.ts.map +1 -0
  216. package/dist/utils/info.js +15 -0
  217. package/dist/utils/info.js.map +1 -0
  218. package/dist/utils/provenance-reattachment.d.ts +32 -0
  219. package/dist/utils/provenance-reattachment.d.ts.map +1 -0
  220. package/dist/utils/provenance-reattachment.js +115 -0
  221. package/dist/utils/provenance-reattachment.js.map +1 -0
  222. package/dist/utils/request.d.ts +21 -0
  223. package/dist/utils/request.d.ts.map +1 -0
  224. package/dist/utils/request.js +44 -0
  225. package/dist/utils/request.js.map +1 -0
  226. package/dist/utils/response.d.ts +30 -0
  227. package/dist/utils/response.d.ts.map +1 -0
  228. package/dist/utils/response.js +53 -0
  229. package/dist/utils/response.js.map +1 -0
  230. package/dist/utils/runtime-types.d.ts +6 -0
  231. package/dist/utils/runtime-types.d.ts.map +1 -0
  232. package/dist/utils/runtime-types.js +14 -0
  233. package/dist/utils/runtime-types.js.map +1 -0
  234. package/dist/utils/schema.d.ts +9 -0
  235. package/dist/utils/schema.d.ts.map +1 -0
  236. package/dist/utils/schema.js +13 -0
  237. package/dist/utils/schema.js.map +1 -0
  238. package/dist/utils/token-emitter.d.ts +21 -0
  239. package/dist/utils/token-emitter.d.ts.map +1 -0
  240. package/dist/utils/token-emitter.js +129 -0
  241. package/dist/utils/token-emitter.js.map +1 -0
  242. package/dist/validator/index.d.ts +36 -0
  243. package/dist/validator/index.d.ts.map +1 -0
  244. package/dist/validator/index.js +224 -0
  245. package/dist/validator/index.js.map +1 -0
  246. package/package.json +68 -0
  247. package/src/aggregator/index.ts +207 -0
  248. package/src/callback/index.ts +191 -0
  249. package/src/client-sessions.ts +234 -0
  250. package/src/controllers/definitions.controller.ts +19 -0
  251. package/src/controllers/execute.controller.ts +166 -0
  252. package/src/controllers/info.controller.ts +14 -0
  253. package/src/controllers/resume.controller.ts +92 -0
  254. package/src/controllers/search.controller.ts +16 -0
  255. package/src/controllers/stream.controller.ts +190 -0
  256. package/src/core/config.ts +180 -0
  257. package/src/core/http.ts +21 -0
  258. package/src/create-server.ts +536 -0
  259. package/src/execution-state/index.ts +204 -0
  260. package/src/executor/ast-provenance-bridge.ts +80 -0
  261. package/src/executor/ast-tracking-runtime.ts +558 -0
  262. package/src/executor/bootstrap-generated.ts +90 -0
  263. package/src/executor/compiler-config.ts +146 -0
  264. package/src/executor/constants.ts +5 -0
  265. package/src/executor/error-handler.ts +118 -0
  266. package/src/executor/execution-error-handler.ts +178 -0
  267. package/src/executor/executor.ts +631 -0
  268. package/src/executor/index.ts +3 -0
  269. package/src/executor/resume-handler.ts +39 -0
  270. package/src/executor/sandbox-builder.ts +684 -0
  271. package/src/executor/sandbox-injector.ts +345 -0
  272. package/src/executor/types.ts +22 -0
  273. package/src/explorer/index.ts +297 -0
  274. package/src/handlers/definitions.handler.ts +13 -0
  275. package/src/handlers/execute.handler.ts +286 -0
  276. package/src/handlers/explorer.handler.ts +18 -0
  277. package/src/handlers/init.handler.ts +53 -0
  278. package/src/handlers/resume.handler.ts +316 -0
  279. package/src/handlers/search.handler.ts +32 -0
  280. package/src/http/request-handler.ts +117 -0
  281. package/src/http/router.ts +29 -0
  282. package/src/index.ts +60 -0
  283. package/src/instrumentation/index.ts +4 -0
  284. package/src/instrumentation/serializer.ts +421 -0
  285. package/src/instrumentation/state-manager.ts +237 -0
  286. package/src/instrumentation/transformer.ts +84 -0
  287. package/src/instrumentation/types.ts +76 -0
  288. package/src/middleware/audit.ts +101 -0
  289. package/src/openapi/index.ts +378 -0
  290. package/src/openapi-loader.ts +744 -0
  291. package/src/routes/index.ts +93 -0
  292. package/src/search/index.ts +216 -0
  293. package/src/security/index.ts +1 -0
  294. package/src/shutdown.ts +108 -0
  295. package/src/utils/banner.ts +25 -0
  296. package/src/utils/context.ts +58 -0
  297. package/src/utils/error.ts +25 -0
  298. package/src/utils/hint-based-instrumentation.ts +99 -0
  299. package/src/utils/index.ts +15 -0
  300. package/src/utils/info.ts +31 -0
  301. package/src/utils/provenance-reattachment.ts +144 -0
  302. package/src/utils/request.ts +53 -0
  303. package/src/utils/response.ts +69 -0
  304. package/src/utils/runtime-types.ts +14 -0
  305. package/src/utils/schema.ts +18 -0
  306. package/src/utils/token-emitter.ts +182 -0
  307. package/src/validator/index.ts +253 -0
@@ -0,0 +1,378 @@
1
+ import type {
2
+ APIGroupConfig,
3
+ CustomFunctionDef,
4
+ ToolOperationType,
5
+ } from '@mondaydotcomorg/atp-protocol';
6
+ import type {
7
+ AuthConfig,
8
+ APIKeyAuthConfig,
9
+ BearerAuthConfig,
10
+ BasicAuthConfig,
11
+ OAuth2AuthConfig,
12
+ } from '@mondaydotcomorg/atp-protocol';
13
+ import { readFile } from 'node:fs/promises';
14
+
15
+ interface OpenAPISpec {
16
+ openapi: string;
17
+ info: {
18
+ title: string;
19
+ version: string;
20
+ description?: string;
21
+ };
22
+ paths: Record<string, Record<string, OpenAPIOperation>>;
23
+ servers?: Array<{ url: string; description?: string }>;
24
+ components?: {
25
+ schemas?: Record<string, unknown>;
26
+ securitySchemes?: Record<string, OpenAPISecurityScheme>;
27
+ };
28
+ security?: Array<Record<string, string[]>>;
29
+ }
30
+
31
+ interface OpenAPISecurityScheme {
32
+ type: 'apiKey' | 'http' | 'oauth2' | 'openIdConnect';
33
+ description?: string;
34
+ name?: string;
35
+ in?: 'query' | 'header' | 'cookie';
36
+ scheme?: string;
37
+ bearerFormat?: string;
38
+ flows?: {
39
+ clientCredentials?: {
40
+ tokenUrl: string;
41
+ refreshUrl?: string;
42
+ scopes?: Record<string, string>;
43
+ };
44
+ authorizationCode?: {
45
+ authorizationUrl: string;
46
+ tokenUrl: string;
47
+ refreshUrl?: string;
48
+ scopes?: Record<string, string>;
49
+ };
50
+ implicit?: {
51
+ authorizationUrl: string;
52
+ scopes?: Record<string, string>;
53
+ };
54
+ password?: {
55
+ tokenUrl: string;
56
+ refreshUrl?: string;
57
+ scopes?: Record<string, string>;
58
+ };
59
+ };
60
+ }
61
+
62
+ interface OpenAPIOperation {
63
+ summary?: string;
64
+ description?: string;
65
+ operationId?: string;
66
+ parameters?: Array<{
67
+ name: string;
68
+ in: string;
69
+ required?: boolean;
70
+ schema?: { type?: string; description?: string };
71
+ description?: string;
72
+ }>;
73
+ requestBody?: {
74
+ content?: {
75
+ 'application/json'?: {
76
+ schema?: unknown;
77
+ };
78
+ };
79
+ };
80
+ responses?: Record<string, unknown>;
81
+ /** Per-operation security requirements */
82
+ security?: Array<Record<string, string[]>>;
83
+ }
84
+
85
+ /**
86
+ * OpenAPIConverter converts OpenAPI specifications to Agent Tool Protocol API groups.
87
+ */
88
+ export class OpenAPIConverter {
89
+ /**
90
+ * Converts an OpenAPI specification to an API group configuration.
91
+ * @param spec - OpenAPI specification object
92
+ * @param httpClient - Function to execute HTTP requests (optional)
93
+ * @param authEnvVarPrefix - Prefix for environment variables (e.g., 'GITHUB' -> 'GITHUB_API_KEY')
94
+ * @returns APIGroupConfig object
95
+ */
96
+ static fromSpec(
97
+ spec: OpenAPISpec,
98
+ httpClient?: (method: string, path: string, params?: unknown) => Promise<unknown>,
99
+ authEnvVarPrefix?: string
100
+ ): APIGroupConfig {
101
+ const functions: CustomFunctionDef[] = [];
102
+
103
+ const baseUrl = spec.servers?.[0]?.url || '';
104
+
105
+ const globalSecurity = spec.security;
106
+
107
+ for (const [path, methods] of Object.entries(spec.paths)) {
108
+ for (const [method, operation] of Object.entries(methods)) {
109
+ const func = this.convertOperation(path, method, operation, httpClient, globalSecurity);
110
+ if (func) {
111
+ functions.push(func);
112
+ }
113
+ }
114
+ }
115
+
116
+ const auth = this.parseAuthentication(spec, authEnvVarPrefix);
117
+
118
+ return {
119
+ name: this.sanitizeName(spec.info.title),
120
+ type: 'openapi',
121
+ spec,
122
+ functions,
123
+ url: baseUrl,
124
+ auth,
125
+ };
126
+ }
127
+
128
+ /**
129
+ * Converts an OpenAPI operation to a function definition.
130
+ */
131
+ private static convertOperation(
132
+ path: string,
133
+ method: string,
134
+ operation: OpenAPIOperation,
135
+ httpClient?: (method: string, path: string, params?: unknown) => Promise<unknown>,
136
+ globalSecurity?: Array<Record<string, string[]>>
137
+ ): CustomFunctionDef | null {
138
+ const functionName = operation.operationId || this.generateFunctionName(method, path);
139
+ const description =
140
+ operation.summary || operation.description || `${method.toUpperCase()} ${path}`;
141
+
142
+ const inputSchema = this.buildInputSchema(operation);
143
+
144
+ const requiredScopes = this.extractRequiredScopes(operation.security || globalSecurity);
145
+
146
+ const operationType = this.inferOperationType(method);
147
+
148
+ const handler = httpClient
149
+ ? async (input: unknown) => {
150
+ return await httpClient(method, path, input);
151
+ }
152
+ : async (input: unknown) => {
153
+ throw new Error(`No HTTP client configured for ${functionName}`);
154
+ };
155
+
156
+ return {
157
+ name: functionName,
158
+ description,
159
+ inputSchema,
160
+ handler,
161
+ metadata: {
162
+ operationType,
163
+ ...(requiredScopes.length > 0 && { requiredScopes }),
164
+ },
165
+ };
166
+ }
167
+
168
+ /**
169
+ * Builds JSON schema from OpenAPI operation parameters and request body.
170
+ */
171
+ private static buildInputSchema(operation: OpenAPIOperation): {
172
+ type: string;
173
+ properties: Record<string, unknown>;
174
+ required?: string[];
175
+ } {
176
+ const properties: Record<string, unknown> = {};
177
+ const required: string[] = [];
178
+
179
+ if (operation.parameters) {
180
+ for (const param of operation.parameters) {
181
+ properties[param.name] = {
182
+ type: param.schema?.type || 'string',
183
+ description: param.description || param.schema?.description,
184
+ };
185
+ if (param.required) {
186
+ required.push(param.name);
187
+ }
188
+ }
189
+ }
190
+
191
+ if (operation.requestBody?.content?.['application/json']?.schema) {
192
+ const bodySchema = operation.requestBody.content['application/json'].schema as {
193
+ properties?: Record<string, unknown>;
194
+ required?: string[];
195
+ };
196
+ if (bodySchema.properties) {
197
+ Object.assign(properties, bodySchema.properties);
198
+ }
199
+ if (bodySchema.required) {
200
+ required.push(...bodySchema.required);
201
+ }
202
+ }
203
+
204
+ return {
205
+ type: 'object',
206
+ properties,
207
+ ...(required.length > 0 && { required }),
208
+ };
209
+ }
210
+
211
+ /**
212
+ * Generates a function name from HTTP method and path.
213
+ */
214
+ private static generateFunctionName(method: string, path: string): string {
215
+ const cleanPath = path
216
+ .replace(/^[^a-zA-Z0-9_]+/, '')
217
+ .replace(/\{([^}]+)\}/g, 'By_$1')
218
+ .replace(/[^a-zA-Z0-9_]/g, '_')
219
+ .replace(/_+/g, '_')
220
+ .replace(/^_|_$/g, '');
221
+
222
+ return `${method}_${cleanPath}`;
223
+ }
224
+
225
+ /**
226
+ * Sanitizes a name for use as an API group name.
227
+ */
228
+ private static sanitizeName(name: string): string {
229
+ return name
230
+ .toLowerCase()
231
+ .replace(/[^a-z0-9]+/g, '_')
232
+ .replace(/^_|_$/g, '');
233
+ }
234
+
235
+ /**
236
+ * Extracts required OAuth scopes from security requirements
237
+ */
238
+ private static extractRequiredScopes(security?: Array<Record<string, string[]>>): string[] {
239
+ if (!security || security.length === 0) {
240
+ return [];
241
+ }
242
+
243
+ const allScopes = new Set<string>();
244
+ for (const secReq of security) {
245
+ for (const scopes of Object.values(secReq)) {
246
+ scopes.forEach((scope) => allScopes.add(scope));
247
+ }
248
+ }
249
+
250
+ return Array.from(allScopes);
251
+ }
252
+
253
+ /**
254
+ * Infers operation type from HTTP method
255
+ */
256
+ private static inferOperationType(method: string): ToolOperationType {
257
+ const m = method.toLowerCase();
258
+ if (m === 'get' || m === 'head' || m === 'options') {
259
+ return 'read' as ToolOperationType;
260
+ }
261
+ if (m === 'delete') {
262
+ return 'destructive' as ToolOperationType;
263
+ }
264
+ return 'write' as ToolOperationType;
265
+ }
266
+
267
+ /**
268
+ * Parses authentication from OpenAPI security schemes
269
+ */
270
+ private static parseAuthentication(
271
+ spec: OpenAPISpec,
272
+ envVarPrefix?: string
273
+ ): AuthConfig | undefined {
274
+ if (!spec.security || spec.security.length === 0) {
275
+ return undefined;
276
+ }
277
+
278
+ const securityReq = spec.security[0];
279
+ if (!securityReq) {
280
+ return undefined;
281
+ }
282
+ const schemeName = Object.keys(securityReq)[0];
283
+
284
+ if (!schemeName || !spec.components?.securitySchemes) {
285
+ return undefined;
286
+ }
287
+
288
+ const scheme = spec.components.securitySchemes[schemeName];
289
+ if (!scheme) {
290
+ return undefined;
291
+ }
292
+
293
+ const envPrefix = envVarPrefix || this.sanitizeName(spec.info.title).toUpperCase();
294
+
295
+ switch (scheme.type) {
296
+ case 'apiKey':
297
+ return {
298
+ scheme: 'apiKey',
299
+ in: scheme.in === 'query' ? 'query' : 'header',
300
+ name: scheme.name || 'X-API-Key',
301
+ envVar: `${envPrefix}_API_KEY`,
302
+ } as APIKeyAuthConfig;
303
+
304
+ case 'http':
305
+ if (scheme.scheme === 'bearer') {
306
+ return {
307
+ scheme: 'bearer',
308
+ bearerFormat: scheme.bearerFormat,
309
+ envVar: `${envPrefix}_TOKEN`,
310
+ } as BearerAuthConfig;
311
+ } else if (scheme.scheme === 'basic') {
312
+ return {
313
+ scheme: 'basic',
314
+ usernameEnvVar: `${envPrefix}_USERNAME`,
315
+ passwordEnvVar: `${envPrefix}_PASSWORD`,
316
+ } as BasicAuthConfig;
317
+ }
318
+ break;
319
+
320
+ case 'oauth2':
321
+ if (scheme.flows?.clientCredentials) {
322
+ return {
323
+ scheme: 'oauth2',
324
+ flow: 'clientCredentials',
325
+ tokenUrl: scheme.flows.clientCredentials.tokenUrl,
326
+ clientIdEnvVar: `${envPrefix}_CLIENT_ID`,
327
+ clientSecretEnvVar: `${envPrefix}_CLIENT_SECRET`,
328
+ scopes: scheme.flows.clientCredentials.scopes
329
+ ? Object.keys(scheme.flows.clientCredentials.scopes)
330
+ : undefined,
331
+ } as OAuth2AuthConfig;
332
+ }
333
+ return {
334
+ scheme: 'bearer',
335
+ envVar: `${envPrefix}_TOKEN`,
336
+ } as BearerAuthConfig;
337
+ }
338
+
339
+ return undefined;
340
+ }
341
+
342
+ /**
343
+ * Loads OpenAPI spec from a URL.
344
+ * @param url - URL to fetch OpenAPI spec from
345
+ * @param httpClient - Optional HTTP client function
346
+ * @param authEnvVarPrefix - Prefix for environment variables
347
+ * @returns APIGroupConfig object
348
+ */
349
+ static async fromURL(
350
+ url: string,
351
+ httpClient?: (method: string, path: string, params?: unknown) => Promise<unknown>,
352
+ authEnvVarPrefix?: string
353
+ ): Promise<APIGroupConfig> {
354
+ const response = await fetch(url);
355
+ if (!response.ok) {
356
+ throw new Error(`Failed to fetch OpenAPI spec from ${url}: ${response.statusText}`);
357
+ }
358
+ const spec = (await response.json()) as OpenAPISpec;
359
+ return this.fromSpec(spec, httpClient, authEnvVarPrefix);
360
+ }
361
+
362
+ /**
363
+ * Loads OpenAPI spec from a file path.
364
+ * @param filePath - Path to OpenAPI spec file
365
+ * @param httpClient - Optional HTTP client function
366
+ * @param authEnvVarPrefix - Prefix for environment variables
367
+ * @returns APIGroupConfig object
368
+ */
369
+ static async fromFile(
370
+ filePath: string,
371
+ httpClient?: (method: string, path: string, params?: unknown) => Promise<unknown>,
372
+ authEnvVarPrefix?: string
373
+ ): Promise<APIGroupConfig> {
374
+ const content = await readFile(filePath, 'utf-8');
375
+ const spec = JSON.parse(content) as OpenAPISpec;
376
+ return this.fromSpec(spec, httpClient, authEnvVarPrefix);
377
+ }
378
+ }