Skip to content

Commit 0c2242c

Browse files
sai-sunder-sdbrtly
authored andcommitted
feat(mcp): Inject GoogleCredentialProvider headers in McpClient (#13783)
1 parent 7a4280a commit 0c2242c

30 files changed

+287
-189
lines changed

packages/a2a-server/src/config/config.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import * as fs from 'node:fs';
88
import * as path from 'node:path';
9-
import { homedir } from 'node:os';
109
import * as dotenv from 'dotenv';
1110

1211
import type { TelemetryTarget } from '@google/gemini-cli-core';
@@ -17,9 +16,9 @@ import {
1716
FileDiscoveryService,
1817
ApprovalMode,
1918
loadServerHierarchicalMemory,
20-
GEMINI_DIR,
2119
DEFAULT_GEMINI_EMBEDDING_MODEL,
2220
DEFAULT_GEMINI_MODEL,
21+
Storage,
2322
type ExtensionLoader,
2423
} from '@google/gemini-cli-core';
2524

@@ -156,7 +155,7 @@ function findEnvFile(startDir: string): string | null {
156155
let currentDir = path.resolve(startDir);
157156
while (true) {
158157
// prefer gemini-specific .env under GEMINI_DIR
159-
const geminiEnvPath = path.join(currentDir, GEMINI_DIR, '.env');
158+
const geminiEnvPath = path.join(currentDir, '.env');
160159
if (fs.existsSync(geminiEnvPath)) {
161160
return geminiEnvPath;
162161
}
@@ -167,11 +166,11 @@ function findEnvFile(startDir: string): string | null {
167166
const parentDir = path.dirname(currentDir);
168167
if (parentDir === currentDir || !parentDir) {
169168
// check .env under home as fallback, again preferring gemini-specific .env
170-
const homeGeminiEnvPath = path.join(process.cwd(), GEMINI_DIR, '.env');
169+
const homeGeminiEnvPath = path.join(Storage.getConfigDir(), '.env');
171170
if (fs.existsSync(homeGeminiEnvPath)) {
172171
return homeGeminiEnvPath;
173172
}
174-
const homeEnvPath = path.join(homedir(), '.env');
173+
const homeEnvPath = path.join(Storage.getConfigDir(), '.env');
175174
if (fs.existsSync(homeEnvPath)) {
176175
return homeEnvPath;
177176
}

packages/a2a-server/src/config/extension.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,16 @@
77
// Copied exactly from packages/cli/src/config/extension.ts, last PR #1026
88

99
import {
10-
GEMINI_DIR,
10+
Storage,
1111
type MCPServerConfig,
1212
type ExtensionInstallMetadata,
1313
type GeminiCLIExtension,
1414
} from '@google/gemini-cli-core';
1515
import * as fs from 'node:fs';
1616
import * as path from 'node:path';
17-
import * as os from 'node:os';
1817
import { logger } from '../utils/logger.js';
1918

20-
export const EXTENSIONS_DIRECTORY_NAME = path.join(GEMINI_DIR, 'extensions');
19+
export const EXTENSIONS_DIRECTORY_NAME = 'extensions';
2120
export const EXTENSIONS_CONFIG_FILENAME = 'gemini-extension.json';
2221
export const INSTALL_METADATA_FILENAME = '.gemini-extension-install.json';
2322

@@ -39,7 +38,7 @@ interface ExtensionConfig {
3938
export function loadExtensions(workspaceDir: string): GeminiCLIExtension[] {
4039
const allExtensions = [
4140
...loadExtensionsFromDir(workspaceDir),
42-
...loadExtensionsFromDir(os.homedir()),
41+
...loadExtensionsFromDir(Storage.getConfigDir()),
4342
];
4443

4544
const uniqueExtensions: GeminiCLIExtension[] = [];

packages/a2a-server/src/config/settings.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@
66

77
import * as fs from 'node:fs';
88
import * as path from 'node:path';
9-
import { homedir } from 'node:os';
109

1110
import type { MCPServerConfig } from '@google/gemini-cli-core';
1211
import {
1312
debugLogger,
14-
GEMINI_DIR,
1513
getErrorMessage,
14+
Storage,
1615
type TelemetrySettings,
1716
} from '@google/gemini-cli-core';
1817
import stripJsonComments from 'strip-json-comments';
1918

20-
export const USER_SETTINGS_DIR = path.join(homedir(), GEMINI_DIR);
19+
export const USER_SETTINGS_DIR = Storage.getConfigDir();
2120
export const USER_SETTINGS_PATH = path.join(USER_SETTINGS_DIR, 'settings.json');
21+
export const WORKSPACE_SETTINGS_DIR = Storage.getWorkspaceGeminiDir();
2222

2323
// Reconcile with https://github.com/google-gemini/gemini-cli/blob/b09bc6656080d4d12e1d06734aae2ec33af5c1ed/packages/cli/src/config/settings.ts#L53
2424
export interface Settings {
@@ -61,6 +61,18 @@ export function loadSettings(workspaceDir: string): Settings {
6161

6262
// Load user settings
6363
try {
64+
if (fs.existsSync(workspaceDir || WORKSPACE_SETTINGS_DIR)) {
65+
const workspaceSettingsPath = path.join(
66+
workspaceDir || WORKSPACE_SETTINGS_DIR,
67+
'settings.json',
68+
);
69+
const userContent = fs.readFileSync(workspaceSettingsPath, 'utf-8');
70+
const parsedUserSettings = JSON.parse(
71+
stripJsonComments(userContent),
72+
) as Settings;
73+
userSettings = resolveEnvVarsInObject(parsedUserSettings);
74+
}
75+
6476
if (fs.existsSync(USER_SETTINGS_PATH)) {
6577
const userContent = fs.readFileSync(USER_SETTINGS_PATH, 'utf-8');
6678
const parsedUserSettings = JSON.parse(
@@ -76,8 +88,7 @@ export function loadSettings(workspaceDir: string): Settings {
7688
}
7789

7890
const workspaceSettingsPath = path.join(
79-
workspaceDir,
80-
GEMINI_DIR,
91+
Storage.getWorkspaceGeminiDir(),
8192
'settings.json',
8293
);
8394

packages/cli/src/config/extensions/storage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export class ExtensionStorage {
3636
}
3737

3838
static getUserExtensionsDir(): string {
39-
return new Storage(os.homedir()).getExtensionsDir();
39+
return path.join(Storage.getConfigDir(), 'extensions');
4040
}
4141

4242
static async createTmpDir(): Promise<string> {

packages/cli/src/config/extensions/variables.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import * as path from 'node:path';
87
import { type VariableSchema, VARIABLE_SCHEMA } from './variableSchema.js';
9-
import { GEMINI_DIR } from '@google/gemini-cli-core';
108

11-
export const EXTENSIONS_DIRECTORY_NAME = path.join(GEMINI_DIR, 'extensions');
9+
export const EXTENSIONS_DIRECTORY_NAME = 'extensions';
1210
export const EXTENSIONS_CONFIG_FILENAME = 'gemini-extension.json';
1311
export const INSTALL_METADATA_FILENAME = '.gemini-extension-install.json';
1412
export const EXTENSION_SETTINGS_FILENAME = '.env';

packages/cli/src/config/settings.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,9 @@ function findEnvFile(startDir: string): string | null {
505505
const parentDir = path.dirname(currentDir);
506506
if (parentDir === currentDir || !parentDir) {
507507
// check .env under home as fallback, again preferring gemini-specific .env
508-
const homeGeminiEnvPath = path.join(homedir(), GEMINI_DIR, '.env');
509-
if (fs.existsSync(homeGeminiEnvPath)) {
510-
return homeGeminiEnvPath;
508+
const userGeminiEnvPath = path.join(Storage.getConfigDir(), '.env');
509+
if (fs.existsSync(userGeminiEnvPath)) {
510+
return userGeminiEnvPath;
511511
}
512512
const homeEnvPath = path.join(homedir(), '.env');
513513
if (fs.existsSync(homeEnvPath)) {

packages/cli/src/config/trustedFolders.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,23 @@
66

77
import * as fs from 'node:fs';
88
import * as path from 'node:path';
9-
import { homedir } from 'node:os';
109
import {
1110
FatalConfigError,
1211
getErrorMessage,
1312
isWithinRoot,
1413
ideContextStore,
15-
GEMINI_DIR,
14+
Storage,
1615
} from '@google/gemini-cli-core';
1716
import type { Settings } from './settings.js';
1817
import stripJsonComments from 'strip-json-comments';
1918

2019
export const TRUSTED_FOLDERS_FILENAME = 'trustedFolders.json';
2120

22-
export function getUserSettingsDir(): string {
23-
return path.join(homedir(), GEMINI_DIR);
24-
}
25-
2621
export function getTrustedFoldersPath(): string {
2722
if (process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH']) {
2823
return process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH'];
2924
}
30-
return path.join(getUserSettingsDir(), TRUSTED_FOLDERS_FILENAME);
25+
return path.join(Storage.getConfigDir(), TRUSTED_FOLDERS_FILENAME);
3126
}
3227

3328
export enum TrustLevel {

packages/cli/src/ui/components/Notifications.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@ import { theme } from '../semantic-colors.js';
1212
import { StreamingState } from '../types.js';
1313
import { UpdateNotification } from './UpdateNotification.js';
1414

15-
import { GEMINI_DIR, Storage } from '@google/gemini-cli-core';
15+
import { Storage } from '@google/gemini-cli-core';
1616

1717
import * as fs from 'node:fs/promises';
18-
import os from 'node:os';
1918
import path from 'node:path';
2019

21-
const settingsPath = path.join(os.homedir(), GEMINI_DIR, 'settings.json');
20+
const settingsPath = path.join(Storage.getConfigDir(), 'settings.json');
2221

2322
const screenReaderNudgeFilePath = path.join(
2423
Storage.getGlobalTempDir(),

packages/cli/src/ui/hooks/useExtensionUpdates.test.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import * as os from 'node:os';
1010
import * as path from 'node:path';
1111
import { createExtension } from '../../test-utils/createExtension.js';
1212
import { useExtensionUpdates } from './useExtensionUpdates.js';
13-
import { GEMINI_DIR } from '@google/gemini-cli-core';
13+
import { Storage } from '@google/gemini-cli-core';
1414
import { render } from '../../test-utils/render.js';
1515
import { waitFor } from '../../test-utils/async.js';
1616
import { MessageType } from '../types.js';
@@ -22,6 +22,17 @@ import { ExtensionUpdateState } from '../state/extensions.js';
2222
import { ExtensionManager } from '../../config/extension-manager.js';
2323
import { loadSettings } from '../../config/settings.js';
2424

25+
beforeEach(() => {
26+
vi.stubEnv('XDG_CONFIG_HOME', '');
27+
vi.stubEnv('XDG_CACHE_HOME', '');
28+
vi.stubEnv('XDG_DATA_HOME', '');
29+
vi.stubEnv('XDG_STATE_HOME', '');
30+
});
31+
32+
afterEach(() => {
33+
vi.unstubAllEnvs();
34+
});
35+
2536
vi.mock('os', async (importOriginal) => {
2637
const mockedOs = await importOriginal<typeof os>();
2738
return {
@@ -50,7 +61,7 @@ describe('useExtensionUpdates', () => {
5061
path.join(tempHomeDir, 'gemini-cli-test-workspace-'),
5162
);
5263
vi.spyOn(process, 'cwd').mockReturnValue(tempWorkspaceDir);
53-
userExtensionsDir = path.join(tempHomeDir, GEMINI_DIR, 'extensions');
64+
userExtensionsDir = path.join(Storage.getConfigDir(), 'extensions');
5465
fs.mkdirSync(userExtensionsDir, { recursive: true });
5566
vi.mocked(checkForAllExtensionUpdates).mockReset();
5667
vi.mocked(updateExtension).mockReset();

packages/cli/src/utils/persistentState.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { PersistentState } from './persistentState.js';
1313
vi.mock('node:fs');
1414
vi.mock('@google/gemini-cli-core', () => ({
1515
Storage: {
16-
getGlobalGeminiDir: vi.fn(),
16+
getStateDir: vi.fn(),
1717
},
1818
debugLogger: {
1919
warn: vi.fn(),
@@ -27,7 +27,7 @@ describe('PersistentState', () => {
2727

2828
beforeEach(() => {
2929
vi.resetAllMocks();
30-
vi.mocked(Storage.getGlobalGeminiDir).mockReturnValue(mockDir);
30+
vi.mocked(Storage.getStateDir).mockReturnValue(mockDir);
3131
persistentState = new PersistentState();
3232
});
3333

0 commit comments

Comments
 (0)