Skip to content

Commit 29500f6

Browse files
committed
handle http errors / rpc errors
1 parent 96a140a commit 29500f6

1 file changed

Lines changed: 31 additions & 5 deletions

File tree

internal/mcp/mcp_request.go

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/json"
77
"io"
88
"net/http"
9+
"strings"
910

1011
"github.com/sourcegraph/src-cli/internal/api"
1112

@@ -14,22 +15,33 @@ import (
1415

1516
const McpURLPath = ".api/mcp/v1"
1617

18+
type jsonRPCError struct {
19+
Code int `json:"code"`
20+
Message string `json:"message"`
21+
}
22+
1723
func FetchToolDefinitions(ctx context.Context, client api.Client) (map[string]*ToolDef, error) {
1824
resp, err := doJSONRPC(ctx, client, "tools/list", nil)
1925
if err != nil {
2026
return nil, errors.Wrap(err, "failed to list tools from mcp endpoint")
2127
}
28+
defer resp.Body.Close()
29+
2230
data, err := readSSEResponseData(resp)
2331
if err != nil {
2432
return nil, errors.Wrap(err, "failed to read list tools SSE response")
2533
}
2634

2735
var rpcResp struct {
2836
Result json.RawMessage `json:"result"`
37+
Error *jsonRPCError `json:"error"`
2938
}
3039
if err := json.Unmarshal(data, &rpcResp); err != nil {
3140
return nil, errors.Wrap(err, "failed to unmarshal JSON-RPC response")
3241
}
42+
if rpcResp.Error != nil {
43+
return nil, errors.Newf("MCP tools/list failed: %d %s", rpcResp.Error.Code, rpcResp.Error.Message)
44+
}
3345

3446
return loadToolDefinitions(rpcResp.Result)
3547
}
@@ -70,9 +82,21 @@ func doJSONRPC(ctx context.Context, client api.Client, method string, params any
7082
return nil, err
7183
}
7284
req.Header.Add("Content-Type", "application/json")
73-
req.Header.Add("Accept", "*/*")
85+
req.Header.Add("Accept", "application/json, text/event-stream")
7486

75-
return client.Do(req)
87+
resp, err := client.Do(req)
88+
if err != nil {
89+
return nil, err
90+
}
91+
92+
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
93+
body, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
94+
resp.Body.Close()
95+
return nil, errors.Newf("MCP endpoint %s returned %d: %s",
96+
McpURLPath, resp.StatusCode, strings.TrimSpace(string(body)))
97+
}
98+
99+
return resp, nil
76100
}
77101

78102
func DecodeToolResponse(resp *http.Response) (map[string]json.RawMessage, error) {
@@ -86,16 +110,18 @@ func DecodeToolResponse(resp *http.Response) (map[string]json.RawMessage, error)
86110
}
87111

88112
jsonRPCResp := struct {
89-
Version string `json:"jsonrpc"`
90-
ID int `json:"id"`
91-
Result struct {
113+
Result struct {
92114
Content []json.RawMessage `json:"content"`
93115
StructuredContent map[string]json.RawMessage `json:"structuredContent"`
94116
} `json:"result"`
117+
Error *jsonRPCError `json:"error"`
95118
}{}
96119
if err := json.Unmarshal(data, &jsonRPCResp); err != nil {
97120
return nil, errors.Wrapf(err, "failed to unmarshal MCP JSON-RPC response")
98121
}
122+
if jsonRPCResp.Error != nil {
123+
return nil, errors.Newf("MCP tools/call failed: %d %s", jsonRPCResp.Error.Code, jsonRPCResp.Error.Message)
124+
}
99125

100126
return jsonRPCResp.Result.StructuredContent, nil
101127
}

0 commit comments

Comments
 (0)