forge-toolkit: хелперы для разработки MCP-серверов на Go. - toolkit: args/schema/result/env/probe/server - toolkit/validate: валидаторы синтаксиса - configreload: live-reload конфига по контент-хэшу - docs: ARCHITECTURE, quickstart, mcp-contract - template/ и examples/hello-tool/ - CI (Gitea Actions), лицензия Apache-2.0
68 lines
2.8 KiB
Go
68 lines
2.8 KiB
Go
package toolkit
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
|
)
|
|
|
|
// Ключи forge-специфичных метаданных в стандартном поле `_meta` (SEP-2575).
|
|
// MCP-хост forge, вызвав инструмент с флагом probe, ожидает, что сервер НЕ
|
|
// выполнит действие, а вернёт эмитированные permission-паттерны. Константы
|
|
// дублируются на стороне хоста: хост не импортирует этот пакет.
|
|
const (
|
|
metaProbeKey = "forge.permission_patterns"
|
|
metaPatternsKey = "forge.patterns"
|
|
metaAlwaysKey = "forge.always"
|
|
// metaCapabilityKey — флаг в Tool.Meta: сервер объявляет поддержку
|
|
// forge-протокола эмитированных паттернов. Хост проверяет его перед
|
|
// probe, чтобы не слать probe серверам без поддержки.
|
|
metaCapabilityKey = "forge.supports_permission_patterns"
|
|
)
|
|
|
|
// PatternsFn вычисляет эмитированные permission-паттерны и безопасные
|
|
// префиксы "always" по аргументам инструмента. nil — инструмент паттернов
|
|
// не эмитирует (хост применит политику по умолчанию).
|
|
type PatternsFn func(args map[string]any) (patterns, always []string)
|
|
|
|
// WrapProbe оборачивает handler, перехватывая probe-запрос хоста: вместо
|
|
// выполнения действия возвращает `_meta` с паттернами.
|
|
func WrapProbe(h mcp.ToolHandler, fn PatternsFn) mcp.ToolHandler {
|
|
return func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
|
if IsProbe(req) {
|
|
var patterns, always []string
|
|
if fn != nil {
|
|
patterns, always = fn(RequestArgs(req))
|
|
}
|
|
return &mcp.CallToolResult{
|
|
Meta: mcp.Meta{metaPatternsKey: patterns, metaAlwaysKey: always},
|
|
}, nil
|
|
}
|
|
return h(ctx, req)
|
|
}
|
|
}
|
|
|
|
// RegisterPatternTool регистрирует инструмент с поддержкой forge-probe:
|
|
// помечает Tool.Meta флагом поддержки и оборачивает handler. Без флага хост
|
|
// не стал бы слать probe-вызов.
|
|
func RegisterPatternTool(s *mcp.Server, tool *mcp.Tool, fn PatternsFn, h mcp.ToolHandler) {
|
|
if tool.Meta == nil {
|
|
tool.Meta = mcp.Meta{}
|
|
}
|
|
tool.Meta[metaCapabilityKey] = true
|
|
s.AddTool(tool, WrapProbe(h, fn))
|
|
}
|
|
|
|
// IsProbe сообщает, является ли вызов probe-запросом паттернов.
|
|
func IsProbe(req *mcp.CallToolRequest) bool {
|
|
if req == nil || req.Params == nil {
|
|
return false
|
|
}
|
|
v, ok := req.Params.GetMeta()[metaProbeKey]
|
|
if !ok {
|
|
return false
|
|
}
|
|
b, _ := v.(bool)
|
|
return b
|
|
}
|