Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit86fdd92

Browse files
committed
feat(cli): add in exp mcp configure commands from kyle/tasks
1 parent9086555 commit86fdd92

File tree

4 files changed

+179
-9
lines changed

4 files changed

+179
-9
lines changed

‎cli/exp_mcp.go

Lines changed: 174 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package cli
22

33
import (
44
"context"
5+
"encoding/json"
56
"errors"
7+
"os"
8+
"path/filepath"
69

710
"cdr.dev/slog"
811
"cdr.dev/slog/sloggers/sloghuman"
@@ -13,17 +16,184 @@ import (
1316
)
1417

1518
func (r*RootCmd)mcpCommand()*serpent.Command {
19+
cmd:=&serpent.Command{
20+
Use:"mcp",
21+
Short:"Run the Coder MCP server and configure it to work with AI tools.",
22+
Long:"The Coder MCP server allows you to automatically create workspaces with parameters.",
23+
Children: []*serpent.Command{
24+
r.mcpConfigure(),
25+
r.mcpServer(),
26+
},
27+
}
28+
returncmd
29+
}
30+
31+
func (r*RootCmd)mcpConfigure()*serpent.Command {
32+
cmd:=&serpent.Command{
33+
Use:"configure",
34+
Short:"Automatically configure the MCP server.",
35+
Children: []*serpent.Command{
36+
r.mcpConfigureClaudeDesktop(),
37+
r.mcpConfigureClaudeCode(),
38+
r.mcpConfigureCursor(),
39+
},
40+
}
41+
returncmd
42+
}
43+
44+
func (r*RootCmd)mcpConfigureClaudeDesktop()*serpent.Command {
45+
cmd:=&serpent.Command{
46+
Use:"claude-desktop",
47+
Short:"Configure the Claude Desktop server.",
48+
Handler:func(_*serpent.Invocation)error {
49+
configPath,err:=os.UserConfigDir()
50+
iferr!=nil {
51+
returnerr
52+
}
53+
configPath=filepath.Join(configPath,"Claude")
54+
err=os.MkdirAll(configPath,0755)
55+
iferr!=nil {
56+
returnerr
57+
}
58+
configPath=filepath.Join(configPath,"claude_desktop_config.json")
59+
_,err=os.Stat(configPath)
60+
iferr!=nil {
61+
if!os.IsNotExist(err) {
62+
returnerr
63+
}
64+
}
65+
contents:=map[string]any{}
66+
data,err:=os.ReadFile(configPath)
67+
iferr!=nil {
68+
if!os.IsNotExist(err) {
69+
returnerr
70+
}
71+
}else {
72+
err=json.Unmarshal(data,&contents)
73+
iferr!=nil {
74+
returnerr
75+
}
76+
}
77+
binPath,err:=os.Executable()
78+
iferr!=nil {
79+
returnerr
80+
}
81+
contents["mcpServers"]=map[string]any{
82+
"coder":map[string]any{"command":binPath,"args": []string{"mcp","server"}},
83+
}
84+
data,err=json.MarshalIndent(contents,""," ")
85+
iferr!=nil {
86+
returnerr
87+
}
88+
err=os.WriteFile(configPath,data,0600)
89+
iferr!=nil {
90+
returnerr
91+
}
92+
returnnil
93+
},
94+
}
95+
returncmd
96+
}
97+
98+
func (_*RootCmd)mcpConfigureClaudeCode()*serpent.Command {
99+
cmd:=&serpent.Command{
100+
Use:"claude-code",
101+
Short:"Configure the Claude Code server.",
102+
Handler:func(_*serpent.Invocation)error {
103+
returnnil
104+
},
105+
}
106+
returncmd
107+
}
108+
109+
func (_*RootCmd)mcpConfigureCursor()*serpent.Command {
110+
varprojectbool
111+
cmd:=&serpent.Command{
112+
Use:"cursor",
113+
Short:"Configure Cursor to use Coder MCP.",
114+
Options: serpent.OptionSet{
115+
serpent.Option{
116+
Flag:"project",
117+
Env:"CODER_MCP_CURSOR_PROJECT",
118+
Description:"Use to configure a local project to use the Cursor MCP.",
119+
Value:serpent.BoolOf(&project),
120+
},
121+
},
122+
Handler:func(_*serpent.Invocation)error {
123+
dir,err:=os.Getwd()
124+
iferr!=nil {
125+
returnerr
126+
}
127+
if!project {
128+
dir,err=os.UserHomeDir()
129+
iferr!=nil {
130+
returnerr
131+
}
132+
}
133+
cursorDir:=filepath.Join(dir,".cursor")
134+
err=os.MkdirAll(cursorDir,0755)
135+
iferr!=nil {
136+
returnerr
137+
}
138+
mcpConfig:=filepath.Join(cursorDir,"mcp.json")
139+
_,err=os.Stat(mcpConfig)
140+
contents:=map[string]any{}
141+
iferr!=nil {
142+
if!os.IsNotExist(err) {
143+
returnerr
144+
}
145+
}else {
146+
data,err:=os.ReadFile(mcpConfig)
147+
iferr!=nil {
148+
returnerr
149+
}
150+
// The config can be empty, so we don't want to return an error if it is.
151+
iflen(data)>0 {
152+
err=json.Unmarshal(data,&contents)
153+
iferr!=nil {
154+
returnerr
155+
}
156+
}
157+
}
158+
mcpServers,ok:=contents["mcpServers"].(map[string]any)
159+
if!ok {
160+
mcpServers=map[string]any{}
161+
}
162+
binPath,err:=os.Executable()
163+
iferr!=nil {
164+
returnerr
165+
}
166+
mcpServers["coder"]=map[string]any{
167+
"command":binPath,
168+
"args": []string{"mcp","server"},
169+
}
170+
contents["mcpServers"]=mcpServers
171+
data,err:=json.MarshalIndent(contents,""," ")
172+
iferr!=nil {
173+
returnerr
174+
}
175+
err=os.WriteFile(mcpConfig,data,0600)
176+
iferr!=nil {
177+
returnerr
178+
}
179+
returnnil
180+
},
181+
}
182+
returncmd
183+
}
184+
185+
func (r*RootCmd)mcpServer()*serpent.Command {
16186
var (
17187
client=new(codersdk.Client)
18188
instructionsstring
19189
allowedTools []string
20190
)
21191
return&serpent.Command{
22-
Use:"mcp",
192+
Use:"server",
23193
Handler:func(inv*serpent.Invocation)error {
24-
returnmcpHandler(inv,client,instructions,allowedTools)
194+
returnmcpServerHandler(inv,client,instructions,allowedTools)
25195
},
26-
Short:"StartanMCP server that can be used to interact with a Coder deployment.",
196+
Short:"Startthe CoderMCP server.",
27197
Middleware:serpent.Chain(
28198
r.InitClient(client),
29199
),
@@ -44,7 +214,7 @@ func (r *RootCmd) mcpCommand() *serpent.Command {
44214
}
45215
}
46216

47-
funcmcpHandler(inv*serpent.Invocation,client*codersdk.Client,instructionsstring,allowedTools []string)error {
217+
funcmcpServerHandler(inv*serpent.Invocation,client*codersdk.Client,instructionsstring,allowedTools []string)error {
48218
ctx,cancel:=context.WithCancel(inv.Context())
49219
defercancel()
50220

‎cli/exp_mcp_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func TestExpMcp(t *testing.T) {
3636
_=coderdtest.CreateFirstUser(t,client)
3737

3838
// Given: we run the exp mcp command with allowed tools set
39-
inv,root:=clitest.New(t,"exp","mcp","--allowed-tools=coder_whoami,coder_list_templates")
39+
inv,root:=clitest.New(t,"exp","mcp","server","--allowed-tools=coder_whoami,coder_list_templates")
4040
inv=inv.WithContext(cancelCtx)
4141

4242
pty:=ptytest.New(t)
@@ -88,7 +88,7 @@ func TestExpMcp(t *testing.T) {
8888

8989
client:=coderdtest.New(t,nil)
9090
_=coderdtest.CreateFirstUser(t,client)
91-
inv,root:=clitest.New(t,"exp","mcp")
91+
inv,root:=clitest.New(t,"exp","mcp","server")
9292
inv=inv.WithContext(cancelCtx)
9393

9494
pty:=ptytest.New(t)
@@ -128,7 +128,7 @@ func TestExpMcp(t *testing.T) {
128128
t.Cleanup(cancel)
129129

130130
client:=coderdtest.New(t,nil)
131-
inv,root:=clitest.New(t,"exp","mcp")
131+
inv,root:=clitest.New(t,"exp","mcp","server")
132132
inv=inv.WithContext(cancelCtx)
133133

134134
pty:=ptytest.New(t)

‎cli/testdata/TestProvisioners_Golden/list.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ID CREATED AT LAST SEEN AT NAME VERSION TAGS KEY NAME STATUS CURRENT JOB ID CURRENT JOB STATUS PREVIOUS JOB ID PREVIOUS JOB STATUS ORGANIZATION
1+
ID CREATED AT LAST SEEN ATNAME VERSION TAGS KEY NAME STATUS CURRENT JOB ID CURRENT JOB STATUS PREVIOUS JOB ID PREVIOUS JOB STATUS ORGANIZATION
22
00000000-0000-0000-aaaa-000000000000 ====[timestamp]===== ====[timestamp]===== default-provisioner v0.0.0-devel map[owner: scope:organization] built-in idle <nil> <nil> 00000000-0000-0000-bbbb-000000000001 succeeded Coder
33
00000000-0000-0000-aaaa-000000000001 ====[timestamp]===== ====[timestamp]===== provisioner-1 v0.0.0 map[foo:bar owner: scope:organization] built-in busy 00000000-0000-0000-bbbb-000000000002 running <nil> <nil> Coder
44
00000000-0000-0000-aaaa-000000000002 ====[timestamp]===== ====[timestamp]===== provisioner-2 v0.0.0 map[owner: scope:organization] built-in offline <nil> <nil> 00000000-0000-0000-bbbb-000000000003 succeeded Coder
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
CREATED AT LAST SEEN AT KEY NAME NAME VERSION STATUS TAGS
1+
CREATED AT LAST SEEN ATKEY NAME NAME VERSION STATUS TAGS
22
====[timestamp]===== ====[timestamp]===== built-in test v0.0.0-devel idle map[owner: scope:organization]

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp