Skip to content

Commit 2c45a43

Browse files
committed
parse mcp tool json
1 parent a421135 commit 2c45a43

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed

cmd/src/mcp_parse.go

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
//go:generate ../../scripts/gen-mcp-tool-json.sh mcp_tools.json
2+
package main
3+
4+
import (
5+
_ "embed"
6+
"encoding/json"
7+
"errors"
8+
"fmt"
9+
)
10+
11+
//go:embed mcp_tools.json
12+
var mcpToolListJSON []byte
13+
14+
type MCPToolDef struct {
15+
Name string `json:"name"`
16+
Description string `json:"description"`
17+
InputSchema Schema `json:"inputSchema"`
18+
OutputSchema Schema `json:"outputSchema"`
19+
}
20+
21+
type InputProperty struct {
22+
Name string
23+
Type string
24+
Description string
25+
ItemType string
26+
}
27+
28+
type Schema struct {
29+
Schema string `json:"$schema"`
30+
SchemaObject
31+
}
32+
33+
type RawSchema struct {
34+
Type string `json:"type"`
35+
Description string `json:"description"`
36+
Schema string `json:"$schema"`
37+
Required []string `json:"required,omitempty"`
38+
AdditionalProperties bool `json:"additionalProperties"`
39+
Properties map[string]json.RawMessage `json:"properties"`
40+
Items json.RawMessage `json:"items"`
41+
}
42+
43+
type SchemaValue interface {
44+
Type() string
45+
}
46+
47+
type SchemaObject struct {
48+
Kind string `json:"type"`
49+
Description string `json:"description"`
50+
Required []string `json:"required,omitempty"`
51+
AdditionalProperties bool `json:"additionalProperties"`
52+
Properties map[string]SchemaValue `json:"properties"`
53+
}
54+
55+
func (s SchemaObject) Type() string { return s.Kind }
56+
57+
type SchemaArray struct {
58+
Kind string `json:"type"`
59+
Description string `json:"description"`
60+
Items []SchemaValue `json:"items"`
61+
}
62+
63+
func (s SchemaArray) Type() string { return s.Kind }
64+
65+
type SchemaPrimitive struct {
66+
Description string `json:"description"`
67+
Kind string `json:"type"`
68+
}
69+
70+
func (s SchemaPrimitive) Type() string { return s.Kind }
71+
72+
type PropertyType struct {
73+
Type string `json:"type"`
74+
}
75+
76+
type Parser struct {
77+
errors []error
78+
}
79+
80+
func (p *Parser) parseRootSchema(r RawSchema) Schema {
81+
return Schema{
82+
Schema: r.Schema,
83+
SchemaObject: SchemaObject{
84+
Kind: r.Type,
85+
Description: r.Description,
86+
Required: r.Required,
87+
AdditionalProperties: r.AdditionalProperties,
88+
Properties: p.parseProperties(r.Properties),
89+
},
90+
}
91+
}
92+
93+
func (p *Parser) parseSchema(r *RawSchema) SchemaValue {
94+
switch r.Type {
95+
case "object":
96+
return &SchemaObject{
97+
Kind: r.Type,
98+
Description: r.Description,
99+
Required: r.Required,
100+
AdditionalProperties: r.AdditionalProperties,
101+
Properties: p.parseProperties(r.Properties),
102+
}
103+
case "array":
104+
var items []SchemaValue
105+
if len(r.Items) > 0 {
106+
var itemRaw RawSchema
107+
if err := json.Unmarshal(r.Items, &itemRaw); err == nil {
108+
items = append(items, p.parseSchema(&itemRaw))
109+
} else {
110+
p.errors = append(p.errors, fmt.Errorf("failed to unmarshal array items: %w", err))
111+
}
112+
}
113+
return &SchemaArray{
114+
Kind: r.Type,
115+
Description: r.Description,
116+
Items: items,
117+
}
118+
default:
119+
return &SchemaPrimitive{
120+
Kind: r.Type,
121+
Description: r.Description,
122+
}
123+
}
124+
}
125+
126+
func (p *Parser) parseProperties(props map[string]json.RawMessage) map[string]SchemaValue {
127+
res := make(map[string]SchemaValue)
128+
for name, raw := range props {
129+
var r RawSchema
130+
if err := json.Unmarshal(raw, &r); err != nil {
131+
p.errors = append(p.errors, fmt.Errorf("failed to parse property %q: %w", name, err))
132+
continue
133+
}
134+
res[name] = p.parseSchema(&r)
135+
}
136+
return res
137+
}
138+
139+
func LoadMCPToolDefinitions(data []byte) (map[string]*MCPToolDef, error) {
140+
defs := struct {
141+
Tools []struct {
142+
Name string `json:"name"`
143+
Description string `json:"description"`
144+
InputSchema RawSchema `json:"inputSchema"`
145+
OutputSchema RawSchema `json:"outputSchema"`
146+
} `json:"tools"`
147+
}{}
148+
149+
if err := json.Unmarshal(data, &defs); err != nil {
150+
// TODO: think we should panic instead
151+
return nil, err
152+
}
153+
154+
tools := map[string]*MCPToolDef{}
155+
parser := &Parser{}
156+
157+
for _, t := range defs.Tools {
158+
tools[t.Name] = &MCPToolDef{
159+
Name: t.Name,
160+
Description: t.Description,
161+
InputSchema: parser.parseRootSchema(t.InputSchema),
162+
OutputSchema: parser.parseRootSchema(t.OutputSchema),
163+
}
164+
}
165+
166+
if len(parser.errors) > 0 {
167+
return tools, errors.Join(parser.errors...)
168+
}
169+
170+
return tools, nil
171+
}

0 commit comments

Comments
 (0)