Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | 2x 18x 2x 26x 26x 26x 26x 26x 26x 1x 26x 2x 7x 7x 7x 2x 6x 6x 18x 6x 2x 4x 4x 1x 3x 2x 1x 2x 3x 3x 3x 3x | /**
* Configuration generator for various MCP clients
*/
import { McpServerConfig, WizardConfig, MCP_CLIENT_INFO, ROLE_PRESETS } from "./types";
/**
* Escape a string for safe use in shell double-quoted context.
* Escapes: $ ` " \ and newlines
*/
function shellEscape(value: string): string {
return value
.replace(/\\/g, "\\\\")
.replace(/"/g, '\\"')
.replace(/\$/g, "\\$")
.replace(/`/g, "\\`")
.replace(/\n/g, "\\n");
}
/**
* Generate MCP server configuration object
*/
export function generateServerConfig(config: WizardConfig): McpServerConfig {
// Normalize instance URL to avoid double-appending /api/v4 later
const normalizedUrl = config.instanceUrl.replace(/\/+$/, "").replace(/\/api\/v4$/i, "");
const env: Record<string, string> = {
GITLAB_API_URL: normalizedUrl,
GITLAB_TOKEN: config.token,
};
// Add preset if mapped from role
const presetName = ROLE_PRESETS[config.role];
Eif (presetName) {
env.GITLAB_MCP_PRESET = presetName;
}
// Add read-only mode if selected
if (config.readOnly) {
env.GITLAB_READ_ONLY_MODE = "true";
}
return {
command: "npx",
args: ["-y", "@structured-world/gitlab-mcp@latest"],
env,
};
}
/**
* Generate JSON configuration for mcpServers format (most clients)
*/
export function generateMcpServersJson(config: WizardConfig, serverName = "gitlab"): string {
const serverConfig = generateServerConfig(config);
const mcpServers = {
mcpServers: {
[serverName]: serverConfig,
},
};
return JSON.stringify(mcpServers, null, 2);
}
/**
* Generate Claude Code CLI command
*/
export function generateClaudeCodeCommand(config: WizardConfig, serverName = "gitlab"): string {
const serverConfig = generateServerConfig(config);
// Build environment variable flags with proper shell escaping
const envFlags = Object.entries(serverConfig.env)
.map(([key, value]) => `--env ${key}="${shellEscape(value)}"`)
.join(" ");
// claude mcp add <name> <command> [args...] --env KEY=VALUE
return `claude mcp add ${serverName} ${serverConfig.command} ${serverConfig.args.join(" ")} ${envFlags}`;
}
/**
* Generate configuration based on client type
*/
export function generateClientConfig(config: WizardConfig): {
type: "json" | "cli" | "instructions";
content: string;
configPath?: string;
cliCommand?: string;
} {
const clientInfo = MCP_CLIENT_INFO[config.client];
// Claude Code supports CLI installation
if (config.client === "claude-code") {
return {
type: "cli",
content: generateMcpServersJson(config),
cliCommand: generateClaudeCodeCommand(config),
configPath: clientInfo.configPath,
};
}
// Most clients use mcpServers JSON format
if (config.client !== "generic") {
return {
type: "json",
content: generateMcpServersJson(config),
configPath: clientInfo.configPath,
};
}
// Generic: just provide the server config
return {
type: "instructions",
content: generateMcpServersJson(config),
};
}
/**
* Generate Claude Deep Link for one-click installation
* Format: claude://settings/mcp/add?config=BASE64
*
* Uses URL-safe Base64 encoding to handle characters that may be
* problematic in query strings (+, /, =)
*/
export function generateClaudeDeepLink(config: WizardConfig, serverName = "gitlab"): string {
const serverConfig = generateServerConfig(config);
const configObject = {
name: serverName,
...serverConfig,
};
// URL-safe Base64: replace + with -, / with _, and remove = padding
const base64Config = Buffer.from(JSON.stringify(configObject))
.toString("base64")
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "");
return `claude://settings/mcp/add?config=${base64Config}`;
}
|