mcp

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: Mar 6, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

README

x402/mcp

MCP (Model Context Protocol) integration for the x402 payment protocol. This package enables paid tool calls in MCP servers and automatic payment handling in MCP clients.

Installation

go get github.com/coinbase/x402/go/mcp

Quick Start

Server - Using Payment Wrapper
package main

import (
    "context"
    "github.com/coinbase/x402/go/mcp"
    mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp"
)

func main() {
    // Create x402 resource server
    resourceServer := x402.Newx402ResourceServer(...)
    resourceServer.Register("eip155:84532", evmServerScheme)
    
    // Build payment requirements
    accepts, _ := resourceServer.BuildPaymentRequirementsFromConfig(ctx, config)

    // Create payment wrapper
    wrapper := mcp.NewPaymentWrapper(resourceServer, mcp.PaymentWrapperConfig{
        Accepts: accepts,
        Resource: &mcp.ResourceInfo{URL: "mcp://tool/get_weather", Description: "Get weather"},
    })

    // Register paid tool - wrap handler (SDK-style)
    mcpServer.AddTool(&mcpsdk.Tool{Name: "get_weather", ...}, wrapper.Wrap(
        func(ctx context.Context, req *mcpsdk.CallToolRequest) (*mcpsdk.CallToolResult, error) {
            return &mcpsdk.CallToolResult{
                Content: []mcpsdk.Content{&mcpsdk.TextContent{Text: "Result"}},
            }, nil
        },
    ))
}
Client - Wrap Session with x402
package main

import (
    "context"
    "fmt"
    "log"
    "github.com/coinbase/x402/go/mcp"
    mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp"
)

func main() {
    // Connect to MCP server using the official SDK
    mcpClient := mcpsdk.NewClient(&mcpsdk.Implementation{
        Name: "my-agent", Version: "1.0.0",
    }, nil)
    session, err := mcpClient.Connect(ctx, transport, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer session.Close()

    // Wrap session with x402 payment handling (AutoPayment defaults to true)
    x402Mcp := mcp.NewX402MCPClientFromConfig(session, []mcp.SchemeRegistration{
        {Network: "eip155:84532", Client: evmClientScheme},
    }, mcp.Options{})

    // Call tools - payment handled automatically
    ctx := context.Background()
    result, err := x402Mcp.CallTool(ctx, "get_weather", map[string]interface{}{
        "city": "NYC",
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(result)
}

API Reference

Client
NewX402MCPClient

Creates an x402 MCP client from an MCP session (MCPCaller) and payment client.

paymentClient := x402.Newx402Client()
paymentClient.Register("eip155:84532", evmClientScheme)

x402Mcp := mcp.NewX402MCPClient(session, paymentClient, mcp.Options{})
NewX402MCPClientFromConfig

Creates a fully configured x402 MCP client with scheme registrations. Pass *mcp.ClientSession from the official MCP SDK.

x402Mcp := mcp.NewX402MCPClientFromConfig(session, []mcp.SchemeRegistration{
    {Network: "eip155:84532", Client: evmClientScheme},
}, mcp.Options{}) // AutoPayment defaults to true
Server
NewPaymentWrapper + Wrap

For servers using the official modelcontextprotocol/go-sdk. The MCP SDK's AddTool expects handlers with signature (ctx, *mcp.CallToolRequest) → (*mcp.CallToolResult, error).

Supports server hooks (OnBeforeExecution, OnAfterExecution, OnAfterSettlement):

wrapper := mcp.NewPaymentWrapper(resourceServer, mcp.PaymentWrapperConfig{
    Accepts: accepts,
    Resource: &mcp.ResourceInfo{URL: "mcp://tool/get_weather", Description: "Get weather"},
    Hooks: &mcp.PaymentWrapperHooks{
        OnBeforeExecution: &beforeExecHook,
        OnAfterExecution:  &afterExecHook,
        OnAfterSettlement: &afterSettleHook,
    },
})
wrappedHandler := wrapper.Wrap(func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    return &mcp.CallToolResult{Content: []mcp.Content{&mcp.TextContent{Text: "result"}}}, nil
})
mcpServer.AddTool(tool, wrappedHandler)
Utilities
Error Handling
// Create payment required error
err := mcp.CreatePaymentRequiredError("Payment required", &paymentRequired)

// Check if error is payment required
if mcp.IsPaymentRequiredError(err) {
    paymentErr := err.(*mcp.PaymentRequiredError)
    // Handle payment required
}

// Extract PaymentRequired from JSON-RPC error
pr, err := mcp.ExtractPaymentRequiredFromError(jsonRpcError)
Type Guards
// Check if value is an object
if mcp.IsObject(value) {
    obj := value.(map[string]interface{})
    // Use obj
}

Constants

  • MCP_PAYMENT_REQUIRED_CODE - JSON-RPC error code for payment required (402)
  • MCP_PAYMENT_META_KEY - MCP _meta key for payment payload ("x402/payment")
  • MCP_PAYMENT_RESPONSE_META_KEY - MCP _meta key for payment response ("x402/payment-response")

Types

Client Types
  • X402MCPClient - x402-enabled MCP client
  • Options - Options for x402 MCP client behavior (AutoPayment defaults to true)
  • SchemeRegistration - Payment scheme registration for factory functions
  • MCPToolCallResult - Result of a tool call with payment metadata
  • PaymentRequiredContext - Context provided to payment required hooks
  • PaymentRequiredHookResult - Result from payment required hook
Server Types
  • PaymentWrapperConfig - Configuration for payment wrapper
  • ServerHookContext - Context provided to server-side hooks
  • AfterExecutionContext - Context for after execution hook
  • SettlementContext - Context for settlement hooks
Hook Types
  • PaymentRequiredHook - Hook called when payment is required
  • BeforePaymentHook - Hook called before payment creation
  • AfterPaymentHook - Hook called after payment submission
  • BeforeExecutionHook - Hook called before tool execution
  • AfterExecutionHook - Hook called after tool execution
  • AfterSettlementHook - Hook called after settlement

Examples

See the examples directory for complete examples.

License

Copyright (c) Coinbase, Inc.

Documentation

Overview

Package mcp provides MCP (Model Context Protocol) transport integration for the x402 payment protocol.

This package enables paid tool calls in MCP servers and automatic payment handling in MCP clients.

Client Usage

Wrap an MCP session with payment handling:

import (
    "context"
    "github.com/GoPlausible/x402-avm/go/mcp"
    mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp"
)

// Connect to MCP server using the official SDK
mcpClient := mcpsdk.NewClient(&mcpsdk.Implementation{Name: "my-agent", Version: "1.0.0"}, nil)
session, _ := mcpClient.Connect(ctx, transport, nil)

// Wrap session with x402 (AutoPayment defaults to true)
x402Mcp := mcp.NewX402MCPClientFromConfig(session, []mcp.SchemeRegistration{
    {Network: "eip155:84532", Client: evmClientScheme},
}, mcp.Options{})

// Call tools - payment handled automatically
result, err := x402Mcp.CallTool(ctx, "get_weather", map[string]interface{}{"city": "NYC"})

Server Usage

Wrap tool handlers with payment:

import (
    "context"
    x402 "github.com/GoPlausible/x402-avm/go"
    "github.com/GoPlausible/x402-avm/go/mcp"
)

// Create resource server
resourceServer := x402.Newx402ResourceServer(facilitatorClient)
resourceServer.Register("eip155:84532", evmServerScheme)

// Build payment requirements
accepts, _ := resourceServer.BuildPaymentRequirements(ctx, config)

// Create payment wrapper
wrapper := mcp.NewPaymentWrapper(resourceServer, mcp.PaymentWrapperConfig{
    Accepts: accepts,
})

// Register paid tool
mcpServer.AddTool(tool, wrapper.Wrap(func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    return &mcp.CallToolResult{Content: []mcp.Content{&mcp.TextContent{Text: "result"}}}, nil
}))

Factory Functions

NewX402MCPClientFromConfig creates a client with scheme registrations:

x402Mcp := mcp.NewX402MCPClientFromConfig(session, []mcp.SchemeRegistration{
    {Network: "eip155:84532", Client: evmClientScheme},
}, mcp.Options{})

Convenience Re-exports

This package re-exports commonly used types from the x402 core package for convenience:

import "github.com/GoPlausible/x402-avm/go/mcp"

// Re-exported types available:
// - x402.X402Client (via x402 package)
// - x402.X402ResourceServer (via x402 package)
// - types.PaymentPayload, types.PaymentRequired, types.PaymentRequirements (via types package)

Package mcp provides MCP (Model Context Protocol) integration for x402.

Server-side: Use NewPaymentWrapper to wrap MCP tool handlers with automatic x402 payment verification and settlement.

Client-side: Use CallPaidTool to make MCP tool calls with automatic x402 payment handling.

Index

Constants

View Source
const (
	// PaymentMetaKey is the _meta key for sending payment payloads (client -> server).
	PaymentMetaKey = "x402/payment"

	// PaymentResponseMetaKey is the _meta key for settlement responses (server -> client).
	PaymentResponseMetaKey = "x402/payment-response"
)

MCP meta key constants for x402 payment protocol.

View Source
const (
	// MCP_PAYMENT_REQUIRED_CODE is the JSON-RPC error code for payment required (x402)
	MCP_PAYMENT_REQUIRED_CODE = 402

	// MCP_PAYMENT_META_KEY is the MCP _meta key for payment payload (client → server)
	MCP_PAYMENT_META_KEY = "x402/payment"

	// MCP_PAYMENT_RESPONSE_META_KEY is the MCP _meta key for payment response (server → client)
	MCP_PAYMENT_RESPONSE_META_KEY = "x402/payment-response"
)

Protocol constants for MCP x402 payment integration.

Variables

This section is empty.

Functions

func AttachPaymentToMeta

func AttachPaymentToMeta(params map[string]interface{}, payload types.PaymentPayload) map[string]interface{}

AttachPaymentToMeta attaches payment payload to request params

func BoolPtr

func BoolPtr(b bool) *bool

BoolPtr returns a pointer to the given bool value. This is a convenience helper for setting Options.AutoPayment.

Example:

options := mcp.Options{AutoPayment: mcp.BoolPtr(false)}

func CreateToolResourceUrl

func CreateToolResourceUrl(toolName string, customUrl string) string

CreateToolResourceUrl creates a resource URL for an MCP tool

func ExtractPaymentFromMeta

func ExtractPaymentFromMeta(params map[string]interface{}) (*types.PaymentPayload, error)

ExtractPaymentFromMeta extracts payment payload from MCP request _meta field

func ExtractPaymentRequiredFromError

func ExtractPaymentRequiredFromError(err interface{}) (*types.PaymentRequired, error)

ExtractPaymentRequiredFromError extracts PaymentRequired from an MCP JSON-RPC error.

This function checks if the error is a 402 payment required error and extracts the PaymentRequired data from the error's data field.

Example:

err := client.CallTool(ctx, "tool", args)
if pr := mcp.ExtractPaymentRequiredFromError(err); pr != nil {
    // Handle payment required
}

func ExtractPaymentRequiredFromResult

func ExtractPaymentRequiredFromResult(result MCPToolResult) (*types.PaymentRequired, error)

ExtractPaymentRequiredFromResult extracts PaymentRequired from tool result (dual format)

func ExtractPaymentResponseFromMeta

func ExtractPaymentResponseFromMeta(result MCPToolResult) (*x402.SettleResponse, error)

ExtractPaymentResponseFromMeta extracts settlement response from MCP result _meta

func IsObject

func IsObject(value interface{}) bool

IsObject checks if a value is a non-null object (map[string]interface{}).

Example:

if mcp.IsObject(value) {
    obj := value.(map[string]interface{})
    // Use obj
}

func IsPaymentRequiredError

func IsPaymentRequiredError(err error) bool

IsPaymentRequiredError checks if an error is a PaymentRequiredError.

Example:

err := client.CallTool(ctx, "tool", args)
if mcp.IsPaymentRequiredError(err) {
    var paymentErr *mcp.PaymentRequiredError
    errors.As(err, &paymentErr)
    // Handle payment required
}

Types

type AfterExecutionContext

type AfterExecutionContext struct {
	ServerHookContext
	Result MCPToolResult
}

AfterExecutionContext extends ServerHookContext with result

type AfterExecutionHook

type AfterExecutionHook func(context AfterExecutionContext) error

AfterExecutionHook is called after tool execution

type AfterPaymentContext

type AfterPaymentContext struct {
	ToolName       string
	PaymentPayload types.PaymentPayload
	Result         MCPToolResult
	SettleResponse *x402.SettleResponse
}

AfterPaymentContext is provided to after payment hooks

type AfterPaymentHook

type AfterPaymentHook func(context AfterPaymentContext) error

AfterPaymentHook is called after payment is submitted

type AfterSettlementHook

type AfterSettlementHook func(context SettlementContext) error

AfterSettlementHook is called after successful settlement

type BeforeExecutionHook

type BeforeExecutionHook func(context ServerHookContext) (bool, error)

BeforeExecutionHook is called before tool execution (can abort)

type BeforePaymentHook

type BeforePaymentHook func(context PaymentRequiredContext) error

BeforePaymentHook is called before payment is created

type DynamicPayTo

type DynamicPayTo func(context MCPToolContext) (string, error)

DynamicPayTo resolves a payTo address dynamically based on tool call context. Use this type for custom server implementations that need per-request recipient resolution.

type DynamicPrice

type DynamicPrice func(context MCPToolContext) (x402.Price, error)

DynamicPrice resolves a price dynamically based on tool call context. Use this type for custom server implementations that need per-request pricing.

type MCPCaller

type MCPCaller interface {
	CallTool(ctx context.Context, params *mcp.CallToolParams) (*mcp.CallToolResult, error)
}

MCPCaller is the interface for making MCP tool calls. This is satisfied by the official MCP SDK's *mcp.ClientSession.

type MCPContentItem

type MCPContentItem struct {
	Type string
	Text string
}

MCPContentItem represents an MCP content item

type MCPToolCallResult

type MCPToolCallResult struct {
	Content         []MCPContentItem
	IsError         bool
	PaymentResponse *x402.SettleResponse
	PaymentMade     bool
}

MCPToolCallResult represents the result of a tool call with payment metadata

type MCPToolContext

type MCPToolContext struct {
	ToolName  string
	Arguments map[string]interface{}
	Meta      map[string]interface{}
}

MCPToolContext provides context during tool execution

type MCPToolResult

type MCPToolResult struct {
	Content           []MCPContentItem
	IsError           bool
	Meta              map[string]interface{}
	StructuredContent map[string]interface{}
}

MCPToolResult represents an MCP tool call result

func AttachPaymentResponseToMeta

func AttachPaymentResponseToMeta(result MCPToolResult, response x402.SettleResponse) MCPToolResult

AttachPaymentResponseToMeta attaches settlement response to result

type Options

type Options struct {
	// AutoPayment enables automatic payment handling when a tool requires payment.
	// Defaults to true. When nil, defaults to true. Set to BoolPtr(false) to disable.
	AutoPayment *bool

	// OnPaymentRequested is called before creating a payment, allowing the caller
	// to approve or deny. Return (true, nil) to approve, (false, nil) to deny.
	OnPaymentRequested func(context PaymentRequiredContext) (bool, error)
}

Options configures x402MCPClient behavior

type PaymentRequiredContext

type PaymentRequiredContext struct {
	ToolName        string
	Arguments       map[string]interface{}
	PaymentRequired types.PaymentRequired
}

PaymentRequiredContext is provided to onPaymentRequired hooks

type PaymentRequiredError

type PaymentRequiredError struct {
	Code            int
	Message         string
	PaymentRequired *types.PaymentRequired
}

PaymentRequiredError represents a payment required error

func CreatePaymentRequiredError

func CreatePaymentRequiredError(message string, paymentRequired *types.PaymentRequired) *PaymentRequiredError

CreatePaymentRequiredError creates a PaymentRequiredError with the given message and payment required data.

Example:

err := mcp.CreatePaymentRequiredError("Payment required", &paymentRequired)
return nil, err

func (*PaymentRequiredError) Error

func (e *PaymentRequiredError) Error() string

type PaymentRequiredHook

type PaymentRequiredHook func(context PaymentRequiredContext) (*PaymentRequiredHookResult, error)

PaymentRequiredHook is called when a 402 response is received

type PaymentRequiredHookResult

type PaymentRequiredHookResult struct {
	Payment *types.PaymentPayload
	Abort   bool
}

PaymentRequiredHookResult is returned from payment required hooks

type PaymentWrapper

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

PaymentWrapper wraps MCP tool handlers with x402 payment verification and settlement.

func NewPaymentWrapper

func NewPaymentWrapper(server *x402.X402ResourceServer, config PaymentWrapperConfig) *PaymentWrapper

NewPaymentWrapper creates a new payment wrapper for MCP tool handlers.

Example:

wrapper := mcp402.NewPaymentWrapper(resourceServer, mcp402.PaymentWrapperConfig{
    Accepts:  weatherAccepts,
    Resource: &types.ResourceInfo{URL: "mcp://tool/get_weather", Description: "Get weather"},
})

wrappedHandler := wrapper.Wrap(func(ctx context.Context, request *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    // extract args from request.Params.Arguments
    return &mcp.CallToolResult{Content: []mcp.Content{&mcp.TextContent{Text: "result"}}}, nil
})

func (*PaymentWrapper) Wrap

func (w *PaymentWrapper) Wrap(handler ToolHandler) ToolHandler

Wrap wraps a tool handler with x402 payment verification and settlement. The returned handler can be used directly with mcpServer.AddTool().

Flow:

  1. Extracts x402/payment from request _meta
  2. If no payment, returns 402 payment required error
  3. Verifies payment via facilitator
  4. OnBeforeExecution hook (if configured)
  5. Executes the original handler
  6. OnAfterExecution hook (if configured)
  7. Settles payment via facilitator
  8. OnAfterSettlement hook (if configured)
  9. Returns result with settlement info in _meta

type PaymentWrapperConfig

type PaymentWrapperConfig struct {
	Accepts  []types.PaymentRequirements
	Resource *ResourceInfo
	Hooks    *PaymentWrapperHooks
}

PaymentWrapperConfig configures payment wrapper behavior

type PaymentWrapperHooks

type PaymentWrapperHooks struct {
	OnBeforeExecution *BeforeExecutionHook
	OnAfterExecution  *AfterExecutionHook
	OnAfterSettlement *AfterSettlementHook
}

PaymentWrapperHooks provides server-side hooks

type ResourceInfo

type ResourceInfo = types.ResourceInfo

ResourceInfo provides resource metadata. Alias for types.ResourceInfo for compatibility.

type SchemeRegistration

type SchemeRegistration struct {
	Network     x402.Network
	Client      x402.SchemeNetworkClient
	ClientV1    x402.SchemeNetworkClientV1
	X402Version int // 1 or 2 (defaults to 2)
}

SchemeRegistration represents a payment scheme registration

type ServerHookContext

type ServerHookContext struct {
	ToolName            string
	Arguments           map[string]interface{}
	PaymentRequirements types.PaymentRequirements
	PaymentPayload      types.PaymentPayload
}

ServerHookContext is provided to server-side hooks

type SettlementContext

type SettlementContext struct {
	ServerHookContext
	Settlement x402.SettleResponse
}

SettlementContext extends ServerHookContext with settlement

type ToolCallResult

type ToolCallResult struct {
	// Content is the list of content items from the tool response.
	Content []mcp.Content

	// IsError indicates whether the tool returned an error.
	IsError bool

	// PaymentResponse is the settlement response if payment was made.
	PaymentResponse *x402.SettleResponse

	// PaymentMade indicates whether a payment was made during this call.
	PaymentMade bool

	// RawResult is the original MCP CallToolResult.
	RawResult *mcp.CallToolResult
}

ToolCallResult is the result of a paid MCP tool call.

func CallPaidTool

func CallPaidTool(
	ctx context.Context,
	mcpClient MCPCaller,
	x402Client *x402.X402Client,
	name string,
	args map[string]any,
) (*ToolCallResult, error)

CallPaidTool makes an MCP tool call with automatic x402 payment handling.

Flow:

  1. Calls the tool without payment
  2. If the server returns a payment required error, creates a payment
  3. Retries with payment attached in _meta
  4. Returns the result with payment response extracted

Example:

result, err := mcp402.CallPaidTool(ctx, session, x402Client, "get_weather", map[string]any{"city": "SF"})
if err != nil {
    log.Fatal(err)
}
fmt.Println(result.PaymentResponse.Transaction)

type ToolHandler

type ToolHandler = mcp.ToolHandler

ToolHandler is the function signature for MCP tool handlers. This is an alias for the official MCP SDK's mcp.ToolHandler type.

type X402MCPClient

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

X402MCPClient wraps an MCP session (MCPCaller) with automatic x402 payment handling. Use NewX402MCPClient or NewX402MCPClientFromConfig with *mcp.ClientSession.

func NewX402MCPClient

func NewX402MCPClient(caller MCPCaller, paymentClient *x402.X402Client, options Options) *X402MCPClient

NewX402MCPClient creates an x402-aware MCP client.

func NewX402MCPClientFromConfig

func NewX402MCPClientFromConfig(caller MCPCaller, schemes []SchemeRegistration, options Options) *X402MCPClient

NewX402MCPClientFromConfig creates an x402-aware MCP client from scheme registrations.

func (*X402MCPClient) CallTool

func (c *X402MCPClient) CallTool(ctx context.Context, name string, args map[string]interface{}) (*MCPToolCallResult, error)

CallTool calls a tool with automatic payment handling.

func (*X402MCPClient) CallToolWithPayment

func (c *X402MCPClient) CallToolWithPayment(ctx context.Context, name string, args map[string]interface{}, payload types.PaymentPayload) (*MCPToolCallResult, error)

CallToolWithPayment calls a tool with a pre-created payment payload.

func (*X402MCPClient) Client

func (c *X402MCPClient) Client() MCPCaller

Client returns the underlying MCP caller (e.g. *mcp.ClientSession).

func (*X402MCPClient) GetToolPaymentRequirements

func (c *X402MCPClient) GetToolPaymentRequirements(ctx context.Context, name string, args map[string]interface{}) (*types.PaymentRequired, error)

GetToolPaymentRequirements fetches payment requirements for a tool without paying.

func (*X402MCPClient) OnAfterPayment

func (c *X402MCPClient) OnAfterPayment(hook AfterPaymentHook) *X402MCPClient

OnAfterPayment registers a hook called after payment is submitted.

func (*X402MCPClient) OnBeforePayment

func (c *X402MCPClient) OnBeforePayment(hook BeforePaymentHook) *X402MCPClient

OnBeforePayment registers a hook called before creating payment.

func (*X402MCPClient) OnPaymentRequired

func (c *X402MCPClient) OnPaymentRequired(hook PaymentRequiredHook) *X402MCPClient

OnPaymentRequired registers a hook called when payment is required.

func (*X402MCPClient) PaymentClient

func (c *X402MCPClient) PaymentClient() *x402.X402Client

PaymentClient returns the underlying x402 payment client.

Jump to

Keyboard shortcuts

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