diff --git a/packages/cli/src/gemini.tsx b/packages/cli/src/gemini.tsx index eec6dc6290..4bf0e96e85 100644 --- a/packages/cli/src/gemini.tsx +++ b/packages/cli/src/gemini.tsx @@ -271,7 +271,7 @@ export async function main() { if (argv.channels && argv.channels.length > 0) { coreEvents.emitFeedback( 'info', - `Channels enabled: ${argv.channels.join(', ')}`, + `Channels listening for messages: ${argv.channels.join(', ')}`, ); } diff --git a/packages/cli/src/services/BuiltinCommandLoader.ts b/packages/cli/src/services/BuiltinCommandLoader.ts index 66806f5ef1..c55ca10b1c 100644 --- a/packages/cli/src/services/BuiltinCommandLoader.ts +++ b/packages/cli/src/services/BuiltinCommandLoader.ts @@ -22,6 +22,7 @@ import { aboutCommand } from '../ui/commands/aboutCommand.js'; import { agentsCommand } from '../ui/commands/agentsCommand.js'; import { authCommand } from '../ui/commands/authCommand.js'; import { bugCommand } from '../ui/commands/bugCommand.js'; +import { channelsCommand } from '../ui/commands/channelsCommand.js'; import { chatCommand, debugCommand } from '../ui/commands/chatCommand.js'; import { clearCommand } from '../ui/commands/clearCommand.js'; import { commandsCommand } from '../ui/commands/commandsCommand.js'; @@ -121,6 +122,7 @@ export class BuiltinCommandLoader implements ICommandLoader { ...(this.config?.isAgentsEnabled() ? [agentsCommand] : []), authCommand, bugCommand, + channelsCommand, { ...chatCommand, subCommands: chatResumeSubCommands, diff --git a/packages/cli/src/ui/AppContainer.tsx b/packages/cli/src/ui/AppContainer.tsx index 2f836d931e..4d44facb36 100644 --- a/packages/cli/src/ui/AppContainer.tsx +++ b/packages/cli/src/ui/AppContainer.tsx @@ -68,6 +68,7 @@ import { flattenMemory, type MemoryChangedPayload, type ChannelMessagePayload, + activeChannels, writeToStdout, disableMouseEvents, enterAlternateScreen, @@ -1241,6 +1242,22 @@ Logging in with Google... Restarting Gemini CLI to continue. }; }, [channelsEnabled, addMessage]); + // Warn about requested channels whose MCP servers did not declare capability. + const channelWarningFired = useRef(false); + useEffect(() => { + if (!isMcpReady || !channelsEnabled || channelWarningFired.current) return; + channelWarningFired.current = true; + const requested = config.getChannels(); + for (const name of requested) { + if (!activeChannels.has(name)) { + coreEvents.emitFeedback( + 'warning', + `Channel "${name}" was requested but the MCP server did not declare channel capability.`, + ); + } + } + }, [isMcpReady, channelsEnabled, config]); + cancelHandlerRef.current = useCallback( (shouldRestorePrompt: boolean = true) => { const pendingHistoryItems = [ diff --git a/packages/cli/src/ui/commands/channelsCommand.ts b/packages/cli/src/ui/commands/channelsCommand.ts new file mode 100644 index 0000000000..9cd4eb5ccd --- /dev/null +++ b/packages/cli/src/ui/commands/channelsCommand.ts @@ -0,0 +1,39 @@ +/** + * @license + * Copyright 2026 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { SlashCommand, CommandContext } from './types.js'; +import { CommandKind } from './types.js'; +import { + MessageType, + type ChannelInfo, + type HistoryItemChannelsList, +} from '../types.js'; +import { activeChannels } from '@google/gemini-cli-core'; + +export const channelsCommand: SlashCommand = { + name: 'channels', + description: 'List active message channels from MCP servers', + kind: CommandKind.BUILT_IN, + autoExecute: true, + action: async (context: CommandContext) => { + const channels: ChannelInfo[] = Array.from(activeChannels.entries()).map( + ([name, capability]) => ({ + name, + displayName: capability.displayName, + supportsReply: capability.supportsReply, + }), + ); + + const channelsListItem: HistoryItemChannelsList = { + type: MessageType.CHANNELS_LIST, + channels, + }; + + context.ui.addItem(channelsListItem); + + return; + }, +};