From 23d889254b187614d1b5c3b653d036b607426c50 Mon Sep 17 00:00:00 2001 From: Ukjae Jeong Date: Tue, 16 Jun 2026 15:49:49 +0100 Subject: [PATCH] Go SDK: Align hooks with SEP (#23) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SEP spec and C# SDK use hooks (plural, JSON array) but the Go SDK had hook (singular, single object). This meant the wire formats were incompatible — Go would send `{"hook": {...}}` while everything else expects `{"hooks": [...]}`. Signed-off-by: Ukjae Jeong --- go/sdk/README.md | 4 +- go/sdk/examples/mutator/main.go | 4 +- go/sdk/examples/validator/main.go | 4 +- go/sdk/interceptors/chain/chain.go | 21 ++++--- go/sdk/interceptors/chain/chain_test.go | 26 +++++---- go/sdk/interceptors/doc.go | 8 +-- go/sdk/interceptors/extension/rpc.go | 11 +++- go/sdk/interceptors/extension/rpc_test.go | 16 +++--- go/sdk/interceptors/extension/server.go | 6 +- .../extension/server_integration_test.go | 56 +++++++++---------- .../extension/testharness_test.go | 16 +++--- .../gomiddleware/middleware_test.go | 24 ++++---- go/sdk/interceptors/interceptor.go | 2 +- go/sdk/interceptors/wire.go | 4 +- 14 files changed, 110 insertions(+), 92 deletions(-) diff --git a/go/sdk/README.md b/go/sdk/README.md index 56a1fbb..47ca48b 100644 --- a/go/sdk/README.md +++ b/go/sdk/README.md @@ -20,10 +20,10 @@ ext := extension.New() ext.AddInterceptor(&interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "block-dangerous", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.ValidationResult, error) { diff --git a/go/sdk/examples/mutator/main.go b/go/sdk/examples/mutator/main.go index 3f54098..fe3f125 100644 --- a/go/sdk/examples/mutator/main.go +++ b/go/sdk/examples/mutator/main.go @@ -37,10 +37,10 @@ func main() { m := &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: "audit-tag", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseResponse, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.MutationResult, error) { diff --git a/go/sdk/examples/validator/main.go b/go/sdk/examples/validator/main.go index 3d07040..b12516d 100644 --- a/go/sdk/examples/validator/main.go +++ b/go/sdk/examples/validator/main.go @@ -37,10 +37,10 @@ func main() { v := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "block-dangerous-tool", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.ValidationResult, error) { diff --git a/go/sdk/interceptors/chain/chain.go b/go/sdk/interceptors/chain/chain.go index 5c84ecb..20081e7 100644 --- a/go/sdk/interceptors/chain/chain.go +++ b/go/sdk/interceptors/chain/chain.go @@ -143,10 +143,7 @@ func (c *Chain) Execute(ctx context.Context, params *ExecutionParams) (*Executio if len(nameFilter) > 0 && !nameFilter[e.Interceptor.Name] { continue } - if !matchesPhase(e.Interceptor.Hook.Phase, params.Phase) { - continue - } - if !slices.Contains(e.Interceptor.Hook.Events, params.Event) { + if !matchesHooks(e.Interceptor.Hooks, params.Event, params.Phase) { continue } switch e.Interceptor.Type { @@ -432,8 +429,16 @@ func (c *Chain) timeoutResult(cr *ExecutionResult, start time.Time) { }) } -// matchesPhase checks if an interceptor's configured phase covers the target -// phase. An interceptor with PhaseBoth matches any target phase. -func matchesPhase(interceptorPhase, targetPhase interceptors.InterceptionPhase) bool { - return interceptorPhase == interceptors.PhaseBoth || interceptorPhase == targetPhase +// matchesHooks checks if any hook entry matches both the target event and phase. +// A hook with PhaseBoth matches any target phase. +func matchesHooks(hooks []interceptors.Hook, event string, phase interceptors.InterceptionPhase) bool { + for _, h := range hooks { + if h.Phase != interceptors.PhaseBoth && h.Phase != phase { + continue + } + if slices.Contains(h.Events, event) { + return true + } + } + return false } diff --git a/go/sdk/interceptors/chain/chain_test.go b/go/sdk/interceptors/chain/chain_test.go index 35e24f5..25faf6e 100644 --- a/go/sdk/interceptors/chain/chain_test.go +++ b/go/sdk/interceptors/chain/chain_test.go @@ -67,10 +67,12 @@ func registerInterceptorMethods(server *mcp.Server, is []interceptors.Intercepto for _, i := range is { if event != "" { match := false - for _, e := range i.GetMetadata().Hook.Events { - if e == event { - match = true - break + for _, h := range i.GetMetadata().Hooks { + for _, e := range h.Events { + if e == event { + match = true + break + } } } if !match { @@ -142,10 +144,10 @@ func TestChain_FailOpenRecordsExecutionResult(t *testing.T) { failOpenValidator := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "fo-validator", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{"test/event"}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, FailOpen: true, }, @@ -156,10 +158,10 @@ func TestChain_FailOpenRecordsExecutionResult(t *testing.T) { passingValidator := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "passing-validator", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{"test/event"}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, _ *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -190,10 +192,10 @@ func TestChain_FailOpenRecordsExecutionResult(t *testing.T) { failOpenMutator := &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: "fo-mutator", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{"test/event"}, Phase: interceptors.PhaseResponse, - }, + }}, Mode: interceptors.ModeEnforce, FailOpen: true, PriorityHint: interceptors.NewPriority(10), @@ -205,10 +207,10 @@ func TestChain_FailOpenRecordsExecutionResult(t *testing.T) { passingMutator := &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: "passing-mutator", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{"test/event"}, Phase: interceptors.PhaseResponse, - }, + }}, Mode: interceptors.ModeEnforce, PriorityHint: interceptors.NewPriority(20), }, diff --git a/go/sdk/interceptors/doc.go b/go/sdk/interceptors/doc.go index c373016..205848e 100644 --- a/go/sdk/interceptors/doc.go +++ b/go/sdk/interceptors/doc.go @@ -45,10 +45,10 @@ // v := &interceptors.Validator{ // Metadata: interceptors.Metadata{ // Name: "block-dangerous-tool", -// Hook: interceptors.Hook{ +// Hooks: []interceptors.Hook{{ // Events: []string{"tools/call"}, // Phase: interceptors.PhaseRequest, -// }, +// }}, // Mode: interceptors.ModeEnforce, // }, // Handler: func(ctx context.Context, inv *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -73,10 +73,10 @@ // m := &interceptors.Mutator{ // Metadata: interceptors.Metadata{ // Name: "redact-pii", -// Hook: interceptors.Hook{ +// Hooks: []interceptors.Hook{{ // Events: []string{"tools/call"}, // Phase: interceptors.PhaseResponse, -// }, +// }}, // Mode: interceptors.ModeEnforce, // }, // Handler: func(ctx context.Context, inv *interceptors.Invocation) (*interceptors.MutationResult, error) { diff --git a/go/sdk/interceptors/extension/rpc.go b/go/sdk/interceptors/extension/rpc.go index 067d39b..97a3c8f 100644 --- a/go/sdk/interceptors/extension/rpc.go +++ b/go/sdk/interceptors/extension/rpc.go @@ -27,7 +27,7 @@ func (e *Extension) handleList(_ context.Context, req *mcp.ServerRequest[*interc all := e.getInterceptors() infos := make([]interceptors.InterceptorInfo, 0, len(all)) for _, ri := range all { - if event != "" && !slices.Contains(ri.GetMetadata().Hook.Events, event) { + if event != "" && !hooksContainEvent(ri.GetMetadata().Hooks, event) { continue } infos = append(infos, interceptors.InfoFromInterceptor(ri)) @@ -105,3 +105,12 @@ func (e *Extension) handleInvoke(ctx context.Context, req *mcp.ServerRequest[*in return result, nil } + +func hooksContainEvent(hooks []interceptors.Hook, event string) bool { + for _, h := range hooks { + if slices.Contains(h.Events, event) { + return true + } + } + return false +} diff --git a/go/sdk/interceptors/extension/rpc_test.go b/go/sdk/interceptors/extension/rpc_test.go index 521874b..5a2911a 100644 --- a/go/sdk/interceptors/extension/rpc_test.go +++ b/go/sdk/interceptors/extension/rpc_test.go @@ -42,10 +42,10 @@ func TestListWithEventFilter(t *testing.T) { promptsValidator := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "prompts-v", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventPromptsGet}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, _ *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -112,10 +112,10 @@ func TestInvokeValidatorRejects(t *testing.T) { rejectAll := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "reject-all", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, _ *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -155,10 +155,10 @@ func TestInvokeMutator(t *testing.T) { mutator := &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: "add-field", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.MutationResult, error) { @@ -231,10 +231,10 @@ func TestInvokeTimeout(t *testing.T) { slowValidator := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "slow-v", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(ctx context.Context, _ *interceptors.Invocation) (*interceptors.ValidationResult, error) { diff --git a/go/sdk/interceptors/extension/server.go b/go/sdk/interceptors/extension/server.go index 04e60f1..8543383 100644 --- a/go/sdk/interceptors/extension/server.go +++ b/go/sdk/interceptors/extension/server.go @@ -181,8 +181,10 @@ func (e *Extension) enrichInitResult(result mcp.Result) (mcp.Result, error) { all := e.getInterceptors() supportedEvents := map[string]bool{} for _, ri := range all { - for _, ev := range ri.GetMetadata().Hook.Events { - supportedEvents[ev] = true + for _, h := range ri.GetMetadata().Hooks { + for _, ev := range h.Events { + supportedEvents[ev] = true + } } } diff --git a/go/sdk/interceptors/extension/server_integration_test.go b/go/sdk/interceptors/extension/server_integration_test.go index 03c5d22..85e8dab 100644 --- a/go/sdk/interceptors/extension/server_integration_test.go +++ b/go/sdk/interceptors/extension/server_integration_test.go @@ -86,10 +86,10 @@ func TestServer_ValidatorWarnDoesNotBlock(t *testing.T) { warnValidator := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "warn-only", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, _ *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -117,10 +117,10 @@ func TestServer_ValidationFailurePreventsM(t *testing.T) { spy := &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: "spy-mutator", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, _ *interceptors.Invocation) (*interceptors.MutationResult, error) { @@ -141,10 +141,10 @@ func TestServer_ValidatorTimeoutAbortsChain(t *testing.T) { slowValidator := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "slow-validator", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(ctx context.Context, _ *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -172,10 +172,10 @@ func TestServer_MutatorTimeoutAbortsChain(t *testing.T) { slowMutator := &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: "m2-slow", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseResponse, - }, + }}, Mode: interceptors.ModeEnforce, PriorityHint: interceptors.NewPriority(20), }, @@ -208,10 +208,10 @@ func TestServer_MutatorFailOpenContinuesChain(t *testing.T) { failOpenMutator := &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: "m2-failopen", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseResponse, - }, + }}, Mode: interceptors.ModeEnforce, FailOpen: true, PriorityHint: interceptors.NewPriority(20), @@ -248,10 +248,10 @@ func TestServer_ResponseMutatorSeesMutatedParams(t *testing.T) { reqMutator := &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: "inject-marker", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.MutationResult, error) { @@ -309,10 +309,10 @@ func TestServer_CombinedValidatorsAndMutators(t *testing.T) { reqV1 := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "req-v1-tool-check", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -343,10 +343,10 @@ func TestServer_CombinedValidatorsAndMutators(t *testing.T) { reqV2 := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "req-v2-args-check", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -381,10 +381,10 @@ func TestServer_CombinedValidatorsAndMutators(t *testing.T) { reqV3 := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "req-v3-warn", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, _ *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -405,10 +405,10 @@ func TestServer_CombinedValidatorsAndMutators(t *testing.T) { return &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: name, - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, PriorityHint: interceptors.NewPriority(priority), }, @@ -454,10 +454,10 @@ func TestServer_CombinedValidatorsAndMutators(t *testing.T) { return &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: name, - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseResponse, - }, + }}, Mode: interceptors.ModeEnforce, PriorityHint: interceptors.NewPriority(priority), }, @@ -496,10 +496,10 @@ func TestServer_CombinedValidatorsAndMutators(t *testing.T) { respV1 := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "resp-v1-has-content", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseResponse, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -530,10 +530,10 @@ func TestServer_CombinedValidatorsAndMutators(t *testing.T) { respV2 := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "resp-v2-sees-mutation", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseResponse, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -566,10 +566,10 @@ func TestServer_CombinedValidatorsAndMutators(t *testing.T) { respV3 := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "resp-v3-info", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseResponse, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, _ *interceptors.Invocation) (*interceptors.ValidationResult, error) { diff --git a/go/sdk/interceptors/extension/testharness_test.go b/go/sdk/interceptors/extension/testharness_test.go index fc6cd13..b562ca8 100644 --- a/go/sdk/interceptors/extension/testharness_test.go +++ b/go/sdk/interceptors/extension/testharness_test.go @@ -190,10 +190,10 @@ func prefixMutator(name, tag string, phase interceptors.InterceptionPhase, prior return &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: name, - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: phase, - }, + }}, Mode: mode, PriorityHint: interceptors.NewPriority(priority), }, @@ -225,10 +225,10 @@ func failMutator(name string, phase interceptors.InterceptionPhase, priority int return &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: name, - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: phase, - }, + }}, Mode: interceptors.ModeEnforce, PriorityHint: interceptors.NewPriority(priority), }, @@ -243,10 +243,10 @@ func blockToolValidator(toolName string) *interceptors.Validator { return &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "block-" + toolName, - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -278,10 +278,10 @@ func allowAllValidator(name string) *interceptors.Validator { return &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: name, - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, _ *interceptors.Invocation) (*interceptors.ValidationResult, error) { diff --git a/go/sdk/interceptors/integrations/gomiddleware/middleware_test.go b/go/sdk/interceptors/integrations/gomiddleware/middleware_test.go index a38c074..66d15dc 100644 --- a/go/sdk/interceptors/integrations/gomiddleware/middleware_test.go +++ b/go/sdk/interceptors/integrations/gomiddleware/middleware_test.go @@ -81,10 +81,10 @@ func TestMiddlewareBlocksOnValidationError(t *testing.T) { blocker := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "block-echo", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -125,10 +125,10 @@ func TestMiddlewarePassesOnSuccess(t *testing.T) { allow := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "allow-all", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, _ *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -152,10 +152,10 @@ func TestMiddlewareMutatesPayload(t *testing.T) { mutator := &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: "add-prefix", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseResponse, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.MutationResult, error) { @@ -197,10 +197,10 @@ func TestMiddlewareAuditModeNonBlocking(t *testing.T) { auditValidator := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "audit-reject", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeAudit, }, Handler: func(_ context.Context, _ *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -230,10 +230,10 @@ func TestMiddlewareWithContextProvider(t *testing.T) { principalCheck := &interceptors.Validator{ Metadata: interceptors.Metadata{ Name: "check-principal", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.ValidationResult, error) { @@ -312,10 +312,10 @@ func TestMiddlewareRequestMutatorModifiesArgs(t *testing.T) { reqMutator := &interceptors.Mutator{ Metadata: interceptors.Metadata{ Name: "inject-field", - Hook: interceptors.Hook{ + Hooks: []interceptors.Hook{{ Events: []string{interceptors.EventToolsCall}, Phase: interceptors.PhaseRequest, - }, + }}, Mode: interceptors.ModeEnforce, }, Handler: func(_ context.Context, inv *interceptors.Invocation) (*interceptors.MutationResult, error) { diff --git a/go/sdk/interceptors/interceptor.go b/go/sdk/interceptors/interceptor.go index ffed285..ffdee99 100644 --- a/go/sdk/interceptors/interceptor.go +++ b/go/sdk/interceptors/interceptor.go @@ -74,7 +74,7 @@ type Metadata struct { Version string `json:"version,omitempty"` Description string `json:"description,omitempty"` Type InterceptorType `json:"type"` - Hook Hook `json:"hook"` + Hooks []Hook `json:"hooks"` PriorityHint Priority `json:"priorityHint,omitempty"` Compat *Compat `json:"compat,omitempty"` ConfigSchema json.RawMessage `json:"configSchema,omitempty"` diff --git a/go/sdk/interceptors/wire.go b/go/sdk/interceptors/wire.go index 1670b56..f66c696 100644 --- a/go/sdk/interceptors/wire.go +++ b/go/sdk/interceptors/wire.go @@ -42,7 +42,7 @@ type InterceptorInfo struct { Version string `json:"version,omitempty"` Description string `json:"description,omitempty"` Type InterceptorType `json:"type"` - Hook Hook `json:"hook"` + Hooks []Hook `json:"hooks"` PriorityHint Priority `json:"priorityHint,omitempty"` Compat *Compat `json:"compat,omitempty"` ConfigSchema json.RawMessage `json:"configSchema,omitempty"` @@ -58,7 +58,7 @@ func InfoFromInterceptor(i Interceptor) InterceptorInfo { Version: m.Version, Description: m.Description, Type: i.GetType(), - Hook: m.Hook, + Hooks: m.Hooks, PriorityHint: m.PriorityHint, Compat: m.Compat, ConfigSchema: m.ConfigSchema,