agent

package
v0.0.116 Latest Latest
Warning

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

Go to latest
Published: Jul 9, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

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

View Source
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

View Source
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 PrettyJSON

func PrettyJSON(v interface{}) string

PrettyJSON pretty-prints JSON for logging

func SupportsClientIDMetadata

func SupportsClientIDMetadata(asMetadata *AuthorizationServerMetadata) bool

SupportsClientIDMetadata checks if the Authorization Server supports Client ID Metadata Documents based on its metadata.

func ValidateCIMDConsistency

func ValidateCIMDConsistency(ctx context.Context, cimdURL string) error

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

func ValidateClientIDURL(clientIDURL string) error

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):

  1. OAuth 2.0 with path insertion: https://auth.example.com/.well-known/oauth-authorization-server/tenant1
  2. OIDC with path insertion: https://auth.example.com/.well-known/openid-configuration/tenant1
  3. OIDC path appending: https://auth.example.com/tenant1/.well-known/openid-configuration

For issuer URLs without path components (e.g., https://auth.example.com):

  1. OAuth 2.0: https://auth.example.com/.well-known/oauth-authorization-server
  2. 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

func (c *Client) GetResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)

GetResource retrieves a resource by URI, with reconnection logic.

func (*Client) Listen

func (c *Client) Listen(ctx context.Context) error

func (*Client) Reconnect

func (c *Client) Reconnect(ctx context.Context) error

func (*Client) Run

func (c *Client) Run(ctx context.Context) error

Run executes the agent workflow

func (*Client) ServerSupportsPrompts

func (c *Client) ServerSupportsPrompts() bool

func (*Client) ServerSupportsResources

func (c *Client) ServerSupportsResources() bool

func (*Client) ServerSupportsTools

func (c *Client) ServerSupportsTools() bool

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:

  1. Hosted at the client_id URL for AS discovery
  2. Generated for user review/manual hosting
  3. Used as template for custom configurations

type Logger

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

Logger provides formatted logging for the agent

func NewLogger

func NewLogger(verbose, useColor, jsonRPCMode bool) *Logger

NewLogger creates a new logger

func NewLoggerWithWriter

func NewLoggerWithWriter(verbose, useColor, jsonRPCMode bool, writer io.Writer) *Logger

NewLoggerWithWriter creates a new logger with a custom writer

func (*Logger) Debug

func (l *Logger) Debug(format string, args ...interface{})

Debug logs a debug message (only in verbose mode)

func (*Logger) Error

func (l *Logger) Error(format string, args ...interface{})

Error logs an error message

func (*Logger) Info

func (l *Logger) Info(format string, args ...interface{})

Info logs an informational message

func (*Logger) InfoVerbose

func (l *Logger) InfoVerbose(format string, args ...interface{})

InfoVerbose logs an informational message only in verbose mode

func (*Logger) Notification

func (l *Logger) Notification(method string, params interface{})

Notification logs an incoming notification

func (*Logger) Request

func (l *Logger) Request(method string, params interface{})

Request logs an outgoing request

func (*Logger) Response

func (l *Logger) Response(method string, result interface{})

Response logs an incoming response

func (*Logger) SetVerbose

func (l *Logger) SetVerbose(verbose bool)

SetVerbose sets the verbose mode

func (*Logger) SetWriter

func (l *Logger) SetWriter(w io.Writer)

SetWriter sets a custom writer for the logger

func (*Logger) Success

func (l *Logger) Success(format string, args ...interface{})

Success logs a success message

func (*Logger) Warning

func (l *Logger) Warning(format string, args ...interface{})

Warning logs a warning message with yellow highlighting

func (*Logger) WarningVerbose

func (l *Logger) WarningVerbose(format string, args ...interface{})

WarningVerbose logs a warning message only in verbose mode

func (*Logger) Write

func (l *Logger) Write(p []byte) (n int, err error)

Write implements io.Writer for compatibility

type MCPServer

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

MCPServer wraps the agent functionality and exposes it via MCP

func NewMCPServer

func NewMCPServer(client *Client, serverTransport string, logger *Logger, notifyClients bool) (*MCPServer, error)

NewMCPServer creates a new MCP server that exposes agent functionality

func (*MCPServer) Start

func (m *MCPServer) Start(ctx context.Context, listenAddr string) error

Start starts the MCP server using stdio or streamable-http transport

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

func NewREPL

func NewREPL(client *Client, logger *Logger) *REPL

NewREPL creates a new REPL instance

func (*REPL) Run

func (r *REPL) Run(ctx context.Context) error

Run starts the REPL

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

Jump to

Keyboard shortcuts

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