|
|
@@ -6,6 +6,8 @@ package kit
|
|
|
|
|
|
import (
|
|
|
"context"
|
|
|
+ "encoding/json"
|
|
|
+ "fmt"
|
|
|
"strings"
|
|
|
|
|
|
"github.com/mark3labs/mcp-go/mcp"
|
|
|
@@ -40,6 +42,9 @@ type Def[T any] struct {
|
|
|
Description string // 用途、适用场景、返回字段与单位
|
|
|
ReadOnly bool
|
|
|
Handler func(ctx context.Context, args T) (*mcp.CallToolResult, error)
|
|
|
+ // Properties 可选:补充生成的 schema 中各字段的约束(枚举、取值范围、数组长度等),
|
|
|
+ // key 为字段名,value 合并进该字段的 schema(同名键覆盖)。服务端按补充后的 schema 校验参数。
|
|
|
+ Properties map[string]map[string]any
|
|
|
}
|
|
|
|
|
|
func (d Def[T]) Meta() Meta {
|
|
|
@@ -47,7 +52,7 @@ func (d Def[T]) Meta() Meta {
|
|
|
}
|
|
|
|
|
|
func (d Def[T]) Tool() mcp.Tool {
|
|
|
- return mcp.NewTool(d.Name,
|
|
|
+ t := mcp.NewTool(d.Name,
|
|
|
mcp.WithDescription(d.Description),
|
|
|
mcp.WithInputSchema[T](),
|
|
|
mcp.WithTitleAnnotation(d.Title),
|
|
|
@@ -56,6 +61,33 @@ func (d Def[T]) Tool() mcp.Tool {
|
|
|
mcp.WithIdempotentHintAnnotation(d.ReadOnly),
|
|
|
mcp.WithOpenWorldHintAnnotation(false),
|
|
|
)
|
|
|
+ if len(d.Properties) > 0 {
|
|
|
+ t.RawInputSchema = patchProperties(t.RawInputSchema, d.Name, d.Properties)
|
|
|
+ }
|
|
|
+ return t
|
|
|
+}
|
|
|
+
|
|
|
+// patchProperties 把 patch 合并进 schema.properties 中的对应字段;字段不存在视为定义错误,直接 panic(启动即暴露)。
|
|
|
+func patchProperties(raw json.RawMessage, tool string, patch map[string]map[string]any) json.RawMessage {
|
|
|
+ var schema map[string]any
|
|
|
+ if err := json.Unmarshal(raw, &schema); err != nil {
|
|
|
+ panic(fmt.Sprintf("%s: 解析 inputSchema 失败: %v", tool, err))
|
|
|
+ }
|
|
|
+ props, _ := schema["properties"].(map[string]any)
|
|
|
+ for name, extra := range patch {
|
|
|
+ field, ok := props[name].(map[string]any)
|
|
|
+ if !ok {
|
|
|
+ panic(fmt.Sprintf("%s: inputSchema 中没有字段 %s", tool, name))
|
|
|
+ }
|
|
|
+ for k, v := range extra {
|
|
|
+ field[k] = v
|
|
|
+ }
|
|
|
+ }
|
|
|
+ out, err := json.Marshal(schema)
|
|
|
+ if err != nil {
|
|
|
+ panic(fmt.Sprintf("%s: 序列化 inputSchema 失败: %v", tool, err))
|
|
|
+ }
|
|
|
+ return out
|
|
|
}
|
|
|
|
|
|
func (d Def[T]) Register(s *server.MCPServer) {
|