server

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 5, 2026 License: ISC Imports: 14 Imported by: 0

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

Constants

This section is empty.

Variables

View Source
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

func ChargedAtoms(ctx context.Context) int64

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.

func RunBot

func RunBot(ctx context.Context, h *Harness, cfg *kitconfig.BotConfig) error

RunBot serves the harness over a bisonbotkit bot until ctx ends. It owns the notification channels, credits tips from allowed peers into the ledger, and recreates the bot whenever its clientrpc websocket dies (the kit's Run returns with it).

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)

func (*Harness) Allowed

func (h *Harness) Allowed(peer string) bool

Allowed reports whether peer may open sessions.

func (*Harness) Billing

func (h *Harness) Billing() Billing

Billing exposes the balance store paid tools debit against (the bot glue credits tips into it).

func (*Harness) Start

func (h *Harness) Start(ctx context.Context, sender brmcp.PMSender) *brmcp.Router

Start wires the harness to a PM sender and returns the router whose HandlePM the backend must feed with every inbound private message.

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

func OpenLedger(path string) (*Ledger, error)

func (*Ledger) Balance

func (l *Ledger) Balance(uid string) int64

func (*Ledger) Credit

func (l *Ledger) Credit(uid string, atoms int64) error

func (*Ledger) Debit

func (l *Ledger) Debit(uid string, atoms int64) error

type PriceFunc

type PriceFunc[In any] func(ctx context.Context, peer string, in In) (atoms int64, err error)

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.

Jump to

Keyboard shortcuts

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