Documentation
¶
Overview ¶
Package atxp is a client for paid ATXP MCP tools (web search, image/video/music generation, etc.) using a hosted ATXP account (a connection string).
The hosted-account model means this client performs no on-chain crypto: every signing and settlement operation is an HTTP call to the ATXP accounts server. See docs/PROTOCOL.md for the full protocol, with file:line references into the reference TypeScript SDK (github.com/atxp-dev/sdk).
The shape mirrors the TS @atxp/client: an http.RoundTripper (transport.go) wraps an MCP Streamable HTTP transport and transparently handles the two legs of the protocol — OAuth authentication (oauth.go) and payment challenges (account.Authorize → the accounts server's /authorize/auto).
Index ¶
- type ATXPAccount
- func (a *ATXPAccount) AccountID(ctx context.Context) (string, error)
- func (a *ATXPAccount) Authorize(ctx context.Context, p AuthorizeParams) (AuthorizeResult, error)
- func (a *ATXPAccount) Origin() string
- func (a *ATXPAccount) SignChallenge(ctx context.Context, codeChallenge string) (string, error)
- func (a *ATXPAccount) SpendPermission(ctx context.Context, resourceURL string) (string, error)
- type AccessToken
- type Account
- type AuthorizeParams
- type AuthorizeResult
- type Client
- type ClientCredentials
- type Config
- type HybridAccount
- func (h *HybridAccount) AccountID(ctx context.Context) (string, error)
- func (h *HybridAccount) Authorize(ctx context.Context, p AuthorizeParams) (AuthorizeResult, error)
- func (h *HybridAccount) SignChallenge(ctx context.Context, codeChallenge string) (string, error)
- func (h *HybridAccount) SpendPermission(ctx context.Context, resourceURL string) (string, error)
- type MemoryStore
- func (s *MemoryStore) GetAccessToken(userID, u string) (AccessToken, bool)
- func (s *MemoryStore) GetClientCredentials(issuer string) (ClientCredentials, bool)
- func (s *MemoryStore) GetPKCE(userID, state string) (PKCEValues, bool)
- func (s *MemoryStore) SaveAccessToken(userID, u string, t AccessToken)
- func (s *MemoryStore) SaveClientCredentials(issuer string, c ClientCredentials)
- func (s *MemoryStore) SavePKCE(userID, state string, v PKCEValues)
- type PKCEValues
- type RestrictionError
- type Store
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ATXPAccount ¶
type ATXPAccount struct {
// contains filtered or unexported fields
}
ATXPAccount is a hosted account identified by a connection string of the form
https://accounts.atxp.ai/?connection_token=<TOKEN>&account_id=<ID>
account_id is optional and resolved from /me on first use.
func NewATXPAccount ¶
func NewATXPAccount(connectionString string, hc *http.Client) (*ATXPAccount, error)
NewATXPAccount parses a connection string into a hosted account. The http client is used for all accounts-server calls; pass nil for http.DefaultClient.
func (*ATXPAccount) AccountID ¶
func (a *ATXPAccount) AccountID(ctx context.Context) (string, error)
func (*ATXPAccount) Authorize ¶
func (a *ATXPAccount) Authorize(ctx context.Context, p AuthorizeParams) (AuthorizeResult, error)
func (*ATXPAccount) Origin ¶
func (a *ATXPAccount) Origin() string
Origin is the accounts-server base URL (e.g. https://accounts.atxp.ai).
func (*ATXPAccount) SignChallenge ¶
func (*ATXPAccount) SpendPermission ¶
type AccessToken ¶
type AccessToken struct {
ResourceURL string
AccessToken string
RefreshToken string
ExpiresAt int64 // unix seconds, 0 = unknown
}
AccessToken is a stored OAuth token for a (userID, resource) pair.
type Account ¶
type Account interface {
// AccountID returns the qualified account id ("atxp:<id>"), fetching it from
// the accounts server's /me endpoint if it was not in the connection string.
AccountID(ctx context.Context) (string, error)
// SignChallenge asks the accounts server to mint the JWT that authorizes the
// OAuth /authorize GET, binding the PKCE code_challenge to this account.
SignChallenge(ctx context.Context, codeChallenge string) (jwt string, err error)
// SpendPermission pre-authorizes spending for an MCP server during OAuth.
// Returns "" (no error) if the account type does not support it.
SpendPermission(ctx context.Context, resourceURL string) (token string, err error)
// Authorize settles a payment challenge via /authorize/auto and returns the
// protocol + opaque credential to attach to the retried request.
Authorize(ctx context.Context, p AuthorizeParams) (AuthorizeResult, error)
}
Account is the credential + payment backend the transport delegates to. Only the hosted ATXPAccount is implemented; the interface keeps the transport decoupled from it (and leaves room for a future self-custodial account).
type AuthorizeParams ¶
type AuthorizeParams struct {
Protocols []string // "atxp", and optionally "x402"/"mpp"
Amount string // decimal string, e.g. "0.01"
Destination string // receiver address (maps to "receiver")
Memo string // issuer / payee name
PaymentRequirements json.RawMessage // x402 { x402Version, accepts } if present
Challenges json.RawMessage // mpp challenges array if present
}
AuthorizeParams is the payment-challenge data sent to /authorize/auto.
type AuthorizeResult ¶
type AuthorizeResult struct {
Protocol string `json:"protocol"` // "atxp" | "x402" | "mpp"
Credential string `json:"credential"`
Context json.RawMessage `json:"context,omitempty"`
}
AuthorizeResult is the credential returned by /authorize/auto.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client connects to ATXP MCP tool servers, transparently handling OAuth and per-call payments. account is the Account interface, not the concrete hosted ATXPAccount, so NewWithAccount can hand in a different backend (e.g. a self-custodial x402 signer) while reusing this same transport/OAuth glue.
func NewWithAccount ¶
NewWithAccount builds a Client backed by any Account implementation (e.g. a self-custodial signer from a subpackage like x402signer) instead of the hosted ATXPAccount. cfg.ConnectionString is ignored; the other Config fields (HTTPClient, Store, CallbackURL) still apply.
func (*Client) Connect ¶
Connect opens an MCP session to the given ATXP tool server (e.g. "https://search.mcp.atxp.ai/"). Payments and auth are handled transparently on each tool call. The caller owns the returned session and must Close it.
func (*Client) HTTPClient ¶
HTTPClient returns an *http.Client whose transport performs the ATXP OAuth + payment handshake. It can be handed to any HTTP-based MCP transport, or used directly against ATXP REST endpoints.
type ClientCredentials ¶
type ClientCredentials struct {
ClientID string
ClientSecret string // empty for a public client
RedirectURI string
}
ClientCredentials are the dynamic-client-registration result for an authorization server, keyed by the server's issuer.
type Config ¶
type Config struct {
// ConnectionString is the hosted-account credential, e.g.
// "https://accounts.atxp.ai/?connection_token=...&account_id=...".
ConnectionString string
// HTTPClient is used for accounts-server and OAuth calls. Optional.
HTTPClient *http.Client
// Store persists OAuth tokens/credentials. Defaults to an in-memory store.
Store Store
// CallbackURL is the OAuth redirect_uri registered with the auth server.
// It is never actually navigated (ATXP returns the code directly), so the
// default placeholder is fine.
CallbackURL string
}
Config configures an ATXP client.
type HybridAccount ¶
type HybridAccount struct {
// Identity supplies AccountID, SignChallenge, and SpendPermission — the
// OAuth-handshake half.
Identity Account
// Payments supplies Authorize — the actual payment-signing half.
Payments Account
}
HybridAccount composes OAuth identity from one Account with payment authorization from another. It exists for the case where the account capable of completing the OAuth handshake (typically an ATXPAccount) is not the account that should actually pay: a self-custodial signer (e.g. x402signer.X402SignerAccount) has no ATXP identity of its own and cannot complete an OAuth handshake (see x402signer's package doc), but a resource gated behind an OAuth 401 still requires one before it ever issues a payment challenge.
An ATXPAccount for Identity plus an x402signer.X402SignerAccount for Payments is a live-verified combination: it settles a real x402 payment against an OAuth-gated third-party merchant, confirmed on-chain.
If the resource is gated purely by a bare 402 (no OAuth 401 first), Payments alone is sufficient and HybridAccount is unnecessary.
func (*HybridAccount) AccountID ¶
func (h *HybridAccount) AccountID(ctx context.Context) (string, error)
func (*HybridAccount) Authorize ¶
func (h *HybridAccount) Authorize(ctx context.Context, p AuthorizeParams) (AuthorizeResult, error)
func (*HybridAccount) SignChallenge ¶
func (*HybridAccount) SpendPermission ¶
type MemoryStore ¶
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore is a process-local Store.
func NewMemoryStore ¶
func NewMemoryStore() *MemoryStore
NewMemoryStore returns an empty in-memory Store.
func (*MemoryStore) GetAccessToken ¶
func (s *MemoryStore) GetAccessToken(userID, u string) (AccessToken, bool)
GetAccessToken returns the token for the exact path, falling back to parent paths up to the origin — mirroring oAuthResource.ts getAccessToken.
func (*MemoryStore) GetClientCredentials ¶
func (s *MemoryStore) GetClientCredentials(issuer string) (ClientCredentials, bool)
func (*MemoryStore) GetPKCE ¶
func (s *MemoryStore) GetPKCE(userID, state string) (PKCEValues, bool)
func (*MemoryStore) SaveAccessToken ¶
func (s *MemoryStore) SaveAccessToken(userID, u string, t AccessToken)
func (*MemoryStore) SaveClientCredentials ¶
func (s *MemoryStore) SaveClientCredentials(issuer string, c ClientCredentials)
func (*MemoryStore) SavePKCE ¶
func (s *MemoryStore) SavePKCE(userID, state string, v PKCEValues)
type PKCEValues ¶
type PKCEValues struct {
URL string // the resource URL the flow was started for (token key)
CodeVerifier string
CodeChallenge string
ResourceURL string
}
PKCEValues are the per-authorization values stashed between building the authorization URL and handling the callback, keyed by OAuth state.
type RestrictionError ¶
type RestrictionError struct {
Op string // the operation, e.g. "/sign"
Code string // restriction.error, e.g. "fraud_blocked"
Message string // human-readable restriction.message
}
RestrictionError is returned when the accounts server rejects an operation because the account is restricted (e.g. a fresh, unverified account is "fraud_blocked" until a payment method is added). It is environmental, not a client bug: the request was well-formed and the server processed it.
func (*RestrictionError) Error ¶
func (e *RestrictionError) Error() string
type Store ¶
type Store interface {
SavePKCE(userID, state string, v PKCEValues)
GetPKCE(userID, state string) (PKCEValues, bool)
SaveClientCredentials(issuer string, c ClientCredentials)
GetClientCredentials(issuer string) (ClientCredentials, bool)
SaveAccessToken(userID, url string, t AccessToken)
GetAccessToken(userID, url string) (AccessToken, bool)
}
Store persists OAuth state. The in-memory implementation mirrors the TS MemoryOAuthDb closely enough for a single process; a deliberation server that wants tokens to survive restarts can supply a backing implementation.
Token lookup walks parent paths so a token issued for a server root also satisfies requests to sub-paths (see GetAccessToken).
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
mcppay/client
command
Command mcppay-client pays for an MCP tool call whose payment challenge arrives inline in the CallToolResult, rather than as an HTTP 402.
|
Command mcppay-client pays for an MCP tool call whose payment challenge arrives inline in the CallToolResult, rather than as an HTTP 402. |
|
paidmcp
command
Command paidmcp is a minimal, real MCP server that charges callers over ATXP for a tool call, using chit's server package.
|
Command paidmcp is a minimal, real MCP server that charges callers over ATXP for a tool call, using chit's server package. |
|
paidmcp/client
command
Command paidmcp-client drives the payer side of the examples/paidmcp demo: connects to a running paidmcp server over ATXP and calls its "ping" tool, paying for it via the full OAuth + payment retry flow.
|
Command paidmcp-client drives the payer side of the examples/paidmcp demo: connects to a running paidmcp server over ATXP and calls its "ping" tool, paying for it via the full OAuth + payment retry flow. |
|
x402stranger
command
Command x402stranger is a minimal x402 merchant that proves the actual promise of self-custodial x402 payments: a caller with no ATXP account, no OAuth relationship, and no prior interaction with this merchant can still pay for a resource and receive it.
|
Command x402stranger is a minimal x402 merchant that proves the actual promise of self-custodial x402 payments: a caller with no ATXP account, no OAuth relationship, and no prior interaction with this merchant can still pay for a resource and receive it. |
|
x402stranger/client
command
Command x402stranger-client pays for examples/x402stranger's resource with nothing but a raw private key: no ATXP account, no OAuth, no prior relationship with the merchant at all.
|
Command x402stranger-client pays for examples/x402stranger's resource with nothing but a raw private key: no ATXP account, no OAuth, no prior relationship with the merchant at all. |
|
Package server is the merchant/server side of chit — the half that charges callers over ATXP.
|
Package server is the merchant/server side of chit — the half that charges callers over ATXP. |
|
Package x402signer is a self-custodial x402 "exact"-scheme Account for chit's client.
|
Package x402signer is a self-custodial x402 "exact"-scheme Account for chit's client. |