Documentation
¶
Overview ¶
Package dynamic implements low-token GitLab MCP tool surfaces over the canonical action catalog.
Dynamic mode exposes a small discovery and execution interface instead of advertising every GitLab operation as an MCP tool. It registers gitlab_find_action and gitlab_execute_action.
The package builds a deterministic search index from actioncatalog.Catalog, resolves canonical domain.action IDs and aliases, returns exact schemas on demand, and dispatches execution through the same ActionRoute metadata used by meta-tools. It does not wrap or call the visible individual MCP tools.
Token Budget ¶
Dynamic mode is intentionally sparse: find returns ranked action summaries with exact schemas, and execute routes one canonical action. Descriptive package and API-reference documentation belongs in Go package comments and project docs, not in dynamic response fields.
Safety ¶
Execution reuses catalog metadata for destructive flags, read-only filtering, safe-mode previews, compatibility aliases, parameter alias normalization, and schema lookup. This keeps dynamic behavior aligned with meta-tools without a second action registry.
Index ¶
- Constants
- func AddStandaloneCatalog(catalog *actioncatalog.Catalog, client *gitlabclient.Client, ...) (*actioncatalog.Catalog, error)
- func AddStandaloneRoutes(routes map[string]toolutil.ActionMap, client *gitlabclient.Client, ...) (map[string]toolutil.ActionMap, error)
- func ControllerSurfaceSpecs(registry *Registry) []actioncatalog.SurfaceToolSpec
- func NormalizeActionScopedParams(actionID string, params, schema map[string]any) map[string]any
- func NormalizeActionScopedParamsWithExplanation(actionID string, params, schema map[string]any) (map[string]any, []toolutil.ParamAliasExplanation)
- func NormalizeCompatibilityActionAlias(actionID string) (string, bool)
- func RegisterCatalogFindExecuteTools(server *mcp.Server, catalog *actioncatalog.Catalog, opts ...RegistryOption)
- func ResetSearchRuntimeMetrics()
- type ActionDescription
- type ActionExample
- type AliasAuditFinding
- type CatalogDiscoveryFinding
- type DescribeInput
- type DescribeOutput
- type ExecuteInput
- type FindInput
- type FindOutput
- type FindResult
- type MatchReason
- type Registry
- func (r *Registry) AllActionsReadOnly() bool
- func (r *Registry) Describe(_ context.Context, _ *mcp.CallToolRequest, input DescribeInput) (*mcp.CallToolResult, DescribeOutput, error)
- func (r *Registry) Execute(ctx context.Context, req *mcp.CallToolRequest, input ExecuteInput) (*mcp.CallToolResult, any, error)
- func (r *Registry) Find(ctx context.Context, req *mcp.CallToolRequest, input FindInput) (*mcp.CallToolResult, FindOutput, error)
- func (r *Registry) Metrics() RegistryMetrics
- func (r *Registry) Search(ctx context.Context, _ *mcp.CallToolRequest, input SearchInput) (*mcp.CallToolResult, SearchOutput, error)
- type RegistryMetrics
- type RegistryOption
- type ScoringExplanation
- type SearchInput
- type SearchOutput
- type SearchResult
- type SearchRuntimeMetrics
- type StandaloneOptions
Constants ¶
const ( // FindActionToolName is the read-only catalog discovery tool. FindActionToolName = "gitlab_find_action" // ExecuteActionToolName is the dispatcher that routes every catalog action. ExecuteActionToolName = "gitlab_execute_action" )
Tool names of the dynamic surface. They are exported so callers that reason about which tools are catalog-backed — safe-mode exemption, for instance — do not have to hardcode the strings.
const ExecuteActionHeaderName = "Mcp-Param-" + executeActionHeaderSuffix
ExecuteActionHeaderName is the wire header the SEP-2243 annotation on the action property resolves to: for documentation, for tests that assert what a client must actually send, and for the HTTP CORS allow-list. A browser drops a request header its preflight did not authorize, and the server then rejects the call for that header's absence, so the two must be derived from one another rather than maintained in parallel. Declared on its own so it carries its own documentation; the suffix it is built from lives in the block below.
const MaxSearchQueryLength = 256
MaxSearchQueryLength is the longest query the catalog search accepts, in characters.
A search costs the query's word count times the size of the catalog, three times over: the lexical pass, the fuzzy pass that a query matching nothing always reaches, and one pass per window of the segmented pass. Nothing bounded the query, and a request body may be 4 MiB, which is hundreds of thousands of words.
Measured by BenchmarkFind_PathologicalQuery against the Free catalog, with words that match nothing: two words cost 14 ms and 1.7 MB, eight words 229 ms and 6.8 MB, and a query filling this bound 0.8 s and 20 MB. So the bound is what makes one call's cost a number at all.
256 characters is around forty words, comfortably above every query the tool's own description suggests and above anything a model has been observed to send.
It is a count of characters rather than bytes, because that is what JSON Schema's maxLength counts, and the schema and this check have to refuse the same queries.
Variables ¶
This section is empty.
Functions ¶
func AddStandaloneCatalog ¶
func AddStandaloneCatalog(catalog *actioncatalog.Catalog, client *gitlabclient.Client, opts StandaloneOptions) (*actioncatalog.Catalog, error)
AddStandaloneCatalog adds non-meta standalone tools to the canonical dynamic action catalog so dynamic mode can execute them without increasing the visible tool count.
func AddStandaloneRoutes ¶
func AddStandaloneRoutes(routes map[string]toolutil.ActionMap, client *gitlabclient.Client, opts StandaloneOptions) (map[string]toolutil.ActionMap, error)
AddStandaloneRoutes adds non-meta standalone tools to the canonical dynamic action catalog so dynamic mode can still execute them through gitlab_execute_action without increasing the visible tool count.
func ControllerSurfaceSpecs ¶
func ControllerSurfaceSpecs(registry *Registry) []actioncatalog.SurfaceToolSpec
ControllerSurfaceSpecs returns explicit surface metadata for Dynamic controller tools. Registration stays custom because these tools expose controller-specific Markdown results and, for execute, action-dependent output.
func NormalizeActionScopedParams ¶
NormalizeActionScopedParams applies compatibility aliases that are safe only for a specific dynamic catalog action.
func NormalizeActionScopedParamsWithExplanation ¶
func NormalizeActionScopedParamsWithExplanation(actionID string, params, schema map[string]any) (map[string]any, []toolutil.ParamAliasExplanation)
NormalizeActionScopedParamsWithExplanation returns normalized params plus name-only metadata for action-scoped compatibility aliases and coercions.
func NormalizeCompatibilityActionAlias ¶
NormalizeCompatibilityActionAlias canonicalizes an unambiguous built-in dynamic compatibility alias without requiring a registry instance.
func RegisterCatalogFindExecuteTools ¶
func RegisterCatalogFindExecuteTools(server *mcp.Server, catalog *actioncatalog.Catalog, opts ...RegistryOption)
RegisterCatalogFindExecuteTools registers the dynamic find and execute tools from the canonical action catalog.
func ResetSearchRuntimeMetrics ¶
func ResetSearchRuntimeMetrics()
ResetSearchRuntimeMetrics clears process-local search quality counters.
Types ¶
type ActionDescription ¶
type ActionDescription struct {
ID string `json:"id" jsonschema:"Canonical action ID."`
Tool string `json:"tool" jsonschema:"Backing meta-tool name."`
Domain string `json:"domain" jsonschema:"Canonical action domain."`
Action string `json:"action" jsonschema:"Action name inside the catalog group."`
SchemaURI string `json:"schema_uri" jsonschema:"MCP resource URI for the action parameter schema."`
Destructive bool `json:"destructive" jsonschema:"Whether this action requires explicit confirmation."`
RequiredParams []string `` /* 132-byte string literal not displayed */
Usage string `json:"usage,omitempty" jsonschema:"Short disambiguation note for commonly confused actions."`
RelatedActions []string `json:"related_actions,omitempty" jsonschema:"Curated nearby action IDs for workflows where ordering matters."`
ParamGuidance map[string]toolutil.ParameterGuidance `json:"parameter_guidance,omitempty" jsonschema:"Parameter binding guidance for commonly confused params."`
InputSchema map[string]any `json:"input_schema" jsonschema:"Exact JSON Schema for action-specific params."`
OutputSchema map[string]any `json:"output_schema,omitempty" jsonschema:"Best-effort JSON Schema for the action result."`
Example ActionExample `json:"example" jsonschema:"Example gitlab_execute_action call."`
}
ActionDescription describes one GitLab catalog action.
type ActionExample ¶
type ActionExample struct {
Tool string `json:"tool" jsonschema:"Tool to call for execution."`
Arguments map[string]any `json:"arguments" jsonschema:"Example arguments for gitlab_execute_action."`
}
ActionExample shows how to call gitlab_execute_action for an action.
type AliasAuditFinding ¶
type AliasAuditFinding struct {
Severity string
Problem string
Alias string
Canonical string
Source string
Message string
}
AliasAuditFinding describes one dynamic alias governance finding.
func AuditDefaultActionAliases ¶
func AuditDefaultActionAliases(catalog *actioncatalog.Catalog) []AliasAuditFinding
AuditDefaultActionAliases returns governance findings for catalog-projected compatibility aliases. It reports duplicate alias/canonical pairs, aliases that map to missing canonical actions when a catalog is provided, and ambiguous aliases that resolve to multiple canonical IDs.
Severity levels in the returned AliasAuditFinding values are interpreted as follows: "error" for definite violations, "warning" for ambiguous alias mappings that require explicit canonical IDs, and "info" for expected informational states such as intentionally unsearchable aliases.
type CatalogDiscoveryFinding ¶
type CatalogDiscoveryFinding struct {
Severity string
Problem string
Tool string
Action string
ID string
Message string
}
CatalogDiscoveryFinding describes one catalog action whose dynamic search metadata is weak enough to deserve review.
func AuditCatalogDiscoveryTerms ¶
func AuditCatalogDiscoveryTerms(catalog *actioncatalog.Catalog) []CatalogDiscoveryFinding
AuditCatalogDiscoveryTerms reports actions in dense catalog groups that have no discovery signal beyond their canonical ID/domain/action words. It is a deterministic audit helper for targeted metadata work, not a hard production validation gate.
func AuditRegistryDiscoveryTerms ¶
func AuditRegistryDiscoveryTerms(registry *Registry) []CatalogDiscoveryFinding
AuditRegistryDiscoveryTerms reports actions in dense dynamic registry groups that have no discovery signal beyond their canonical ID/domain/action words. Use this variant when a caller already has a dynamic registry available.
type DescribeInput ¶
type DescribeInput struct {
Action string `json:"action,omitempty" jsonschema:"Canonical action ID to describe, such as project.create. Use either action or actions."`
Actions []string `json:"actions,omitempty" jsonschema:"Canonical action IDs to describe in one call."`
}
DescribeInput identifies catalog actions to describe.
type DescribeOutput ¶
type DescribeOutput struct {
Count int `json:"count" jsonschema:"Number of described actions."`
Actions []ActionDescription `json:"actions" jsonschema:"Detailed action descriptions."`
}
DescribeOutput is the structured output for catalog action descriptions.
type ExecuteInput ¶
type ExecuteInput struct {
Action string `` /* 166-byte string literal not displayed */
Params map[string]any `` /* 162-byte string literal not displayed */
Confirm bool `` /* 167-byte string literal not displayed */
}
ExecuteInput is the input for gitlab_execute_action.
type FindInput ¶
type FindInput struct {
Query string `` /* 272-byte string literal not displayed */
Limit int `json:"limit,omitempty" jsonschema:"Maximum number of matches to return. Defaults to 20 and is capped at 50."`
Explain bool `` /* 157-byte string literal not displayed */
}
FindInput is the input for gitlab_find_action.
type FindOutput ¶
type FindOutput struct {
Query string `json:"query" jsonschema:"Original search query."`
Count int `json:"count" jsonschema:"Number of returned matches."`
Results []FindResult `json:"results" jsonschema:"Matching GitLab catalog actions with schemas and execute examples."`
}
FindOutput is the structured output for gitlab_find_action.
type FindResult ¶
type FindResult struct {
ID string `json:"id" jsonschema:"Canonical action ID to pass to gitlab_execute_action."`
Tool string `json:"tool" jsonschema:"Backing meta-tool name."`
Domain string `json:"domain" jsonschema:"Canonical action domain."`
Action string `json:"action" jsonschema:"Action name inside the catalog group."`
SchemaURI string `json:"schema_uri" jsonschema:"MCP resource URI for the action parameter schema."`
Destructive bool `json:"destructive" jsonschema:"Whether this action requires explicit confirmation."`
RequiredParams []string `` /* 132-byte string literal not displayed */
Usage string `json:"usage,omitempty" jsonschema:"Short disambiguation note for commonly confused actions."`
RelatedActions []string `json:"related_actions,omitempty" jsonschema:"Curated nearby action IDs for workflows where ordering matters."`
ParamGuidance map[string]toolutil.ParameterGuidance `json:"parameter_guidance,omitempty" jsonschema:"Parameter binding guidance for commonly confused params."`
Score int `json:"score" jsonschema:"Lexical relevance score for the query."`
Explanation *ScoringExplanation `json:"explanation,omitempty" jsonschema:"Optional scoring explanation returned only when explain is true."`
LowConfidence bool `json:"low_confidence,omitempty" jsonschema:"Whether the top result is below the high-confidence score or margin threshold."`
AmbiguousWith []string `` /* 127-byte string literal not displayed */
InputSchema map[string]any `json:"input_schema" jsonschema:"Exact JSON Schema for action-specific params."`
OutputSchema map[string]any `json:"output_schema,omitempty" jsonschema:"Best-effort JSON Schema for the action result."`
Example ActionExample `json:"example" jsonschema:"Example gitlab_execute_action call."`
}
FindResult is a matching catalog action with schema details and an execute example.
type MatchReason ¶
type MatchReason struct {
Field string `json:"field" jsonschema:"Action metadata field that matched the query term."`
QueryTerm string `json:"query_term" jsonschema:"Original normalized query term."`
MatchedValue string `json:"matched_value" jsonschema:"Action metadata value that matched."`
Alternative string `` /* 131-byte string literal not displayed */
Score int `json:"score" jsonschema:"Score contributed by this match before final match-ratio scaling."`
Fuzzy bool `json:"fuzzy,omitempty" jsonschema:"Whether this match came from typo-tolerant fuzzy recovery."`
Distance int `json:"distance,omitempty" jsonschema:"Levenshtein edit distance for fuzzy matches."`
}
MatchReason explains one query-term match that contributed to an action score.
type Registry ¶
type Registry struct {
SearchIndex searchIndex
// contains filtered or unexported fields
}
Registry holds a deterministic action index and dispatch handlers.
func NewRegistry ¶
NewRegistry builds a deterministic action registry from visible meta routes.
func NewRegistryFromCatalog ¶
func NewRegistryFromCatalog(catalog *actioncatalog.Catalog) *Registry
NewRegistryFromCatalog builds a deterministic dynamic action index from the canonical action catalog.
func (*Registry) AllActionsReadOnly ¶
AllActionsReadOnly reports whether every action this registry can dispatch is read-only. An empty registry counts as read-only: it can mutate nothing.
func (*Registry) Describe ¶
func (r *Registry) Describe(_ context.Context, _ *mcp.CallToolRequest, input DescribeInput) (*mcp.CallToolResult, DescribeOutput, error)
Describe returns schemas and execution metadata for GitLab catalog actions.
func (*Registry) Execute ¶
func (r *Registry) Execute(ctx context.Context, req *mcp.CallToolRequest, input ExecuteInput) (*mcp.CallToolResult, any, error)
Execute dispatches one catalog action through the existing meta-tool handler.
func (*Registry) Find ¶
func (r *Registry) Find(ctx context.Context, req *mcp.CallToolRequest, input FindInput) (*mcp.CallToolResult, FindOutput, error)
Find searches GitLab catalog actions and includes exact schemas for matches.
func (*Registry) Metrics ¶
func (r *Registry) Metrics() RegistryMetrics
Metrics returns static registry and search-index metrics.
func (*Registry) Search ¶
func (r *Registry) Search(ctx context.Context, _ *mcp.CallToolRequest, input SearchInput) (*mcp.CallToolResult, SearchOutput, error)
Search finds GitLab catalog actions by lexical matching over action metadata.
type RegistryMetrics ¶
type RegistryMetrics struct {
ActionCount int
IndexTokenCount int
IndexPostingCount int
AliasCount int
SearchableAliasCount int
UnsearchableAliasCount int
AmbiguousAliasCount int
}
RegistryMetrics summarizes static counts from the dynamic registry and search index, including action totals, token/posting totals, and alias statistics.
type RegistryOption ¶
type RegistryOption func(*Registry)
RegistryOption configures the dynamic registry at registration time.
func WithWithheldActions ¶
func WithWithheldActions(byTokenScope, byOperator []string) RegistryOption
WithWithheldActions tells the registry which action keys were filtered out of the catalog before it was handed over, split by cause: byTokenScope for actions the credential itself cannot reach, byOperator for actions a deployment-wide setting removed. A key is a canonical action ID or any alias that used to resolve to one.
Without this the dynamic surface answers a withheld action with "unknown action" plus near-miss suggestions, which reads as "this server cannot do that" — so a model concludes the capability is absent instead of reporting that the credential needs widening.
type ScoringExplanation ¶
type ScoringExplanation struct {
TotalScore int `json:"total_score" jsonschema:"Final score returned for the action after match-ratio scaling."`
MatchedTerms int `json:"matched_terms" jsonschema:"Number of normalized query terms that matched this action."`
RequiredTerms int `json:"required_terms" jsonschema:"Minimum number of normalized query terms required for this action to match."`
LowConfidence bool `json:"low_confidence,omitempty" jsonschema:"Whether the result is considered low confidence."`
MarginToNext int `json:"margin_to_next,omitempty" jsonschema:"Score difference to the next ranked result when known."`
Reasons []MatchReason `json:"reasons,omitempty" jsonschema:"Deterministic match reasons that contributed to the score."`
}
ScoringExplanation describes how a dynamic search result received its score.
type SearchInput ¶
type SearchInput struct {
Query string `` /* 137-byte string literal not displayed */
Limit int `json:"limit,omitempty" jsonschema:"Maximum number of matches to return. Defaults to 20 and is capped at 50."`
Explain bool `` /* 157-byte string literal not displayed */
}
SearchInput is the input for catalog search.
type SearchOutput ¶
type SearchOutput struct {
Query string `json:"query" jsonschema:"Original search query."`
Count int `json:"count" jsonschema:"Number of returned matches."`
Results []SearchResult `json:"results" jsonschema:"Matching GitLab catalog actions."`
Suggestions []string `json:"suggestions,omitempty" jsonschema:"Small set of nearby tokens or common domains to try when no results matched."`
NextStep string `json:"next_step,omitempty" jsonschema:"Compact instruction for the next action-selection step after search."`
}
SearchOutput is the structured output for catalog search.
type SearchResult ¶
type SearchResult struct {
ID string `json:"id" jsonschema:"Canonical action ID to pass to gitlab_execute_action."`
Tool string `json:"tool" jsonschema:"Backing meta-tool name."`
Domain string `json:"domain" jsonschema:"Canonical action domain."`
Action string `json:"action" jsonschema:"Action name inside the catalog group."`
SchemaURI string `json:"schema_uri" jsonschema:"MCP resource URI for the action parameter schema."`
Destructive bool `json:"destructive" jsonschema:"Whether this action is marked destructive and requires explicit confirmation."`
RequiredParams []string `` /* 132-byte string literal not displayed */
Usage string `json:"usage,omitempty" jsonschema:"Short disambiguation note for commonly confused actions."`
WhyThisAction string `json:"why_this_action,omitempty" jsonschema:"Compact reason included only for close or ambiguous alternatives."`
RelatedActions []string `json:"related_actions,omitempty" jsonschema:"Curated nearby action IDs for workflows where ordering matters."`
Score int `json:"score" jsonschema:"Lexical relevance score for the query."`
Explanation *ScoringExplanation `json:"explanation,omitempty" jsonschema:"Optional scoring explanation returned only when explain is true."`
LowConfidence bool `json:"low_confidence,omitempty" jsonschema:"Whether the top result is below the high-confidence score or margin threshold."`
AmbiguousWith []string `` /* 127-byte string literal not displayed */
}
SearchResult is one matching GitLab catalog action.
type SearchRuntimeMetrics ¶
type SearchRuntimeMetrics struct {
Searches uint64
ZeroResultSearches uint64
FuzzyFallbackSearches uint64
AmbiguousAliasQueries uint64
LowConfidenceSearches uint64
DestructiveFuzzySuppressions uint64
}
SearchRuntimeMetrics summarizes process-local dynamic search quality events.
func SearchRuntimeMetricsSnapshot ¶
func SearchRuntimeMetricsSnapshot() SearchRuntimeMetrics
SearchRuntimeMetricsSnapshot returns process-local search quality counters.
type StandaloneOptions ¶
StandaloneOptions controls which standalone tools are added to the canonical dynamic action catalog.