Governed, auditable knowledge your team curates for its AI assistants, self-hostable
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
We haven't yet run this listing's install command through our automated sandbox check. This isn't a red flag β we're steadily working through the catalog.
π‘ Paste into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows)
Inspect callable tools, capabilities, and parameters exposed to AI agents by Kumbuka.
memory_rememberAppend (or upsert on `key`) a memory. Caller picks `scope`, `type`, optional `key`.
memory_recallRead memories. Filters: `scope`, `type`, substring `query`, optional `include_global`.
memory_forgetDelete by `id` or by `(scope, key)`. Private rows protected by owner check.
memory_scopesList scopes visible to the caller (private + every shared scope).
memory_load_contextTyped digest grouped by type (decision / constraint / convention / glossary / open_question / status), capped per group.
Self-hostable team memory system exposed as a remote Model Context Protocol
(MCP) server over Streamable HTTP. Reachable from claude.ai and other
MCP-capable AI clients. Everything runs in Docker, orchestrated by a
single docker-compose.yml.
Repo layout. This is the OSS server repository (
kumbuka-server): the Quarkus backend (a multi-module Maven build:server+ thespimodule), Caddy/Postgres ops, and the ADR record. The Next.js admin console lives in its own repokumbuka-console; wire it in via acompose.override.yml(see thekumbuka-consoleblock comment indocker-compose.yml). The Keycloak image, realm templates, and theme live inkumbuka-keycloak. A downstream composition build can provide multi-tenant resolution on theai.kumbuka.tenancy.TenantResolverSPI frozen here (ADR-0011).
License: AGPL-3.0.
Status. The MCP surface, the admin REST API, the OAuth integration with Keycloak, and the private-isolation invariant are in place, covered by the unit and integration test suites. The admin console is built and maintained in
kumbuka-console. Seedocs/adr/for the architectural record.
The backend plays two OIDC roles against the Keycloak realm kumbuka:
/mcp. AI clients discover the
authorization server via /.well-known/oauth-protected-resource
(RFC 9728) and run the OAuth authorization-code flow with PKCE. A client
identifies itself through its published client metadata or dynamic client
registration at first authorization β there is no hand-entered client id
and no client secret. It then calls /mcp with a bearer token.
The token's sub claim is the acting user; the realm role
(member / admin) is the authorisation context.kumbuka-admin for the admin console
as a BFF. The browser never holds tokens β the Quarkus backend
keeps the OIDC session and issues an HttpOnly cookie. User management
goes through the backend via the confidential service-account client
kumbuka-backend. The frontend has zero Keycloak knowledge.The MCP endpoint /mcp exposes five tools to the connected model:
| Tool | What it does |
|---|---|
memory_remember | Append (or upsert on key) a memory. Caller picks scope, type, optional key. |
memory_recall | Read memories. Filters: scope, type, substring query, optional include_global. |
memory_forget | Delete by id or by (scope, key). Private rows protected by owner check. |
memory_scopes | List scopes visible to the caller (private + every shared scope). |
memory_load_context | Typed digest grouped by type (decision / constraint / convention / glossary / open_question / status), capped per group. |
There is also an MCP resource memory://{scope} listing scope contents.
Tool returns are structured JSON (MCP structuredContent) so the
model can parse fields reliably rather than re-parsing prose.
Six fixed entry types, two scope kinds, one invariant.
Types (taxonomy is intentionally small):
| Type | Use for |
|---|---|
decision | A settled choice the team committed to. |
convention | A shared way of doing things; the default. |
constraint | A hard boundary that must not be crossed. |
open_question | Unresolved; needs an owner and an answer. |
glossary | A term defined so everyone means the same thing. |
status | The current state of something in motion. |
Scopes:
private β visible/editable only to its owner. Always available to
every user as their personal space. No other user, no admin, and
never the admin console can reach it (see ADR-0003).project β team-shared, addressed by a stable kebab slug
(atlas-web, billing-platform, β¦). Members read, admins manage.global β exactly one per team, the always-on baseline the assistant
reads first.Invariant. Private rows are unreachable from any admin code path β
enforced at the data-access layer via a separate repository class with
no method that can return private rows. The release-gate smoke test
(PrivateIsolationTest) proves it on every build.
A singleton team_settings row drives runtime policy:
| Setting | Values | Meaning |
|---|---|---|
writePolicy | ask (default) / project / global | What memory_remember does when scope is omitted. ask returns a structured prompt asking the user; private is never the default. |
defaultScopeSlug | a project slug | Only used when writePolicy = project. If it goes archived/missing, the resolver falls back to ask at runtime without mutating the row. |
createScopes | admins (default) / members | Who may create new project scopes. |
Admins edit these in the console; the changes take effect immediately.
Then visit https://<your-domain> (whatever you set KUMBUKA_DOMAIN to).
Common targets:
The login screen, the account console, and the invitation / verification /
password-reset emails are all themed by the kumbuka Keycloak theme, which
β along with both realm definitions and the production image β now lives in its
own repository: kumbuka-keycloak.
Both dev and prod consume the same published image
ghcr.io/kumbuka-ai/kumbuka-keycloak, pinned via KEYCLOAK_VERSION. Theme and
realm edits, and the build/verify loop, happen in that repo.
To exercise the email surfaces, bring up MailHog:
See ADR-0010 for the theme's scope, parent themes, and packaging decisions.
Dev test users are no longer seeded by a realm import here β create them via the Keycloak admin console or
kcadm.shagainst the runningkumbukarealm.
See ADR-0012 for the topology decisions. In short: the production stack does not ship its own Caddy. It assumes an existing Caddy is already running on the host and joins its docker network. The kumbuka images are pulled from GHCR by tag.
Three pieces in this repo together describe a production deploy:
| File | Role |
|---|---|
docker-compose.prod.yml | The stack (postgres + kumbuka-keycloak + kumbuka-backend + kumbuka-console). Images come from GHCR by version tag; no Caddy here. |
deploy/caddy/kumbuka.caddy | Caddyfile snippet for the host Caddy. import it from the host Caddyfile. |
.env.prod.example | Production env template β set KUMBUKA_VERSION, CADDY_NETWORK, hostnames, secrets. |
Minimal hand-deploy on a host that's already set up:
How deploys are automated beyond that β pull scripts, health gates, rollback β is a property of your hosting environment, not of this repository. Treat the files above as the reference shape for a compose-based deploy behind an existing reverse proxy, and wire them into your own operations.
All clients use the same OAuth-discovered flow: the URL is all you
enter β there is no client id and no client secret. The client first hits
/mcp, gets a 401 with a WWW-Authenticate header pointing at
/.well-known/oauth-protected-resource, then runs the authorization-code
flow with PKCE against Keycloak, identifying itself through its published
client metadata or dynamic client registration at first authorization.
The backend validates the token's aud claim before letting any tool
call through.
kumbukahttps://mcp.kumbuka.ai/mcp (an example β your deployment's MCP host)memory_* tools should now appear under the connector. Pin
the connector to any project where you want kumbuka active.Claude Desktop's in-app Connectors UI takes the same URL:
https://mcp.kumbuka.ai/mcp (your deployment's MCP host).If your Desktop build is older and doesn't expose the in-app connector
manager, fall back to the mcp-remote
shim in ~/Library/Application Support/Claude/claude_desktop_config.json:
mcp-remote opens a browser window for the OAuth flow on first connect
and caches the refresh token locally.
Add the server once globally and Claude Code picks it up across projects:
Or per project, add to .claude/settings.json:
Run claude once; you'll be redirected to Keycloak to authorise. After
consent the token is cached and subsequent sessions reuse it.
Note. Claude Code only loads MCP servers from
.claude/settings.jsonat session start. If you change the config mid-session, restartclaude.
Same custom-connector dialog as claude.ai web. The OAuth flow opens the in-app browser; on consent the connector becomes available to enable in any project.
The taxonomy and the scope split are deliberately small. Keeping them small is what makes the memory useful β a dumping ground for every chat fragment quickly becomes noise the model has to wade through.
Write when the conversation produced:
decision).convention).constraint β "money is integer minor units, never floats").open_question).glossary).status β "v2.4
canary at 10% since 2026-06-02").Don't write:
private β your personal scratchpad. Drafts, "remind me later",
open threads only you care about. The team can't see it; even the admin
console can't see it. Use freely but don't park team knowledge here.project β the default home for project-specific work. Tie the
slug to the repo / service name (atlas-web, billing-platform).
Members write here when working on that thing.global β the team-wide baseline. Anything that applies across
every project goes here: language conventions, infra rules,
compliance constraints, the team-wide glossary. Keep it lean.If unsure, ask the user. The writePolicy=ask default exists exactly
for this β memory_remember without scope returns a structured
"please specify" prompt that lists available scopes, so the model can
relay the question instead of guessing.
Optional, but recommended for anything the model might want to update later. Convention: lowercase, dot- or kebab-separated namespaces.
The same key in the same scope, by the same author, upserts in place
on the next memory_remember. Pick a slug-like key when the entry has
a single canonical answer; leave key empty for one-shot status notes.
agent authorWhen a memory is written by Claude through /mcp, the row carries
source = mcp. The console renders an "agent" badge next to the
author's name to make the provenance obvious. The actual author is
still the real human under whose token the write happened (ADR-0008)
β there's no agent Keycloak account.
These are starting points. Edit them to your team's voice and the specific project once you've used kumbuka for a week or two and you notice the friction points.
Paste into a Claude project's Instructions so every chat in that project loads context and follows the same memory protocol:
CLAUDE.md for Claude CodeFor repos using Claude Code, add this to the project's CLAUDE.md (or
extend an existing one). Edit the project slug to match the scope you
created in the console.
If you're building an application against the Claude API and want it to use kumbuka, pass the MCP server in the request and add a system prompt along these lines:
Runs the in-process test suite, including the private-isolation smoke test
(PrivateIsolationTest β the release-gate invariant from ADR-0003) and the
admin REST surface checks. No Docker needed beyond DevServices Postgres.
Runs the Testcontainers-based integration tests, including the OAuth
end-to-end flow (E2EOAuthIntegrationIT) against a real Keycloak under
a dedicated OIDC-enabled test profile.
cp .env.example .env, set secrets, just up.https://<your-domain>/mcp.kumbuka realm (create one via the admin console / kcadm.sh first β
dev test users are no longer auto-seeded); on consent it returns a token.memory_* tools. Call
memory_remember scope=private with some content; in a second
Inspector session signed in as a different user, call memory_recall scope=private and confirm the private content is not visible.Acceptance: the Inspector flow succeeds AND the second user does not see the first user's private content. Failure of the second check is a security incident.
.env. Never commit .env. The repo only
ships .env.example with placeholder values..env (client
secrets are rendered into the realms by the kumbuka-keycloak image at
boot) before deploying anywhere beyond your laptop.kumbuka-keycloak image runs kc.sh start --optimized with proper
KC_HOSTNAME and HTTPS termination via Caddy β both dev and prod use it.PrivateIsolationTest
must stay green; treat its failure as a security incident, not a
flake.Decisions land as ADRs under docs/adr/. Code changes that touch
access-control or auth topology require updating the relevant ADR in the
same PR. The private-scope invariant is non-negotiable β if you find
yourself adding a method to SharedMemoryRepository that could return a
private row, stop and re-read ADR-0003.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/kumbuka)<a href="https://allmcps.com/mcp/kumbuka"><img src="https://allmcps.com/api/badge/kumbuka?style=directory" alt="Kumbuka on AllMCPs" /></a>