toolutil

package
v2.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 19, 2026 License: MIT Imports: 37 Imported by: 0

Documentation

Overview

Package toolutil provides shared utilities for MCP tool handler sub-packages. It contains error handling, pagination, logging, text processing, Markdown formatting helpers, and meta-tool infrastructure used across all domain sub-packages under internal/tools/.

The package centralizes cross-cutting behavior for:

  • MCP response construction, annotations, icons, embedded resources, and Markdown formatter registration.
  • GitLab API support types for pagination, GraphQL cursors, access levels, diff positions, file validation, and flexible string-or-integer IDs.
  • Operational helpers for structured errors, not-found results, logging, rate limiting, polling, destructive-action confirmation, and identity resolution.
  • Schema middleware that hardens generated tool schemas and enriches common pagination parameters with numeric bounds.

This package must never import from domain sub-packages to prevent circular dependencies. The dependency direction is: domain sub-packages -> toolutil.

Common Entry Points

Handlers usually use WrapErr, WrapErrWithMessage, or WrapErrWithHint for errors; PaginationInput and PaginationOutput for paginated endpoints; StringOrInt for GitLab IDs that may be numeric or path-based; and RegisterMarkdown or RegisterMarkdownResult to publish type-specific Markdown renderers.

Destructive tools use ConfirmAction when they need an MCP elicitation step, and list/detail outputs commonly embed HintableOutput so meta-tools can add next-step guidance.

Markdown and Structured Output

Domain packages register Markdown renderers with RegisterMarkdown and RegisterMarkdownResult. The registry lets handlers return typed structured output for MCP clients while still producing compact human-readable Markdown. Shared helpers such as MarkdownTableHeader, MarkdownTableSeparator, and MarkdownTableRow keep table formatting consistent across domains.

Dependency Direction

The package dependency shape is intentionally one-way:

internal/tools/{domain}
    |
    v
toolutil
    |
    v
MCP SDK and GitLab client primitives

Index

Constants

View Source
const (
	ActionSpecContentList      = "list"
	ActionSpecContentDetail    = "detail"
	ActionSpecContentMutate    = "mutate"
	ActionSpecContentAssistant = "assistant"
	ActionSpecContentImage     = "image"

	ActionSpecNotFoundNone      = "none"
	ActionSpecNotFoundResult    = "not_found_result"
	ActionSpecNotFoundPropagate = "propagate_error"

	ActionSpecEmbeddedNone     = "none"
	ActionSpecEmbeddedOptional = "optional"
	ActionSpecEmbeddedAlways   = "always"

	ActionSpecRichStandard     = "standard"
	ActionSpecRichImage        = "image"
	ActionSpecRichResourceLink = "resource_link"
	ActionSpecRichMixed        = "mixed"
)
View Source
const (
	DefaultMaxFileSize = config.DefaultMaxFileSize
	// ImportArchiveAllowlistEnv names extra directories allowed for local
	// GitLab project/group import archives, separated by the OS path-list separator.
	ImportArchiveAllowlistEnv = "GITLAB_MCP_ALLOWED_IMPORT_DIRS"
)

DefaultMaxFileSize re-exports the upload size limit from config as the single source of truth for tool utilities.

View Source
const (
	GraphQLDefaultFirst = 20
	GraphQLMaxFirst     = 100
)

GraphQL pagination defaults.

View Source
const (
	DateFormatISO  = "2006-01-02"
	DateTimeFormat = "2006-01-02T15:04:05Z"
)

Common date format constants used across tool sub-packages.

View Source
const (
	TblRowID          = "| ID | %d |\n"
	TblRowStatus      = "| Status | %s |\n"
	TblRowCreatedAt   = "| Created At | %s |\n"
	TblRowUpdatedAt   = "| Updated At | %s |\n"
	TblRowHasFailures = "| Has Failures | %v |\n"
)

Table row format constants for common detail-table fields. Each pairs with TblFieldValue and is shared across sub-packages to avoid duplicated literals.

View Source
const (
	FmtMdH1 = "# %s\n\n"
	FmtMdH2 = "## %s\n\n"
	FmtMdH3 = "### %s\n\n"
	FmtMdH4 = "#### %s\n\n"
	FmtMdH5 = "##### %s\n\n"
	FmtMdH6 = "###### %s\n\n"
)

Headings format string with trailing blank line.

View Source
const (
	FmtMdID          = "- **ID**: %d\n"
	FmtMdName        = "- **Name**: %s\n"
	FmtMdTitle       = "- **Title**: %s\n"
	FmtMdState       = "- **State**: %s\n"
	FmtMdStatus      = "- **Status**: %s\n"
	FmtMdDescription = "- **Description**: %s\n"
	FmtMdPath        = "- **Path**: %s\n"
	FmtMdVisibility  = "- **Visibility**: %s\n"
	FmtMdEmail       = "- **Email**: %s\n"
	FmtMdUsername    = "- **Username**: %s\n"
	FmtMdTarget      = "- **Target**: %s\n"
	FmtMdCreated     = "- **Created**: %s\n"
	FmtMdUpdated     = "- **Updated**: %s\n"
	FmtMdURL         = "- **URL**: [%[1]s](%[1]s)\n"
	FmtMdURLNewline  = "\n- **URL**: [%[1]s](%[1]s)\n"
	FmtMdAuthorAt    = "- **Author**: @%s\n"
	FmtMdAuthor      = "- **Author**: %s\n"
	FmtMdSectionText = "\n%s\n"
	FmtMdH2Count     = "## %s (%d)\n\n"
	TblSep1Col       = "| --- |\n"
	TblSep2Col       = "| --- | --- |\n"
	TblSep3Col       = "| --- | --- | --- |\n"
	TblSep4Col       = "| --- | --- | --- | --- |\n"
	TblSep5Col       = "| --- | --- | --- | --- | --- |\n"
	TblSep6Col       = "| --- | --- | --- | --- | --- | --- |\n"
	TblSep7Col       = "| --- | --- | --- | --- | --- | --- | --- |\n"
	TblSep8Col       = "| --- | --- | --- | --- | --- | --- | --- | --- |\n"
	TblSep9Col       = "| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n"
	TblSep10Col      = "| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n"
	FmtRow1Str       = "| %s |\n"
	FmtRow2Str       = "| %s | %s |\n"
	FmtRow3Str       = "| %s | %s | %s |\n"
	FmtRow4Str       = "| %s | %s | %s | %s |\n"
	FmtRow5Str       = "| %s | %s | %s | %s | %s |\n"
	FmtRow6Str       = "| %s | %s | %s | %s | %s | %s |\n"
	FmtRow7Str       = "| %s | %s | %s | %s | %s | %s | %s |\n"
	FmtRow8Str       = "| %s | %s | %s | %s | %s | %s | %s | %s |\n"
	FmtRow9Str       = "| %s | %s | %s | %s | %s | %s | %s | %s | %s |\n"
	FmtRow10Str      = "| %s | %s | %s | %s | %s | %s | %s | %s | %s | %s |\n"
)

Markdown format constants for repeated table separators and field patterns.

View Source
const (
	EmojiDraft        = "\U0001F4DD"   // 📝
	EmojiWarning      = "\u26A0\uFE0F" // ⚠️
	EmojiConfidential = "\U0001F512"   // 🔒
	EmojiArchived     = "\U0001F4E6"   // 📦
	EmojiStar         = "\u2B50"       // ⭐
	EmojiSuccess      = "\u2705"       // ✅
	EmojiCross        = "\u274C"       // ❌
	EmojiRefresh      = "\U0001F504"   // 🔄
	EmojiFile         = "\U0001F4C4"   // 📄
	EmojiFolder       = "\U0001F4C1"   // 📁
	EmojiCalendar     = "\U0001F4C5"   // 📅
	EmojiUpArrow      = "\u2B06\uFE0F" // ⬆️
	EmojiDownArrow    = "\u2B07\uFE0F" // ⬇️
	EmojiInfo         = "\u2139\uFE0F" // ℹ️
	EmojiQuestion     = "\u2753"       // ❓
	EmojiLink         = "\U0001F517"   // 🔗
	EmojiUser         = "\U0001F464"   // 👤
	EmojiGroup        = "\U0001F465"   // 👥
	EmojiPipeline     = "\U0001F6A7"   // 🚧
	EmojiMergeRequest = "\U0001F5C3"   // 🗃️
	EmojiIssue        = "\U0001F4A1"   // 💡
	EmojiRed          = "\U0001F534"   // 🔴
	EmojiYellow       = "\U0001F7E1"   // 🟡
	EmojiGreen        = "\U0001F7E2"   // 🟢
	EmojiProhibited   = "\U0001F6AB"   // 🚫
	EmojiWhiteCircle  = "\u26AA"       // ⚪
	EmojiParty        = "\U0001F389"   // 🎉
	EmojiPurple       = "\U0001F7E3"   // 🟣
	EmojiBlue         = "\U0001F535"   // 🔵
	EmojiStop         = "\u26D4"       // ⛔
	EmojiSkip         = "\u23ED\uFE0F" // ⏭️
	EmojiNew          = "\U0001F195"   // 🆕
	EmojiHand         = "\u270B"       // ✋
)

Contextual emoji constants for consistent visual indicators across formatters.

View Source
const (
	MetaParamSchemaOpaque  = "opaque"
	MetaParamSchemaCompact = "compact"
	MetaParamSchemaFull    = "full"
)

Meta-tool param schema mode constants. Mirrors the values accepted by the META_PARAM_SCHEMA env var and --meta-param-schema CLI flag in package config. Duplicated here to avoid an import cycle (config → toolutil → mcp).

View Source
const (
	PollMinInterval     = 5
	PollMaxInterval     = 60
	PollDefaultInterval = 10
	PollMinTimeout      = 1
	PollMaxTimeout      = 3600
	PollDefaultTimeout  = 300
)

Polling bounds and defaults (all values in seconds) for tools that wait on a GitLab resource to reach a terminal state (pipelines, jobs, deployments).

View Source
const ErrMsgContextCanceled = "context canceled"

ErrMsgContextCanceled is the operation label passed to WrapErr when a tool handler detects context cancellation before calling the GitLab API.

View Source
const HintPreserveLinks = "" /* 127-byte string literal not displayed */

HintPreserveLinks reminds the LLM to keep the clickable [text](url) markdown links when presenting list results to the user.

View Source
const MetaSchemaIndexURI = "gitlab://schema/meta/"

MetaSchemaIndexURI is the static URI returning the full meta-tool action catalog.

View Source
const MetaSchemaTemplateURI = "gitlab://schema/meta/{tool}/{action}"

MetaSchemaTemplateURI is the URI template for per-action params schemas.

View Source
const RedactedSecretValue = "REDACTED"

RedactedSecretValue is the standard placeholder for sensitive values that must not be exposed through structured output or Markdown renderers.

View Source
const StepFormattingResponse = "Formatting response..."

StepFormattingResponse is a standard progress step label for response formatting.

View Source
const TblFieldValue = "| Field | Value |\n| --- | --- |\n"

TblFieldValue is the standard "| Field | Value |" detail table header+separator.

Variables

View Source
var (
	ReadAnnotations = &mcp.ToolAnnotations{
		ReadOnlyHint:    true,
		DestructiveHint: new(false),
		IdempotentHint:  true,
		OpenWorldHint:   new(true),
	}
	CreateAnnotations = &mcp.ToolAnnotations{
		DestructiveHint: new(false),
		OpenWorldHint:   new(true),
	}
	UpdateAnnotations = &mcp.ToolAnnotations{
		DestructiveHint: new(false),
		IdempotentHint:  true,
		OpenWorldHint:   new(true),
	}
	DeleteAnnotations = &mcp.ToolAnnotations{
		DestructiveHint: new(true),
		IdempotentHint:  true,
		OpenWorldHint:   new(true),
	}
	// NonDestructiveMetaAnnotations are for meta-tools that include
	// create/update operations but no delete actions.
	NonDestructiveMetaAnnotations = &mcp.ToolAnnotations{
		DestructiveHint: new(false),
		OpenWorldHint:   new(true),
	}
	// MetaAnnotations are annotations for meta-tools that combine read/write/delete.
	// Since a single meta-tool may include destructive actions, annotations reflect
	// the most cautious combination.
	MetaAnnotations = &mcp.ToolAnnotations{
		DestructiveHint: new(true),
		OpenWorldHint:   new(true),
	}
	// ReadOnlyMetaAnnotations are for meta-tools with only list/get/search actions.
	ReadOnlyMetaAnnotations = &mcp.ToolAnnotations{
		ReadOnlyHint:    true,
		DestructiveHint: new(false),
		IdempotentHint:  true,
		OpenWorldHint:   new(true),
	}
)

Tool annotation presets for different operation categories. Each preset configures MCP hints that help LLMs understand whether a tool is read-only, destructive, or idempotent.

View Source
var (
	// ContentBoth marks content for both user display and LLM processing (default).
	ContentBoth = &mcp.Annotations{
		Audience: []mcp.Role{"user", "assistant"},
		Priority: 0.5,
	}
	// ContentUser marks content primarily for user display (uploads, visualizations).
	ContentUser = &mcp.Annotations{
		Audience: []mcp.Role{"user"},
		Priority: 0.8,
	}
	// ContentAssistant marks content primarily for LLM processing (search, raw data).
	ContentAssistant = &mcp.Annotations{
		Audience: []mcp.Role{"assistant"},
		Priority: 0.7,
	}
)

Content annotation presets for TextContent responses. These guide MCP clients on who the content is intended for and its importance.

View Source
var (
	// ContentList marks list/search results for LLM processing with lower priority.
	ContentList = &mcp.Annotations{
		Audience: []mcp.Role{"assistant"},
		Priority: 0.4,
	}
	// ContentDetail marks single-entity details for LLM processing with medium priority.
	ContentDetail = &mcp.Annotations{
		Audience: []mcp.Role{"assistant"},
		Priority: 0.6,
	}
	// ContentMutate marks create/update/delete results for LLM processing with high priority.
	ContentMutate = &mcp.Annotations{
		Audience: []mcp.Role{"assistant"},
		Priority: 0.8,
	}
)

Operation-based content annotation presets. All use audience ["assistant"] so the Markdown content is available to the LLM for reasoning, while StructuredContent (JSON) serves programmatic clients. This avoids redundant display when clients show both Content and StructuredContent.

View Source
var (
	IconBranch        = icon(svgBranch)
	IconCommit        = icon(svgCommit)
	IconIssue         = icon(svgIssue)
	IconMR            = icon(svgMR)
	IconPipeline      = icon(svgPipeline)
	IconJob           = icon(svgJob)
	IconRelease       = icon(svgRelease)
	IconTag           = icon(svgTag)
	IconProject       = icon(svgProject)
	IconGroup         = icon(svgGroup)
	IconUser          = icon(svgUser)
	IconWiki          = icon(svgWiki)
	IconFile          = icon(svgFile)
	IconPackage       = icon(svgPackage)
	IconSearch        = icon(svgSearch)
	IconLabel         = icon(svgLabel)
	IconMilestone     = icon(svgMilestone)
	IconEnvironment   = icon(svgEnvironment)
	IconDeploy        = icon(svgDeploy)
	IconSchedule      = icon(svgSchedule)
	IconVariable      = icon(svgVariable)
	IconRunner        = icon(svgRunner)
	IconTodo          = icon(svgTodo)
	IconHealth        = icon(svgHealth)
	IconUpload        = icon(svgUpload)
	IconBoard         = icon(svgBoard)
	IconSnippet       = icon(svgSnippet)
	IconToken         = icon(svgToken)
	IconIntegration   = icon(svgIntegration)
	IconNotify        = icon(svgNotify)
	IconServer        = icon(svgServer)
	IconSecurity      = icon(svgSecurity)
	IconConfig        = icon(svgConfig)
	IconAnalytics     = icon(svgAnalytics)
	IconKey           = icon(svgKey)
	IconLink          = icon(svgLink)
	IconDiscussion    = icon(svgDiscussion)
	IconEvent         = icon(svgEvent)
	IconContainer     = icon(svgContainer)
	IconImport        = icon(svgImport)
	IconAlert         = icon(svgAlert)
	IconTemplate      = icon(svgTemplate)
	IconInfra         = icon(svgInfra)
	IconEpic          = icon(svgEpic)
	IconShield        = icon(svgShield)
	IconAudit         = icon(svgAudit)
	IconQueue         = icon(svgQueue)
	IconBot           = icon(svgBot)
	IconVulnerability = icon(svgVulnerability)
	IconCompliance    = icon(svgCompliance)
)

Domain icons — each returns a one-element []mcp.Icon ready for the Icons field.

View Source
var ErrInvalidRateLimit = errors.New("invalid rate limit configuration")

ErrInvalidRateLimit is returned by ValidateRateLimit when the parameters are inconsistent (e.g. burst < 1 with rps > 0).

Functions

func AccessLevelDescription

func AccessLevelDescription(level gl.AccessLevelValue) string

AccessLevelDescription maps GitLab access level integers to human-readable labels.

func ActionDispatchOutputSchema

func ActionDispatchOutputSchema() map[string]any

ActionDispatchOutputSchema returns a permissive JSON Schema for tools whose exact structured result depends on the selected catalog action.

func AddMetaTool

func AddMetaTool(server *mcp.Server, name, desc string, routes ActionMap, icons []mcp.Icon, formatResult FormatResultFunc)

AddMetaTool registers an action-dispatched meta-tool with route-derived annotations. Use it for meta-tools that may include mutating or destructive actions; if any route is destructive, the tool receives DestructiveHint=true.

func AddReadOnlyMetaTool

func AddReadOnlyMetaTool(server *mcp.Server, name, desc string, routes ActionMap, icons []mcp.Icon, formatResult FormatResultFunc)

AddReadOnlyMetaTool registers an action-dispatched meta-tool whose actions are all read-only list/get/search-style operations.

func AdjustPagination

func AdjustPagination(p *PaginationOutput, itemCount int)

AdjustPagination corrects pagination metadata when the GitLab API does not return X-Total and X-Total-Pages headers (e.g., the Search API). It infers TotalItems and TotalPages from the actual item count received and the presence of a NextPage indicator.

func AppendResourceLink(_ *mcp.CallToolResult, _, _, _ string)

AppendResourceLink preserves the legacy resource-link hook as a no-op.

Deprecated: AppendResourceLink is intentionally a no-op. It previously emitted mcp.ResourceLink content blocks with external HTTP URLs (GitLab WebURL), but ResourceLink is reserved for MCP-registered resources (gitlab:// URIs). Clients that received an https:// ResourceLink attempted to resolve it via resources/read, triggering JSON-RPC -32002 "Resource not found" errors. External web links are already included in the Markdown text output. Callers will be removed in a future major version.

func AttachRateLimit

func AttachRateLimit(server *mcp.Server, limiter *RateLimiter)

AttachRateLimit registers a receiving middleware that rejects `tools/call` requests when the bucket is empty. Rejection is reported as an MCP tool error result (IsError: true) rather than a JSON-RPC error so the LLM receives a structured, retryable diagnostic and the surrounding agent loop can choose to back off and retry.

All other methods (initialize, tools/list, resources/*, prompts/*) bypass the limiter — only tool execution is gated. If limiter is nil, this function is a no-op.

func BoolEmoji

func BoolEmoji(v bool) string

BoolEmoji returns ✅ for true and ❌ for false.

func BoolPtr

func BoolPtr(b bool) *bool

BoolPtr returns a pointer to the given bool value.

func BuildMetaToolSchema

func BuildMetaToolSchema(routes ActionMap, mode string) map[string]any

BuildMetaToolSchema returns the input schema for a meta-tool given the chosen mode. Unknown modes silently fall back to MetaParamSchemaOpaque so that callers cannot break the tools/list payload by passing a typo.

  • opaque: legacy {action, params:any} envelope (default).
  • full: discriminated oneOf with full per-action params schemas.
  • compact: discriminated oneOf with descriptions and $defs stripped.

func BuildTargetURL

func BuildTargetURL(projectWebURL, targetType string, targetIID int64) string

BuildTargetURL constructs a GitLab web URL for a target resource. Returns "" when the project web URL is empty, the IID is zero, or the target type has no known URL segment.

Supported target types: Issue, MergeRequest, Milestone.

func CancelledResult

func CancelledResult(message string) *mcp.CallToolResult

CancelledResult returns a non-error tool result indicating the user canceled.

func CanonicalImportArchivePath

func CanonicalImportArchivePath(path string) (string, error)

CanonicalImportArchivePath validates a local GitLab export archive path and returns the canonical path resolved through symlinks. Archives must be regular .tar.gz files under the current working directory, the OS temporary directory, or a directory listed in GITLAB_MCP_ALLOWED_IMPORT_DIRS.

func ClampPollInterval

func ClampPollInterval(v int) int

ClampPollInterval constrains a polling interval to [PollMinInterval, PollMaxInterval], returning PollDefaultInterval when the value is below the minimum.

func ClampPollTimeout

func ClampPollTimeout(v int) int

ClampPollTimeout constrains a polling timeout to [PollMinTimeout, PollMaxTimeout], returning PollDefaultTimeout when the value is below the minimum.

func ClassifyError

func ClassifyError(err error) string

ClassifyError inspects the error chain and returns a short, human-friendly diagnostic message explaining what went wrong at a high level.

func ClassifyHTTPStatus

func ClassifyHTTPStatus(code int) string

ClassifyHTTPStatus returns a semantic description for common HTTP status codes.

func CloneMetaSchemaRoutes

func CloneMetaSchemaRoutes(routes map[string]ActionMap) map[string]ActionMap

CloneMetaSchemaRoutes creates a defensive snapshot of route maps so consumers do not observe later registration, filtering, or schema map changes.

func ComputeSHA256

func ComputeSHA256(path string) (string, error)

ComputeSHA256 computes the SHA-256 checksum of a file at the given path and returns the lowercase hex-encoded hash string.

func ComputeSHA256Reader

func ComputeSHA256Reader(r io.Reader) (string, error)

ComputeSHA256Reader computes the SHA-256 checksum from an arbitrary io.Reader and returns the lowercase hex-encoded hash string.

func ConfirmAction

func ConfirmAction(ctx context.Context, req *mcp.CallToolRequest, message string) *mcp.CallToolResult

ConfirmAction uses MCP elicitation to ask the user for confirmation before a destructive action. Returns nil if the user confirmed or elicitation is unsupported (fallback: action proceeds). Returns a non-error tool result if the user declined or canceled.

func ConfirmDestructiveAction

func ConfirmDestructiveAction(ctx context.Context, req *mcp.CallToolRequest, params map[string]any, message string) *mcp.CallToolResult

ConfirmDestructiveAction checks whether a destructive action should proceed. The confirmation flow is:

  1. YOLO_MODE / AUTOPILOT env var → skip confirmation entirely
  2. Explicit "confirm": true in params → skip confirmation
  3. MCP elicitation supported → ask user interactively
  4. Elicitation unsupported and no confirm param → return error prompting the caller to re-send with confirm: true

Returns nil if the action should proceed. Returns a non-nil *mcp.CallToolResult if the action was canceled or requires explicit confirmation.

func ContainsAny

func ContainsAny(err error, substrs ...string) bool

ContainsAny returns true if err.Error() contains any of the substrings.

func ContextWithRequest

func ContextWithRequest(ctx context.Context, req *mcp.CallToolRequest) context.Context

ContextWithRequest returns a derived context carrying the MCP request.

func DeriveAnnotations

func DeriveAnnotations(routes ActionMap) *mcp.ToolAnnotations

DeriveAnnotations computes tool-level MCP annotations from the route map. If any route is destructive, returns a copy of MetaAnnotations (DestructiveHint: true). If all routes are non-destructive, returns a copy of NonDestructiveMetaAnnotations. Each call returns a fresh copy to avoid aliasing the shared singletons.

func DeriveAnnotationsWithTitle

func DeriveAnnotationsWithTitle(name string, routes ActionMap) *mcp.ToolAnnotations

DeriveAnnotationsWithTitle returns route-derived annotations with Title set from the tool name.

func DetectRichContent

func DetectRichContent(body string) string

DetectRichContent scans a GFM body for non-portable features that may not render correctly outside GitLab (mermaid diagrams, math blocks, raw HTML). Returns a comma-separated list of detected features or an empty string.

func EmbedResource

func EmbedResource(result *mcp.CallToolResult, uri, mimeType, text string)

EmbedResource appends an EmbeddedResource content block to result that references the canonical MCP resource URI for the entity returned by the tool. mimeType should typically be "application/json" with text containing a compact JSON serialization of the entity (or empty if the resource is addressable but the body is large).

When result is nil, the URI is empty, or the global toggle is disabled, EmbedResource is a no-op. No further URI validation is performed; callers are responsible for passing well-formed URIs that match an MCP resource template registered with the server.

func EmbedResourceJSON

func EmbedResourceJSON(result *mcp.CallToolResult, uri string, value any)

EmbedResourceJSON marshals value as JSON and embeds the result with MIME type application/json. Marshaling errors are dropped silently — the tool result is still returned with text and StructuredContent so the LLM has a usable response.

func EmbeddedResourcesEnabled

func EmbeddedResourcesEnabled() bool

EmbeddedResourcesEnabled reports the current state of the global toggle. Exposed for tests; production code should call EmbedResource directly.

func EnableEmbeddedResources

func EnableEmbeddedResources(enabled bool)

EnableEmbeddedResources toggles the global EmbedResource behavior. When false, EmbedResource is a no-op, preserving the legacy two-block (text + structuredContent) tool result shape.

func EnrichPaginationConstraints

func EnrichPaginationConstraints(server *mcp.Server)

EnrichPaginationConstraints registers a receiving middleware that walks every tools/list response and injects JSON Schema numeric constraints on the standard pagination property names so LLM clients see the bounds directly in tools/list rather than only through prose in the description.

The middleware operates per property name:

  • `page` gets `minimum: 1`
  • `per_page` gets `minimum: 1` and `maximum: 100`

Existing constraints are preserved: if a schema already declares `minimum` or `maximum` on these properties the middleware leaves them untouched so domain-specific overrides remain authoritative. Only nodes whose `type` is `integer` or `number` (or unset, defaulting to integer per the Go SDK's int-typed pagination input) are modified, so unrelated properties named `page` on a custom schema cannot be silently mutated.

The transformation runs after LockdownInputSchemas so it sees the same fully-populated schema set every list/tools response carries.

Concurrency. As with LockdownInputSchemas, the mutation is guarded by a `sync.Once` so concurrent `tools/list` calls cannot race on the shared *Tool.InputSchema maps.

func ErrFieldRequired

func ErrFieldRequired(field string) error

ErrFieldRequired returns a validation error indicating that a required field is missing or empty. It produces the message "<field> is required", which is the standard validation pattern used across all tool handlers.

func ErrInvalidEnum

func ErrInvalidEnum(field, value string, validValues []string) error

ErrInvalidEnum returns a validation error indicating that a field value is not one of the allowed options. The error message lists the valid values to guide LLMs toward correct parameter usage.

func ErrRequiredInt64

func ErrRequiredInt64(operation, field string) error

ErrRequiredInt64 returns a formatted error when a required int64 field is missing or has its zero value. This catches silent deserialization failures in meta-tool dispatch, where a misnamed JSON parameter (e.g. "mr_iid" instead of "merge_request_iid") is silently ignored and the field defaults to 0.

func ErrRequiredString

func ErrRequiredString(operation, field string) error

ErrRequiredString returns a formatted error when a required string field is missing or empty. Like ErrRequiredInt64, this guides LLMs to use the exact parameter name when silent deserialization failures occur.

func ErrorResult

func ErrorResult(message string) *mcp.CallToolResult

ErrorResult builds a standard error mcp.CallToolResult with IsError set. It returns the error message as Markdown content for display.

func ErrorResultMarkdown

func ErrorResultMarkdown(domain, action string, err error) *mcp.CallToolResult

ErrorResultMarkdown creates an MCP tool error result with Markdown formatting. The result has IsError = true for MCP clients that distinguish error results.

func EscapeMdHeading

func EscapeMdHeading(s string) string

EscapeMdHeading sanitizes a user-controlled string that will be interpolated into a Markdown heading (e.g. `## Project: {name}`). It strips leading '#' characters that could promote/demote the heading level and collapses newlines into spaces so the heading stays on one line.

func EscapeMdTableCell

func EscapeMdTableCell(s string) string

EscapeMdTableCell escapes characters in s that would break a Markdown table row. Pipes are replaced with the HTML entity &#124; and newlines/carriage-returns are replaced with a space so the cell stays on a single row.

func ExtractGitLabMessage

func ExtractGitLabMessage(err error) string

ExtractGitLabMessage extracts the specific error message from a GitLab ErrorResponse in the error chain. Returns empty string if not found or if the message only repeats the HTTP status text (e.g., "405 Method Not Allowed"). The extracted message is truncated to 300 characters to prevent overly verbose error output from user-generated content.

func ExtractHints

func ExtractHints(md string) []string

ExtractHints parses the "💡 Next steps" section from a Markdown tool response and returns the individual hint strings. Returns nil when the section is absent.

func FormatCICDVariableCollectionMarkdown

func FormatCICDVariableCollectionMarkdown[T any](variables []T, pagination PaginationOutput, convert func(T) CICDVariableMarkdown, title, emptyMessage string, includeEnvironmentScope bool, hints ...string) string

FormatCICDVariableCollectionMarkdown maps package-specific CI/CD variable outputs and renders them as a shared Markdown list.

func FormatCICDVariableDetailMarkdown

func FormatCICDVariableDetailMarkdown(v CICDVariableMarkdown, title string, includeEnvironmentScope bool) string

FormatCICDVariableDetailMarkdown renders a CI/CD variable with standard update/delete next-step hints shared by project and group variables.

func FormatCICDVariableListMarkdown

func FormatCICDVariableListMarkdown(variables []CICDVariableMarkdown, pagination PaginationOutput, opts CICDVariableListMarkdownOptions) string

FormatCICDVariableListMarkdown renders CI/CD variables as a Markdown table.

func FormatCICDVariableMarkdown

func FormatCICDVariableMarkdown(v CICDVariableMarkdown, opts CICDVariableMarkdownOptions) string

FormatCICDVariableMarkdown renders a single CI/CD variable as a Markdown detail table.

func FormatDiscussionListMarkdown

func FormatDiscussionListMarkdown(discussions []DiscussionMarkdown, opts DiscussionListMarkdownOptions) string

FormatDiscussionListMarkdown renders discussion threads as Markdown.

func FormatDiscussionMarkdown

func FormatDiscussionMarkdown(discussion DiscussionMarkdown, hints ...string) string

FormatDiscussionMarkdown renders a single discussion thread as Markdown.

func FormatDiscussionNoteMarkdown

func FormatDiscussionNoteMarkdown(note DiscussionNoteMarkdown, hints ...string) string

FormatDiscussionNoteMarkdown renders a single discussion note as Markdown.

func FormatGID

func FormatGID(typeName string, id int64) string

FormatGID builds a GitLab Global ID string from a type name and numeric ID.

FormatGID("Vulnerability", 42) → "gid://gitlab/Vulnerability/42"

func FormatGraphQLDiscussionListMarkdown

func FormatGraphQLDiscussionListMarkdown[T any](discussions []T, pagination GraphQLPaginationOutput, convert func(T) DiscussionMarkdown, title, emptyMessage string, hints ...string) string

FormatGraphQLDiscussionListMarkdown maps GraphQL discussion outputs and renders them with cursor pagination metadata.

func FormatGraphQLPagination

func FormatGraphQLPagination(p GraphQLPaginationOutput, shown int) string

FormatGraphQLPagination renders cursor-based pagination metadata as a Markdown summary line, suitable for appending to list tool responses.

func FormatLabelListMarkdown

func FormatLabelListMarkdown(labels []LabelMarkdown, pagination PaginationOutput, opts LabelMarkdownOptions) string

FormatLabelListMarkdown renders project or group labels as a paginated table.

func FormatLabelListMarkdownFunc

func FormatLabelListMarkdownFunc[T any](labels []T, pagination PaginationOutput, opts LabelMarkdownOptions, convert func(T) LabelMarkdown) string

FormatLabelListMarkdownFunc renders labels after mapping domain-specific outputs to the shared Markdown view.

func FormatLabelMarkdown

func FormatLabelMarkdown(label LabelMarkdown, opts LabelMarkdownOptions) string

FormatLabelMarkdown renders a project or group label as a Markdown summary.

func FormatNoteListMarkdown

func FormatNoteListMarkdown(notes []NoteMarkdown, pagination PaginationOutput, opts NoteListMarkdownOptions) string

FormatNoteListMarkdown renders a list of GitLab notes as Markdown.

func FormatNoteMarkdown

func FormatNoteMarkdown(note NoteMarkdown, opts NoteMarkdownOptions) string

FormatNoteMarkdown renders a single GitLab note as Markdown.

func FormatPagination

func FormatPagination(p PaginationOutput) string

FormatPagination renders pagination metadata as a compact Markdown line.

func FormatRESTDiscussionListMarkdown

func FormatRESTDiscussionListMarkdown[T any](discussions []T, pagination PaginationOutput, convert func(T) DiscussionMarkdown, title, emptyMessage string, hints ...string) string

FormatRESTDiscussionListMarkdown maps REST discussion outputs and renders them with offset pagination metadata.

func FormatStorageMoveCollectionMarkdown

func FormatStorageMoveCollectionMarkdown[T any](moves []T, pagination PaginationOutput, convert func(T) StorageMoveMarkdown, title, emptyMessage, entityColumn string) string

FormatStorageMoveCollectionMarkdown maps package-specific storage moves and renders them as a shared Markdown list.

func FormatStorageMoveDetailMarkdown

func FormatStorageMoveDetailMarkdown(move StorageMoveMarkdown, title string, hints ...string) string

FormatStorageMoveDetailMarkdown renders one repository storage move as a Markdown detail table.

func FormatStorageMoveListMarkdown

func FormatStorageMoveListMarkdown(moves []StorageMoveMarkdown, opts StorageMoveListMarkdownOptions) string

FormatStorageMoveListMarkdown renders repository storage moves as a Markdown table with the domain-specific entity column supplied by the caller.

func FormatTarget

func FormatTarget(targetType string, targetIID int64, targetTitle, targetURL string) string

FormatTarget builds a Markdown table cell for a typed target resource. When targetURL is non-empty, the result is a clickable link like [Issue #42](url). When empty, the label is returned as plain text. Returns "" if there is nothing to display.

func FormatTemplateCollectionMarkdown

func FormatTemplateCollectionMarkdown[T any](templates []T, pagination PaginationOutput, convert func(T) TemplateMarkdown, title, emptyMessage string, hints ...string) string

FormatTemplateCollectionMarkdown maps package-specific template outputs and renders them as a shared Markdown list.

func FormatTemplateContentMarkdown

func FormatTemplateContentMarkdown(title, name, language, content string, hints ...string) string

FormatTemplateContentMarkdown renders a GitLab template body inside a fenced code block.

func FormatTemplateListMarkdown

func FormatTemplateListMarkdown(templates []TemplateMarkdown, pagination PaginationOutput, opts TemplateListMarkdownOptions) string

FormatTemplateListMarkdown renders GitLab template list entries as Markdown.

func FormatTime

func FormatTime(s string) string

FormatTime converts an RFC3339 timestamp string to a human-readable format ("2 Jan 2006 15:04 UTC"). Returns the original string unchanged if parsing fails, so existing callers remain safe.

func GraphQLMutationError

func GraphQLMutationError(operation string, errors []string) error

GraphQLMutationError formats mutation payload errors, if any.

func GraphQLTopLevelError

func GraphQLTopLevelError(operation string, errors []GraphQLError) error

GraphQLTopLevelError formats top-level GraphQL response errors, if any.

func IdentityToContext

func IdentityToContext(ctx context.Context, id UserIdentity) context.Context

IdentityToContext stores a UserIdentity in the context. Used at startup in stdio mode to make the identity available to all tool handlers.

func ImageMIMEType

func ImageMIMEType(filename string) string

ImageMIMEType returns the MIME type for image file extensions. Returns an empty string for non-image files.

func IndividualToolFromActionSpec

func IndividualToolFromActionSpec(spec ActionSpec, opts IndividualToolProjectionOptions) (*mcp.Tool, error)

IndividualToolFromActionSpec projects canonical action metadata into an MCP tool definition for the individual-tool surface.

func IndividualToolFromSpecs

func IndividualToolFromSpecs(specs []ActionSpec, individualName string, opts IndividualToolProjectionOptions) (*mcp.Tool, error)

IndividualToolFromSpecs projects the spec that owns an individual tool name.

func IsBinaryFile

func IsBinaryFile(filename string) bool

IsBinaryFile returns true when the filename has a known binary extension that is not an image. Returns false for text and image files.

func IsHTTPStatus

func IsHTTPStatus(err error, code int) bool

IsHTTPStatus reports whether err wraps a GitLab ErrorResponse with the given HTTP status code. Useful for handling specific API responses like 404 (feature not available on CE) or 403 (insufficient permissions).

func IsImageFile

func IsImageFile(filename string) bool

IsImageFile returns true when the filename has an image extension. Comparison is case-insensitive. Returns false for empty strings.

func IsNotFound

func IsNotFound(err error) bool

IsNotFound reports whether err represents a 404 Not Found, either via a structured GitLab ErrorResponse status code or via a plain-text error message from client-go (which may contain "404 Not Found" as text).

func IsTerminalStatus

func IsTerminalStatus(status string) bool

IsTerminalStatus reports whether a CI/CD status represents a finished state.

func IsYOLOMode

func IsYOLOMode() bool

IsYOLOMode returns true when destructive action confirmation should be skipped entirely. Checks the YOLO_MODE and AUTOPILOT environment variables. Any truthy value (1, true, yes — case-insensitive) enables the mode.

func IssueStateEmoji

func IssueStateEmoji(state string) string

IssueStateEmoji returns the Markdown emoji for an issue state.

func ListHints

func ListHints(hints ...string) []string

ListHints prepends HintPreserveLinks to list-result next-step hints.

func LockdownInputSchemas

func LockdownInputSchemas(server *mcp.Server)

LockdownInputSchemas registers a receiving middleware that rewrites tools/list responses so every tool's inputSchema declares `additionalProperties: false` at the root and on any nested object schema reachable through "properties", "items", "anyOf", "oneOf", or "allOf". It also strips jsonschema tag metadata such as ",required" from property descriptions after the SDK generates schemas. Schemas converted from SDK types are stored back as map[string]any values, so callers inspecting tools after this middleware runs should not expect the original concrete schema type.

Background. The MCP specification (2025-11-25 §server/tools) requires inputSchema to be a valid JSON Schema object but does not mandate `additionalProperties`. JSON Schema 2020-12 default semantics treat an unspecified `additionalProperties` as `true`, which silently accepts unknown fields. When an LLM mistypes an argument name (e.g. "projetc_id" instead of "project_id"), the server forwards an empty value to the handler, which then fails with a confusing "missing parameter" error rather than the actionable "unknown property" diagnostic the LLM needs to self-correct.

Schemas that already declare `additionalProperties` (true or false) at a given level are left untouched, so meta-tool router branches that intentionally permit unknown fields for forward compatibility remain intact.

Concurrency. The MCP Go SDK does not expose a public API to enumerate registered tools at startup, so the transformation runs inside a `tools/list` middleware. To avoid a data race when multiple clients call `tools/list` concurrently (each invocation would otherwise mutate the shared *Tool.InputSchema map), the actual mutation is guarded by a `sync.Once`: the first call performs the lockdown, and concurrent callers block until that mutation completes. Subsequent calls are pure reads on the (now stable) schema maps and run lock-free.

func LogToolCall

func LogToolCall(tool string, start time.Time, err error)

LogToolCall logs a structured message after a tool handler completes. It records the tool name, elapsed duration, and any error that occurred.

func LogToolCallAll

func LogToolCallAll(ctx context.Context, req *mcp.CallToolRequest, tool string, start time.Time, err error)

LogToolCallAll logs to both stderr (slog) and the MCP client (protocol logging). It is the standard logging function for all tool handlers. When the request contains authenticated user identity (any mode), it includes the user in the log output for audit trail purposes.

func LookupMetaActionSchema

func LookupMetaActionSchema(routes map[string]ActionMap, tool, action string) (map[string]any, bool)

LookupMetaActionSchema returns the per-action params schema for a tool/action pair.

func MRStateEmoji

func MRStateEmoji(state string) string

MRStateEmoji returns the Markdown emoji for a merge request state.

func MakeMetaHandler

func MakeMetaHandler(toolName string, routes ActionMap, formatResult FormatResultFunc) func(ctx context.Context, req *mcp.CallToolRequest, input MetaToolInput) (*mcp.CallToolResult, any, error)

MakeMetaHandler creates a generic MCP tool handler that dispatches to action routes. The formatResult function converts the action result into an MCP response. If formatResult is nil, a default JSON formatter is used.

Destructive actions (delete, remove, revoke, unprotect, etc.) are automatically intercepted with a user confirmation prompt via MCP elicitation before execution. Confirmation can be bypassed with YOLO_MODE/AUTOPILOT env vars or by passing "confirm": true in the action params.

func MarkdownForResult

func MarkdownForResult(result any) *mcp.CallToolResult

MarkdownForResult resolves a tool output to its Markdown mcp.CallToolResult. Returns nil for nil input (caller should handle), returns nil when no formatter is registered for the concrete type.

func MarkdownTableHeader

func MarkdownTableHeader(columns ...string) string

MarkdownTableHeader returns a Markdown table header followed by a standard separator row for the supplied column labels.

func MarkdownTableRow

func MarkdownTableRow(cells ...string) string

MarkdownTableRow returns a Markdown table row for the supplied cell values.

func MarkdownTableSeparator

func MarkdownTableSeparator(columns int) string

MarkdownTableSeparator returns a standard left-aligned Markdown separator row for the requested number of columns.

func MdTitleLink(title, url string) string

MdTitleLink returns the title as a Markdown link if url is non-empty, otherwise returns the escaped title. Suitable for table cells.

func MergeVariables

func MergeVariables(sources ...map[string]any) map[string]any

MergeVariables merges multiple variable maps into a single map. Later maps override earlier ones for duplicate keys.

func MetaSchemaURI

func MetaSchemaURI(tool, action string) string

MetaSchemaURI returns the resource URI for a tool/action schema.

func MetaToolDescriptionPrefix

func MetaToolDescriptionPrefix(toolName string, routes ActionMap) string

MetaToolDescriptionPrefix builds a fixed-format header that should be prepended to a meta-tool's user-supplied description. The header gives LLMs a literal JSON usage example based on a representative action and points at the gitlab://schema/meta resource for per-action params schemas. Returns an empty string when routes is empty so callers degrade gracefully rather than emit a malformed header.

func MetaToolOutputSchema

func MetaToolOutputSchema() map[string]any

MetaToolOutputSchema returns the shared action-dispatch output schema used by meta-tools.

func MetaToolSchema

func MetaToolSchema(routes ActionMap) map[string]any

MetaToolSchema builds a JSON Schema for a meta-tool with the action field constrained to an enum of valid action names extracted from the routes map. Setting this as Tool.InputSchema ensures the LLM sees the exact list of valid actions in the schema, enabling first-try action selection.

The strategy used (opaque, compact, full) is read from the package-level mode set via SetMetaParamSchemaMode. Default is opaque. Callers that always want the opaque envelope regardless of global configuration should invoke BuildMetaToolSchema directly.

func MustIndividualToolFromSpecs

func MustIndividualToolFromSpecs(specs []ActionSpec, individualName string, opts IndividualToolProjectionOptions) *mcp.Tool

MustIndividualToolFromSpecs projects an individual tool or panics on invalid registration metadata. Use it from catalog-backed startup paths where a missing spec is a programming error.

func NormalizeActionAlias

func NormalizeActionAlias(action string, routes ActionMap) string

NormalizeActionAlias returns the canonical action name for common shortened action spellings when the canonical action exists on the target meta-tool.

func NormalizeParamAliasesForSchema

func NormalizeParamAliasesForSchema(params, schema map[string]any) map[string]any

NormalizeParamAliasesForSchema applies the same compatibility aliases used by UnmarshalParams, driven by a JSON Schema properties map instead of a Go struct type. It is used by evaluation code that validates simulated calls.

func NormalizeText

func NormalizeText(s string) string

NormalizeText replaces literal escape sequences with real characters. MCP clients may send text with literal backslash-n instead of real newlines when the JSON transport double-escapes the input.

Replacement order matters to avoid cascading conversions:

  1. `\\` -> `\` (double-escaped backslash first, so `\\n` becomes `\` + literal n, not a newline)
  2. `\r\n` -> `\n` (CRLF before individual CR/LF to avoid double-replacement)
  3. `\r` -> `\n` (standalone carriage return)
  4. `\n` -> newline (the most common case)
  5. `\t` -> tab

func NotFoundResult

func NotFoundResult(resource, identifier string, hints ...string) *mcp.CallToolResult

NotFoundResult creates an informational MCP tool result for resources that do not exist or are not accessible. Instead of returning a Go error (which would be logged as ERROR and produce an opaque error message for the LLM), this returns a structured Markdown result with actionable next steps.

The result has IsError=true to signal the tool could not fulfill the request, but the content is rich and helpful — the LLM can act on the suggestions.

Use this in register.go handler closures when IsHTTPStatus(err, 404) is true for "get" operations. Pass nil error back to the SDK so the call is logged at INFO level instead of ERROR.

func OpenAndValidateFile

func OpenAndValidateFile(path string, maxSize int64) (*os.File, os.FileInfo, error)

OpenAndValidateFile opens a local file for reading after validating it exists, is a regular file (not a directory, symlink, device or pipe), and does not exceed maxSize bytes. Returns the open file handle and its FileInfo.

func ParseGID

func ParseGID(gid string) (typeName string, id int64, err error)

ParseGID extracts the type name and numeric ID from a GitLab Global ID. It returns an error if the format is invalid.

ParseGID("gid://gitlab/Vulnerability/42") → ("Vulnerability", 42, nil)

func ParseMetaSchemaURI

func ParseMetaSchemaURI(uri string) (tool, action string)

ParseMetaSchemaURI extracts the tool and action segments from a schema URI.

func ParseOptionalTime

func ParseOptionalTime(s string) *time.Time

ParseOptionalTime parses an RFC3339 string and returns a *time.Time. Returns nil if the string is empty or unparseable.

func PipelineStatusEmoji

func PipelineStatusEmoji(status string) string

PipelineStatusEmoji returns the Markdown emoji for a pipeline status.

func PopulateHints

func PopulateHints(result *mcp.CallToolResult, setter HintSetter)

PopulateHints extracts next-step hints from the Markdown content of a CallToolResult and sets them on the output struct. It is a no-op when result is nil, contains no TextContent, or has no hints section.

func ProgressReportInterval

func ProgressReportInterval(total int64) int64

ProgressReportInterval returns the byte interval between progress reports. It is the smaller of 1 MB or 5% of total, with a minimum of 64 KB.

func ReadOnlyMetaAnnotationsWithTitle

func ReadOnlyMetaAnnotationsWithTitle(name string) *mcp.ToolAnnotations

ReadOnlyMetaAnnotationsWithTitle returns a copy of ReadOnlyMetaAnnotations with Title set.

func RegisterMarkdown

func RegisterMarkdown[T any](fn func(T) string)

RegisterMarkdown registers a Markdown string formatter for type T. Subsequent calls to MarkdownForResult with a value of type T will invoke fn and wrap the returned string in a mcp.CallToolResult.

func RegisterMarkdownPair

func RegisterMarkdownPair[A, B any](first func(A) string, second func(B) string)

RegisterMarkdownPair registers two Markdown string formatters.

func RegisterMarkdownResult

func RegisterMarkdownResult[T any](fn func(T) *mcp.CallToolResult)

RegisterMarkdownResult registers a result formatter for type T. Use this for types that need custom mcp.CallToolResult construction (e.g. uploads with image content).

func RegisterMarkdownTriple

func RegisterMarkdownTriple[A, B, C any](first func(A) string, second func(B) string, third func(C) string)

RegisterMarkdownTriple registers three Markdown string formatters.

func RegisterSurfaceToolFromSpec

func RegisterSurfaceToolFromSpec(server *mcp.Server, spec ActionSpec, opts SurfaceToolRegisterOptions)

RegisterSurfaceToolFromSpec registers one visible MCP tool by projecting an ActionSpec and executing its route handler directly.

func RegisteredMarkdownTypeNames

func RegisteredMarkdownTypeNames() []string

RegisteredMarkdownTypeNames returns the type names of all registered Markdown formatters (both string and result variants). Used by validation tests to verify sub-packages self-register their formatters.

func RequestFromContext

func RequestFromContext(ctx context.Context) *mcp.CallToolRequest

RequestFromContext extracts the MCP request from a context, or nil if absent.

func RichContentHint

func RichContentHint(features, webURL string) string

RichContentHint returns an informational note directing users to the GitLab web URL for full rendering when non-portable GFM features are detected. Returns an empty string when features or webURL is empty.

func SchemaForRoute

func SchemaForRoute[R any]() map[string]any

SchemaForRoute returns the cached output schema for type R. Exported for use by gen_llms and audit tools.

func SetMetaParamSchemaMode

func SetMetaParamSchemaMode(mode string)

SetMetaParamSchemaMode selects the meta-tool input schema strategy used by MetaToolSchema. Accepts "opaque" (default), "compact", or "full". Any other value is coerced to opaque so that misconfiguration cannot break the tools/list payload. Must be called before meta-tools are registered; later calls only affect schemas built after the call returns.

func SetMetaParamSchemaModeScoped

func SetMetaParamSchemaModeScoped(mode string) func()

SetMetaParamSchemaModeScoped selects the meta-tool input schema strategy and returns a restore function for tests that temporarily override the global mode.

func SetUploadConfig

func SetUploadConfig(maxFileSize int64)

SetUploadConfig overrides the default upload thresholds. Call before RegisterAll to propagate values into tool handler closures.

func StripMetaToolDescriptionPrefix

func StripMetaToolDescriptionPrefix(description string) string

StripMetaToolDescriptionPrefix removes the generated meta-tool usage header added by MetaToolDescriptionPrefix while preserving standalone descriptions that happen to start with an example.

func SuccessResult

func SuccessResult(markdown string) *mcp.CallToolResult

SuccessResult builds a standard success mcp.CallToolResult with Markdown and the structured output for both human-readable and programmatic consumption. If markdown is empty, the result contains only a structured JSON annotation.

func TitleFromName

func TitleFromName(name string) string

TitleFromName generates a human-readable UI title from a snake_case MCP tool name by stripping the "gitlab_" prefix and converting to Title Case.

TitleFromName("gitlab_list_projects") // returns "List Projects"

func ToolResultAnnotated

func ToolResultAnnotated(md string, ann *mcp.Annotations) *mcp.CallToolResult

ToolResultAnnotated wraps a Markdown string into a CallToolResult with content annotations that guide MCP clients on audience and priority. Pass nil annotations to get the same behavior as ToolResultWithMarkdown.

func ToolResultWithImage

func ToolResultWithImage(md string, ann *mcp.Annotations, imageData []byte, mimeType string) *mcp.CallToolResult

ToolResultWithImage creates a CallToolResult containing both a text description (metadata) and an ImageContent block with the raw image bytes. Multimodal LLMs can "see" the image; text-only LLMs get the metadata.

func ToolResultWithMarkdown

func ToolResultWithMarkdown(md string) *mcp.CallToolResult

ToolResultWithMarkdown wraps a Markdown string into a CallToolResult with a single TextContent entry annotated for assistant-only audience. This prevents MCP clients (e.g. VS Code) from displaying raw Markdown inline — the LLM processes it and presents formatted output to the user.

func UnmarshalParams

func UnmarshalParams[T any](params map[string]any) (T, error)

UnmarshalParams re-serializes params map to JSON and deserializes into T. LLMs frequently send numeric values as JSON strings (e.g. "17" instead of 17). When standard unmarshalling fails, this function retries after coercing string values that look like integers or floats into actual numbers.

Unknown keys in params (i.e. fields that do not exist on T) are rejected with an actionable error so that LLMs receive a clear diagnostic when they mistype a parameter name (e.g. "iid" instead of "snippet_id"). This mirrors the JSON Schema lockdown applied to tools/list responses (see LockdownInputSchemas) and the MCP guidance to surface validation errors as recoverable tool results so the model can self-correct. Meta-protocol keys (see [reservedParamKeys]) are stripped before unmarshalling.

func ValidActionsString

func ValidActionsString(routes ActionMap) string

ValidActionsString returns a sorted, comma-separated list of action names.

func ValidateDiffPosition

func ValidateDiffPosition(diffLines []DiffLine, newLine, oldLine int) error

ValidateDiffPosition checks whether a (newLine, oldLine) combination corresponds to a valid commentable position in the parsed diff lines.

Rules enforced (per GitLab API):

  • new_line only → line must be an added (+) line
  • old_line only → line must be a removed (-) line
  • both set → line must be an unchanged context line

Returns nil when the position is valid, or a descriptive error explaining exactly why the position is invalid and what the caller should do instead.

func ValidatePackageFileName

func ValidatePackageFileName(filename string) error

ValidatePackageFileName validates a filename for GitLab generic package upload. Filenames must not be empty, must not contain spaces, and must not start with a tilde or at-sign.

func ValidatePackageName

func ValidatePackageName(name string) error

ValidatePackageName validates a GitLab generic package name against allowed characters. Names must start with a letter or digit and may contain A-Z a-z 0-9 . _ - + ~ / @.

func ValidateRateLimit

func ValidateRateLimit(rps float64, burst int) error

ValidateRateLimit reports whether the given rps/burst pair forms a well-defined limiter configuration. Used by the server entrypoint to fail fast on bad CLI input rather than silently disabling the limiter.

func WithHints

func WithHints[O any](result *mcp.CallToolResult, out O, err error) (*mcp.CallToolResult, O, error)

WithHints extracts hints from a CallToolResult and populates them on the typed output struct, returning all three handler values in one call. This avoids evaluation-order ambiguity in multi-value return statements.

For value Out types (the common case), &out is used internally to satisfy the HintSetter pointer receiver. For pointer Out types (*T), the pointer itself implements HintSetter. If neither case applies, WithHints is a no-op.

return toolutil.WithHints(toolutil.ToolResultWithMarkdown(md), out, err)

func WrapErr

func WrapErr(operation string, err error) error

WrapErr classifies the error, enriches it with a semantic message, and wraps it with the operation name. All tool handlers funnel through here so connectivity and auth problems are reported consistently.

func WrapErrWithHint

func WrapErrWithHint(operation string, err error, hint string) error

WrapErrWithHint works like WrapErrWithMessage but appends an actionable hint that tells the LLM what to do next. Example:

"branchDelete: bad request — Cannot delete: protected branch.
 Suggestion: use gitlab_branch_unprotect first, then retry deletion: <original>"

The hint should be a concise suggestion starting with a verb (e.g., "use gitlab_branch_list to verify the branch name").

func WrapErrWithMessage

func WrapErrWithMessage(operation string, err error) error

WrapErrWithMessage works like WrapErr but also includes the specific GitLab error message (from ErrorResponse.Message) when available. This produces richer errors like:

"fileCreate: bad request — {error: A file with this name already exists}: POST .../files: 400"

Use WrapErrWithMessage for mutating operations where the specific GitLab error detail helps the LLM understand what went wrong. Use WrapErr for read-only operations where the generic classification suffices.

func WrapErrWithStatusHint

func WrapErrWithStatusHint(operation string, err error, code int, hint string) error

WrapErrWithStatusHint returns WrapErrWithHint(operation, err, hint) when err matches the given HTTP status code, otherwise falls back to WrapErrWithMessage(operation, err). It compresses the common pattern:

if toolutil.IsHTTPStatus(err, 404) {
    return ..., toolutil.WrapErrWithHint(op, err, hint)
}
return ..., toolutil.WrapErrWithMessage(op, err)

into a single call. For handlers that need different hints per status, use a switch over IsHTTPStatus checks; this helper covers the dominant single- status case.

func WrapGFMBody

func WrapGFMBody(body string) string

WrapGFMBody wraps user-generated GFM content in a Markdown blockquote to prevent heading hierarchy conflicts and structural breaks in the formatted output. Empty bodies return an empty string.

func WriteEmpty

func WriteEmpty(b *strings.Builder, resource string)

WriteEmpty writes a standardized empty-result message to the builder. The resource parameter should be a clear, specific plural noun (e.g. "merge requests", "pipeline variables", "protected branches").

func WriteHints

func WriteHints(b *strings.Builder, hints ...string)

WriteHints appends a "💡 Next steps" section to the Markdown builder. Each hint is a short string describing a related action the LLM can take (e.g. "Use action 'delete' to remove this package"). If no hints are provided, nothing is written.

func WriteListSummary

func WriteListSummary(b *strings.Builder, shown int, p PaginationOutput)

WriteListSummary appends a brief "Showing N of M results (page X of Y)" line between the heading and the table body. It is a no-op when there is only a single page, because the heading count already conveys everything.

func WritePagination

func WritePagination(b *strings.Builder, p PaginationOutput)

WritePagination appends a newline-wrapped pagination summary to the builder.

Types

type ActionAliasSpec

type ActionAliasSpec struct {
	Alias          string
	Target         string
	Source         string
	Searchable     bool
	Deprecated     bool
	RemovalVersion string
	Reason         string
}

ActionAliasSpec describes a compatibility alias that resolves to a canonical action owned by an ActionSpec.

type ActionFunc

type ActionFunc func(ctx context.Context, params map[string]any) (any, error)

ActionFunc is a handler that receives raw params and returns a result or error.

func WrapAction

func WrapAction[T any, R any](client *gitlabclient.Client, fn func(ctx context.Context, client *gitlabclient.Client, input T) (R, error)) ActionFunc

WrapAction wraps a typed handler (input T -> output R) into a generic ActionFunc.

func WrapActionWithRequest

func WrapActionWithRequest[T any, R any](client *gitlabclient.Client, fn func(ctx context.Context, req *mcp.CallToolRequest, client *gitlabclient.Client, input T) (R, error)) ActionFunc

WrapActionWithRequest wraps a handler that also requires the MCP request (e.g., for progress tracking). The request is extracted from context via RequestFromContext; if absent, nil is passed.

func WrapVoidAction

func WrapVoidAction[T any](client *gitlabclient.Client, fn func(ctx context.Context, client *gitlabclient.Client, input T) error) ActionFunc

WrapVoidAction wraps a typed handler that returns only error.

func WrapVoidActionWithRequest

func WrapVoidActionWithRequest[T any](client *gitlabclient.Client, fn func(ctx context.Context, req *mcp.CallToolRequest, client *gitlabclient.Client, input T) error) ActionFunc

WrapVoidActionWithRequest wraps a void handler that also requires the MCP request. The request is extracted from context via RequestFromContext; if absent, nil is passed.

type ActionMap

type ActionMap map[string]ActionRoute

ActionMap maps action names to their route definitions (handler + metadata).

func ActionSpecsToMap

func ActionSpecsToMap(specs []ActionSpec) ActionMap

ActionSpecsToMap converts canonical action specs to a legacy ActionMap.

func ActionSpecsToMapWithError

func ActionSpecsToMapWithError(specs []ActionSpec) (ActionMap, error)

ActionSpecsToMapWithError converts canonical action specs to a legacy ActionMap.

type ActionRoute

type ActionRoute struct {
	Handler           ActionFunc
	Destructive       bool
	InputType         reflect.Type
	InputSchema       map[string]any
	OutputSchema      map[string]any
	ParameterGuidance map[string]ParameterGuidance
	Aliases           []string
	Tags              []string
	Usage             string
	RelatedActions    []string
}

ActionRoute pairs an action handler with metadata about its behavior. Used by meta-tools to carry per-route destructive classification without string parsing. OutputSchema holds the JSON Schema for the action's typed output. InputSchema holds the JSON Schema for the action's typed params (nil for routes constructed via the untyped Route and DestructiveRoute constructors).

func DestructiveAction

func DestructiveAction[T any, R any](client *gitlabclient.Client, fn func(ctx context.Context, client *gitlabclient.Client, input T) (R, error)) ActionRoute

DestructiveAction wraps a typed function as a destructive ActionRoute and attaches input/output schemas.

func DestructiveActionWithRequest

func DestructiveActionWithRequest[T any, R any](client *gitlabclient.Client, fn func(ctx context.Context, req *mcp.CallToolRequest, client *gitlabclient.Client, input T) (R, error)) ActionRoute

DestructiveActionWithRequest wraps a typed function that needs the MCP request as a destructive ActionRoute and attaches input/output schemas.

func DestructiveFunc

func DestructiveFunc[T any, R any](fn func(ctx context.Context, input T) (R, error)) ActionRoute

DestructiveFunc wraps a typed function as a destructive ActionRoute without a GitLab client dependency and attaches input and output schemas.

func DestructiveRoute

func DestructiveRoute(fn ActionFunc) ActionRoute

DestructiveRoute creates a destructive ActionRoute without an output schema.

func DestructiveVoidAction

func DestructiveVoidAction[T any](client *gitlabclient.Client, fn func(ctx context.Context, client *gitlabclient.Client, input T) error) ActionRoute

DestructiveVoidAction wraps a typed void function as a destructive ActionRoute. The handler returns a typed DeleteOutput confirmation so meta-tool routes expose structured output instead of nil content.

func DestructiveVoidActionWithRequest

func DestructiveVoidActionWithRequest[T any](client *gitlabclient.Client, fn func(ctx context.Context, req *mcp.CallToolRequest, client *gitlabclient.Client, input T) error) ActionRoute

DestructiveVoidActionWithRequest wraps a request-aware void function as a destructive ActionRoute with typed DeleteOutput confirmation, reusing WrapVoidActionWithRequest so the request-extraction logic is not duplicated.

func Route

func Route(fn ActionFunc) ActionRoute

Route creates a non-destructive ActionRoute without an output schema.

func RouteAction

func RouteAction[T any, R any](client *gitlabclient.Client, fn func(ctx context.Context, client *gitlabclient.Client, input T) (R, error)) ActionRoute

RouteAction wraps a typed function as a non-destructive ActionRoute and attaches the JSON Schema for the input type T and output type R.

func RouteActionWithRequest

func RouteActionWithRequest[T any, R any](client *gitlabclient.Client, fn func(ctx context.Context, req *mcp.CallToolRequest, client *gitlabclient.Client, input T) (R, error)) ActionRoute

RouteActionWithRequest wraps a typed function that needs the MCP request as a non-destructive ActionRoute and attaches input/output schemas.

func RouteFunc

func RouteFunc[T any, R any](fn func(ctx context.Context, input T) (R, error)) ActionRoute

RouteFunc wraps a typed function as a non-destructive ActionRoute without a GitLab client dependency and attaches input and output schemas.

func RouteRequestFunc

func RouteRequestFunc[T any, R any](fn func(ctx context.Context, req *mcp.CallToolRequest, input T) (R, error)) ActionRoute

RouteRequestFunc wraps a typed request-aware function as a non-destructive ActionRoute without a GitLab client dependency and attaches schemas.

func RouteVoidAction

func RouteVoidAction[T any](client *gitlabclient.Client, fn func(ctx context.Context, client *gitlabclient.Client, input T) error) ActionRoute

RouteVoidAction wraps a typed void function as a non-destructive ActionRoute. The handler returns a typed VoidOutput confirmation so meta-tool routes expose structured output instead of nil content.

func (ActionRoute) WithAliases

func (route ActionRoute) WithAliases(aliases ...string) ActionRoute

WithAliases returns a copy of route with additional search aliases.

func (ActionRoute) WithParameterGuidance

func (route ActionRoute) WithParameterGuidance(guidance map[string]ParameterGuidance) ActionRoute

WithParameterGuidance returns a copy of route with merged parameter guidance.

func (ActionRoute) WithRelatedActions

func (route ActionRoute) WithRelatedActions(actions ...string) ActionRoute

WithRelatedActions returns a copy of route with related canonical action IDs.

func (ActionRoute) WithTags

func (route ActionRoute) WithTags(tags ...string) ActionRoute

WithTags returns a copy of route with additional search tags.

func (ActionRoute) WithUsage

func (route ActionRoute) WithUsage(usage string) ActionRoute

WithUsage returns a copy of route with a short model-facing usage hint.

type ActionSpec

type ActionSpec struct {
	Name                   string
	Route                  ActionRoute
	Aliases                []string
	Tags                   []string
	Usage                  string
	RelatedActions         []string
	Compatibility          CompatibilityPolicy
	ParameterGuidance      map[string]ParameterGuidance
	InputSchemaOverrides   []InputSchemaOverride
	ReadOnly               bool
	Destructive            bool
	Idempotent             bool
	OpenWorld              bool
	Edition                string
	GitLabDotComOnly       bool
	OwnerPackage           string
	IndividualTool         IndividualToolSpec
	ContentKind            string
	NotFoundPolicy         string
	EmbeddedResourcePolicy string
	RichResultPolicy       string
	SchemaValidationNotes  []string
	RuntimeValidationNotes []string
}

ActionSpec is the canonical metadata contract for one GitLab action.

func CloneActionSpec

func CloneActionSpec(spec ActionSpec) ActionSpec

CloneActionSpec returns a defensive copy of spec and all mutable metadata it owns.

func CloneActionSpecs

func CloneActionSpecs(specs []ActionSpec) []ActionSpec

CloneActionSpecs returns defensive copies of specs in their original order.

func NewActionSpec

func NewActionSpec(name string, route ActionRoute, opts ActionSpecOptions) ActionSpec

NewActionSpec creates a defensive canonical action specification.

func (ActionSpec) Validate

func (spec ActionSpec) Validate() error

Validate verifies invariants that must hold before projecting a spec.

type ActionSpecOptions

type ActionSpecOptions struct {
	Aliases                []string
	Tags                   []string
	Usage                  string
	RelatedActions         []string
	Compatibility          CompatibilityPolicy
	ParameterGuidance      map[string]ParameterGuidance
	InputSchemaOverrides   []InputSchemaOverride
	ReadOnly               bool
	Destructive            bool
	Idempotent             bool
	OpenWorld              bool
	Edition                string
	GitLabDotComOnly       bool
	OwnerPackage           string
	IndividualTool         IndividualToolSpec
	ContentKind            string
	NotFoundPolicy         string
	EmbeddedResourcePolicy string
	RichResultPolicy       string
	SchemaValidationNotes  []string
	RuntimeValidationNotes []string
}

ActionSpecOptions contains optional metadata for NewActionSpec.

type CICDVariableFlags

type CICDVariableFlags struct {
	Protected bool
	Masked    bool
	Hidden    bool
	Raw       bool
}

CICDVariableFlags groups boolean CI/CD variable attributes for Markdown view-model construction.

type CICDVariableListMarkdownOptions

type CICDVariableListMarkdownOptions struct {
	Title                   string
	EmptyMessage            string
	IncludeEnvironmentScope bool
	Hints                   []string
}

CICDVariableListMarkdownOptions configures the shared CI/CD variable list renderer.

type CICDVariableMarkdown

type CICDVariableMarkdown struct {
	Key              string
	Value            string
	VariableType     string
	Protected        bool
	Masked           bool
	Hidden           bool
	Raw              bool
	EnvironmentScope string
	Description      string
}

CICDVariableMarkdown carries the common fields rendered by GitLab CI/CD variable tools at project, group, and instance scopes.

func CICDVariableMarkdowns

func CICDVariableMarkdowns[T any](variables []T, convert func(T) CICDVariableMarkdown) []CICDVariableMarkdown

CICDVariableMarkdowns maps package-specific variable outputs to the shared CI/CD variable Markdown view model.

func NewCICDVariableMarkdown

func NewCICDVariableMarkdown(key, value, variableType string, flags CICDVariableFlags, environmentScope, description string) CICDVariableMarkdown

NewCICDVariableMarkdown builds a shared Markdown view model for CI/CD variables without forcing tool packages to duplicate composite literals.

type CICDVariableMarkdownOptions

type CICDVariableMarkdownOptions struct {
	Title                   string
	IncludeEnvironmentScope bool
	Hints                   []string
}

CICDVariableMarkdownOptions configures the shared CI/CD variable detail renderer.

type CompatibilityPolicy

type CompatibilityPolicy struct {
	ActionAliases    []ActionAliasSpec
	ParameterAliases []ParameterAliasSpec
}

CompatibilityPolicy carries compatibility aliases and their ownership policy.

func CloneCompatibilityPolicy

func CloneCompatibilityPolicy(policy CompatibilityPolicy) CompatibilityPolicy

CloneCompatibilityPolicy returns a defensive copy of compatibility metadata.

type DeleteOutput

type DeleteOutput struct {
	HintableOutput
	Status  string `json:"status"`
	Message string `json:"message"`
}

DeleteOutput is a confirmation message returned by destructive tool handlers (delete, unprotect, unapprove) so the LLM receives explicit feedback instead of empty content when the operation succeeds.

func DeleteResult

func DeleteResult(resource string) (*mcp.CallToolResult, DeleteOutput, error)

DeleteResult builds a DeleteOutput and its Markdown representation for a successful destructive operation. The resource parameter describes what was affected (e.g., "project 42", "branch feature/x").

type DetailedError

type DetailedError struct {
	Domain       string `json:"domain"`
	Action       string `json:"action"`
	Message      string `json:"message"`
	Details      string `json:"details,omitempty"`
	GitLabStatus int    `json:"gitlab_status,omitempty"`
	RequestID    string `json:"request_id,omitempty"`
}

DetailedError represents a rich, structured error with domain context for diagnostic output. It extends ToolError with additional fields useful for automated issue creation and Markdown error reporting.

func NewDetailedError

func NewDetailedError(domain, action string, err error) *DetailedError

NewDetailedError creates a DetailedError from a GitLab API error, extracting HTTP status and request ID when available.

func (*DetailedError) Error

func (e *DetailedError) Error() string

Error returns a concise representation: "domain/action: message".

func (*DetailedError) Markdown

func (e *DetailedError) Markdown() string

Markdown renders the error as a Markdown block suitable for display in MCP tool results. Includes all available context for diagnostics.

type DiffLine

type DiffLine struct {
	OldLine int      // Line number in old file (0 for added lines)
	NewLine int      // Line number in new file (0 for removed lines)
	Type    LineType // Whether the line was added, removed, or unchanged
}

DiffLine represents a single line in a parsed unified diff with its old/new line numbers and type (added, removed, or context).

func ParseDiffLines

func ParseDiffLines(diff string) []DiffLine

ParseDiffLines parses a unified diff string and returns metadata for each line, including old/new line numbers and whether it is added, removed, or context. Only lines inside @@ hunk headers are returned.

type DiffOutput

type DiffOutput struct {
	OldPath     string `json:"old_path"`
	NewPath     string `json:"new_path"`
	AMode       string `json:"a_mode,omitempty"`
	BMode       string `json:"b_mode,omitempty"`
	Diff        string `json:"diff"`
	NewFile     bool   `json:"new_file"`
	RenamedFile bool   `json:"renamed_file"`
	DeletedFile bool   `json:"deleted_file"`
}

DiffOutput represents a single file diff from the GitLab API. It is used by both commit diff and repository compare operations.

func DiffToOutput

func DiffToOutput(d *gl.Diff) DiffOutput

DiffToOutput converts a GitLab API gl.Diff to the MCP tool output format.

type DiscussionListMarkdownOptions

type DiscussionListMarkdownOptions struct {
	Title             string
	EmptyMessage      string
	Pagination        PaginationOutput
	GraphQLPagination *GraphQLPaginationOutput
	Hints             []string
}

DiscussionListMarkdownOptions configures shared discussion list rendering.

type DiscussionMarkdown

type DiscussionMarkdown struct {
	ID    string
	Notes []DiscussionNoteMarkdown
}

DiscussionMarkdown carries common discussion fields for Markdown responses.

func DiscussionMarkdowns

func DiscussionMarkdowns[T any](discussions []T, convert func(T) DiscussionMarkdown) []DiscussionMarkdown

DiscussionMarkdowns maps package-specific discussion outputs to the shared discussion Markdown view model.

func DiscussionOutputMarkdowns

func DiscussionOutputMarkdowns(discussions []DiscussionOutput) []DiscussionMarkdown

DiscussionOutputMarkdowns maps shared REST discussion outputs to Markdown view models.

func NewDiscussionMarkdown

func NewDiscussionMarkdown(id string, notes []DiscussionNoteMarkdown) DiscussionMarkdown

NewDiscussionMarkdown builds a shared Markdown view model for discussion threads.

type DiscussionNoteMarkdown

type DiscussionNoteMarkdown struct {
	ID        int64
	Body      string
	Author    string
	CreatedAt string
}

DiscussionNoteMarkdown carries common note fields rendered inside discussion Markdown responses.

func DiscussionNoteMarkdowns

func DiscussionNoteMarkdowns[T any](notes []T, convert func(T) DiscussionNoteMarkdown) []DiscussionNoteMarkdown

DiscussionNoteMarkdowns maps package-specific note outputs to the shared discussion note Markdown view model.

func NewDiscussionNoteMarkdown

func NewDiscussionNoteMarkdown(id int64, body, author, createdAt string) DiscussionNoteMarkdown

NewDiscussionNoteMarkdown builds a shared Markdown view model for discussion notes.

type DiscussionNoteOutput

type DiscussionNoteOutput struct {
	HintableOutput
	ID        int64  `json:"id"`
	Body      string `json:"body"`
	Author    string `json:"author"`
	CreatedAt string `json:"created_at"`
	UpdatedAt string `json:"updated_at,omitempty"`
	System    bool   `json:"system"`
}

DiscussionNoteOutput carries the common JSON fields returned by REST discussion note tools.

func (DiscussionNoteOutput) MarkdownNote

func (note DiscussionNoteOutput) MarkdownNote() DiscussionNoteMarkdown

MarkdownNote returns the shared Markdown view model for a discussion note.

type DiscussionOutput

type DiscussionOutput struct {
	HintableOutput
	ID             string                 `json:"id"`
	IndividualNote bool                   `json:"individual_note"`
	Notes          []DiscussionNoteOutput `json:"notes"`
}

DiscussionOutput carries the common JSON fields returned by REST discussion tools.

func (DiscussionOutput) MarkdownDiscussion

func (discussion DiscussionOutput) MarkdownDiscussion() DiscussionMarkdown

MarkdownDiscussion returns the shared Markdown view model for a discussion.

type DiscussionRenderer

type DiscussionRenderer struct {
	ListTitle       string
	EmptyMessage    string
	ListHints       []string
	DiscussionHints []string
	NoteHints       []string
}

DiscussionRenderer stores stable labels and hints for a discussion family so package formatters can avoid repeating identical rendering glue.

func NewDiscussionRenderer

func NewDiscussionRenderer(listTitle, emptyMessage, listHint, discussionHint, noteHint string) DiscussionRenderer

NewDiscussionRenderer builds a renderer for discussion tool families that use one hint for each list, discussion, and note view.

func (DiscussionRenderer) FormatDiscussion

func (r DiscussionRenderer) FormatDiscussion(discussion DiscussionMarkdown) string

FormatDiscussion renders a single discussion using the renderer hints.

func (DiscussionRenderer) FormatGraphQLList

func (r DiscussionRenderer) FormatGraphQLList(discussions []DiscussionMarkdown, pagination GraphQLPaginationOutput) string

FormatGraphQLList renders GraphQL discussion threads with cursor pagination.

func (DiscussionRenderer) FormatNote

FormatNote renders a single discussion note using the renderer hints.

func (DiscussionRenderer) FormatRESTList

func (r DiscussionRenderer) FormatRESTList(discussions []DiscussionMarkdown, pagination PaginationOutput) string

FormatRESTList renders REST discussion threads with offset pagination.

type FormatResultFunc

type FormatResultFunc func(any) *mcp.CallToolResult

FormatResultFunc converts an action result into an MCP call tool result.

type GraphQLError

type GraphQLError struct {
	Message string `json:"message"`
}

GraphQLError is one top-level GraphQL error returned in a successful HTTP response body.

type GraphQLPageInfo

type GraphQLPageInfo struct {
	HasNextPage     bool   `json:"has_next_page"`
	HasPreviousPage bool   `json:"has_previous_page"`
	EndCursor       string `json:"end_cursor,omitempty"`
	StartCursor     string `json:"start_cursor,omitempty"`
}

GraphQLPageInfo holds cursor-based pagination metadata returned by GraphQL connection responses. It maps directly to GitLab's PageInfo type.

type GraphQLPaginationInput

type GraphQLPaginationInput struct {
	First  *int   `json:"first,omitempty"  jsonschema:"Number of items to return (default 20, max 100)"`
	After  string `json:"after,omitempty"  jsonschema:"Cursor for forward pagination (from previous response end_cursor)"`
	Last   *int   `json:"last,omitempty"   jsonschema:"Number of items from the end (backward pagination)"`
	Before string `json:"before,omitempty" jsonschema:"Cursor for backward pagination (from previous response start_cursor)"`
}

GraphQLPaginationInput holds cursor-based pagination parameters for GraphQL list queries. It mirrors the standard GraphQL connection model (first/after for forward, last/before for backward).

func (GraphQLPaginationInput) EffectiveFirst

func (p GraphQLPaginationInput) EffectiveFirst() int

EffectiveFirst returns the requested page size, clamped to [1, GraphQLMaxFirst] with GraphQLDefaultFirst as fallback.

func (GraphQLPaginationInput) Variables

func (p GraphQLPaginationInput) Variables() map[string]any

Variables returns a map suitable for inclusion in a GraphQL variables payload. Only non-zero fields are included.

type GraphQLPaginationOutput

type GraphQLPaginationOutput struct {
	HasNextPage     bool   `json:"has_next_page"`
	HasPreviousPage bool   `json:"has_previous_page"`
	EndCursor       string `json:"end_cursor,omitempty"`
	StartCursor     string `json:"start_cursor,omitempty"`
}

GraphQLPaginationOutput holds pagination metadata for GraphQL list tool responses, presented in a consistent format for LLM consumers.

func PageInfoToOutput

func PageInfoToOutput(pi GraphQLRawPageInfo) GraphQLPaginationOutput

PageInfoToOutput converts a raw GraphQL PageInfo response struct (with camelCase JSON keys from the API) to the snake_case output struct.

type GraphQLRawPageInfo

type GraphQLRawPageInfo struct {
	HasNextPage     bool   `json:"hasNextPage"`
	HasPreviousPage bool   `json:"hasPreviousPage"`
	EndCursor       string `json:"endCursor"`
	StartCursor     string `json:"startCursor"`
}

GraphQLRawPageInfo matches the camelCase JSON shape returned by the GitLab GraphQL API before conversion to our snake_case output.

type HintSetter

type HintSetter interface {
	// SetNextSteps stores the extracted next-step hints on the output struct.
	SetNextSteps(hints []string)
}

HintSetter is implemented by any Output struct that embeds HintableOutput. PopulateHints uses this interface to set extracted hints on the output.

type HintableOutput

type HintableOutput struct {
	NextSteps []string `json:"next_steps,omitempty"`
}

HintableOutput is an embeddable struct that adds a next_steps field to any Output type. Embed it as the FIRST field of an Output struct so that next_steps appears first in the serialized JSON, giving LLMs immediate guidance before reading the rest of the payload.

type Output struct {
    toolutil.HintableOutput
    Name string `json:"name"`
}

func (*HintableOutput) SetNextSteps

func (h *HintableOutput) SetNextSteps(hints []string)

SetNextSteps stores the given hints in the NextSteps field.

type IndividualToolAnnotationOverrides

type IndividualToolAnnotationOverrides struct {
	ReadOnly    *bool
	Destructive *bool
	Idempotent  *bool
	OpenWorld   *bool
}

IndividualToolAnnotationOverrides carries compatibility overrides for historical individual-tool annotations that intentionally differ from the canonical action semantics.

type IndividualToolProjectionOptions

type IndividualToolProjectionOptions struct {
	Description string
	Icons       []mcp.Icon
}

IndividualToolProjectionOptions contains surface-level metadata that is shared by an individual tool projection but not owned by the action spec itself.

type IndividualToolSpec

type IndividualToolSpec struct {
	Name                string
	Title               string
	Description         string
	AnnotationOverrides IndividualToolAnnotationOverrides
}

IndividualToolSpec carries compatibility metadata for the individual-tool surface.

func CloneIndividualToolSpec

func CloneIndividualToolSpec(spec IndividualToolSpec) IndividualToolSpec

CloneIndividualToolSpec returns a defensive copy of individual-tool metadata.

type InputSchemaOverride

type InputSchemaOverride struct {
	PropertyPath string
	Values       map[string]any
}

InputSchemaOverride describes a deterministic JSON Schema patch for an action input schema. PropertyPath is a dot-separated input property path; an empty path applies Values at the schema root. Array properties automatically traverse through their items schema for nested paths.

func SchemaAnyOfRequired

func SchemaAnyOfRequired(propertyNames ...string) InputSchemaOverride

SchemaAnyOfRequired returns a root override that requires at least one of the supplied property names to be present.

func SchemaPropertyOverride

func SchemaPropertyOverride(propertyPath string, values map[string]any) InputSchemaOverride

SchemaPropertyOverride returns an input-schema override for a property path.

func SchemaRootOverride

func SchemaRootOverride(values map[string]any) InputSchemaOverride

SchemaRootOverride returns an input-schema override applied at the schema root.

type LabelMarkdown

type LabelMarkdown struct {
	ID                     int64
	Name                   string
	Color                  string
	Description            string
	OpenIssuesCount        int64
	ClosedIssuesCount      int64
	OpenMergeRequestsCount int64
	Priority               int64
	PrioritySpecified      bool
	IsProjectLabel         bool
	Subscribed             bool
}

LabelMarkdown holds the common fields rendered for project and group labels.

type LabelMarkdownOptions

type LabelMarkdownOptions struct {
	DetailTitle       string
	ListTitle         string
	EmptyListText     string
	DetailHints       []string
	ListHints         []string
	EscapeDescription bool
}

LabelMarkdownOptions controls label detail and list Markdown copy.

type LineType

type LineType int

LineType classifies a line within a unified diff hunk.

const (
	// LineContext identifies an unchanged line present in both old and new file versions.
	LineContext LineType = iota // Unchanged line (present in both old and new file)
	// LineAdded identifies a line present only in the new file version.
	LineAdded // Added line (present only in new file)
	// LineRemoved identifies a line present only in the old file version.
	LineRemoved // Removed line (present only in old file)
)

type MetaSchemaActionEntry

type MetaSchemaActionEntry struct {
	Action      string `json:"action"`
	SchemaURI   string `json:"schema_uri"`
	Destructive bool   `json:"destructive"`
}

MetaSchemaActionEntry describes one meta-tool action in the tool-call index.

type MetaSchemaDiscoveryIndex

type MetaSchemaDiscoveryIndex struct {
	URITemplate string                `json:"uri_template"`
	ToolCount   int                   `json:"tool_count"`
	ActionCount int                   `json:"action_count"`
	Tools       []MetaSchemaToolEntry `json:"tools"`
}

MetaSchemaDiscoveryIndex is a model-controlled schema discovery payload.

func BuildMetaSchemaDiscoveryIndex

func BuildMetaSchemaDiscoveryIndex(routes map[string]ActionMap) MetaSchemaDiscoveryIndex

BuildMetaSchemaDiscoveryIndex builds the richer tool-call schema index payload.

func BuildMetaSchemaDiscoveryIndexForTool

func BuildMetaSchemaDiscoveryIndexForTool(routes map[string]ActionMap, tool string) (MetaSchemaDiscoveryIndex, bool)

BuildMetaSchemaDiscoveryIndexForTool builds the tool-call index for one meta-tool.

type MetaSchemaIndex

type MetaSchemaIndex struct {
	URITemplate string                 `json:"uri_template"`
	Tools       []MetaSchemaIndexEntry `json:"tools"`
}

MetaSchemaIndex is the payload returned by the schema index resource.

func BuildMetaSchemaIndex

func BuildMetaSchemaIndex(routes map[string]ActionMap) MetaSchemaIndex

BuildMetaSchemaIndex builds the resource-compatible schema index payload.

type MetaSchemaIndexEntry

type MetaSchemaIndexEntry struct {
	Tool    string   `json:"tool"`
	Actions []string `json:"actions"`
}

MetaSchemaIndexEntry is a single tool entry in the resource index payload.

type MetaSchemaRegistry

type MetaSchemaRegistry struct {
	// contains filtered or unexported fields
}

MetaSchemaRegistry stores the visible meta-tool route snapshot used by model-controlled schema discovery actions.

func NewMetaSchemaRegistry

func NewMetaSchemaRegistry(routes map[string]ActionMap) *MetaSchemaRegistry

NewMetaSchemaRegistry creates a registry initialized with a route snapshot.

func (*MetaSchemaRegistry) Routes

func (r *MetaSchemaRegistry) Routes() map[string]ActionMap

Routes returns a defensive copy of the registry contents.

func (*MetaSchemaRegistry) SetRoutes

func (r *MetaSchemaRegistry) SetRoutes(routes map[string]ActionMap)

SetRoutes replaces the registry contents with a defensive route snapshot.

type MetaSchemaToolEntry

type MetaSchemaToolEntry struct {
	Tool        string                  `json:"tool"`
	ActionCount int                     `json:"action_count"`
	Actions     []MetaSchemaActionEntry `json:"actions"`
}

MetaSchemaToolEntry describes one meta-tool in the tool-call index.

type MetaToolInput

type MetaToolInput struct {
	Action string         `json:"action" jsonschema:"Action to perform. See the tool description for available actions and their parameters."`
	Params map[string]any `` /* 147-byte string literal not displayed */
}

MetaToolInput is the common input for all meta-tools. The LLM sends an action name and a params object; the dispatcher routes to the underlying handler function and deserializes params into the action-specific input struct.

type NoteListMarkdownOptions

type NoteListMarkdownOptions struct {
	Title           string
	EmptyMessage    string
	IncludeInternal bool
	Hints           []string
}

NoteListMarkdownOptions configures shared note list rendering.

type NoteMarkdown

type NoteMarkdown struct {
	ID         int64
	Body       string
	Author     string
	CreatedAt  string
	System     bool
	Internal   bool
	Resolvable bool
	Resolved   bool
	ResolvedBy string
}

NoteMarkdown carries common fields rendered by issue, merge request, and snippet note tools.

func NewNoteMarkdown

func NewNoteMarkdown(id int64, body, author, createdAt string, flags NoteMarkdownFlags, resolvedBy string) NoteMarkdown

NewNoteMarkdown builds a shared Markdown view model for GitLab notes.

func NoteMarkdowns

func NoteMarkdowns[T any](notes []T, convert func(T) NoteMarkdown) []NoteMarkdown

NoteMarkdowns maps package-specific note outputs to the shared note Markdown view model.

type NoteMarkdownFlags

type NoteMarkdownFlags struct {
	System     bool
	Internal   bool
	Resolvable bool
	Resolved   bool
}

NoteMarkdownFlags groups boolean note attributes for Markdown view-model construction.

type NoteMarkdownOptions

type NoteMarkdownOptions struct {
	Title             string
	IncludeInternal   bool
	IncludeResolvable bool
	Hints             []string
}

NoteMarkdownOptions configures shared note detail rendering.

type PaginationInput

type PaginationInput struct {
	Page    int `` /* 156-byte string literal not displayed */
	PerPage int `` /* 156-byte string literal not displayed */
}

PaginationInput holds common pagination query parameters for list endpoints. Constraints (page>=1, per_page in [1,100]) are also enforced at the JSON Schema level by EnrichPaginationConstraints so LLM clients see the bounds directly in tools/list responses.

type PaginationOutput

type PaginationOutput struct {
	Page       int64 `json:"page"`
	PerPage    int64 `json:"per_page"`
	TotalItems int64 `json:"total_items"`
	TotalPages int64 `json:"total_pages"`
	NextPage   int64 `json:"next_page"`
	PrevPage   int64 `json:"prev_page"`
	HasMore    bool  `json:"has_more"`
}

PaginationOutput holds pagination metadata extracted from GitLab API responses. Fields map to GitLab's X-Page, X-Per-Page, X-Total, X-Total-Pages, X-Next-Page, X-Prev-Page headers. HasMore is a derived convenience flag (NextPage > 0) so LLM clients can decide whether to paginate without inspecting NextPage.

func PaginationFromResponse

func PaginationFromResponse(resp *gl.Response) PaginationOutput

PaginationFromResponse extracts pagination metadata from a GitLab API response.

type ParamAliasExplanation

type ParamAliasExplanation struct {
	Alias     string `json:"alias"`
	Canonical string `json:"canonical"`
	Source    string `json:"source"`
	Notes     string `json:"notes,omitempty"`
}

ParamAliasExplanation describes a compatibility parameter normalization. It intentionally records parameter names only, never parameter values.

func NormalizeParamAliasesForSchemaWithExplanation

func NormalizeParamAliasesForSchemaWithExplanation(params, schema map[string]any) (map[string]any, []ParamAliasExplanation)

NormalizeParamAliasesForSchemaWithExplanation returns the normalized params and name-only metadata describing compatibility aliases that were applied.

type ParamValidationError

type ParamValidationError struct {
	Err error
}

ParamValidationError marks parameter decoding failures that should be surfaced as recoverable tool errors instead of protocol errors.

func (*ParamValidationError) Error

func (e *ParamValidationError) Error() string

Error returns the underlying validation error message.

func (*ParamValidationError) Unwrap

func (e *ParamValidationError) Unwrap() error

Unwrap returns the underlying validation error.

type ParameterAliasSpec

type ParameterAliasSpec struct {
	Alias          string
	Target         string
	Source         string
	Searchable     bool
	Deprecated     bool
	RemovalVersion string
	Reason         string
}

ParameterAliasSpec describes a compatibility alias for one action parameter.

type ParameterGuidance

type ParameterGuidance struct {
	SemanticRole     string   `json:"semantic_role,omitempty"`
	ValueSource      string   `json:"value_source,omitempty"`
	CommonConfusions []string `json:"common_confusions,omitempty"`
	ExampleBinding   string   `json:"example_binding,omitempty"`
}

ParameterGuidance carries compact model-facing hints for parameters that are easy to confuse across similar GitLab actions.

type ProgressReader

type ProgressReader struct {
	// contains filtered or unexported fields
}

ProgressReader wraps an io.Reader and reports progress to an MCP progress tracker as bytes are read. Safe to use with a zero-value/inactive tracker.

func NewProgressReader

func NewProgressReader(ctx context.Context, r io.Reader, total int64, tracker progress.Tracker) *ProgressReader

NewProgressReader creates a ProgressReader that reports upload progress. If the tracker is inactive, the wrapper still works but skips notifications.

func (*ProgressReader) BytesRead

func (pr *ProgressReader) BytesRead() int64

BytesRead returns the total number of bytes read so far.

func (*ProgressReader) Read

func (pr *ProgressReader) Read(p []byte) (int, error)

Read implements io.Reader. It reads from the inner reader and periodically sends progress notifications via the MCP tracker.

type ProgressWriter

type ProgressWriter struct {
	// contains filtered or unexported fields
}

ProgressWriter wraps an io.Writer and reports progress to an MCP progress tracker as bytes are written (used for downloads to disk).

func NewProgressWriter

func NewProgressWriter(ctx context.Context, w io.Writer, total int64, tracker progress.Tracker) *ProgressWriter

NewProgressWriter creates a ProgressWriter that reports download progress.

func (*ProgressWriter) BytesWritten

func (pw *ProgressWriter) BytesWritten() int64

BytesWritten returns the total number of bytes written so far.

func (*ProgressWriter) Write

func (pw *ProgressWriter) Write(p []byte) (int, error)

Write implements io.Writer. It writes to the inner writer and periodically sends progress notifications via the MCP tracker.

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

RateLimiter enforces a token-bucket rate limit on `tools/call` requests. A zero RPS disables the limiter (the constructor returns nil and the resulting middleware is a no-op).

Limits are advisory; the primary defense remains GitLab's own per-token rate limits. The local limiter exists to soften bursts (typical LLM retry-loop with a flaky tool can fire dozens of identical calls per second) and to give operators a single knob they can tighten when they see 429s in practice. Default is off so existing deployments keep their current behavior.

The limiter shares a single bucket across the server. In HTTP mode each per-token server instance from the pool gets its own RateLimiter, so the limit is effectively per-token. In stdio mode the bucket is global to the single process.

rate.Limiter is safe for concurrent use by design, so RateLimiter does not need additional synchronization of its own.

func NewRateLimiter

func NewRateLimiter(rps float64, burst int) *RateLimiter

NewRateLimiter builds a RateLimiter with the given rate (requests per second) and burst (maximum concurrent tokens in the bucket). Returns nil if rps <= 0, which the middleware treats as "disabled". Burst is clamped to a minimum of 1 when rps > 0 to avoid an unusable zero-burst limiter.

type StorageMoveEntityMarkdown

type StorageMoveEntityMarkdown struct {
	Label string
	Name  string
	URL   string
	ID    int64
}

StorageMoveEntityMarkdown carries the optional GitLab resource associated with a repository storage move.

func NewStorageMoveEntityMarkdown

func NewStorageMoveEntityMarkdown(label, name, url string, id int64) *StorageMoveEntityMarkdown

NewStorageMoveEntityMarkdown builds the optional entity view model for a repository storage move.

type StorageMoveListMarkdownOptions

type StorageMoveListMarkdownOptions struct {
	Title        string
	EmptyMessage string
	EntityColumn string
	Pagination   PaginationOutput
}

StorageMoveListMarkdownOptions configures the shared storage move list renderer.

type StorageMoveMarkdown

type StorageMoveMarkdown struct {
	ID                     int64
	State                  string
	SourceStorageName      string
	DestinationStorageName string
	CreatedAt              time.Time
	Entity                 *StorageMoveEntityMarkdown
}

StorageMoveMarkdown carries the common fields rendered by repository storage move tools at group, snippet, and other resource scopes.

func NewStorageMoveMarkdown

func NewStorageMoveMarkdown(id int64, state, sourceStorageName, destinationStorageName string, createdAt time.Time, entity *StorageMoveEntityMarkdown) StorageMoveMarkdown

NewStorageMoveMarkdown builds a shared repository storage move Markdown view model without forcing tool packages to duplicate composite literals.

func StorageMoveMarkdowns

func StorageMoveMarkdowns[T any](moves []T, convert func(T) StorageMoveMarkdown) []StorageMoveMarkdown

StorageMoveMarkdowns maps package-specific storage move outputs to the shared Markdown view model.

type StringOrInt

type StringOrInt string //nolint:recvcheck // UnmarshalJSON requires pointer receiver, others are value receivers by design

StringOrInt is a string type that accepts both JSON strings and JSON numbers during unmarshalling. It always stores the value as a string internally. This is needed because LLMs frequently send numeric IDs (e.g. 405) as JSON numbers rather than strings, even when the schema declares "type": "string".

func (StringOrInt) Int64

func (s StringOrInt) Int64() (int64, error)

Int64 parses the stored string as a base-10 integer and returns it. Returns 0 and an error if the value is empty or not a valid integer.

func (StringOrInt) MarshalJSON

func (s StringOrInt) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler to always output a JSON string.

func (StringOrInt) String

func (s StringOrInt) String() string

String returns the underlying string value.

func (*StringOrInt) UnmarshalJSON

func (s *StringOrInt) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler to accept both JSON strings (e.g. "405", "group/project") and JSON numbers (e.g. 405, 42.0).

type SurfaceToolRegisterOptions

type SurfaceToolRegisterOptions struct {
	Description  string
	Icons        []mcp.Icon
	FormatResult FormatResultFunc
}

SurfaceToolRegisterOptions controls how an ActionSpec is exposed as a standalone visible MCP tool.

type TemplateListMarkdownOptions

type TemplateListMarkdownOptions struct {
	Title        string
	EmptyMessage string
	Hints        []string
}

TemplateListMarkdownOptions configures shared template list rendering.

type TemplateMarkdown

type TemplateMarkdown struct {
	Key  string `json:"key"`
	Name string `json:"name"`
}

TemplateMarkdown carries common fields rendered by template list tools.

func NewTemplateMarkdown

func NewTemplateMarkdown(key, name string) TemplateMarkdown

NewTemplateMarkdown builds a shared Markdown view model for GitLab template list entries.

func TemplateMarkdowns

func TemplateMarkdowns[T any](templates []T, convert func(T) TemplateMarkdown) []TemplateMarkdown

TemplateMarkdowns maps package-specific template outputs to the shared template Markdown view model.

type TemplateRenderer

type TemplateRenderer struct {
	ListTitle    string
	EmptyMessage string
	ListHint     string
	DetailTitle  string
	Language     string
	DetailHint   string
}

TemplateRenderer stores the stable labels and hints for a GitLab template family so package formatters can avoid repeating identical rendering glue.

func NewTemplateRenderer

func NewTemplateRenderer(listTitle, emptyMessage, listHint, detailTitle, language, detailHint string) TemplateRenderer

NewTemplateRenderer builds a renderer for a GitLab template family.

func (TemplateRenderer) FormatContent

func (r TemplateRenderer) FormatContent(name, content string) string

FormatContent renders a single GitLab template body with the renderer configuration.

func (TemplateRenderer) FormatList

func (r TemplateRenderer) FormatList(templates []TemplateMarkdown, pagination PaginationOutput) string

FormatList renders a GitLab template list with the renderer configuration.

type ToolError

type ToolError struct {
	Tool       string `json:"tool"`
	Message    string `json:"message"`
	StatusCode int    `json:"status_code,omitempty"`
}

ToolError represents a structured error from a tool handler.

func (*ToolError) Error

func (e *ToolError) Error() string

Error returns a human-readable representation of the tool error. When StatusCode is set, it is appended as "(HTTP <code>)".

type UploadConfig

type UploadConfig struct {
	MaxFileSize int64
}

UploadConfig holds runtime-configurable upload parameters. Initialized with package defaults; use SetUploadConfig to override from environment config.

func GetUploadConfig

func GetUploadConfig() UploadConfig

GetUploadConfig returns the current upload configuration (for testing).

type UserIdentity

type UserIdentity struct {
	UserID   string
	Username string
}

UserIdentity holds the authenticated user's identity. Populated from OAuth TokenInfo (HTTP modes) or from the startup-resolved identity stored in context (stdio mode).

func IdentityFromContext

func IdentityFromContext(ctx context.Context) UserIdentity

IdentityFromContext retrieves the UserIdentity stored in the context. Returns a zero-value UserIdentity if none was stored.

func ResolveIdentity

func ResolveIdentity(ctx context.Context, req *mcp.CallToolRequest) UserIdentity

ResolveIdentity returns the authenticated user's identity by checking two sources in priority order:

  1. req.Extra.TokenInfo (populated by SDK in HTTP modes via RequireBearerToken)
  2. Context-stored identity (populated at startup in stdio mode)

Returns a zero-value UserIdentity if neither source has identity.

func (UserIdentity) IsAuthenticated

func (u UserIdentity) IsAuthenticated() bool

IsAuthenticated returns true if the identity contains a non-empty UserID.

type VoidOutput

type VoidOutput struct {
	HintableOutput
	Status  string `json:"status"`
	Message string `json:"message"`
}

VoidOutput is a confirmation message returned by tool handlers that perform an action without returning domain data (e.g., set header, start mirroring).

func VoidResult

func VoidResult(message string) (*mcp.CallToolResult, VoidOutput, error)

VoidResult builds a VoidOutput and its Markdown representation for a successful void operation. The message describes what happened.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL