Help us shape the future of Go! Take the 2026 Go Developer Survey

client

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Nov 2, 2026 License: MIT, Apache-2.0, MIT Imports: 19 Imported by: 0

Documentation

Overview

Package client pays for MCP tool calls made with the official MCP Go SDK (github.com/modelcontextprotocol/go-sdk), matching mppx's McpClient.wrap.

Wrap installs sending middleware on an *mcp.Client, so every session it connects, and every CallTool on them, handles payment challenges whether they arrive as payment-required JSON-RPC errors (-32042 or -32043) or as tool results carrying _meta["org.paymentauth/payment-required"]. The client pays with a configured method and retries the call with the Credential in _meta["org.paymentauth/credential"]; Receipt reads the receipt from the result:

c := mcp.NewClient(&mcp.Implementation{Name: "my-client", Version: "1.0.0"}, nil)
mcpclient.Wrap(c, mcpclient.Config{Methods: []client.Method{method}})
session, err := c.Connect(ctx, transport, nil)
...
result, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "premium_tool"})
receipt, err := mcpclient.Receipt(result)

Middleware returns the same handling as sending middleware to install yourself, without Wrap's per-client registry:

c.AddSendingMiddleware(mcpclient.Middleware(mcpclient.Config{Methods: methods}))

A zero-amount Tempo proof authenticates the payer at the challenge realm, so the client binds it to the session that received the challenge: it signs one only for a session connected with Connect (a Streamable HTTP transport whose HTTP client refuses cross-origin redirects) and whose endpoint origin the payment method trusts for that realm (by default an HTTPS endpoint on the default port whose hostname is the realm; the Tempo method's Config.TrustedProofRealms adds others by origin). A server cannot relay another server's challenge through a shared client:

session, err := mcpclient.Connect(ctx, c, &mcp.StreamableClientTransport{
	Endpoint: "https://service.example/mcp",
}, nil)

Sessions without an endpoint (stdio, in-memory) get proofs only when Config.ValidateTempoProofSession authorizes them. A Streamable HTTP session whose client follows cross-origin redirects (http.DefaultClient does) never gets one, since a redirect could deliver it to another server.

Index

Constants

This section is empty.

Variables

View Source
var ErrPaymentDeclined = mppclient.ErrPaymentDeclined

ErrPaymentDeclined is returned, wrapped, when the approval hook declines a payment. It is client.ErrPaymentDeclined, which the HTTP client returns when an OnChallenge hook declines, so errors.Is matches either.

Functions

func Connect added in v0.7.0

Connect connects c to the Streamable HTTP endpoint of transport, like c.Connect, with the transport's HTTPClient (http.DefaultClient when nil) wrapped by HTTPClient so it refuses cross-origin redirects. Sessions connected this way get zero-amount Tempo proofs for realms their endpoint's origin is trusted for, with no other configuration. transport is copied, not modified.

func HTTPClient added in v0.7.0

func HTTPClient(base *http.Client) *http.Client

HTTPClient returns a copy of base (http.DefaultClient when nil) whose CheckRedirect refuses every redirect away from the origin of the request it follows, after base's own CheckRedirect (or net/http's 10-redirect limit). Connect sets it for you; otherwise give it to mcp.StreamableClientTransport as HTTPClient: zero-amount Tempo proofs are signed only for Streamable HTTP sessions whose client refuses cross-origin redirects, since a redirect would deliver the proof to another server than the endpoint whose origin vouched for the realm.

It is not inlined, so every client it returns shares one CheckRedirect code pointer, which refusesCrossOriginRedirects recognizes.

func IsPaymentRequiredError

func IsPaymentRequiredError(err error) bool

IsPaymentRequiredError reports whether err is an MCP payment-required or payment-verification-failed error that carries at least one Challenge.

func Middleware added in v0.6.0

func Middleware(config Config) mcp.Middleware

Middleware returns sending middleware that pays for tool calls, to install with c.AddSendingMiddleware(mcpclient.Middleware(config)). It is the explicit form of Wrap: every session of c, connected before or after, uses it, and installing it again adds a second payment layer rather than replacing the first.

func Receipt

func Receipt(result *mcp.CallToolResult) (*mpp.MCPReceipt, error)

Receipt returns the payment receipt in a tool result's _meta["org.paymentauth/receipt"], or nil when it has none.

func WithOnPaymentRequired

func WithOnPaymentRequired(ctx context.Context, fn OnPaymentRequired) context.Context

WithOnPaymentRequired returns a context whose tool calls use fn instead of Config.OnPaymentRequired. A nil fn pays without asking.

func Wrap

func Wrap(c *mcp.Client, config Config) *mcp.Client

Wrap adds automatic payment handling to tool calls made through sessions of c and returns c. Sessions connected before and after Wrap both use it. Calling Wrap again on the same client replaces its payment configuration. Middleware installs the same handling without Wrap's per-client registry.

Types

type Config

type Config struct {
	// Methods are the payment methods the client can pay with.
	Methods []mppclient.Method
	// OnPaymentRequired, when set, approves every payment before it is made.
	OnPaymentRequired OnPaymentRequired
	// OrderChallenges, when set, filters and sorts payable Challenges.
	OrderChallenges OrderChallenges
	// ValidateTempoProofSession, when set, also authorizes the session for a
	// zero-amount Tempo proof's realm before a proof is signed or reused;
	// return an error to refuse. Most clients leave it nil: a proof is then
	// bound to the session's transport, so only a session the client connected
	// with Connect (a StreamableClientTransport with HTTPClient's redirect guard), to
	// an endpoint whose origin the method trusts for the realm (by default an
	// HTTPS endpoint on the default port whose hostname is the realm), gets
	// one, whichever session relays the challenge. Set it for sessions without
	// an endpoint (stdio, in-memory or wrapped transports), which are otherwise
	// refused proofs. It cannot authorize a Streamable HTTP session whose
	// client follows cross-origin redirects, which is always refused; compare the
	// session pointer with sessions you connected yourself, never with a name
	// or realm the peer sent. WithOnPaymentRequired does not bypass it, and the
	// method's OriginValidator still runs with the session's origin.
	ValidateTempoProofSession func(context.Context, *mcp.ClientSession, string) error
	// PaymentPreferences ranks Challenges by "method/intent" q-values.
	PaymentPreferences mppclient.PaymentPreferences
}

Config configures payment handling for an MCP client.

type OnPaymentRequired

type OnPaymentRequired func(ctx context.Context, challenge *mpp.Challenge) (bool, error)

OnPaymentRequired approves a payment before a Credential is created for challenge. Returning false declines it.

type OrderChallenges

type OrderChallenges func(
	ctx context.Context,
	candidates []mppclient.ChallengeCandidate,
) ([]mppclient.ChallengeCandidate, error)

OrderChallenges filters and sorts the payable Challenges before one is paid; the first one returned that passes the realm checks is paid. It has the semantics and signature of client.OrderChallenges, which the HTTP client takes with client.WithOrderChallenges, so one hook converts to either: mcpclient.OrderChallenges(fn).

Jump to

Keyboard shortcuts

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