strapi-oauth-mcp-manager 0.1.0 → 0.1.2
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.
- package/README.md +222 -46
- package/dist/server/index.js +12 -1
- package/dist/server/index.mjs +12 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,11 +31,144 @@ export default () => ({
|
|
|
31
31
|
'yt-transcript-strapi-plugin': {
|
|
32
32
|
enabled: true,
|
|
33
33
|
},
|
|
34
|
+
'strapi-content-mcp': {
|
|
35
|
+
enabled: true,
|
|
36
|
+
},
|
|
34
37
|
});
|
|
35
38
|
```
|
|
36
39
|
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Quick Start: ChatGPT Setup
|
|
43
|
+
|
|
44
|
+
### Step 1: Create a Strapi API Token
|
|
45
|
+
|
|
46
|
+
1. Go to **Strapi Admin** → **Settings** → **API Tokens**
|
|
47
|
+
2. Click **Create new API Token**
|
|
48
|
+
3. Configure:
|
|
49
|
+
- **Name**: `ChatGPT MCP Access`
|
|
50
|
+
- **Token type**: `Full access` (or custom with specific permissions)
|
|
51
|
+
- **Token duration**: `Unlimited` (recommended) or set expiry
|
|
52
|
+
4. Click **Save** and **copy the token** (you won't see it again)
|
|
53
|
+
|
|
54
|
+
### Step 2: Create an OAuth Client in Strapi
|
|
55
|
+
|
|
56
|
+
1. Go to **Strapi Admin** → **Content Manager** → **MCP OAuth Client**
|
|
57
|
+
2. Click **Create new entry**
|
|
58
|
+
3. Fill in the fields:
|
|
59
|
+
|
|
60
|
+
| Field | Value |
|
|
61
|
+
|-------|-------|
|
|
62
|
+
| **name** | `ChatGPT` |
|
|
63
|
+
| **clientId** | `chatgpt` |
|
|
64
|
+
| **clientSecret** | Choose a secure secret (e.g., `my-super-secret-key-123`) |
|
|
65
|
+
| **redirectUris** | `https://chatgpt.com/connector_platform_oauth_redirect` |
|
|
66
|
+
| **strapiApiToken** | Paste the API token from Step 1 |
|
|
67
|
+
| **active** | `true` |
|
|
68
|
+
|
|
69
|
+
4. Click **Save**
|
|
70
|
+
|
|
71
|
+
### Step 3: Configure ChatGPT
|
|
72
|
+
|
|
73
|
+
1. Go to [ChatGPT](https://chatgpt.com)
|
|
74
|
+
2. Click your profile → **Settings** → **Connected Apps** → **Add App**
|
|
75
|
+
3. Fill in the form:
|
|
76
|
+
|
|
77
|
+
| Field | Value |
|
|
78
|
+
|-------|-------|
|
|
79
|
+
| **Name** | `Your App Name` (e.g., "YT Transcripts") |
|
|
80
|
+
| **Description** | What the app does |
|
|
81
|
+
| **MCP Server URL** | `https://your-strapi-domain.com/api/yt-transcript-strapi-plugin/mcp` |
|
|
82
|
+
| **Authentication** | `OAuth` |
|
|
83
|
+
| **Client ID** | `chatgpt` (from Step 2) |
|
|
84
|
+
| **Client Secret** | Your secret from Step 2 |
|
|
85
|
+
|
|
86
|
+
4. Click **Save**
|
|
87
|
+
|
|
88
|
+
### Step 4: Authorize
|
|
89
|
+
|
|
90
|
+
When you first use the MCP tools in ChatGPT, it will redirect you to Strapi to authorize. Click **Authorize** to complete the OAuth flow.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Quick Start: Claude Desktop Setup
|
|
95
|
+
|
|
96
|
+
Claude Desktop uses direct Strapi API tokens (no OAuth flow needed).
|
|
97
|
+
|
|
98
|
+
### Step 1: Create a Strapi API Token
|
|
99
|
+
|
|
100
|
+
Same as ChatGPT Step 1 above.
|
|
101
|
+
|
|
102
|
+
### Step 2: Configure Claude Desktop
|
|
103
|
+
|
|
104
|
+
Edit your Claude Desktop config file:
|
|
105
|
+
|
|
106
|
+
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
107
|
+
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"mcpServers": {
|
|
112
|
+
"yt-transcript": {
|
|
113
|
+
"command": "npx",
|
|
114
|
+
"args": [
|
|
115
|
+
"mcp-remote",
|
|
116
|
+
"https://your-strapi-domain.com/api/yt-transcript-strapi-plugin/mcp",
|
|
117
|
+
"--header",
|
|
118
|
+
"Authorization: Bearer YOUR_STRAPI_API_TOKEN"
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
"strapi-content": {
|
|
122
|
+
"command": "npx",
|
|
123
|
+
"args": [
|
|
124
|
+
"mcp-remote",
|
|
125
|
+
"https://your-strapi-domain.com/api/strapi-content-mcp/mcp",
|
|
126
|
+
"--header",
|
|
127
|
+
"Authorization: Bearer YOUR_STRAPI_API_TOKEN"
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Replace:
|
|
135
|
+
- `your-strapi-domain.com` with your actual Strapi URL
|
|
136
|
+
- `YOUR_STRAPI_API_TOKEN` with the token from Step 1
|
|
137
|
+
|
|
138
|
+
### Step 3: Restart Claude Desktop
|
|
139
|
+
|
|
140
|
+
Quit and reopen Claude Desktop to load the new configuration.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
37
144
|
## How It Works
|
|
38
145
|
|
|
146
|
+
### Architecture
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
150
|
+
│ Strapi Application │
|
|
151
|
+
│ │
|
|
152
|
+
│ ┌─────────────────────────────────────────────────────┐ │
|
|
153
|
+
│ │ strapi-oauth-mcp-manager │ │
|
|
154
|
+
│ │ ┌───────────────┐ ┌───────────────────────────┐ │ │
|
|
155
|
+
│ │ │ OAuth │ │ Global Auth Middleware │ │ │
|
|
156
|
+
│ │ │ Endpoints │ │ (protects all registered │ │ │
|
|
157
|
+
│ │ │ /authorize │ │ MCP endpoints) │ │ │
|
|
158
|
+
│ │ │ /token │ └───────────────────────────┘ │ │
|
|
159
|
+
│ │ └───────────────┘ │ │
|
|
160
|
+
│ └─────────────────────────────────────────────────────┘ │
|
|
161
|
+
│ │ │
|
|
162
|
+
│ ┌──────────────────┼──────────────────┐ │
|
|
163
|
+
│ ▼ ▼ ▼ │
|
|
164
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
165
|
+
│ │ MCP Plugin │ │ MCP Plugin │ │ MCP Plugin │ │
|
|
166
|
+
│ │ A │ │ B │ │ C │ │
|
|
167
|
+
│ │ (registers) │ │ (registers) │ │ (registers) │ │
|
|
168
|
+
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
169
|
+
└─────────────────────────────────────────────────────────────┘
|
|
170
|
+
```
|
|
171
|
+
|
|
39
172
|
### For MCP Plugin Developers
|
|
40
173
|
|
|
41
174
|
MCP plugins register with the OAuth manager to gain authentication support:
|
|
@@ -54,17 +187,40 @@ if (oauthPlugin) {
|
|
|
54
187
|
}
|
|
55
188
|
```
|
|
56
189
|
|
|
57
|
-
###
|
|
190
|
+
### Authentication Flow
|
|
58
191
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
192
|
+
```
|
|
193
|
+
ChatGPT/OAuth Client Strapi
|
|
194
|
+
│ │
|
|
195
|
+
│ 1. Request MCP endpoint │
|
|
196
|
+
│ ─────────────────────────────────>│
|
|
197
|
+
│ │
|
|
198
|
+
│ 2. 401 + WWW-Authenticate header │
|
|
199
|
+
│ <─────────────────────────────────│
|
|
200
|
+
│ │
|
|
201
|
+
│ 3. Discover OAuth via .well-known │
|
|
202
|
+
│ ─────────────────────────────────>│
|
|
203
|
+
│ │
|
|
204
|
+
│ 4. Redirect to /authorize │
|
|
205
|
+
│ ─────────────────────────────────>│
|
|
206
|
+
│ │
|
|
207
|
+
│ 5. User authorizes, get code │
|
|
208
|
+
│ <─────────────────────────────────│
|
|
209
|
+
│ │
|
|
210
|
+
│ 6. Exchange code for token │
|
|
211
|
+
│ ─────────────────────────────────>│
|
|
212
|
+
│ │
|
|
213
|
+
│ 7. Access token returned │
|
|
214
|
+
│ <─────────────────────────────────│
|
|
215
|
+
│ │
|
|
216
|
+
│ 8. MCP requests with Bearer token │
|
|
217
|
+
│ ─────────────────────────────────>│
|
|
218
|
+
│ │
|
|
219
|
+
│ 9. MCP response │
|
|
220
|
+
│ <─────────────────────────────────│
|
|
221
|
+
```
|
|
63
222
|
|
|
64
|
-
|
|
65
|
-
- MCP Server URL: `https://your-domain/api/your-mcp-plugin/mcp`
|
|
66
|
-
- OAuth Client ID: From Strapi admin
|
|
67
|
-
- OAuth Client Secret: From Strapi admin
|
|
223
|
+
---
|
|
68
224
|
|
|
69
225
|
## OAuth Endpoints
|
|
70
226
|
|
|
@@ -75,6 +231,8 @@ if (oauthPlugin) {
|
|
|
75
231
|
| Discovery (RFC 8414) | `/api/strapi-oauth-mcp-manager/.well-known/oauth-authorization-server` |
|
|
76
232
|
| Protected Resource (RFC 9728) | `/api/strapi-oauth-mcp-manager/.well-known/oauth-protected-resource` |
|
|
77
233
|
|
|
234
|
+
---
|
|
235
|
+
|
|
78
236
|
## Content Types
|
|
79
237
|
|
|
80
238
|
The plugin creates these content types:
|
|
@@ -86,52 +244,70 @@ The plugin creates these content types:
|
|
|
86
244
|
| `mcp-oauth-token` | Access and refresh tokens |
|
|
87
245
|
| `mcp-endpoint` | Registered MCP endpoints |
|
|
88
246
|
|
|
89
|
-
|
|
247
|
+
---
|
|
90
248
|
|
|
91
|
-
|
|
249
|
+
## OAuth Client Configuration
|
|
92
250
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
251
|
+
### Required Fields
|
|
252
|
+
|
|
253
|
+
| Field | Type | Description |
|
|
254
|
+
|-------|------|-------------|
|
|
255
|
+
| `name` | string | Display name for the client |
|
|
256
|
+
| `clientId` | string | Unique identifier (e.g., `chatgpt`) |
|
|
257
|
+
| `clientSecret` | string | Secret for token exchange |
|
|
258
|
+
| `redirectUris` | string[] | Allowed redirect URIs after authorization |
|
|
259
|
+
| `strapiApiToken` | string | Strapi API token to use for authenticated requests |
|
|
260
|
+
| `active` | boolean | Whether the client is active |
|
|
261
|
+
|
|
262
|
+
### Redirect URIs
|
|
263
|
+
|
|
264
|
+
Common redirect URIs:
|
|
265
|
+
|
|
266
|
+
| Client | Redirect URI |
|
|
267
|
+
|--------|--------------|
|
|
268
|
+
| ChatGPT | `https://chatgpt.com/connector_platform_oauth_redirect` |
|
|
269
|
+
| Custom OAuth | Your app's callback URL |
|
|
270
|
+
|
|
271
|
+
Wildcard patterns are supported (e.g., `https://*.example.com/callback`).
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Troubleshooting
|
|
103
276
|
|
|
104
|
-
|
|
277
|
+
### "Invalid redirect_uri" Error
|
|
105
278
|
|
|
279
|
+
Make sure the redirect URI in your OAuth client exactly matches what the client sends. For ChatGPT, use:
|
|
106
280
|
```
|
|
107
|
-
|
|
108
|
-
2. Returns 401 with WWW-Authenticate header
|
|
109
|
-
3. Client discovers OAuth endpoints via .well-known
|
|
110
|
-
4. Client completes OAuth authorization code flow
|
|
111
|
-
5. Client receives access token
|
|
112
|
-
6. Client makes MCP requests with Bearer token
|
|
113
|
-
7. OAuth manager validates and forwards to MCP plugin
|
|
281
|
+
https://chatgpt.com/connector_platform_oauth_redirect
|
|
114
282
|
```
|
|
115
283
|
|
|
116
|
-
|
|
284
|
+
### "Session expired" Error
|
|
117
285
|
|
|
118
|
-
|
|
286
|
+
Sessions expire after 4 hours. The client should automatically reinitialize the connection.
|
|
119
287
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
288
|
+
### Claude Desktop Not Connecting
|
|
289
|
+
|
|
290
|
+
1. Check that `mcp-remote` is installed: `npx mcp-remote --version`
|
|
291
|
+
2. Verify your API token is valid in Strapi Admin
|
|
292
|
+
3. Check the Strapi logs for authentication errors
|
|
293
|
+
4. Ensure your Strapi instance is accessible from your machine
|
|
294
|
+
|
|
295
|
+
### OAuth Flow Not Starting
|
|
296
|
+
|
|
297
|
+
1. Verify the OAuth client is set to `active: true`
|
|
298
|
+
2. Check that the `strapiApiToken` in the OAuth client is valid
|
|
299
|
+
3. Look at Strapi logs for detailed error messages
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Compatible MCP Plugins
|
|
304
|
+
|
|
305
|
+
These plugins support `strapi-oauth-mcp-manager`:
|
|
306
|
+
|
|
307
|
+
- [yt-transcript-strapi-plugin](https://www.npmjs.com/package/yt-transcript-strapi-plugin) - YouTube transcript tools
|
|
308
|
+
- [strapi-content-mcp](https://www.npmjs.com/package/strapi-content-mcp) - Strapi content management tools
|
|
309
|
+
|
|
310
|
+
---
|
|
135
311
|
|
|
136
312
|
## Requirements
|
|
137
313
|
|
package/dist/server/index.js
CHANGED
|
@@ -417,7 +417,18 @@ const oauthController = ({ strapi }) => ({
|
|
|
417
417
|
ctx.body = { error: "invalid_client", error_description: "Unknown client_id" };
|
|
418
418
|
return;
|
|
419
419
|
}
|
|
420
|
-
|
|
420
|
+
let allowedRedirects = [];
|
|
421
|
+
if (Array.isArray(client.redirectUris)) {
|
|
422
|
+
allowedRedirects = client.redirectUris;
|
|
423
|
+
} else if (typeof client.redirectUris === "string") {
|
|
424
|
+
try {
|
|
425
|
+
allowedRedirects = JSON.parse(client.redirectUris);
|
|
426
|
+
} catch {
|
|
427
|
+
allowedRedirects = [client.redirectUris];
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
strapi.log.debug(`[${PLUGIN_ID}] Checking redirect_uri: ${redirect_uri}`);
|
|
431
|
+
strapi.log.debug(`[${PLUGIN_ID}] Allowed redirects (${typeof client.redirectUris}): ${JSON.stringify(allowedRedirects)}`);
|
|
421
432
|
if (!matchRedirectUri(redirect_uri, allowedRedirects)) {
|
|
422
433
|
strapi.log.warn(`[${PLUGIN_ID}] Invalid redirect_uri: ${redirect_uri}`);
|
|
423
434
|
strapi.log.warn(`[${PLUGIN_ID}] Allowed patterns: ${allowedRedirects.join(", ")}`);
|
package/dist/server/index.mjs
CHANGED
|
@@ -416,7 +416,18 @@ const oauthController = ({ strapi }) => ({
|
|
|
416
416
|
ctx.body = { error: "invalid_client", error_description: "Unknown client_id" };
|
|
417
417
|
return;
|
|
418
418
|
}
|
|
419
|
-
|
|
419
|
+
let allowedRedirects = [];
|
|
420
|
+
if (Array.isArray(client.redirectUris)) {
|
|
421
|
+
allowedRedirects = client.redirectUris;
|
|
422
|
+
} else if (typeof client.redirectUris === "string") {
|
|
423
|
+
try {
|
|
424
|
+
allowedRedirects = JSON.parse(client.redirectUris);
|
|
425
|
+
} catch {
|
|
426
|
+
allowedRedirects = [client.redirectUris];
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
strapi.log.debug(`[${PLUGIN_ID}] Checking redirect_uri: ${redirect_uri}`);
|
|
430
|
+
strapi.log.debug(`[${PLUGIN_ID}] Allowed redirects (${typeof client.redirectUris}): ${JSON.stringify(allowedRedirects)}`);
|
|
420
431
|
if (!matchRedirectUri(redirect_uri, allowedRedirects)) {
|
|
421
432
|
strapi.log.warn(`[${PLUGIN_ID}] Invalid redirect_uri: ${redirect_uri}`);
|
|
422
433
|
strapi.log.warn(`[${PLUGIN_ID}] Allowed patterns: ${allowedRedirects.join(", ")}`);
|
package/package.json
CHANGED