Documentation
¶
Overview ¶
Package server is the serving harness: it publishes MCP tools over Bison Relay private messages with default-deny authorization, per-caller rate limiting, and paid tools settled by Bison Relay tips against a prepaid per-caller balance (the built-in Ledger, or any store implementing Billing). RunBot serves a harness over a bisonbotkit bot; embedded hosts wire Harness.Start to their own client instead.
Index ¶
- Variables
- func AddTool[In any](h *Harness, tool *mcp.Tool, priceAtoms int64, ...)
- func AddToolPriced[In any](h *Harness, tool *mcp.Tool, price PriceFunc[In], ...)
- func ChargedAtoms(ctx context.Context) int64
- func RunBot(ctx context.Context, h *Harness, cfg *kitconfig.BotConfig) error
- type Billing
- type Harness
- type HarnessConfig
- type Ledger
- type PriceFunc
- type TipJournal
Constants ¶
This section is empty.
Variables ¶
var ErrInsufficient = errors.New("insufficient balance")
ErrInsufficient reports a debit larger than the caller's balance.
Functions ¶
func AddTool ¶
func AddTool[In any](h *Harness, tool *mcp.Tool, priceAtoms int64, fn func(ctx context.Context, peer string, in In) (any, error))
AddTool registers a tool with a fixed price. priceAtoms of zero makes it free; a positive price is advertised in _meta and enforced against the caller's balance before the handler runs.
func AddToolPriced ¶
func AddToolPriced[In any](h *Harness, tool *mcp.Tool, price PriceFunc[In], fn func(ctx context.Context, peer string, in In) (any, error))
AddToolPriced registers a tool whose price is computed per call by price (e.g. per-second video). Unless a fixed price is already advertised, the tool is marked dynamic in _meta.
func ChargedAtoms ¶
ChargedAtoms reports the amount debited from the caller for the current tool call, so handlers can echo the actual charge in their own delivery channel. Zero for free tools.
Types ¶
type Billing ¶
type Billing interface {
Balance(uid string) int64
// Debit returns ErrInsufficient when the balance cannot cover atoms.
Debit(uid string, atoms int64) error
Credit(uid string, atoms int64) error
}
Billing is the balance store paid tools debit against. The built-in Ledger implements it; services with their own accounting (tip-funded balances etc.) plug that in via HarnessConfig.Billing instead.
type Harness ¶
type Harness struct {
// contains filtered or unexported fields
}
Harness carries an MCP tool server over Bison Relay PMs with default-deny authorization, rate limiting, and paid tools settled by Bison Relay tips. Operators register tools and connect a PM backend; everything else is plumbing they never see.
func NewHarness ¶
func NewHarness(impl *mcp.Implementation, cfg HarnessConfig) (*Harness, error)
type HarnessConfig ¶
type HarnessConfig struct {
// DataDir holds the built-in ledger. Required unless Billing is set.
DataDir string
// AllowedPeers is the default-deny caller allowlist (64-hex uids).
AllowedPeers []string
// AllowFunc, when non-nil, replaces the allowlist entirely (e.g. an
// open service that admits every KX'd caller and lets billing and
// rate limits do the gating).
AllowFunc func(uid string) bool
// Billing, when non-nil, replaces the built-in ledger for balance
// reads, debits, and credits.
Billing Billing
// CallsPerMinute rate-limits each caller. Zero selects 30.
CallsPerMinute int
// TTL/ChunkSize/Assembler tune the transport (zero = defaults).
TTL time.Duration
ChunkSize int
Logf func(format string, args ...any)
}
HarnessConfig configures a serving harness.
type Ledger ¶
type Ledger struct {
// contains filtered or unexported fields
}
Ledger is the server-authoritative payment state: per-caller balances credited by tips, debited by paid tool calls. Every mutation persists synchronously; balances are money.
func OpenLedger ¶
type PriceFunc ¶
PriceFunc computes a tool's price per call, before the handler runs. It sees the caller and the decoded arguments, so prices may vary by parameters (e.g. video seconds). Returning an error refuses the call.
type TipJournal ¶
type TipJournal struct {
// contains filtered or unexported fields
}
TipJournal remembers recently credited tip sequence ids so a tip redelivered after a crash between the credit and its acknowledgement is not credited twice. The crediting order is: credit, Record, ack - a crash before Record can still double-credit one tip (the credit is owed to the tipper, so it must land before the id does), but the window shrinks from the whole ack round trip to one file write.
func OpenTipJournal ¶
func OpenTipJournal(path string) (*TipJournal, error)
func (*TipJournal) Record ¶
func (j *TipJournal) Record(seq uint64) error
Record persists seq as credited, keeping the newest entries only.
func (*TipJournal) Seen ¶
func (j *TipJournal) Seen(seq uint64) bool
Seen reports whether seq was already credited.