@samanhappy/mcphub 0.9.3 → 0.9.4

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.
@@ -0,0 +1,256 @@
1
+ import { getServersInfo } from './mcpService.js';
2
+ import config from '../config/index.js';
3
+ import { loadSettings } from '../config/index.js';
4
+ /**
5
+ * Convert MCP tool input schema to OpenAPI parameter or request body schema
6
+ */
7
+ function convertToolSchemaToOpenAPI(tool) {
8
+ const schema = tool.inputSchema;
9
+ if (!schema || typeof schema !== 'object') {
10
+ return {};
11
+ }
12
+ // If schema has properties, convert them to parameters or request body
13
+ if (schema.properties && typeof schema.properties === 'object') {
14
+ const properties = schema.properties;
15
+ const required = Array.isArray(schema.required) ? schema.required : [];
16
+ // For simple tools with only primitive parameters, use query parameters
17
+ const hasComplexTypes = Object.values(properties).some((prop) => prop.type === 'object' ||
18
+ prop.type === 'array' ||
19
+ (prop.type === 'string' && prop.enum && prop.enum.length > 10));
20
+ if (!hasComplexTypes && Object.keys(properties).length <= 10) {
21
+ // Use query parameters for simple tools
22
+ const parameters = Object.entries(properties).map(([name, prop]) => ({
23
+ name,
24
+ in: 'query',
25
+ required: required.includes(name),
26
+ description: prop.description || `Parameter ${name}`,
27
+ schema: {
28
+ type: prop.type || 'string',
29
+ ...(prop.enum && { enum: prop.enum }),
30
+ ...(prop.default !== undefined && { default: prop.default }),
31
+ ...(prop.format && { format: prop.format }),
32
+ },
33
+ }));
34
+ return { parameters };
35
+ }
36
+ else {
37
+ // Use request body for complex tools
38
+ const requestBody = {
39
+ required: required.length > 0,
40
+ content: {
41
+ 'application/json': {
42
+ schema: {
43
+ type: 'object',
44
+ properties,
45
+ ...(required.length > 0 && { required }),
46
+ },
47
+ },
48
+ },
49
+ };
50
+ return { requestBody };
51
+ }
52
+ }
53
+ return {};
54
+ }
55
+ /**
56
+ * Generate OpenAPI operation from MCP tool
57
+ */
58
+ function generateOperationFromTool(tool, serverName) {
59
+ const { parameters, requestBody } = convertToolSchemaToOpenAPI(tool);
60
+ const operation = {
61
+ summary: tool.description || `Execute ${tool.name} tool`,
62
+ description: tool.description || `Execute the ${tool.name} tool from ${serverName} server`,
63
+ operationId: `${serverName}_${tool.name}`,
64
+ tags: [serverName],
65
+ ...(parameters && parameters.length > 0 && { parameters }),
66
+ ...(requestBody && { requestBody }),
67
+ responses: {
68
+ '200': {
69
+ description: 'Successful tool execution',
70
+ content: {
71
+ 'application/json': {
72
+ schema: {
73
+ type: 'object',
74
+ properties: {
75
+ content: {
76
+ type: 'array',
77
+ items: {
78
+ type: 'object',
79
+ properties: {
80
+ type: { type: 'string' },
81
+ text: { type: 'string' },
82
+ },
83
+ },
84
+ },
85
+ isError: { type: 'boolean' },
86
+ },
87
+ },
88
+ },
89
+ },
90
+ },
91
+ '400': {
92
+ description: 'Bad request - invalid parameters',
93
+ content: {
94
+ 'application/json': {
95
+ schema: {
96
+ type: 'object',
97
+ properties: {
98
+ error: { type: 'string' },
99
+ message: { type: 'string' },
100
+ },
101
+ },
102
+ },
103
+ },
104
+ },
105
+ '500': {
106
+ description: 'Internal server error',
107
+ content: {
108
+ 'application/json': {
109
+ schema: {
110
+ type: 'object',
111
+ properties: {
112
+ error: { type: 'string' },
113
+ message: { type: 'string' },
114
+ },
115
+ },
116
+ },
117
+ },
118
+ },
119
+ },
120
+ };
121
+ return operation;
122
+ }
123
+ /**
124
+ * Generate OpenAPI specification from MCP tools
125
+ */
126
+ export function generateOpenAPISpec(options = {}) {
127
+ const serverInfos = getServersInfo();
128
+ // Filter servers based on options
129
+ const filteredServers = serverInfos.filter((server) => server.status === 'connected' &&
130
+ (!options.serverFilter || options.serverFilter.includes(server.name)));
131
+ // Collect all tools from filtered servers
132
+ const allTools = [];
133
+ for (const serverInfo of filteredServers) {
134
+ const tools = options.includeDisabledTools
135
+ ? serverInfo.tools
136
+ : serverInfo.tools.filter((tool) => tool.enabled !== false);
137
+ for (const tool of tools) {
138
+ allTools.push({ tool, serverName: serverInfo.name });
139
+ }
140
+ }
141
+ // Generate paths from tools
142
+ const paths = {};
143
+ for (const { tool, serverName } of allTools) {
144
+ const operation = generateOperationFromTool(tool, serverName);
145
+ const { requestBody } = convertToolSchemaToOpenAPI(tool);
146
+ // Create path for the tool
147
+ const pathName = `/tools/${serverName}/${tool.name}`;
148
+ const method = requestBody ? 'post' : 'get';
149
+ if (!paths[pathName]) {
150
+ paths[pathName] = {};
151
+ }
152
+ paths[pathName][method] = operation;
153
+ }
154
+ const settings = loadSettings();
155
+ // Get server URL
156
+ const baseUrl = options.serverUrl ||
157
+ settings.systemConfig?.install?.baseUrl ||
158
+ `http://localhost:${config.port}`;
159
+ const serverUrl = `${baseUrl}${config.basePath}/api`;
160
+ // Generate OpenAPI document
161
+ const openApiDoc = {
162
+ openapi: '3.0.3',
163
+ info: {
164
+ title: options.title || 'MCPHub API',
165
+ description: options.description ||
166
+ 'OpenAPI specification for MCP tools managed by MCPHub. This enables integration with OpenWebUI and other OpenAPI-compatible systems.',
167
+ version: options.version || '1.0.0',
168
+ contact: {
169
+ name: 'MCPHub',
170
+ url: 'https://github.com/samanhappy/mcphub',
171
+ },
172
+ license: {
173
+ name: 'ISC',
174
+ url: 'https://github.com/samanhappy/mcphub/blob/main/LICENSE',
175
+ },
176
+ },
177
+ servers: [
178
+ {
179
+ url: serverUrl,
180
+ description: 'MCPHub API Server',
181
+ },
182
+ ],
183
+ paths,
184
+ components: {
185
+ schemas: {
186
+ ToolResponse: {
187
+ type: 'object',
188
+ properties: {
189
+ content: {
190
+ type: 'array',
191
+ items: {
192
+ type: 'object',
193
+ properties: {
194
+ type: { type: 'string' },
195
+ text: { type: 'string' },
196
+ },
197
+ },
198
+ },
199
+ isError: { type: 'boolean' },
200
+ },
201
+ },
202
+ ErrorResponse: {
203
+ type: 'object',
204
+ properties: {
205
+ error: { type: 'string' },
206
+ message: { type: 'string' },
207
+ },
208
+ },
209
+ },
210
+ securitySchemes: {
211
+ bearerAuth: {
212
+ type: 'http',
213
+ scheme: 'bearer',
214
+ bearerFormat: 'JWT',
215
+ },
216
+ },
217
+ },
218
+ security: [
219
+ {
220
+ bearerAuth: [],
221
+ },
222
+ ],
223
+ tags: filteredServers.map((server) => ({
224
+ name: server.name,
225
+ description: `Tools from ${server.name} server`,
226
+ })),
227
+ };
228
+ return openApiDoc;
229
+ }
230
+ /**
231
+ * Get available server names for filtering
232
+ */
233
+ export function getAvailableServers() {
234
+ const serverInfos = getServersInfo();
235
+ return serverInfos.filter((server) => server.status === 'connected').map((server) => server.name);
236
+ }
237
+ /**
238
+ * Get statistics about available tools
239
+ */
240
+ export function getToolStats() {
241
+ const serverInfos = getServersInfo();
242
+ const serverBreakdown = serverInfos.map((server) => ({
243
+ name: server.name,
244
+ toolCount: server.tools.length,
245
+ status: server.status,
246
+ }));
247
+ const totalTools = serverInfos
248
+ .filter((server) => server.status === 'connected')
249
+ .reduce((sum, server) => sum + server.tools.length, 0);
250
+ return {
251
+ totalServers: serverInfos.filter((server) => server.status === 'connected').length,
252
+ totalTools,
253
+ serverBreakdown,
254
+ };
255
+ }
256
+ //# sourceMappingURL=openApiGeneratorService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openApiGeneratorService.js","sourceRoot":"","sources":["../../src/services/openApiGeneratorService.ts"],"names":[],"mappings":"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"}