mcp-twake-mail 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +77 -48
  2. package/build/cli/commands/setup.js +54 -12
  3. package/build/cli/commands/setup.js.map +1 -1
  4. package/build/cli/prompts/setup-wizard.d.ts +33 -1
  5. package/build/cli/prompts/setup-wizard.js +134 -2
  6. package/build/cli/prompts/setup-wizard.js.map +1 -1
  7. package/build/cli/prompts/setup-wizard.test.d.ts +1 -0
  8. package/build/cli/prompts/setup-wizard.test.js +161 -0
  9. package/build/cli/prompts/setup-wizard.test.js.map +1 -0
  10. package/build/config/schema.d.ts +2 -0
  11. package/build/config/schema.js +3 -0
  12. package/build/config/schema.js.map +1 -1
  13. package/build/discovery/dns-srv.d.ts +18 -0
  14. package/build/discovery/dns-srv.js +60 -0
  15. package/build/discovery/dns-srv.js.map +1 -0
  16. package/build/discovery/dns-srv.test.d.ts +4 -0
  17. package/build/discovery/dns-srv.test.js +79 -0
  18. package/build/discovery/dns-srv.test.js.map +1 -0
  19. package/build/discovery/index.d.ts +9 -0
  20. package/build/discovery/index.js +13 -0
  21. package/build/discovery/index.js.map +1 -0
  22. package/build/discovery/oauth-discovery.d.ts +34 -0
  23. package/build/discovery/oauth-discovery.js +160 -0
  24. package/build/discovery/oauth-discovery.js.map +1 -0
  25. package/build/discovery/oauth-discovery.test.d.ts +1 -0
  26. package/build/discovery/oauth-discovery.test.js +198 -0
  27. package/build/discovery/oauth-discovery.test.js.map +1 -0
  28. package/build/discovery/orchestrator.d.ts +31 -0
  29. package/build/discovery/orchestrator.js +87 -0
  30. package/build/discovery/orchestrator.js.map +1 -0
  31. package/build/discovery/orchestrator.test.d.ts +4 -0
  32. package/build/discovery/orchestrator.test.js +242 -0
  33. package/build/discovery/orchestrator.test.js.map +1 -0
  34. package/build/discovery/types.d.ts +18 -0
  35. package/build/discovery/types.js +15 -0
  36. package/build/discovery/types.js.map +1 -0
  37. package/build/discovery/well-known.d.ts +21 -0
  38. package/build/discovery/well-known.js +52 -0
  39. package/build/discovery/well-known.js.map +1 -0
  40. package/build/discovery/well-known.test.d.ts +4 -0
  41. package/build/discovery/well-known.test.js +120 -0
  42. package/build/discovery/well-known.test.js.map +1 -0
  43. package/build/mcp/server.d.ts +5 -3
  44. package/build/mcp/server.js +11 -5
  45. package/build/mcp/server.js.map +1 -1
  46. package/build/mcp/tools/email-sending.d.ts +10 -1
  47. package/build/mcp/tools/email-sending.js +60 -15
  48. package/build/mcp/tools/email-sending.js.map +1 -1
  49. package/build/mcp/tools/index.d.ts +10 -1
  50. package/build/mcp/tools/index.js +4 -3
  51. package/build/mcp/tools/index.js.map +1 -1
  52. package/build/signature/converter.d.ts +2 -0
  53. package/build/signature/converter.js +23 -0
  54. package/build/signature/converter.js.map +1 -0
  55. package/build/signature/converter.test.d.ts +1 -0
  56. package/build/signature/converter.test.js +84 -0
  57. package/build/signature/converter.test.js.map +1 -0
  58. package/build/signature/index.d.ts +2 -0
  59. package/build/signature/index.js +3 -0
  60. package/build/signature/index.js.map +1 -0
  61. package/build/signature/loader.d.ts +6 -0
  62. package/build/signature/loader.js +31 -0
  63. package/build/signature/loader.js.map +1 -0
  64. package/build/signature/loader.test.d.ts +1 -0
  65. package/build/signature/loader.test.js +85 -0
  66. package/build/signature/loader.test.js.map +1 -0
  67. package/docs/auto-discovery.md +210 -0
  68. package/docs/oidc-configuration.md +261 -0
  69. package/package.json +3 -1
@@ -0,0 +1,261 @@
1
+ # OIDC Configuration Guide
2
+
3
+ This guide explains how to configure mcp-twake-mail for OpenID Connect (OIDC) authentication with your JMAP email server.
4
+
5
+ ## Overview
6
+
7
+ OIDC authentication uses the OAuth 2.0 Authorization Code flow with PKCE (Proof Key for Code Exchange) to securely authenticate users. This is the recommended method for enterprise environments with Single Sign-On (SSO).
8
+
9
+ **Key benefits:**
10
+ - No passwords stored in configuration files
11
+ - Automatic token refresh
12
+ - Enterprise SSO integration
13
+ - Secure PKCE S256 code challenge
14
+
15
+ ## Prerequisites
16
+
17
+ Before configuring OIDC, you need:
18
+
19
+ 1. **OIDC Provider** — An identity provider that supports OpenID Connect:
20
+ - Keycloak
21
+ - Auth0
22
+ - Okta
23
+ - Azure AD
24
+ - Google Workspace
25
+ - Any OIDC-compliant provider
26
+
27
+ 2. **Client Registration** — A registered OAuth client with:
28
+ - Client ID
29
+ - Redirect URI: `http://localhost:3000/callback`
30
+ - Authorization Code flow enabled
31
+ - PKCE support (S256)
32
+
33
+ 3. **JMAP Server** — Must accept tokens from your OIDC provider
34
+
35
+ ## Quick Setup
36
+
37
+ The easiest way to configure OIDC is with the setup wizard:
38
+
39
+ ```bash
40
+ npx mcp-twake-mail setup
41
+ ```
42
+
43
+ Choose **OIDC** when prompted for authentication method. The wizard will:
44
+ 1. Ask for OIDC issuer URL
45
+ 2. Ask for client ID
46
+ 3. Open your browser for authentication
47
+ 4. Store tokens securely
48
+ 5. Generate configuration
49
+
50
+ ## Configuration Variables
51
+
52
+ | Variable | Required | Description | Example |
53
+ |----------|----------|-------------|---------|
54
+ | `JMAP_SESSION_URL` | Yes | JMAP server session URL | `https://jmap.example.com/jmap/session` |
55
+ | `JMAP_AUTH_METHOD` | Yes | Must be `oidc` | `oidc` |
56
+ | `JMAP_OIDC_ISSUER` | Yes | OIDC provider base URL | `https://sso.example.com` |
57
+ | `JMAP_OIDC_CLIENT_ID` | Yes | OAuth client identifier | `mcp-twake-mail` |
58
+ | `JMAP_OIDC_SCOPE` | No | OAuth scopes to request | `openid profile email offline_access` |
59
+ | `JMAP_OIDC_REDIRECT_URI` | No | OAuth callback URL | `http://localhost:3000/callback` |
60
+
61
+ ### Scopes
62
+
63
+ The default scopes are: `openid profile email offline_access`
64
+
65
+ | Scope | Required | Purpose |
66
+ |-------|----------|---------|
67
+ | `openid` | Yes | OpenID Connect authentication |
68
+ | `profile` | Recommended | User profile information |
69
+ | `email` | Recommended | User email address |
70
+ | `offline_access` | Recommended | Refresh token for automatic renewal |
71
+
72
+ **Important:** Include `offline_access` to enable automatic token refresh. Without it, users must re-authenticate when the access token expires.
73
+
74
+ ### Redirect URI
75
+
76
+ The default redirect URI is `http://localhost:3000/callback`.
77
+
78
+ You can customize this with `JMAP_OIDC_REDIRECT_URI`, but it must:
79
+ - Match exactly what's registered in your OIDC provider
80
+ - Be accessible on your local machine during authentication
81
+ - Use HTTP for localhost (HTTPS not required)
82
+
83
+ For remote development (e.g., via ngrok), use the full ngrok URL:
84
+ ```
85
+ JMAP_OIDC_REDIRECT_URI=https://abc123.ngrok.io/callback
86
+ ```
87
+
88
+ ## Claude Desktop Configuration
89
+
90
+ ```json
91
+ {
92
+ "mcpServers": {
93
+ "mcp-twake-mail": {
94
+ "command": "npx",
95
+ "args": ["-y", "mcp-twake-mail"],
96
+ "env": {
97
+ "JMAP_SESSION_URL": "https://jmap.example.com/jmap/session",
98
+ "JMAP_AUTH_METHOD": "oidc",
99
+ "JMAP_OIDC_ISSUER": "https://sso.example.com",
100
+ "JMAP_OIDC_CLIENT_ID": "mcp-twake-mail",
101
+ "JMAP_OIDC_SCOPE": "openid profile email offline_access"
102
+ }
103
+ }
104
+ }
105
+ }
106
+ ```
107
+
108
+ ## Authentication Flow
109
+
110
+ ### Initial Authentication
111
+
112
+ 1. **Start mcp-twake-mail** — The MCP server starts
113
+ 2. **Check for tokens** — Looks in `~/.mcp-twake-mail/tokens.json`
114
+ 3. **If no valid token** — Opens browser for OIDC login
115
+ 4. **User authenticates** — In browser with OIDC provider
116
+ 5. **Callback received** — Server receives authorization code
117
+ 6. **Token exchange** — Code exchanged for access + refresh tokens
118
+ 7. **Tokens stored** — Saved securely with 0600 permissions
119
+ 8. **JMAP session** — Access token used to authenticate with JMAP
120
+
121
+ ### Token Refresh
122
+
123
+ Tokens are automatically refreshed:
124
+
125
+ 1. **Before each request** — Token expiry is checked
126
+ 2. **60-second buffer** — Refresh happens before expiry
127
+ 3. **Refresh grant** — Refresh token exchanged for new access token
128
+ 4. **New tokens stored** — Updated in `~/.mcp-twake-mail/tokens.json`
129
+ 5. **Transparent to user** — No re-authentication needed
130
+
131
+ ### Re-Authentication
132
+
133
+ If refresh fails (e.g., refresh token expired), you can re-authenticate:
134
+
135
+ ```bash
136
+ npx mcp-twake-mail auth
137
+ ```
138
+
139
+ This triggers a new browser-based authentication flow.
140
+
141
+ ## Token Storage
142
+
143
+ Tokens are stored in `~/.mcp-twake-mail/tokens.json`:
144
+
145
+ ```json
146
+ {
147
+ "accessToken": "eyJhbGciOiJSUzI1NiIs...",
148
+ "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...",
149
+ "expiresAt": 1706623200000,
150
+ "tokenType": "Bearer"
151
+ }
152
+ ```
153
+
154
+ **Security:**
155
+ - File permissions: `0600` (owner read/write only)
156
+ - Directory permissions: `0700`
157
+ - Never commit to version control
158
+
159
+ ## PKCE Flow Details
160
+
161
+ mcp-twake-mail uses PKCE with S256 for security:
162
+
163
+ 1. **Code Verifier** — Random 43-128 character string generated
164
+ 2. **Code Challenge** — SHA-256 hash of verifier, base64url encoded
165
+ 3. **Authorization Request** — Challenge sent to OIDC provider
166
+ 4. **Token Request** — Verifier sent to prove possession
167
+
168
+ This prevents authorization code interception attacks.
169
+
170
+ ## Provider-Specific Setup
171
+
172
+ ### Keycloak
173
+
174
+ 1. Create a new client in your realm
175
+ 2. Set **Client type** to "OpenID Connect"
176
+ 3. Enable **Standard flow** (Authorization Code)
177
+ 4. Set **Valid redirect URIs** to `http://localhost:3000/callback`
178
+ 5. Under **Capability config**, enable **Client authentication: Off** (public client)
179
+ 6. Under **Login settings**, enable **Consent required: Off** (optional)
180
+
181
+ **Issuer URL:** `https://keycloak.example.com/realms/your-realm`
182
+
183
+ ### Auth0
184
+
185
+ 1. Create a new Application (Regular Web Application)
186
+ 2. Set **Allowed Callback URLs** to `http://localhost:3000/callback`
187
+ 3. Under **Advanced Settings > Grant Types**, enable "Authorization Code" and "Refresh Token"
188
+ 4. Under **Advanced Settings > OAuth**, enable PKCE
189
+
190
+ **Issuer URL:** `https://your-tenant.auth0.com`
191
+
192
+ ### Azure AD
193
+
194
+ 1. Register a new application
195
+ 2. Add **Redirect URI**: `http://localhost:3000/callback` (Web platform)
196
+ 3. Under **API permissions**, add `openid`, `profile`, `email`, `offline_access`
197
+ 4. Under **Authentication**, enable "Allow public client flows"
198
+
199
+ **Issuer URL:** `https://login.microsoftonline.com/{tenant-id}/v2.0`
200
+
201
+ ### Okta
202
+
203
+ 1. Create a new App Integration (OIDC - OpenID Connect)
204
+ 2. Choose "Native Application" for PKCE support
205
+ 3. Set **Sign-in redirect URIs** to `http://localhost:3000/callback`
206
+ 4. Under **Assignments**, assign users or groups
207
+
208
+ **Issuer URL:** `https://your-org.okta.com`
209
+
210
+ ## Troubleshooting
211
+
212
+ ### "Invalid redirect_uri"
213
+
214
+ The redirect URI in your configuration must exactly match what's registered in your OIDC provider. Check for:
215
+ - Trailing slashes
216
+ - HTTP vs HTTPS
217
+ - Port numbers
218
+ - Path case sensitivity
219
+
220
+ ### "Token refresh failed"
221
+
222
+ Possible causes:
223
+ 1. Refresh token expired (re-authenticate with `npx mcp-twake-mail auth`)
224
+ 2. `offline_access` scope not granted
225
+ 3. OIDC provider configuration changed
226
+
227
+ ### "PKCE validation failed"
228
+
229
+ Your OIDC provider may not support S256 PKCE. Check provider documentation and ensure:
230
+ - PKCE is enabled for the client
231
+ - S256 code challenge method is supported
232
+
233
+ ### Browser Doesn't Open
234
+
235
+ If running in a headless environment:
236
+ 1. Copy the authorization URL from the console
237
+ 2. Open it in a browser on another machine
238
+ 3. After authentication, copy the callback URL
239
+ 4. The server will detect the callback automatically
240
+
241
+ ### Token File Permissions
242
+
243
+ If you see permission errors:
244
+ ```bash
245
+ chmod 600 ~/.mcp-twake-mail/tokens.json
246
+ chmod 700 ~/.mcp-twake-mail
247
+ ```
248
+
249
+ ## Security Considerations
250
+
251
+ 1. **Never share tokens** — Access and refresh tokens grant full email access
252
+ 2. **Secure token storage** — Use encrypted disk if possible
253
+ 3. **Minimal scopes** — Only request scopes you need
254
+ 4. **Token rotation** — Some providers rotate refresh tokens; mcp-twake-mail handles this
255
+ 5. **Revoke on compromise** — If tokens are exposed, revoke them at your OIDC provider
256
+
257
+ ## References
258
+
259
+ - [RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749) — OAuth 2.0 Authorization Framework
260
+ - [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636) — PKCE for OAuth 2.0
261
+ - [OpenID Connect Core](https://openid.net/specs/openid-connect-core-1_0.html) — OIDC Specification
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-twake-mail",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
4
  "description": "MCP server for Twake.ai — integrate your sovereign JMAP email server with any MCP-compatible AI assistant",
5
5
  "type": "module",
6
6
  "main": "./build/index.js",
@@ -9,6 +9,7 @@
9
9
  },
10
10
  "files": [
11
11
  "build",
12
+ "docs",
12
13
  "README.md",
13
14
  "LICENSE"
14
15
  ],
@@ -52,6 +53,7 @@
52
53
  "@inquirer/prompts": "^8.2.0",
53
54
  "@modelcontextprotocol/sdk": "^1.25.3",
54
55
  "commander": "^14.0.2",
56
+ "marked": "^17.0.1",
55
57
  "oauth-callback": "^2.2.0",
56
58
  "open": "^11.0.0",
57
59
  "openid-client": "^6.8.1",