chore: initial release v0.1.0
ci / test (push) Failing after 5s
ci / lint (push) Failing after 4s

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
This commit is contained in:
Maksim Totmin
2026-09-14 00:23:08 +07:00
commit c398045664
43 changed files with 2581 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
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
}