mcp4openapi 0.1.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 (209) hide show
  1. package/LICENSE.md +7 -0
  2. package/README.md +489 -0
  3. package/dist/composite-executor.d.ts +65 -0
  4. package/dist/composite-executor.d.ts.map +1 -0
  5. package/dist/composite-executor.js +147 -0
  6. package/dist/composite-executor.js.map +1 -0
  7. package/dist/constants.d.ts +36 -0
  8. package/dist/constants.d.ts.map +1 -0
  9. package/dist/constants.js +36 -0
  10. package/dist/constants.js.map +1 -0
  11. package/dist/http-transport.d.ts +195 -0
  12. package/dist/http-transport.d.ts.map +1 -0
  13. package/dist/http-transport.js +760 -0
  14. package/dist/http-transport.js.map +1 -0
  15. package/dist/interceptors.d.ts +74 -0
  16. package/dist/interceptors.d.ts.map +1 -0
  17. package/dist/interceptors.js +220 -0
  18. package/dist/interceptors.js.map +1 -0
  19. package/dist/logger.d.ts +81 -0
  20. package/dist/logger.d.ts.map +1 -0
  21. package/dist/logger.js +264 -0
  22. package/dist/logger.js.map +1 -0
  23. package/dist/mcp-server.d.ts +110 -0
  24. package/dist/mcp-server.d.ts.map +1 -0
  25. package/dist/mcp-server.js +568 -0
  26. package/dist/mcp-server.js.map +1 -0
  27. package/dist/metrics.d.ts +86 -0
  28. package/dist/metrics.d.ts.map +1 -0
  29. package/dist/metrics.js +229 -0
  30. package/dist/metrics.js.map +1 -0
  31. package/dist/openapi-parser.d.ts +35 -0
  32. package/dist/openapi-parser.d.ts.map +1 -0
  33. package/dist/openapi-parser.js +160 -0
  34. package/dist/openapi-parser.js.map +1 -0
  35. package/dist/profile-loader.d.ts +25 -0
  36. package/dist/profile-loader.d.ts.map +1 -0
  37. package/dist/profile-loader.js +134 -0
  38. package/dist/profile-loader.js.map +1 -0
  39. package/dist/schema-validator.d.ts +32 -0
  40. package/dist/schema-validator.d.ts.map +1 -0
  41. package/dist/schema-validator.js +126 -0
  42. package/dist/schema-validator.js.map +1 -0
  43. package/dist/scripts/validate-profile.d.ts +9 -0
  44. package/dist/scripts/validate-profile.d.ts.map +1 -0
  45. package/dist/scripts/validate-profile.js +289 -0
  46. package/dist/scripts/validate-profile.js.map +1 -0
  47. package/dist/scripts/validate-schema.d.ts +9 -0
  48. package/dist/scripts/validate-schema.d.ts.map +1 -0
  49. package/dist/scripts/validate-schema.js +84 -0
  50. package/dist/scripts/validate-schema.js.map +1 -0
  51. package/dist/src/composite-executor.d.ts +75 -0
  52. package/dist/src/composite-executor.d.ts.map +1 -0
  53. package/dist/src/composite-executor.js +175 -0
  54. package/dist/src/composite-executor.js.map +1 -0
  55. package/dist/src/constants.d.ts +36 -0
  56. package/dist/src/constants.d.ts.map +1 -0
  57. package/dist/src/constants.js +36 -0
  58. package/dist/src/constants.js.map +1 -0
  59. package/dist/src/dag-executor.d.ts +49 -0
  60. package/dist/src/dag-executor.d.ts.map +1 -0
  61. package/dist/src/dag-executor.js +138 -0
  62. package/dist/src/dag-executor.js.map +1 -0
  63. package/dist/src/errors.d.ts +47 -0
  64. package/dist/src/errors.d.ts.map +1 -0
  65. package/dist/src/errors.js +99 -0
  66. package/dist/src/errors.js.map +1 -0
  67. package/dist/src/generated-schemas.d.ts +661 -0
  68. package/dist/src/generated-schemas.d.ts.map +1 -0
  69. package/dist/src/generated-schemas.js +66 -0
  70. package/dist/src/generated-schemas.js.map +1 -0
  71. package/dist/src/http-client-factory.d.ts +62 -0
  72. package/dist/src/http-client-factory.d.ts.map +1 -0
  73. package/dist/src/http-client-factory.js +121 -0
  74. package/dist/src/http-client-factory.js.map +1 -0
  75. package/dist/src/http-transport.d.ts +194 -0
  76. package/dist/src/http-transport.d.ts.map +1 -0
  77. package/dist/src/http-transport.js +851 -0
  78. package/dist/src/http-transport.js.map +1 -0
  79. package/dist/src/index.d.ts +8 -0
  80. package/dist/src/index.d.ts.map +1 -0
  81. package/dist/src/index.js +59 -0
  82. package/dist/src/index.js.map +1 -0
  83. package/dist/src/interceptors.d.ts +78 -0
  84. package/dist/src/interceptors.d.ts.map +1 -0
  85. package/dist/src/interceptors.js +252 -0
  86. package/dist/src/interceptors.js.map +1 -0
  87. package/dist/src/jsonrpc-validator.d.ts +27 -0
  88. package/dist/src/jsonrpc-validator.d.ts.map +1 -0
  89. package/dist/src/jsonrpc-validator.js +58 -0
  90. package/dist/src/jsonrpc-validator.js.map +1 -0
  91. package/dist/src/lib.d.ts +8 -0
  92. package/dist/src/lib.d.ts.map +1 -0
  93. package/dist/src/lib.js +7 -0
  94. package/dist/src/lib.js.map +1 -0
  95. package/dist/src/logger.d.ts +81 -0
  96. package/dist/src/logger.d.ts.map +1 -0
  97. package/dist/src/logger.js +264 -0
  98. package/dist/src/logger.js.map +1 -0
  99. package/dist/src/mcp-server.d.ts +117 -0
  100. package/dist/src/mcp-server.d.ts.map +1 -0
  101. package/dist/src/mcp-server.js +621 -0
  102. package/dist/src/mcp-server.js.map +1 -0
  103. package/dist/src/metrics.d.ts +86 -0
  104. package/dist/src/metrics.d.ts.map +1 -0
  105. package/dist/src/metrics.js +229 -0
  106. package/dist/src/metrics.js.map +1 -0
  107. package/dist/src/naming-warnings.d.ts +23 -0
  108. package/dist/src/naming-warnings.d.ts.map +1 -0
  109. package/dist/src/naming-warnings.js +83 -0
  110. package/dist/src/naming-warnings.js.map +1 -0
  111. package/dist/src/naming.d.ts +58 -0
  112. package/dist/src/naming.d.ts.map +1 -0
  113. package/dist/src/naming.js +510 -0
  114. package/dist/src/naming.js.map +1 -0
  115. package/dist/src/openapi-parser.d.ts +49 -0
  116. package/dist/src/openapi-parser.d.ts.map +1 -0
  117. package/dist/src/openapi-parser.js +216 -0
  118. package/dist/src/openapi-parser.js.map +1 -0
  119. package/dist/src/profile-loader.d.ts +77 -0
  120. package/dist/src/profile-loader.d.ts.map +1 -0
  121. package/dist/src/profile-loader.js +443 -0
  122. package/dist/src/profile-loader.js.map +1 -0
  123. package/dist/src/schema-validator.d.ts +30 -0
  124. package/dist/src/schema-validator.d.ts.map +1 -0
  125. package/dist/src/schema-validator.js +115 -0
  126. package/dist/src/schema-validator.js.map +1 -0
  127. package/dist/src/testing/fixtures.d.ts +268 -0
  128. package/dist/src/testing/fixtures.d.ts.map +1 -0
  129. package/dist/src/testing/fixtures.js +210 -0
  130. package/dist/src/testing/fixtures.js.map +1 -0
  131. package/dist/src/testing/mock-gitlab-server.d.ts +34 -0
  132. package/dist/src/testing/mock-gitlab-server.d.ts.map +1 -0
  133. package/dist/src/testing/mock-gitlab-server.js +351 -0
  134. package/dist/src/testing/mock-gitlab-server.js.map +1 -0
  135. package/dist/src/testing/mock-utils.d.ts +41 -0
  136. package/dist/src/testing/mock-utils.d.ts.map +1 -0
  137. package/dist/src/testing/mock-utils.js +59 -0
  138. package/dist/src/testing/mock-utils.js.map +1 -0
  139. package/dist/src/testing/test-http-utils.d.ts +52 -0
  140. package/dist/src/testing/test-http-utils.d.ts.map +1 -0
  141. package/dist/src/testing/test-http-utils.js +109 -0
  142. package/dist/src/testing/test-http-utils.js.map +1 -0
  143. package/dist/src/testing/test-types.d.ts +76 -0
  144. package/dist/src/testing/test-types.d.ts.map +1 -0
  145. package/dist/src/testing/test-types.js +7 -0
  146. package/dist/src/testing/test-types.js.map +1 -0
  147. package/dist/src/tool-generator.d.ts +43 -0
  148. package/dist/src/tool-generator.d.ts.map +1 -0
  149. package/dist/src/tool-generator.js +123 -0
  150. package/dist/src/tool-generator.js.map +1 -0
  151. package/dist/src/types/http-transport.d.ts +45 -0
  152. package/dist/src/types/http-transport.d.ts.map +1 -0
  153. package/dist/src/types/http-transport.js +8 -0
  154. package/dist/src/types/http-transport.js.map +1 -0
  155. package/dist/src/types/openapi.d.ts +50 -0
  156. package/dist/src/types/openapi.d.ts.map +1 -0
  157. package/dist/src/types/openapi.js +9 -0
  158. package/dist/src/types/openapi.js.map +1 -0
  159. package/dist/src/types/profile.d.ts +80 -0
  160. package/dist/src/types/profile.d.ts.map +1 -0
  161. package/dist/src/types/profile.js +9 -0
  162. package/dist/src/types/profile.js.map +1 -0
  163. package/dist/src/validation-utils.d.ts +15 -0
  164. package/dist/src/validation-utils.d.ts.map +1 -0
  165. package/dist/src/validation-utils.js +25 -0
  166. package/dist/src/validation-utils.js.map +1 -0
  167. package/dist/testing/fixtures.d.ts +186 -0
  168. package/dist/testing/fixtures.d.ts.map +1 -0
  169. package/dist/testing/fixtures.js +135 -0
  170. package/dist/testing/fixtures.js.map +1 -0
  171. package/dist/testing/http-integration.test.d.ts +7 -0
  172. package/dist/testing/http-integration.test.d.ts.map +1 -0
  173. package/dist/testing/http-integration.test.js +383 -0
  174. package/dist/testing/http-integration.test.js.map +1 -0
  175. package/dist/testing/http-multiuser.test.d.ts +10 -0
  176. package/dist/testing/http-multiuser.test.d.ts.map +1 -0
  177. package/dist/testing/http-multiuser.test.js +255 -0
  178. package/dist/testing/http-multiuser.test.js.map +1 -0
  179. package/dist/testing/integration.test.d.ts +8 -0
  180. package/dist/testing/integration.test.d.ts.map +1 -0
  181. package/dist/testing/integration.test.js +247 -0
  182. package/dist/testing/integration.test.js.map +1 -0
  183. package/dist/testing/mock-gitlab-server.d.ts +34 -0
  184. package/dist/testing/mock-gitlab-server.d.ts.map +1 -0
  185. package/dist/testing/mock-gitlab-server.js +224 -0
  186. package/dist/testing/mock-gitlab-server.js.map +1 -0
  187. package/dist/testing/test-types.d.ts +59 -0
  188. package/dist/testing/test-types.d.ts.map +1 -0
  189. package/dist/testing/test-types.js +7 -0
  190. package/dist/testing/test-types.js.map +1 -0
  191. package/dist/tool-generator.d.ts +43 -0
  192. package/dist/tool-generator.d.ts.map +1 -0
  193. package/dist/tool-generator.js +123 -0
  194. package/dist/tool-generator.js.map +1 -0
  195. package/dist/tsconfig.tsbuildinfo +1 -0
  196. package/dist/types/http-transport.d.ts +39 -0
  197. package/dist/types/http-transport.d.ts.map +1 -0
  198. package/dist/types/http-transport.js +8 -0
  199. package/dist/types/http-transport.js.map +1 -0
  200. package/dist/types/openapi.d.ts +50 -0
  201. package/dist/types/openapi.d.ts.map +1 -0
  202. package/dist/types/openapi.js +9 -0
  203. package/dist/types/openapi.js.map +1 -0
  204. package/dist/types/profile.d.ts +76 -0
  205. package/dist/types/profile.d.ts.map +1 -0
  206. package/dist/types/profile.js +9 -0
  207. package/dist/types/profile.js.map +1 -0
  208. package/package.json +84 -0
  209. package/profile-schema.json +369 -0
@@ -0,0 +1,568 @@
1
+ /**
2
+ * Main MCP server implementation
3
+ *
4
+ * Why: Coordinates OpenAPI parser, profile loader, tool generator, and request execution.
5
+ * Single entry point for tool registration and invocation.
6
+ */
7
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
8
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
9
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
10
+ import { OpenAPIParser } from './openapi-parser.js';
11
+ import { ProfileLoader } from './profile-loader.js';
12
+ import { ToolGenerator } from './tool-generator.js';
13
+ import { CompositeExecutor } from './composite-executor.js';
14
+ import { InterceptorChain, HttpClient } from './interceptors.js';
15
+ import { SchemaValidator } from './schema-validator.js';
16
+ import { ConsoleLogger, JsonLogger } from './logger.js';
17
+ export class MCPServer {
18
+ server;
19
+ parser;
20
+ profile;
21
+ toolGenerator;
22
+ httpClient;
23
+ compositeExecutor;
24
+ schemaValidator;
25
+ logger;
26
+ httpTransport = null;
27
+ sessionHttpClients = new Map();
28
+ /**
29
+ * Filter response object to include only specified fields
30
+ * Supports nested objects but keeps first level of arrays
31
+ */
32
+ filterFields(data, fields) {
33
+ if (!data || typeof data !== 'object') {
34
+ return data;
35
+ }
36
+ if (Array.isArray(data)) {
37
+ return data.map(item => this.filterFields(item, fields));
38
+ }
39
+ const filtered = {};
40
+ for (const field of fields) {
41
+ if (field in data) {
42
+ filtered[field] = data[field];
43
+ }
44
+ }
45
+ return filtered;
46
+ }
47
+ constructor(logger) {
48
+ this.logger = logger || new ConsoleLogger();
49
+ this.schemaValidator = new SchemaValidator();
50
+ this.server = new Server({
51
+ name: 'mcp-from-openapi',
52
+ version: '0.1.0',
53
+ }, {
54
+ capabilities: {
55
+ tools: {},
56
+ },
57
+ });
58
+ this.parser = new OpenAPIParser();
59
+ this.toolGenerator = new ToolGenerator(this.parser);
60
+ this.setupHandlers();
61
+ }
62
+ async initialize(specPath, profilePath) {
63
+ // Load OpenAPI spec
64
+ await this.parser.load(specPath);
65
+ this.logger.info('Loaded OpenAPI spec', { specPath });
66
+ // Load profile
67
+ if (profilePath) {
68
+ const loader = new ProfileLoader();
69
+ this.profile = await loader.load(profilePath);
70
+ this.logger.info('Loaded profile', {
71
+ profile: this.profile.profile_name,
72
+ toolCount: this.profile.tools.length,
73
+ });
74
+ // DEBUG: Check response_fields
75
+ const groupsTool = this.profile.tools.find(t => t.name === 'manage_groups');
76
+ this.logger.info('[DEBUG] manage_groups tool', {
77
+ hasResponseFields: !!groupsTool?.response_fields,
78
+ responseFields: groupsTool?.response_fields
79
+ });
80
+ }
81
+ else {
82
+ this.profile = ProfileLoader.createDefaultProfile('default');
83
+ this.logger.warn('Using default profile (no profile specified)');
84
+ }
85
+ // Re-create logger with auth config for token redaction
86
+ if (this.profile.interceptors?.auth) {
87
+ this.logger = this.createLoggerWithAuth(this.profile.interceptors.auth);
88
+ this.logger.info('Logger re-configured with auth token redaction');
89
+ }
90
+ // Setup HTTP client with interceptors
91
+ // For stdio transport, create client with env token
92
+ // For HTTP transport, clients are created per-session with user's token
93
+ const baseUrl = this.getBaseUrl();
94
+ if (this.profile.interceptors?.auth) {
95
+ const envToken = process.env[this.profile.interceptors.auth.value_from_env];
96
+ if (envToken) {
97
+ // Token available in env - create global client (stdio transport)
98
+ const interceptors = new InterceptorChain(this.profile.interceptors);
99
+ this.httpClient = new HttpClient(baseUrl, interceptors);
100
+ this.compositeExecutor = new CompositeExecutor(this.parser, this.httpClient);
101
+ }
102
+ else {
103
+ // No env token - will use per-session clients (HTTP transport)
104
+ this.compositeExecutor = new CompositeExecutor(this.parser);
105
+ }
106
+ }
107
+ else {
108
+ // No auth configured
109
+ const interceptors = new InterceptorChain(this.profile.interceptors || {});
110
+ this.httpClient = new HttpClient(baseUrl, interceptors);
111
+ this.compositeExecutor = new CompositeExecutor(this.parser, this.httpClient);
112
+ }
113
+ this.logger.info('MCP server initialized', {
114
+ baseUrl,
115
+ toolCount: this.profile.tools.length,
116
+ });
117
+ }
118
+ /**
119
+ * Create logger with auth configuration for token redaction
120
+ *
121
+ * Why: Prevents sensitive tokens from appearing in logs
122
+ */
123
+ createLoggerWithAuth(authConfig) {
124
+ const logFormat = process.env.LOG_FORMAT || 'console';
125
+ const logLevel = this.logger instanceof ConsoleLogger || this.logger instanceof JsonLogger
126
+ ? this.logger.level
127
+ : undefined;
128
+ return logFormat === 'json'
129
+ ? new JsonLogger(logLevel, authConfig)
130
+ : new ConsoleLogger(logLevel, authConfig);
131
+ }
132
+ /**
133
+ * Get base URL from profile config or OpenAPI spec
134
+ */
135
+ getBaseUrl() {
136
+ const baseUrlConfig = this.profile?.interceptors?.base_url;
137
+ if (baseUrlConfig) {
138
+ const envValue = process.env[baseUrlConfig.value_from_env];
139
+ if (envValue)
140
+ return envValue;
141
+ if (baseUrlConfig.default)
142
+ return baseUrlConfig.default;
143
+ }
144
+ return this.parser.getBaseUrl();
145
+ }
146
+ /**
147
+ * Get or create HTTP client for session
148
+ */
149
+ getHttpClientForSession(sessionId) {
150
+ if (!sessionId) {
151
+ // Fallback to global client for stdio transport
152
+ if (!this.httpClient) {
153
+ const hasHttpTransport = !!this.httpTransport;
154
+ const transport = hasHttpTransport ? 'http' : 'stdio';
155
+ const authConfig = this.profile?.interceptors?.auth;
156
+ const envVarName = authConfig?.value_from_env || 'API_TOKEN';
157
+ const hasEnvToken = !!process.env[envVarName];
158
+ throw new Error(`HTTP client not initialized. ` +
159
+ `Transport: ${transport}, ` +
160
+ `HasEnvToken(${envVarName}): ${hasEnvToken}, ` +
161
+ `Suggestion: ${hasHttpTransport
162
+ ? 'Send token in Authorization header during initialization'
163
+ : `Set ${envVarName} environment variable`}`);
164
+ }
165
+ return this.httpClient;
166
+ }
167
+ // Check cache first
168
+ let client = this.sessionHttpClients.get(sessionId);
169
+ if (client) {
170
+ return client;
171
+ }
172
+ // Get auth token from session or env
173
+ const authToken = this.getAuthTokenFromSession(sessionId);
174
+ const envToken = this.profile?.interceptors?.auth
175
+ ? process.env[this.profile.interceptors.auth.value_from_env]
176
+ : undefined;
177
+ if (!authToken && !envToken) {
178
+ const authConfig = this.profile?.interceptors?.auth;
179
+ const expectedEnvVar = authConfig?.value_from_env || 'API_TOKEN';
180
+ throw new Error(`No auth token found for session ${sessionId}. ` +
181
+ `Expected token in Authorization/X-API-Token header or ${expectedEnvVar} env var`);
182
+ }
183
+ // Create new client with session-specific interceptor
184
+ if (!this.profile) {
185
+ throw new Error('Profile not initialized');
186
+ }
187
+ const baseUrl = this.getBaseUrl();
188
+ const tokenToUse = authToken || envToken;
189
+ const interceptors = new InterceptorChain(this.profile.interceptors || {}, tokenToUse);
190
+ const newClient = new HttpClient(baseUrl, interceptors);
191
+ // Double-check: Another concurrent request might have created client
192
+ // Race condition prevention: Use first client that was set
193
+ const existingClient = this.sessionHttpClients.get(sessionId);
194
+ if (existingClient) {
195
+ // Another request won the race, use its client
196
+ return existingClient;
197
+ }
198
+ // We won the race, cache our client
199
+ this.sessionHttpClients.set(sessionId, newClient);
200
+ return newClient;
201
+ }
202
+ /**
203
+ * Get auth token from HTTP transport session
204
+ */
205
+ getAuthTokenFromSession(sessionId) {
206
+ if (!this.httpTransport) {
207
+ return undefined;
208
+ }
209
+ // Use public API instead of type casting
210
+ return this.httpTransport.getSessionToken(sessionId);
211
+ }
212
+ /**
213
+ * Cleanup HTTP client for destroyed session
214
+ *
215
+ * Why: Prevent memory leak - sessions expire but cached clients stay forever
216
+ */
217
+ cleanupSessionClient(sessionId) {
218
+ const removed = this.sessionHttpClients.delete(sessionId);
219
+ if (removed) {
220
+ this.logger.info('Cleaned up session HTTP client', { sessionId });
221
+ }
222
+ }
223
+ /**
224
+ * Setup MCP request handlers
225
+ */
226
+ setupHandlers() {
227
+ // List available tools
228
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
229
+ if (!this.profile) {
230
+ throw new Error('Server not initialized');
231
+ }
232
+ const tools = this.profile.tools.map(toolDef => this.toolGenerator.generateTool(toolDef));
233
+ return { tools };
234
+ });
235
+ // Execute tool
236
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
237
+ if (!this.profile || !this.httpClient || !this.compositeExecutor) {
238
+ throw new Error('Server not initialized');
239
+ }
240
+ const toolDef = this.profile.tools.find(t => t.name === request.params.name);
241
+ if (!toolDef) {
242
+ throw new Error(`Tool not found: ${request.params.name}`);
243
+ }
244
+ const args = request.params.arguments || {};
245
+ // Validate arguments
246
+ this.toolGenerator.validateArguments(toolDef, args);
247
+ // Execute composite or simple tool
248
+ let result;
249
+ if (toolDef.composite && toolDef.steps) {
250
+ const compositeResult = await this.compositeExecutor.execute(toolDef.steps, args, toolDef.partial_results || false);
251
+ // Include metadata about completion
252
+ result = {
253
+ ...compositeResult.data,
254
+ _metadata: {
255
+ completed_steps: compositeResult.completed_steps,
256
+ total_steps: compositeResult.total_steps,
257
+ success: compositeResult.completed_steps === compositeResult.total_steps,
258
+ errors: compositeResult.errors,
259
+ },
260
+ };
261
+ }
262
+ else {
263
+ result = await this.executeSimpleTool(toolDef, args);
264
+ }
265
+ return {
266
+ content: [
267
+ {
268
+ type: 'text',
269
+ text: JSON.stringify(result, null, 2),
270
+ },
271
+ ],
272
+ };
273
+ });
274
+ }
275
+ /**
276
+ * Execute simple (non-composite) tool
277
+ *
278
+ * Why separate: Simple tools map directly to single OpenAPI operation.
279
+ * No result aggregation needed.
280
+ */
281
+ async executeSimpleTool(toolDef, args, sessionId) {
282
+ // DEBUG: Check if response_fields is present
283
+ this.logger.info('[DEBUG] executeSimpleTool', {
284
+ toolName: toolDef.name,
285
+ action: args.action,
286
+ hasResponseFields: !!toolDef.response_fields,
287
+ responseFields: toolDef.response_fields
288
+ });
289
+ const operationId = this.toolGenerator.mapActionToOperation(toolDef, args);
290
+ if (!operationId) {
291
+ throw new Error(`Could not map tool action to operation`);
292
+ }
293
+ const operation = this.parser.getOperation(operationId);
294
+ if (!operation) {
295
+ throw new Error(`Operation not found: ${operationId}`);
296
+ }
297
+ // Build request
298
+ const path = this.resolvePath(operation.path, args);
299
+ const queryParams = this.extractQueryParams(operation, args);
300
+ const body = this.extractBody(operation, args, toolDef);
301
+ // Validate request body against schema
302
+ if (body && operation.requestBody) {
303
+ const validationResult = this.schemaValidator.validateRequestBody(operation, body);
304
+ if (!validationResult.valid && validationResult.errors) {
305
+ const errorDetails = validationResult.errors
306
+ .map(e => ` - ${e.path}: ${e.message}`)
307
+ .join('\n');
308
+ throw new Error(`Request body validation failed:\n${errorDetails}`);
309
+ }
310
+ }
311
+ // Execute with session-specific client
312
+ const httpClient = this.getHttpClientForSession(sessionId);
313
+ const response = await httpClient.request(operation.method, path, {
314
+ params: queryParams,
315
+ body,
316
+ });
317
+ // Apply response field filtering if configured
318
+ let result = response.body;
319
+ if (toolDef.response_fields) {
320
+ const action = args.action;
321
+ if (action && toolDef.response_fields[action]) {
322
+ const fields = toolDef.response_fields[action];
323
+ result = this.filterFields(result, fields);
324
+ }
325
+ }
326
+ return result;
327
+ }
328
+ /**
329
+ * Resolve path parameters using profile aliases
330
+ *
331
+ * Why aliases: Different tools may use different parameter names for same path param.
332
+ * Example: GitLab uses "resource_id", "project_id", "group_id" all mapping to "{id}"
333
+ */
334
+ resolvePath(template, args) {
335
+ const aliases = this.profile?.parameter_aliases || {};
336
+ return template.replace(/\{(\w+)\}/g, (_, key) => {
337
+ // Try direct match first
338
+ if (args[key] !== undefined) {
339
+ return String(args[key]);
340
+ }
341
+ // Try aliases from profile
342
+ const possibleAliases = aliases[key] || [];
343
+ for (const alias of possibleAliases) {
344
+ if (args[alias] !== undefined) {
345
+ return String(args[alias]);
346
+ }
347
+ }
348
+ throw new Error(`Missing path parameter: ${key}` +
349
+ (possibleAliases.length > 0 ? `. Tried aliases: ${possibleAliases.join(', ')}` : ''));
350
+ });
351
+ }
352
+ /**
353
+ * Extract query parameters from args
354
+ *
355
+ * Why: Separate query params from body params. Array handling is done by HttpClient
356
+ * based on profile's array_format setting.
357
+ */
358
+ extractQueryParams(operation, args) {
359
+ const params = {};
360
+ for (const param of operation.parameters) {
361
+ if (param.in === 'query' && args[param.name] !== undefined) {
362
+ const value = args[param.name];
363
+ // Pass arrays as-is, HttpClient will serialize based on array_format
364
+ if (Array.isArray(value)) {
365
+ params[param.name] = value.map(String);
366
+ }
367
+ else {
368
+ params[param.name] = String(value);
369
+ }
370
+ }
371
+ }
372
+ return params;
373
+ }
374
+ /**
375
+ * Extract request body from args
376
+ *
377
+ * Why: For create/update operations, collect non-metadata fields into body.
378
+ * Metadata (action, resource_type, etc.) are not sent to API.
379
+ * Path/query parameters are also excluded from body.
380
+ *
381
+ * Uses metadata_params from tool definition, defaults to ['action', 'resource_type']
382
+ */
383
+ extractBody(operation, args, toolDef) {
384
+ // Metadata fields from tool definition (or defaults)
385
+ const metadataList = toolDef.metadata_params || ['action', 'resource_type'];
386
+ const metadata = new Set(metadataList);
387
+ // Collect parameter names that go in path or query
388
+ const pathOrQuery = new Set();
389
+ for (const param of operation.parameters) {
390
+ if (param.in === 'path' || param.in === 'query') {
391
+ pathOrQuery.add(param.name);
392
+ }
393
+ }
394
+ const body = {};
395
+ let hasBody = false;
396
+ for (const [key, value] of Object.entries(args)) {
397
+ if (!metadata.has(key) && !pathOrQuery.has(key) && value !== undefined) {
398
+ body[key] = value;
399
+ hasBody = true;
400
+ }
401
+ }
402
+ return hasBody ? body : undefined;
403
+ }
404
+ /**
405
+ * Start server with stdio transport
406
+ */
407
+ async runStdio() {
408
+ const transport = new StdioServerTransport();
409
+ await this.server.connect(transport);
410
+ this.logger.info('MCP server running on stdio');
411
+ }
412
+ /**
413
+ * Start server with HTTP transport
414
+ *
415
+ * Implements MCP Specification 2025-03-26 Streamable HTTP transport
416
+ *
417
+ * Why: Enables remote MCP server access with SSE streaming, session management,
418
+ * and resumability for reliable communication over HTTP.
419
+ */
420
+ async runHttp(host, port) {
421
+ const { HttpTransport } = await import('./http-transport.js');
422
+ const config = {
423
+ host,
424
+ port,
425
+ sessionTimeoutMs: parseInt(process.env.SESSION_TIMEOUT_MS || '1800000', 10),
426
+ heartbeatEnabled: process.env.HEARTBEAT_ENABLED === 'true',
427
+ heartbeatIntervalMs: parseInt(process.env.HEARTBEAT_INTERVAL_MS || '30000', 10),
428
+ metricsEnabled: process.env.METRICS_ENABLED === 'true',
429
+ metricsPath: process.env.METRICS_PATH || '/metrics',
430
+ allowedOrigins: process.env.ALLOWED_ORIGINS
431
+ ? process.env.ALLOWED_ORIGINS.split(',').map(o => o.trim())
432
+ : undefined,
433
+ };
434
+ this.httpTransport = new HttpTransport(config, this.logger);
435
+ // Set message handler to process JSON-RPC messages
436
+ this.httpTransport.setMessageHandler(async (message, sessionId) => {
437
+ return await this.handleJsonRpcMessage(message, sessionId);
438
+ });
439
+ // Register cleanup listener for session destruction (memory leak prevention)
440
+ this.httpTransport.onSessionDestroyed((sessionId) => {
441
+ this.cleanupSessionClient(sessionId);
442
+ });
443
+ await this.httpTransport.start();
444
+ this.logger.info('MCP server running on HTTP', { host, port });
445
+ }
446
+ /**
447
+ * Handle JSON-RPC message from HTTP transport
448
+ *
449
+ * Why: Unified message handling for both stdio and HTTP transports
450
+ */
451
+ async handleJsonRpcMessage(message, sessionId) {
452
+ // Handle initialize
453
+ if (this.isInitializeRequest(message)) {
454
+ return this.handleInitialize(message);
455
+ }
456
+ // Handle tool calls
457
+ if (this.isToolCallRequest(message)) {
458
+ return await this.handleToolCall(message, sessionId);
459
+ }
460
+ // Handle other JSON-RPC requests
461
+ // (tools/list, prompts/list, etc.)
462
+ return this.handleOtherRequest(message);
463
+ }
464
+ isInitializeRequest(message) {
465
+ if (typeof message !== 'object' || message === null)
466
+ return false;
467
+ const req = message;
468
+ return req.method === 'initialize';
469
+ }
470
+ isToolCallRequest(message) {
471
+ if (typeof message !== 'object' || message === null)
472
+ return false;
473
+ const req = message;
474
+ return req.method === 'tools/call';
475
+ }
476
+ handleInitialize(message) {
477
+ const req = message;
478
+ return {
479
+ jsonrpc: '2.0',
480
+ id: req.id,
481
+ result: {
482
+ protocolVersion: '2025-03-26',
483
+ serverInfo: {
484
+ name: 'mcp-from-openapi',
485
+ version: '0.1.0',
486
+ },
487
+ capabilities: {
488
+ tools: {},
489
+ },
490
+ },
491
+ };
492
+ }
493
+ async handleToolCall(message, sessionId) {
494
+ const req = message;
495
+ const params = req.params;
496
+ const toolName = params.name;
497
+ const args = params.arguments;
498
+ try {
499
+ // Find tool definition
500
+ const toolDef = this.profile?.tools.find(t => t.name === toolName);
501
+ if (!toolDef) {
502
+ throw new Error(`Tool not found: ${toolName}`);
503
+ }
504
+ // Execute tool (reuse existing execution logic)
505
+ let result;
506
+ if (toolDef.composite && toolDef.steps) {
507
+ const httpClient = this.getHttpClientForSession(sessionId);
508
+ const compositeResult = await this.compositeExecutor.execute(toolDef.steps, args, toolDef.partial_results || false, httpClient);
509
+ result = {
510
+ data: compositeResult.data,
511
+ completed_steps: compositeResult.completed_steps,
512
+ total_steps: compositeResult.total_steps,
513
+ success: compositeResult.completed_steps === compositeResult.total_steps,
514
+ errors: compositeResult.errors,
515
+ };
516
+ }
517
+ else {
518
+ result = await this.executeSimpleTool(toolDef, args, sessionId);
519
+ }
520
+ return {
521
+ jsonrpc: '2.0',
522
+ id: req.id,
523
+ result: {
524
+ content: [
525
+ {
526
+ type: 'text',
527
+ text: JSON.stringify(result, null, 2),
528
+ },
529
+ ],
530
+ },
531
+ };
532
+ }
533
+ catch (error) {
534
+ return {
535
+ jsonrpc: '2.0',
536
+ id: req.id,
537
+ error: {
538
+ code: -32603,
539
+ message: error.message,
540
+ },
541
+ };
542
+ }
543
+ }
544
+ handleOtherRequest(message) {
545
+ const req = message;
546
+ // Handle tools/list
547
+ if (req.method === 'tools/list') {
548
+ const tools = this.profile?.tools.map(toolDef => this.toolGenerator.generateTool(toolDef)) || [];
549
+ return {
550
+ jsonrpc: '2.0',
551
+ id: req.id,
552
+ result: {
553
+ tools,
554
+ },
555
+ };
556
+ }
557
+ // Unknown method
558
+ return {
559
+ jsonrpc: '2.0',
560
+ id: req.id,
561
+ error: {
562
+ code: -32601,
563
+ message: `Method not found: ${req.method}`,
564
+ },
565
+ };
566
+ }
567
+ }
568
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Prometheus Metrics Collector
3
+ *
4
+ * Why: Observability for production deployments
5
+ *
6
+ * Tracks:
7
+ * - HTTP requests (status, method, path)
8
+ * - Session lifecycle (active, created, destroyed)
9
+ * - MCP operations (tool calls, duration, errors)
10
+ * - API calls to backend (operation, status, duration)
11
+ */
12
+ import { Registry } from 'prom-client';
13
+ export interface MetricsCollectorConfig {
14
+ enabled: boolean;
15
+ prefix?: string;
16
+ }
17
+ export declare class MetricsCollector {
18
+ private registry;
19
+ private enabled;
20
+ private httpRequestsTotal;
21
+ private httpRequestDuration;
22
+ private sessionsActive;
23
+ private sessionsCreatedTotal;
24
+ private sessionsDestroyedTotal;
25
+ private mcpToolCallsTotal;
26
+ private mcpToolCallDuration;
27
+ private mcpToolCallErrors;
28
+ private apiCallsTotal;
29
+ private apiCallDuration;
30
+ private apiCallErrors;
31
+ constructor(config: MetricsCollectorConfig);
32
+ /**
33
+ * Record HTTP request
34
+ */
35
+ recordHttpRequest(method: string, path: string, status: number, durationSeconds: number): void;
36
+ /**
37
+ * Record session created
38
+ */
39
+ recordSessionCreated(): void;
40
+ /**
41
+ * Record session destroyed
42
+ */
43
+ recordSessionDestroyed(): void;
44
+ /**
45
+ * Record MCP tool call
46
+ */
47
+ recordToolCall(tool: string, status: 'success' | 'error', durationSeconds: number): void;
48
+ /**
49
+ * Record MCP tool call error
50
+ */
51
+ recordToolCallError(tool: string, errorType: string): void;
52
+ /**
53
+ * Record API call to backend
54
+ */
55
+ recordApiCall(operation: string, status: number, durationSeconds: number): void;
56
+ /**
57
+ * Record API call error
58
+ */
59
+ recordApiCallError(operation: string, errorType: string): void;
60
+ /**
61
+ * Get metrics in Prometheus format
62
+ */
63
+ getMetrics(): Promise<string>;
64
+ /**
65
+ * Get registry (for testing)
66
+ */
67
+ getRegistry(): Registry;
68
+ /**
69
+ * Normalize path for metrics (remove dynamic segments)
70
+ *
71
+ * Why: Avoid high cardinality in metrics labels
72
+ *
73
+ * Examples:
74
+ * - /mcp?sessionId=abc123 -> /mcp
75
+ * - /metrics -> /metrics
76
+ * - /health -> /health
77
+ */
78
+ private normalizePath;
79
+ /**
80
+ * Get status label (2xx, 4xx, 5xx)
81
+ *
82
+ * Why: Group similar statuses to reduce cardinality
83
+ */
84
+ private getStatusLabel;
85
+ }
86
+ //# sourceMappingURL=metrics.d.ts.map