Skip to content

DumbMachine/access-mcp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Access MCP

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.

Why

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.

What it looks like

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.

Quick start

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.

MCP surface — five tools, no more

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:

  • HTTPhttp://127.0.0.1:4820/mcp, bearer token, loopback only.
  • stdioaccess mcp, spawned by the client; no token needed.

Development

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

Test resources, up and down

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.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors