Skip to content

Commit 4ee5883

Browse files
author
Lasim
committed
feat(mcp-catalog): integrate Claude Desktop config for MCP server creation with auto-extraction of installation methods and environment variables
1 parent 2683ffb commit 4ee5883

File tree

2 files changed

+96
-19
lines changed

2 files changed

+96
-19
lines changed

services/backend/src/routes/mcp/servers/create-global.ts

Lines changed: 93 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,26 @@ import { requireGlobalAdmin } from '../../../middleware/roleMiddleware';
55
import { McpCatalogService } from '../../../services/mcpCatalogService';
66
import { getDb } from '../../../db';
77

8+
// Claude Desktop configuration schema
9+
const claudeDesktopConfigSchema = z.object({
10+
mcpServers: z.record(z.object({
11+
command: z.string().min(1, 'Command is required'),
12+
args: z.array(z.string()),
13+
env: z.record(z.string()).optional()
14+
}))
15+
}).refine(
16+
(config) => Object.keys(config.mcpServers).length === 1,
17+
{ message: "Claude Desktop config must contain exactly one MCP server" }
18+
);
19+
820
// Request schema for creating global MCP servers
921
const createGlobalServerRequestSchema = z.object({
1022
// Required fields
1123
name: z.string().min(1, 'Name is required').max(255, 'Name must be 255 characters or less'),
1224
description: z.string().min(1, 'Description is required'),
1325
language: z.string().min(1, 'Language is required'),
1426
runtime: z.string().min(1, 'Runtime is required'),
15-
installation_methods: z.array(z.object({
16-
type: z.string().min(1, 'Installation method type is required'),
17-
command: z.string().optional(),
18-
image: z.string().optional(),
19-
description: z.string().optional()
20-
})).min(1, 'At least one installation method is required'),
27+
claude_desktop_config: claudeDesktopConfigSchema,
2128
tools: z.array(z.object({
2229
name: z.string().min(1, 'Tool name is required'),
2330
description: z.string().min(1, 'Tool description is required')
@@ -41,19 +48,48 @@ const createGlobalServerRequestSchema = z.object({
4148
author_contact: z.string().optional(),
4249
organization: z.string().optional(),
4350
license: z.string().optional(),
44-
default_config: z.record(z.any()).optional(),
45-
environment_variables: z.array(z.object({
46-
name: z.string().min(1, 'Environment variable name is required'),
47-
description: z.string().min(1, 'Environment variable description is required'),
48-
required: z.boolean().default(false),
49-
default_value: z.string().optional()
50-
})).optional(),
5151
dependencies: z.record(z.any()).optional(),
5252
category_id: z.string().optional(),
5353
tags: z.array(z.string()).optional(),
5454
featured: z.boolean().default(false)
5555
});
5656

57+
// Utility function to extract MCP configuration data from Claude Desktop config
58+
function extractMcpConfigData(claudeConfig: z.infer<typeof claudeDesktopConfigSchema>) {
59+
const serverKey = Object.keys(claudeConfig.mcpServers)[0];
60+
const serverConfig = claudeConfig.mcpServers[serverKey];
61+
62+
// Extract installation_methods (Claude Desktop format)
63+
const installation_methods = [{
64+
client: "claude-desktop",
65+
command: serverConfig.command,
66+
args: serverConfig.args,
67+
env: serverConfig.env || {}
68+
}];
69+
70+
// Extract environment_variables metadata
71+
const environment_variables = Object.keys(serverConfig.env || {}).map(envKey => ({
72+
name: envKey,
73+
description: `${envKey} environment variable`,
74+
required: true,
75+
type: "password",
76+
validation: "",
77+
placeholder: serverConfig.env![envKey]
78+
}));
79+
80+
// Extract default_config
81+
const default_config = {
82+
base_command: serverConfig.command,
83+
base_args: serverConfig.args,
84+
transport_type: "stdio",
85+
required_env: Object.keys(serverConfig.env || {}),
86+
optional_args: [],
87+
working_directory: null
88+
};
89+
90+
return { installation_methods, environment_variables, default_config };
91+
}
92+
5793
// Response schema for successful creation
5894
const createGlobalServerResponseSchema = z.object({
5995
success: z.boolean(),
@@ -162,10 +198,51 @@ export default async function createGlobalServer(server: FastifyInstance) {
162198
const db = getDb();
163199
const mcpService = new McpCatalogService(db, request.log);
164200

165-
// Force global visibility and no team ownership for global servers
201+
// Extract MCP configuration data from Claude Desktop config
202+
request.log.debug({
203+
operation: 'create_global_mcp_server',
204+
userId: request.user?.id,
205+
claudeConfig: requestData.claude_desktop_config
206+
}, 'Extracting MCP configuration data from Claude Desktop config');
207+
208+
const { installation_methods, environment_variables, default_config } = extractMcpConfigData(requestData.claude_desktop_config);
209+
210+
request.log.debug({
211+
operation: 'create_global_mcp_server',
212+
userId: request.user?.id,
213+
extractedData: {
214+
installation_methods,
215+
environment_variables,
216+
default_config
217+
}
218+
}, 'Successfully extracted MCP configuration data');
219+
220+
// Prepare server data with extracted configuration
166221
const serverData = {
167-
...requestData,
168-
visibility: 'global' as const
222+
name: requestData.name,
223+
description: requestData.description,
224+
long_description: requestData.long_description,
225+
github_url: requestData.github_url,
226+
git_branch: requestData.git_branch,
227+
homepage_url: requestData.homepage_url,
228+
language: requestData.language,
229+
runtime: requestData.runtime,
230+
runtime_min_version: requestData.runtime_min_version,
231+
installation_methods,
232+
tools: requestData.tools,
233+
resources: requestData.resources,
234+
prompts: requestData.prompts,
235+
visibility: 'global' as const,
236+
author_name: requestData.author_name,
237+
author_contact: requestData.author_contact,
238+
organization: requestData.organization,
239+
license: requestData.license,
240+
default_config,
241+
environment_variables,
242+
dependencies: requestData.dependencies,
243+
category_id: requestData.category_id,
244+
tags: requestData.tags,
245+
featured: requestData.featured
169246
};
170247

171248
const newServer = await mcpService.createServer(

services/backend/src/services/mcpCatalogService.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export interface CreateMcpServerRequest {
5252
language: string;
5353
runtime: string;
5454
runtime_min_version?: string;
55-
installation_methods: any[]; // Will be JSON stringified
55+
installation_methods: any[]; // Will be JSON stringified - auto-extracted from Claude Desktop config
5656
tools: any[]; // Will be JSON stringified
5757
resources?: any[]; // Will be JSON stringified
5858
prompts?: any[]; // Will be JSON stringified
@@ -61,8 +61,8 @@ export interface CreateMcpServerRequest {
6161
author_contact?: string;
6262
organization?: string;
6363
license?: string;
64-
default_config?: any; // Will be JSON stringified
65-
environment_variables?: any[]; // Will be JSON stringified
64+
default_config?: any; // Will be JSON stringified - auto-extracted from Claude Desktop config
65+
environment_variables?: any[]; // Will be JSON stringified - auto-extracted from Claude Desktop config
6666
dependencies?: any; // Will be JSON stringified
6767
category_id?: string;
6868
tags?: string[];

0 commit comments

Comments
 (0)