Documentation
¶
Overview ¶
Package runtime provides OAuth discovery and authorization URL handling for MCP servers.
OAuth Discovery Implementation Gap in MCP Ecosystem:
While the MCP Specification technically describes using /.well-known/oauth-protected-resource for discovery (RFC 9728, see https://www.speakeasy.com/mcp/building-servers/state-of-oauth-in-mcp), most current MCP servers actually look for /.well-known/oauth-authorization-server directly at the MCP server's domain (RFC 8414). This is how the OAuth dance works in practice today. The gap between specification and implementation is prevalent in the MCP ecosystem.
The mcp-go oauthHandler.GetAuthorizationURL doesn't handle this correctly and follows only the strict RFC 9728 path, which fails with most real-world MCP servers. While waiting for this PR https://github.com/mark3labs/mcp-go/pull/581 to fix the upstream discovery logic, we need a workaround that implements the correct discovery sequence that actually works with existing MCP servers.
This implementation bridges the gap by:
- First trying the RFC 9728 approach (/.well-known/oauth-protected-resource)
- Falling back to the RFC 8414 approach (/.well-known/oauth-authorization-server) which is what most MCP servers actually implement
- Providing sensible defaults as a final fallback
This ensures compatibility with both specification-compliant servers and the majority of existing MCP server implementations that follow the more common OAuth patterns.
Index ¶
- func DecodeSessionIDFromState(state string) (string, error)
- func GetAuthorizationURL(ctx context.Context, oauthHandler *transport.OAuthHandler, ...) (string, error)
- type AgentChoiceEvent
- type AgentChoiceReasoningEvent
- type AgentContext
- type AuthServerMetadata
- type AuthorizationRequiredEvent
- type Client
- func (c *Client) CreateAgent(ctx context.Context, prompt string) (*api.CreateAgentResponse, error)
- func (c *Client) CreateAgentConfig(ctx context.Context, filename, model, description, instruction string) (*api.CreateAgentConfigResponse, error)
- func (c *Client) CreateSession(ctx context.Context, sessTemplate *session.Session) (*session.Session, error)
- func (c *Client) DeleteAgent(ctx context.Context, filePath string) (*api.DeleteAgentResponse, error)
- func (c *Client) DeleteSession(ctx context.Context, id string) error
- func (c *Client) EditAgentConfig(ctx context.Context, filename string, config v2.Config) (*api.EditAgentConfigResponse, error)
- func (c *Client) ExportAgents(ctx context.Context) (*api.ExportAgentsResponse, error)
- func (c *Client) GetAgent(ctx context.Context, id string) (*v2.Config, error)
- func (c *Client) GetAgents(ctx context.Context) ([]api.Agent, error)
- func (c *Client) GetDesktopToken(ctx context.Context) (*api.DesktopTokenResponse, error)
- func (c *Client) GetSession(ctx context.Context, id string) (*api.SessionResponse, error)
- func (c *Client) GetSessions(ctx context.Context) ([]api.SessionsResponse, error)
- func (c *Client) ImportAgent(ctx context.Context, filePath string) (*api.ImportAgentResponse, error)
- func (c *Client) PullAgent(ctx context.Context, name string) (*api.PullAgentResponse, error)
- func (c *Client) PushAgent(ctx context.Context, filepath, tag string) (*api.PushAgentResponse, error)
- func (c *Client) ResumeCodeReceived(ctx context.Context, code string) error
- func (c *Client) ResumeSession(ctx context.Context, id, confirmation string) error
- func (c *Client) ResumeStartAuthorizationFlow(ctx context.Context, id string, confirmation bool) error
- func (c *Client) RunAgent(ctx context.Context, sessionID, agent string, messages []api.Message) (<-chan Event, error)
- func (c *Client) RunAgentWithAgentName(ctx context.Context, sessionID, agent, agentName string, ...) (<-chan Event, error)
- type ClientOption
- type ErrorEvent
- type ErrorResponse
- type Event
- func AgentChoice(agentName string, content string) Event
- func AgentChoiceReasoning(agentName string, content string) Event
- func AuthorizationRequired(serverURL, serverType, confirmation string) Event
- func Error(msg string) Event
- func PartialToolCall(toolCall tools.ToolCall, agentName string) Event
- func SessionCompaction(sessionID, status string) Event
- func SessionSummary(sessionID, summary string) Event
- func SessionTitle(sessionID, title string) Event
- func ShellOutput(output string) Event
- func StreamStarted() Event
- func StreamStopped() Event
- func TokenUsage(inputTokens, outputTokens, contextLength, contextLimit int, cost float64) Event
- func ToolCall(toolCall tools.ToolCall, agentName string) Event
- func ToolCallConfirmation(toolCall tools.ToolCall, agentName string) Event
- func ToolCallResponse(toolCall tools.ToolCall, response, agentName string) Event
- func UserMessage(message string) Event
- type OAuthAuthorizationRequiredError
- type OAuthProtectedResource
- type OAuthStateData
- type Opt
- type PartialToolCallEvent
- type RemoteRuntime
- func (r *RemoteRuntime) CurrentAgent() *agent.Agent
- func (r *RemoteRuntime) Resume(ctx context.Context, confirmationType string)
- func (r *RemoteRuntime) ResumeCodeReceived(ctx context.Context, code string) error
- func (r *RemoteRuntime) ResumeStartAuthorizationFlow(ctx context.Context, confirmationType bool)
- func (r *RemoteRuntime) Run(ctx context.Context, sess *session.Session) ([]session.Message, error)
- func (r *RemoteRuntime) RunStream(ctx context.Context, sess *session.Session) <-chan Event
- func (r *RemoteRuntime) Summarize(ctx context.Context, sess *session.Session, events chan Event)
- type RemoteRuntimeOption
- type ResumeType
- type Runtime
- type ServerInfoProvider
- type SessionCompactionEvent
- type SessionSummaryEvent
- type SessionTitleEvent
- type ShellOutputEvent
- type StreamStartedEvent
- type StreamStoppedEvent
- type TokenUsageEvent
- type ToolCallConfirmationEvent
- type ToolCallEvent
- type ToolCallResponseEvent
- type ToolHandler
- type Usage
- type UserMessageEvent
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DecodeSessionIDFromState ¶ added in v1.3.1
DecodeSessionIDFromState extracts the session ID from an OAuth state parameter.
This function is exported to allow OAuth callback handlers to decode session IDs. When the OAuth provider redirects back to our callback endpoint, they include the state parameter we originally sent. This function reverses the encoding done by generateStateWithSessionID to extract the session ID, allowing us to route the authorization code back to the correct agent session that initiated the OAuth flow.
This is the critical piece that bridges the browser-based OAuth callback back to the specific runtime session that needs the authorization.
func GetAuthorizationURL ¶ added in v1.3.1
func GetAuthorizationURL(ctx context.Context, oauthHandler *transport.OAuthHandler, state, codeChallenge string) (string, error)
GetAuthorizationURL gets the OAuth authorization URL using the correct discovery logic.
This function works around the mcp-go library's incomplete OAuth discovery implementation. The upstream GetAuthorizationURL method fails with most MCP servers because it only tries the RFC 9728 discovery path, while most servers implement RFC 8414 directly.
Our approach: 1. Use our custom discovery logic to find the correct authorization endpoint 2. Leverage the existing mcp-go logic for parameter construction (client_id, scope, etc.) 3. Combine the correct endpoint with the correct parameters
This ensures we get properly formatted OAuth URLs that work with real MCP servers.
Types ¶
type AgentChoiceEvent ¶
type AgentChoiceEvent struct {
Type string `json:"type"`
Content string `json:"content"`
AgentContext
}
type AgentChoiceReasoningEvent ¶ added in v1.0.5
type AgentChoiceReasoningEvent struct {
Type string `json:"type"`
Content string `json:"content"`
AgentContext
}
type AgentContext ¶
type AgentContext struct {
AgentName string `json:"agent_name,omitempty"`
}
AgentContext carries optional agent attribution for an event.
func (AgentContext) GetAgentName ¶
func (a AgentContext) GetAgentName() string
GetAgentName returns the agent name for events embedding AgentContext.
type AuthServerMetadata ¶ added in v1.3.1
type AuthServerMetadata struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
JwksURI string `json:"jwks_uri,omitempty"`
ScopesSupported []string `json:"scopes_supported,omitempty"`
ResponseTypesSupported []string `json:"response_types_supported"`
GrantTypesSupported []string `json:"grant_types_supported,omitempty"`
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported,omitempty"`
}
AuthServerMetadata represents the OAuth 2.0 Authorization Server Metadata This is a copy from the mcp-go library to avoid importing internal types
type AuthorizationRequiredEvent ¶ added in v1.2.0
type AuthorizationRequiredEvent struct {
Type string `json:"type"`
ServerURL string `json:"server_url"`
ServerType string `json:"server_type"`
Confirmation string `json:"confirmation"` // only "pending" | "confirmed" | "denied"
}
func (*AuthorizationRequiredEvent) GetAgentName ¶ added in v1.2.0
func (e *AuthorizationRequiredEvent) GetAgentName() string
type Client ¶ added in v1.3.1
type Client struct {
// contains filtered or unexported fields
}
Client is an HTTP client for the cagent server API
func NewClient ¶ added in v1.3.1
func NewClient(baseURL string, opts ...ClientOption) (*Client, error)
NewClient creates a new HTTP client for the cagent server
func (*Client) CreateAgent ¶ added in v1.3.1
CreateAgent creates a new agent using a prompt
func (*Client) CreateAgentConfig ¶ added in v1.3.1
func (c *Client) CreateAgentConfig(ctx context.Context, filename, model, description, instruction string) (*api.CreateAgentConfigResponse, error)
CreateAgentConfig creates a new agent manually with YAML configuration
func (*Client) CreateSession ¶ added in v1.3.1
func (c *Client) CreateSession(ctx context.Context, sessTemplate *session.Session) (*session.Session, error)
CreateSession creates a new session
func (*Client) DeleteAgent ¶ added in v1.3.1
func (c *Client) DeleteAgent(ctx context.Context, filePath string) (*api.DeleteAgentResponse, error)
DeleteAgent deletes an agent by file path
func (*Client) DeleteSession ¶ added in v1.3.1
DeleteSession deletes a session by ID
func (*Client) EditAgentConfig ¶ added in v1.3.1
func (c *Client) EditAgentConfig(ctx context.Context, filename string, config v2.Config) (*api.EditAgentConfigResponse, error)
EditAgentConfig edits an agent configuration
func (*Client) ExportAgents ¶ added in v1.3.1
ExportAgents exports multiple agents as a zip file
func (*Client) GetDesktopToken ¶ added in v1.3.1
GetDesktopToken retrieves a desktop authentication token
func (*Client) GetSession ¶ added in v1.3.1
GetSession retrieves a session by ID
func (*Client) GetSessions ¶ added in v1.3.1
GetSessions retrieves all sessions
func (*Client) ImportAgent ¶ added in v1.3.1
func (c *Client) ImportAgent(ctx context.Context, filePath string) (*api.ImportAgentResponse, error)
ImportAgent imports an agent from a file path
func (*Client) PushAgent ¶ added in v1.3.1
func (c *Client) PushAgent(ctx context.Context, filepath, tag string) (*api.PushAgentResponse, error)
PushAgent pushes an agent to a remote registry
func (*Client) ResumeCodeReceived ¶ added in v1.3.1
func (*Client) ResumeSession ¶ added in v1.3.1
ResumeSession resumes a session by ID
func (*Client) ResumeStartAuthorizationFlow ¶ added in v1.3.1
func (*Client) RunAgent ¶ added in v1.3.1
func (c *Client) RunAgent(ctx context.Context, sessionID, agent string, messages []api.Message) (<-chan Event, error)
RunAgent executes an agent and returns a channel of streaming events
func (*Client) RunAgentWithAgentName ¶ added in v1.3.1
func (c *Client) RunAgentWithAgentName(ctx context.Context, sessionID, agent, agentName string, messages []api.Message) (<-chan Event, error)
RunAgentWithAgentName executes an agent with a specific agent name and returns a channel of streaming events
type ClientOption ¶ added in v1.3.1
type ClientOption func(*Client)
ClientOption is a function for configuring the Client
func WithHTTPClient ¶ added in v1.3.1
func WithHTTPClient(client *http.Client) ClientOption
WithHTTPClient sets a custom HTTP client
func WithTimeout ¶ added in v1.3.1
func WithTimeout(timeout time.Duration) ClientOption
WithTimeout sets the HTTP client timeout
type ErrorEvent ¶
type ErrorEvent struct {
Type string `json:"type"`
Error string `json:"error"`
AgentContext
}
type ErrorResponse ¶ added in v1.3.1
type ErrorResponse struct {
Error string `json:"error"`
}
ErrorResponse represents an error response from the API
type Event ¶
type Event interface {
GetAgentName() string
// contains filtered or unexported methods
}
func AgentChoice ¶
func AgentChoiceReasoning ¶ added in v1.0.5
func AuthorizationRequired ¶ added in v1.2.0
func SessionCompaction ¶
func SessionSummary ¶
func SessionTitle ¶
func ShellOutput ¶ added in v1.0.0
func StreamStarted ¶
func StreamStarted() Event
func StreamStopped ¶
func StreamStopped() Event
func TokenUsage ¶
func ToolCallConfirmation ¶
func ToolCallResponse ¶
func UserMessage ¶
type OAuthAuthorizationRequiredError ¶ added in v1.3.1
OAuthAuthorizationRequiredError wraps an OAuth authorization error with server information
func (*OAuthAuthorizationRequiredError) Error ¶ added in v1.3.1
func (e *OAuthAuthorizationRequiredError) Error() string
func (*OAuthAuthorizationRequiredError) Unwrap ¶ added in v1.3.1
func (e *OAuthAuthorizationRequiredError) Unwrap() error
type OAuthProtectedResource ¶ added in v1.3.1
type OAuthProtectedResource struct {
AuthorizationServers []string `json:"authorization_servers"`
Resource string `json:"resource"`
ResourceName string `json:"resource_name,omitempty"`
}
OAuthProtectedResource represents the response from /.well-known/oauth-protected-resource
type OAuthStateData ¶ added in v1.3.1
type OAuthStateData struct {
SessionID string `json:"session_id"` // The session ID that initiated the OAuth flow
Random string `json:"random"` // Random component for CSRF protection
}
OAuthStateData represents the data encoded in the OAuth state parameter.
In OAuth flows, the state parameter serves dual purposes:
- Security: CSRF protection by including random data
- Session tracking: When the browser returns from authorization, we need to know which session triggered the OAuth flow to route the callback correctly.
Since OAuth authorization happens in a browser (different context from our runtime), we embed the session ID in the state parameter so we can retrieve it when the authorization server redirects back to us with the authorization code.
type Opt ¶
type Opt func(*runtime)
func WithCurrentAgent ¶
func WithSessionCompaction ¶
func WithTracer ¶
WithTracer sets a custom OpenTelemetry tracer; if not provided, tracing is disabled (no-op).
type PartialToolCallEvent ¶
type PartialToolCallEvent struct {
Type string `json:"type"`
ToolCall tools.ToolCall `json:"tool_call"`
AgentContext
}
ToolCallEvent is sent when a tool call is received PartialToolCallEvent is sent when a tool call is first received (partial/complete)
type RemoteRuntime ¶ added in v1.3.1
type RemoteRuntime struct {
// contains filtered or unexported fields
}
RemoteRuntime implements the Interface using a remote client
func NewRemoteRuntime ¶ added in v1.3.1
func NewRemoteRuntime(client *Client, opts ...RemoteRuntimeOption) (*RemoteRuntime, error)
NewRemoteRuntime creates a new remote runtime that implements the Interface
func (*RemoteRuntime) CurrentAgent ¶ added in v1.3.1
func (r *RemoteRuntime) CurrentAgent() *agent.Agent
CurrentAgent returns the currently active agent
func (*RemoteRuntime) Resume ¶ added in v1.3.1
func (r *RemoteRuntime) Resume(ctx context.Context, confirmationType string)
Resume allows resuming execution after user confirmation
func (*RemoteRuntime) ResumeCodeReceived ¶ added in v1.3.1
func (r *RemoteRuntime) ResumeCodeReceived(ctx context.Context, code string) error
Resume allows resuming execution after user confirmation
func (*RemoteRuntime) ResumeStartAuthorizationFlow ¶ added in v1.3.1
func (r *RemoteRuntime) ResumeStartAuthorizationFlow(ctx context.Context, confirmationType bool)
Resume allows resuming execution after user confirmation
func (*RemoteRuntime) Run ¶ added in v1.3.1
Run starts the agent's interaction loop and returns the final messages
type RemoteRuntimeOption ¶ added in v1.3.1
type RemoteRuntimeOption func(*RemoteRuntime)
RemoteRuntimeOption is a function for configuring the RemoteRuntime
func WithRemoteAgentFilename ¶ added in v1.3.1
func WithRemoteAgentFilename(filename string) RemoteRuntimeOption
WithRemoteAgentFilename sets the agent filename to use with the remote API
func WithRemoteCurrentAgent ¶ added in v1.3.1
func WithRemoteCurrentAgent(agentName string) RemoteRuntimeOption
WithRemoteCurrentAgent sets the current agent name
func WithRemoteSessionID ¶ added in v1.3.1
func WithRemoteSessionID(sessionID string) RemoteRuntimeOption
WithRemoteSessionID sets the session ID for the remote runtime
type ResumeType ¶
type ResumeType string
const ( ResumeTypeApprove ResumeType = "approve" ResumeTypeApproveSession ResumeType = "approve-session" ResumeTypeReject ResumeType = "reject" )
type Runtime ¶
type Runtime interface {
// CurrentAgent returns the currently active agent
CurrentAgent() *agent.Agent
// RunStream starts the agent's interaction loop and returns a channel of events
RunStream(ctx context.Context, sess *session.Session) <-chan Event
// Run starts the agent's interaction loop and returns the final messages
Run(ctx context.Context, sess *session.Session) ([]session.Message, error)
// Resume allows resuming execution after user confirmation
Resume(ctx context.Context, confirmationType string)
// Summarize generates a summary for the session
Summarize(ctx context.Context, sess *session.Session, events chan Event)
// ResumeStartAuthorizationFlow signals that user confirmation has been given to start the OAuth flow
ResumeStartAuthorizationFlow(_ context.Context, confirmation bool)
// ResumeCodeReceived sends the OAuth authorization code to the runtime after user has completed the OAuth flow in their browser
ResumeCodeReceived(_ context.Context, code string) error
}
Runtime defines the contract for runtime execution
type ServerInfoProvider ¶ added in v1.3.1
type ServerInfoProvider interface {
GetServerInfo() (serverURL, serverType string)
}
ServerInfoProvider interface for toolsets that can provide server information
type SessionCompactionEvent ¶
type SessionCompactionEvent struct {
Type string `json:"type"`
SessionID string `json:"session_id"`
Status string `json:"status"`
AgentContext
}
type SessionSummaryEvent ¶
type SessionSummaryEvent struct {
Type string `json:"type"`
SessionID string `json:"session_id"`
Summary string `json:"summary"`
AgentContext
}
type SessionTitleEvent ¶
type SessionTitleEvent struct {
Type string `json:"type"`
SessionID string `json:"session_id"`
Title string `json:"title"`
AgentContext
}
type ShellOutputEvent ¶ added in v1.0.0
func (*ShellOutputEvent) GetAgentName ¶ added in v1.0.0
func (e *ShellOutputEvent) GetAgentName() string
type StreamStartedEvent ¶
type StreamStartedEvent struct {
Type string `json:"type"`
}
func (*StreamStartedEvent) GetAgentName ¶
func (e *StreamStartedEvent) GetAgentName() string
type StreamStoppedEvent ¶
type StreamStoppedEvent struct {
Type string `json:"type"`
}
func (*StreamStoppedEvent) GetAgentName ¶
func (e *StreamStoppedEvent) GetAgentName() string
type TokenUsageEvent ¶
type TokenUsageEvent struct {
Type string `json:"type"`
Usage *Usage `json:"usage"`
AgentContext
}
type ToolCallConfirmationEvent ¶
type ToolCallConfirmationEvent struct {
Type string `json:"type"`
ToolCall tools.ToolCall `json:"tool_call"`
AgentContext
}
type ToolCallEvent ¶
type ToolCallEvent struct {
Type string `json:"type"`
ToolCall tools.ToolCall `json:"tool_call"`
AgentContext
}
type ToolCallResponseEvent ¶
type ToolCallResponseEvent struct {
Type string `json:"type"`
ToolCall tools.ToolCall `json:"tool_call"`
Response string `json:"response"`
AgentContext
}
type ToolHandler ¶
type ToolHandler func(ctx context.Context, sess *session.Session, toolCall tools.ToolCall, events chan Event) (*tools.ToolCallResult, error)
ToolHandler is a function type for handling tool calls
type UserMessageEvent ¶
UserMessageEvent is sent when a user message is received
func (*UserMessageEvent) GetAgentName ¶
func (e *UserMessageEvent) GetAgentName() string