Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion packages/core/src/services/shellExecutionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ const { Terminal } = pkg;

const MAX_CHILD_PROCESS_BUFFER_SIZE = 16 * 1024 * 1024; // 16MB

/**
* An environment variable that is set for shell executions. This can be used
* by downstream executables and scripts to identify that they were executed
* from within Gemini CLI.
*/
export const GEMINI_CLI_IDENTIFICATION_ENV_VAR = 'GEMINI_CLI';

/**
* The value of {@link GEMINI_CLI_IDENTIFICATION_ENV_VAR}
*/
export const GEMINI_CLI_IDENTIFICATION_ENV_VAR_VALUE = '1';

// We want to allow shell outputs that are close to the context window in size.
// 300,000 lines is roughly equivalent to a large context window, ensuring
// we capture significant output from long-running commands.
Expand Down Expand Up @@ -302,7 +314,8 @@ export class ShellExecutionService {
detached: !isWindows,
env: {
...sanitizeEnvironment(process.env, sanitizationConfig),
GEMINI_CLI: '1',
[GEMINI_CLI_IDENTIFICATION_ENV_VAR]:
GEMINI_CLI_IDENTIFICATION_ENV_VAR_VALUE,
TERM: 'xterm-256color',
PAGER: 'cat',
GIT_PAGER: 'cat',
Expand Down
22 changes: 22 additions & 0 deletions packages/core/src/tools/mcp-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1639,6 +1639,28 @@ describe('mcp-client', () => {
});
});

it('sets an env variable GEMINI_CLI=1 for stdio MCP servers', async () => {
const mockedTransport = vi
.spyOn(SdkClientStdioLib, 'StdioClientTransport')
.mockReturnValue({} as SdkClientStdioLib.StdioClientTransport);

await createTransport(
'test-server',
{
command: 'test-command',
args: ['--foo', 'bar'],
env: {},
cwd: 'test/cwd',
},
false,
EMPTY_CONFIG,
);

const callArgs = mockedTransport.mock.calls[0][0];
expect(callArgs.env).toBeDefined();
expect(callArgs.env!['GEMINI_CLI']).toBe('1');
});

it('should exclude extension settings with undefined values from environment', async () => {
const mockedTransport = vi
.spyOn(SdkClientStdioLib, 'StdioClientTransport')
Expand Down
7 changes: 6 additions & 1 deletion packages/core/src/tools/mcp-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ import {
sanitizeEnvironment,
type EnvironmentSanitizationConfig,
} from '../services/environmentSanitization.js';
import {
GEMINI_CLI_IDENTIFICATION_ENV_VAR,
GEMINI_CLI_IDENTIFICATION_ENV_VAR_VALUE,
} from '../services/shellExecutionService.js';

export const MCP_DEFAULT_TIMEOUT_MSEC = 10 * 60 * 1000; // default to 10 minutes

Expand Down Expand Up @@ -1897,10 +1901,11 @@ export async function createTransport(
let transport: Transport = new StdioClientTransport({
command: mcpServerConfig.command,
args: mcpServerConfig.args || [],
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
env: {
...sanitizeEnvironment(process.env, sanitizationConfig),
...(mcpServerConfig.env || {}),
[GEMINI_CLI_IDENTIFICATION_ENV_VAR]:
GEMINI_CLI_IDENTIFICATION_ENV_VAR_VALUE,
} as Record<string, string>,
cwd: mcpServerConfig.cwd,
stderr: 'pipe',
Expand Down
Loading