agent-auth
Enables AI agents to authenticate to Amazon Web Services (AWS) by injecting credentials for login and API calls, including TOTP.
Provides secure credential injection for AI agents to authenticate to GitHub, enabling login operations without exposing passwords.
Allows AI agents to authenticate to OpenAI's API by injecting API keys via bearer header or other methods.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@agent-authLog into GitHub"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
agent-auth
Zero-knowledge credential injection for AI agents. Your agent authenticates to websites and APIs without ever seeing a password, TOTP code, or API key.
Agent says: fill #email with {{email}}, fill #password with {{password}}, click Sign In
agent-auth: resolves {{email}} and {{password}} from encrypted vault, injects into browser
Agent gets: "Login completed." (never sees the real values)Why
AI agents are getting good at browsing the web and calling APIs. But authentication is a wall — you either hand the agent your password (dangerous) or do it yourself every time (defeats the purpose).
agent-auth sits between the agent and the browser. The agent describes what to do with placeholder tokens. agent-auth resolves the real credentials from a local encrypted vault and injects them directly into the browser via CDP. The agent never touches the secret material.
Works with any MCP-compatible agent: Claude Code, Claude Desktop, OpenCode, Cursor, or your own.
Related MCP server: Access
How It Works
AI Agent agent-auth Browser
| | |
| "Log into AWS" | |
| steps: [ | |
| fill #email {{email}} | |
| fill #pass {{password}} | 1. Decrypt from local vault |
| fill #totp {{totp}} | 2. Generate TOTP from seed |
| click Submit | 3. Inject via CDP --------->| Form filled
| ] | 4. Zero memory |
| | |
| "Login completed" <--------- | |
| | |
| (never saw any secrets) | (secrets wiped from RAM) |Quick Start
# Clone and install
git clone https://github.com/ex-nihilo-labs/agent-auth.git
cd agent-auth && bun install
# Create your vault (you'll set a passphrase)
bun run src/index.ts init
# Add a credential
bun run src/index.ts add github \
--username "you@example.com" \
--password "your-password" \
--domains "github.com"
# Add one with TOTP
bun run src/index.ts add aws-root \
--username "admin@company.com" \
--password "hunter2" \
--totp "JBSWY3DPEHPK3PXP" \
--domains "signin.aws.amazon.com,console.aws.amazon.com"
# See what's stored (names only — no secrets shown)
bun run src/index.ts list
# → github (domains: github.com)
# → aws-root (domains: signin.aws.amazon.com, console.aws.amazon.com)Connect to Your Agent
agent-auth is an MCP server. Add it to your agent's config:
Claude Code / Claude Desktop
Add to .mcp.json in your project root (or ~/.claude/settings.json for global):
{
"mcpServers": {
"agent-auth": {
"type": "stdio",
"command": "bun",
"args": ["run", "/path/to/agent-auth/src/index.ts", "serve"],
"env": {
"AGENT_AUTH_CDP_URL": "http://localhost:9222"
}
}
}
}The passphrase is read from your OS keychain automatically (stored during init). For development, you can set AGENT_AUTH_PASSPHRASE in the env block instead.
Other MCP Agents
Any agent that speaks MCP over stdio can use agent-auth. Start the server:
bun run src/index.ts serveIt exposes three tools over stdin/stdout JSONRPC.
MCP Tools
Tool | What the agent sends | What the agent gets back |
| Service name + browser steps with | "Login completed" or error |
| Service name + HTTP request details | API response body (credentials redacted) |
| (nothing) | Service names and allowed domains only |
secure_login
Browser-based authentication. The agent describes the login flow as steps:
{
"service": "github",
"url": "https://github.com/login",
"steps": [
{ "action": "fill", "selector": "#login_field", "value": "{{email}}" },
{ "action": "fill", "selector": "#password", "value": "{{password}}" },
{ "action": "click", "selector": "input[type='submit']" },
{ "action": "wait", "selector": ".logged-in", "timeout": 5000 }
]
}Step actions: fill, type (character-by-character for SPAs), click, wait, select.
auth_api
Authenticated HTTP requests. Six injection methods:
{
"service": "openai",
"url": "https://api.openai.com/v1/models",
"method": "GET",
"injection": "bearer"
}Injection methods: bearer, header, query, basic, json_body, form.
list_credentials
Returns service names and allowed domains. Never returns passwords, TOTP seeds, or API keys.
Security Model
The core guarantee: credentials never appear in MCP responses. They flow from vault to browser/HTTP and are zeroed from memory immediately after.
Layer | Implementation |
Encryption at rest | AES-256-GCM, 12-byte random nonce per field |
Key derivation | Argon2id (3 iterations, 64MB memory, 4 parallelism) |
Master key storage | OS keychain (macOS Keychain, Linux secret-tool) with encrypted file fallback |
Memory hygiene | All credentials as |
Domain allowlist | Deny-by-default. Each credential lists which domains it can be injected into. |
Redirect protection | Domain re-verified after every navigation step. Aborts if redirect leaves the allowlist. |
Human approval | First use of each credential+domain pair sends a push notification (Pushover) with a 4-digit code. 50-second window. |
Rate limiting | 3 requests/minute, 20/hour. Persisted in SQLite across restarts. |
Audit trail | Append-only JSONL log. All credential values masked. |
No cloud | Everything local. Vault never synced, uploaded, or phoned home. |
CLI Reference
All CLI commands are human-only — never exposed via MCP.
agent-auth init # Create vault, set passphrase
agent-auth add <service> # Add credential (interactive or with flags)
agent-auth list # List services (names only)
agent-auth remove <service> # Delete a credential
agent-auth domains <service> # View/edit allowed domains
agent-auth approve <code> # Approve a pending auth request
agent-auth unlock # Unlock vault for current session
agent-auth lock # Lock vault, clear key from memory
agent-auth serve # Start MCP server (stdio)Flags for add: --username, --password, --totp (base32 or otpauth:// URI), --domains (comma-separated), --notes.
Environment Variables
Variable | Purpose | Default |
| Chrome DevTools Protocol endpoint for browser injection | (none — browser tools disabled) |
| Vault passphrase (dev/CI only — use keychain in production) | (prompt or keychain) |
| Skip OS keychain, use file-only key storage |
|
| Pushover app token for approval notifications | (approval disabled) |
| Pushover user key | (approval disabled) |
Architecture
agent-auth/
├── src/
│ ├── index.ts # CLI dispatcher + MCP serve
│ ├── mcp/ # MCP server (3 tools over stdio JSONRPC)
│ ├── browser/ # CDP injection via Playwright (fill/type/click/wait/select)
│ ├── placeholder/ # {{email}}, {{username}}, {{password}}, {{totp}} resolution
│ ├── vault/ # AES-256-GCM encrypted SQLite + Argon2id KDF
│ ├── totp/ # TOTP generation via otpauth
│ ├── proxy/ # HTTP credential injection (6 methods)
│ ├── approval/ # Human approval gate + Pushover
│ ├── security/ # Rate limiter, input validator, domain allowlist
│ ├── audit/ # Append-only JSONL audit log
│ └── cli/ # Human-only credential management
└── tests/ # 65 tests across 6 suitesVault location: ~/.agent-auth/vault.db (SQLite, mode 0600)
Dependencies (intentionally minimal):
@modelcontextprotocol/sdk— MCP protocolplaywright-core— CDP browser automation (no bundled browser)bun:sqlite— Built-in SQLite (zero deps)otpauth— TOTP generation (5KB, pure JS)@noble/hashes— Argon2id KDF (audited, pure JS)zod— Input validation
Testing
bun test # 65 tests, 6 suites
bun run typecheck # TypeScript strict modeTests use AGENT_AUTH_NO_KEYCHAIN=1 to avoid macOS Keychain permission dialogs in CI.
Acknowledgments
agent-auth was inspired by these projects:
AgentSecrets (MIT) — Crypto envelope design (AES-256-GCM + Argon2id), domain allowlists, HTTP credential proxy pattern.
Virtual FIDO (MIT) — Passkey/WebAuthn emulation architecture. Planned for future passkey support.
Roadmap
Passkey/WebAuthn support via Virtual FIDO signing
npx agent-auth/ global installCredential import from 1Password, Bitwarden (CLI export)
Browser profile persistence (stay logged in across sessions)
Multi-page login flow templates (common services)
Contributing
PRs welcome. The codebase is small (~1,500 lines) and intentionally simple.
Ground rules:
No cloud features. The vault is local-only. This is not negotiable.
No new runtime dependencies without justification. We have 5 — that's enough.
Credentials must never be converted to JS strings.
Buffer/Uint8Arrayonly.Tests required for any new functionality.
# Development
bun install
AGENT_AUTH_NO_KEYCHAIN=1 bun test # Run tests
bun run typecheck # Type checkLicense
MIT — Ex Nihilo Labs, 2026
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/ex-nihilo-labs/agent-auth'
If you have feedback or need assistance with the MCP directory API, please join our Discord server