Documentation
¶
Overview ¶
Package plugin implements plugin process management, discovery, lifecycle, and the bidirectional JSON-lines transport.
Index ¶
- func ValidatePluginName(name string) error
- type AuthServiceConfig
- type CacheServiceConfig
- type CallToolResult
- type CompiledSchema
- type CredentialMeta
- type DisabledPlugin
- type DiscoveryOptions
- type DiscoveryResult
- type HTTPServiceConfig
- type Handle
- func (h *Handle) AuthBindings() map[string]string
- func (h *Handle) CallTool(ctx context.Context, toolName string, params json.RawMessage) (*CallToolResult, error)
- func (h *Handle) InitDomains() []string
- func (h *Handle) InitialResources() []protocol.ResourceDef
- func (h *Handle) IsReady() bool
- func (h *Handle) ListResources(ctx context.Context) ([]protocol.ResourceDef, error)
- func (h *Handle) ReadResource(ctx context.Context, uri string) (string, string, error)
- func (h *Handle) SetResources(resources []protocol.ResourceDef)
- func (h *Handle) SetSandbox(sb *sandbox.Manager)
- func (h *Handle) Start(ctx context.Context) error
- func (h *Handle) Stop(ctx context.Context) error
- type ItemsDef
- type Manager
- func (m *Manager) CallTool(_ context.Context, toolName string) (string, *Handle)
- func (m *Manager) ConfigDisabledPlugins() map[string]*Manifest
- func (m *Manager) DisabledPlugins() map[string]DisabledPlugin
- func (m *Manager) Discover(dirs []string, userDir string) error
- func (m *Manager) Handle(name string) *Handle
- func (m *Manager) IsLoading() bool
- func (m *Manager) Load(ctx context.Context, name string) error
- func (m *Manager) LoadAll(ctx context.Context) error
- func (m *Manager) LoadedPlugins() []string
- func (m *Manager) Manifests() map[string]*Manifest
- func (m *Manager) Reload(ctx context.Context, name string) error
- func (m *Manager) SetDisabledPlugin(name, reason string)
- func (m *Manager) SetHandle(name string)
- func (m *Manager) SetManifest(name string, manifest *Manifest)
- func (m *Manager) SetSandbox(sb *sandbox.Manager)
- func (m *Manager) ShutdownAll(ctx context.Context)
- func (m *Manager) StartPending(ctx context.Context)
- func (m *Manager) ToolOwner(toolName string) string
- func (m *Manager) Unload(ctx context.Context, name string) error
- func (m *Manager) WaitLoaded()
- type Manifest
- func (m *Manifest) CacheEnabled() bool
- func (m *Manifest) CacheNamespace() string
- func (m *Manifest) HandlerPath() string
- func (m *Manifest) IsEnabled() bool
- func (m *Manifest) ProvidesAuth() bool
- func (m *Manifest) ProvidesResources() bool
- func (m *Manifest) SetResolvedConfig(cfg json.RawMessage)
- func (m *Manifest) Validate() error
- type OutputConfig
- type ParamDef
- type Process
- type ProcessConfig
- type ProvidesAuthConfig
- type ProvidesConfig
- type ServiceConfig
- type ServiceHandler
- type SetupConfig
- type SetupVariant
- type State
- type TLSConfig
- type ToolDef
- type Transport
- func (t *Transport) ForwardStderr(pluginName string)
- func (t *Transport) GenerateID(prefix string) string
- func (t *Transport) ReadLoop(pluginName string, concurrency int, serviceHandler ServiceHandler)
- func (t *Transport) Send(msg protocol.Message) error
- func (t *Transport) SendAndWait(ctx context.Context, id string, msg protocol.Message) (protocol.Message, error)
- func (t *Transport) SetToolContext(ctx *context.Context)
- func (t *Transport) ToolContext() context.Context
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ValidatePluginName ¶ added in v0.1.5
ValidatePluginName checks whether name matches the plugin name pattern. Returns an error if the name is invalid.
Types ¶
type AuthServiceConfig ¶
type AuthServiceConfig struct {
Type string `yaml:"type"`
// Token holds a bearer token (type=bearer) or refresh/offline
// token (type=refresh_token). Typically set via env var: "${MY_TOKEN}".
Token string `yaml:"token"`
Header string `yaml:"header"`
Prefix string `yaml:"prefix"`
Username string `yaml:"username"`
Password string `yaml:"password"`
SPN string `yaml:"spn"`
SPNEGOProactive *bool `yaml:"spnego_proactive"`
Scopes []string `yaml:"scopes"`
CredentialsFile string `yaml:"credentials_file"`
TokenFile string `yaml:"token_file"`
TokenURL string `yaml:"token_url"`
ClientID string `yaml:"client_id"`
Select string `yaml:"select"`
Variants map[string]AuthServiceConfig `yaml:"variants"`
VariantOrder []string `yaml:"-"` // populated from YAML key order
}
AuthServiceConfig declares auth requirements.
type CacheServiceConfig ¶
type CacheServiceConfig struct {
Enabled *bool `yaml:"enabled"`
Namespace string `yaml:"namespace"`
DefaultTTL int `yaml:"default_ttl"`
}
CacheServiceConfig declares cache settings.
type CallToolResult ¶ added in v0.1.5
type CallToolResult struct {
Result json.RawMessage
Actions []protocol.Action
}
CallToolResult holds the result of a tool call along with any actions.
type CompiledSchema ¶ added in v0.1.7
type CompiledSchema struct {
// contains filtered or unexported fields
}
CompiledSchema wraps a compiled JSON Schema for parameter validation.
func CompileParamsSchema ¶ added in v0.1.7
func CompileParamsSchema(toolName string, toolDef ToolDef) (*CompiledSchema, error)
CompileParamsSchema compiles a tool's parameter schema for validation. Returns nil schema (no validation) if the schema has no properties. Returns an error if the schema is malformed or oversized, causing the caller to disable the tool.
func (*CompiledSchema) Validate ¶ added in v0.1.7
func (cs *CompiledSchema) Validate(params json.RawMessage) error
Validate checks params against the compiled schema. Returns nil if valid.
type CredentialMeta ¶
type CredentialMeta struct {
Description string `yaml:"description"`
Example string `yaml:"example"`
HelpURL string `yaml:"help_url"`
Instructions string `yaml:"instructions"`
Secret bool `yaml:"secret"`
}
CredentialMeta describes how to obtain a credential value.
type DisabledPlugin ¶ added in v0.1.4
DisabledPlugin records a plugin that was discovered but could not be loaded due to a configuration issue (e.g., env.d file with bad permissions). Its tools are registered with [DISABLED] descriptions so the LLM can tell the user how to fix it.
type DiscoveryOptions ¶ added in v0.1.5
type DiscoveryOptions struct {
ConfigPath string // Optional config file path
WorkdirOverride string // Optional workdir override
SkipConfigFiltering bool // If true, ignore plugins.enabled and plugins.disabled during discovery
}
DiscoveryOptions configures plugin discovery behavior.
type DiscoveryResult ¶ added in v0.1.5
type DiscoveryResult struct {
Workdir string
ConfigPath string // Resolved config file path (for write-back)
Config *config.Config
EnvDir string // Resolved env.d directory path
EnvGroups map[string]map[string]string
EnvErrors map[string]string
EnvDirError string // env.d directory-level error, if any
Manager *Manager
VaultResolver func(vaultID string) ([]byte, error)
}
DiscoveryResult contains the results of plugin discovery.
func Discover ¶ added in v0.1.5
func Discover(opts DiscoveryOptions) (*DiscoveryResult, error)
Discover performs plugin discovery without loading plugins. This is the common discovery logic used by CLI tools and the check command. For the main server runtime, use the full initialization in run().
type HTTPServiceConfig ¶
type HTTPServiceConfig struct {
BaseURL string `yaml:"base_url"`
AllowedDomains []string `yaml:"allowed_domains"`
AllowPrivateIPs bool `yaml:"allow_private_ips"`
TLS TLSConfig `yaml:"tls"`
}
HTTPServiceConfig declares HTTP proxy settings.
type Handle ¶
type Handle struct {
// contains filtered or unexported fields
}
Handle wraps a plugin process and serializes tool calls based on the plugin's concurrency setting.
func NewHandle ¶
func NewHandle(manifest *Manifest, handler ServiceHandler, cfg ProcessConfig, toolTimeout time.Duration, groupVars map[string]string) *Handle
NewHandle creates a Handle for dispatching tool calls to a plugin.
func (*Handle) AuthBindings ¶ added in v0.1.7
AuthBindings returns per-domain auth bindings registered during plugin init. Keys are domain names, values are env var names.
func (*Handle) CallTool ¶
func (h *Handle) CallTool(ctx context.Context, toolName string, params json.RawMessage) (*CallToolResult, error)
CallTool dispatches a tool call to the plugin. For persistent plugins, sends via the transport. For oneshot plugins, spawns a fresh process per call.
func (*Handle) InitDomains ¶ added in v0.1.7
InitDomains returns dynamic domains registered during plugin init.
func (*Handle) InitialResources ¶ added in v0.1.5
func (h *Handle) InitialResources() []protocol.ResourceDef
InitialResources returns the cached resource list (thread-safe).
func (*Handle) IsReady ¶ added in v0.1.6
IsReady returns true if the handle can accept tool calls. Non-persistent (oneshot) plugins are always ready; persistent plugins are ready once Start has been called and succeeded.
func (*Handle) ListResources ¶ added in v0.1.5
ListResources queries the handler for its current resource list. Uses transport directly (not h.mu) to avoid deadlock with tool calls.
func (*Handle) ReadResource ¶ added in v0.1.5
ReadResource requests the content of a specific resource URI. Uses transport directly (not h.mu) to avoid deadlock with tool calls.
func (*Handle) SetResources ¶ added in v0.1.5
func (h *Handle) SetResources(resources []protocol.ResourceDef)
SetResources updates the cached resource list (thread-safe).
func (*Handle) SetSandbox ¶ added in v0.1.7
SetSandbox configures the sandbox manager for this handle's processes.
type ItemsDef ¶
type ItemsDef struct {
Type string `yaml:"type"`
}
ItemsDef describes array item types.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager discovers, loads, and manages plugin lifecycles.
func NewManager ¶
func NewManager(authReg *auth.Registry, p *proxy.Proxy, c cache.Store, cfg *config.Config, envGroups config.EnvGroups, envErrors map[string]string, envDirError, workdir, envDir string, envLoadOpts config.EnvLoadOptions, sessionDir string) *Manager
NewManager creates a plugin manager. envErrors maps credential group names to their load errors (from LoadEnvGroups). Plugins whose credential_group appears in envErrors will be disabled during LoadAll instead of loaded. envDirError, if non-empty, indicates the env.d directory itself has a problem (bad permissions, stat failure) — all credential-dependent plugins will be disabled. envDir is the resolved env.d directory path used to re-read env files on plugin reload.
func NewManagerForTest ¶ added in v0.1.4
func NewManagerForTest() *Manager
NewManagerForTest creates a Manager with no dependencies for use in tests that need to populate manifests and handles directly.
func (*Manager) ConfigDisabledPlugins ¶ added in v0.1.5
ConfigDisabledPlugins returns plugins that were skipped during discovery because they are listed in plugins.disabled config.
func (*Manager) DisabledPlugins ¶ added in v0.1.4
func (m *Manager) DisabledPlugins() map[string]DisabledPlugin
DisabledPlugins returns a snapshot of plugins that were discovered but could not be loaded (e.g., bad env.d permissions, TLS/cert errors, missing dependencies, process start failures). Thread-safe.
func (*Manager) Discover ¶
Discover scans directories for plugin.yaml files and loads manifests. First directory wins for a given plugin name; duplicates in later directories are skipped with a warning. userDir, if non-empty, identifies the user plugins directory — plugins from it are restricted (e.g., cannot declare provides.auth).
func (*Manager) Handle ¶ added in v0.1.5
Handle returns the handle for a loaded plugin, or nil if not loaded.
func (*Manager) IsLoading ¶ added in v0.1.6
IsLoading returns true if StartPending is still running.
func (*Manager) LoadAll ¶
LoadAll prepares all discovered plugins synchronously: resolves dependencies, loads auth providers, filters disabled plugins, and prepares handles (config, proxy, TLS). This is the fast phase.
After LoadAll returns, m.disabled is fully populated and all handles are prepared. Call StartPending to launch the plugin processes in the background (the slow phase).
func (*Manager) LoadedPlugins ¶ added in v0.1.4
LoadedPlugins returns the names of successfully loaded plugins.
func (*Manager) Reload ¶
Reload stops and restarts a plugin. Re-reads the env.d file to pick up any changes (e.g., new IPA_CA_CERT added by create_config). If the plugin was disabled due to an env.d error, enables it if the issue is resolved.
func (*Manager) SetDisabledPlugin ¶ added in v0.1.7
SetDisabledPlugin marks a plugin as disabled for testing.
func (*Manager) SetHandle ¶ added in v0.1.4
SetHandle marks a plugin as loaded by creating a placeholder handle.
func (*Manager) SetManifest ¶ added in v0.1.4
SetManifest sets a manifest in the manager for testing.
func (*Manager) SetSandbox ¶ added in v0.1.7
SetSandbox configures the sandbox manager. When set, all plugin processes are launched in arapuca sandboxes. Must be called before LoadAll.
func (*Manager) ShutdownAll ¶
ShutdownAll stops all loaded plugins.
func (*Manager) StartPending ¶ added in v0.1.6
StartPending starts all prepared plugin processes by dependency level. This is the slow phase — each plugin spawns a subprocess and blocks on the init handshake (up to InitTimeout per plugin). Independent plugins within a level start in parallel.
Closes loadDone when complete. Safe to call from a goroutine.
func (*Manager) Unload ¶
Unload stops a plugin. Removes the handle from the map before stopping the process so new tool calls are not dispatched to a stopping plugin.
func (*Manager) WaitLoaded ¶ added in v0.1.6
func (m *Manager) WaitLoaded()
WaitLoaded blocks until StartPending completes.
type Manifest ¶
type Manifest struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
Description string `yaml:"description"`
Execution string `yaml:"execution"` // "oneshot" or "persistent"
Concurrency int `yaml:"concurrency"` // default: 1
Handler string `yaml:"handler"`
DependsOn []string `yaml:"depends_on"`
CredentialGroup string `yaml:"credential_group"` // scopes env.d access
EnvPassthrough string `yaml:"env_passthrough"` // "all" to pass all group vars
Env []string `yaml:"env"` // env vars to pass from credential group
Services ServiceConfig `yaml:"services"`
Provides ProvidesConfig `yaml:"provides"`
Config map[string]string `yaml:"config"`
Tools []ToolDef `yaml:"tools"`
ContextFiles []string `yaml:"context_files"`
Priority int `yaml:"priority"`
Enabled *bool `yaml:"enabled"`
Output OutputConfig `yaml:"output"`
Setup SetupConfig `yaml:"setup"`
// Dir is the directory containing this manifest (set at load time).
Dir string `yaml:"-"`
// contains filtered or unexported fields
}
Manifest holds plugin metadata loaded from plugin.yaml.
func LoadManifest ¶
LoadManifest reads and validates a plugin.yaml file.
func (*Manifest) CacheEnabled ¶
CacheEnabled returns whether cache is enabled (defaults to true).
func (*Manifest) CacheNamespace ¶
CacheNamespace returns the cache namespace (defaults to plugin name).
func (*Manifest) HandlerPath ¶
HandlerPath returns the absolute path to the handler executable.
func (*Manifest) ProvidesAuth ¶
ProvidesAuth returns true if this plugin provides an auth type.
func (*Manifest) ProvidesResources ¶ added in v0.1.5
ProvidesResources returns true if the plugin provides dynamic resources.
func (*Manifest) SetResolvedConfig ¶
func (m *Manifest) SetResolvedConfig(cfg json.RawMessage)
SetResolvedConfig sets the resolved config JSON for the plugin.
type OutputConfig ¶
type OutputConfig struct {
Format string `yaml:"format"`
}
OutputConfig allows per-plugin output format override.
type ParamDef ¶
type ParamDef struct {
Type string `yaml:"type"`
Description string `yaml:"description"`
Required bool `yaml:"required"`
Default any `yaml:"default"`
Items *ItemsDef `yaml:"items"`
}
ParamDef describes a tool parameter.
type Process ¶
type Process struct {
Transport *Transport
Resources []protocol.ResourceDef // resources discovered at init
Domains []string // dynamic domains from init_ok
AuthBindings map[string]string // per-domain auth bindings from init_ok
// contains filtered or unexported fields
}
Process manages a plugin handler's OS process and transport.
func NewProcess ¶
func NewProcess(manifest *Manifest, handler ServiceHandler, cfg ProcessConfig, groupVars map[string]string) *Process
NewProcess creates a Process for the given manifest. groupVars are the scoped env.d variables for this plugin's credential_group.
func (*Process) SetSandbox ¶ added in v0.1.7
SetSandbox configures the sandbox manager for this process. When set and enabled, Start() launches via arapuca instead of exec.CommandContext.
type ProcessConfig ¶
type ProcessConfig struct {
InitTimeout time.Duration
ShutdownTimeout time.Duration
ShutdownKillAfter time.Duration
MaxMessageSize int
}
ProcessConfig holds process management settings.
type ProvidesAuthConfig ¶
type ProvidesAuthConfig struct {
Type string `yaml:"type"`
Description string `yaml:"description"`
}
ProvidesAuthConfig describes a plugin-provided auth type.
type ProvidesConfig ¶
type ProvidesConfig struct {
Auth *ProvidesAuthConfig `yaml:"auth"`
Resources bool `yaml:"resources"`
}
ProvidesConfig declares what services a plugin provides.
type ServiceConfig ¶
type ServiceConfig struct {
Auth AuthServiceConfig `yaml:"auth"`
HTTP HTTPServiceConfig `yaml:"http"`
Cache CacheServiceConfig `yaml:"cache"`
}
ServiceConfig declares what services a plugin requires.
type ServiceHandler ¶
type ServiceHandler interface {
HandleHTTP(ctx context.Context, pluginName string, req protocol.Message) protocol.Message
HandleCache(ctx context.Context, pluginName string, req protocol.Message) protocol.Message
}
ServiceHandler handles service requests from plugins. Implemented by the proxy and cache subsystems.
type SetupConfig ¶
type SetupConfig struct {
Credentials map[string]CredentialMeta `yaml:"credentials"`
Variants map[string]SetupVariant `yaml:"variants"`
ValidationTool string `yaml:"validation_tool"`
PostSetupMessage string `yaml:"post_setup_message"`
}
SetupConfig holds human-facing metadata for configuration wizards. The core parses it but does not act on it — consumed by CLI tools.
type SetupVariant ¶
type SetupVariant struct {
Label string `yaml:"label"`
Description string `yaml:"description"`
Required []string `yaml:"required"`
}
SetupVariant adds human-facing labels to auth variants.
type TLSConfig ¶ added in v0.1.4
type TLSConfig struct {
CACert string `yaml:"ca_cert"`
ClientCert string `yaml:"client_cert"`
ClientKey string `yaml:"client_key"`
SkipHostnameVerify bool `yaml:"skip_hostname_verify"`
// CACertPEM holds the pre-loaded CA cert bytes (set at load time,
// not from YAML). Prevents TOCTOU between validation and use.
CACertPEM []byte `yaml:"-"`
}
TLSConfig declares per-plugin TLS settings for custom CAs and mTLS.
type ToolDef ¶
type ToolDef struct {
Name string `yaml:"name"`
Description string `yaml:"description"`
Access string `yaml:"access"` // "read" or "write" (default: "write")
Visibility string `yaml:"visibility"` // "primary" or "deferred" (default: "deferred")
Params map[string]ParamDef `yaml:"params"`
}
ToolDef declares an MCP tool with its parameter schema. ToolDef describes a single tool exposed by a plugin.
func (ToolDef) IsPrimary ¶ added in v0.1.4
IsPrimary returns true if the tool should be registered without the defer_loading flag. Tools default to deferred.
func (ToolDef) IsReadOnly ¶ added in v0.1.2
IsReadOnly returns true if the tool is declared as read-only (no side effects).
func (*ToolDef) ParamsSchema ¶
ParamsSchema converts the tool's parameter definitions to JSON Schema as required by the MCP spec.
type Transport ¶
type Transport struct {
// contains filtered or unexported fields
}
Transport manages bidirectional JSON-lines communication with a plugin process over stdin/stdout.
func NewTransport ¶
NewTransport creates a Transport for communicating with a plugin process.
func (*Transport) ForwardStderr ¶
ForwardStderr reads the plugin's stderr and logs it with a prefix.
func (*Transport) GenerateID ¶
GenerateID returns a unique message ID for service requests.
func (*Transport) ReadLoop ¶
func (t *Transport) ReadLoop(pluginName string, concurrency int, serviceHandler ServiceHandler)
ReadLoop reads messages from the plugin's stdout and routes them.
For concurrency <= 1, service requests (http_request, cache_*) are handled synchronously — no goroutines, no race conditions. This guarantees that sequential plugins can use simple blocking read/write loops.
For concurrency > 1, service requests are handled in goroutines.
The handler functions are provided by the caller (proxy and cache).
func (*Transport) Send ¶
Send writes a JSON message to the plugin's stdin. Thread-safe: serializes writes via mutex to guarantee atomic lines.
func (*Transport) SendAndWait ¶
func (t *Transport) SendAndWait(ctx context.Context, id string, msg protocol.Message) (protocol.Message, error)
SendAndWait sends a message and waits for a response with the same ID. The response is routed by ReadLoop. The context controls the maximum wait time — if the context is cancelled or its deadline expires, SendAndWait returns immediately with the context error.
func (*Transport) SetToolContext ¶ added in v0.1.5
SetToolContext sets the current tool call's context so ReadLoop can use it for service requests (HTTP, cache). Cleared by the caller when the tool call completes or times out. The deferred cancel() from the tool call's context.WithTimeout propagates cancellation to any in-flight HTTP request, unblocking ReadLoop.
func (*Transport) ToolContext ¶ added in v0.1.5
ToolContext returns the current tool call context, or context.Background() if none is set (e.g., during plugin init).