Documentation
¶
Index ¶
- func BestParamSuggestionForTest(unknown string, validParams []string, maxDistance int) (string, int)
- func BestValueSuggestionForTest(value string, validValues []string, maxDistance int) (string, int)
- func ClassifyOutcomeForTest(result mcpsdk.Result, err error) string
- func EditOutcomeEnumForTest() []string
- func ExtractBadParamsForTest(errMsg string) []string
- func InstallLazyInitMiddleware(server *mcpsdk.Server, activateFn func(ctx context.Context, path string) error, ...)
- func InstallMiddleware(server *mcpsdk.Server, provider *obs.Provider, resolver ProfileResolver, ...)
- func InstallSuggestionMiddleware(server *mcpsdk.Server, schemaMap *ToolSchemaMap, logger *slog.Logger)
- func LevenshteinDistanceForTest(a, b string) int
- func OutcomeEnumForTest() []string
- func ProfileFilterMiddleware(resolver ProfileResolver, getSession func(ctx context.Context) *SessionInfo, ...) mcpsdk.Middleware
- func RecordEditOutcome(ctx context.Context, toolName, outcome, strategy string)
- func RecordRenameStrategy(ctx context.Context, strategy string)
- func SetEditOutcomeSinkForTest(fn func(ctx context.Context, toolName, outcome, strategy string))
- func SetVersion(v string)
- func StrategyEnumForTest() []string
- func SuggestionMiddleware(schemaMap *ToolSchemaMap, logger *slog.Logger) mcpsdk.Middleware
- func TelemetryMiddleware(provider *obs.Provider, getSession func(ctx context.Context) *SessionInfo, ...) mcpsdk.Middleware
- type ActivateCallback
- type ActivateProjectArgs
- type BudgetFunc
- type EchoArgs
- type GRPCStream
- type GRPCTransport
- type LazyInitMiddleware
- type ModeTransition
- type PingArgs
- type ProfileResolver
- type SerenaMCPServer
- func (s *SerenaMCPServer) AddSkillTool(name, description, briefDescription, helpText string, ...)
- func (s *SerenaMCPServer) AddTool(tool *mcpsdk.Tool, handler mcpsdk.ToolHandler)
- func (s *SerenaMCPServer) AddToolWithMeta(tool *mcpsdk.Tool, handler mcpsdk.ToolHandler, brief, helpText string)
- func (s *SerenaMCPServer) CollectToolSchemas() []*mcpsdk.Tool
- func (s *SerenaMCPServer) HTTPHandler() http.Handler
- func (s *SerenaMCPServer) Registry() *ToolRegistry
- func (s *SerenaMCPServer) RemoveTool(name string)
- func (s *SerenaMCPServer) RunStdio(ctx context.Context) error
- func (s *SerenaMCPServer) SDK() *mcpsdk.Server
- func (s *SerenaMCPServer) SetActivateCallback(cb ActivateCallback)
- type SessionInfo
- type SessionSnapshot
- type SkillToolExecutor
- type ToolDef
- type ToolParamInfo
- type ToolRegistry
- type ToolSchemaMap
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BestParamSuggestionForTest ¶
func BestParamSuggestionForTest(unknown string, validParams []string, maxDistance int) (string, int)
BestParamSuggestionForTest exposes bestParamSuggestion to the _test package.
func BestValueSuggestionForTest ¶
BestValueSuggestionForTest exposes bestValueSuggestion to the _test package.
func ClassifyOutcomeForTest ¶
ClassifyOutcomeForTest exposes classifyOutcome to the _test package.
func EditOutcomeEnumForTest ¶
func EditOutcomeEnumForTest() []string
EditOutcomeEnumForTest returns a copy of the closed edit-outcome enum (Phase 53 D-10) for test assertions that the 6-value vocabulary is preserved.
func ExtractBadParamsForTest ¶
ExtractBadParamsForTest exposes extractBadParams to the _test package.
func InstallLazyInitMiddleware ¶
func InstallLazyInitMiddleware(server *mcpsdk.Server, activateFn func(ctx context.Context, path string) error, isActiveFn func() bool, defaultRoot string, logger *slog.Logger)
InstallLazyInitMiddleware wires the lazy init middleware onto the MCP SDK server. MUST be called LAST (after InstallSuggestionMiddleware) so it runs FIRST in the LIFO middleware chain -- before TelemetryMiddleware's deadline (Pitfall 3).
func InstallMiddleware ¶
func InstallMiddleware(server *mcpsdk.Server, provider *obs.Provider, resolver ProfileResolver, getSession func(ctx context.Context) *SessionInfo, budgetFn BudgetFunc, registry *ToolRegistry, logger *slog.Logger)
func InstallSuggestionMiddleware ¶
func InstallSuggestionMiddleware(server *mcpsdk.Server, schemaMap *ToolSchemaMap, logger *slog.Logger)
InstallSuggestionMiddleware wires the suggestion middleware onto the MCP SDK server.
func LevenshteinDistanceForTest ¶
LevenshteinDistanceForTest exposes levenshteinDistance to the _test package.
func OutcomeEnumForTest ¶
func OutcomeEnumForTest() []string
OutcomeEnumForTest returns a copy of the closed outcome enum for test assertions that the 7-value vocabulary is preserved.
func ProfileFilterMiddleware ¶
func ProfileFilterMiddleware(resolver ProfileResolver, getSession func(ctx context.Context) *SessionInfo, briefDescs map[string]string, logger *slog.Logger) mcpsdk.Middleware
ProfileFilterMiddleware creates middleware that filters tool listings based on the active session's AllowedTools and applies description overrides from the profile (PRF-03). For tools/list requests it filters and rewrites descriptions; all other methods pass through unchanged.
func RecordEditOutcome ¶
RecordEditOutcome increments the helix_edit_outcome_total counter. Called from edit (internal/kernel/edit/) and fileops (internal/kernel/fileops/) tool handlers at return.
Closed enums (Phase 53 D-10 + D-11 + Q-4):
outcome ∈ {success, no_match, ambiguous_match, validation_failed, ls_error, internal}
strategy ∈ {exact, whitespace_normalized, indentation_flexible, none}
Unknown values are dropped silently at the *obs.Metrics layer (EditOutcomeInc), mirroring the closed-enum drop-unknown discipline of RenameStrategyInc. Q-4: "failed" is NEVER a valid strategy value at this layer — fuzzy.StrategyFailed paths emit outcome="no_match", strategy="none".
Test-only sink wiring: the editOutcomeSink package-level pointer is process-global. Tests that mutate it via SetEditOutcomeSinkForTest MUST NOT use t.Parallel() — concurrent goroutines would race over the shared recorder and observe each other's emissions. WR-05: prefer paired t.Cleanup(func() { mcp.SetEditOutcomeSinkForTest(nil) }) in any test that installs a custom sink so the leak does not bleed into adjacent tests. Same caveat applies to setRenameStrategySink (Phase 47 D-07).
func RecordRenameStrategy ¶
RecordRenameStrategy increments the helix_rename_strategy_total counter. The strategy string MUST be one of {"lsp-native","rust-client-side"}; any other value is dropped by the underlying obs.Metrics.RenameStrategyInc (closed-enum cardinality discipline, threat T-47-08). ctx is threaded through for future OTel integration; currently the sink adapter discards it.
func SetEditOutcomeSinkForTest ¶
SetEditOutcomeSinkForTest exposes setEditOutcomeSink to external tests (e.g. internal/kernel/edit/tools_test.go) that need to install a recording recorder without going through InstallMiddleware. Production code MUST continue to wire via InstallMiddleware.
WR-05: this mutates process-global state. Callers MUST NOT use t.Parallel() on tests that touch the sink, and SHOULD pair the call with t.Cleanup(func() { SetEditOutcomeSinkForTest(nil) }) so the recorder does not leak into adjacent tests in the same package.
func SetVersion ¶
func SetVersion(v string)
SetVersion records the binary version reported as MCP `Implementation.Version`. Called once from internal/daemon/daemon.go during bootstrap with the ldflag-injected value (which the daemon receives via an optional version argument; see daemon.New for the wiring).
func StrategyEnumForTest ¶
func StrategyEnumForTest() []string
StrategyEnumForTest returns a copy of the closed strategy enum (Phase 53 D-11 + Q-4) for test assertions that the 4-value vocabulary is preserved. Note: "failed" is intentionally absent — see strategyEnum doc.
func SuggestionMiddleware ¶
func SuggestionMiddleware(schemaMap *ToolSchemaMap, logger *slog.Logger) mcpsdk.Middleware
SuggestionMiddleware creates MCP middleware that enriches error responses with "did you mean" parameter and enum value suggestions. It intercepts both protocol errors (from SDK schema validation) and tool errors (IsError=true), looking up the correct parameter names from the pre-built ToolSchemaMap.
Only tools/call requests are intercepted; all other methods pass through. Per D-09, suggestions only reference parameters from the same tool. Per D-10, no new error kinds are created.
func TelemetryMiddleware ¶
func TelemetryMiddleware(provider *obs.Provider, getSession func(ctx context.Context) *SessionInfo, budgetFn BudgetFunc, logger *slog.Logger) mcpsdk.Middleware
TelemetryMiddleware emits RED metrics for every tools/call and preserves the Phase 8 structured log lines for all methods. The Phase 8 log closure has been absorbed here so we only traverse the middleware chain once per request.
Metric emission is gated on method == "tools/call"; tools/list, initialize, and all other methods are pure log pass-through. This matches the v1.2 scope: RED metrics are per-tool-call only (T-11-09 "accept" disposition).
Types ¶
type ActivateCallback ¶
ActivateCallback is called when a project is activated via the activate_project tool. It allows the daemon to wire kernel workspace activation alongside the registry.
type ActivateProjectArgs ¶
type ActivateProjectArgs struct {
RepoPath string `json:"repo_path" jsonschema:"Path to the repository root"`
}
ActivateProjectArgs is the input schema for the activate_project tool (WRK-01).
type BudgetFunc ¶
InstallMiddleware wires Helix's receiving middleware onto the MCP SDK server (MCP-04 + METRIC-02).
TelemetryMiddleware absorbs the previous Phase 8 logging closure: it preserves the structured log lines for every method AND emits RED metrics for method == "tools/call". It fully replaces the Phase 8 log-only middleware.
NOTE: ProfileFilterMiddleware only touches tools/list; TelemetryMiddleware only emits metrics on tools/call. Ordering between the two is independent, so callers may install them in either order. The D-06 "before ProfileFilter" constraint from CONTEXT.md was written assuming ProfileFilter had a deny path at tool-call time; since it does not in v1.2, that ordering constraint is obsolete here. BudgetFunc returns the timeout budget for a tool name. A nil BudgetFunc disables deadline injection (all calls pass through without a timeout). Wired from degrade.BudgetFor in daemon.go to avoid an import cycle (mcp -> config -> profile -> mcp).
type EchoArgs ¶
type EchoArgs struct {
Text string `json:"text" jsonschema:"Text to echo back"`
}
EchoArgs is the input schema for the echo diagnostic tool.
type GRPCStream ¶
type GRPCStream interface {
Recv() (*serenav1.MCPMessage, error)
Send(*serenav1.MCPMessage) error
}
GRPCStream abstracts the gRPC bidirectional stream for testability.
type GRPCTransport ¶
type GRPCTransport struct {
// contains filtered or unexported fields
}
GRPCTransport bridges a gRPC bidirectional stream to the MCP SDK's Transport interface. It uses io.Pipe pairs so that gRPC stream messages flow into the MCP SDK's IOTransport.
Data flow:
gRPC stream.Recv() -> pipeWriter (clientToServer) -> IOTransport.Reader -> MCP SDK MCP SDK -> IOTransport.Writer -> pipeReader (serverToClient) -> gRPC stream.Send()
func NewGRPCTransport ¶
func NewGRPCTransport(stream GRPCStream, sessionID string, firstMsg *serenav1.MCPMessage) *GRPCTransport
NewGRPCTransport creates a new transport backed by a gRPC stream. If firstMsg is non-nil, it is replayed into the client->server pipe before reading from the stream.
func (*GRPCTransport) Connect ¶
func (t *GRPCTransport) Connect(ctx context.Context) (mcpsdk.Connection, error)
Connect returns a Connection that bridges the gRPC stream to the MCP SDK. It spawns goroutines to pump data between gRPC and io.Pipe pairs.
type LazyInitMiddleware ¶
type LazyInitMiddleware struct {
// contains filtered or unexported fields
}
LazyInitMiddleware transparently activates the workspace on the first tools/call if no workspace is active (LAZY-01). Thread-safe via sync.Once per workspace path (LAZY-02).
func NewLazyInitMiddleware ¶
func NewLazyInitMiddleware(activateFn func(ctx context.Context, path string) error, isActiveFn func() bool, defaultRoot string, logger *slog.Logger) *LazyInitMiddleware
NewLazyInitMiddleware creates a lazy init middleware. activateFn is called to activate a workspace (typically daemon's activate callback). isActiveFn returns true if any workspace is currently active. defaultRoot is the fallback project root (from config or forwarder cwd).
func (*LazyInitMiddleware) Middleware ¶
func (m *LazyInitMiddleware) Middleware() mcpsdk.Middleware
Middleware returns the mcpsdk.Middleware function.
type ModeTransition ¶
ModeTransition records a single mode switch for audit purposes (D-07).
type PingArgs ¶
type PingArgs struct {
Message string `json:"message" jsonschema:"Message to echo back"`
}
PingArgs is the input schema for the ping diagnostic tool.
type ProfileResolver ¶
type ProfileResolver interface {
// ToolDescriptionOverrides returns the description override map for the named profile.
// Returns nil if the profile has no overrides or is not found.
ToolDescriptionOverrides(profileName string) map[string]string
}
ProfileResolver provides profile information for middleware filtering. This interface avoids a circular import between mcp and profile packages.
type SerenaMCPServer ¶
type SerenaMCPServer struct {
// contains filtered or unexported fields
}
SerenaMCPServer wraps the official MCP SDK server with Helix's tool registry, structured errors, and middleware (MCP-01, MCP-02, MCP-03, MCP-05, MCP-06).
func NewSerenaMCPServer ¶
func NewSerenaMCPServer(workspaces *workspace.Registry, logger *slog.Logger, tracer trace.Tracer) *SerenaMCPServer
NewSerenaMCPServer creates a new MCP server with dummy tools registered.
The tracer is used by AddSkillTool to emit kernel.tool.{name} spans on invocation (Phase 55-02 / OBS-04). Per Phase 12 D-01 the tracer is injected (never resolved via otel.GetTracerProvider). When tracer is nil, a process-local noop tracer is substituted so all paths stay safe.
func (*SerenaMCPServer) AddSkillTool ¶
func (s *SerenaMCPServer) AddSkillTool(name, description, briefDescription, helpText string, executor SkillToolExecutor)
AddSkillTool registers a skill-provided tool with a generic ExecuteTool handler. Uses the generic mcpsdk.AddTool so the SDK auto-generates an input schema.
func (*SerenaMCPServer) AddTool ¶
func (s *SerenaMCPServer) AddTool(tool *mcpsdk.Tool, handler mcpsdk.ToolHandler)
AddTool registers a new tool dynamically at runtime (MCP-07).
func (*SerenaMCPServer) AddToolWithMeta ¶
func (s *SerenaMCPServer) AddToolWithMeta(tool *mcpsdk.Tool, handler mcpsdk.ToolHandler, brief, helpText string)
AddToolWithMeta registers a tool with optional BriefDescription and HelpText metadata (DESC-01, DESC-02).
func (*SerenaMCPServer) CollectToolSchemas ¶
func (s *SerenaMCPServer) CollectToolSchemas() []*mcpsdk.Tool
CollectToolSchemas returns all registered tool definitions with their InputSchema for suggestion middleware schema introspection (D-07). Called once at daemon startup after all tools are registered.
func (*SerenaMCPServer) HTTPHandler ¶
func (s *SerenaMCPServer) HTTPHandler() http.Handler
HTTPHandler returns an http.Handler for Streamable HTTP transport (MCP-02).
func (*SerenaMCPServer) Registry ¶
func (s *SerenaMCPServer) Registry() *ToolRegistry
Registry returns the tool registry for dynamic tool management.
func (*SerenaMCPServer) RemoveTool ¶
func (s *SerenaMCPServer) RemoveTool(name string)
RemoveTool removes a tool by name at runtime (MCP-07).
func (*SerenaMCPServer) RunStdio ¶
func (s *SerenaMCPServer) RunStdio(ctx context.Context) error
RunStdio runs the MCP server over stdio transport (MCP-01).
func (*SerenaMCPServer) SDK ¶
func (s *SerenaMCPServer) SDK() *mcpsdk.Server
SDK returns the underlying MCP SDK server for direct use (e.g., transport wiring).
func (*SerenaMCPServer) SetActivateCallback ¶
func (s *SerenaMCPServer) SetActivateCallback(cb ActivateCallback)
SetActivateCallback installs a callback invoked when activate_project succeeds. The daemon uses this to activate the kernel workspace alongside the registry.
type SessionInfo ¶
type SessionInfo struct {
SessionID string
WorkspaceKey string // hash of workspace.WorkspaceKey
Mode string // current operational mode (D-07) — read/write via accessors after bootstrap
Profile string // active profile name
Language string // active workspace primary language (A2: Phase 11 metric label)
AllowedTools []string // tools available in current mode/profile (nil = all)
// ModeHistory records all mode transitions for auditability (D-07).
ModeHistory []ModeTransition
// contains filtered or unexported fields
}
SessionInfo tracks Helix-specific session state layered on top of MCP SDK sessions. Per DMN-06: session keyed by MCP session + dirty buffer overlay + mode/capability profile.
Thread-safety: All fields are guarded by mu. Callers MUST use the accessor methods (Snapshot, SetAllowedTools, RecordModeTransition) rather than touching fields directly, because concurrent MCP tool calls and tools/list requests can race on Mode / AllowedTools (threat T-08-08: Tampering / EoP on session state under concurrent switch_mode + tool invocation). Direct field access is retained only for single-writer initialization in the daemon bootstrap before the session is exposed to MCP handlers.
func (*SessionInfo) RecordModeTransition ¶
func (s *SessionInfo) RecordModeTransition(from, to string)
RecordModeTransition appends a transition to the mode history and updates the current mode atomically.
func (*SessionInfo) SetAllowedTools ¶
func (s *SessionInfo) SetAllowedTools(tools []string)
SetAllowedTools replaces the session's tool whitelist under the write lock. The provided slice is copied so callers may safely mutate it afterwards.
func (*SessionInfo) SetLanguage ¶
func (s *SessionInfo) SetLanguage(lang string)
SetLanguage updates the session's active workspace language under the write lock. Symmetric with SetAllowedTools — the Phase 11 TelemetryMiddleware reads this via Snapshot() to populate the "language" metric label (A2).
func (*SessionInfo) Snapshot ¶
func (s *SessionInfo) Snapshot() SessionSnapshot
Snapshot returns a defensively-copied snapshot of the session state. It is the preferred read path for code outside of this package.
type SessionSnapshot ¶
type SessionSnapshot struct {
SessionID string
WorkspaceKey string
Mode string
Profile string
Language string // A2: v1.2 metric label — empty string is a valid Prometheus label value
AllowedTools []string // defensive copy; safe to iterate without locking
}
SessionSnapshot is an immutable point-in-time view of a SessionInfo suitable for use by readers (middleware, tool handlers) that need a consistent read of multiple related fields without holding the session lock across further work.
type SkillToolExecutor ¶
type SkillToolExecutor interface {
ExecuteTool(name string, args map[string]interface{}) (string, error)
}
SkillToolExecutor is implemented by skills that support direct tool execution.
type ToolDef ¶
type ToolDef struct {
Name string
Description string
BriefDescription string // short description for tools/list (under 100 tokens, DESC-01)
HelpText string // usage examples and patterns for get_tool_help (DESC-02)
// RegisterFn is called to register this tool with the MCP SDK server.
// This is a callback because the SDK's AddTool is generic and requires type params.
RegisterFn func(server interface{}) error
}
ToolDef holds a tool definition before registration with the MCP SDK server.
type ToolParamInfo ¶
type ToolParamInfo struct {
ValidParams []string // known parameter names for this tool
EnumValues map[string][]string // param_name -> valid enum values (nil if no enums)
}
ToolParamInfo holds known parameter names and enum values for a single tool.
type ToolRegistry ¶
type ToolRegistry struct {
// contains filtered or unexported fields
}
ToolRegistry manages tools that can be dynamically added/removed (MCP-07).
func NewToolRegistry ¶
func NewToolRegistry(logger *slog.Logger) *ToolRegistry
NewToolRegistry creates a new registry.
func (*ToolRegistry) BriefDescriptions ¶
func (r *ToolRegistry) BriefDescriptions() map[string]string
BriefDescriptions returns a map of tool name to BriefDescription for all tools that have a non-empty BriefDescription (DESC-01).
func (*ToolRegistry) Count ¶
func (r *ToolRegistry) Count() int
Count returns the number of registered tools.
func (*ToolRegistry) Get ¶
func (r *ToolRegistry) Get(name string) *ToolDef
Get returns the ToolDef for a tool by name, or nil if not found.
func (*ToolRegistry) Names ¶
func (r *ToolRegistry) Names() []string
Names returns all registered tool names.
func (*ToolRegistry) Register ¶
func (r *ToolRegistry) Register(def *ToolDef)
Register adds a tool definition to the registry.
func (*ToolRegistry) Unregister ¶
func (r *ToolRegistry) Unregister(name string)
Unregister removes a tool by name.
type ToolSchemaMap ¶
type ToolSchemaMap struct {
// contains filtered or unexported fields
}
ToolSchemaMap maps tool names to their parameter information, used by SuggestionMiddleware to provide "did you mean" suggestions.
func BuildToolSchemaMap ¶
func BuildToolSchemaMap(tools []*mcpsdk.Tool) *ToolSchemaMap
BuildToolSchemaMap constructs a ToolSchemaMap from registered tool definitions. It extracts parameter names and enum constraints from each tool's InputSchema. Tools whose schema fails to parse are skipped gracefully.