A local-only, single-binary execution layer for AI agents. Point it at your databases and infrastructure; agents get CLI-shaped access over MCP, with native Go execution, local guardrails, a full audit log, and a context store that makes every session start warmer than the last.
$ access serve
access v0.1.0 — listening on http://127.0.0.1:4820
UI: http://127.0.0.1:4820/?_token=…
MCP: http://127.0.0.1:4820/mcp
Kinds in v1: postgres, mysql, redis, kubernetes.
No sandbox, because no code. Agents send argv
(["psql","-c","select 1"]); access parses it into typed native driver
calls (pgx, mysql, go-redis) or a fenced kubectl. Nothing an agent sends is
evaluated or shelled on your machine. That makes it as safe as — usually
safer than — a sandboxed shell: there is no shell to escape.
The interface agents already know. AI Labs have spent billions making sure your agents know cli tools — psql, redis-cli, kubectl. access keeps exactly that shape in it's mcp.
No bespoke tool-per-table schemas to learn, no
JSON query DSL: the agent writes the command it would have written in a
terminal, and gets guardrails instead of a shell.
It learns, so agents stop re-learning. Without memory, every session
burns tokens rediscovering the same schemas and conventions. Adding a
resource builds ~/.access/context/system/<name>/*.md from live
introspection; agents search it before probing, and you layer curated
notes and skills on top.
One connection, five tools. Instead of a dozen MCP servers each pushing
10–40 tool schemas into every prompt, agents connect to one server exposing
five stable tools. The catalog is data returned by discover, not tool
definitions — so adding your tenth database costs the prompt nothing.
Secrets never reach the agent. Write-only vault (AES-256-GCM), decrypted only inside a connection handshake. No API returns a secret, ever.
Read-only by default, audited always. Statement classification (SQL), command allowlists (Redis), verb allowlists (kubectl) — enforced locally, before your credential is used. Every attempt, including denials, lands in the run log.
Query by business context. You don't tell the agent where the data is — it already knows, because it learned your infra when the resource was added.
You: how did each product category do on revenue?
discover()
-> dev-postgres (postgres, read-only, 6 knowledge files)
search({
resource:"dev-postgres",
query:"revenue",
})
-> schema.demo.md: "v_revenue_by_category —
revenue rolled up per category"
execute({
resource:"dev-postgres",
argv:["psql","-c", "select * from demo.v_revenue_by_category"],
})
Three calls, no schema dumping, no trial-and-error \dt spelunking. The
search hit came from context docs access generated by introspecting the
database — and from any notes you added ("revenue excludes internal test
accounts — filter email like '%@internal.test'"), which the agent applies
without being told twice.
Triage a cluster without handing over the cluster.
You: checkout is slow in staging — take a look
discover({kind:"kubernetes"})
→ staging-k8s (read-only)
search({
resource:"staging-k8s",
query:"checkout",
})
→ workloads.checkout.md: deployments, services
execute({
resource:"staging-k8s",
argv:["kubectl","get","pods","-n","checkout"],
})
execute({
resource:"staging-k8s",
argv:["kubectl","logs","deploy/checkout-api","-n","checkout","--tail","200"],
})
The agent can get, describe, logs, top — but exec, delete,
port-forward, and credential-swapping flags are fenced off locally, and
read-only mode enforces the verb allowlist before your kubeconfig is ever
used.
Teach it once. Drop a note or a skill in the knowledge store ("when
asked about churn, use mrr_facts, not the raw events table") and every
agent, in every future session, finds it with search before it starts
guessing. Deterministic sync keeps the system docs fresh; your curation
compounds on top.
Install the latest release — one binary, no dependencies:
curl -fsSL https://raw.githubusercontent.com/dumbmachine/access-mcp/main/scripts/install.sh | sh
This drops access into /usr/local/bin (or ~/.local/bin if that isn't
writable). Pin a version with ACCESS_VERSION=v0.1.0 or pick a location with
ACCESS_INSTALL_DIR=~/bin. Prefer to grab a tarball yourself? They're on the
releases page for macOS
and Linux (arm64 + amd64), each with a checksums.txt.
Run:
access serve
Build from source instead (Go 1.25+, pnpm)
git clone https://github.com/dumbmachine/access-mcp
cd access-mcp
make # SPA + binary → bin/access
./bin/access serve
Connect your agent — one command configures every MCP client on your machine (add-mcp detects Claude Code, Cursor, Codex, VS Code, and friends):
npx add-mcp http://127.0.0.1:4820/mcp \
--name access \
--header "Authorization: Bearer <your-token>"
The token is printed by access serve and shown on the UI's Connect
page, alongside the raw endpoint for wiring a client by hand.
Prefer stdio? Clients can spawn the binary directly — no URL or token:
npx add-mcp "access mcp" --name access # or: claude mcp add access -- access mcp
access ships with a demo database already connected. Try:
Using the access MCP tools, explore the demo-sqlite resource and answer: which three artists sold the most tracks? Show the SQL you used.
Then add your own resources in the UI (Add resource) — credentials go straight into the vault and a context sync builds the resource's knowledge base from live introspection.
| tool | what |
|---|---|
discover |
lean catalog of your resources (+ how much context each has) |
describe |
argv grammar & recipes per kind; per-resource manifest |
execute |
run argv against a resource (dry_run supported) |
search |
search / read the context store |
help |
the invariants doc |
Two transports, same data dir:
- HTTP —
http://127.0.0.1:4820/mcp, bearer token, loopback only. - stdio —
access mcp, spawned by the client; no token needed.
make # full build: SPA + binary with SPA embedded
make build # Go binary only → bin/access
make run # build + serve
make test # go test ./...
make vet
make web-dev # Vite dev server proxying /api + /mcp to a running serve
With a server running (make run), stand up seeded docker databases and
register them through the public API — exactly like the UI would:
make bootstrap postgres # postgres:16 + demo e-commerce schema → resource dev-postgres
make bootstrap redis # redis:7 + demo keys → resource dev-redis
Both are created read-write and context-synced immediately, so search
works on the first query. Tear everything down when you're done:
make bootstrap down # remove containers + resources + secrets
make bootstrap down postgres # just one kind
Ports/dirs are overridable via ACCESS_PORT, ACCESS_DATA_DIR, PG_PORT,
REDIS_PORT (see scripts/bootstrap.sh).
See PLAN.md for the full design.