66 "encoding/json"
77 "io"
88 "net/http"
9+ "strings"
910
1011 "github.com/sourcegraph/src-cli/internal/api"
1112
@@ -14,25 +15,59 @@ import (
1415
1516const McpURLPath = ".api/mcp/v1"
1617
17- func DoToolRequest (ctx context.Context , client api.Client , tool * ToolDef , vars map [string ]any ) (* http.Response , error ) {
18+ func FetchToolDefinitions (ctx context.Context , client api.Client ) (map [string ]* ToolDef , error ) {
19+ resp , err := doJSONRPC (ctx , client , "tools/list" , nil )
20+ if err != nil {
21+ return nil , errors .Wrap (err , "failed to list tools from mcp endpoint" )
22+ }
23+ defer resp .Body .Close ()
24+
25+ data , err := readSSEResponseData (resp )
26+ if err != nil {
27+ return nil , errors .Wrap (err , "failed to read list tools SSE response" )
28+ }
29+
30+ var rpcResp struct {
31+ Result json.RawMessage `json:"result"`
32+ Error * struct {
33+ Code int `json:"code"`
34+ Message string `json:"message"`
35+ } `json:"error,omitempty"`
36+ }
37+ if err := json .Unmarshal (data , & rpcResp ); err != nil {
38+ return nil , errors .Wrap (err , "failed to unmarshal JSON-RPC response" )
39+ }
40+ if rpcResp .Error != nil {
41+ return nil , errors .Newf ("MCP tools/list failed: %d %s" , rpcResp .Error .Code , rpcResp .Error .Message )
42+ }
43+
44+ return loadToolDefinitions (rpcResp .Result )
45+ }
46+
47+ func DoToolCall (ctx context.Context , client api.Client , tool string , vars map [string ]any ) (* http.Response , error ) {
48+ params := struct {
49+ Name string `json:"name"`
50+ Arguments map [string ]any `json:"arguments"`
51+ }{
52+ Name : tool ,
53+ Arguments : vars ,
54+ }
55+
56+ return doJSONRPC (ctx , client , "tools/call" , params )
57+ }
58+
59+ func doJSONRPC (ctx context.Context , client api.Client , method string , params any ) (* http.Response , error ) {
1860 jsonRPC := struct {
1961 Version string `json:"jsonrpc"`
2062 ID int `json:"id"`
2163 Method string `json:"method"`
22- Params any `json:"params"`
64+ Params any `json:"params,omitempty "`
2365 }{
2466 Version : "2.0" ,
2567 ID : 1 ,
26- Method : "tools/call" ,
27- Params : struct {
28- Name string `json:"name"`
29- Arguments map [string ]any `json:"arguments"`
30- }{
31- Name : tool .RawName ,
32- Arguments : vars ,
33- },
68+ Method : method ,
69+ Params : params ,
3470 }
35-
3671 buf := bytes .NewBuffer (nil )
3772 data , err := json .Marshal (jsonRPC )
3873 if err != nil {
@@ -45,9 +80,21 @@ func DoToolRequest(ctx context.Context, client api.Client, tool *ToolDef, vars m
4580 return nil , err
4681 }
4782 req .Header .Add ("Content-Type" , "application/json" )
48- req .Header .Add ("Accept" , "*/*" )
83+ req .Header .Add ("Accept" , "application/json, text/event-stream" )
84+
85+ resp , err := client .Do (req )
86+ if err != nil {
87+ return nil , err
88+ }
89+
90+ if resp .StatusCode < 200 || resp .StatusCode >= 300 {
91+ body , _ := io .ReadAll (io .LimitReader (resp .Body , 4096 ))
92+ resp .Body .Close ()
93+ return nil , errors .Newf ("MCP endpoint %s returned %d: %s" ,
94+ McpURLPath , resp .StatusCode , strings .TrimSpace (string (body )))
95+ }
4996
50- return client . Do ( req )
97+ return resp , nil
5198}
5299
53100func DecodeToolResponse (resp * http.Response ) (map [string ]json.RawMessage , error ) {
@@ -61,16 +108,21 @@ func DecodeToolResponse(resp *http.Response) (map[string]json.RawMessage, error)
61108 }
62109
63110 jsonRPCResp := struct {
64- Version string `json:"jsonrpc"`
65- ID int `json:"id"`
66- Result struct {
111+ Result struct {
67112 Content []json.RawMessage `json:"content"`
68113 StructuredContent map [string ]json.RawMessage `json:"structuredContent"`
69114 } `json:"result"`
115+ Error * struct {
116+ Code int `json:"code"`
117+ Message string `json:"message"`
118+ } `json:"error,omitempty"`
70119 }{}
71120 if err := json .Unmarshal (data , & jsonRPCResp ); err != nil {
72121 return nil , errors .Wrapf (err , "failed to unmarshal MCP JSON-RPC response" )
73122 }
123+ if jsonRPCResp .Error != nil {
124+ return nil , errors .Newf ("MCP tools/call failed: %d %s" , jsonRPCResp .Error .Code , jsonRPCResp .Error .Message )
125+ }
74126
75127 return jsonRPCResp .Result .StructuredContent , nil
76128}
0 commit comments