on main help sign in
chore: fix mcp servers
ef06564Kujtim Hoxha
crush-schema.json+3−8
@@ -154,7 +154,8 @@
154 "stdio",
154 "stdio",
155 "sse",
155 "sse",
156 "stdio",
156 "stdio",
157− "sse"
157+ "sse",
158+ "http"
158 ],
159 ],
159 "title": "Type",
160 "title": "Type",
160 "description": "Type of MCP connection",
161 "description": "Type of MCP connection",
@@ -176,7 +177,6 @@
176 },
177 },
177 "type": "object",
178 "type": "object",
178 "required": [
179 "required": [
179− "command",
180 "type"
180 "type"
181 ]
181 ]
182 },
182 },
@@ -253,13 +253,8 @@
253 "required": [
253 "required": [
254 "id",
254 "id",
255 "name",
255 "name",
256− "cost_per_1m_out_cached",
257 "context_window",
256 "context_window",
258− "default_max_tokens",
257+ "default_max_tokens"
259− "can_reason",
260− "reasoning_effort",
261− "has_reasoning_effort",
262− "supports_attachments"
263 ]
258 ]
264 },
259 },
265 "Options": {
260 "Options": {
crush.json+7
@@ -4,5 +4,12 @@
4 "go": {
4 "go": {
5 "command": "gopls"
5 "command": "gopls"
6 }
6 }
7+ },
8+ "mcp": {
9+ "context7": {
10+ "command": "",
11+ "url": "https://mcp.context7.com/mcp",
12+ "type": "http"
13+ }
7 }
14 }
8}
15}
go.mod+3−1
@@ -25,7 +25,7 @@ require (
25 github.com/go-logfmt/logfmt v0.6.0
25 github.com/go-logfmt/logfmt v0.6.0
26 github.com/google/uuid v1.6.0
26 github.com/google/uuid v1.6.0
27 github.com/invopop/jsonschema v0.13.0
27 github.com/invopop/jsonschema v0.13.0
28− github.com/mark3labs/mcp-go v0.17.0
28+ github.com/mark3labs/mcp-go v0.32.0
29 github.com/muesli/termenv v0.16.0
29 github.com/muesli/termenv v0.16.0
30 github.com/ncruces/go-sqlite3 v0.25.0
30 github.com/ncruces/go-sqlite3 v0.25.0
31 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
31 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
@@ -40,6 +40,8 @@ require (
40 mvdan.cc/sh/v3 v3.11.0
40 mvdan.cc/sh/v3 v3.11.0
41)
41)
42
42
43+require github.com/spf13/cast v1.7.1 // indirect
44+
43require (
45require (
44 cloud.google.com/go v0.116.0 // indirect
46 cloud.google.com/go v0.116.0 // indirect
45 cloud.google.com/go/auth v0.13.0 // indirect
47 cloud.google.com/go/auth v0.13.0 // indirect
go.sum+6−2
@@ -116,6 +116,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
116github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
116github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
117github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
117github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
118github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
118github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
119+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
120+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
119github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
121github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
120github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
122github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
121github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
123github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
@@ -165,8 +167,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69
165github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
167github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
166github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
168github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
167github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
169github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
168−github.com/mark3labs/mcp-go v0.17.0 h1:5Ps6T7qXr7De/2QTqs9h6BKeZ/qdeUeGrgM5lPzi930=
170+github.com/mark3labs/mcp-go v0.32.0 h1:fgwmbfL2gbd67obg57OfV2Dnrhs1HtSdlY/i5fn7MU8=
169−github.com/mark3labs/mcp-go v0.17.0/go.mod h1:KmJndYv7GIgcPVwEKJjNcbhVQ+hJGJhrCCB/9xITzpE=
171+github.com/mark3labs/mcp-go v0.32.0/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
170github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
172github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
171github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
173github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
172github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
174github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
@@ -224,6 +226,8 @@ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN
224github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
226github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
225github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
227github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
226github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
228github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
229+github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
230+github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
227github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
231github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
228github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
232github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
229github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
233github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
internal/config/config.go+5−4
@@ -124,13 +124,14 @@ type MCPType string
124const (
124const (
125 MCPStdio MCPType = "stdio"
125 MCPStdio MCPType = "stdio"
126 MCPSse MCPType = "sse"
126 MCPSse MCPType = "sse"
127+ MCPHttp MCPType = "http"
127)
128)
128
129
129type MCP struct {
130type MCP struct {
130− Command string `json:"command" jsonschema:"title=Command,description=Command to execute for stdio MCP servers"`
131+ Command string `json:"command,omitempty" jsonschema:"title=Command,description=Command to execute for stdio MCP servers"`
131 Env []string `json:"env,omitempty" jsonschema:"title=Environment,description=Environment variables for the MCP server"`
132 Env []string `json:"env,omitempty" jsonschema:"title=Environment,description=Environment variables for the MCP server"`
132 Args []string `json:"args,omitempty" jsonschema:"title=Arguments,description=Command line arguments for the MCP server"`
133 Args []string `json:"args,omitempty" jsonschema:"title=Arguments,description=Command line arguments for the MCP server"`
133− Type MCPType `json:"type" jsonschema:"title=Type,description=Type of MCP connection,enum=stdio,enum=sse,default=stdio"`
134+ Type MCPType `json:"type" jsonschema:"title=Type,description=Type of MCP connection,enum=stdio,enum=sse,enum=http,default=stdio"`
134 URL string `json:"url,omitempty" jsonschema:"title=URL,description=URL for SSE MCP servers"`
135 URL string `json:"url,omitempty" jsonschema:"title=URL,description=URL for SSE MCP servers"`
135 // TODO: maybe make it possible to get the value from the env
136 // TODO: maybe make it possible to get the value from the env
136 Headers map[string]string `json:"headers,omitempty" jsonschema:"title=Headers,description=HTTP headers for SSE MCP servers"`
137 Headers map[string]string `json:"headers,omitempty" jsonschema:"title=Headers,description=HTTP headers for SSE MCP servers"`
@@ -1407,8 +1408,8 @@ func (c *Config) validateMCPs(errors *ValidationErrors) {
1407 fieldPrefix := fmt.Sprintf("mcp.%s", mcpName)
1408 fieldPrefix := fmt.Sprintf("mcp.%s", mcpName)
1408
1409
1409 // Validate MCP type
1410 // Validate MCP type
1410− if mcpConfig.Type != MCPStdio && mcpConfig.Type != MCPSse {
1411+ if mcpConfig.Type != MCPStdio && mcpConfig.Type != MCPSse && mcpConfig.Type != MCPHttp {
1411− errors.Add(fieldPrefix+".type", fmt.Sprintf("invalid MCP type: %s (must be 'stdio' or 'sse')", mcpConfig.Type))
1412+ errors.Add(fieldPrefix+".type", fmt.Sprintf("invalid MCP type: %s (must be 'stdio' or 'sse' or 'http')", mcpConfig.Type))
1412 }
1413 }
1413
1414
1414 // Validate based on type
1415 // Validate based on type
internal/llm/agent/mcp-tools.go+20
@@ -12,6 +12,7 @@ import (
12 "github.com/charmbracelet/crush/internal/version"
12 "github.com/charmbracelet/crush/internal/version"
13
13
14 "github.com/mark3labs/mcp-go/client"
14 "github.com/mark3labs/mcp-go/client"
15+ "github.com/mark3labs/mcp-go/client/transport"
15 "github.com/mark3labs/mcp-go/mcp"
16 "github.com/mark3labs/mcp-go/mcp"
16)
17)
17
18
@@ -118,6 +119,15 @@ func (b *mcpTool) Run(ctx context.Context, params tools.ToolCall) (tools.ToolRes
118 return tools.NewTextErrorResponse(err.Error()), nil
119 return tools.NewTextErrorResponse(err.Error()), nil
119 }
120 }
120 return runTool(ctx, c, b.tool.Name, params.Input)
121 return runTool(ctx, c, b.tool.Name, params.Input)
122+ case config.MCPHttp:
123+ c, err := client.NewStreamableHttpClient(
124+ b.mcpConfig.URL,
125+ transport.WithHTTPHeaders(b.mcpConfig.Headers),
126+ )
127+ if err != nil {
128+ return tools.NewTextErrorResponse(err.Error()), nil
129+ }
130+ return runTool(ctx, c, b.tool.Name, params.Input)
121 case config.MCPSse:
131 case config.MCPSse:
122 c, err := client.NewSSEMCPClient(
132 c, err := client.NewSSEMCPClient(
123 b.mcpConfig.URL,
133 b.mcpConfig.URL,
@@ -187,6 +197,16 @@ func GetMcpTools(ctx context.Context, permissions permission.Service) []tools.Ba
187 continue
197 continue
188 }
198 }
189
199
200+ mcpTools = append(mcpTools, getTools(ctx, name, m, permissions, c)...)
201+ case config.MCPHttp:
202+ c, err := client.NewStreamableHttpClient(
203+ m.URL,
204+ transport.WithHTTPHeaders(m.Headers),
205+ )
206+ if err != nil {
207+ logging.Error("error creating mcp client", "error", err)
208+ continue
209+ }
190 mcpTools = append(mcpTools, getTools(ctx, name, m, permissions, c)...)
210 mcpTools = append(mcpTools, getTools(ctx, name, m, permissions, c)...)
191 case config.MCPSse:
211 case config.MCPSse:
192 c, err := client.NewSSEMCPClient(
212 c, err := client.NewSSEMCPClient(