Documentation
¶
Overview ¶
Package tool is the registration framework for an MCP service's tools: each tool declares, in one place, its name, the upstream routes its arguments can reach, its behaviour hint, and how it attaches to the server.
The layout is the point. A tool spread across several packages — name constant, MCP declaration, route derivation, application logic — means adding or changing one requires finding all of them, and the copies can disagree. Everything a tool decides lives in one declaration.
The registry is generic over the service's dependency container type C, so this package depends on no particular DI framework: each service instantiates a Registry with its own container type and keeps thin, service-specific route constructors around ServiceRoute.
Index ¶
- type Behaviour
- type Registry
- func (r *Registry[C]) All() []Tool[C]
- func (r *Registry[C]) AnnotationsFor(name string) *mcp.ToolAnnotations
- func (r *Registry[C]) IsLocal(name string) bool
- func (r *Registry[C]) MappedTools() map[string]bool
- func (r *Registry[C]) Register(t Tool[C])
- func (r *Registry[C]) Routes() map[string][]Route
- func (r *Registry[C]) ServiceKeys() []string
- type Route
- type Tool
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Behaviour ¶
type Behaviour int
Behaviour is what a tool does to the state on the other side of it, and the hint clients gate approval on.
One declaration rather than a boolean per protocol hint. ReadOnlyHint and DestructiveHint have three meaningful combinations, not four: a pair of booleans lets a tool declare the impossible fourth, and lets it declare nothing at all.
const ( // ReadOnly does not change the state on the other side at all. ReadOnly Behaviour // Additive changes it, but only by adding — the protocol's own word for // destructiveHint: false on a tool that is not read-only. Reach for it when // the upstream route is a GET but the call still leaves something behind. Additive // Destructive may update or remove what is already there. Destructive )
type Registry ¶
type Registry[C any] struct { // contains filtered or unexported fields }
Registry holds one MCP service's tool declarations. Each service creates one (typically as a package-level variable filled by each tool file's init) via NewRegistry.
func (*Registry[C]) All ¶
All returns every registered tool, ordered by name so registration order — and therefore the tools/list order — does not depend on file or init order.
func (*Registry[C]) AnnotationsFor ¶
func (r *Registry[C]) AnnotationsFor(name string) *mcp.ToolAnnotations
AnnotationsFor builds one tool's MCP annotations from its registration. Central, so no tool file can omit them or contradict what it declared, and so DestructiveHint is never left nil — nil is read as the protocol default, true.
func (*Registry[C]) IsLocal ¶
IsLocal reports whether a tool is served entirely inside the MCP service and so has no upstream route to authorize.
func (*Registry[C]) MappedTools ¶
MappedTools returns every tool name that reaches an upstream route — the authoritative set for RBAC and for server-instruction guards.
func (*Registry[C]) Register ¶
Register records one tool. Every failure here is a configuration bug, so it panics: the service not starting is the loudest possible signal, and unlike a test it cannot be skipped or forgotten.
func (*Registry[C]) Routes ¶
Routes returns every upstream-mapped tool's route universe. Local tools have no upstream route and are absent. Sole source of truth for tools/list visibility.
func (*Registry[C]) ServiceKeys ¶
ServiceKeys returns every distinct upstream service key some tool needs, ordered by name; local tools contribute nothing. Read from the declarations rather than derived anywhere else: a second derivation would drift, and the drift would show as a service nobody warmed.
type Route ¶
Route is the (URI, method) pair security-proxy-auth's RBAC is keyed by. The URI is the upstream path prefixed by its service, as proxy-auth sees it.
func ServiceRoute ¶
ServiceRoute builds a Route for one upstream service, so a tool names the API route it reaches without repeating the service prefix. serviceKey is the bare service key (e.g. "core-metadata"); each MCP service defines its own thin constructors over this.
type Tool ¶
type Tool[C any] struct { // Name is the MCP tool name. Name string // ServiceKey is the upstream service whose client must exist before this // tool can be registered. Empty for a tool served entirely in-process. ServiceKey string // VisibilityRoutes is every upstream route this tool's arguments can reach. // tools/list has no arguments, so it decides visibility against the whole set. // // Required unless Local. It must be DECLARED, never derived from "this tool // has no routes": an empty universe is fail-closed, so a forgotten // declaration hides the tool — whereas deriving "no routes means local" would // turn the same mistake into a tool visible to everyone. VisibilityRoutes []Route // Local marks a tool with no upstream route for route-authz to authorize — // see the reason above. Such a tool may still call an upstream, in which case // it must validate caller-controlled path values itself (see middleware README). Local bool // Behaviour is the tool's MCP behaviour hint. // // Declared here rather than at the mcp.AddTool site because omitting it there // is silent and wrong in the dangerous direction: the SDK documents // DestructiveHint as "Default: true", so a tool that says nothing is // advertised to clients as destructive — and clients gate approval on exactly // that. Register refuses the omission. Behaviour Behaviour // Add attaches the tool to the server. Add func(*mcp.Server, C) }
Tool is what the server needs to know about one MCP tool that is not the tool's own behaviour. C is the service's dependency container type.