Skip to content

feat(cli): implement exp mcp configure claude-code command #17195

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Apr 1, 2025
Prev Previous commit
Next Next commit
require project directory
  • Loading branch information
johnstcn committed Apr 1, 2025
commit e348d1e2cb5a5790e1c13af2d81981ac70a00d27
28 changes: 8 additions & 20 deletions cli/exp_mcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,17 @@ func (*RootCmd) mcpConfigureClaudeCode() *serpent.Command {
var (
apiKey string
claudeConfigPath string
projectDirectory string
systemPrompt string
taskPrompt string
testBinaryName string
)
cmd := &serpent.Command{
Use: "claude-code",
Short: "Configure the Claude Code server.",
Use: "claude-code <project-directory>",
Short: "Configure the Claude Code server. You will need to run this command for each project you want to use. Specify the project directory as the first argument.",
Handler: func(inv *serpent.Invocation) error {
if len(inv.Args) == 0 {
return xerrors.Errorf("project directory is required")
}
projectDirectory := inv.Args[0]
fs := afero.NewOsFs()
binPath, err := os.Executable()
if err != nil {
Expand Down Expand Up @@ -174,20 +176,6 @@ func (*RootCmd) mcpConfigureClaudeCode() *serpent.Command {
Flag: "claude-system-prompt",
Value: serpent.StringOf(&systemPrompt),
},
{
Name: "task-prompt",
Description: "The task prompt to use for the Claude Code server.",
Env: "CODER_MCP_CLAUDE_TASK_PROMPT",
Flag: "claude-task-prompt",
Value: serpent.StringOf(&taskPrompt),
},
{
Name: "project-directory",
Description: "The project directory to use for the Claude Code server.",
Env: "CODER_MCP_CLAUDE_PROJECT_DIRECTORY",
Flag: "claude-project-directory",
Value: serpent.StringOf(&projectDirectory),
},
{
Name: "test-binary-name",
Description: "Only used for testing.",
Expand Down Expand Up @@ -428,7 +416,7 @@ func configureClaude(fs afero.Fs, cfg ClaudeConfig) error {
return xerrors.Errorf("failed to stat claude config: %w", err)
}
// Touch the file to create it if it doesn't exist.
if err = afero.WriteFile(fs, cfg.ConfigPath, []byte(`{}`), 0600); err != nil {
if err = afero.WriteFile(fs, cfg.ConfigPath, []byte(`{}`), 0o600); err != nil {
return xerrors.Errorf("failed to touch claude config: %w", err)
}
}
Expand Down Expand Up @@ -513,7 +501,7 @@ func configureClaude(fs afero.Fs, cfg ClaudeConfig) error {
if err != nil {
return xerrors.Errorf("failed to marshal claude config: %w", err)
}
err = afero.WriteFile(fs, cfg.ConfigPath, newConfigBytes, 0644)
err = afero.WriteFile(fs, cfg.ConfigPath, newConfigBytes, 0o644)
if err != nil {
return xerrors.Errorf("failed to write claude config: %w", err)
}
Expand Down
22 changes: 14 additions & 8 deletions cli/exp_mcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,18 @@ func TestExpMcpServer(t *testing.T) {
})
}

func TestExpMcpConfigure(t *testing.T) {
t.Run("ClaudeCode", func(t *testing.T) {
//nolint:tparallel,paralleltest
func TestExpMcpConfigureClaudeCode(t *testing.T) {
t.Run("NoProjectDirectory", func(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitShort)
cancelCtx, cancel := context.WithCancel(ctx)
t.Cleanup(cancel)

inv, _ := clitest.New(t, "exp", "mcp", "configure", "claude-code")
err := inv.WithContext(cancelCtx).Run()
require.ErrorContains(t, err, "project directory is required")
})
t.Run("NewConfig", func(t *testing.T) {
t.Setenv("CODER_AGENT_TOKEN", "test-agent-token")
ctx := testutil.Context(t, testutil.WaitShort)
cancelCtx, cancel := context.WithCancel(ctx)
Expand Down Expand Up @@ -182,12 +192,10 @@ func TestExpMcpConfigure(t *testing.T) {
}
}`

inv, root := clitest.New(t, "exp", "mcp", "configure", "claude-code",
inv, root := clitest.New(t, "exp", "mcp", "configure", "claude-code", "/path/to/project",
"--claude-api-key=test-api-key",
"--claude-config-path="+claudeConfigPath,
"--claude-project-directory=/path/to/project",
"--claude-system-prompt=test-system-prompt",
"--claude-task-prompt=test-task-prompt",
"--claude-test-binary-name=pathtothecoderbinary",
)
clitest.SetupConfig(t, client, root)
Expand Down Expand Up @@ -246,12 +254,10 @@ func TestExpMcpConfigure(t *testing.T) {
}
}`

inv, root := clitest.New(t, "exp", "mcp", "configure", "claude-code",
inv, root := clitest.New(t, "exp", "mcp", "configure", "claude-code", "/path/to/project",
"--claude-api-key=test-api-key",
"--claude-config-path="+claudeConfigPath,
"--claude-project-directory=/path/to/project",
"--claude-system-prompt=test-system-prompt",
"--claude-task-prompt=test-task-prompt",
"--claude-test-binary-name=pathtothecoderbinary",
)

Expand Down