Blame

3c5a91 Claude (MCP) 2026-03-15 06:15:32
[mcp] VS-2: Document persistent MCP OAuth implementation
1
---
2
category: reference
3
tags:
4
- vs-2
5
- oauth
6
- mcp
7
- infrastructure
8
last_updated: 2026-03-15
9
---
10
11
# VS-2: Persistent MCP OAuth for Claude.ai
12
13
## Problem
14
15
The otterwiki-mcp server used FastMCP's `InMemoryOAuthProvider` for OAuth 2.1. All OAuth state (registered clients, authorization codes, access/refresh tokens) was lost on every server restart, forcing Claude.ai to re-authorize each time.
16
17
## Solution
18
19
Replaced `InMemoryOAuthProvider` with `SQLiteOAuthProvider` — a drop-in persistent provider backed by a local SQLite database.
20
21
## Changes
22
23
| File | Description |
24
|------|-------------|
25
| `otterwiki_mcp/oauth_store.py` | New SQLiteOAuthProvider implementing FastMCP's OAuthProvider interface |
26
| `otterwiki_mcp/server.py` | Swapped InMemoryOAuthProvider for SQLiteOAuthProvider |
27
| `otterwiki_mcp/config.py` | Added `MCP_OAUTH_DB` env var (default: `mcp_oauth.db`) |
28
| `tests/test_oauth_store.py` | 20 tests covering registration, auth flow, tokens, refresh, revocation, persistence |
29
| `tests/test_server_auth.py` | Updated to expect SQLiteOAuthProvider; uses `:memory:` DB for test isolation |
30
| `.gitignore` | Added `*.db` pattern |
31
32
## Configuration
33
34
- **`MCP_OAUTH_DB`** — Path to the SQLite database file. Default: `mcp_oauth.db` in the working directory. Set to `:memory:` for ephemeral (test) usage.
35
36
## Token Lifetimes
37
38
| Token Type | Expiry |
39
|------------|--------|
40
| Authorization code | 10 minutes |
41
| Access token | 1 hour |
42
| Refresh token | 30 days |
43
44
## Schema
45
46
Three tables, auto-created on first use:
47
48
- **oauth_clients** — Registered OAuth clients (client_id, full client JSON, created_at)
49
- **oauth_codes** — Authorization codes (code, client_id, redirect_uri, PKCE challenge, scopes, expiry, resource)
50
- **oauth_tokens** — Access and refresh tokens stored as paired rows (token, client_id, scopes, expiry, type, paired counterpart, resource)
51
52
Token pairs are linked: revoking either token in a pair removes both.
53
54
## Branch
55
56
`feat/persistent-oauth` on otterwiki-mcp repo. Not pushed, not merged.
57
58
## Test Results
59
60
All 133 tests pass (20 new + 113 existing).