mirror of
https://github.com/googleapis/genai-toolbox.git
synced 2026-01-14 09:57:58 -05:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0f94a559b | ||
|
|
32dbb0c0f4 | ||
|
|
ce2c121c95 |
@@ -77,12 +77,12 @@ the parameter.
|
|||||||
description: Airline unique 2 letter identifier
|
description: Airline unique 2 letter identifier
|
||||||
```
|
```
|
||||||
|
|
||||||
| **field** | **type** | **required** | **description** |
|
| **field** | **type** | **required** | **description** |
|
||||||
|-------------|:---------------:|:------------:|-----------------------------------------------------------------------------|
|
|-------------|:--------------:|:------------:|-----------------------------------------------------------------------------|
|
||||||
| name | string | true | Name of the parameter. |
|
| name | string | true | Name of the parameter. |
|
||||||
| type | string | true | Must be one of "string", "integer", "float", "boolean" "array" |
|
| type | string | true | Must be one of "string", "integer", "float", "boolean" "array" |
|
||||||
| default | parameter type | false | Default value of the parameter. If provided, the parameter is not required. |
|
| default | parameter type | false | Default value of the parameter. If provided, the parameter is not required. |
|
||||||
| description | string | true | Natural language description of the parameter to describe it to the agent. |
|
| description | string | true | Natural language description of the parameter to describe it to the agent. |
|
||||||
|
|
||||||
### Array Parameters
|
### Array Parameters
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ in the list using the items field:
|
|||||||
|-------------|:----------------:|:------------:|-----------------------------------------------------------------------------|
|
|-------------|:----------------:|:------------:|-----------------------------------------------------------------------------|
|
||||||
| name | string | true | Name of the parameter. |
|
| name | string | true | Name of the parameter. |
|
||||||
| type | string | true | Must be "array" |
|
| type | string | true | Must be "array" |
|
||||||
| default | parameter type | false | Default value of the parameter. If provided, the parameter is not required. |
|
| default | parameter type | false | Default value of the parameter. If provided, the parameter is not required. |
|
||||||
| description | string | true | Natural language description of the parameter to describe it to the agent. |
|
| description | string | true | Natural language description of the parameter to describe it to the agent. |
|
||||||
| items | parameter object | true | Specify a Parameter object for the type of the values in the array. |
|
| items | parameter object | true | Specify a Parameter object for the type of the values in the array. |
|
||||||
|
|
||||||
@@ -115,6 +115,43 @@ in the list using the items field:
|
|||||||
Items in array should not have a default value. If provided, it will be ignored.
|
Items in array should not have a default value. If provided, it will be ignored.
|
||||||
{{< /notice >}}
|
{{< /notice >}}
|
||||||
|
|
||||||
|
### Object Parameters
|
||||||
|
|
||||||
|
The object type is a collection of key-value pairs passed in as a single
|
||||||
|
parameter. To use the object type, you must specify the schema for each
|
||||||
|
key-value pair using the properties field.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
parameters:
|
||||||
|
- name: new_user
|
||||||
|
type: object
|
||||||
|
description: A new user's profile information.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The full name of the user.
|
||||||
|
age:
|
||||||
|
type: integer
|
||||||
|
description: The age of the user.
|
||||||
|
is_subscriber:
|
||||||
|
type: boolean
|
||||||
|
description: Whether the user is a subscriber.
|
||||||
|
statement: |
|
||||||
|
INSERT INTO users (name, age, is_subscriber) VALUES ($1->>'name', ($1->>'age')::integer, ($1->>'is_subscriber')::boolean);
|
||||||
|
```
|
||||||
|
|
||||||
|
| **field** | **type** | **required** | **description** |
|
||||||
|
|-------------|:------------------------:|:------------:|---------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| name | string | true | Name of the parameter. |
|
||||||
|
| type | string | true | Must be "object" |
|
||||||
|
| default | parameter type | false | Default value of the parameter. If provided, the parameter is not required. |
|
||||||
|
| description | string | true | Natural language description of the parameter to describe it to the agent. |
|
||||||
|
| properties | map of parameter objects | true | A map where each key is a property name and each value is a Parameter object defining the schema for that property. |
|
||||||
|
|
||||||
|
{{< notice note >}}
|
||||||
|
Properties within an object should not have a default value. If provided, it will be ignored. A default can only be provided for the top-level object parameter.
|
||||||
|
{{< /notice >}}
|
||||||
|
|
||||||
### Authenticated Parameters
|
### Authenticated Parameters
|
||||||
|
|
||||||
Authenticated parameters are automatically populated with user
|
Authenticated parameters are automatically populated with user
|
||||||
@@ -143,10 +180,10 @@ user's ID token.
|
|||||||
field: sub
|
field: sub
|
||||||
```
|
```
|
||||||
|
|
||||||
| **field** | **type** | **required** | **description** |
|
| **field** | **type** | **required** | **description** |
|
||||||
|-----------|:--------:|:------------:|-----------------------------------------------------------------------------------------|
|
|-----------|:--------:|:------------:|---------------------------------------------------------------------------------|
|
||||||
| name | string | true | Name of the [authServices](../authservices) used to verify the OIDC auth token. |
|
| name | string | true | Name of the [authServices](../authservices) used to verify the OIDC auth token. |
|
||||||
| field | string | true | Claim field decoded from the OIDC token used to auto-populate this parameter. |
|
| field | string | true | Claim field decoded from the OIDC token used to auto-populate this parameter. |
|
||||||
|
|
||||||
### Template Parameters
|
### Template Parameters
|
||||||
|
|
||||||
@@ -195,12 +232,12 @@ tools:
|
|||||||
description: Name of a column to select
|
description: Name of a column to select
|
||||||
```
|
```
|
||||||
|
|
||||||
| **field** | **type** | **required** | **description** |
|
| **field** | **type** | **required** | **description** |
|
||||||
|-------------|:----------------:|:-------------:|-------------------------------------------------------------------------------------|
|
|-------------|:----------------:|:---------------:|-------------------------------------------------------------------------------------|
|
||||||
| name | string | true | Name of the template parameter. |
|
| name | string | true | Name of the template parameter. |
|
||||||
| type | string | true | Must be one of "string", "integer", "float", "boolean" "array" |
|
| type | string | true | Must be one of "string", "integer", "float", "boolean" "array" |
|
||||||
| description | string | true | Natural language description of the template parameter to describe it to the agent. |
|
| description | string | true | Natural language description of the template parameter to describe it to the agent. |
|
||||||
| items | parameter object |true (if array)| Specify a Parameter object for the type of the values in the array (string only). |
|
| items | parameter object | true (if array) | Specify a Parameter object for the type of the values in the array (string only). |
|
||||||
|
|
||||||
## Authorized Invocations
|
## Authorized Invocations
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ const (
|
|||||||
typeFloat = "float"
|
typeFloat = "float"
|
||||||
typeBool = "boolean"
|
typeBool = "boolean"
|
||||||
typeArray = "array"
|
typeArray = "array"
|
||||||
|
typeObject = "object"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParamValues is an ordered list of ParamValue
|
// ParamValues is an ordered list of ParamValue
|
||||||
@@ -367,6 +368,17 @@ func parseParamFromDelayedUnmarshaler(ctx context.Context, u *util.DelayedUnmars
|
|||||||
a.AuthSources = nil
|
a.AuthSources = nil
|
||||||
}
|
}
|
||||||
return a, nil
|
return a, nil
|
||||||
|
case typeObject:
|
||||||
|
a := &ObjectParameter{}
|
||||||
|
if err := dec.DecodeContext(ctx, a); err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to parse as %q: %w", t, err)
|
||||||
|
}
|
||||||
|
if a.AuthSources != nil {
|
||||||
|
logger.WarnContext(ctx, "`authSources` is deprecated, use `authServices` for parameters instead")
|
||||||
|
a.AuthServices = append(a.AuthServices, a.AuthSources...)
|
||||||
|
a.AuthSources = nil
|
||||||
|
}
|
||||||
|
return a, nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("%q is not valid type for a parameter", t)
|
return nil, fmt.Errorf("%q is not valid type for a parameter", t)
|
||||||
}
|
}
|
||||||
@@ -401,19 +413,23 @@ func (ps Parameters) McpManifest() McpToolsSchema {
|
|||||||
|
|
||||||
// ParameterManifest represents parameters when served as part of a ToolManifest.
|
// ParameterManifest represents parameters when served as part of a ToolManifest.
|
||||||
type ParameterManifest struct {
|
type ParameterManifest struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Required bool `json:"required"`
|
Required bool `json:"required"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
AuthServices []string `json:"authSources"`
|
AuthServices []string `json:"authSources"`
|
||||||
Items *ParameterManifest `json:"items,omitempty"`
|
Items *ParameterManifest `json:"items,omitempty"`
|
||||||
|
Properties map[string]*ParameterManifest `json:"properties,omitempty"`
|
||||||
|
AdditionalProperties *ParameterManifest `json:"additionalProperties,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParameterMcpManifest represents properties when served as part of a ToolMcpManifest.
|
// ParameterMcpManifest represents properties when served as part of a ToolMcpManifest.
|
||||||
type ParameterMcpManifest struct {
|
type ParameterMcpManifest struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Items *ParameterMcpManifest `json:"items,omitempty"`
|
Items *ParameterMcpManifest `json:"items,omitempty"`
|
||||||
|
Properties map[string]*ParameterMcpManifest `json:"properties,omitempty"`
|
||||||
|
AdditionalProperties *ParameterMcpManifest `json:"addtionalProperties,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommonParameter are default fields that are emebdding in most Parameter implementations. Embedding this stuct will give the object Name() and Type() functions.
|
// CommonParameter are default fields that are emebdding in most Parameter implementations. Embedding this stuct will give the object Name() and Type() functions.
|
||||||
@@ -1022,3 +1038,194 @@ func (p *ArrayParameter) McpManifest() ParameterMcpManifest {
|
|||||||
Items: &items,
|
Items: &items,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewObjectParameter is a convenience function for initializing a ObjectParameter.
|
||||||
|
func NewObjectParameter(name string, desc string, properties map[string]Parameter, additionalProperties Parameter) *ObjectParameter {
|
||||||
|
return &ObjectParameter{
|
||||||
|
CommonParameter: CommonParameter{
|
||||||
|
Name: name,
|
||||||
|
Type: typeObject,
|
||||||
|
Desc: desc,
|
||||||
|
AuthServices: nil,
|
||||||
|
},
|
||||||
|
Properties: properties,
|
||||||
|
AdditionalProperties: additionalProperties,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewObjectParameterWithDefault is a convenience function for initializing a ObjectParameter with default value.
|
||||||
|
func NewObjectParameterWithDefault(name string, defaultV map[string]any, desc string, properties map[string]Parameter, additionalProperties Parameter) *ObjectParameter {
|
||||||
|
return &ObjectParameter{
|
||||||
|
CommonParameter: CommonParameter{
|
||||||
|
Name: name,
|
||||||
|
Type: typeObject,
|
||||||
|
Desc: desc,
|
||||||
|
AuthServices: nil,
|
||||||
|
},
|
||||||
|
Default: &defaultV,
|
||||||
|
Properties: properties,
|
||||||
|
AdditionalProperties: additionalProperties,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewObjectParameterWithAuth is a convenience function for initializing a ObjectParameter with a list of ParamAuthService.
|
||||||
|
func NewObjectParameterWithAuth(name string, desc string, authServices []ParamAuthService, properties map[string]Parameter, additionalProperties Parameter) *ObjectParameter {
|
||||||
|
return &ObjectParameter{
|
||||||
|
CommonParameter: CommonParameter{
|
||||||
|
Name: name,
|
||||||
|
Type: typeObject,
|
||||||
|
Desc: desc,
|
||||||
|
AuthServices: authServices,
|
||||||
|
},
|
||||||
|
Properties: properties,
|
||||||
|
AdditionalProperties: additionalProperties,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Parameter = &ObjectParameter{}
|
||||||
|
|
||||||
|
// ObjectParameter is a parameter representing the "map" type.
|
||||||
|
type ObjectParameter struct {
|
||||||
|
CommonParameter `yaml:",inline"`
|
||||||
|
Default *map[string]any `yaml:"default"`
|
||||||
|
Properties map[string]Parameter `yaml:"properties"`
|
||||||
|
AdditionalProperties Parameter `yaml:"addtionalProperties"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ObjectParameter) UnmarshalYAML(ctx context.Context, unmarshal func(interface{}) error) error {
|
||||||
|
var rawItem struct {
|
||||||
|
CommonParameter `yaml:",inline"`
|
||||||
|
Default *map[string]any `yaml:"default"`
|
||||||
|
Properties map[string]*util.DelayedUnmarshaler `yaml:"properties"`
|
||||||
|
AdditionalProperties *util.DelayedUnmarshaler `yaml:"additionalProperties"`
|
||||||
|
}
|
||||||
|
if err := unmarshal(&rawItem); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.CommonParameter = rawItem.CommonParameter
|
||||||
|
p.Default = rawItem.Default
|
||||||
|
|
||||||
|
if rawItem.AdditionalProperties != nil {
|
||||||
|
param, err := parseParamFromDelayedUnmarshaler(ctx, rawItem.AdditionalProperties)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse additionalProperties: %w", err)
|
||||||
|
}
|
||||||
|
p.AdditionalProperties = param
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rawItem.Properties) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Properties = make(map[string]Parameter, len(rawItem.Properties))
|
||||||
|
for key, delayedParam := range rawItem.Properties {
|
||||||
|
// Parse individual property parameters
|
||||||
|
param, err := parseParamFromDelayedUnmarshaler(ctx, delayedParam)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse property %q: %w", key, err)
|
||||||
|
}
|
||||||
|
p.Properties[key] = param
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ObjectParameter) Parse(v any) (any, error) {
|
||||||
|
objVal, ok := v.(map[string]any)
|
||||||
|
if !ok {
|
||||||
|
return nil, &ParseTypeError{p.Name, p.Type, v}
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedObj := make(map[string]any, len(objVal))
|
||||||
|
|
||||||
|
for key, val := range objVal {
|
||||||
|
var (
|
||||||
|
parsedVal any
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
propertySchema, isDefinedProperty := p.Properties[key]
|
||||||
|
|
||||||
|
if isDefinedProperty {
|
||||||
|
// If the property is explicitly defined in the schema.
|
||||||
|
parsedVal, err = propertySchema.Parse(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to parse property %q: %w", key, err)
|
||||||
|
}
|
||||||
|
} else if p.AdditionalProperties != nil {
|
||||||
|
// If the property is not defined, but the schema allows additional properties.
|
||||||
|
parsedVal, err = p.AdditionalProperties.Parse(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to parse additional property %q: %w", key, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("unknown property %q found and additional properties are not allowed", key)
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedObj[key] = parsedVal
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedObj, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ObjectParameter) GetAuthServices() []ParamAuthService {
|
||||||
|
return p.AuthServices
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ObjectParameter) GetDefault() any {
|
||||||
|
if p.Default == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return *p.Default
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manifest returns the manifest for the ObjectParameter.
|
||||||
|
func (p *ObjectParameter) Manifest() ParameterManifest {
|
||||||
|
// only list ParamAuthService names (without fields) in manifest
|
||||||
|
authNames := make([]string, len(p.AuthServices))
|
||||||
|
for i, a := range p.AuthServices {
|
||||||
|
authNames[i] = a.Name
|
||||||
|
}
|
||||||
|
required := p.Default == nil
|
||||||
|
propertiesManifest := make(map[string]*ParameterManifest, len(p.Properties))
|
||||||
|
for key, p := range p.Properties {
|
||||||
|
m := p.Manifest()
|
||||||
|
propertiesManifest[key] = &m
|
||||||
|
}
|
||||||
|
var apManifest ParameterManifest
|
||||||
|
if p.AdditionalProperties != nil {
|
||||||
|
apManifest = p.AdditionalProperties.Manifest()
|
||||||
|
}
|
||||||
|
return ParameterManifest{
|
||||||
|
Name: p.Name,
|
||||||
|
Type: p.Type,
|
||||||
|
Required: required,
|
||||||
|
Description: p.Desc,
|
||||||
|
AuthServices: authNames,
|
||||||
|
Properties: propertiesManifest,
|
||||||
|
AdditionalProperties: &apManifest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// McpManifest returns the MCP manifest for the ObjectParameter.
|
||||||
|
func (p *ObjectParameter) McpManifest() ParameterMcpManifest {
|
||||||
|
// only list ParamAuthService names (without fields) in manifest
|
||||||
|
authNames := make([]string, len(p.AuthServices))
|
||||||
|
for i, a := range p.AuthServices {
|
||||||
|
authNames[i] = a.Name
|
||||||
|
}
|
||||||
|
propertiesManifest := make(map[string]*ParameterMcpManifest, len(p.Properties))
|
||||||
|
for key, p := range p.Properties {
|
||||||
|
m := p.McpManifest()
|
||||||
|
propertiesManifest[key] = &m
|
||||||
|
}
|
||||||
|
var apManifest ParameterMcpManifest
|
||||||
|
if p.AdditionalProperties != nil {
|
||||||
|
apManifest = p.AdditionalProperties.McpManifest()
|
||||||
|
}
|
||||||
|
return ParameterMcpManifest{
|
||||||
|
Type: p.Type,
|
||||||
|
Description: p.Desc,
|
||||||
|
Properties: propertiesManifest,
|
||||||
|
AdditionalProperties: &apManifest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
"github.com/googleapis/genai-toolbox/internal/testutils"
|
"github.com/googleapis/genai-toolbox/internal/testutils"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
)
|
)
|
||||||
@@ -200,6 +201,31 @@ func TestParametersMarshal(t *testing.T) {
|
|||||||
tools.NewArrayParameter("my_array", "this param is an array of floats", tools.NewFloatParameter("my_float", "float item")),
|
tools.NewArrayParameter("my_array", "this param is an array of floats", tools.NewFloatParameter("my_float", "float item")),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "object",
|
||||||
|
in: []map[string]any{
|
||||||
|
{
|
||||||
|
"name": "my_object",
|
||||||
|
"type": "object",
|
||||||
|
"description": "this param is an object",
|
||||||
|
"properties": map[string]any{
|
||||||
|
"k1": map[string]any{
|
||||||
|
"name": "k1",
|
||||||
|
"type": "float",
|
||||||
|
"description": "float property",
|
||||||
|
},
|
||||||
|
"k2": map[string]any{
|
||||||
|
"name": "k2",
|
||||||
|
"type": "string",
|
||||||
|
"description": "string property",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: tools.Parameters{
|
||||||
|
tools.NewObjectParameter("my_object", "this param is an object", map[string]tools.Parameter{"k1": tools.NewFloatParameter("k1", "float property"), "k2": tools.NewStringParameter("k2", "string property")}, nil),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "string default",
|
name: "string default",
|
||||||
in: []map[string]any{
|
in: []map[string]any{
|
||||||
@@ -294,6 +320,37 @@ func TestParametersMarshal(t *testing.T) {
|
|||||||
tools.NewArrayParameterWithDefault("my_array", []any{1.0, 1.1}, "this param is an array of floats", tools.NewFloatParameter("my_float", "float item")),
|
tools.NewArrayParameterWithDefault("my_array", []any{1.0, 1.1}, "this param is an array of floats", tools.NewFloatParameter("my_float", "float item")),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "object",
|
||||||
|
in: []map[string]any{
|
||||||
|
{
|
||||||
|
"name": "my_object",
|
||||||
|
"type": "object",
|
||||||
|
"default": map[string]any{"hello": "world"},
|
||||||
|
"description": "this param is an object",
|
||||||
|
"properties": map[string]any{
|
||||||
|
"k1": map[string]any{
|
||||||
|
"name": "k1",
|
||||||
|
"type": "float",
|
||||||
|
"description": "float property",
|
||||||
|
},
|
||||||
|
"k2": map[string]any{
|
||||||
|
"name": "k2",
|
||||||
|
"type": "string",
|
||||||
|
"description": "string property",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"additionalProperties": map[string]any{
|
||||||
|
"name": "strProperty",
|
||||||
|
"type": "string",
|
||||||
|
"description": "string property",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: tools.Parameters{
|
||||||
|
tools.NewObjectParameterWithDefault("my_object", map[string]any{"hello": "world"}, "this param is an object", map[string]tools.Parameter{"k1": tools.NewFloatParameter("k1", "float property"), "k2": tools.NewStringParameter("k2", "string property")}, tools.NewStringParameter("strProperty", "string property")),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
@@ -350,13 +407,13 @@ func TestAuthParametersMarshal(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "string with authSources",
|
name: "string with authServices",
|
||||||
in: []map[string]any{
|
in: []map[string]any{
|
||||||
{
|
{
|
||||||
"name": "my_string",
|
"name": "my_string",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "this param is a string",
|
"description": "this param is a string",
|
||||||
"authSources": []map[string]string{
|
"authServices": []map[string]string{
|
||||||
{
|
{
|
||||||
"name": "my-google-auth-service",
|
"name": "my-google-auth-service",
|
||||||
"field": "user_id",
|
"field": "user_id",
|
||||||
@@ -396,13 +453,13 @@ func TestAuthParametersMarshal(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "int with authSources",
|
name: "int with authServices",
|
||||||
in: []map[string]any{
|
in: []map[string]any{
|
||||||
{
|
{
|
||||||
"name": "my_integer",
|
"name": "my_integer",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "this param is an int",
|
"description": "this param is an int",
|
||||||
"authSources": []map[string]string{
|
"authServices": []map[string]string{
|
||||||
{
|
{
|
||||||
"name": "my-google-auth-service",
|
"name": "my-google-auth-service",
|
||||||
"field": "user_id",
|
"field": "user_id",
|
||||||
@@ -442,13 +499,13 @@ func TestAuthParametersMarshal(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "float with authSources",
|
name: "float with authServices",
|
||||||
in: []map[string]any{
|
in: []map[string]any{
|
||||||
{
|
{
|
||||||
"name": "my_float",
|
"name": "my_float",
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"description": "my param is a float",
|
"description": "my param is a float",
|
||||||
"authSources": []map[string]string{
|
"authServices": []map[string]string{
|
||||||
{
|
{
|
||||||
"name": "my-google-auth-service",
|
"name": "my-google-auth-service",
|
||||||
"field": "user_id",
|
"field": "user_id",
|
||||||
@@ -488,13 +545,13 @@ func TestAuthParametersMarshal(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "bool with authSources",
|
name: "bool with authServices",
|
||||||
in: []map[string]any{
|
in: []map[string]any{
|
||||||
{
|
{
|
||||||
"name": "my_bool",
|
"name": "my_bool",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "this param is a boolean",
|
"description": "this param is a boolean",
|
||||||
"authSources": []map[string]string{
|
"authServices": []map[string]string{
|
||||||
{
|
{
|
||||||
"name": "my-google-auth-service",
|
"name": "my-google-auth-service",
|
||||||
"field": "user_id",
|
"field": "user_id",
|
||||||
@@ -539,7 +596,7 @@ func TestAuthParametersMarshal(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "string array with authSources",
|
name: "string array with authServices",
|
||||||
in: []map[string]any{
|
in: []map[string]any{
|
||||||
{
|
{
|
||||||
"name": "my_array",
|
"name": "my_array",
|
||||||
@@ -550,7 +607,7 @@ func TestAuthParametersMarshal(t *testing.T) {
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "string item",
|
"description": "string item",
|
||||||
},
|
},
|
||||||
"authSources": []map[string]string{
|
"authServices": []map[string]string{
|
||||||
{
|
{
|
||||||
"name": "my-google-auth-service",
|
"name": "my-google-auth-service",
|
||||||
"field": "user_id",
|
"field": "user_id",
|
||||||
@@ -594,6 +651,46 @@ func TestAuthParametersMarshal(t *testing.T) {
|
|||||||
tools.NewArrayParameterWithAuth("my_array", "this param is an array of floats", tools.NewFloatParameter("my_float", "float item"), authServices),
|
tools.NewArrayParameterWithAuth("my_array", "this param is an array of floats", tools.NewFloatParameter("my_float", "float item"), authServices),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "object",
|
||||||
|
in: []map[string]any{
|
||||||
|
{
|
||||||
|
"name": "my_object",
|
||||||
|
"type": "object",
|
||||||
|
"description": "this param is an object",
|
||||||
|
"authServices": []map[string]string{
|
||||||
|
{
|
||||||
|
"name": "my-google-auth-service",
|
||||||
|
"field": "user_id",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "other-auth-service",
|
||||||
|
"field": "user_id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"properties": map[string]any{
|
||||||
|
"k1": map[string]any{
|
||||||
|
"name": "k1",
|
||||||
|
"type": "float",
|
||||||
|
"description": "float property",
|
||||||
|
},
|
||||||
|
"k2": map[string]any{
|
||||||
|
"name": "k2",
|
||||||
|
"type": "string",
|
||||||
|
"description": "string property",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"additionalProperties": map[string]any{
|
||||||
|
"name": "strProperty",
|
||||||
|
"type": "string",
|
||||||
|
"description": "string property",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: tools.Parameters{
|
||||||
|
tools.NewObjectParameterWithAuth("my_object", "this param is an object", authServices, map[string]tools.Parameter{"k1": tools.NewFloatParameter("k1", "float property"), "k2": tools.NewStringParameter("k2", "string property")}, tools.NewStringParameter("strProperty", "string property")),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
@@ -617,10 +714,11 @@ func TestAuthParametersMarshal(t *testing.T) {
|
|||||||
|
|
||||||
func TestParametersParse(t *testing.T) {
|
func TestParametersParse(t *testing.T) {
|
||||||
tcs := []struct {
|
tcs := []struct {
|
||||||
name string
|
name string
|
||||||
params tools.Parameters
|
params tools.Parameters
|
||||||
in map[string]any
|
in map[string]any
|
||||||
want tools.ParamValues
|
want tools.ParamValues
|
||||||
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "string",
|
name: "string",
|
||||||
@@ -640,6 +738,7 @@ func TestParametersParse(t *testing.T) {
|
|||||||
in: map[string]any{
|
in: map[string]any{
|
||||||
"my_string": 4,
|
"my_string": 4,
|
||||||
},
|
},
|
||||||
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "int",
|
name: "int",
|
||||||
@@ -659,16 +758,17 @@ func TestParametersParse(t *testing.T) {
|
|||||||
in: map[string]any{
|
in: map[string]any{
|
||||||
"my_int": 14.5,
|
"my_int": 14.5,
|
||||||
},
|
},
|
||||||
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not int (big)",
|
name: "int from json.Number",
|
||||||
params: tools.Parameters{
|
params: tools.Parameters{
|
||||||
tools.NewIntParameter("my_int", "this param is an int"),
|
tools.NewIntParameter("my_int", "this param is an int"),
|
||||||
},
|
},
|
||||||
in: map[string]any{
|
in: map[string]any{
|
||||||
"my_int": math.MaxInt64,
|
"my_int": json.Number("9223372036854775807"),
|
||||||
},
|
},
|
||||||
want: tools.ParamValues{tools.ParamValue{Name: "my_int", Value: math.MaxInt64}},
|
want: tools.ParamValues{tools.ParamValue{Name: "my_int", Value: int(math.MaxInt64)}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "float",
|
name: "float",
|
||||||
@@ -688,6 +788,7 @@ func TestParametersParse(t *testing.T) {
|
|||||||
in: map[string]any{
|
in: map[string]any{
|
||||||
"my_float": true,
|
"my_float": true,
|
||||||
},
|
},
|
||||||
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "bool",
|
name: "bool",
|
||||||
@@ -707,6 +808,7 @@ func TestParametersParse(t *testing.T) {
|
|||||||
in: map[string]any{
|
in: map[string]any{
|
||||||
"my_bool": 1.5,
|
"my_bool": 1.5,
|
||||||
},
|
},
|
||||||
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "string default",
|
name: "string default",
|
||||||
@@ -780,44 +882,103 @@ func TestParametersParse(t *testing.T) {
|
|||||||
in: map[string]any{},
|
in: map[string]any{},
|
||||||
want: tools.ParamValues{tools.ParamValue{Name: "my_bool", Value: nil}},
|
want: tools.ParamValues{tools.ParamValue{Name: "my_bool", Value: nil}},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "array of strings",
|
||||||
|
params: tools.Parameters{
|
||||||
|
tools.NewArrayParameter("my_array", "an array", tools.NewStringParameter("item", "a string item")),
|
||||||
|
},
|
||||||
|
in: map[string]any{"my_array": []any{"a", "b", "c"}},
|
||||||
|
want: tools.ParamValues{tools.ParamValue{Name: "my_array", Value: []any{"a", "b", "c"}}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "array with item type mismatch",
|
||||||
|
params: tools.Parameters{
|
||||||
|
tools.NewArrayParameter("my_array", "an array", tools.NewIntParameter("item", "an int item")),
|
||||||
|
},
|
||||||
|
in: map[string]any{"my_array": []any{1, "b", 3}},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "array not required",
|
||||||
|
params: tools.Parameters{
|
||||||
|
tools.NewArrayParameterWithRequired("my_array", "an array", false, tools.NewStringParameter("item", "a string item")),
|
||||||
|
},
|
||||||
|
in: map[string]any{},
|
||||||
|
want: tools.ParamValues{tools.ParamValue{Name: "my_array", Value: nil}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "array with default",
|
||||||
|
params: tools.Parameters{
|
||||||
|
tools.NewArrayParameterWithDefault("my_array", []any{"x", "y"}, "an array", tools.NewStringParameter("item", "a string item")),
|
||||||
|
},
|
||||||
|
in: map[string]any{},
|
||||||
|
want: tools.ParamValues{tools.ParamValue{Name: "my_array", Value: []any{"x", "y"}}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "object",
|
||||||
|
params: tools.Parameters{
|
||||||
|
tools.NewObjectParameter("my_object", "an object", map[string]tools.Parameter{
|
||||||
|
"key1": tools.NewStringParameter("key1", "string value"),
|
||||||
|
"key2": tools.NewIntParameter("key2", "int value"),
|
||||||
|
}, nil),
|
||||||
|
},
|
||||||
|
in: map[string]any{"my_object": map[string]any{
|
||||||
|
"key1": "hello",
|
||||||
|
"key2": 123,
|
||||||
|
}},
|
||||||
|
want: tools.ParamValues{tools.ParamValue{Name: "my_object", Value: map[string]any{
|
||||||
|
"key1": "hello",
|
||||||
|
"key2": 123,
|
||||||
|
}}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "object with property type mismatch",
|
||||||
|
params: tools.Parameters{
|
||||||
|
tools.NewObjectParameter("my_object", "an object", map[string]tools.Parameter{
|
||||||
|
"key1": tools.NewStringParameter("key1", "string value"),
|
||||||
|
}, nil),
|
||||||
|
},
|
||||||
|
in: map[string]any{"my_object": map[string]any{"key1": 123}},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "object with missing required property",
|
||||||
|
params: tools.Parameters{
|
||||||
|
tools.NewObjectParameter("my_object", "an object", map[string]tools.Parameter{
|
||||||
|
"required_key": tools.NewStringParameter("required_key", "a required value"),
|
||||||
|
}, nil),
|
||||||
|
},
|
||||||
|
in: map[string]any{"my_object": map[string]any{"another_key": "foo"}},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "object with default",
|
||||||
|
params: tools.Parameters{
|
||||||
|
tools.NewObjectParameterWithDefault("my_object", map[string]any{"key1": "default"}, "an object", map[string]tools.Parameter{
|
||||||
|
"key1": tools.NewStringParameter("key1", "string value"),
|
||||||
|
}, nil),
|
||||||
|
},
|
||||||
|
in: map[string]any{},
|
||||||
|
want: tools.ParamValues{tools.ParamValue{Name: "my_object", Value: map[string]any{"key1": "default"}}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
// parse map to bytes
|
got, err := tools.ParseParams(tc.params, tc.in, make(map[string]map[string]any))
|
||||||
data, err := json.Marshal(tc.in)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to marshal input to yaml: %s", err)
|
|
||||||
}
|
|
||||||
// parse bytes to object
|
|
||||||
var m map[string]any
|
|
||||||
|
|
||||||
d := json.NewDecoder(bytes.NewReader(data))
|
if tc.wantErr {
|
||||||
d.UseNumber()
|
if err == nil {
|
||||||
err = d.Decode(&m)
|
t.Fatal("expected error but got nil")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to unmarshal: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
wantErr := len(tc.want) == 0 // error is expected if no items in want
|
|
||||||
gotAll, err := tools.ParseParams(tc.params, m, make(map[string]map[string]any))
|
|
||||||
if err != nil {
|
|
||||||
if wantErr {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
t.Fatalf("unexpected error from ParseParams: %s", err)
|
t.Fatalf("unexpected error from ParseParams: %s", err)
|
||||||
}
|
}
|
||||||
if wantErr {
|
|
||||||
t.Fatalf("expected error but Param parsed successfully: %s", gotAll)
|
if diff := cmp.Diff(tc.want, got); diff != "" {
|
||||||
}
|
t.Fatalf("ParseParams() mismatch (-want +got):\n%s", diff)
|
||||||
for i, got := range gotAll {
|
|
||||||
want := tc.want[i]
|
|
||||||
if got != want {
|
|
||||||
t.Fatalf("unexpected value: got %q, want %q", got, want)
|
|
||||||
}
|
|
||||||
gotType, wantType := reflect.TypeOf(got), reflect.TypeOf(want)
|
|
||||||
if gotType != wantType {
|
|
||||||
t.Fatalf("unexpected value: got %q, want %q", got, want)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1075,7 +1236,27 @@ func TestParamManifest(t *testing.T) {
|
|||||||
Required: true,
|
Required: true,
|
||||||
Description: "bar",
|
Description: "bar",
|
||||||
AuthServices: []string{},
|
AuthServices: []string{},
|
||||||
Items: &tools.ParameterManifest{Name: "foo-string", Type: "string", Required: true, Description: "bar", AuthServices: []string{}},
|
Items: &tools.ParameterManifest{
|
||||||
|
Name: "foo-string",
|
||||||
|
Type: "string",
|
||||||
|
Required: true,
|
||||||
|
Description: "bar",
|
||||||
|
AuthServices: []string{}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "object",
|
||||||
|
in: tools.NewObjectParameter("foo-object", "bar", map[string]tools.Parameter{"propertyName": tools.NewStringParameter("property", "property desc")}, tools.NewStringParameter("strProperty", "string property")),
|
||||||
|
want: tools.ParameterManifest{
|
||||||
|
Name: "foo-object",
|
||||||
|
Type: "object",
|
||||||
|
Required: true,
|
||||||
|
Description: "bar",
|
||||||
|
AuthServices: []string{},
|
||||||
|
Properties: map[string]*tools.ParameterManifest{"propertyName": {
|
||||||
|
Name: "property", Type: "string",
|
||||||
|
Required: true, Description: "property desc", AuthServices: []string{}}},
|
||||||
|
AdditionalProperties: &tools.ParameterManifest{Name: "strProperty", Type: "string", Required: true, Description: "string property", AuthServices: []string{}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1142,12 +1323,25 @@ func TestParamManifest(t *testing.T) {
|
|||||||
Items: &tools.ParameterManifest{Name: "foo-string", Type: "string", Required: false, Description: "bar", AuthServices: []string{}},
|
Items: &tools.ParameterManifest{Name: "foo-string", Type: "string", Required: false, Description: "bar", AuthServices: []string{}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "object default",
|
||||||
|
in: tools.NewObjectParameterWithDefault("object-default", map[string]any{"hello": "world"}, "bar", map[string]tools.Parameter{"k1": tools.NewFloatParameter("k1", "float property")}, nil),
|
||||||
|
want: tools.ParameterManifest{
|
||||||
|
Name: "object-default",
|
||||||
|
Type: "object",
|
||||||
|
Required: false,
|
||||||
|
Description: "bar",
|
||||||
|
AuthServices: []string{},
|
||||||
|
Properties: map[string]*tools.ParameterManifest{"k1": {Name: "k1", Type: "float", Required: true, Description: "float property", AuthServices: []string{}}},
|
||||||
|
AdditionalProperties: &tools.ParameterManifest{},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
got := tc.in.Manifest()
|
got := tc.in.Manifest()
|
||||||
if !reflect.DeepEqual(got, tc.want) {
|
if diff := cmp.Diff(tc.want, got); diff != "" {
|
||||||
t.Fatalf("unexpected manifest: got %+v, want %+v", got, tc.want)
|
t.Fatalf("unexpected manifest (-want +got):\n%s", diff)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1188,12 +1382,22 @@ func TestParamMcpManifest(t *testing.T) {
|
|||||||
Items: &tools.ParameterMcpManifest{Type: "string", Description: "bar"},
|
Items: &tools.ParameterMcpManifest{Type: "string", Description: "bar"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "object",
|
||||||
|
in: tools.NewObjectParameter("foo-object", "bar", map[string]tools.Parameter{"k1": tools.NewStringParameter("k1", "bar")}, tools.NewStringParameter("p1", "additional property")),
|
||||||
|
want: tools.ParameterMcpManifest{
|
||||||
|
Type: "object",
|
||||||
|
Description: "bar",
|
||||||
|
Properties: map[string]*tools.ParameterMcpManifest{"k1": {Type: "string", Description: "bar"}},
|
||||||
|
AdditionalProperties: &tools.ParameterMcpManifest{Type: "string", Description: "additional property"},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
got := tc.in.McpManifest()
|
got := tc.in.McpManifest()
|
||||||
if !reflect.DeepEqual(got, tc.want) {
|
if diff := cmp.Diff(tc.want, got); diff != "" {
|
||||||
t.Fatalf("unexpected manifest: got %+v, want %+v", got, tc.want)
|
t.Fatalf("unexpected manifest (-want +got):\n%s", diff)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1206,7 +1410,7 @@ func TestMcpManifest(t *testing.T) {
|
|||||||
want tools.McpToolsSchema
|
want tools.McpToolsSchema
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "string",
|
name: "various parameters",
|
||||||
in: tools.Parameters{
|
in: tools.Parameters{
|
||||||
tools.NewStringParameterWithDefault("foo-string", "foo", "bar"),
|
tools.NewStringParameterWithDefault("foo-string", "foo", "bar"),
|
||||||
tools.NewStringParameter("foo-string2", "bar"),
|
tools.NewStringParameter("foo-string2", "bar"),
|
||||||
@@ -1214,38 +1418,41 @@ func TestMcpManifest(t *testing.T) {
|
|||||||
tools.NewStringParameterWithRequired("foo-string-not-req", "bar", false),
|
tools.NewStringParameterWithRequired("foo-string-not-req", "bar", false),
|
||||||
tools.NewIntParameterWithDefault("foo-int", 1, "bar"),
|
tools.NewIntParameterWithDefault("foo-int", 1, "bar"),
|
||||||
tools.NewIntParameter("foo-int2", "bar"),
|
tools.NewIntParameter("foo-int2", "bar"),
|
||||||
tools.NewArrayParameterWithDefault("foo-array", []any{"hello", "world"}, "bar", tools.NewStringParameter("foo-string", "bar")),
|
tools.NewArrayParameterWithDefault("foo-array", []any{"hello", "world"}, "bar", tools.NewStringParameter("foo-string-item", "bar")),
|
||||||
tools.NewArrayParameter("foo-array2", "bar", tools.NewStringParameter("foo-string", "bar")),
|
tools.NewArrayParameter("foo-array2", "bar", tools.NewStringParameter("foo-string-item2", "bar")),
|
||||||
|
tools.NewObjectParameter("foo-object", "bar", map[string]tools.Parameter{"k1": tools.NewFloatParameter("k1", "float property")}, nil),
|
||||||
},
|
},
|
||||||
want: tools.McpToolsSchema{
|
want: tools.McpToolsSchema{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
Properties: map[string]tools.ParameterMcpManifest{
|
Properties: map[string]tools.ParameterMcpManifest{
|
||||||
"foo-string": tools.ParameterMcpManifest{Type: "string", Description: "bar"},
|
"foo-string": {Type: "string", Description: "bar"},
|
||||||
"foo-string2": tools.ParameterMcpManifest{Type: "string", Description: "bar"},
|
"foo-string2": {Type: "string", Description: "bar"},
|
||||||
"foo-string-req": tools.ParameterMcpManifest{Type: "string", Description: "bar"},
|
"foo-string-req": {Type: "string", Description: "bar"},
|
||||||
"foo-string-not-req": tools.ParameterMcpManifest{Type: "string", Description: "bar"},
|
"foo-string-not-req": {Type: "string", Description: "bar"},
|
||||||
"foo-int": tools.ParameterMcpManifest{Type: "integer", Description: "bar"},
|
"foo-int": {Type: "integer", Description: "bar"},
|
||||||
"foo-int2": tools.ParameterMcpManifest{Type: "integer", Description: "bar"},
|
"foo-int2": {Type: "integer", Description: "bar"},
|
||||||
"foo-array": tools.ParameterMcpManifest{
|
"foo-array": {
|
||||||
Type: "array",
|
Type: "array",
|
||||||
Description: "bar",
|
Description: "bar",
|
||||||
Items: &tools.ParameterMcpManifest{Type: "string", Description: "bar"},
|
Items: &tools.ParameterMcpManifest{Type: "string", Description: "bar"},
|
||||||
},
|
},
|
||||||
"foo-array2": tools.ParameterMcpManifest{
|
"foo-array2": {
|
||||||
Type: "array",
|
Type: "array",
|
||||||
Description: "bar",
|
Description: "bar",
|
||||||
Items: &tools.ParameterMcpManifest{Type: "string", Description: "bar"},
|
Items: &tools.ParameterMcpManifest{Type: "string", Description: "bar"},
|
||||||
},
|
},
|
||||||
|
"foo-object": {Type: "object", Description: "bar", Properties: map[string]*tools.ParameterMcpManifest{"k1": {Type: "float", Description: "float property"}}, AdditionalProperties: &tools.ParameterMcpManifest{}},
|
||||||
},
|
},
|
||||||
Required: []string{"foo-string2", "foo-string-req", "foo-int2", "foo-array2"},
|
Required: []string{"foo-array2", "foo-int2", "foo-object", "foo-string-req", "foo-string2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
got := tc.in.McpManifest()
|
got := tc.in.McpManifest()
|
||||||
if !reflect.DeepEqual(got, tc.want) {
|
opts := cmpopts.SortSlices(func(a, b string) bool { return a < b })
|
||||||
t.Fatalf("unexpected manifest: got %+v, want %+v", got, tc.want)
|
if diff := cmp.Diff(tc.want, got, opts); diff != "" {
|
||||||
|
t.Fatalf("unexpected manifest (-want +got):\n%s", diff)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user