Access
Access
"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]What it does
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.
Per-agent and per-fleet permissioning — each agent or group gets its own token with scoped access. Coding agents see GitHub and Linear. Comms agents see Gmail and Slack. Ops agents see AWS. Managed from the admin UI — no config files, no CLI juggling.
Stores everything encrypted — API keys, OAuth tokens, bot tokens, agent-to-agent credentials, service secrets. AES-256-GCM at rest, HMAC-hashed access tokens.
Handles OAuth — token refresh, consent flows, multi-account Google — your agent never participates
Proxies API calls — for services with adapters, agents hit Access and get JSON back without ever seeing the underlying key
Serves credentials directly — for everything else, agents pull keys via
/bootstrapor/secrets/by-env/WHATEVERLogs everything — every secret access, every API call, every auth attempt, with actor and IP
Bootstraps sessions — one
/bootstrapcall gives an agent only what it's authorized to see — env vars, docs, and context
The happy path: Agent sends Bearer token → Access handles auth, refresh, and proxying → Agent gets JSON or a bootstrap bundle back. That's it.
What it looks like
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:

30-second example
# 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.
Who this is for
Good fit:
Running AI agents (Claude Code, Cursor, Gemini CLI, Codex) across multiple sessions or machines
Multi-agent setups where agents need credentials for other agents, bots, and internal services
Self-hosted personal or small-team setups
Multi-service workflows where agents need Gmail, Slack, GitHub, etc.
Anyone tired of bootstrapping agent sessions with scattered
.envfiles
Not a fit:
Enterprise secrets management with compliance requirements (use HashiCorp Vault)
High-compliance infrastructure with KMS/HSM requirements
Large team IAM or multi-tenant access control
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.
Security posture
What Access protects against:
Agents seeing or storing raw credentials
Expired OAuth tokens breaking agent sessions
Unaudited credential access across machines
Plaintext secrets in databases (AES-256-GCM encryption at rest)
Brute-force token guessing (HMAC-SHA256 hashed, constant-time comparison)
What Access does not protect against:
A compromised Access instance (if someone gets your server, they get everything)
Cloud-grade key management (no KMS/HSM integration yet — see roadmap)
Multi-tenant isolation (this is a single-owner system)
Network-level attacks (deploy behind HTTPS, use a firewall)
Why not just use .env files?
OAuth tokens expire. Google access tokens last 60 minutes. Your agent can't refresh them — Access can.
Credentials scatter. Each agent session needs its own copy. Rotate a key and you're updating it in 6 places.
No audit trail. Which agent accessed which service? When? From where? No idea.
Bootstrapping is painful. Every new session starts with loading env vars and hoping nothing expired.
Existing solutions (and where Access fits)
There are real tools for parts of this problem. Most solve one slice:
Secret managers (1Password CLI, Doppler, Infisical) — inject static secrets at runtime via
op run/doppler run. Great for API keys. Don't handle OAuth refresh or API proxying.Workload identity / OIDC (GitHub Actions OIDC) — avoid long-lived secrets entirely by proving identity for short-lived credentials. Great for CI/CD. Doesn't help with local agent sessions.
Dynamic secrets (Vault dynamic secrets) — mint time-bound credentials on demand. Serious infrastructure. Overkill for most agent setups.
OAuth brokers (Nango, Composio) — handle OAuth authorization, token storage, and refresh. Cloud-first platforms with their own dashboards and billing.
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 |
| 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 |
Quick Start
Prerequisites
Node.js 20+
PostgreSQL (or use the included Docker Compose)
A Google Cloud OAuth app (if you want Google API proxying)
1. Clone and install
git clone https://github.com/Scottpedia0/access.git
cd access
npm install2. Set up the database
# Option A: Use Docker Compose
docker compose up -d
# Option B: Use your own Postgres
# Set DATABASE_URL and DIRECT_DATABASE_URL in .env3. Configure environment
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_SECRETEdit .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)One auth provider (Google OAuth, email magic link, or owner password)
4. Run migrations and seed
npx prisma migrate deploy
npm run db:seed # Creates example services and a consumer token5. Start the app
npm run devVisit http://localhost:3000 and sign in with an email from your OWNER_EMAILS list.
6. Install agent skill + MCP config
bash scripts/install.shThis 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.
Supported Services
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:me@company.com,personal:me@gmail.com). Adding a new adapter is ~100 lines — see Adding a New Service.
Core Endpoints
These aren't service proxies — they're Access itself:
Endpoint | What it does |
| One pull that returns all secrets as env vars + service metadata + docs + linked resources. This is how agents bootstrap a session. |
| Write-only endpoint for submitting new credentials without read access to the store. |
| Look up a single decrypted secret by its env var name. |
| Service metadata, docs, and linked resources. |
| Decrypted secrets for a specific service. |
Authentication
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 |
Permissioning by agent or fleet
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 anythingGrants 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.
Adding a New Service
Each proxy adapter is a Next.js route handler under src/app/api/v1/<service>/route.ts. To add one:
Create
src/app/api/v1/your-service/route.tsUse
authenticateRequestActor()from@/lib/accessfor authRead the API key from the encrypted store (via Prisma) or env vars
Proxy the request to the upstream API
Return the result
Most adapters are under 100 lines. See src/app/api/v1/hubspot/route.ts for a clean example.
Agent Instructions
AGENTS.md in this repo has two sections:
For agents developing on Access — architecture, patterns, data model, commands
For agents using Access — a ready-to-paste block for your
CLAUDE.mdor agent instructions that tells your agents how to bootstrap, pull credentials, and use proxy endpoints
Copy the "For agents USING Access" section into your agent's instruction file and set ACCESS_BASE_URL and ACCESS_TOKEN in your environment.
MCP Server
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 |
|
Cursor | Cursor MCP settings |
Gemini CLI |
|
Windsurf | Windsurf MCP settings |
VS Code (Copilot) |
|
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.
Direct API (No MCP)
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"Architecture
How a request flows
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 tableDesign principles
Agents never see credentials. They send a Bearer token, get back API results.
OAuth is handled server-side. Token refresh, consent flows, multi-account management — all inside Access.
Everything is audited. Every secret access, every API proxy call, every login attempt is logged with actor, timestamp, and IP.
Secrets are encrypted at rest. AES-256-GCM with versioned payloads (
v2.iv.authTag.ciphertext), key rotation supported.Consumer tokens use HMAC. Constant-time comparison, only the prefix is stored — never the raw token.
Stateless proxy. Access doesn't cache or store API responses. It's a pass-through.
Security
AES-256-GCM encryption for all stored secrets
HMAC-SHA256 consumer token hashing with constant-time comparison
Zod input validation on all API endpoints
Audit logging for all access events and auth failures
Owner email allowlist for admin UI access
Error messages in production never leak upstream details
Health endpoint requires auth to expose inventory counts
Rate limiting on auth and API endpoints (configurable, in-memory by default)
Request body size limits on all mutating endpoints
Key Rotation
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_PREVIOUSThe 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.
Security Roadmap
Per-service scoped tokens (split global token into granular permissions)
Key rotation supportRedis-backed rate limiting for serverless
Envelope encryption / KMS integration
Deployment
Access deploys well on Vercel with a Neon or Supabase Postgres database:
Push to GitHub
Import in Vercel
Set all env vars from
.env.exampleSet
NEXTAUTH_URLto your production URLAdd
your-domain.com/api/google/callbackas an authorized redirect URI in Google Cloud ConsoleRun
npx prisma migrate deployvia Vercel build command
Works anywhere Node.js runs — Vercel, Railway, Fly.io, a VPS, your laptop.
Development
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 dataLicense
MIT
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Scottpedia0/access'
If you have feedback or need assistance with the MCP directory API, please join our Discord server