Passman Documentation
Complete reference for the secure credential proxy MCP server. Learn how to install, configure, and use all 13 tools across 4 protocols.
Introduction
Passman is a secure credential proxy that lets AI agents use your passwords, API tokens, SSH keys, and other secrets without ever seeing them. It implements the Model Context Protocol (MCP), which means it works with any MCP-compatible client: Claude Code, Cursor, VS Code Copilot, Claude Desktop, and Windsurf.
How It Works
Passman sits between the AI agent and your external services. Secrets never appear in the conversation:
| Step | What Happens |
|---|---|
| 1. AI Requests | The agent calls an MCP tool, referencing a credential by name or UUID |
| 2. Policy Check | Passman validates the request against per-credential policies (URL patterns, command patterns, rate limits) |
| 3. Secret Injection | The credential is decrypted from the vault and injected into the outbound request server-side |
| 4. Execute & Scrub | The request executes and the response is sanitized — all secret traces removed across 6 encodings |
| 5. Safe Result | The AI receives the clean result. Secrets were never visible to the agent. |
Security Model
| Layer | Protection |
|---|---|
| No Raw Secret Access | The MCP protocol never exposes secret values. No read_secret tool exists. |
| Output Sanitization | All proxy responses scrubbed across 6 encoding variants (raw, Base64, URL-encoded, hex, upper hex, partial) |
| Policy Engine | Per-credential rules: URL whitelists, command patterns, read-only SQL, recipient restrictions, rate limits |
| Rate Limiting | Per-credential rate limits prevent runaway usage and abuse |
| Audit Trail | Every operation logged with timestamp, credential, operation type, and outcome |
| Memory Safety | Built in Rust with zeroize for cryptographic memory hygiene. Secrets wiped from RAM after use. |
Installation
One-Line Installer (Recommended)
Downloads a pre-built binary for your platform. No Rust toolchain required.
The binary is installed to ~/.local/bin/passman-mcp-server.
Build from Source
Requires the Rust toolchain.
Desktop GUI
A Tauri v2 + React desktop app for managing your vault visually. Shares the same vault file as the MCP server.
| Platform | Download |
|---|---|
| macOS (Apple Silicon) | .dmg (ARM64) |
| macOS (Intel) | .dmg (x64) |
| Windows | .exe Installer · .msi |
| Linux | AppImage · .deb · .rpm |
The app is not signed with an Apple Developer certificate. After installing, run this in Terminal:
Verify Installation
Configuration
Add Passman to your MCP client. Pick your client and paste the config.
Claude Code
Create .mcp.json in your project root, or use the CLI:
Or manually add to .mcp.json:
Cursor
VS Code Copilot
Claude Desktop
Windsurf
Getting Started
Walk through the basic flow: unlock, store, use, lock.
1. Unlock the Vault
On first run, a new vault is created automatically.
2. Store a Credential
3. Use the Credential
The AI agent makes an HTTP request. Passman injects the token and scrubs the response.
4. Lock the Vault
Tools Reference
Passman exposes 13 MCP tools across 5 categories.
Vault Management
vault_unlock
Unlock the vault with the master password. Creates a new vault if none exists.
| Parameter | Type | Required | Description |
|---|---|---|---|
password | String | required | Master password to unlock the vault |
Output: Confirmation message with credential count.
vault_lock
Lock the vault, clearing the encryption key from memory.
Parameters: None
vault_status
Check vault status: locked/unlocked, credential count, environments in use.
Parameters: None
Discovery
credential_list
List credentials with optional filters. Never returns secret values.
| Parameter | Type | Required | Description |
|---|---|---|---|
kind | String | optional | Filter by kind: password, api_token, ssh_key, ssh_password, database_connection, certificate, smtp_account, custom |
environment | String | optional | Filter by environment: local, development, staging, production |
tag | String | optional | Filter by tag |
credential_search
Search credentials by name, tags, or notes. Never returns secret values.
| Parameter | Type | Required | Description |
|---|---|---|---|
query | String | required | Search query (matches name, tags, notes) |
credential_info
Get detailed metadata for a credential. Never returns secret values.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | String | required | Credential UUID |
Storage
credential_store
Store a new credential in the vault. The secret field structure depends on the credential kind (see Credential Types).
| Parameter | Type | Required | Description |
|---|---|---|---|
name | String | required | Human-readable name for the credential |
kind | String | required | Credential kind (see types) |
environment | String | required | Environment: local, development, staging, production |
secret | Object | required | Secret data (structure depends on kind) |
tags | String[] | optional | Tags for categorization |
notes | String | optional | Freeform notes |
credential_delete
Delete a credential from the vault. Requires explicit confirmation.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | String | required | Credential UUID to delete |
confirm | Boolean | required | Must be true to confirm deletion |
Protocol Proxies
http_request
Make an HTTP request using a stored credential for authentication. The credential's secret is injected as auth headers and never exposed. Response is sanitized.
| Parameter | Type | Required | Description |
|---|---|---|---|
credential_id | String | required | Credential UUID for authentication |
method | String | required | GET, POST, PUT, PATCH, DELETE, HEAD |
url | String | required | Target URL |
headers | Object | optional | Additional HTTP headers (key-value pairs) |
body | String | optional | Request body |
Auth modes depend on the credential type:
- api_token — Injects
header_name: prefix + token(e.g.Authorization: Bearer ghp_xxx) - password — Uses HTTP Basic Auth (
Authorization: Basic base64(user:pass)) - custom — Injects custom fields as headers
ssh_exec
Execute a command on a remote host via SSH. Supports both SSH key and SSH password credentials. Output is sanitized.
| Parameter | Type | Required | Description |
|---|---|---|---|
credential_id | String | required | Credential UUID (SSH key or SSH password) |
command | String | required | Shell command to execute on the remote host |
sql_query
Execute a SQL query using a stored database credential. Supports PostgreSQL, MySQL, and SQLite. Results are sanitized. Policy can enforce read-only mode.
| Parameter | Type | Required | Description |
|---|---|---|---|
credential_id | String | required | Credential UUID (database connection) |
query | String | required | SQL query to execute |
params | Array | optional | Positional query parameters for parameterized queries |
Always use parameterized queries to prevent SQL injection. Use $1, $2 placeholders and pass values via params.
send_email
Send an email using a stored SMTP credential. Recipients can be restricted by policy.
| Parameter | Type | Required | Description |
|---|---|---|---|
credential_id | String | required | Credential UUID (SMTP account) |
to | String[] | required | Recipient email addresses |
subject | String | required | Email subject |
body | String | required | Email body (plain text) |
cc | String[] | optional | CC recipients |
bcc | String[] | optional | BCC recipients |
Audit
audit_log
View the audit log of proxy operations. Filter by credential, limit results, or filter by time range.
| Parameter | Type | Required | Description |
|---|---|---|---|
credential_id | String | optional | Filter by credential UUID |
limit | Integer | optional | Maximum number of entries to return |
since | String | optional | Only entries after this RFC3339 datetime (e.g. 2025-01-15T00:00:00Z) |
Credential Types
Passman supports 8 credential types. Each type has a specific JSON schema for the secret field when storing a credential.
Password
Username/password pairs for web services, APIs, or any login.
API Token
Bearer tokens, API keys, and other token-based authentication.
SSH Key
SSH key-based authentication for remote server access.
SSH Password
SSH password-based authentication for remote server access.
Database Connection
Connection credentials for PostgreSQL, MySQL, or SQLite databases.
Certificate
PEM-encoded certificates and private keys for mutual TLS or client certificate authentication.
SMTP Account
SMTP server credentials for sending email.
Custom
Arbitrary key-value pairs for credentials that don't fit other types.
Environments
Every credential is tagged with an environment for organizational purposes.
| Environment | Description |
|---|---|
local | Local development machine |
development | Shared development / sandbox environment |
staging | Pre-production staging environment |
production | Live production environment |
custom | Any custom string (e.g. "dr-staging", "eu-west") |
Use environments to filter credentials with credential_list and to organize your vault when you have credentials for the same service across different environments.
Policy Engine
The policy engine provides per-credential access controls. When policy patterns are specified, unmatched requests are denied by default.
Policy Fields
| Field | Type | Description |
|---|---|---|
allowed_tools | String[] | Which MCP tools can use this credential (e.g. ["http_request"]) |
http_url_patterns | String[] | URL glob patterns allowed for HTTP requests (e.g. ["https://api.github.com/*"]) |
ssh_command_patterns | String[] | Command glob patterns allowed for SSH (e.g. ["ls *", "cat *"]) |
sql_allow_write | Boolean | If false (default), blocks INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE, REPLACE, MERGE |
smtp_allowed_recipients | String[] | Email glob patterns for allowed recipients (e.g. ["*@company.com"]) |
rate_limit | Object | { "max_requests": 100, "window_secs": 3600 } — sliding window rate limit |
All patterns use glob-style matching with * as wildcard. Example: https://api.github.com/* matches any path under that domain. If no patterns are specified for a category, all requests for that category are allowed.
Full Policy Example
SQL Read-Only Enforcement
When sql_allow_write is false, the following SQL statements are blocked:
INSERT,UPDATE,DELETEDROP,ALTER,CREATETRUNCATE,REPLACE,MERGE
Output Sanitization
Every proxy response is scrubbed to ensure secrets cannot leak back to the AI agent, even if the external service echoes them.
Encoding Variants
For each secret value (4+ characters), the sanitizer checks and replaces across 6 encoding variants:
| # | Encoding | Example |
|---|---|---|
| 1 | Raw | my-secret-token |
| 2 | Base64 (Standard) | bXktc2VjcmV0LXRva2Vu |
| 3 | Base64 (URL-safe) | bXktc2VjcmV0LXRva2Vu |
| 4 | URL-encoded | my-secret-token (percent-encoded if special chars) |
| 5 | Hex (lowercase) | 6d792d7365637265742d746f6b656e |
| 6 | Hex (uppercase) | 6D792D7365637265742D746F6B656E |
Secrets shorter than 4 characters are not sanitized to avoid false positives with common words or values.
What Gets Sanitized
| Proxy | Sanitized Output |
|---|---|
| http_request | Response body and response headers |
| ssh_exec | stdout and stderr |
| sql_query | Query result values |
| send_email | Status messages |
All matched values are replaced with [REDACTED].
Desktop GUI
The desktop app provides a visual interface for managing your Passman vault. Built with Tauri v2 and React, it shares the same vault file as the MCP server — changes sync automatically.
Screens
| Screen | Description |
|---|---|
| Unlock | Master password entry. Creates a new vault on first run. |
| Vault Browser | List, search, and filter all credentials. Displays metadata only — no secrets shown. |
| Credential Editor | Create and edit credentials with form fields matching each credential type's schema. |
| Policy Editor | Configure per-credential policies: URL patterns, command patterns, rate limits. |
| Audit Log | Browse and filter the audit trail of all proxy operations. |
| Settings | Configure MCP server auto-install, vault file location, and other preferences. |
MCP Auto-Install
The desktop GUI can automatically install the MCP server configuration for detected AI clients (Claude Code, Cursor, VS Code, Claude Desktop, Windsurf).
Install via CLI
Build from Source
Architecture
Passman is a Rust workspace with a layered architecture. Each crate has a single responsibility.
Crate Structure
| Crate | Responsibility |
|---|---|
passman-vault | Encryption, KDF, credential storage, policy engine, audit log |
passman-proxy | HTTP, SSH, SQL, SMTP proxy clients + output sanitizer |
passman-mcp-server | MCP protocol implementation, tool definitions, stdio transport |
gui/ | Tauri v2 + React desktop application |
Tech Stack
| Component | Technology |
|---|---|
| Language | Rust |
| Encryption | AES-256-GCM (aes-gcm crate) |
| Key Derivation | Argon2id (64 MiB memory, 3 iterations, 4 parallelism) |
| HTTP Client | reqwest (rustls-tls) |
| SSH Client | russh |
| SQL Client | sqlx (PostgreSQL, MySQL, SQLite) |
| SMTP Client | lettre |
| MCP Protocol | rmcp (stdio transport) |
| Memory Safety | zeroize (cryptographic memory hygiene) |
| Desktop GUI | Tauri v2 + React + TypeScript |
File Locations
| File | Purpose |
|---|---|
~/.passman/vault.json | Vault file (credentials encrypted with AES-256-GCM) |
~/.passman/audit.jsonl | Audit log (JSON Lines, append-only) |
Common Workflows
Store and Use an API Key
SSH into a Server
Query a Database
Send an Email
Review the Audit Trail
Set Up Policies
Policies are set per-credential when storing via the Desktop GUI policy editor, or by including policy rules in the vault configuration.
Troubleshooting
Common Errors
| Error | Cause | Solution |
|---|---|---|
Vault is locked | Trying to use tools before unlocking | Call vault_unlock first |
Policy denied | Request doesn't match the credential's policy rules | Check the credential's policy — update URL patterns, command patterns, or allowed tools |
Rate limit exceeded | Too many requests in the rate limit window | Wait for the window to reset, or increase the max_requests / window_secs |
Binary not found | passman-mcp-server not in PATH | Ensure ~/.local/bin is in your PATH, or use the full path in MCP config |
macOS Gatekeeper block | Unsigned binary quarantined by macOS | Run: xattr -cr /Applications/Passman.app |
Connection refused (SSH) | Wrong host, port, or firewall blocking | Verify host/port in the SSH credential. Check that the remote server allows SSH connections. |
SQL: write not allowed | sql_allow_write is false in policy | Set sql_allow_write: true in the credential's policy |
Invalid credential kind | Secret fields don't match the kind schema | Check the Credential Types section for the correct schema |
Debugging Tips
- Use
vault_statusto check if the vault is unlocked and how many credentials are loaded - Use
credential_info(id="...")to inspect a credential's metadata (kind, environment, tags) - Use
audit_log(limit=5)to check recent operations and see if they succeeded - If the MCP server doesn't appear in your client, verify the config file path and restart the client
- Ensure
~/.local/binis in your shell's PATH: addexport PATH="$HOME/.local/bin:$PATH"to your~/.bashrcor~/.zshrc
File Permissions
The vault file at ~/.passman/vault.json should only be readable by your user:
FAQ
Can AI agents read my passwords?
No. Passman has no read_secret tool. AI agents can only reference credentials by name or UUID. The actual secret values are decrypted server-side and injected into outbound requests. Furthermore, all responses are sanitized across 6 encoding variants to prevent accidental leaks.
Where is my data stored?
All data is stored locally on your machine:
~/.passman/vault.json— Encrypted vault file~/.passman/audit.jsonl— Audit log
No cloud sync, no telemetry, no third-party access. Your secrets never leave your machine except when proxied to the target service.
What encryption is used?
Passman uses AES-256-GCM for encryption with Argon2id for key derivation (64 MiB memory, 3 iterations, 4 parallelism). The encryption key is derived from your master password and wiped from memory (using Rust's zeroize crate) when you lock the vault.
Can multiple AI clients use the same vault?
Yes. The vault is a single file on disk. Both the MCP server and the Desktop GUI can access it. However, only one process should write to the vault at a time — the MCP server and GUI coordinate through file locking.
What happens if I forget my master password?
The vault cannot be recovered without the master password. There is no password reset, no recovery key, and no backdoor. This is by design — it means even if someone obtains your vault file, they cannot access your credentials without the password.
Is Passman free?
Yes, free forever. Passman is open source under the MIT License. No paid tiers, no subscriptions, no usage limits.
Which MCP clients are supported?
Any MCP-compatible client that supports stdio transport. Tested with:
- Claude Code (CLI)
- Claude Desktop
- Cursor
- VS Code Copilot
- Windsurf
How do I update Passman?
Run the installer again. It will download and replace the existing binary:
Your vault file is preserved across updates.