summaryrefslogtreecommitdiff
path: root/packages/cli/src/commands/mcp/list.ts
diff options
context:
space:
mode:
authorJack Wotherspoon <[email protected]>2025-08-06 11:52:29 -0400
committerGitHub <[email protected]>2025-08-06 15:52:29 +0000
commitca4c745e3b620e3ac4eca24b610cc7b936c0a50d (patch)
treeeb1b9cfb46bd4fa2e7f9631828b0704df1050eb7 /packages/cli/src/commands/mcp/list.ts
parentb38f377c9a2672e88dd15119b38d908c0f00b54a (diff)
feat(mcp): add `gemini mcp` commands for `add`, `remove` and `list` (#5481)
Diffstat (limited to 'packages/cli/src/commands/mcp/list.ts')
-rw-r--r--packages/cli/src/commands/mcp/list.ts139
1 files changed, 139 insertions, 0 deletions
diff --git a/packages/cli/src/commands/mcp/list.ts b/packages/cli/src/commands/mcp/list.ts
new file mode 100644
index 00000000..48ea912e
--- /dev/null
+++ b/packages/cli/src/commands/mcp/list.ts
@@ -0,0 +1,139 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// File for 'gemini mcp list' command
+import type { CommandModule } from 'yargs';
+import { loadSettings } from '../../config/settings.js';
+import {
+ MCPServerConfig,
+ MCPServerStatus,
+ createTransport,
+} from '@google/gemini-cli-core';
+import { Client } from '@modelcontextprotocol/sdk/client/index.js';
+import { loadExtensions } from '../../config/extension.js';
+
+const COLOR_GREEN = '\u001b[32m';
+const COLOR_YELLOW = '\u001b[33m';
+const COLOR_RED = '\u001b[31m';
+const RESET_COLOR = '\u001b[0m';
+
+async function getMcpServersFromConfig(): Promise<
+ Record<string, MCPServerConfig>
+> {
+ const settings = loadSettings(process.cwd());
+ const extensions = loadExtensions(process.cwd());
+ const mcpServers = { ...(settings.merged.mcpServers || {}) };
+ for (const extension of extensions) {
+ Object.entries(extension.config.mcpServers || {}).forEach(
+ ([key, server]) => {
+ if (mcpServers[key]) {
+ return;
+ }
+ mcpServers[key] = {
+ ...server,
+ extensionName: extension.config.name,
+ };
+ },
+ );
+ }
+ return mcpServers;
+}
+
+async function testMCPConnection(
+ serverName: string,
+ config: MCPServerConfig,
+): Promise<MCPServerStatus> {
+ const client = new Client({
+ name: 'mcp-test-client',
+ version: '0.0.1',
+ });
+
+ let transport;
+ try {
+ // Use the same transport creation logic as core
+ transport = await createTransport(serverName, config, false);
+ } catch (_error) {
+ await client.close();
+ return MCPServerStatus.DISCONNECTED;
+ }
+
+ try {
+ // Attempt actual MCP connection with short timeout
+ await client.connect(transport, { timeout: 5000 }); // 5s timeout
+
+ // Test basic MCP protocol by pinging the server
+ await client.ping();
+
+ await client.close();
+ return MCPServerStatus.CONNECTED;
+ } catch (_error) {
+ await transport.close();
+ return MCPServerStatus.DISCONNECTED;
+ }
+}
+
+async function getServerStatus(
+ serverName: string,
+ server: MCPServerConfig,
+): Promise<MCPServerStatus> {
+ // Test all server types by attempting actual connection
+ return await testMCPConnection(serverName, server);
+}
+
+export async function listMcpServers(): Promise<void> {
+ const mcpServers = await getMcpServersFromConfig();
+ const serverNames = Object.keys(mcpServers);
+
+ if (serverNames.length === 0) {
+ console.log('No MCP servers configured.');
+ return;
+ }
+
+ console.log('Configured MCP servers:\n');
+
+ for (const serverName of serverNames) {
+ const server = mcpServers[serverName];
+
+ const status = await getServerStatus(serverName, server);
+
+ let statusIndicator = '';
+ let statusText = '';
+ switch (status) {
+ case MCPServerStatus.CONNECTED:
+ statusIndicator = COLOR_GREEN + '✓' + RESET_COLOR;
+ statusText = 'Connected';
+ break;
+ case MCPServerStatus.CONNECTING:
+ statusIndicator = COLOR_YELLOW + '…' + RESET_COLOR;
+ statusText = 'Connecting';
+ break;
+ case MCPServerStatus.DISCONNECTED:
+ default:
+ statusIndicator = COLOR_RED + '✗' + RESET_COLOR;
+ statusText = 'Disconnected';
+ break;
+ }
+
+ let serverInfo = `${serverName}: `;
+ if (server.httpUrl) {
+ serverInfo += `${server.httpUrl} (http)`;
+ } else if (server.url) {
+ serverInfo += `${server.url} (sse)`;
+ } else if (server.command) {
+ serverInfo += `${server.command} ${server.args?.join(' ') || ''} (stdio)`;
+ }
+
+ console.log(`${statusIndicator} ${serverInfo} - ${statusText}`);
+ }
+}
+
+export const listCommand: CommandModule = {
+ command: 'list',
+ describe: 'List all configured MCP servers',
+ handler: async () => {
+ await listMcpServers();
+ },
+};