Skip to content

Commit 6bfa522

Browse files
committed
feat(mcp): build flagset from mcp input schema to parse args (#1215)
- parse input schema to build flagset for mcp command
1 parent 0b1b072 commit 6bfa522

File tree

2 files changed

+32
-25
lines changed

2 files changed

+32
-25
lines changed

cmd/src/mcp.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
11
package main
22

33
import (
4-
"context"
5-
"encoding/json"
64
"flag"
75
"fmt"
8-
"strings"
96

10-
"github.com/sourcegraph/src-cli/internal/api"
117
"github.com/sourcegraph/src-cli/internal/mcp"
12-
13-
"github.com/sourcegraph/sourcegraph/lib/errors"
148
)
159

1610
func init() {
@@ -22,7 +16,7 @@ func init() {
2216
}
2317
func mcpMain(args []string) error {
2418
fmt.Println("NOTE: This command is still experimental")
25-
tools, err := mcp.LoadDefaultToolDefinitions()
19+
tools, err := mcp.LoadToolDefinitions()
2620
if err != nil {
2721
return err
2822
}

internal/mcp/mcp_parse.go

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@ package mcp
33
import (
44
_ "embed"
55
"encoding/json"
6-
"fmt"
6+
"strings"
77

88
"github.com/sourcegraph/sourcegraph/lib/errors"
99
)
1010

1111
//go:embed mcp_tools.json
12-
var _ []byte
12+
var mcpToolListJSON []byte
1313

1414
type ToolDef struct {
15-
Name string `json:"name"`
15+
Name string
16+
RawName string `json:"name"`
1617
Description string `json:"description"`
1718
InputSchema SchemaObject `json:"inputSchema"`
1819
OutputSchema SchemaObject `json:"outputSchema"`
@@ -62,13 +63,17 @@ type decoder struct {
6263
errors []error
6364
}
6465

65-
func LoadToolDefinitions(data []byte) (map[string]*ToolDef, error) {
66+
func LoadDefaultToolDefinitions() (map[string]*ToolDef, error) {
67+
return loadToolDefinitions(mcpToolListJSON)
68+
}
69+
70+
func loadToolDefinitions(data []byte) (map[string]*ToolDef, error) {
6671
defs := struct {
6772
Tools []struct {
6873
Name string `json:"name"`
6974
Description string `json:"description"`
70-
InputSchema rawSchema `json:"inputSchema"`
71-
OutputSchema rawSchema `json:"outputSchema"`
75+
InputSchema RawSchema `json:"inputSchema"`
76+
OutputSchema RawSchema `json:"outputSchema"`
7277
} `json:"tools"`
7378
}{}
7479

@@ -80,12 +85,19 @@ func LoadToolDefinitions(data []byte) (map[string]*ToolDef, error) {
8085
decoder := &decoder{}
8186

8287
for _, t := range defs.Tools {
83-
tools[t.Name] = &ToolDef{
84-
Name: t.Name,
88+
// normalize the raw mcp tool name to be without the mcp identifiers
89+
rawName := t.Name
90+
name, _ := strings.CutPrefix(rawName, "sg_")
91+
name = strings.ReplaceAll(name, "_", "-")
92+
93+
tool := &ToolDef{
94+
Name: name,
95+
RawName: rawName,
8596
Description: t.Description,
8697
InputSchema: decoder.decodeRootSchema(t.InputSchema),
8798
OutputSchema: decoder.decodeRootSchema(t.OutputSchema),
8899
}
100+
tools[tool.Name] = tool
89101
}
90102

91103
if len(decoder.errors) > 0 {
@@ -97,21 +109,22 @@ func LoadToolDefinitions(data []byte) (map[string]*ToolDef, error) {
97109

98110
func (d *decoder) decodeRootSchema(r rawSchema) SchemaObject {
99111
return SchemaObject{
100-
Type: r.Type,
101-
Description: r.Description,
102-
Required: r.Required,
103-
Properties: d.decodeProperties(r.Properties),
112+
Schema: r.SchemaVersion,
113+
Type: r.Type,
114+
Description: r.Description,
115+
Required: r.Required,
116+
Properties: d.decodeProperties(r.Properties),
104117
}
105118
}
106119

107120
func (d *decoder) decodeSchema(r *rawSchema) SchemaValue {
108121
switch r.Type {
109122
case "object":
110123
return &SchemaObject{
111-
Type: r.Type,
112-
Description: r.Description,
113-
Required: r.Required,
114-
Properties: d.decodeProperties(r.Properties),
124+
Type: r.Type,
125+
Description: r.Description,
126+
Required: r.Required,
127+
Properties: d.decodeProperties(r.Properties),
115128
}
116129
case "array":
117130
var items SchemaValue
@@ -125,7 +138,7 @@ func (d *decoder) decodeSchema(r *rawSchema) SchemaValue {
125138
if err := json.Unmarshal(r.Items, &itemRaw); err == nil {
126139
items = d.decodeSchema(&itemRaw)
127140
} else {
128-
d.errors = append(d.errors, errors.Errorf("failed to unmarshal array items: %w", err))
141+
d.errors = append(d.errors, errors.Wrap(err, "failed to unmarshal array items"))
129142
}
130143
}
131144
}
@@ -147,7 +160,7 @@ func (d *decoder) decodeProperties(props map[string]json.RawMessage) map[string]
147160
for name, raw := range props {
148161
var r rawSchema
149162
if err := json.Unmarshal(raw, &r); err != nil {
150-
d.errors = append(d.errors, fmt.Errorf("failed to parse property %q: %w", name, err))
163+
d.errors = append(d.errors, errors.Wrapf(err, "failed to parse property %q: %w", name))
151164
continue
152165
}
153166
res[name] = d.decodeSchema(&r)

0 commit comments

Comments
 (0)