mcp

package
v2.5.2 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2026 License: Apache-2.0 Imports: 32 Imported by: 0

Documentation

Overview

Package mcp implements Dynamic Client Registration Protocol (RFC 7591)

Package mcp provides a client for the Model Control Protocol (MCP) that allows the AI plugin to access external tools provided by MCP servers.

The UserClients represents a single user's connection to multiple MCP servers. The Client represents a connection to a single MCP server. The UserClients currently only supports authentication via Mattermost user ID header X-Mattermost-UserID. In the future it will support our OAuth implementation.

The ClientManager manages multiple UserClients, allowing for efficient mangement of connections. It is responsible for creating and closing UserClients as needed.

The organization reflects the need for each user to have their own connection to the MCP server given the design of MCP.

Index

Constants

View Source
const (
	MMUserIDHeader     = "X-Mattermost-UserID"
	EmbeddedServerName = "Mattermost"
	EmbeddedClientKey  = "embedded://mattermost"

	ToolPolicyAsk               = config.MCPToolPolicyAsk
	ToolPolicyAutoRunInDM       = config.MCPToolPolicyAutoRunInDM
	ToolPolicyAutoRunEverywhere = config.MCPToolPolicyAutoRunEverywhere
)
View Source
const (
	SearchToolsName = "search_tools"
	LoadToolName    = "load_tool"
)
View Source
const (
	UserPreferencesMaxRequestBodyBytes = 256 << 10 // 256 KiB HTTP body cap for PUT /mcp/user-preferences
	UserPreferencesMaxDisabledServers  = 256
	UserPreferencesMaxServerEntryLen   = 512 // max runes per disabled server identifier
)

Limits for persisted user MCP provider preferences (stored in the plugin KV store). Mattermost's PluginKeyValue.IsValid does not cap value size; these bounds keep requests and stored JSON small and predictable (see model.PluginKeyValue in mattermost/server/public).

View Source
const (
	BeforeHookKeyTTL = 30 * time.Minute
)
View Source
const DefaultMCPToolSearchLimit = 8

Variables

View Source
var (
	ErrBeforeHookKeyNotFound   = errors.New("before-hook key not found")
	ErrInvalidBeforeHookConfig = errors.New("invalid before-hook config")
)
View Source
var ErrOAuthNotConfigured = errors.New("oauth not configured")
View Source
var ErrUserPreferencesInvalid = errors.New("invalid user preferences")

ErrUserPreferencesInvalid indicates normalized preferences violate size or count limits.

Functions

func GetRegistrationEndpoint

func GetRegistrationEndpoint(ctx context.Context, httpClient *http.Client, serverURL string) (string, error)

GetRegistrationEndpoint discovers the registration endpoint from server metadata

func IsMCPMetaTool

func IsMCPMetaTool(name string) bool

func IsRemoteServerOrigin

func IsRemoteServerOrigin(origin string) bool

IsRemoteServerOrigin reports whether an MCP server origin points at a remote/external server. Built-in tools carry an empty origin and the embedded Mattermost server uses EmbeddedClientKey; neither counts as remote. Every other origin — remote HTTP servers and plugin-registered servers — belongs to the licensed "MCP Support" feature.

func IsToolPolicyAutoRunEverywhere

func IsToolPolicyAutoRunEverywhere(policy string) bool

func IsToolPolicyAutoRunInDM

func IsToolPolicyAutoRunInDM(policy string) bool

func IsVettedHost

func IsVettedHost(baseURL string) bool

IsVettedHost returns true when the baseURL host matches one of the Mattermost-curated vetted MCP server hosts.

Matching semantics intentionally preserve the previous approved-server behavior: - host-only matching - path/query/fragment/port ignored - exact host or subdomain match - supports embedded://mattermost

func LookupToolPolicy

func LookupToolPolicy(cfg Config, serverBaseURL, toolName string) (string, bool)

LookupToolPolicy resolves a tool's policy for embedded, remote, and plugin origins. Unknown or disabled origins never auto-execute.

func NewMetaTools

func NewMetaTools(registry *ToolRegistry) []llm.Tool

func ToolPolicyLookupName

func ToolPolicyLookupName(sc *ServerConfig, toolName string) string

ToolPolicyLookupName returns the configured name to use for a runtime tool name. Runtime MCP tools may be namespaced while persisted policy config is usually stored by the server's bare tool name. An exact configured name still wins.

func ToolRetrievalOverrideKey

func ToolRetrievalOverrideKey(serverOrigin, toolName string) string

func UnloadedMCPToolUserHint

func UnloadedMCPToolUserHint(name string) string

UnloadedMCPToolUserHint returns the canonical message returned to the LLM when it tries to call an MCP tool that is visible in the registry but has not yet been loaded into the active tool store. Callers that surface this to the model should reuse this helper so the wording (and the suggested load_tool invocation) stays consistent across entry points.

func ValidateResourceMetadataMatchesServerBaseURL

func ValidateResourceMetadataMatchesServerBaseURL(serverBaseURL, metadataURL string) error

ValidateResourceMetadataMatchesServerBaseURL ensures resource_metadata is on the same origin as the admin-configured MCP server BaseURL (scheme + host + port). metadataURL must be non-empty; callers should skip when empty.

func ValidateResourceMetadataURL

func ValidateResourceMetadataURL(metadataURL string) error

ValidateResourceMetadataURL validates a resource_metadata URL from an OAuth challenge or from the MCP OAuth start redirect query string.

func ValidateUserPreferencesNormalized

func ValidateUserPreferencesNormalized(prefs *UserToolProviderPreferences) error

ValidateUserPreferencesNormalized returns an error if normalized preferences exceed storage limits.

Types

type AuthorizationServerMetadata

type AuthorizationServerMetadata struct {
	Issuer                 string   `json:"issuer"`
	AuthorizationEndpoint  string   `json:"authorization_endpoint"`
	TokenEndpoint          string   `json:"token_endpoint"`
	ResponseTypesSupported []string `json:"response_types_supported"`
	GrantTypesSupported    []string `json:"grant_types_supported,omitempty"`
	ScopesSupported        []string `json:"scopes_supported,omitempty"`
	RegistrationEndpoint   string   `json:"registration_endpoint,omitempty"`
}

AuthorizationServerMetadata represents the OAuth 2.0 Authorization Server Metadata (RFC 8414)

type BM25Document

type BM25Document struct {
	ID   string
	Text string
}

type BM25Index

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

func NewBM25Index

func NewBM25Index(docs []BM25Document) *BM25Index

func (*BM25Index) Search

func (idx *BM25Index) Search(query string, limit int) []BM25Result

type BM25Result

type BM25Result struct {
	ID    string
	Score float64
}

type BeforeHookEntry

type BeforeHookEntry struct {
	UserID      string `json:"user_id"`
	ToolName    string `json:"tool_name"`
	CallbackURL string `json:"callback_url"`
}

BeforeHookEntry is the trusted callback target stored for a short-lived hook key.

type BeforeHookStore

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

BeforeHookStore owns short-lived before-hook key persistence.

func NewBeforeHookStore

func NewBeforeHookStore(kv KVStore) *BeforeHookStore

NewBeforeHookStore creates a store for short-lived before-hook keys.

func (*BeforeHookStore) Delete

func (s *BeforeHookStore) Delete(hookKey string) error

Delete removes a before-hook key. It is used for best-effort cleanup once a bridge request completes; TTL remains the fallback for interrupted requests.

func (*BeforeHookStore) Issue

func (s *BeforeHookStore) Issue(userID, toolName, pluginID, beforeCallback string) (string, error)

Issue stores a trusted callback endpoint and returns an opaque key bound to the user and tool.

func (*BeforeHookStore) Resolve

func (s *BeforeHookStore) Resolve(userID, toolName, hookKey string) (BeforeHookEntry, error)

Resolve returns a trusted callback URL for a key bound to userID and toolName. The key remains valid until its KV TTL expires so a single bridge run can call the same tool more than once.

type CachedTools

type CachedTools struct {
	Tools      map[string]*mcp.Tool `json:"tools"`
	Timestamp  time.Time            `json:"timestamp"`
	ServerURL  string               `json:"server_url"`
	ServerName string               `json:"server_name"`
}

CachedTools represents a cached set of tools for a specific MCP server

type Client

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

Client represents the connection to a single MCP server

func NewClient

func NewClient(ctx context.Context, userID string, serverConfig ServerConfig, log pluginapi.LogService, oauthManager *OAuthManager, httpClient *http.Client, toolsCache *ToolsCache, forceRefresh bool) (*Client, error)

NewClient creates a new MCP client for the given server and user and connects to the specified MCP server. forceRefresh bypasses the shared tools cache read. Its sole purpose is to close the race where a concurrent lookup repopulates the cache between a manual refresh's invalidation and this reconnect; a plain post-invalidation rediscovery would otherwise cache-miss on its own.

func NewPluginClient

func NewPluginClient(ctx context.Context, userID string, cfg PluginServerConfig, sourcePluginAPI mmapi.Client, log pluginapi.LogService) (*Client, error)

NewPluginClient creates a per-user MCP client for a plugin-registered server. Plugin clients list tools at connect time and do not use the shared tools cache.

func (*Client) CallTool

func (c *Client) CallTool(ctx context.Context, toolName string, args map[string]any) (string, error)

CallTool calls a tool on this MCP server

func (*Client) CallToolWithMetadata

func (c *Client) CallToolWithMetadata(ctx context.Context, toolName string, args map[string]any, metadata map[string]any) (string, error)

CallToolWithMetadata calls a tool on this MCP server with optional metadata

func (*Client) Close

func (c *Client) Close() error

Close closes the connection to the MCP server

func (*Client) Tools

func (c *Client) Tools() map[string]*mcp.Tool

Tools returns the tools available from this client

type ClientCredentials

type ClientCredentials struct {
	ClientID     string    `json:"clientID"`
	ClientSecret string    `json:"clientSecret"`
	ServerURL    string    `json:"serverURL"`
	CreatedAt    time.Time `json:"createdAt"`
}

type ClientManager

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

ClientManager manages MCP clients for multiple users

func NewClientManager

func NewClientManager(config Config, log pluginapi.LogService, pluginAPI *pluginapi.Client, oauthManager *OAuthManager, embeddedServer EmbeddedMCPServer, httpClient *http.Client, sourcePluginAPI mmapi.Client) *ClientManager

NewClientManager creates a new MCP client manager. embeddedServer may be nil. sourcePluginAPI routes PluginHTTP to source plugins; may be nil.

func (*ClientManager) Close

func (m *ClientManager) Close()

Close closes the client manager and all managed clients The client manger should not be used after Close is called

func (*ClientManager) DisconnectUserOAuth

func (m *ClientManager) DisconnectUserOAuth(userID, serverName string) error

DisconnectUserOAuth removes the stored OAuth token for a user and server, and invalidates the cached MCP client so a fresh connection is established on the next request.

func (*ClientManager) DiscoverPluginServerTools

func (m *ClientManager) DiscoverPluginServerTools(ctx context.Context, userID string, cfg PluginServerConfig) ([]ToolInfo, error)

func (*ClientManager) EnsureMCPSessionID

func (m *ClientManager) EnsureMCPSessionID(userID string) (string, error)

EnsureMCPSessionID ensures there is a valid MCP session for the user This is used by both embedded and HTTP MCP servers to get a dedicated session

func (*ClientManager) GetConfig

func (m *ClientManager) GetConfig() Config

GetConfig returns a snapshot of the current MCP configuration.

func (*ClientManager) GetEmbeddedServer

func (m *ClientManager) GetEmbeddedServer() EmbeddedMCPServer

GetEmbeddedServer returns the embedded MCP server instance (may be nil) This method is kept for API compatibility

func (*ClientManager) GetHTTPClient

func (m *ClientManager) GetHTTPClient() *http.Client

GetHTTPClient returns the HTTP client for upstream requests

func (*ClientManager) GetOAuthManager

func (m *ClientManager) GetOAuthManager() *OAuthManager

GetOAuthManager returns the OAuth manager instance

func (*ClientManager) GetPluginServer

func (m *ClientManager) GetPluginServer(pluginID string) (PluginServerConfig, bool)

GetPluginServer returns a value-copy of the stored config for pluginID.

func (*ClientManager) GetToolRetrievalOverrides

func (m *ClientManager) GetToolRetrievalOverrides() map[string]ToolRetrievalOverride

func (*ClientManager) GetToolsCache

func (m *ClientManager) GetToolsCache() *ToolsCache

GetToolsCache returns the tools cache instance

func (*ClientManager) GetToolsForUser

func (m *ClientManager) GetToolsForUser(ctx context.Context, userID string) ([]llm.Tool, *Errors)

GetToolsForUser returns the tools available for a specific user, connecting to embedded server if session ID provided.

func (*ClientManager) InvalidateUserClients

func (m *ClientManager) InvalidateUserClients(userID string)

InvalidateUserClients closes and removes cached MCP clients for a user.

func (*ClientManager) IsPluginRegistered

func (m *ClientManager) IsPluginRegistered(pluginID string) bool

IsPluginRegistered reports whether the source plugin currently has a live in-process registration. Returns false for entries hydrated only from persisted config.

func (*ClientManager) ListPluginServers

func (m *ClientManager) ListPluginServers() []PluginServerConfig

func (*ClientManager) MarkOAuthNeeded

func (m *ClientManager) MarkOAuthNeeded(userID, serverName, authURL string) error

MarkOAuthNeeded stores the latest upstream OAuth-needed state for a user/server and drops any cached client so subsequent tool discovery reflects the reconnectable state.

func (*ClientManager) ProcessOAuthCallback

func (m *ClientManager) ProcessOAuthCallback(ctx context.Context, userID, state, code string) (*OAuthSession, error)

ProcessOAuthCallback processes the OAuth callback for a user

func (*ClientManager) ReInit

func (m *ClientManager) ReInit(config Config, embeddedServer EmbeddedMCPServer)

ReInit re-initializes the client manager with a new configuration and embedded server

func (*ClientManager) RefreshToolsForUser

func (m *ClientManager) RefreshToolsForUser(ctx context.Context, userID string) ([]llm.Tool, *Errors, error)

RefreshToolsForUser drops cached user clients and shared server tool lists, pre-warms a fresh user client, then delegates to GetToolsForUser for the embedded/plugin connect + filtering it shares with the normal lookup path.

func (*ClientManager) RegisterPluginServer

func (m *ClientManager) RegisterPluginServer(cfg PluginServerConfig)

RegisterPluginServer stores or overwrites a plugin-server registration. Callers must ensure cfg.PluginID is non-empty.

func (*ClientManager) UnregisterPluginServer

func (m *ClientManager) UnregisterPluginServer(pluginID string)

type Config

type Config = config.MCPConfig

Type aliases for MCP config types, which are defined in the config package to avoid circular imports. Existing callers can continue to use mcp.Config, etc.

type EmbeddedMCPServer

type EmbeddedMCPServer interface {
	CreateClientTransport(userID, sessionID string, pluginAPI *pluginapi.Client) (*mcp.InMemoryTransport, error)
}

EmbeddedMCPServer interface for dependency injection

type EmbeddedServerClient

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

EmbeddedServerClient handles connections to the embedded MCP server

func NewEmbeddedServerClient

func NewEmbeddedServerClient(server EmbeddedMCPServer, log pluginapi.LogService, pluginAPI *pluginapi.Client) *EmbeddedServerClient

func NewEmbeddedServerClientWithCache

func NewEmbeddedServerClientWithCache(server EmbeddedMCPServer, log pluginapi.LogService, pluginAPI *pluginapi.Client, toolsCache *ToolsCache) *EmbeddedServerClient

NewEmbeddedServerClientWithCache is the same as NewEmbeddedServerClient but also wires up a shared tools cache. Pass a non-nil cache when callers want per-user tool listings to be cached across requests.

func (*EmbeddedServerClient) CreateClient

func (c *EmbeddedServerClient) CreateClient(ctx context.Context, userID, sessionID string) (*Client, error)

CreateClient creates an embedded MCP client using session ID for authentication. If sessionID is empty, creates an unauthenticated client (used for tool discovery).

type EmbeddedServerConfig

type EmbeddedServerConfig = config.MCPEmbeddedServerConfig

type Errors

type Errors struct {
	ToolAuthErrors []llm.ToolAuthError // Authentication errors users need to resolve
	Errors         []error             // Generic errors (connection, config, etc.)
}

Errors represents a collection of errors from MCP operations.

type KVStore

type KVStore interface {
	Get(key string, o any) error
	Set(key string, value any, options ...pluginapi.KVSetOption) (bool, error)
	Delete(key string) error
	ListKeys(page, count int, options ...pluginapi.ListKeysOption) ([]string, error)
}

KVStore interface for key-value operations

type LoadToolArgs

type LoadToolArgs struct {
	Name string `json:"name" jsonschema:"Exact namespaced MCP tool name to load,minLength=1"`
}

type LoadToolResult

type LoadToolResult struct {
	Loaded  bool                    `json:"loaded"`
	Name    string                  `json:"name,omitempty"`
	Schema  any                     `json:"schema,omitempty"`
	Matches []SearchToolsResultItem `json:"matches,omitempty"`
	Error   string                  `json:"error,omitempty"`
}

type Logger

type Logger interface {
	Debug(msg string, keyValuePairs ...interface{})
	Info(msg string, keyValuePairs ...interface{})
	Warn(msg string, keyValuePairs ...interface{})
	Error(msg string, keyValuePairs ...interface{})
}

Logger interface for logging operations

type OAuthManager

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

func NewOAuthManager

func NewOAuthManager(pluginAPI mmapi.Client, callbackURL string, httpClient *http.Client, serverConfigLookup ServerConfigLookup) *OAuthManager

func (*OAuthManager) DeleteAuthNeededState

func (m *OAuthManager) DeleteAuthNeededState(userID, serverID string) error

func (*OAuthManager) DeleteUserToken

func (m *OAuthManager) DeleteUserToken(userID, serverID string) error

DeleteUserToken removes the stored OAuth token for a user and server, effectively disconnecting the user from that MCP server.

func (*OAuthManager) HasStoredToken

func (m *OAuthManager) HasStoredToken(userID, serverID string) (bool, error)

HasStoredToken returns true when a non-expired OAuth token exists for the given user and server. It does not refresh the token or contact upstream.

func (*OAuthManager) InitiateOAuthFlow

func (m *OAuthManager) InitiateOAuthFlow(ctx context.Context, userID, serverID, serverURL, metadataURL string, staticCreds *StaticOAuthCredentials) (string, error)

func (*OAuthManager) InitiateOAuthFlowForServer

func (m *OAuthManager) InitiateOAuthFlowForServer(ctx context.Context, userID string, serverConfig ServerConfig) (string, error)

func (*OAuthManager) InitiateOAuthFlowForServerWithMetadata

func (m *OAuthManager) InitiateOAuthFlowForServerWithMetadata(ctx context.Context, userID string, serverConfig ServerConfig, metadataURL string) (string, error)

InitiateOAuthFlowForServerWithMetadata starts OAuth like InitiateOAuthFlowForServer but passes resource_metadata from the upstream 401 when present (RFC 9728).

func (*OAuthManager) LoadAuthNeededState

func (m *OAuthManager) LoadAuthNeededState(userID, serverID string) (*OAuthNeededState, error)

func (*OAuthManager) ProcessCallback

func (m *OAuthManager) ProcessCallback(ctx context.Context, loggedInUserID, state, code string) (*OAuthSession, error)

func (*OAuthManager) StartURL

func (m *OAuthManager) StartURL(serverID string) string

func (*OAuthManager) StoreAuthNeededState

func (m *OAuthManager) StoreAuthNeededState(userID, serverID, authURL string) error

type OAuthNeededError

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

func (*OAuthNeededError) AuthURL

func (e *OAuthNeededError) AuthURL() string

func (*OAuthNeededError) Error

func (e *OAuthNeededError) Error() string

func (*OAuthNeededError) MetadataURL

func (e *OAuthNeededError) MetadataURL() string

MetadataURL returns the RFC 9728 resource_metadata URL from the upstream 401 challenge when known (may be empty).

func (*OAuthNeededError) Unwrap

func (e *OAuthNeededError) Unwrap() error

type OAuthNeededState

type OAuthNeededState struct {
	AuthURL string    `json:"authURL"`
	SeenAt  time.Time `json:"seenAt"`
}

type OAuthSession

type OAuthSession struct {
	UserID            string    `json:"userID"`
	ServerID          string    `json:"serverID"`
	ServerURL         string    `json:"serverURL"`
	ServerMetadataURL string    `json:"serverMetadataURL"`
	CodeVerifier      string    `json:"codeVerifier"`
	State             string    `json:"state"`
	StaticClientID    string    `json:"staticClientID,omitempty"`
	CreatedAt         time.Time `json:"createdAt"`
}

type PluginHTTPRoundTripper

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

PluginHTTPRoundTripper routes requests to a source plugin's MCP endpoint via PluginHTTP. Callers layer user headers above it.

func NewPluginHTTPRoundTripper

func NewPluginHTTPRoundTripper(pluginID, basePath string, pluginAPI mmapi.Client) *PluginHTTPRoundTripper

NewPluginHTTPRoundTripper constructs a PluginHTTP-based transport for a source plugin MCP endpoint.

func (*PluginHTTPRoundTripper) RoundTrip

func (p *PluginHTTPRoundTripper) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip rewrites req.URL.Path to "/{pluginID}{basePath}", the path PluginHTTP dispatches on.

type PluginServerConfig

type PluginServerConfig = config.PluginServerConfig

type ProtectedResourceMetadata

type ProtectedResourceMetadata struct {
	Resource             string   `json:"resource"`
	AuthorizationServers []string `json:"authorization_servers"`
	ScopesSupported      []string `json:"scopes_supported,omitempty"`
}

ProtectedResourceMetadata represents the OAuth 2.0 Protected Resource Metadata (RFC 9728)

type RegistrationError

type RegistrationError struct {
	ErrorCode        string         `json:"error"`
	ErrorDescription string         `json:"error_description,omitempty"`
	HTTPStatusCode   int            `json:"-"`
	HTTPResponse     *http.Response `json:"-"`
}

RegistrationError represents an error response per RFC 7591

func (*RegistrationError) Error

func (e *RegistrationError) Error() string

type RegistrationRequest

type RegistrationRequest struct {
	// Required fields
	RedirectURIs []string `json:"redirect_uris"`

	// Optional fields commonly used
	TokenEndpointAuthMethod string   `json:"token_endpoint_auth_method,omitempty"`
	GrantTypes              []string `json:"grant_types,omitempty"`
	ResponseTypes           []string `json:"response_types,omitempty"`
	ClientName              string   `json:"client_name,omitempty"`
	Scope                   string   `json:"scope,omitempty"`
	Contacts                []string `json:"contacts,omitempty"`

	// Additional optional fields can be added as needed
	ClientURI string `json:"client_uri,omitempty"`
	LogoURI   string `json:"logo_uri,omitempty"`
	ToSURI    string `json:"tos_uri,omitempty"`
	PolicyURI string `json:"policy_uri,omitempty"`
}

RegistrationRequest represents a client registration request per RFC 7591

func DefaultRegistrationRequest

func DefaultRegistrationRequest(redirectURI, clientName string) *RegistrationRequest

DefaultRegistrationRequest creates a default registration request for MCP clients

type RegistrationResponse

type RegistrationResponse struct {
	// Required fields
	ClientID string `json:"client_id"`

	// Optional fields
	ClientSecret          string `json:"client_secret,omitempty"`
	ClientIDIssuedAt      *int64 `json:"client_id_issued_at,omitempty"`
	ClientSecretExpiresAt *int64 `json:"client_secret_expires_at,omitempty"`

	// Echo back the registration metadata
	RedirectURIs            []string `json:"redirect_uris,omitempty"`
	TokenEndpointAuthMethod string   `json:"token_endpoint_auth_method,omitempty"`
	GrantTypes              []string `json:"grant_types,omitempty"`
	ResponseTypes           []string `json:"response_types,omitempty"`
	ClientName              string   `json:"client_name,omitempty"`
	Scope                   string   `json:"scope,omitempty"`
	Contacts                []string `json:"contacts,omitempty"`
	ClientURI               string   `json:"client_uri,omitempty"`
	LogoURI                 string   `json:"logo_uri,omitempty"`
	ToSURI                  string   `json:"tos_uri,omitempty"`
	PolicyURI               string   `json:"policy_uri,omitempty"`
}

RegistrationResponse represents the server's response per RFC 7591

func DiscoverAndRegisterClient

func DiscoverAndRegisterClient(ctx context.Context, httpClient *http.Client, serverURL, callbackURL, clientID, initialAccessToken string) (*RegistrationResponse, error)

DiscoverAndRegisterClient performs the complete client registration flow: 1. Discovers the registration endpoint from server metadata 2. Creates a default registration request 3. Registers the client with the server

func RegisterClient

func RegisterClient(ctx context.Context, httpClient *http.Client, registrationEndpoint string, request *RegistrationRequest, initialAccessToken string) (*RegistrationResponse, error)

RegisterClient performs dynamic client registration per RFC 7591

type SearchToolsArgs

type SearchToolsArgs struct {
	Query string `json:"query" jsonschema:"Search query for finding available MCP tools,minLength=1"`
}

type SearchToolsResult

type SearchToolsResult struct {
	Tools []SearchToolsResultItem `json:"tools"`
}

type SearchToolsResultItem

type SearchToolsResultItem struct {
	Name    string `json:"name"`
	Summary string `json:"summary"`
}

type ServerConfig

type ServerConfig = config.MCPServerConfig

type ServerConfigLookup

type ServerConfigLookup func(serverID string) (ServerConfig, bool)

ServerConfigLookup resolves a server's current configuration by its ID. It returns the config and true if found, or a zero value and false if not.

type StaticOAuthCredentials

type StaticOAuthCredentials struct {
	ClientID     string
	ClientSecret string
}

StaticOAuthCredentials holds pre-configured OAuth client credentials from server config. When set, these bypass Dynamic Client Registration (RFC 7591) for providers that require a pre-registered OAuth application.

type ToolConfig

type ToolConfig = config.MCPToolConfig

func SeedVettedToolConfigs

func SeedVettedToolConfigs(baseURL string) []ToolConfig

SeedVettedToolConfigs returns one-time seed tool configs for vetted MCP hosts.

Only Mattermost-curated READ-only tools are seeded. Most are enabled with policy auto_run_in_dm; GitHub security-scanning reads default to policy ask (admins may switch). Non-READ tools are intentionally not persisted here; tools without config fall back to the runtime default of policy="ask", enabled=true until an admin explicitly configures them.

type ToolInfo

type ToolInfo struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	InputSchema any    `json:"inputSchema"`
}

ToolInfo represents a tool's metadata for discovery purposes

func DiscoverEmbeddedServerTools

func DiscoverEmbeddedServerTools(
	ctx context.Context,
	userID string,
	sessionID string,
	embeddedServerConfig EmbeddedServerConfig,
	embeddedServer EmbeddedMCPServer,
	log pluginapi.LogService,
	pluginAPI *pluginapi.Client,
) ([]ToolInfo, error)

DiscoverEmbeddedServerTools creates a temporary connection to an embedded MCP server and discovers its tools

func DiscoverPluginServerTools

func DiscoverPluginServerTools(
	ctx context.Context,
	userID string,
	cfg PluginServerConfig,
	sourcePluginAPI mmapi.Client,
	log pluginapi.LogService,
) ([]ToolInfo, error)

DiscoverPluginServerTools lists tools from a plugin-registered MCP server over PluginHTTP, bypassing the per-user client cache.

func DiscoverRemoteServerTools

func DiscoverRemoteServerTools(
	ctx context.Context,
	userID string,
	serverConfig ServerConfig,
	log pluginapi.LogService,
	oauthManger *OAuthManager,
	httpClient *http.Client,
	toolsCache *ToolsCache,
) ([]ToolInfo, error)

DiscoverRemoteServerTools creates a temporary connection to a remote MCP server and discovers its tools

type ToolPolicyChecker

type ToolPolicyChecker interface {
	GetToolPolicy(serverBaseURL string, toolName string) (policy string, enabled bool)
}

ToolPolicyChecker looks up the per-tool policy for a given MCP server/tool.

type ToolPolicyFunc

type ToolPolicyFunc func(serverBaseURL string, toolName string) (string, bool)

ToolPolicyFunc is a function adapter that implements ToolPolicyChecker.

func (ToolPolicyFunc) GetToolPolicy

func (f ToolPolicyFunc) GetToolPolicy(serverBaseURL string, toolName string) (string, bool)

GetToolPolicy implements ToolPolicyChecker.

type ToolRegistry

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

func NewToolRegistry

func NewToolRegistry(tools []llm.Tool, opts ...ToolRegistryOption) *ToolRegistry

func (*ToolRegistry) ClosestMatches

func (r *ToolRegistry) ClosestMatches(name string, limit int) []ToolSearchResult

func (*ToolRegistry) Len

func (r *ToolRegistry) Len() int

func (*ToolRegistry) List

func (r *ToolRegistry) List() []ToolRegistryEntry

func (*ToolRegistry) Lookup

func (r *ToolRegistry) Lookup(name string) (ToolRegistryEntry, bool)

func (*ToolRegistry) Search

func (r *ToolRegistry) Search(query string, limit int) []ToolSearchResult

type ToolRegistryEntry

type ToolRegistryEntry struct {
	Tool             llm.Tool
	Name             string
	BareName         string
	ServerOrigin     string
	RetrievalSummary string
}

type ToolRegistryOption

type ToolRegistryOption func(*toolRegistryOptions)

func WithToolRetrievalOverrides

func WithToolRetrievalOverrides(overrides map[string]ToolRetrievalOverride) ToolRegistryOption

type ToolRetrievalOverride

type ToolRetrievalOverride struct {
	Summary string
}

type ToolSearchResult

type ToolSearchResult struct {
	Name    string
	Summary string
	Score   float64
}

type ToolsCache

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

ToolsCache manages the global cache of MCP tools across all users It uses the KV store directly for HA mode compatibility

func NewToolsCache

func NewToolsCache(kvAPI KVStore, log Logger) *ToolsCache

NewToolsCache creates a new ToolsCache instance

func (*ToolsCache) ClearAll

func (tc *ToolsCache) ClearAll() (int, error)

ClearAll removes all cached tools from KV store

func (*ToolsCache) GetTools

func (tc *ToolsCache) GetTools(serverID string) map[string]*mcp.Tool

GetTools retrieves cached tools for a server, returns nil if missing

func (*ToolsCache) InvalidateServer

func (tc *ToolsCache) InvalidateServer(serverID string) error

InvalidateServer removes a server's cache entry from KV store Delete returns no error for non-existent keys, only errors on actual failures

func (*ToolsCache) SetTools

func (tc *ToolsCache) SetTools(serverID string, serverName string, serverURL string, tools map[string]*mcp.Tool, timestamp time.Time) error

SetTools updates the cache for a server and persists to KV store

type UserClients

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

UserClients represents a per-user MCP client with multiple server connections

func NewUserClients

func NewUserClients(userID string, log pluginapi.LogService, oauthManager *OAuthManager, httpClient *http.Client, toolsCache *ToolsCache) *UserClients

func (*UserClients) Close

func (c *UserClients) Close()

Close closes all server connections for a user client

func (*UserClients) ConnectToEmbeddedServerIfAvailable

func (c *UserClients) ConnectToEmbeddedServerIfAvailable(ctx context.Context, sessionID string, embeddedClient *EmbeddedServerClient, embeddedConfig EmbeddedServerConfig) error

ConnectToEmbeddedServerIfAvailable connects to the embedded server if session ID is provided. If a connection already exists, it is reused.

func (*UserClients) ConnectToPluginServer

func (c *UserClients) ConnectToPluginServer(ctx context.Context, cfg PluginServerConfig, sourcePluginAPI mmapi.Client) error

ConnectToPluginServer establishes a cached MCP session with a source plugin over PluginHTTP, injecting X-Mattermost-UserID. Plugin servers use inter-plugin auth, not user OAuth.

func (*UserClients) ConnectToRemoteServers

func (c *UserClients) ConnectToRemoteServers(ctx context.Context, servers []ServerConfig, forceRefresh bool) *Errors

ConnectToRemoteServers initializes connections to remote MCP servers.

func (*UserClients) GetTools

func (c *UserClients) GetTools(ctx context.Context) []llm.Tool

GetTools returns the tools available from the clients

func (*UserClients) InitialRemoteConnectErrors

func (c *UserClients) InitialRemoteConnectErrors() *Errors

type UserToolProviderPreferences

type UserToolProviderPreferences struct {
	DisabledServers []string `json:"disabled_servers"`
}

UserToolProviderPreferences stores per-user provider toggle state.

func LoadUserPreferences

func LoadUserPreferences(pluginAPI mmapi.Client, userID string) (*UserToolProviderPreferences, error)

LoadUserPreferences loads the user's tool provider preferences from KV. Returns a default (empty disabled list) when no entry exists.

func SaveUserPreferences

func SaveUserPreferences(pluginAPI mmapi.Client, userID string, prefs *UserToolProviderPreferences) (*UserToolProviderPreferences, error)

SaveUserPreferences normalizes and persists the user's tool provider preferences.

Jump to

Keyboard shortcuts

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