strapi-oauth-mcp-manager 0.1.2 → 0.1.3

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.
@@ -2,6 +2,7 @@
2
2
  const node_crypto = require("node:crypto");
3
3
  const PLUGIN_ID = "strapi-oauth-mcp-manager";
4
4
  const PLUGIN_UID$3 = `plugin::${PLUGIN_ID}`;
5
+ const MCP_ENDPOINT_PATTERN = /^\/api\/[^/]+\/mcp(\/.*)?$/;
5
6
  function extractBearerToken(authHeader) {
6
7
  if (!authHeader?.startsWith("Bearer ")) {
7
8
  return null;
@@ -45,32 +46,15 @@ async function validateOAuthToken(token, strapi) {
45
46
  return { valid: false, error: "Token validation failed" };
46
47
  }
47
48
  }
49
+ function isMcpEndpoint(path) {
50
+ return MCP_ENDPOINT_PATTERN.test(path);
51
+ }
48
52
  const mcpOauthMiddleware = (config2, { strapi }) => {
49
- let endpointCache = [];
50
- let lastCacheUpdate = 0;
51
- const CACHE_TTL = 6e4;
52
- async function refreshEndpointCache() {
53
- const now = Date.now();
54
- if (now - lastCacheUpdate > CACHE_TTL) {
55
- try {
56
- const endpoints = await strapi.documents(`${PLUGIN_UID$3}.mcp-endpoint`).findMany({
57
- filters: { active: true }
58
- });
59
- endpointCache = endpoints.map((e) => e.path);
60
- lastCacheUpdate = now;
61
- } catch (error) {
62
- strapi.log.error(`[${PLUGIN_ID}] Error refreshing endpoint cache`, { error });
63
- }
64
- }
65
- }
66
- function isProtectedPath(path) {
67
- return endpointCache.some((endpoint) => path.includes(endpoint));
68
- }
69
53
  return async (ctx, next) => {
70
- await refreshEndpointCache();
71
- if (!isProtectedPath(ctx.path)) {
54
+ if (!isMcpEndpoint(ctx.path)) {
72
55
  return next();
73
56
  }
57
+ strapi.log.debug(`[${PLUGIN_ID}] Protecting MCP endpoint: ${ctx.path}`);
74
58
  const authHeader = ctx.request.headers.authorization;
75
59
  const token = extractBearerToken(authHeader);
76
60
  if (!token) {
@@ -1,6 +1,7 @@
1
1
  import { randomBytes } from "node:crypto";
2
2
  const PLUGIN_ID = "strapi-oauth-mcp-manager";
3
3
  const PLUGIN_UID$3 = `plugin::${PLUGIN_ID}`;
4
+ const MCP_ENDPOINT_PATTERN = /^\/api\/[^/]+\/mcp(\/.*)?$/;
4
5
  function extractBearerToken(authHeader) {
5
6
  if (!authHeader?.startsWith("Bearer ")) {
6
7
  return null;
@@ -44,32 +45,15 @@ async function validateOAuthToken(token, strapi) {
44
45
  return { valid: false, error: "Token validation failed" };
45
46
  }
46
47
  }
48
+ function isMcpEndpoint(path) {
49
+ return MCP_ENDPOINT_PATTERN.test(path);
50
+ }
47
51
  const mcpOauthMiddleware = (config2, { strapi }) => {
48
- let endpointCache = [];
49
- let lastCacheUpdate = 0;
50
- const CACHE_TTL = 6e4;
51
- async function refreshEndpointCache() {
52
- const now = Date.now();
53
- if (now - lastCacheUpdate > CACHE_TTL) {
54
- try {
55
- const endpoints = await strapi.documents(`${PLUGIN_UID$3}.mcp-endpoint`).findMany({
56
- filters: { active: true }
57
- });
58
- endpointCache = endpoints.map((e) => e.path);
59
- lastCacheUpdate = now;
60
- } catch (error) {
61
- strapi.log.error(`[${PLUGIN_ID}] Error refreshing endpoint cache`, { error });
62
- }
63
- }
64
- }
65
- function isProtectedPath(path) {
66
- return endpointCache.some((endpoint) => path.includes(endpoint));
67
- }
68
52
  return async (ctx, next) => {
69
- await refreshEndpointCache();
70
- if (!isProtectedPath(ctx.path)) {
53
+ if (!isMcpEndpoint(ctx.path)) {
71
54
  return next();
72
55
  }
56
+ strapi.log.debug(`[${PLUGIN_ID}] Protecting MCP endpoint: ${ctx.path}`);
73
57
  const authHeader = ctx.request.headers.authorization;
74
58
  const token = extractBearerToken(authHeader);
75
59
  if (!token) {
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * MCP OAuth Authentication Middleware
3
3
  *
4
- * This middleware provides OAuth 2.0 authentication for all registered MCP endpoints.
4
+ * This middleware provides OAuth 2.0 authentication for all MCP endpoints.
5
+ * Uses convention-based protection: any route matching /api/{plugin}/mcp is protected.
6
+ *
5
7
  * It supports dual authentication:
6
8
  * - OAuth 2.0 tokens (for ChatGPT and other OAuth clients)
7
9
  * - Direct Strapi API tokens (for Claude Desktop and scripts)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strapi-oauth-mcp-manager",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Centralized OAuth 2.0 authentication manager for Strapi MCP plugins. Supports ChatGPT, Claude, and custom OAuth clients.",
5
5
  "keywords": [
6
6
  "strapi",