loading…
Search for a command to run...
loading…
Self-hosted credential store and API proxy for AI agents. One Bearer token, all your services. Handles OAuth refresh, encrypted storage, audit logging, and per-
Self-hosted credential store and API proxy for AI agents. One Bearer token, all your services. Handles OAuth refresh, encrypted storage, audit logging, and per-agent permissioning.
"It's kind of a nifty little utility." — me
Once in a while, an agent needs to be reminded that this exists.
Everything below this line was drafted by the bots.
One Bearer token, all your services.
Access gives agents and scripts secure access to OAuth and API-key-backed services without handling credentials directly. Store your secrets, refresh tokens automatically, proxy requests, audit everything — through one stable interface over HTTP and MCP.
flowchart LR
A[Any MCP client\nor HTTP caller] -->|Bearer token| B["Access\n(Next.js + Postgres)"]
B -->|OAuth 2.0| C[Google · GitHub · Sentry · Oura]
B -->|API key| D[HubSpot · Linear · Jira · Stripe\nNotion · Apollo · Cal · Porkbun]
B -->|Token| E[Slack · Cloudflare · Vercel\nGitLab · AWS]
You put every credential in it — API keys, OAuth tokens, bot tokens, agent credentials, service secrets, whatever your agents and scripts need. Then you decide who gets what.
/bootstrap or /secrets/by-env/WHATEVER/bootstrap call gives an agent only what it's authorized to see — env vars, docs, and contextThe happy path: Agent sends Bearer token → Access handles auth, refresh, and proxying → Agent gets JSON or a bootstrap bundle back. That's it.
Dashboard — services, keys, agents, and audit history at a glance:

Agent permissioning — each agent gets its own token with scoped access grants:

Agent detail — trust level, token prefix, last used, and grant count:

# Set once per session (don't paste tokens directly in commands)
export TOKEN="your-token"
export ACCESS="https://your-access-instance"
# Your agent searches Gmail through Access
curl -H "Authorization: Bearer $TOKEN" "$ACCESS/api/v1/google/gmail?action=search&q=from:alice&account=work"
# Or bootstraps an entire session in one call
curl -H "Authorization: Bearer $TOKEN" "$ACCESS/api/v1/bootstrap"
With MCP, your agent gets tools like gmail_search, calendar_list, drive_list — no configuration per service, no expired tokens, no credential management.
Good fit:
.env filesNot a fit:
How it differs from a password manager: 1Password stores credentials for humans to copy-paste. Access stores credentials and uses them — proxying API calls, refreshing OAuth tokens, bootstrapping agent sessions. Your agent never sees the raw key for proxied services.
What Access protects against:
What Access does not protect against:
.env files?There are real tools for parts of this problem. Most solve one slice:
op run / doppler run. Great for API keys. Don't handle OAuth refresh or API proxying.Mature orgs split the problem across Vault + OIDC + OAuth brokers + internal platform tooling. Smaller teams use 1Password/Doppler for static secrets and still suffer on OAuth.
Access collapses these layers into one self-hosted app: store credentials, refresh OAuth, proxy API calls, bootstrap agent sessions, audit everything. It's less secure than Vault + KMS, but it's one thing instead of four — and it actually ships.
| Access | .env files |
1Password/Doppler | Nango/Composio | Vault | |
|---|---|---|---|---|---|
| Self-hosted | Yes | Yes | Varies | Cloud-first | Yes |
| OAuth refresh | Automatic | Manual | No | Yes | No |
| API proxying | Yes | No | No | Some | No |
| MCP server | Built-in | No | No | No | No |
| Agent bootstrapping | One call | Manual | No | No | No |
| Audit trail | Yes | No | Yes | Varies | Yes |
| Complexity | One app | None | CLI + cloud | Platform | Significant |
| Cost | Free | Free | Paid | Paid | Free / paid |
git clone https://github.com/Scottpedia0/access.git
cd access
npm install
# Option A: Use Docker Compose
docker compose up -d
# Option B: Use your own Postgres
# Set DATABASE_URL and DIRECT_DATABASE_URL in .env
cp .env.example .env
# Generate required secrets
openssl rand -base64 32 # -> SECRET_ENCRYPTION_KEY
openssl rand -base64 32 # -> NEXTAUTH_SECRET
openssl rand -base64 32 # -> CONSUMER_TOKEN_HASH_SECRET
Edit .env with your values. At minimum you need:
DATABASE_URL / DIRECT_DATABASE_URLSECRET_ENCRYPTION_KEYNEXTAUTH_SECRETOWNER_EMAILS (comma-separated list of emails allowed to log in)npx prisma migrate deploy
npm run db:seed # Creates example services and a consumer token
npm run dev
Visit http://localhost:3000 and sign in with an email from your OWNER_EMAILS list.
bash scripts/install.sh
This detects your installed agent harnesses (Claude Code, Cursor, Gemini CLI, Windsurf, VS Code, Codex), installs the health-check skill, and shows you the MCP config for each. You can accept or reject each step.
27 service endpoints across /api/v1/*. Each adapter handles auth and proxies requests upstream.
Google Workspace (OAuth 2.0, multi-account) — Gmail, Calendar, Drive, Sheets, Docs, Contacts, Analytics, Search Console, Tag Manager, Admin Reports, Profile
Developer tools — GitHub, GitLab, Linear, Jira, Notion, Sentry, Vercel
Business — HubSpot, Slack, Stripe (read-only), Apollo.io, Cal.com
Infrastructure — AWS (S3, EC2, Lambda, CloudWatch — optional SDK deps), Cloudflare
Other — Oura Ring, Porkbun
Google services support multiple accounts — configure via the GOOGLE_ACCOUNTS env var (e.g., work:[email protected],personal:[email protected]). Adding a new adapter is ~100 lines — see Adding a New Service.
These aren't service proxies — they're Access itself:
| Endpoint | What it does |
|---|---|
GET /api/v1/bootstrap |
One pull that returns all secrets as env vars + service metadata + docs + linked resources. This is how agents bootstrap a session. |
POST /api/v1/intake |
Write-only endpoint for submitting new credentials without read access to the store. |
GET /api/v1/secrets/by-env/:name |
Look up a single decrypted secret by its env var name. |
GET /api/v1/services/:slug |
Service metadata, docs, and linked resources. |
GET /api/v1/services/:slug/secrets |
Decrypted secrets for a specific service. |
Access supports three token types for agent authentication:
| Token Type | Scope | Use case |
|---|---|---|
| Global Agent Token | Full access to all services and secrets | Trusted single-operator setups |
| Consumer Tokens | Granular per-service or per-secret access grants | Multi-agent setups where each agent or fleet gets different permissions |
| Shared Intake Token | Write-only credential submission | Let team members drop keys without read access |
Consumer tokens let you segment access by role. Each consumer gets its own identity, token, and scoped grants:
Coding agents (Claude Code, Cursor) → GitHub, Linear, Sentry
Comms agents → Gmail, Slack, Calendar
Ops agents → AWS, Cloudflare, Vercel
Intake-only (team members) → Write keys, can't read anything
Grants work at two levels — whole service (agent sees everything in that service) or individual secrets (agent sees only specific keys). When an agent calls /bootstrap, it only gets back what it's authorized to see.
# Search Gmail with a global token
curl -H "Authorization: Bearer YOUR_TOKEN" \
"http://localhost:3000/api/v1/google/gmail?action=search&q=from:alice&account=work"
# Bootstrap an agent session — pull only what this token is authorized for
curl -H "Authorization: Bearer YOUR_TOKEN" \
"http://localhost:3000/api/v1/bootstrap"
Human authentication for the admin UI uses Google OAuth, email magic links, or a simple password — configured via env vars. Only emails in OWNER_EMAILS can log in.
Each proxy adapter is a Next.js route handler under src/app/api/v1/<service>/route.ts. To add one:
src/app/api/v1/your-service/route.tsauthenticateRequestActor() from @/lib/access for authMost adapters are under 100 lines. See src/app/api/v1/hubspot/route.ts for a clean example.
AGENTS.md in this repo has two sections:
CLAUDE.md or agent instructions that tells your agents how to bootstrap, pull credentials, and use proxy endpointsCopy the "For agents USING Access" section into your agent's instruction file and set ACCESS_BASE_URL and ACCESS_TOKEN in your environment.
Access includes an MCP server (mcp-server.mjs) that exposes Google Workspace tools via stdio transport. Works with any MCP-compatible client.
Add the following config to your client. The JSON is the same — only the file path changes per client:
| Client | Config location |
|---|---|
| Claude Code | ~/.claude/mcp.json or project .mcp.json |
| Cursor | Cursor MCP settings |
| Gemini CLI | .gemini/settings.json |
| Windsurf | Windsurf MCP settings |
| VS Code (Copilot) | .vscode/mcp.json (use "servers" instead of "mcpServers") |
| Codex / other | Any MCP-compatible config |
{
"mcpServers": {
"access": {
"command": "node",
"args": ["/path/to/access/mcp-server.mjs"],
"env": {
"ACCESS_BASE_URL": "http://localhost:3000",
"GLOBAL_AGENT_TOKEN": "your-token-here"
}
}
}
}
VS Code note: Use
"servers"as the top-level key instead of"mcpServers".
Once connected, your agent gets tools like gmail_search, calendar_list, drive_list, contacts_search, and more — all authenticated through Access.
You don't need MCP. Any HTTP client works:
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:3000/api/v1/google/gmail?action=search&q=is:unread"
1. Agent sends: GET /api/v1/google/gmail?action=search&q=from:alice&account=work
Authorization: Bearer amb_live_xxxx
2. Middleware: Rate limit check → Body size check → Pass
3. Auth: Validate Bearer token (HMAC comparison)
Look up consumer permissions or verify global token
4. Proxy: Load OAuth credentials from Postgres (encrypted)
Refresh access token if expired
Forward request to Gmail API
5. Response: Return Gmail results as JSON to agent
Log access in audit_events table
v2.iv.authTag.ciphertext), key rotation supported.Access supports zero-downtime encryption key rotation:
# 1. Generate a new key
openssl rand -base64 32
# 2. Set the new key and keep the old one
SECRET_ENCRYPTION_KEY="<new key>"
SECRET_ENCRYPTION_KEY_PREVIOUS="<old key>"
# 3. Re-encrypt all secrets
npx tsx scripts/rotate-keys.ts
# 4. After success, remove the old key
# unset SECRET_ENCRYPTION_KEY_PREVIOUS
The script is idempotent — secrets already on the current key are skipped. It decrypts with whichever key works (current or previous) and re-encrypts with the current key.
Access deploys well on Vercel with a Neon or Supabase Postgres database:
.env.exampleNEXTAUTH_URL to your production URLyour-domain.com/api/google/callback as an authorized redirect URI in Google Cloud Consolenpx prisma migrate deploy via Vercel build commandWorks anywhere Node.js runs — Vercel, Railway, Fly.io, a VPS, your laptop.
npm run dev # Start dev server
npm run build # Production build
npm run lint # ESLint
npm run typecheck # TypeScript check
npm run db:studio # Prisma Studio (GUI for database)
npm run db:seed # Seed example data
MIT
Добавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"access": {
"command": "npx",
"args": []
}
}
}