Download packages/cli/src/commands/mcp/add.ts from SaylorTwift/gemini-cli: direct link, hf CLI and curl.
- Browser
- Download file 7.58 kB
-
https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/cli/src/commands/mcp/add.ts
- Command line
-
hf download hf://SaylorTwift/gemini-cli/packages/cli/src/commands/mcp/add.ts
-
curl -L -o add.ts https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/cli/src/commands/mcp/add.ts
7.58 kB
| /** | |
| * @license | |
| * Copyright 2025 Google LLC | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| // File for 'gemini mcp add' command | |
| import type { CommandModule } from 'yargs'; | |
| import { loadSettings, SettingScope } from '../../config/settings.js'; | |
| import { debugLogger, type MCPServerConfig } from '@google/gemini-cli-core'; | |
| import { exitCli } from '../utils.js'; | |
| async function addMcpServer( | |
| name: string, | |
| commandOrUrl: string, | |
| args: Array<string | number> | undefined, | |
| options: { | |
| scope: string; | |
| transport: string; | |
| env: string[] | undefined; | |
| header: string[] | undefined; | |
| timeout?: number; | |
| trust?: boolean; | |
| description?: string; | |
| includeTools?: string[]; | |
| excludeTools?: string[]; | |
| }, | |
| ) { | |
| const { | |
| scope, | |
| transport, | |
| env, | |
| header, | |
| timeout, | |
| trust, | |
| description, | |
| includeTools, | |
| excludeTools, | |
| } = options; | |
| const settings = loadSettings(process.cwd()); | |
| const inHome = settings.workspace.path === settings.user.path; | |
| if (scope === 'project' && inHome) { | |
| debugLogger.error( | |
| 'Error: Please use --scope user to edit settings in the home directory.', | |
| ); | |
| process.exit(1); | |
| } | |
| const settingsScope = | |
| scope === 'user' ? SettingScope.User : SettingScope.Workspace; | |
| let newServer: Partial<MCPServerConfig> = {}; | |
| const headers = header?.reduce( | |
| (acc, curr) => { | |
| const [key, ...valueParts] = curr.split(':'); | |
| const value = valueParts.join(':').trim(); | |
| if (key.trim() && value) { | |
| acc[key.trim()] = value; | |
| } | |
| return acc; | |
| }, | |
| {} as Record<string, string>, | |
| ); | |
| switch (transport) { | |
| case 'sse': | |
| newServer = { | |
| url: commandOrUrl, | |
| type: 'sse', | |
| headers, | |
| timeout, | |
| trust, | |
| description, | |
| includeTools, | |
| excludeTools, | |
| }; | |
| break; | |
| case 'http': | |
| newServer = { | |
| url: commandOrUrl, | |
| type: 'http', | |
| headers, | |
| timeout, | |
| trust, | |
| description, | |
| includeTools, | |
| excludeTools, | |
| }; | |
| break; | |
| case 'stdio': | |
| default: | |
| newServer = { | |
| command: commandOrUrl, | |
| args: args?.map(String), | |
| env: env?.reduce( | |
| (acc, curr) => { | |
| const [key, value] = curr.split('='); | |
| if (key && value) { | |
| acc[key] = value; | |
| } | |
| return acc; | |
| }, | |
| {} as Record<string, string>, | |
| ), | |
| timeout, | |
| trust, | |
| description, | |
| includeTools, | |
| excludeTools, | |
| }; | |
| break; | |
| } | |
| const existingSettings = settings.forScope(settingsScope).settings; | |
| const mcpServers = existingSettings.mcpServers || {}; | |
| const isExistingServer = !!mcpServers[name]; | |
| if (isExistingServer) { | |
| debugLogger.log( | |
| `MCP server "${name}" is already configured within ${scope} settings.`, | |
| ); | |
| } | |
| mcpServers[name] = newServer as MCPServerConfig; | |
| settings.setValue(settingsScope, 'mcpServers', mcpServers); | |
| if (isExistingServer) { | |
| debugLogger.log(`MCP server "${name}" updated in ${scope} settings.`); | |
| } else { | |
| debugLogger.log( | |
| `MCP server "${name}" added to ${scope} settings. (${transport})`, | |
| ); | |
| } | |
| } | |
| export const addCommand: CommandModule = { | |
| command: 'add <name> <commandOrUrl> [args...]', | |
| describe: 'Add a server', | |
| builder: (yargs) => | |
| yargs | |
| .usage('Usage: gemini mcp add [options] <name> <commandOrUrl> [args...]') | |
| .parserConfiguration({ | |
| 'unknown-options-as-args': true, // Pass unknown options as server args | |
| 'populate--': true, // Populate server args after -- separator | |
| }) | |
| .positional('name', { | |
| describe: 'Name of the server', | |
| type: 'string', | |
| demandOption: true, | |
| }) | |
| .positional('commandOrUrl', { | |
| describe: 'Command (stdio) or URL (sse, http)', | |
| type: 'string', | |
| demandOption: true, | |
| }) | |
| .option('scope', { | |
| alias: 's', | |
| describe: 'Configuration scope (user or project)', | |
| type: 'string', | |
| default: 'project', | |
| choices: ['user', 'project'], | |
| }) | |
| .option('transport', { | |
| alias: ['t', 'type'], | |
| describe: 'Transport type (stdio, sse, http)', | |
| type: 'string', | |
| default: 'stdio', | |
| choices: ['stdio', 'sse', 'http'], | |
| }) | |
| .option('env', { | |
| alias: 'e', | |
| describe: 'Set environment variables (e.g. -e KEY=value)', | |
| type: 'array', | |
| string: true, | |
| nargs: 1, | |
| }) | |
| .option('header', { | |
| alias: 'H', | |
| describe: | |
| 'Set HTTP headers for SSE and HTTP transports (e.g. -H "X-Api-Key: abc123" -H "Authorization: Bearer abc123")', | |
| type: 'array', | |
| string: true, | |
| nargs: 1, | |
| }) | |
| .option('timeout', { | |
| describe: 'Set connection timeout in milliseconds', | |
| type: 'number', | |
| }) | |
| .option('trust', { | |
| describe: | |
| 'Trust the server (bypass all tool call confirmation prompts)', | |
| type: 'boolean', | |
| }) | |
| .option('description', { | |
| describe: 'Set the description for the server', | |
| type: 'string', | |
| }) | |
| .option('include-tools', { | |
| describe: 'A comma-separated list of tools to include', | |
| type: 'array', | |
| string: true, | |
| }) | |
| .option('exclude-tools', { | |
| describe: 'A comma-separated list of tools to exclude', | |
| type: 'array', | |
| string: true, | |
| }) | |
| .middleware((argv) => { | |
| // Handle -- separator args as server args if present | |
| if (argv['--']) { | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| const existingArgs = (argv['args'] as Array<string | number>) || []; | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| argv['args'] = [...existingArgs, ...(argv['--'] as string[])]; | |
| } | |
| }), | |
| handler: async (argv) => { | |
| await addMcpServer( | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| argv['name'] as string, | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| argv['commandOrUrl'] as string, | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| argv['args'] as Array<string | number>, | |
| { | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| scope: argv['scope'] as string, | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| transport: argv['transport'] as string, | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| env: argv['env'] as string[], | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| header: argv['header'] as string[], | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| timeout: argv['timeout'] as number | undefined, | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| trust: argv['trust'] as boolean | undefined, | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| description: argv['description'] as string | undefined, | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| includeTools: argv['includeTools'] as string[] | undefined, | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| excludeTools: argv['excludeTools'] as string[] | undefined, | |
| }, | |
| ); | |
| await exitCli(); | |
| }, | |
| }; | |