Help us shape the future of Go! Take the 2026 Go Developer Survey

gatewaycompat

package
v3.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package gatewaycompat rewrites the human-readable text this server lists — tool, prompt, resource and resource-template descriptions and titles, and the description and title annotations embedded in tool schemas — according to operator-defined substitutions.

It exists because MCP gateways validate a server's catalog before admitting it, and their rules are the gateway operator's to choose: one production gateway (IBM mcp-context-forge before 0.7.0) refused any tool whose description contained a semicolon. This server keeps its own text clean of the characters known to be rejected (cmd/audit_gateway_chars gates that), but the next gateway rule is not this project's to predict. The substitution knob lets the operator comply with a rule the day they meet it, without waiting for a release.

The knob rewrites catalog metadata and nothing else: names, URIs, schema constraints (pattern, const, enum values, defaults) and tool-call payloads are never touched, because those are contract, not prose.

Index

Constants

View Source
const (
	MaxSubstitutions     = 32
	MaxSubstitutionBytes = 256
)

MaxSubstitutions and MaxSubstitutionBytes bound the configuration, and growthFactor and growthAllowance bound its effect.

The knob is the only setting that writes operator-chosen prose into the channel a model reads as instructions, and it is an ordinary environment variable rather than a flag. Bounding it keeps a compliance tool a compliance tool: a gateway rule is satisfied by a handful of short rewrites, so a configuration that needs hundreds of rules, or a paragraph per rule, is not the use this exists for.

The two effect bounds exist because a length limit per rule does not bound the result. A rule replacing a single frequent letter with 200 bytes stays well inside every configuration limit and still multiplies the served catalog. So the ceiling is relative to the text being rewritten: output may not exceed growthFactor times the input, nor the input plus growthAllowance bytes, whichever is larger. The allowance is what keeps short titles rewritable.

View Source
const EnvVar = "GITLAB_MCP_DESCRIPTION_SUBSTITUTIONS"

EnvVar configures the substitutions in both stdio and HTTP modes. The value is a comma-separated list of old=new pairs applied in order to every listed description and title. A backslash escapes a literal comma, equals sign or backslash inside either half, so a semicolon can become a comma:

GITLAB_MCP_DESCRIPTION_SUBSTITUTIONS=';=\,'

Whitespace is significant: "; = " substitutes "; " (semicolon, space) with " " (a single space). An empty or unset value disables the middleware.

Variables

This section is empty.

Functions

func Apply

func Apply(subs []Substitution, text string) string

Apply runs every substitution over text, in declared order, unless doing so would grow the text past the ceiling growthLimit sets — in which case text is returned as written.

The refusal is all-or-nothing. Applying the rules that fit would serve a third text nobody configured, and the unrewritten one is the text this project's own gateway-character audit vouches for.

Each rule's result length is computed before the rule runs, so an oversized string is never built.

func Middleware

func Middleware(subs []Substitution) mcp.Middleware

Middleware returns a receiving middleware that applies subs to the four catalog listings a gateway validates: tools/list, prompts/list, resources/list and resources/templates/list. Every other method passes through untouched — a prompt's message content or a tool call's result is payload, and rewriting payload would change what the server does rather than how it introduces itself.

Results are cloned before modification: list results return pointers shared with the server's registries, so an in-place edit would corrupt the catalog for every other session of this process.

func RewriteSchemaProse

func RewriteSchemaProse(v any, rewrite func(text string) string) bool

RewriteSchemaProse walks a decoded JSON schema value, passes every prose string — the value of a description or title keyword, however deeply nested — to rewrite, stores what it returns, and reports whether anything changed. Everything that is not prose survives verbatim: names, patterns, and the data keywords (default, const, enum, examples), whose subtrees are never entered.

It is exported for cmd/audit_gateway_chars, which scans the same strings this package rewrites: sharing the walk is what keeps "what the audit checks" and "what the knob can fix" the same set by construction.

Types

type Substitution

type Substitution struct {
	// Old is the literal text to replace. Never empty.
	Old string
	// New is the literal replacement. May be empty, which deletes Old.
	New string
}

Substitution is one ordered old→new text replacement.

func FromEnv

func FromEnv() ([]Substitution, error)

FromEnv parses EnvVar. An unset or empty variable is not an error: it returns nil, nil, and the caller installs nothing.

An active configuration is announced at WARN, once per process. A rewritten catalog is otherwise indistinguishable at runtime from an unrewritten one, which makes "the descriptions the model reads are not the ones this build ships" a fact with no local evidence.

func ParseSubstitutions

func ParseSubstitutions(value string) ([]Substitution, error)

ParseSubstitutions parses a comma-separated list of old=new pairs.

Within a pair, the first unescaped equals sign separates old from new; later unescaped equals signs in new are literal. Backslash escapes a comma, an equals sign or a backslash; any other escape is an error, because a silently absorbed typo here would ship a substitution the operator did not write. An empty old is an error for the same reason: ReplaceAll with an empty pattern inserts new between every pair of characters.

Jump to

Keyboard shortcuts

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