@@ -8,6 +8,7 @@ import type { ConfigFileContents } from '../configure/index.js';
88
99import { cursorConfigPath } from '../configure/client/cursor.js' ;
1010import { claudeConfigPath } from '../configure/client/claude.js' ;
11+ import { claudeCodeConfigPath } from '../configure/client/claude-code.js' ;
1112import { windsurfConfigPath } from '../configure/client/windsurf.js' ;
1213import { gooseConfigPath } from '../configure/client/goose.js' ;
1314import yaml from 'yaml' ;
@@ -99,7 +100,7 @@ describe('CLI', () => {
99100 help Show this help message
100101
101102 Options for configure
102- --client, -c MCP client to configure for (claude, cursor, goose, vscode, windsurf)
103+ --client, -c MCP client to configure for (claude-code, claude , cursor, goose, vscode, windsurf)
103104 --token, -t Glean API token (required)
104105 --instance, -i Glean instance name
105106 --env, -e Path to .env file containing GLEAN_INSTANCE and GLEAN_API_TOKEN
@@ -147,15 +148,15 @@ describe('CLI', () => {
147148 help Show this help message
148149
149150 Options for local
150- --client, -c MCP client to configure for (claude, cursor, goose, vscode, windsurf)
151+ --client, -c MCP client to configure for (claude-code, claude , cursor, goose, vscode, windsurf)
151152 --token, -t Glean API token (required)
152153 --instance, -i Glean instance name
153154 --env, -e Path to .env file containing GLEAN_INSTANCE and GLEAN_API_TOKEN
154155 --workspace Create workspace configuration instead of global (VS Code only)
155156
156157 Options for remote
157158 --agents Connect your Glean Agents to your MCP client. If unset, will connect the default tools.
158- --client, -c MCP client to configure for (claude, cursor, goose, vscode, windsurf)
159+ --client, -c MCP client to configure for (claude-code, claude , cursor, goose, vscode, windsurf)
159160 --token, -t Glean API token (required)
160161 --instance, -i Glean instance name
161162 --env, -e Path to .env file containing GLEAN_INSTANCE and GLEAN_API_TOKEN
@@ -197,7 +198,7 @@ describe('CLI', () => {
197198 expect ( result . exitCode ) . toEqual ( 1 ) ;
198199 expect ( result . stderr ) . toMatchInlineSnapshot ( `
199200 "Unsupported MCP client: invalid-client
200- Supported clients: claude, cursor, goose, vscode, windsurf"
201+ Supported clients: claude-code, claude , cursor, goose, vscode, windsurf"
201202 ` ) ;
202203 expect ( result . stdout ) . toMatchInlineSnapshot ( `""` ) ;
203204 } ) ;
@@ -358,6 +359,153 @@ describe('CLI', () => {
358359 ` ) ;
359360 } ) ;
360361
362+ describe ( 'Claude Code client' , ( ) => {
363+ let configPath : string ;
364+ let configFilePath : string ;
365+
366+ const { configDir, configFileName } = claudeCodeConfigPath ;
367+
368+ beforeEach ( ( ) => {
369+ configPath = path . join ( project . baseDir , configDir ) ;
370+ configFilePath = path . join ( configPath , configFileName ) ;
371+ } ) ;
372+
373+ it ( 'creates a new config file when none exists' , async ( ) => {
374+ const result = await runBin (
375+ '--client' ,
376+ 'claude-code' ,
377+ '--token' ,
378+ 'glean_api_test' ,
379+ '--instance' ,
380+ 'test-domain' ,
381+ {
382+ env : {
383+ GLEAN_MCP_CONFIG_DIR : project . baseDir ,
384+ HOME : project . baseDir ,
385+ USERPROFILE : project . baseDir ,
386+ APPDATA : project . baseDir ,
387+ } ,
388+ } ,
389+ ) ;
390+
391+ expect ( result . exitCode ) . toEqual ( 0 ) ;
392+ expect ( normalizeOutput ( result . stdout , project . baseDir ) )
393+ . toMatchInlineSnapshot ( `
394+ "Configuring Glean MCP for Claude Code...
395+ Created new configuration file at: <TMP_DIR>/.claude.json
396+
397+ Claude Code MCP configuration has been configured to: <TMP_DIR>/.claude.json
398+
399+ To use it:
400+ 1. Run \`claude mcp list\` and verify the server is listed
401+ "
402+ ` ) ;
403+
404+ const configFileContents = fs . readFileSync ( configFilePath , 'utf8' ) ;
405+
406+ expect ( fs . existsSync ( configFilePath ) ) . toBe ( true ) ;
407+ expect ( configFileContents ) . toMatchInlineSnapshot ( `
408+ "{
409+ "mcpServers": {
410+ "glean_local": {
411+ "type": "stdio",
412+ "command": "npx",
413+ "args": [
414+ "-y",
415+ "@gleanwork/local-mcp-server"
416+ ],
417+ "env": {
418+ "GLEAN_INSTANCE": "test-domain",
419+ "GLEAN_API_TOKEN": "glean_api_test"
420+ }
421+ }
422+ }
423+ }"
424+ ` ) ;
425+ } ) ;
426+
427+ it ( "adds config to existing file that doesn't have Glean config" , async ( ) => {
428+ const existingConfig = {
429+ 'some-other-config' : {
430+ options : {
431+ enabled : true ,
432+ } ,
433+ } ,
434+ '.mcpServers' : {
435+ 'github-remote' : {
436+ url : 'https://api.githubcopilot.com/mcp' ,
437+ authorization_token : 'Bearer $MY_TOKEN' ,
438+ } ,
439+ } ,
440+ } as ConfigFileContents ;
441+
442+ createConfigFile ( configFilePath , existingConfig ) ;
443+
444+ const result = await runBin (
445+ '--client' ,
446+ 'claude-code' ,
447+ '--token' ,
448+ 'glean_api_test' ,
449+ '--instance' ,
450+ 'test-domain' ,
451+ {
452+ env : {
453+ GLEAN_MCP_CONFIG_DIR : project . baseDir ,
454+ HOME : project . baseDir ,
455+ USERPROFILE : project . baseDir ,
456+ APPDATA : project . baseDir ,
457+ } ,
458+ } ,
459+ ) ;
460+
461+ expect ( result . exitCode ) . toEqual ( 0 ) ;
462+ expect ( normalizeOutput ( result . stdout , project . baseDir ) )
463+ . toMatchInlineSnapshot ( `
464+ "Configuring Glean MCP for Claude Code...
465+ Updated configuration file at: <TMP_DIR>/.claude.json
466+
467+ Claude Code MCP configuration has been configured to: <TMP_DIR>/.claude.json
468+
469+ To use it:
470+ 1. Run \`claude mcp list\` and verify the server is listed
471+ "
472+ ` ) ;
473+
474+ const configFileContents = fs . readFileSync ( configFilePath , 'utf8' ) ;
475+
476+ expect ( fs . existsSync ( configFilePath ) ) . toBe ( true ) ;
477+ expect ( configFileContents ) . toMatchInlineSnapshot ( `
478+ "{
479+ "some-other-config": {
480+ "options": {
481+ "enabled": true
482+ }
483+ },
484+ ".mcpServers": {
485+ "github-remote": {
486+ "url": "https://api.githubcopilot.com/mcp",
487+ "authorization_token": "Bearer $MY_TOKEN"
488+ }
489+ },
490+ "mcpServers": {
491+ "glean_local": {
492+ "type": "stdio",
493+ "command": "npx",
494+ "args": [
495+ "-y",
496+ "@gleanwork/local-mcp-server"
497+ ],
498+ "env": {
499+ "GLEAN_INSTANCE": "test-domain",
500+ "GLEAN_API_TOKEN": "glean_api_test"
501+ }
502+ }
503+ }
504+ }"
505+ ` ) ;
506+ } ) ;
507+ } ) ;
508+
361509 it ( 'uses token auth when both token and instance provided via flags' , async ( ) => {
362510 const result = await runBin (
363511 '--client' ,
@@ -856,6 +1004,143 @@ Error configuring client: API token is required. Please provide a token with the
8561004 } ) ;
8571005 } ) ;
8581006
1007+ describe ( 'Claude Code client' , ( ) => {
1008+ let configPath : string ;
1009+ let configFilePath : string ;
1010+
1011+ const { configDir, configFileName } = claudeCodeConfigPath ;
1012+
1013+ beforeEach ( ( ) => {
1014+ configPath = path . join ( project . baseDir , configDir ) ;
1015+ configFilePath = path . join ( configPath , configFileName ) ;
1016+ } ) ;
1017+
1018+ it ( 'creates a new config file when none exists' , async ( ) => {
1019+ const result = await runBin (
1020+ 'remote' ,
1021+ '--client' ,
1022+ 'claude-code' ,
1023+ '--token' ,
1024+ 'glean_api_test' ,
1025+ '--instance' ,
1026+ 'test-domain' ,
1027+ {
1028+ env : {
1029+ GLEAN_MCP_CONFIG_DIR : project . baseDir ,
1030+ } ,
1031+ } ,
1032+ ) ;
1033+
1034+ expect ( result . exitCode ) . toEqual ( 0 ) ;
1035+ expect ( normalizeOutput ( result . stdout , project . baseDir ) )
1036+ . toMatchInlineSnapshot ( `
1037+ "Configuring Glean MCP for Claude Code...
1038+ Created new configuration file at: <TMP_DIR>/.claude.json
1039+
1040+ Claude Code MCP configuration has been configured to: <TMP_DIR>/.claude.json
1041+
1042+ To use it:
1043+ 1. Run \`claude mcp list\` and verify the server is listed
1044+ "
1045+ ` ) ;
1046+
1047+ const configFileContents = fs . readFileSync ( configFilePath , 'utf8' ) ;
1048+
1049+ expect ( fs . existsSync ( configFilePath ) ) . toBe ( true ) ;
1050+ expect ( configFileContents ) . toMatchInlineSnapshot ( `
1051+ "{
1052+ "mcpServers": {
1053+ "glean": {
1054+ "command": "npx",
1055+ "args": [
1056+ "-y",
1057+ "@gleanwork/connect-mcp-server",
1058+ "https://test-domain-be.glean.com/mcp/default/sse",
1059+ "--header",
1060+ "Authorization:\${AUTH_HEADER}"
1061+ ],
1062+ "type": "stdio",
1063+ "env": {
1064+ "AUTH_HEADER": "Bearer glean_api_test"
1065+ }
1066+ }
1067+ }
1068+ }"
1069+ ` ) ;
1070+ } ) ;
1071+
1072+ it ( "adds config to existing file that doesn't have Glean config" , async ( ) => {
1073+ const existingConfig = {
1074+ tools : [
1075+ {
1076+ name : 'some-other-tool' ,
1077+ description : 'Another tool' ,
1078+ } ,
1079+ ] ,
1080+ } as ConfigFileContents ;
1081+
1082+ createConfigFile ( configFilePath , existingConfig ) ;
1083+
1084+ const result = await runBin (
1085+ 'remote' ,
1086+ '--client' ,
1087+ 'claude-code' ,
1088+ '--token' ,
1089+ 'glean_api_test' ,
1090+ '--instance' ,
1091+ 'test-domain' ,
1092+ {
1093+ env : {
1094+ GLEAN_MCP_CONFIG_DIR : project . baseDir ,
1095+ } ,
1096+ } ,
1097+ ) ;
1098+
1099+ expect ( result . exitCode ) . toEqual ( 0 ) ;
1100+ expect ( normalizeOutput ( result . stdout , project . baseDir ) )
1101+ . toMatchInlineSnapshot ( `
1102+ "Configuring Glean MCP for Claude Code...
1103+ Updated configuration file at: <TMP_DIR>/.claude.json
1104+
1105+ Claude Code MCP configuration has been configured to: <TMP_DIR>/.claude.json
1106+
1107+ To use it:
1108+ 1. Run \`claude mcp list\` and verify the server is listed
1109+ "
1110+ ` ) ;
1111+
1112+ const configFileContents = fs . readFileSync ( configFilePath , 'utf8' ) ;
1113+
1114+ expect ( fs . existsSync ( configFilePath ) ) . toBe ( true ) ;
1115+ expect ( configFileContents ) . toMatchInlineSnapshot ( `
1116+ "{
1117+ "tools": [
1118+ {
1119+ "name": "some-other-tool",
1120+ "description": "Another tool"
1121+ }
1122+ ],
1123+ "mcpServers": {
1124+ "glean": {
1125+ "command": "npx",
1126+ "args": [
1127+ "-y",
1128+ "@gleanwork/connect-mcp-server",
1129+ "https://test-domain-be.glean.com/mcp/default/sse",
1130+ "--header",
1131+ "Authorization:\${AUTH_HEADER}"
1132+ ],
1133+ "type": "stdio",
1134+ "env": {
1135+ "AUTH_HEADER": "Bearer glean_api_test"
1136+ }
1137+ }
1138+ }
1139+ }"
1140+ ` ) ;
1141+ } ) ;
1142+ } ) ;
1143+
8591144 describe ( 'Windsurf client' , ( ) => {
8601145 let configPath : string ;
8611146 let configFilePath : string ;
0 commit comments