Catalog›MCP servers›AI, search & memory›io.github.CloudCorpRecords/banditkeepIGio.github.CloudCorpRecords/banditkeepDecision memory for agents: bandit campaigns that learn which action works in which context. Open site Open in the app JSON README (API)READMELoading documentation…# banditkeep Give a swarm of agents a memory for decisions. banditkeep is a small client for a BanditDB server: a contextual bandit database that learns, per campaign, which action tends to pay off in which context. An agent asks which arm to pick, acts on the answer, then reports whether it worked — and every later agent pointing at the same server benefits from that outcome immediately, with no retraining step. Two exploration algorithms anchor the campaigns: LinUCB, deterministic and tunable through `alpha`, and Thompson Sampling, which explores naturally in a Bayesian way and needs no tuning. Campaigns can also carry budgets for actions that cost something limited, so spend is steered across a horizon instead of running dry on the first day. ## Configuration Three environment variables control the client: - `BANDITDB_URL` (optional) — base URL of your BanditDB server. Defaults to `http://localhost:8080`. - `BANDITDB_API_KEY` (optional) — when set, it is sent on every request as `Authorization: Bearer <key>`. Omit it when your server runs without auth; leaving it unset is never an error by itself. - `BANDITDB_TIMEOUT_MS` (optional) — per-request timeout in milliseconds, enforced with an AbortController. Defaults to `15000`. (This variable is this rebuild's own addition.) ## Tools - `create_campaign` — create a new decision campaign. Requires `campaign_id` and `arms`; optionally takes `features` (names, in order) or `feature_dim`, `alpha`, `algorithm` (`"linucb"` or `"thompson_sampling"`), `metadata`, `budgets`, and `decay_half_life_hours`. - `list_campaigns` — list all active campaigns, showing algorithm and alpha; useful to check what exists before calling `get_intuition`. - `campaign_diagnostics` — inspect per-arm learning state: theta norms, prediction counts, reward rates, and entropy health. Reach for it when a campaign does not seem to be learning or one arm is dominating. - `campaign_report` — a business-level convergence report: whether the campaign has statistically converged, and which arm is winning, with confidence intervals. - `get_intuition` — ask which arm to pick for a given `context` (an object of feature-name to number, or an array of numbers). Optional `eligible_arms` / `exclude_arms` narrow the choice for this request only. Returns the arm and an `interaction_id` to save. - `batch_get_intuition` — get decisions for multiple campaigns in a single round-trip: pass `predictions` as a list of `{campaign_id, context}` dicts, at most 100 per call. - `record_outcome` — report whether the chosen action succeeded (`1.0`) or failed (`0.0`), closing the loop for an `interaction_id`. Rewards outside `[0, 1]` are rejected locally with `reward must be between 0 and 1`. - `archive_campaign` — soft-delete a campaign: it pauses predictions and rewards but preserves all learned weights. - `restore_campaign` — restore an archived campaign to active status with all weights intact. - `campaign_budget` — budget spend per resource: consumed, remaining, utilization, shadow price, and exhaustion. - `add_arm` — add an action to a live campaign, optionally warm-started from existing arms and with budget `costs`. - `set_arm_status` — pause, retire, or reactivate an action (`status` is `"active"`, `"paused"`, or `"retired"`); the arm keeps everything it learned. Unset optional arguments are omitted from requests entirely. Responses come back exactly as the server returned them. An upstream non-2xx reply fails with `banditdb error: HTTP <status>` and an unreachable server (including a timeout) with `banditdb unreachable`. ### Endpoint provenance The original project's README and MCP documentation pin the twelve tools, their arguments, the configuration above, and the decision-loop semantics — but no HTTP API is published in those sources. The request paths below are reconstructions, labelled as such: - `POST <base>/campaigns` with the arguments as the JSON body (used by `create_campaign`). - `GET <base>/campaigns` (used by `list_campaigns`). - `GET <base>/campaigns/{campaign_id}/diagnostics` (used by `campaign_diagnostics`). - `GET <base>/campaigns/{campaign_id}/report` (used by `campaign_report`). - `GET <base>/campaigns/{campaign_id}/pacing` (used by `campaign_budget`; the SDK method is named `pacing`). - `POST <base>/predict` with body `{"campaign_id": ..., "context": ...}` (used by `get_intuition`). - `POST <base>/predict/batch` with body `{"predictions": [...]}` (used by `batch_get_intuition`). - `POST <base>/reward` with body `{"interaction_id": ..., "reward": ...}` (used by `record_outcome`). - `POST <base>/campaigns/{campaign_id}/archive` with body `{}` (used by `archive_campaign`). - `POST <base>/campaigns/{campaign_id}/restore` with body `{}` (used by `restore_campaign`). - `POST <base>/campaigns/{campaign_id}/arms` with body `{"arm_id": ...}` (used by `add_arm`). - `POST <base>/campaigns/{campaign_id}/arms/{arm_id}/status` with body `{"status": ...}` (used by `set_arm_status`). Path segments are sent verbatim. One discrepancy worth knowing: the vendor's MCP docs page lists nine of the twelve tools (it omits `campaign_budget`, `add_arm`, and `set_arm_status`); the package's own MCP table enumerates all twelve, and this rebuild follows the package table. ## CLI Each tool is a subcommand taking one JSON argument string: ```bash npx @reneturcios/banditkeep create_campaign '{"campaign_id":"model-routing","arms":["fast","cheap"],"feature_dim":4}' npx @reneturcios/banditkeep list_campaigns '{}' npx @reneturcios/banditkeep campaign_diagnostics '{"campaign_id":"model-routing"}' npx @reneturcios/banditkeep campaign_report '{"campaign_id":"model-routing"}' npx @reneturcios/banditkeep get_intuition '{"campaign_id":"model-routing","context":[0.8,0.2,0.5,0.1]}' npx @reneturcios/banditkeep batch_get_intuition '{"predictions":[{"campaign_id":"model-routing","context":[0.8,0.2,0.5,0.1]}]}' npx @reneturcios/banditkeep record_outcome '{"interaction_id":"9f2c-4e1a","reward":1.0}' npx @reneturcios/banditkeep archive_campaign '{"campaign_id":"model-routing"}' npx @reneturcios/banditkeep restore_campaign '{"campaign_id":"model-routing"}' npx @reneturcios/banditkeep campaign_budget '{"campaign_id":"model-routing"}' npx @reneturcios/banditkeep add_arm '{"campaign_id":"model-routing","arm_id":"balanced"}' npx @reneturcios/banditkeep set_arm_status '{"campaign_id":"model-routing","arm_id":"cheap","status":"paused"}' npx @reneturcios/banditkeep --version ``` Output is the tool's result text (the upstream body on success). Exit codes: `0` on success, `1` on a runtime error, `2` on a usage error. ## MCP server ```bash npx -y @reneturcios/banditkeep mcp ``` MCP client config (provide the key through the client's environment when your server uses one): ```json { "mcpServers": { "banditkeep": { "command": "npx", "args": ["-y", "@reneturcios/banditkeep", "mcp"], "env": { "BANDITDB_URL": "http://localhost:8080", "BANDITDB_API_KEY": "<your key>" } } } } ``` ## Docker ```bash docker run -i ghcr.io/cloudcorprecords/banditkeep docker run --rm ghcr.io/cloudcorprecords/banditkeep list_campaigns '{}' ``` ## Development ```bash npm install npm run build # tsc -> dist/ npm test # tsx --test test/*.test.ts (fake fetch only, no network) npm run dev # run the CLI from source ``` ## License MIT — Copyright (c) 2026 Rene Turcios DetailsTypeMCP serversTopicAI, search & memoryPublishercloudcorprecordsSourceofficialCategoryToolsWhere it runsOn my computerVersion0.1.0Last updateNov 4, 20262 weeks agoProject statusActiveLanguageTypeScriptLicenseMITAddedNov 4, 20262 weeks agoUpdatedNov 4, 20262 weeks agoSource idio.github.CloudCorpRecords/banditkeepMoreMore mcp servers on AI, search & memoryAll from cloudcorprecordsA–Z index