Skip to content

Commit c8b0ade

Browse files
committed
docs: Address CodeRabbit review feedback
- Strengthen dynamic auth test to assert exact token value - Add thread-safety documentation for AuthorizationProvider - Improve docstring coverage for MCP server facilitator types
1 parent e5f2874 commit c8b0ade

File tree

3 files changed

+36
-6
lines changed

3 files changed

+36
-6
lines changed

http/facilitator.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ import (
1818

1919
// AuthorizationProvider is a function that returns an Authorization header value.
2020
// This is useful for dynamic tokens (e.g., JWT refresh) where the value may change.
21+
//
22+
// Thread-safety: The provider function is called on each HTTP request, including
23+
// during retry attempts. If your provider accesses shared state or performs I/O
24+
// (e.g., token refresh), ensure it is safe for concurrent use. The FacilitatorClient
25+
// does not serialize calls to the provider.
2126
type AuthorizationProvider func() string
2227

2328
// FacilitatorClient is a client for communicating with x402 facilitator services.
@@ -39,6 +44,8 @@ type FacilitatorClient struct {
3944
}
4045

4146
// setAuthorizationHeader sets the Authorization header on the request if configured.
47+
// If AuthorizationProvider is set, it is called to get the current token value;
48+
// otherwise, the static Authorization string is used. This is called per-request.
4249
func (c *FacilitatorClient) setAuthorizationHeader(req *http.Request) {
4350
var authValue string
4451
if c.AuthorizationProvider != nil {

http/facilitator_test.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ func TestFacilitatorClient_Verify_WithAuthorizationProvider(t *testing.T) {
128128
return "Bearer dynamic-token-" + string(rune('0'+callCount))
129129
}
130130

131+
// Expected token for the first call
132+
expectedAuth := "Bearer dynamic-token-1"
133+
131134
// Create a mock facilitator server that validates the Authorization header
132135
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
133136
authHeader := r.Header.Get("Authorization")
@@ -137,6 +140,13 @@ func TestFacilitatorClient_Verify_WithAuthorizationProvider(t *testing.T) {
137140
return
138141
}
139142

143+
// Verify the dynamic token value is used and static is ignored
144+
if authHeader != expectedAuth {
145+
t.Errorf("Expected Authorization header %q, got %q", expectedAuth, authHeader)
146+
w.WriteHeader(http.StatusUnauthorized)
147+
return
148+
}
149+
140150
response := facilitator.VerifyResponse{
141151
IsValid: true,
142152
Payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66",
@@ -174,8 +184,8 @@ func TestFacilitatorClient_Verify_WithAuthorizationProvider(t *testing.T) {
174184
t.Fatalf("Verify failed: %v", err)
175185
}
176186

177-
if callCount == 0 {
178-
t.Error("Expected AuthorizationProvider to be called")
187+
if callCount != 1 {
188+
t.Errorf("Expected AuthorizationProvider to be called exactly once, got %d calls", callCount)
179189
}
180190
}
181191

mcp/server/facilitator.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Package server provides MCP server integration for x402 payment gating.
2+
// It enables payment-gated AI tools via the Model Context Protocol.
13
package server
24

35
import (
@@ -10,7 +12,9 @@ import (
1012
"github.com/mark3labs/x402-go/http"
1113
)
1214

13-
// Facilitator interface for payment verification and settlement
15+
// Facilitator defines the interface for payment verification and settlement.
16+
// Implementations communicate with an x402 facilitator service to verify
17+
// payment authorizations and execute settlements on the blockchain.
1418
type Facilitator interface {
1519
// Verify verifies a payment without settling it
1620
Verify(ctx context.Context, payment *x402.PaymentPayload, requirement x402.PaymentRequirement) (*facilitator.VerifyResponse, error)
@@ -19,12 +23,14 @@ type Facilitator interface {
1923
Settle(ctx context.Context, payment *x402.PaymentPayload, requirement x402.PaymentRequirement) (*x402.SettlementResponse, error)
2024
}
2125

22-
// HTTPFacilitator implements Facilitator using the http.FacilitatorClient
26+
// HTTPFacilitator implements the Facilitator interface using the http.FacilitatorClient.
27+
// It communicates with an x402 facilitator service over HTTP to verify and settle payments.
2328
type HTTPFacilitator struct {
2429
client *http.FacilitatorClient
2530
}
2631

27-
// HTTPFacilitatorOption configures an HTTPFacilitator
32+
// HTTPFacilitatorOption is a functional option for configuring an HTTPFacilitator.
33+
// Use WithAuthorization or WithAuthorizationProvider to set authentication.
2834
type HTTPFacilitatorOption func(*http.FacilitatorClient)
2935

3036
// WithAuthorization sets a static Authorization header value for the facilitator.
@@ -44,7 +50,14 @@ func WithAuthorizationProvider(provider http.AuthorizationProvider) HTTPFacilita
4450
}
4551
}
4652

47-
// NewHTTPFacilitator creates a new HTTP facilitator client
53+
// NewHTTPFacilitator creates a new HTTP facilitator client with the given URL and options.
54+
// The facilitator is used to verify and settle payments for payment-gated MCP tools.
55+
//
56+
// Example:
57+
//
58+
// facilitator := NewHTTPFacilitator("https://api.x402.coinbase.com",
59+
// WithAuthorization("Bearer my-api-key"),
60+
// )
4861
func NewHTTPFacilitator(facilitatorURL string, opts ...HTTPFacilitatorOption) *HTTPFacilitator {
4962
timeouts := x402.DefaultTimeouts
5063
client := &http.FacilitatorClient{

0 commit comments

Comments
 (0)