auth-patterns.md

reference

← Back to skill

Content hash: ab7838c0641d2167f468dc6b89a268419932ad964187610b8df59f0f88ef08cb
## MCP Server Auth Patterns

### The Skill Vault pattern (reference implementation)

```
Authorization: Bearer <api_key>  OR  X-Agent-Key: <key>
```

Two paths, same resolution: the server resolves the key from EITHER the header
or a tool argument, normalizes to agent identity, and enforces scope.

### Scope enforcement table
| Action | Regular agent | Super-agent |
|--------|--------------|-------------|
| Publish personal/team | ✓ | ✓ |
| Publish global | DENIED (SV_FORBIDDEN) | ✓ |
| Update own skill | ✓ | ✓ |
| Update foreign skill | DENIED | DENIED (owner only, or ✓ admin override) |
| Delete own skill | ✓ | ✓ |
| Delete foreign skill | DENIED | ✓ (admin) |
| List global skills | ✓ (public) | ✓ |

### Key management patterns
- **Onboard**: generate key, return ONCE, store hash server-side
- **Rotate**: issue new key, invalidate old
- **Revoke**: mark key invalid, reject all future calls
- **Never log raw keys**: log only key prefix or hash

### Transport-specific hardening

| Transport | Risk | Mitigation |
|-----------|------|-----------|
| stdio | Minimal (local process) | Validate inputs server-side |
| Streamable HTTP | Network-exposed | Auth header, rate limit, CORS, TLS |

### Input validation checklist
```
[ ] Empty names/bodies rejected before execution
[ ] Max lengths enforced on all string params
[ ] Enum values validated (not just hoped)
[ ] Domain errors mapped to structured codes (SV_FORBIDDEN, SV_NOT_FOUND)
[ ] Stack traces NEVER returned to callers
[ ] Tool args treated as untrusted input (from the LLM, which is attacker-influenced)
```

### Audit log requirements
Every mutation tool call must log:
- agent_id (who)
- tool_name (what action)
- timestamp (when)
- result (success/failure)
- Never: the raw API key, full request body containing secrets