Skip to main content
Glama
README.md
# Keiko

Secure secrets manager for AI agents. Keiko lets AI tools like Claude Code use API tokens, passwords, and credentials **without ever seeing the actual values**.

## The Problem

AI agents need API tokens to do useful work — calling APIs, deploying code, managing infrastructure. But passing secret values through an AI's context window is a security risk: they appear in conversation logs, tool responses, and potentially in training data.

## How Keiko Solves It

Keiko uses a **proxy pattern**. The AI agent tells Keiko *what command to run* and *which secrets it needs*, but never sees the secret values themselves:

```
AI Agent ──► Keiko MCP Server ──► Keiko Backend
                   │                      │
              resolves secrets ◄── HTTPS ──┘
                   │
              spawns: bash -c "your command"
              with secrets as env vars
                   │
              captures output
              sanitizes (redacts leaked values)
                   │
AI Agent ◄── clean output only
```

The AI says *"run this curl command with my API token"* — Keiko injects the token as an environment variable, runs the command, scans the output for any leaked values, redacts them, and returns clean output.

## Quick Start

### 1. Deploy the backend

The backend stores secrets encrypted (AES-256-GCM) and serves them over HTTPS. Deploy with Docker to any platform with persistent storage:

```bash
# Generate an encryption key
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# Deploy (Railway, Render, Fly, Docker Compose, etc.)
# See docs/setup-guide.md for full instructions
```

### 2. Set up the MCP server

The MCP server runs on each machine that needs access to secrets. It's a standalone package with only 2 dependencies — no native compilation needed.

```bash
cd packages/mcp
npm install
npm run build
node dist/index.js --store-token YOUR_TOKEN
```

### 3. Connect to Claude Code

Add to `~/.mcp.json`:

```json
{
  "mcpServers": {
    "keiko": {
      "command": "node",
      "args": ["/absolute/path/to/keiko/packages/mcp/dist/index.js"],
      "env": {
        "KEIKO_URL": "https://your-keiko-backend.example.com"
      }
    }
  }
}
```

Restart Claude Code. Ask *"Check Keiko session status"* to verify.

## How the AI Uses It

Once connected, the AI discovers available secrets and uses them in commands — without ever seeing the values:

```
AI: list_secrets
→ my_api_token [Bearer token in Authorization header]

AI: run_with_secrets
   command: curl -s -H "Authorization: Bearer $API_TOKEN" https://api.example.com/data
   secrets: [{env: "API_TOKEN", name: "my_api_token"}]
→ {"data": [...]}  (secret values redacted from output)
```

Each secret includes `auth_pattern` and `auth_instructions` metadata, so the AI knows how to use it without external documentation.

## MCP Tools

| Tool | Purpose |
|------|---------|
| `run_with_secrets` | Run a command with secrets injected as env vars |
| `list_secrets` | Discover available secrets (names and auth patterns only) |
| `session_status` | Check authentication state |
| `lock` | Kill switch — revoke all active sessions |
| `set_ttl` | Configure session expiry (0.5–24 hours) |
| `add_secret` | Create a new secret |
| `update_secret` | Replace an existing secret's value |
| `get_guide` | Fetch the usage guide |

## Security

- **Encryption at rest** — AES-256-GCM with per-secret random IV, plus versioned keys (`ENCRYPTION_KEY`, `ENCRYPTION_KEY_V2`, …) and an in-place rotation endpoint so the key can be rotated without downtime
- **Hashed auth tokens** — 64-char hex tokens, SHA-256 hashed in the database, plaintext shown once
- **Token scoping** — each token is restricted to a set of secret-name glob patterns (e.g. `railway_*`), so a leaked token only exposes the slice of the vault it actually needs
- **Output sanitization** — command output scanned for secret values in raw, base64, base64url, URL-encoded, hex, JSON-string-escaped, and HTML-entity-escaped forms
- **Per-token rate limit** — independent of per-IP, caps abuse from a single token routed through multiple IPs
- **CSRF protection** — `X-CSRF-Token` header required on every mutating admin-UI endpoint
- **Session management** — configurable TTL, auto-refresh, global kill switch
- **Audit trail** — every action logged with token ID, session ID, IP, and timestamp

Secret values **never** appear in AI tool responses, conversation logs, or on disk on client machines. See `GET /api/guide` for the full threat model — what the proxy pattern does and does not prevent.

## Architecture

```
keiko/
├── packages/mcp/          # MCP server (runs on your machine)
│   ├── src/
│   │   ├── server.ts       #   7 tool registrations
│   │   ├── client.ts       #   HTTPS client to backend
│   │   ├── executor.ts     #   Shell spawner + env var injection
│   │   ├── sanitizer.ts    #   Output redaction
│   │   └── keychain.ts     #   OS keychain (Win/Mac/Linux)
│   └── package.json        #   2 deps: @modelcontextprotocol/sdk + zod
│
├── src/                    # Backend API (runs on your server)
│   ├── api/                #   Express routes, auth, crypto
│   └── ui/                 #   EJS admin templates
│
└── Dockerfile              # Multi-stage production build
```

The MCP server and backend are fully independent packages. The MCP server has **zero native dependencies** — `npm install` works everywhere without compilers or `--ignore-scripts`.

## Platform Support

| Environment | Token Storage | Notes |
|------------|---------------|-------|
| Windows | Windows Credential Manager | Commands run via Git Bash (not WSL) |
| macOS | macOS Keychain | System bash |
| Linux | libsecret | Requires `secret-tool` |
| Docker / CI | `KEIKO_TOKEN` env var | No keychain needed |

## Documentation

- **[Setup Guide](docs/setup-guide.md)** — Full setup instructions for all environments, backend deployment, troubleshooting, API reference, and configuration options

## Tech Stack

**Backend:** Node.js 20, TypeScript, Express, SQLite (better-sqlite3), EJS, Google OAuth

**MCP Server:** Node.js 20, TypeScript, MCP SDK v1.x, Zod

**Deployment:** Docker (multi-stage build), any platform with persistent volumes. Tested with [Railway](https://railway.com).