@scupit/mcp-ecosystem 0.1.0 → 0.2.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 (123) hide show
  1. package/README.md +273 -0
  2. package/dist/auth0/management-client.d.ts +6 -1
  3. package/dist/auth0/management-client.d.ts.map +1 -1
  4. package/dist/auth0/management-client.js +56 -20
  5. package/dist/auth0/management-client.js.map +1 -1
  6. package/dist/cli.js +9 -2
  7. package/dist/cli.js.map +1 -1
  8. package/dist/commands/add-scope.d.ts.map +1 -1
  9. package/dist/commands/add-scope.js +5 -1
  10. package/dist/commands/add-scope.js.map +1 -1
  11. package/dist/commands/env-root-validation.d.ts +3 -0
  12. package/dist/commands/env-root-validation.d.ts.map +1 -0
  13. package/dist/commands/env-root-validation.js +27 -0
  14. package/dist/commands/env-root-validation.js.map +1 -0
  15. package/dist/commands/generate-artifacts.d.ts +1 -1
  16. package/dist/commands/generate-artifacts.d.ts.map +1 -1
  17. package/dist/commands/generate-artifacts.js +49 -75
  18. package/dist/commands/generate-artifacts.js.map +1 -1
  19. package/dist/commands/grant-client.d.ts.map +1 -1
  20. package/dist/commands/grant-client.js +17 -2
  21. package/dist/commands/grant-client.js.map +1 -1
  22. package/dist/commands/reconcile-all.d.ts.map +1 -1
  23. package/dist/commands/reconcile-all.js +9 -0
  24. package/dist/commands/reconcile-all.js.map +1 -1
  25. package/dist/commands/reconcile-client.d.ts +3 -1
  26. package/dist/commands/reconcile-client.d.ts.map +1 -1
  27. package/dist/commands/reconcile-client.js +109 -17
  28. package/dist/commands/reconcile-client.js.map +1 -1
  29. package/dist/commands/reconcile-server.d.ts.map +1 -1
  30. package/dist/commands/reconcile-server.js +49 -20
  31. package/dist/commands/reconcile-server.js.map +1 -1
  32. package/dist/commands/validated-client-cache.d.ts +7 -0
  33. package/dist/commands/validated-client-cache.d.ts.map +1 -0
  34. package/dist/commands/validated-client-cache.js +50 -0
  35. package/dist/commands/validated-client-cache.js.map +1 -0
  36. package/dist/commands/verify-tenant.d.ts.map +1 -1
  37. package/dist/commands/verify-tenant.js +2 -5
  38. package/dist/commands/verify-tenant.js.map +1 -1
  39. package/dist/config/defaults.d.ts +19 -0
  40. package/dist/config/defaults.d.ts.map +1 -0
  41. package/dist/config/defaults.js +49 -0
  42. package/dist/config/defaults.js.map +1 -0
  43. package/dist/config/env-policy.d.ts +7 -0
  44. package/dist/config/env-policy.d.ts.map +1 -0
  45. package/dist/config/env-policy.js +30 -0
  46. package/dist/config/env-policy.js.map +1 -0
  47. package/dist/config/index.d.ts +3 -1
  48. package/dist/config/index.d.ts.map +1 -1
  49. package/dist/config/index.js +3 -1
  50. package/dist/config/index.js.map +1 -1
  51. package/dist/config/loader.d.ts +15 -0
  52. package/dist/config/loader.d.ts.map +1 -1
  53. package/dist/config/loader.js +95 -4
  54. package/dist/config/loader.js.map +1 -1
  55. package/dist/index.d.ts +1 -1
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +2 -2
  58. package/dist/index.js.map +1 -1
  59. package/dist/mcp-server/create-server.d.ts +17 -24
  60. package/dist/mcp-server/create-server.d.ts.map +1 -1
  61. package/dist/mcp-server/create-server.js +157 -58
  62. package/dist/mcp-server/create-server.js.map +1 -1
  63. package/dist/mcp-server/http-app.d.ts +24 -0
  64. package/dist/mcp-server/http-app.d.ts.map +1 -0
  65. package/dist/mcp-server/http-app.js +66 -0
  66. package/dist/mcp-server/http-app.js.map +1 -0
  67. package/dist/mcp-server/index.d.ts +4 -2
  68. package/dist/mcp-server/index.d.ts.map +1 -1
  69. package/dist/mcp-server/index.js +1 -1
  70. package/dist/mcp-server/index.js.map +1 -1
  71. package/dist/mcp-server/mcp-configuration.d.ts +35 -0
  72. package/dist/mcp-server/mcp-configuration.d.ts.map +1 -0
  73. package/dist/mcp-server/mcp-configuration.js +2 -0
  74. package/dist/mcp-server/mcp-configuration.js.map +1 -0
  75. package/dist/mcp-server/stdio-mcp.d.ts +17 -0
  76. package/dist/mcp-server/stdio-mcp.d.ts.map +1 -0
  77. package/dist/mcp-server/stdio-mcp.js +28 -0
  78. package/dist/mcp-server/stdio-mcp.js.map +1 -0
  79. package/dist/mcp-server/streamable-http-stateful-mcp.d.ts +22 -0
  80. package/dist/mcp-server/streamable-http-stateful-mcp.d.ts.map +1 -0
  81. package/dist/mcp-server/streamable-http-stateful-mcp.js +105 -0
  82. package/dist/mcp-server/streamable-http-stateful-mcp.js.map +1 -0
  83. package/dist/mcp-server/streamable-http-stateless-mcp.d.ts +20 -0
  84. package/dist/mcp-server/streamable-http-stateless-mcp.d.ts.map +1 -0
  85. package/dist/mcp-server/streamable-http-stateless-mcp.js +58 -0
  86. package/dist/mcp-server/streamable-http-stateless-mcp.js.map +1 -0
  87. package/dist/mcp-server/transport-config.d.ts +80 -0
  88. package/dist/mcp-server/transport-config.d.ts.map +1 -0
  89. package/dist/mcp-server/transport-config.js +2 -0
  90. package/dist/mcp-server/transport-config.js.map +1 -0
  91. package/dist/types/auth0-responses.d.ts +11 -0
  92. package/dist/types/auth0-responses.d.ts.map +1 -1
  93. package/dist/types/client-config.d.ts +6 -24
  94. package/dist/types/client-config.d.ts.map +1 -1
  95. package/dist/types/client-config.js +4 -7
  96. package/dist/types/client-config.js.map +1 -1
  97. package/dist/types/ecosystem-config.d.ts +211 -70
  98. package/dist/types/ecosystem-config.d.ts.map +1 -1
  99. package/dist/types/ecosystem-config.js +33 -21
  100. package/dist/types/ecosystem-config.js.map +1 -1
  101. package/dist/types/index.d.ts +3 -3
  102. package/dist/types/index.d.ts.map +1 -1
  103. package/dist/types/index.js +1 -1
  104. package/dist/types/index.js.map +1 -1
  105. package/dist/types/server-config.js +1 -1
  106. package/dist/types/server-config.js.map +1 -1
  107. package/dist/utils/context.d.ts +6 -5
  108. package/dist/utils/context.d.ts.map +1 -1
  109. package/dist/utils/context.js +43 -7
  110. package/dist/utils/context.js.map +1 -1
  111. package/dist/utils/env-manager.d.ts +113 -0
  112. package/dist/utils/env-manager.d.ts.map +1 -0
  113. package/dist/utils/env-manager.js +509 -0
  114. package/dist/utils/env-manager.js.map +1 -0
  115. package/dist/utils/env-writer.d.ts +23 -0
  116. package/dist/utils/env-writer.d.ts.map +1 -0
  117. package/dist/utils/env-writer.js +131 -0
  118. package/dist/utils/env-writer.js.map +1 -0
  119. package/dist/utils/index.d.ts +1 -0
  120. package/dist/utils/index.d.ts.map +1 -1
  121. package/dist/utils/index.js +1 -0
  122. package/dist/utils/index.js.map +1 -1
  123. package/package.json +8 -6
@@ -0,0 +1,27 @@
1
+ import { join } from "node:path";
2
+ import { isManagedClientCredentialEnvKey } from "../config/index.js";
3
+ export function assertNoManagedClientCredentialsOutsideManagedBlock(ctx) {
4
+ const invalidAssignments = ctx.envManager.getOuterAssignments(isManagedClientCredentialEnvKey);
5
+ if (invalidAssignments.length === 0) {
6
+ return;
7
+ }
8
+ const envPath = join(ctx.rootDir, ".env");
9
+ const entries = invalidAssignments.map((assignment) => ` ${maskSecretAssignment(assignment.rawLine)}`);
10
+ throw new Error(`Invalid tool-managed client credentials in root .env at ${envPath}\n\n` +
11
+ ` These variables are managed by mcp-ecosystem and must appear only inside\n` +
12
+ ` the auto-generated block marked by:\n` +
13
+ ` # <automatically-generated>\n` +
14
+ ` # </automatically-generated>\n\n` +
15
+ ` Remove these user-authored assignments from outside the managed block:\n` +
16
+ `${entries.join("\n")}\n\n` +
17
+ ` Then re-run reconcile-client or reconcile-all so the CLI can regenerate\n` +
18
+ ` the managed entries safely.`);
19
+ }
20
+ function maskSecretAssignment(line) {
21
+ const eqIdx = line.indexOf("=");
22
+ if (eqIdx === -1)
23
+ return line;
24
+ const key = line.slice(0, eqIdx).trim();
25
+ return key.includes("_SECRET") ? `${key}=********` : line;
26
+ }
27
+ //# sourceMappingURL=env-root-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-root-validation.js","sourceRoot":"","sources":["../../src/commands/env-root-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;AAGrE,MAAM,UAAU,mDAAmD,CACjE,GAAmD;IAEnD,MAAM,kBAAkB,GAAG,GAAG,CAAC,UAAU,CAAC,mBAAmB,CAC3D,+BAA+B,CAChC,CAAC;IAEF,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,CACpC,CAAC,UAAU,EAAE,EAAE,CAAC,OAAO,oBAAoB,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAClE,CAAC;IAEF,MAAM,IAAI,KAAK,CACb,2DAA2D,OAAO,MAAM;QACtE,8EAA8E;QAC9E,yCAAyC;QACzC,mCAAmC;QACnC,sCAAsC;QACtC,4EAA4E;QAC5E,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;QAC3B,6EAA6E;QAC7E,+BAA+B,CAClC,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAY;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,KAAK,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,OAAO,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5D,CAAC"}
@@ -3,7 +3,7 @@ export interface GenerateArtifactsResult {
3
3
  filesWritten: string[];
4
4
  }
5
5
  /**
6
- * Generates or refreshes the .env.example and per-server runtime config files.
6
+ * Generates or refreshes the .env.example file.
7
7
  * Never writes live secrets.
8
8
  */
9
9
  export declare function generateArtifacts(ctx: CommandContext): Promise<GenerateArtifactsResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"generate-artifacts.d.ts","sourceRoot":"","sources":["../../src/commands/generate-artifacts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAUxD,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,uBAAuB,CAAC,CAiGlC"}
1
+ {"version":3,"file":"generate-artifacts.d.ts","sourceRoot":"","sources":["../../src/commands/generate-artifacts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQxD,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,uBAAuB,CAAC,CA4ClC"}
@@ -1,91 +1,65 @@
1
- import { writeFile, mkdir } from "node:fs/promises";
2
1
  import { join } from "node:path";
3
- import { logger } from "../utils/index.js";
4
- import { deriveCanonicalResourceUri, deriveHostname, deriveMcpEndpoint, deriveProtectedResourceMetadataUrl, resolveScopes, } from "../config/index.js";
2
+ import { logger, ManagedEnvFile } from "../utils/index.js";
3
+ import { ECOSYSTEM_ENV, AUTH0_ENV, getEnvPlaceholder, } from "../config/index.js";
5
4
  /**
6
- * Generates or refreshes the .env.example and per-server runtime config files.
5
+ * Generates or refreshes the .env.example file.
7
6
  * Never writes live secrets.
8
7
  */
9
8
  export async function generateArtifacts(ctx) {
10
- const { config, rootDir, dryRun } = ctx;
11
- const ecosystem = config.ecosystem;
9
+ const { rootDir, dryRun } = ctx;
12
10
  const written = [];
13
- // ── .env.example ──
14
11
  const envLines = [
15
- "# Auth0 Management API credentials (required)",
16
- `${ecosystem.auth0.management_client_id_env}=__REQUIRED__`,
17
- `${ecosystem.auth0.management_client_secret_env}=__REQUIRED__`,
18
- `AUTH0_TENANT_DOMAIN=${ecosystem.auth0.tenant_domain}`,
12
+ "# Ecosystem base domain (required)",
13
+ `${ECOSYSTEM_ENV.baseDomain}=${getEnvPlaceholder(ECOSYSTEM_ENV.baseDomain) ?? "example.com"}`,
14
+ "",
15
+ "# Auth0 tenant and Management API credentials (required for provisioning)",
16
+ `${AUTH0_ENV.tenantDomain}=${getEnvPlaceholder(AUTH0_ENV.tenantDomain) ?? "your-tenant.auth0.com"}`,
17
+ `${AUTH0_ENV.clientId}=${getEnvPlaceholder(AUTH0_ENV.clientId) ?? "__REQUIRED__"}`,
18
+ `${AUTH0_ENV.clientSecret}=${getEnvPlaceholder(AUTH0_ENV.clientSecret) ?? "__REQUIRED__"}`,
19
+ "",
20
+ "# Client IDs and secrets are automatically written to .env by",
21
+ "# reconcile-client and reconcile-all. Do not set them manually.",
19
22
  "",
20
23
  ];
21
- for (const [key, client] of config.clientConfigs) {
22
- const envPrefix = `AUTH0_${key.toUpperCase().replace(/-/g, "_")}`;
23
- envLines.push(`# Client: ${client.display_name}`);
24
- envLines.push(`${envPrefix}_CLIENT_ID=__GENERATED_OR_EXISTING__`);
25
- const isPublic = client.profile === "native_interactive" ||
26
- client.profile === "spa_interactive";
27
- if (client.credentials?.client_secret_env) {
28
- envLines.push(`${client.credentials.client_secret_env}=__FILL_SECRET__`);
29
- }
30
- else if (!isPublic) {
31
- envLines.push(`${envPrefix}_CLIENT_SECRET=__GENERATED__`);
32
- }
33
- else {
34
- envLines.push(`# ${envPrefix}_CLIENT_SECRET=__ONLY_IF_CONFIDENTIAL__`);
35
- }
36
- envLines.push("");
37
- }
38
- for (const [slug, server] of config.serverConfigs) {
39
- const identifier = deriveCanonicalResourceUri(ecosystem, slug);
40
- const envPrefix = `AUTH0_${slug.toUpperCase().replace(/-/g, "_")}_MCP`;
41
- envLines.push(`# Server: ${server.name}`);
42
- envLines.push(`${envPrefix}_AUDIENCE=${identifier}`);
43
- envLines.push("");
44
- }
45
24
  const envExamplePath = join(rootDir, ".env.example");
46
- if (!dryRun) {
47
- await writeFile(envExamplePath, envLines.join("\n"), "utf-8");
48
- written.push(envExamplePath);
49
- logger.success(`Generated: ${envExamplePath}`);
25
+ const envExample = await ManagedEnvFile.load(envExamplePath, {
26
+ displayName: ".env.example",
27
+ blockHeaderLines: [
28
+ "# Managed by @scupit/mcp-ecosystem -- placeholders only.",
29
+ "# Add your own notes or extra example variables outside this block.",
30
+ ],
31
+ });
32
+ if (!envExample.hasManagedBlock && isLegacyGeneratedEnvExample(envExample.getOuterContent())) {
33
+ envExample.replaceOuterContent("");
50
34
  }
51
- else {
52
- logger.info(`[DRY RUN] Would generate: ${envExamplePath}`);
35
+ envExample.setManagedLines(envLines);
36
+ const changed = await envExample.flush(dryRun, {
37
+ dryRunLabel: "[DRY RUN] Would update .env.example managed block:",
38
+ successMessage: `Generated: ${envExamplePath}`,
39
+ });
40
+ if (changed && !dryRun) {
41
+ written.push(envExamplePath);
53
42
  }
54
- // ── Per-server runtime config ──
55
- for (const [slug, server] of config.serverConfigs) {
56
- const hostname = deriveHostname(ecosystem, slug);
57
- const resourceUri = deriveCanonicalResourceUri(ecosystem, slug);
58
- const mcpEndpoint = deriveMcpEndpoint(ecosystem, slug);
59
- const metadataUrl = deriveProtectedResourceMetadataUrl(ecosystem, slug);
60
- const scopes = resolveScopes(ecosystem, server);
61
- const runtimeConfig = {
62
- server: {
63
- name: server.name,
64
- slug: server.slug,
65
- hostname,
66
- resource_uri: resourceUri,
67
- mcp_endpoint: mcpEndpoint,
68
- },
69
- auth: {
70
- issuer: `https://${ecosystem.auth0.tenant_domain}/`,
71
- audience: resourceUri,
72
- jwks_uri: `https://${ecosystem.auth0.tenant_domain}/.well-known/jwks.json`,
73
- protected_resource_metadata_url: metadataUrl,
74
- },
75
- scopes,
76
- };
77
- const serverDir = join(rootDir, "mcps", slug);
78
- await mkdir(serverDir, { recursive: true });
79
- const runtimeConfigPath = join(serverDir, "runtime-config.generated.json");
80
- if (!dryRun) {
81
- await writeFile(runtimeConfigPath, JSON.stringify(runtimeConfig, null, 2) + "\n", "utf-8");
82
- written.push(runtimeConfigPath);
83
- logger.success(`Generated: ${runtimeConfigPath}`);
84
- }
85
- else {
86
- logger.info(`[DRY RUN] Would generate: ${runtimeConfigPath}`);
87
- }
43
+ else if (!changed) {
44
+ logger.info(`No changes needed: ${envExamplePath}`);
88
45
  }
89
46
  return { filesWritten: written };
90
47
  }
48
+ function isLegacyGeneratedEnvExample(content) {
49
+ const lines = content.split(/\r?\n/);
50
+ while (lines.length > 0 && lines[lines.length - 1] === "") {
51
+ lines.pop();
52
+ }
53
+ return (lines.length === 10 &&
54
+ lines[0] === "# Ecosystem base domain (required)" &&
55
+ /^ECOSYSTEM_BASE_DOMAIN=/.test(lines[1] ?? "") &&
56
+ lines[2] === "" &&
57
+ lines[3] === "# Auth0 tenant and Management API credentials (required for provisioning)" &&
58
+ /^AUTH0_TENANT_DOMAIN=/.test(lines[4] ?? "") &&
59
+ /^AUTH0_MGMT_CLIENT_ID=/.test(lines[5] ?? "") &&
60
+ /^AUTH0_MGMT_CLIENT_SECRET=/.test(lines[6] ?? "") &&
61
+ lines[7] === "" &&
62
+ lines[8] === "# Client IDs and secrets are automatically written to .env by" &&
63
+ lines[9] === "# reconcile-client and reconcile-all. Do not set them manually.");
64
+ }
91
65
  //# sourceMappingURL=generate-artifacts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate-artifacts.js","sourceRoot":"","sources":["../../src/commands/generate-artifacts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generate-artifacts.js","sourceRoot":"","sources":["../../src/commands/generate-artifacts.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"grant-client.d.ts","sourceRoot":"","sources":["../../src/commands/grant-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAKxD,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IACxD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,WAAW,CAC/B,GAAG,EAAE,cAAc,EACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,iBAAiB,CAAC,CAwI5B"}
1
+ {"version":3,"file":"grant-client.d.ts","sourceRoot":"","sources":["../../src/commands/grant-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAYxD,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IACxD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,WAAW,CAC/B,GAAG,EAAE,cAAc,EACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,iBAAiB,CAAC,CA0J5B"}
@@ -1,8 +1,11 @@
1
1
  import { logger } from "../utils/index.js";
2
- import { deriveCanonicalResourceUri, resolveScopes } from "../config/index.js";
2
+ import { assertRequiredEcosystemEnv, deriveCanonicalResourceUri, resolveClientAccessPolicy, resolveScopes, } from "../config/index.js";
3
3
  import { reconcileClient } from "./reconcile-client.js";
4
+ import { assertNoManagedClientCredentialsOutsideManagedBlock } from "./env-root-validation.js";
5
+ import { loadValidatedCachedClientApplication } from "./validated-client-cache.js";
4
6
  export async function grantClient(ctx, serverSlug, clientKey, scopes) {
5
7
  const { config, auth0, dryRun } = ctx;
8
+ assertNoManagedClientCredentialsOutsideManagedBlock(ctx);
6
9
  const serverConfig = config.serverConfigs.get(serverSlug);
7
10
  if (!serverConfig) {
8
11
  throw new Error(`Unknown server slug: "${serverSlug}"`);
@@ -11,13 +14,25 @@ export async function grantClient(ctx, serverSlug, clientKey, scopes) {
11
14
  if (!clientConfig) {
12
15
  throw new Error(`Unknown client key: "${clientKey}"`);
13
16
  }
17
+ assertRequiredEcosystemEnv(config.ecosystem, {
18
+ context: `grant access to server "${serverSlug}"`,
19
+ requireBaseDomain: true,
20
+ });
14
21
  const audience = deriveCanonicalResourceUri(config.ecosystem, serverConfig.slug);
15
22
  const grantScopes = scopes && scopes.length > 0
16
23
  ? scopes
17
24
  : resolveScopes(config.ecosystem, serverConfig);
18
25
  const profileDef = config.ecosystem.defaults.client_profiles?.[clientConfig.profile];
19
26
  const subjectType = profileDef?.access_mode === "machine" ? "client" : "user";
20
- let clientId = clientConfig.auth0.existing_client_id;
27
+ if (subjectType === "client" &&
28
+ resolveClientAccessPolicy(config.ecosystem, serverConfig) === "deny_all") {
29
+ throw new Error(`Server "${serverSlug}" has effective client access policy deny_all.\n\n` +
30
+ ` Machine-to-machine grants are disabled for this server.\n` +
31
+ ` Set access_policy.client or defaults.api.client_access_policy to "require_client_grant"\n` +
32
+ ` before creating a client grant for "${clientKey}".`);
33
+ }
34
+ let clientId = (await loadValidatedCachedClientApplication(ctx, clientKey))
35
+ ?.client_id;
21
36
  if (!clientId) {
22
37
  logger.info(`Ensuring client "${clientKey}" exists...`);
23
38
  const result = await reconcileClient(ctx, clientKey);
@@ -1 +1 @@
1
- {"version":3,"file":"grant-client.js","sourceRoot":"","sources":["../../src/commands/grant-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"grant-client.js","sourceRoot":"","sources":["../../src/commands/grant-client.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"reconcile-all.d.ts","sourceRoot":"","sources":["../../src/commands/reconcile-all.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,EAAmB,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACpF,OAAO,EAAmB,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEpF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,OAAO,EAAE,qBAAqB,EAAE,CAAC;CAClC;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,kBAAkB,CAAC,CAsE7B"}
1
+ {"version":3,"file":"reconcile-all.d.ts","sourceRoot":"","sources":["../../src/commands/reconcile-all.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAIxD,OAAO,EAAmB,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACpF,OAAO,EAAmB,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAGpF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,OAAO,EAAE,qBAAqB,EAAE,CAAC;CAClC;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,kBAAkB,CAAC,CA8E7B"}
@@ -1,9 +1,12 @@
1
1
  import { logger } from "../utils/index.js";
2
+ import { assertRequiredEcosystemEnv } from "../config/index.js";
2
3
  import { verifyTenant } from "./verify-tenant.js";
3
4
  import { reconcileClient } from "./reconcile-client.js";
4
5
  import { reconcileServer } from "./reconcile-server.js";
6
+ import { assertNoManagedClientCredentialsOutsideManagedBlock } from "./env-root-validation.js";
5
7
  export async function reconcileAll(ctx) {
6
8
  const { config } = ctx;
9
+ assertNoManagedClientCredentialsOutsideManagedBlock(ctx);
7
10
  logger.info("=== Full Ecosystem Reconciliation ===");
8
11
  logger.blank();
9
12
  // Phase 1: Verify tenant
@@ -28,6 +31,12 @@ export async function reconcileAll(ctx) {
28
31
  }
29
32
  logger.info("=== Phase 3: Reconcile MCP Servers ===");
30
33
  logger.blank();
34
+ if (config.serverConfigs.size > 0) {
35
+ assertRequiredEcosystemEnv(config.ecosystem, {
36
+ context: "reconcile MCP servers",
37
+ requireBaseDomain: true,
38
+ });
39
+ }
31
40
  const serverResults = [];
32
41
  for (const slug of config.serverConfigs.keys()) {
33
42
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"reconcile-all.js","sourceRoot":"","sources":["../../src/commands/reconcile-all.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reconcile-all.js","sourceRoot":"","sources":["../../src/commands/reconcile-all.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,13 @@
1
1
  import type { CommandContext } from "../utils/index.js";
2
+ export type ClientSecretStatus = "not_applicable" | "dry_run" | "written" | "matched_existing_managed" | "skipped_existing_managed";
2
3
  export interface ReconcileClientResult {
3
4
  clientKey: string;
4
5
  clientId: string;
5
6
  action: "created" | "reused" | "patched" | "dry_run";
6
7
  applicationType: string;
7
8
  tokenEndpointAuthMethod: string;
8
- secretPlaceholderRequired: boolean;
9
+ secretWritten: boolean;
10
+ secretStatus: ClientSecretStatus;
9
11
  }
10
12
  export declare function reconcileClient(ctx: CommandContext, clientKey: string): Promise<ReconcileClientResult>;
11
13
  //# sourceMappingURL=reconcile-client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reconcile-client.d.ts","sourceRoot":"","sources":["../../src/commands/reconcile-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAWxD,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IACrD,eAAe,EAAE,MAAM,CAAC;IACxB,uBAAuB,EAAE,MAAM,CAAC;IAChC,yBAAyB,EAAE,OAAO,CAAC;CACpC;AAcD,wBAAsB,eAAe,CACnC,GAAG,EAAE,cAAc,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,CAAC,CA6KhC"}
1
+ {"version":3,"file":"reconcile-client.d.ts","sourceRoot":"","sources":["../../src/commands/reconcile-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAiBxD,MAAM,MAAM,kBAAkB,GAC1B,gBAAgB,GAChB,SAAS,GACT,SAAS,GACT,0BAA0B,GAC1B,0BAA0B,CAAC;AAE/B,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IACrD,eAAe,EAAE,MAAM,CAAC;IACxB,uBAAuB,EAAE,MAAM,CAAC;IAChC,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,kBAAkB,CAAC;CAClC;AAcD,wBAAsB,eAAe,CACnC,GAAG,EAAE,cAAc,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,CAAC,CA0QhC"}
@@ -1,6 +1,10 @@
1
- import { logger } from "../utils/index.js";
1
+ import { join } from "node:path";
2
+ import { logger, clientIdEnvVar, clientSecretEnvVar } from "../utils/index.js";
3
+ import { assertNoManagedClientCredentialsOutsideManagedBlock } from "./env-root-validation.js";
4
+ import { expectedManagedClientMetadata, loadValidatedCachedClientApplication, MANAGED_BY, } from "./validated-client-cache.js";
2
5
  export async function reconcileClient(ctx, clientKey) {
3
- const { config, auth0, dryRun } = ctx;
6
+ const { config, auth0, envManager, dryRun } = ctx;
7
+ assertNoManagedClientCredentialsOutsideManagedBlock(ctx);
4
8
  const clientConfig = config.clientConfigs.get(clientKey);
5
9
  if (!clientConfig) {
6
10
  throw new Error(`Unknown client key: "${clientKey}"`);
@@ -13,51 +17,77 @@ export async function reconcileClient(ctx, clientKey) {
13
17
  logger.debug(` Profile: ${clientConfig.profile}`);
14
18
  logger.debug(` App type: ${settings.appType}`);
15
19
  logger.debug(` Auth method: ${settings.tokenEndpointAuthMethod}`);
16
- if (clientConfig.auth0.existing_client_id) {
17
- logger.info(` Using existing client_id: ${clientConfig.auth0.existing_client_id}`);
18
- const existing = await auth0.getApplication(clientConfig.auth0.existing_client_id);
20
+ const idEnvKey = clientIdEnvVar(clientKey);
21
+ const expectedMetadata = expectedManagedClientMetadata(config.ecosystem, clientConfig);
22
+ const existing = await loadValidatedCachedClientApplication(ctx, clientKey);
23
+ if (existing) {
24
+ logger.info(` Using existing client_id from ${idEnvKey}: ${existing.client_id}`);
19
25
  const reuse = checkCompatibility(existing, settings);
20
26
  if (!reuse.compatible) {
21
27
  logger.warn(` Existing application is NOT fully compatible: ${reuse.reason}`);
22
- const policy = descriptor?.reuse_policy ?? "share_if_exact_match";
23
- if (policy === "patch_if_safe" && !dryRun) {
28
+ const policy = resolveReusePolicy(clientConfig, descriptor);
29
+ if (policy === "patch_if_safe") {
30
+ if (dryRun) {
31
+ logger.info(" [DRY RUN] Would patch existing application.");
32
+ return {
33
+ clientKey,
34
+ clientId: existing.client_id,
35
+ action: "dry_run",
36
+ applicationType: settings.appType,
37
+ tokenEndpointAuthMethod: settings.tokenEndpointAuthMethod,
38
+ secretWritten: false,
39
+ secretStatus: "not_applicable",
40
+ };
41
+ }
24
42
  logger.info(" Attempting safe patch...");
25
43
  await patchApplication(auth0, existing, settings, config.ecosystem, clientConfig);
26
44
  logger.success(" Application patched.");
45
+ assertManagedClientEnvWrite(envManager.set(idEnvKey, existing.client_id, {
46
+ rejectOuterCollision: true,
47
+ }), ctx.rootDir);
27
48
  return {
28
49
  clientKey,
29
50
  clientId: existing.client_id,
30
51
  action: "patched",
31
52
  applicationType: settings.appType,
32
53
  tokenEndpointAuthMethod: settings.tokenEndpointAuthMethod,
33
- secretPlaceholderRequired: isConfidential(settings),
54
+ secretWritten: false,
55
+ secretStatus: "not_applicable",
34
56
  };
35
57
  }
36
58
  logger.warn(" Reusing as-is (policy does not allow patching).");
37
59
  }
60
+ assertManagedClientEnvWrite(envManager.set(idEnvKey, existing.client_id, {
61
+ rejectOuterCollision: true,
62
+ }), ctx.rootDir);
38
63
  return {
39
64
  clientKey,
40
65
  clientId: existing.client_id,
41
66
  action: "reused",
42
67
  applicationType: settings.appType,
43
68
  tokenEndpointAuthMethod: settings.tokenEndpointAuthMethod,
44
- secretPlaceholderRequired: isConfidential(settings),
69
+ secretWritten: false,
70
+ secretStatus: "not_applicable",
45
71
  };
46
72
  }
47
73
  logger.info(" Searching for existing Auth0 application by metadata...");
48
- const existingApp = await auth0.findApplicationByMetadata("client_key", clientKey);
74
+ const existingApp = await auth0.findApplicationByMetadataEntries(expectedMetadata);
49
75
  if (existingApp) {
50
76
  logger.info(` Found existing application: ${existingApp.name} (${existingApp.client_id})`);
51
77
  const reuse = checkCompatibility(existingApp, settings);
52
78
  if (reuse.compatible) {
53
79
  logger.success(" Application is compatible. Reusing.");
80
+ assertManagedClientEnvWrite(envManager.set(idEnvKey, existingApp.client_id, {
81
+ rejectOuterCollision: true,
82
+ }), ctx.rootDir);
54
83
  return {
55
84
  clientKey,
56
85
  clientId: existingApp.client_id,
57
86
  action: "reused",
58
87
  applicationType: settings.appType,
59
88
  tokenEndpointAuthMethod: settings.tokenEndpointAuthMethod,
60
- secretPlaceholderRequired: isConfidential(settings),
89
+ secretWritten: false,
90
+ secretStatus: "not_applicable",
61
91
  };
62
92
  }
63
93
  logger.warn(` Existing application is not compatible: ${reuse.reason}`);
@@ -71,19 +101,24 @@ export async function reconcileClient(ctx, clientKey) {
71
101
  action: "dry_run",
72
102
  applicationType: settings.appType,
73
103
  tokenEndpointAuthMethod: settings.tokenEndpointAuthMethod,
74
- secretPlaceholderRequired: isConfidential(settings),
104
+ secretWritten: false,
105
+ secretStatus: "not_applicable",
75
106
  };
76
107
  }
77
108
  logger.info(" Patching existing application...");
78
109
  await patchApplication(auth0, existingApp, settings, config.ecosystem, clientConfig);
79
110
  logger.success(" Application patched.");
111
+ assertManagedClientEnvWrite(envManager.set(idEnvKey, existingApp.client_id, {
112
+ rejectOuterCollision: true,
113
+ }), ctx.rootDir);
80
114
  return {
81
115
  clientKey,
82
116
  clientId: existingApp.client_id,
83
117
  action: "patched",
84
118
  applicationType: settings.appType,
85
119
  tokenEndpointAuthMethod: settings.tokenEndpointAuthMethod,
86
- secretPlaceholderRequired: isConfidential(settings),
120
+ secretWritten: false,
121
+ secretStatus: "not_applicable",
87
122
  };
88
123
  }
89
124
  if (policy === "share_if_exact_match") {
@@ -104,13 +139,15 @@ export async function reconcileClient(ctx, clientKey) {
104
139
  action: "dry_run",
105
140
  applicationType: settings.appType,
106
141
  tokenEndpointAuthMethod: settings.tokenEndpointAuthMethod,
107
- secretPlaceholderRequired: isConfidential(settings),
142
+ secretWritten: false,
143
+ secretStatus: isConfidential(settings) ? "dry_run" : "not_applicable",
108
144
  };
109
145
  }
110
146
  logger.info(" Creating new Auth0 Application...");
111
147
  const newApp = await auth0.createApplication({
112
148
  name: clientConfig.display_name,
113
149
  app_type: settings.appType,
150
+ oidc_conformant: true,
114
151
  token_endpoint_auth_method: settings.tokenEndpointAuthMethod,
115
152
  grant_types: settings.grantTypes,
116
153
  callbacks: settings.callbackUrls.length > 0 ? settings.callbackUrls : undefined,
@@ -121,7 +158,7 @@ export async function reconcileClient(ctx, clientKey) {
121
158
  client_key: clientKey,
122
159
  descriptor: clientConfig.descriptor ?? "",
123
160
  profile: clientConfig.profile,
124
- managed_by: "@scupit/mcp-ecosystem",
161
+ managed_by: MANAGED_BY,
125
162
  },
126
163
  ...(settings.useRefreshTokens && {
127
164
  refresh_token: {
@@ -133,13 +170,45 @@ export async function reconcileClient(ctx, clientKey) {
133
170
  }),
134
171
  });
135
172
  logger.success(` Application created: ${newApp.name} (${newApp.client_id})`);
173
+ assertManagedClientEnvWrite(envManager.set(idEnvKey, newApp.client_id, {
174
+ rejectOuterCollision: true,
175
+ }), ctx.rootDir);
176
+ let secretWritten = false;
177
+ let secretStatus = "not_applicable";
178
+ if (isConfidential(settings) && newApp.client_secret) {
179
+ const secretEnvKey = clientSecretEnvVar(clientKey);
180
+ const secretWriteResult = envManager.set(secretEnvKey, newApp.client_secret, {
181
+ writeOnce: true,
182
+ rejectOuterCollision: true,
183
+ });
184
+ switch (secretWriteResult.status) {
185
+ case "created":
186
+ case "updated":
187
+ secretWritten = true;
188
+ secretStatus = "written";
189
+ logger.success(` Client secret captured in ${secretEnvKey}.`);
190
+ break;
191
+ case "matched_existing_managed":
192
+ secretStatus = "matched_existing_managed";
193
+ logger.info(` Client secret already present in managed ${secretEnvKey}.`);
194
+ break;
195
+ case "skipped_existing_managed":
196
+ secretStatus = "skipped_existing_managed";
197
+ logger.warn(` Client secret already exists in managed ${secretEnvKey}. ` +
198
+ `Preserving the existing write-once value.`);
199
+ break;
200
+ case "rejected_outer_collision":
201
+ throw new Error(buildUnexpectedOuterCollisionError(secretEnvKey, ctx.rootDir, secretWriteResult.outerAssignments?.map((assignment) => assignment.rawLine) ?? []));
202
+ }
203
+ }
136
204
  return {
137
205
  clientKey,
138
206
  clientId: newApp.client_id,
139
207
  action: "created",
140
208
  applicationType: settings.appType,
141
209
  tokenEndpointAuthMethod: settings.tokenEndpointAuthMethod,
142
- secretPlaceholderRequired: isConfidential(settings),
210
+ secretWritten,
211
+ secretStatus,
143
212
  };
144
213
  }
145
214
  function resolveSettings(ecosystem, client, descriptor) {
@@ -280,7 +349,7 @@ async function patchApplication(auth0, existing, settings, ecosystem, clientConf
280
349
  client_key: clientConfig.client_key,
281
350
  descriptor: clientConfig.descriptor ?? "",
282
351
  profile: clientConfig.profile,
283
- managed_by: "mcp-ecosystem-script",
352
+ managed_by: MANAGED_BY,
284
353
  };
285
354
  if (Object.keys(patch).length > 0) {
286
355
  await auth0.updateApplication(existing.client_id, patch);
@@ -292,4 +361,27 @@ function mergeArrays(existing, desired) {
292
361
  set.add(item);
293
362
  return [...set];
294
363
  }
364
+ function assertManagedClientEnvWrite(result, rootDir) {
365
+ if (result.status !== "rejected_outer_collision") {
366
+ return;
367
+ }
368
+ throw new Error(buildUnexpectedOuterCollisionError(result.key, rootDir, result.outerAssignments?.map((assignment) => assignment.rawLine) ?? []));
369
+ }
370
+ function buildUnexpectedOuterCollisionError(envKey, rootDir, rawAssignments) {
371
+ const envPath = join(rootDir, ".env");
372
+ const entries = rawAssignments.length > 0
373
+ ? rawAssignments.map((line) => ` ${maskSecretAssignment(line)}`)
374
+ : [` ${maskSecretAssignment(`${envKey}=<user-authored-value>`)}`];
375
+ return (`Invalid tool-managed client credential in ${envPath}\n\n` +
376
+ ` ${envKey} exists outside the managed block, so the CLI refused to write a managed value.\n\n` +
377
+ ` Remove the outer assignment and re-run reconciliation:\n` +
378
+ `${entries.join("\n")}`);
379
+ }
380
+ function maskSecretAssignment(line) {
381
+ const eqIdx = line.indexOf("=");
382
+ if (eqIdx === -1)
383
+ return line;
384
+ const key = line.slice(0, eqIdx).trim();
385
+ return key.includes("_SECRET") ? `${key}=********` : line;
386
+ }
295
387
  //# sourceMappingURL=reconcile-client.js.map