summaryrefslogtreecommitdiff
path: root/packages/cli/src/commands/mcp/list.test.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.test.ts
parentb38f377c9a2672e88dd15119b38d908c0f00b54a (diff)
feat(mcp): add `gemini mcp` commands for `add`, `remove` and `list` (#5481)
Diffstat (limited to 'packages/cli/src/commands/mcp/list.test.ts')
-rw-r--r--packages/cli/src/commands/mcp/list.test.ts154
1 files changed, 154 insertions, 0 deletions
diff --git a/packages/cli/src/commands/mcp/list.test.ts b/packages/cli/src/commands/mcp/list.test.ts
new file mode 100644
index 00000000..daf2e3d7
--- /dev/null
+++ b/packages/cli/src/commands/mcp/list.test.ts
@@ -0,0 +1,154 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
+import { listMcpServers } from './list.js';
+import { loadSettings } from '../../config/settings.js';
+import { loadExtensions } from '../../config/extension.js';
+import { createTransport } from '@google/gemini-cli-core';
+import { Client } from '@modelcontextprotocol/sdk/client/index.js';
+
+vi.mock('../../config/settings.js');
+vi.mock('../../config/extension.js');
+vi.mock('@google/gemini-cli-core');
+vi.mock('@modelcontextprotocol/sdk/client/index.js');
+
+const mockedLoadSettings = loadSettings as vi.Mock;
+const mockedLoadExtensions = loadExtensions as vi.Mock;
+const mockedCreateTransport = createTransport as vi.Mock;
+const MockedClient = Client as vi.Mock;
+
+interface MockClient {
+ connect: vi.Mock;
+ ping: vi.Mock;
+ close: vi.Mock;
+}
+
+interface MockTransport {
+ close: vi.Mock;
+}
+
+describe('mcp list command', () => {
+ let consoleSpy: vi.SpyInstance;
+ let mockClient: MockClient;
+ let mockTransport: MockTransport;
+
+ beforeEach(() => {
+ vi.resetAllMocks();
+
+ consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
+
+ mockTransport = { close: vi.fn() };
+ mockClient = {
+ connect: vi.fn(),
+ ping: vi.fn(),
+ close: vi.fn(),
+ };
+
+ MockedClient.mockImplementation(() => mockClient);
+ mockedCreateTransport.mockResolvedValue(mockTransport);
+ mockedLoadExtensions.mockReturnValue([]);
+ });
+
+ afterEach(() => {
+ consoleSpy.mockRestore();
+ });
+
+ it('should display message when no servers configured', async () => {
+ mockedLoadSettings.mockReturnValue({ merged: { mcpServers: {} } });
+
+ await listMcpServers();
+
+ expect(consoleSpy).toHaveBeenCalledWith('No MCP servers configured.');
+ });
+
+ it('should display different server types with connected status', async () => {
+ mockedLoadSettings.mockReturnValue({
+ merged: {
+ mcpServers: {
+ 'stdio-server': { command: '/path/to/server', args: ['arg1'] },
+ 'sse-server': { url: 'https://example.com/sse' },
+ 'http-server': { httpUrl: 'https://example.com/http' },
+ },
+ },
+ });
+
+ mockClient.connect.mockResolvedValue(undefined);
+ mockClient.ping.mockResolvedValue(undefined);
+
+ await listMcpServers();
+
+ expect(consoleSpy).toHaveBeenCalledWith('Configured MCP servers:\n');
+ expect(consoleSpy).toHaveBeenCalledWith(
+ expect.stringContaining(
+ 'stdio-server: /path/to/server arg1 (stdio) - Connected',
+ ),
+ );
+ expect(consoleSpy).toHaveBeenCalledWith(
+ expect.stringContaining(
+ 'sse-server: https://example.com/sse (sse) - Connected',
+ ),
+ );
+ expect(consoleSpy).toHaveBeenCalledWith(
+ expect.stringContaining(
+ 'http-server: https://example.com/http (http) - Connected',
+ ),
+ );
+ });
+
+ it('should display disconnected status when connection fails', async () => {
+ mockedLoadSettings.mockReturnValue({
+ merged: {
+ mcpServers: {
+ 'test-server': { command: '/test/server' },
+ },
+ },
+ });
+
+ mockClient.connect.mockRejectedValue(new Error('Connection failed'));
+
+ await listMcpServers();
+
+ expect(consoleSpy).toHaveBeenCalledWith(
+ expect.stringContaining(
+ 'test-server: /test/server (stdio) - Disconnected',
+ ),
+ );
+ });
+
+ it('should merge extension servers with config servers', async () => {
+ mockedLoadSettings.mockReturnValue({
+ merged: {
+ mcpServers: { 'config-server': { command: '/config/server' } },
+ },
+ });
+
+ mockedLoadExtensions.mockReturnValue([
+ {
+ config: {
+ name: 'test-extension',
+ mcpServers: { 'extension-server': { command: '/ext/server' } },
+ },
+ },
+ ]);
+
+ mockClient.connect.mockResolvedValue(undefined);
+ mockClient.ping.mockResolvedValue(undefined);
+
+ await listMcpServers();
+
+ expect(consoleSpy).toHaveBeenCalledWith(
+ expect.stringContaining(
+ 'config-server: /config/server (stdio) - Connected',
+ ),
+ );
+ expect(consoleSpy).toHaveBeenCalledWith(
+ expect.stringContaining(
+ 'extension-server: /ext/server (stdio) - Connected',
+ ),
+ );
+ });
+});