Documentation
¶
Overview ¶
Package agent provides an MCP client and REPL for debugging MCP servers.
Package agent provides the MCP debugging agent implementation.
This package includes client connectivity for MCP servers, OAuth 2.1 authentication support, interactive REPL capabilities for exploring MCP servers, and an MCP server implementation that exposes debugging functionality as MCP tools.
OAuth 2.1 Support ¶
The agent package implements the MCP authorization specification (2025-11-25) with comprehensive OAuth 2.1 support including:
Discovery:
- RFC 9728: Protected Resource Metadata Discovery
- RFC 8414: Authorization Server Metadata Discovery
- Multi-endpoint probing (OAuth 2.0 and OIDC)
- WWW-Authenticate header parsing
Security Features:
- RFC 7636: PKCE (Proof Key for Code Exchange) with S256 method validation
- RFC 8707: Resource Indicators for token audience binding
- In-memory token storage (never persisted to disk)
- HTTPS enforcement for sensitive operations
Client Registration:
- RFC 7591: Dynamic Client Registration (DCR)
- Client ID Metadata Documents (draft-ietf-oauth-client-id-metadata-document-00)
- Pre-registered client support
- Authenticated DCR with registration tokens
Scope Management:
- Automatic scope selection per MCP spec priority
- Manual scope override capability
- Step-up authorization for runtime permission escalation
- Scope validation and security checks
Key Components ¶
- Client: Connects to MCP servers and handles communication
- OAuthConfig: Configuration for OAuth 2.1 authentication
- REPL: Interactive Read-Eval-Print Loop for exploring MCP servers
- MCPServer: Exposes debugging functionality as an MCP server
- Logger: Formatted logging with color support and JSON-RPC message tracking
Documentation ¶
For complete OAuth documentation, see:
- docs/oauth/ - Complete OAuth 2.1 documentation
- docs/oauth/README.md - Overview and quick start
- docs/oauth/security.md - Security features and best practices
- docs/oauth/examples/ - Practical examples and tutorials
For usage documentation, see:
- docs/usage.md - Complete usage guide
- README.md - Project overview and quick start
Package agent implements Authorization Server Metadata Discovery per RFC 8414.
Multi-Endpoint Discovery: Probes multiple discovery endpoints in priority order based on issuer URL format. Supports both OAuth 2.0 Authorization Server Metadata (RFC 8414) and OpenID Connect Discovery 1.0.
PKCE Validation: Enforces PKCE support check as required by MCP spec (2025-11-25). Authorization servers MUST advertise code_challenge_methods_supported. Use SkipPKCEValidation flag only for testing non-compliant servers.
Security: - Validates PKCE support by default (fail closed) - Supports S256 code challenge method requirement - Validates metadata structure and required fields
Package agent implements Client ID Metadata Document support per draft-ietf-oauth-client-id-metadata-document-00.
Client ID Metadata Documents allow clients to use HTTPS URLs as client identifiers, enabling clients to self-assert metadata without pre-registration.
Security: - HTTPS is REQUIRED for client_id URLs (HTTP not allowed) - client_id URL MUST contain a path component - localhost redirect URIs have specific security implications (see spec Section 6)
Package agent implements Protected Resource Metadata Discovery per RFC 9728.
Package agent implements MCP client functionality including OAuth 2.1 authentication with RFC 8707 Resource Indicators support.
Package agent implements step-up authorization per MCP OAuth 2.1 spec.
Step-up authorization handles runtime 403 Forbidden responses with insufficient_scope errors by automatically requesting additional permissions and retrying the operation.
Index ¶
- Constants
- func PrettyJSON(v interface{}) string
- func SupportsClientIDMetadata(asMetadata *AuthorizationServerMetadata) bool
- func ValidateCIMDConsistency(ctx context.Context, cimdURL string) error
- func ValidateClientIDURL(clientIDURL string) error
- func ValidateClientMetadata(metadata *ClientMetadataDocument) error
- func ValidatePKCESupport(metadata *AuthorizationServerMetadata, skipValidation bool, logger *Logger) error
- type AuthorizationServerMetadata
- type Client
- func (c *Client) CallTool(ctx context.Context, name string, args map[string]interface{}) (*mcp.CallToolResult, error)
- func (c *Client) GetPrompt(ctx context.Context, name string, args map[string]string) (*mcp.GetPromptResult, error)
- func (c *Client) GetResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)
- func (c *Client) Listen(ctx context.Context) error
- func (c *Client) Reconnect(ctx context.Context) error
- func (c *Client) Run(ctx context.Context) error
- func (c *Client) ServerSupportsPrompts() bool
- func (c *Client) ServerSupportsResources() bool
- func (c *Client) ServerSupportsTools() bool
- type ClientConfig
- type ClientMetadataDocument
- type Logger
- func (l *Logger) Debug(format string, args ...interface{})
- func (l *Logger) Error(format string, args ...interface{})
- func (l *Logger) Info(format string, args ...interface{})
- func (l *Logger) InfoVerbose(format string, args ...interface{})
- func (l *Logger) Notification(method string, params interface{})
- func (l *Logger) Request(method string, params interface{})
- func (l *Logger) Response(method string, result interface{})
- func (l *Logger) SetVerbose(verbose bool)
- func (l *Logger) SetWriter(w io.Writer)
- func (l *Logger) Success(format string, args ...interface{})
- func (l *Logger) Warning(format string, args ...interface{})
- func (l *Logger) WarningVerbose(format string, args ...interface{})
- func (l *Logger) Write(p []byte) (n int, err error)
- type MCPServer
- type NotificationHandler
- type OAuthConfig
- type ProtectedResourceMetadata
- type REPL
- type WWWAuthenticateChallenge
Constants ¶
const ( // ScopeModeManual indicates manual scope selection ScopeModeManual = "manual" // ScopeModeAuto indicates automatic scope selection per MCP spec ScopeModeAuto = "auto" // DefaultRedirectURL is the default OAuth callback URL DefaultRedirectURL = "http://localhost:8765/callback" // DefaultClientName is the default OAuth client name DefaultClientName = "mcp-debug" )
OAuth configuration constants
const DefaultClientIDMetadataURL = "https://giantswarm.github.io/mcp-debug/client.json"
DefaultClientIDMetadataURL is the official CIMD URL hosted on GitHub Pages. This URL contains the client metadata for mcp-debug and is used when the authorization server supports Client ID Metadata Documents (CIMD).
Variables ¶
This section is empty.
Functions ¶
func SupportsClientIDMetadata ¶
func SupportsClientIDMetadata(asMetadata *AuthorizationServerMetadata) bool
SupportsClientIDMetadata checks if the Authorization Server supports Client ID Metadata Documents based on its metadata.
func ValidateCIMDConsistency ¶
ValidateCIMDConsistency fetches a Client ID Metadata Document and validates that the client_id field in the document matches the URL it was fetched from.
This is a security check to catch configuration errors early, especially when users provide custom CIMD URLs. The CIMD spec requires that the client_id in the document matches the URL where it is hosted.
Returns nil if validation passes, or an error describing the mismatch.
func ValidateClientIDURL ¶
ValidateClientIDURL validates that a client_id URL meets CIMD requirements per draft-ietf-oauth-client-id-metadata-document-00 Section 2.
Requirements:
- MUST use https scheme (HTTP is not allowed)
- MUST contain a path component (cannot be just https://example.com)
- MUST be a valid absolute URL
func ValidateClientMetadata ¶
func ValidateClientMetadata(metadata *ClientMetadataDocument) error
ValidateClientMetadata validates a Client ID Metadata Document structure per draft-ietf-oauth-client-id-metadata-document-00.
func ValidatePKCESupport ¶
func ValidatePKCESupport(metadata *AuthorizationServerMetadata, skipValidation bool, logger *Logger) error
ValidatePKCESupport checks if the authorization server advertises PKCE support. Per MCP spec (2025-11-25), authorization servers MUST support PKCE and MUST advertise it in code_challenge_methods_supported.
Returns an error if:
- code_challenge_methods_supported is absent
- code_challenge_methods_supported is empty
- S256 method is not supported
Use skipValidation=true only for testing with non-compliant servers. Requires MCP_DEBUG_ALLOW_INSECURE=true environment variable when skipValidation is true.
Types ¶
type AuthorizationServerMetadata ¶
type AuthorizationServerMetadata struct {
// Issuer is the authorization server's issuer identifier URL
Issuer string `json:"issuer"`
// AuthorizationEndpoint is the URL for the authorization endpoint
AuthorizationEndpoint string `json:"authorization_endpoint"`
// TokenEndpoint is the URL for the token endpoint
TokenEndpoint string `json:"token_endpoint"`
// RegistrationEndpoint is the URL for Dynamic Client Registration (optional)
RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
// CodeChallengeMethods lists supported PKCE code challenge methods
// MCP spec requires this field to be present and include "S256"
CodeChallengeMethods []string `json:"code_challenge_methods_supported,omitempty"`
// ClientIDMetadataDocumentSupported indicates support for Client ID Metadata Documents
ClientIDMetadataDocumentSupported bool `json:"client_id_metadata_document_supported,omitempty"`
// ScopesSupported lists supported OAuth scopes (optional)
ScopesSupported []string `json:"scopes_supported,omitempty"`
// ResponseTypesSupported lists supported OAuth response types
ResponseTypesSupported []string `json:"response_types_supported,omitempty"`
// GrantTypesSupported lists supported OAuth grant types
GrantTypesSupported []string `json:"grant_types_supported,omitempty"`
// TokenEndpointAuthMethodsSupported lists supported token endpoint auth methods
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported,omitempty"`
}
AuthorizationServerMetadata represents OAuth 2.0 Authorization Server Metadata as defined in RFC 8414 and OpenID Connect Discovery 1.0.
func DiscoverAuthorizationServerMetadata ¶
func DiscoverAuthorizationServerMetadata(ctx context.Context, issuerURL string, logger *Logger) (*AuthorizationServerMetadata, error)
DiscoverAuthorizationServerMetadata discovers authorization server metadata for the given issuer URL per RFC 8414 and OIDC Discovery 1.0.
Discovery probes endpoints in this priority order:
For issuer URLs with path components (e.g., https://auth.example.com/tenant1):
- OAuth 2.0 with path insertion: https://auth.example.com/.well-known/oauth-authorization-server/tenant1
- OIDC with path insertion: https://auth.example.com/.well-known/openid-configuration/tenant1
- OIDC path appending: https://auth.example.com/tenant1/.well-known/openid-configuration
For issuer URLs without path components (e.g., https://auth.example.com):
- OAuth 2.0: https://auth.example.com/.well-known/oauth-authorization-server
- OIDC: https://auth.example.com/.well-known/openid-configuration
Returns the first successfully retrieved metadata document.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client represents an MCP agent client
func NewClient ¶
func NewClient(cfg ClientConfig) *Client
NewClient creates a new agent client from a configuration
func (*Client) CallTool ¶
func (c *Client) CallTool(ctx context.Context, name string, args map[string]interface{}) (*mcp.CallToolResult, error)
CallTool executes a tool with the given arguments, with reconnection logic.
func (*Client) GetPrompt ¶
func (c *Client) GetPrompt(ctx context.Context, name string, args map[string]string) (*mcp.GetPromptResult, error)
GetPrompt retrieves a prompt with arguments, with reconnection logic.
func (*Client) GetResource ¶
GetResource retrieves a resource by URI, with reconnection logic.
func (*Client) ServerSupportsPrompts ¶
func (*Client) ServerSupportsResources ¶
func (*Client) ServerSupportsTools ¶
Helper methods to check server capabilities
type ClientConfig ¶
type ClientConfig struct {
Endpoint string
Transport string
Logger *Logger
OAuthConfig *OAuthConfig
Version string
}
ClientConfig holds configuration for creating a new Client
type ClientMetadataDocument ¶
type ClientMetadataDocument struct {
// ClientID is the HTTPS URL that identifies this client
// REQUIRED: Must use https scheme and include a path component
ClientID string `json:"client_id"`
// ClientName is the human-readable name of the client
ClientName string `json:"client_name,omitempty"`
// ClientURI is the URL of the client's home page
ClientURI string `json:"client_uri,omitempty"`
// LogoURI is the URL of the client's logo image
LogoURI string `json:"logo_uri,omitempty"`
// RedirectURIs are the redirect URIs for OAuth callbacks
// REQUIRED for authorization code grant
RedirectURIs []string `json:"redirect_uris"`
// GrantTypes are the OAuth grant types the client will use
// Default: ["authorization_code"]
GrantTypes []string `json:"grant_types,omitempty"`
// ResponseTypes are the OAuth response types the client will use
// Default: ["code"]
ResponseTypes []string `json:"response_types,omitempty"`
// TokenEndpointAuthMethod is the authentication method for the token endpoint
// Default: "none" for public clients
TokenEndpointAuthMethod string `json:"token_endpoint_auth_method,omitempty"`
}
ClientMetadataDocument represents an OAuth Client ID Metadata Document as defined in draft-ietf-oauth-client-id-metadata-document-00.
When a client uses an HTTPS URL as its client_id, the Authorization Server can fetch this document to retrieve the client's metadata.
func FetchClientMetadata ¶
func FetchClientMetadata(ctx context.Context, clientIDURL string) (*ClientMetadataDocument, error)
FetchClientMetadata fetches and parses a Client ID Metadata Document from the specified HTTPS URL.
This is typically used by Authorization Servers to discover client metadata, but can also be used for validation/testing.
func GenerateClientMetadata ¶
func GenerateClientMetadata(config *OAuthConfig) (*ClientMetadataDocument, error)
GenerateClientMetadata generates a Client ID Metadata Document for mcp-debug.
The document describes the client's OAuth configuration and is meant to be:
- Hosted at the client_id URL for AS discovery
- Generated for user review/manual hosting
- Used as template for custom configurations
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger provides formatted logging for the agent
func NewLoggerWithWriter ¶
NewLoggerWithWriter creates a new logger with a custom writer
func (*Logger) InfoVerbose ¶
InfoVerbose logs an informational message only in verbose mode
func (*Logger) Notification ¶
Notification logs an incoming notification
func (*Logger) SetVerbose ¶
SetVerbose sets the verbose mode
func (*Logger) WarningVerbose ¶
WarningVerbose logs a warning message only in verbose mode
type MCPServer ¶
type MCPServer struct {
// contains filtered or unexported fields
}
MCPServer wraps the agent functionality and exposes it via MCP
type NotificationHandler ¶
type NotificationHandler func(notification mcp.JSONRPCNotification)
OnNotification is a helper type for type-safe notification handling
type OAuthConfig ¶
type OAuthConfig struct {
// Enabled indicates whether OAuth authentication should be used
Enabled bool
// ClientID is the OAuth client identifier (optional - will use DCR if not provided)
ClientID string
// ClientSecret is the OAuth client secret (optional for public clients)
ClientSecret string
// Scopes are the OAuth scopes to request (optional, no default scopes)
// When ScopeSelectionMode is "manual", these scopes are used directly.
// When ScopeSelectionMode is "auto", these scopes are used as a fallback
// if no scopes can be determined from WWW-Authenticate or resource metadata.
Scopes []string
// ScopeSelectionMode controls automatic scope selection per MCP spec
// - "auto" (default): Follow MCP spec priority (secure by default)
// Priority 1: Use scope from WWW-Authenticate header
// Priority 2: Use scopes_supported from Protected Resource Metadata
// Priority 3: Omit scope parameter entirely
// - "manual": Use only the Scopes field value
ScopeSelectionMode string
// RedirectURL is the callback URL for OAuth flow (default: http://localhost:8765/callback)
//
// IMPORTANT SECURITY LIMITATION:
// - HTTPS redirect URIs are NOT currently supported
// - HTTP is only allowed for localhost/127.0.0.1/[::1] addresses
// - The callback server runs on localhost only with HTTP
// - For production OAuth flows requiring HTTPS callbacks, this is a known limitation
//
// This design follows OAuth 2.1 best practices for native/desktop applications
// which use localhost loopback for authorization callbacks.
RedirectURL string
// UsePKCE enables Proof Key for Code Exchange (recommended, enabled by default)
UsePKCE bool
// AuthorizationTimeout is the maximum time to wait for user authorization (default: 5 minutes)
AuthorizationTimeout time.Duration
// UseOIDC enables OpenID Connect features including nonce validation (optional)
UseOIDC bool
// RegistrationToken is the OAuth registration access token for Dynamic Client Registration
// Required if the authorization server has DCR authentication enabled
RegistrationToken string
// ResourceURI is the target MCP server URI for RFC 8707 Resource Indicators
// If empty, automatically derived from endpoint URL
// This parameter is included in authorization and token requests for better security
ResourceURI string
// SkipResourceParam disables RFC 8707 resource parameter inclusion
// Only use this for testing with older servers that don't support RFC 8707
// Security: Disabling this weakens token audience binding
SkipResourceParam bool
// SkipResourceMetadata disables RFC 9728 Protected Resource Metadata discovery
// Only use this for testing with older servers that don't support RFC 9728
// Security: Disabling this may require manual authorization server configuration
SkipResourceMetadata bool
// PreferredAuthServer allows selecting a specific authorization server
// when multiple servers are available in the protected resource metadata
// If empty, the first server in the list is used
PreferredAuthServer string
// SkipPKCEValidation disables checking for PKCE support in AS metadata
// DANGEROUS: Only use for testing servers that support PKCE but don't advertise it
// Security: This weakens security by allowing connections to servers without PKCE
SkipPKCEValidation bool
// SkipAuthServerDiscovery disables automatic AS metadata discovery
// Useful for testing with pre-configured endpoints or older servers
// When enabled, relies on mcp-go's internal discovery mechanisms
SkipAuthServerDiscovery bool
// EnableStepUpAuth enables automatic step-up authorization when the server
// returns 403 Forbidden with insufficient_scope error per MCP spec
// Default: true (secure by default, provides better UX)
EnableStepUpAuth bool
// StepUpMaxRetries limits the number of retry attempts per resource/operation
// when handling insufficient_scope errors during step-up authorization
// Default: 2 (prevents infinite authorization loops)
StepUpMaxRetries int
// StepUpUserPrompt asks user before requesting additional scopes
// When false, step-up authorization happens automatically
// Default: false (automatic for better UX, user can always decline in browser)
StepUpUserPrompt bool
// ClientIDMetadataURL is the HTTPS URL hosting the Client ID Metadata Document
// When set, this URL will be used as the client_id per
// draft-ietf-oauth-client-id-metadata-document-00
// Requirements:
// - MUST use https scheme (HTTP not allowed, even for localhost)
// - MUST contain a path component
// - The document at this URL should contain client metadata in JSON format
// Example: "https://app.example.com/oauth/client-metadata.json"
ClientIDMetadataURL string
// DisableCIMD disables Client ID Metadata Documents support
// When true, falls back to Dynamic Client Registration or manual registration
// Use this for testing with Authorization Servers that don't support CIMD
DisableCIMD bool
}
OAuthConfig contains OAuth 2.1 configuration for authenticating with MCP servers
func DefaultOAuthConfig ¶
func DefaultOAuthConfig() *OAuthConfig
DefaultOAuthConfig returns a default OAuth configuration
func (*OAuthConfig) Validate ¶
func (c *OAuthConfig) Validate() error
Validate checks if the OAuth configuration is valid (read-only, does not modify config)
func (*OAuthConfig) WithDefaults ¶
func (c *OAuthConfig) WithDefaults() *OAuthConfig
WithDefaults returns a new config with defaults applied for any unset fields
type ProtectedResourceMetadata ¶
type ProtectedResourceMetadata struct {
// Resource is the protected resource identifier
Resource string `json:"resource"`
// AuthorizationServers lists the authorization servers for this resource
AuthorizationServers []string `json:"authorization_servers"`
// ScopesSupported lists the OAuth scopes supported by this resource
ScopesSupported []string `json:"scopes_supported,omitempty"`
// BearerMethodsSupported indicates how bearer tokens can be presented
BearerMethodsSupported []string `json:"bearer_methods_supported,omitempty"`
// ResourceDocumentation provides human-readable documentation URL
ResourceDocumentation string `json:"resource_documentation,omitempty"`
}
ProtectedResourceMetadata represents OAuth 2.0 Protected Resource Metadata as defined in RFC 9728.
type REPL ¶
type REPL struct {
// contains filtered or unexported fields
}
REPL represents the Read-Eval-Print Loop for MCP interaction
type WWWAuthenticateChallenge ¶
type WWWAuthenticateChallenge struct {
// Scheme is the authentication scheme (typically "Bearer")
Scheme string
// ResourceMetadataURL is the URL to fetch protected resource metadata
ResourceMetadataURL string
// Scopes are the required scopes for this resource/operation
Scopes []string
// Error indicates the error type (e.g., "insufficient_scope")
Error string
// ErrorDescription provides human-readable error details
ErrorDescription string
}
WWWAuthenticateChallenge represents parsed WWW-Authenticate header information