@openziti/ziti-mcp-server 0.1.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 (210) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +868 -0
  3. package/dist/auth/client-credentials-flow.d.ts +21 -0
  4. package/dist/auth/client-credentials-flow.js +63 -0
  5. package/dist/auth/client-credentials-flow.js.map +1 -0
  6. package/dist/auth/device-auth-flow.d.ts +47 -0
  7. package/dist/auth/device-auth-flow.js +291 -0
  8. package/dist/auth/device-auth-flow.js.map +1 -0
  9. package/dist/clients/base.d.ts +74 -0
  10. package/dist/clients/base.js +109 -0
  11. package/dist/clients/base.js.map +1 -0
  12. package/dist/clients/claude.d.ts +22 -0
  13. package/dist/clients/claude.js +40 -0
  14. package/dist/clients/claude.js.map +1 -0
  15. package/dist/clients/cursor.d.ts +22 -0
  16. package/dist/clients/cursor.js +39 -0
  17. package/dist/clients/cursor.js.map +1 -0
  18. package/dist/clients/index.d.ts +33 -0
  19. package/dist/clients/index.js +39 -0
  20. package/dist/clients/index.js.map +1 -0
  21. package/dist/clients/types.d.ts +70 -0
  22. package/dist/clients/types.js +2 -0
  23. package/dist/clients/types.js.map +1 -0
  24. package/dist/clients/utils.d.ts +22 -0
  25. package/dist/clients/utils.js +46 -0
  26. package/dist/clients/utils.js.map +1 -0
  27. package/dist/clients/vscode.d.ts +76 -0
  28. package/dist/clients/vscode.js +159 -0
  29. package/dist/clients/vscode.js.map +1 -0
  30. package/dist/clients/windsurf.d.ts +22 -0
  31. package/dist/clients/windsurf.js +39 -0
  32. package/dist/clients/windsurf.js.map +1 -0
  33. package/dist/commands/init.d.ts +45 -0
  34. package/dist/commands/init.js +133 -0
  35. package/dist/commands/init.js.map +1 -0
  36. package/dist/commands/logout.d.ts +12 -0
  37. package/dist/commands/logout.js +90 -0
  38. package/dist/commands/logout.js.map +1 -0
  39. package/dist/commands/run.d.ts +15 -0
  40. package/dist/commands/run.js +94 -0
  41. package/dist/commands/run.js.map +1 -0
  42. package/dist/commands/session.d.ts +12 -0
  43. package/dist/commands/session.js +99 -0
  44. package/dist/commands/session.js.map +1 -0
  45. package/dist/index.d.ts +2 -0
  46. package/dist/index.js +105 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/server.d.ts +67 -0
  49. package/dist/server.js +171 -0
  50. package/dist/server.js.map +1 -0
  51. package/dist/tools/api-sessions.d.ts +3 -0
  52. package/dist/tools/api-sessions.js +86 -0
  53. package/dist/tools/api-sessions.js.map +1 -0
  54. package/dist/tools/auth-policies.d.ts +3 -0
  55. package/dist/tools/auth-policies.js +347 -0
  56. package/dist/tools/auth-policies.js.map +1 -0
  57. package/dist/tools/authenticators.d.ts +3 -0
  58. package/dist/tools/authenticators.js +183 -0
  59. package/dist/tools/authenticators.js.map +1 -0
  60. package/dist/tools/certificate-authorities.d.ts +3 -0
  61. package/dist/tools/certificate-authorities.js +288 -0
  62. package/dist/tools/certificate-authorities.js.map +1 -0
  63. package/dist/tools/config-types.d.ts +3 -0
  64. package/dist/tools/config-types.js +194 -0
  65. package/dist/tools/config-types.js.map +1 -0
  66. package/dist/tools/configs.d.ts +3 -0
  67. package/dist/tools/configs.js +203 -0
  68. package/dist/tools/configs.js.map +1 -0
  69. package/dist/tools/controller-settings.d.ts +3 -0
  70. package/dist/tools/controller-settings.js +219 -0
  71. package/dist/tools/controller-settings.js.map +1 -0
  72. package/dist/tools/controllers.d.ts +3 -0
  73. package/dist/tools/controllers.js +89 -0
  74. package/dist/tools/controllers.js.map +1 -0
  75. package/dist/tools/edge-router-policies.d.ts +3 -0
  76. package/dist/tools/edge-router-policies.js +262 -0
  77. package/dist/tools/edge-router-policies.js.map +1 -0
  78. package/dist/tools/edge-routers.d.ts +3 -0
  79. package/dist/tools/edge-routers.js +381 -0
  80. package/dist/tools/edge-routers.js.map +1 -0
  81. package/dist/tools/enrollments.d.ts +3 -0
  82. package/dist/tools/enrollments.js +187 -0
  83. package/dist/tools/enrollments.js.map +1 -0
  84. package/dist/tools/external-jwt-signers.d.ts +3 -0
  85. package/dist/tools/external-jwt-signers.js +242 -0
  86. package/dist/tools/external-jwt-signers.js.map +1 -0
  87. package/dist/tools/identities.d.ts +3 -0
  88. package/dist/tools/identities.js +741 -0
  89. package/dist/tools/identities.js.map +1 -0
  90. package/dist/tools/identity-types.d.ts +3 -0
  91. package/dist/tools/identity-types.js +58 -0
  92. package/dist/tools/identity-types.js.map +1 -0
  93. package/dist/tools/index.d.ts +3 -0
  94. package/dist/tools/index.js +101 -0
  95. package/dist/tools/index.js.map +1 -0
  96. package/dist/tools/posture-checks.d.ts +3 -0
  97. package/dist/tools/posture-checks.js +254 -0
  98. package/dist/tools/posture-checks.js.map +1 -0
  99. package/dist/tools/routers.d.ts +3 -0
  100. package/dist/tools/routers.js +169 -0
  101. package/dist/tools/routers.js.map +1 -0
  102. package/dist/tools/service-edge-router-policies.d.ts +3 -0
  103. package/dist/tools/service-edge-router-policies.js +282 -0
  104. package/dist/tools/service-edge-router-policies.js.map +1 -0
  105. package/dist/tools/service-policies.d.ts +3 -0
  106. package/dist/tools/service-policies.js +311 -0
  107. package/dist/tools/service-policies.js.map +1 -0
  108. package/dist/tools/services.d.ts +3 -0
  109. package/dist/tools/services.js +403 -0
  110. package/dist/tools/services.js.map +1 -0
  111. package/dist/tools/sessions.d.ts +3 -0
  112. package/dist/tools/sessions.js +86 -0
  113. package/dist/tools/sessions.js.map +1 -0
  114. package/dist/tools/terminators.d.ts +3 -0
  115. package/dist/tools/terminators.js +187 -0
  116. package/dist/tools/terminators.js.map +1 -0
  117. package/dist/tools/transit-routers.d.ts +3 -0
  118. package/dist/tools/transit-routers.js +169 -0
  119. package/dist/tools/transit-routers.js.map +1 -0
  120. package/dist/utils/analytics.d.ts +75 -0
  121. package/dist/utils/analytics.js +191 -0
  122. package/dist/utils/analytics.js.map +1 -0
  123. package/dist/utils/auth0-client.d.ts +27 -0
  124. package/dist/utils/auth0-client.js +67 -0
  125. package/dist/utils/auth0-client.js.map +1 -0
  126. package/dist/utils/authenticated-client.d.ts +6 -0
  127. package/dist/utils/authenticated-client.js +55 -0
  128. package/dist/utils/authenticated-client.js.map +1 -0
  129. package/dist/utils/config.d.ts +65 -0
  130. package/dist/utils/config.js +80 -0
  131. package/dist/utils/config.js.map +1 -0
  132. package/dist/utils/constants.d.ts +15 -0
  133. package/dist/utils/constants.js +17 -0
  134. package/dist/utils/constants.js.map +1 -0
  135. package/dist/utils/controller-client/client/client.gen.d.ts +2 -0
  136. package/dist/utils/controller-client/client/client.gen.js +229 -0
  137. package/dist/utils/controller-client/client/client.gen.js.map +1 -0
  138. package/dist/utils/controller-client/client/index.d.ts +8 -0
  139. package/dist/utils/controller-client/client/index.js +7 -0
  140. package/dist/utils/controller-client/client/index.js.map +1 -0
  141. package/dist/utils/controller-client/client/types.gen.d.ts +117 -0
  142. package/dist/utils/controller-client/client/types.gen.js +3 -0
  143. package/dist/utils/controller-client/client/types.gen.js.map +1 -0
  144. package/dist/utils/controller-client/client/utils.gen.d.ts +33 -0
  145. package/dist/utils/controller-client/client/utils.gen.js +232 -0
  146. package/dist/utils/controller-client/client/utils.gen.js.map +1 -0
  147. package/dist/utils/controller-client/client.gen.d.ts +12 -0
  148. package/dist/utils/controller-client/client.gen.js +6 -0
  149. package/dist/utils/controller-client/client.gen.js.map +1 -0
  150. package/dist/utils/controller-client/core/auth.gen.d.ts +18 -0
  151. package/dist/utils/controller-client/core/auth.gen.js +15 -0
  152. package/dist/utils/controller-client/core/auth.gen.js.map +1 -0
  153. package/dist/utils/controller-client/core/bodySerializer.gen.d.ts +25 -0
  154. package/dist/utils/controller-client/core/bodySerializer.gen.js +58 -0
  155. package/dist/utils/controller-client/core/bodySerializer.gen.js.map +1 -0
  156. package/dist/utils/controller-client/core/params.gen.d.ts +43 -0
  157. package/dist/utils/controller-client/core/params.gen.js +101 -0
  158. package/dist/utils/controller-client/core/params.gen.js.map +1 -0
  159. package/dist/utils/controller-client/core/pathSerializer.gen.d.ts +33 -0
  160. package/dist/utils/controller-client/core/pathSerializer.gen.js +115 -0
  161. package/dist/utils/controller-client/core/pathSerializer.gen.js.map +1 -0
  162. package/dist/utils/controller-client/core/queryKeySerializer.gen.d.ts +18 -0
  163. package/dist/utils/controller-client/core/queryKeySerializer.gen.js +100 -0
  164. package/dist/utils/controller-client/core/queryKeySerializer.gen.js.map +1 -0
  165. package/dist/utils/controller-client/core/serverSentEvents.gen.d.ts +71 -0
  166. package/dist/utils/controller-client/core/serverSentEvents.gen.js +136 -0
  167. package/dist/utils/controller-client/core/serverSentEvents.gen.js.map +1 -0
  168. package/dist/utils/controller-client/core/types.gen.d.ts +78 -0
  169. package/dist/utils/controller-client/core/types.gen.js +3 -0
  170. package/dist/utils/controller-client/core/types.gen.js.map +1 -0
  171. package/dist/utils/controller-client/core/utils.gen.d.ts +19 -0
  172. package/dist/utils/controller-client/core/utils.gen.js +88 -0
  173. package/dist/utils/controller-client/core/utils.gen.js.map +1 -0
  174. package/dist/utils/controller-client/index.d.ts +2 -0
  175. package/dist/utils/controller-client/index.js +3 -0
  176. package/dist/utils/controller-client/index.js.map +1 -0
  177. package/dist/utils/controller-client/sdk.gen.d.ts +1302 -0
  178. package/dist/utils/controller-client/sdk.gen.js +4436 -0
  179. package/dist/utils/controller-client/sdk.gen.js.map +1 -0
  180. package/dist/utils/controller-client/types.gen.d.ts +9170 -0
  181. package/dist/utils/controller-client/types.gen.js +3 -0
  182. package/dist/utils/controller-client/types.gen.js.map +1 -0
  183. package/dist/utils/glob.d.ts +75 -0
  184. package/dist/utils/glob.js +110 -0
  185. package/dist/utils/glob.js.map +1 -0
  186. package/dist/utils/http-utility.d.ts +5 -0
  187. package/dist/utils/http-utility.js +68 -0
  188. package/dist/utils/http-utility.js.map +1 -0
  189. package/dist/utils/keychain.d.ts +129 -0
  190. package/dist/utils/keychain.js +193 -0
  191. package/dist/utils/keychain.js.map +1 -0
  192. package/dist/utils/logger.d.ts +4 -0
  193. package/dist/utils/logger.js +28 -0
  194. package/dist/utils/logger.js.map +1 -0
  195. package/dist/utils/package.d.ts +3 -0
  196. package/dist/utils/package.js +9 -0
  197. package/dist/utils/package.js.map +1 -0
  198. package/dist/utils/scopes.d.ts +12 -0
  199. package/dist/utils/scopes.js +19 -0
  200. package/dist/utils/scopes.js.map +1 -0
  201. package/dist/utils/terminal.d.ts +35 -0
  202. package/dist/utils/terminal.js +409 -0
  203. package/dist/utils/terminal.js.map +1 -0
  204. package/dist/utils/tools.d.ts +63 -0
  205. package/dist/utils/tools.js +149 -0
  206. package/dist/utils/tools.js.map +1 -0
  207. package/dist/utils/types.d.ts +55 -0
  208. package/dist/utils/types.js +3 -0
  209. package/dist/utils/types.js.map +1 -0
  210. package/package.json +89 -0
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Interface for client credentials configuration
3
+ */
4
+ export interface ClientCredentialsConfig {
5
+ zitiControllerHost: string;
6
+ idpDomain: string;
7
+ idpClientId: string;
8
+ idpClientSecret: string;
9
+ audience?: string;
10
+ scopes?: string[];
11
+ }
12
+ /**
13
+ * Request authorization using client credentials flow
14
+ *
15
+ * This method is primarily designed for Private Cloud users who cannot use the
16
+ * device authorization flow. It uses client credentials flow to obtain an access token.
17
+ *
18
+ * @param {ClientCredentialsConfig} config - Configuration for client credentials flow
19
+ * @returns {Promise<void>}
20
+ */
21
+ export declare function requestClientCredentialsAuthorization(config: ClientCredentialsConfig): Promise<void>;
@@ -0,0 +1,63 @@
1
+ import chalk from 'chalk';
2
+ import { cliOutput } from '../utils/terminal.js';
3
+ import { log, logError } from '../utils/logger.js';
4
+ import { keychain } from '../utils/keychain.js';
5
+ import { getAuthenticationClient } from '../utils/auth0-client.js';
6
+ /**
7
+ * Request authorization using client credentials flow
8
+ *
9
+ * This method is primarily designed for Private Cloud users who cannot use the
10
+ * device authorization flow. It uses client credentials flow to obtain an access token.
11
+ *
12
+ * @param {ClientCredentialsConfig} config - Configuration for client credentials flow
13
+ * @returns {Promise<void>}
14
+ */
15
+ export async function requestClientCredentialsAuthorization(config) {
16
+ log('Initiating client credentials flow authentication...');
17
+ try {
18
+ // Auth client
19
+ const authClient = await getAuthenticationClient(config.idpDomain, config.idpClientId, config.idpClientSecret);
20
+ // Set audience if provided, otherwise use a default based on the domain
21
+ const audience = config.audience || `https://${config.idpDomain}/api/v2/`;
22
+ // Make the token request
23
+ const { data: { access_token, expires_in }, } = await authClient.oauth.clientCredentialsGrant({
24
+ audience,
25
+ });
26
+ const tokenSet = { access_token, expires_in };
27
+ // Store the token information
28
+ await storeTokenInfo(tokenSet, config.zitiControllerHost, config.idpDomain);
29
+ cliOutput(`\n${chalk.green('✓')} Successfully authenticated to ${chalk.blue(config.idpDomain)} using client credentials.\n`);
30
+ }
31
+ catch (error) {
32
+ logError('Client credentials authentication error:', error);
33
+ cliOutput(`\n${chalk.red('✗')} Failed to authenticate with client credentials.\n`);
34
+ process.exit(1);
35
+ }
36
+ }
37
+ /**
38
+ * Store token information from client credentials flow
39
+ *
40
+ * @param {any} tokenSet - Token response from the server
41
+ * @param {string} domain - The domain used for authentication
42
+ */
43
+ async function storeTokenInfo(tokenSet, zitiControllerHost, domain) {
44
+ // For client credentials flow, we use the provided domain directly,
45
+ // as the token may not contain tenant information in the same format as device flow
46
+ // Store access token
47
+ await keychain.setToken(tokenSet.access_token);
48
+ await keychain.setZitiControllerHost(zitiControllerHost);
49
+ await keychain.setDomain(domain);
50
+ // Client credentials flow typically doesn't return refresh tokens
51
+ // but we'll handle it just in case
52
+ if (tokenSet.refresh_token) {
53
+ await keychain.setRefreshToken(tokenSet.refresh_token);
54
+ log('Refresh token stored in keychain');
55
+ }
56
+ // Set token expiration
57
+ if (tokenSet.expires_in) {
58
+ const expiresAt = Date.now() + tokenSet.expires_in * 1000;
59
+ await keychain.setTokenExpiresAt(expiresAt);
60
+ log(`Token expires at: ${new Date(expiresAt).toISOString()}`);
61
+ }
62
+ }
63
+ //# sourceMappingURL=client-credentials-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-credentials-flow.js","sourceRoot":"","sources":["../../src/auth/client-credentials-flow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAcnE;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,qCAAqC,CACzD,MAA+B;IAE/B,GAAG,CAAC,sDAAsD,CAAC,CAAC;IAE5D,IAAI,CAAC;QACH,cAAc;QACd,MAAM,UAAU,GAAG,MAAM,uBAAuB,CAC9C,MAAM,CAAC,SAAS,EAChB,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,eAAe,CACvB,CAAC;QAEF,wEAAwE;QACxE,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,WAAW,MAAM,CAAC,SAAS,UAAU,CAAC;QAE1E,yBAAyB;QACzB,MAAM,EACJ,IAAI,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,GACnC,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,sBAAsB,CAAC;YAChD,QAAQ;SACT,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;QAE9C,8BAA8B;QAC9B,MAAM,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QAE5E,SAAS,CACP,KAAK,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,kCAAkC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,8BAA8B,CAClH,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,QAAQ,CAAC,0CAA0C,EAAE,KAAK,CAAC,CAAC;QAC5D,SAAS,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;QACnF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,cAAc,CAC3B,QAAa,EACb,kBAA0B,EAC1B,MAAc;IAEd,oEAAoE;IACpE,oFAAoF;IAEpF,qBAAqB;IACrB,MAAM,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC/C,MAAM,QAAQ,CAAC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC;IACzD,MAAM,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEjC,kEAAkE;IAClE,mCAAmC;IACnC,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC3B,MAAM,QAAQ,CAAC,eAAe,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACvD,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAC1C,CAAC;IAED,uBAAuB;IACvB,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QACxB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAC;QAC1D,MAAM,QAAQ,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAC5C,GAAG,CAAC,qBAAqB,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAChE,CAAC;AACH,CAAC"}
@@ -0,0 +1,47 @@
1
+ declare function requestAuthorization(selectedScopes?: string[]): Promise<void>;
2
+ export declare function refreshAccessToken(selectedScopes?: string[]): Promise<string | null>;
3
+ /**
4
+ * Revokes the refresh token that is previously set within keychain when offline_access is requested.
5
+ * Returns true if the call is successful or if the refresh token does not exist.
6
+ * @returns {Promise<boolean>}
7
+ */
8
+ export declare function revokeRefreshToken(): Promise<boolean>;
9
+ /**
10
+ * Determines if the current access token is expired or will expire soon.
11
+ *
12
+ * This security check is crucial for maintaining continuous authenticated access
13
+ * to Auth0 APIs. It includes a configurable buffer time to proactively detect
14
+ * tokens that will expire soon, preventing potential disruptions during operations
15
+ * that might span multiple API calls. This proactive approach allows the system to
16
+ * initiate refresh flows before actual expiration occurs.
17
+ *
18
+ * The function considers a token expired in the following cases:
19
+ * - No expiration time is found in the keychain via `keychain.getTokenExpiresAt()`
20
+ * - Current time + buffer exceeds the token's expiration time
21
+ * - Error occurs during expiration check (fails secure)
22
+ *
23
+ * This function is used both by `validateAuthorization()` in `run.ts` for user-friendly
24
+ * startup validation and by `validateConfig()` for continuous runtime validation.
25
+ *
26
+ * @param {number} bufferSeconds - Seconds before actual expiration to consider token expired (default: 300s/5min)
27
+ * @returns {Promise<boolean>} True if token is expired or will expire within the buffer period
28
+ */
29
+ export declare function isTokenExpired(bufferSeconds?: number): Promise<boolean>;
30
+ /**
31
+ * Retrieves a valid access token for OpenZiti Controller Management API operations.
32
+ *
33
+ * This function serves as the main entry point for credential retrieval,
34
+ * ensuring that only valid, non-expired tokens are provided to API operations.
35
+ * It implements a critical security checkpoint that prevents operations from
36
+ * proceeding with invalid authentication, which could lead to API failures
37
+ * or unpredictable behavior.
38
+ *
39
+ * The function performs these key security checks:
40
+ * 1. Verifies token expiration status using isTokenExpired
41
+ * 2. Provides clear guidance to users when re-authentication is needed
42
+ * 3. Handles errors gracefully with a fail-secure approach
43
+ *
44
+ * @returns {Promise<string|null>} A valid access token, or null if no valid token is available
45
+ */
46
+ export declare function getValidAccessToken(): Promise<string | null>;
47
+ export { requestAuthorization };
@@ -0,0 +1,291 @@
1
+ import chalk from 'chalk';
2
+ import open from 'open';
3
+ import { startSpinner, stopSpinner, getTenantFromToken, cliOutput, promptForBrowserPermission, } from '../utils/terminal.js';
4
+ import { log, logError } from '../utils/logger.js';
5
+ import { keychain } from '../utils/keychain.js';
6
+ import { DEFAULT_SCOPES } from '../utils/scopes.js';
7
+ function getConfig(selectedScopes) {
8
+ // If selectedScopes is provided, use those scopes
9
+ // If not provided or empty, use DEFAULT_SCOPES (which is now empty by default)
10
+ const scopes = selectedScopes && selectedScopes.length > 0
11
+ ? selectedScopes.join(' ')
12
+ : DEFAULT_SCOPES.join(' ');
13
+ return {
14
+ tenant: 'auth0.auth0.com',
15
+ clientId: '2lhnuYMRQ8IpR5hNsOhDFQqrGQUQMRm5',
16
+ audience: 'https://*.auth0.com/api/v2/',
17
+ scopes,
18
+ };
19
+ }
20
+ async function requestAuthorization(selectedScopes) {
21
+ const config = getConfig(selectedScopes);
22
+ const body = {
23
+ client_id: config.clientId,
24
+ };
25
+ if (config.audience) {
26
+ body.audience = config.audience;
27
+ }
28
+ if (config.scopes.length) {
29
+ body.scope = config.scopes;
30
+ }
31
+ try {
32
+ const response = await fetch(`https://${config.tenant}/oauth/device/code`, {
33
+ method: 'POST',
34
+ body: new URLSearchParams(body),
35
+ headers: {
36
+ Accept: 'application/json',
37
+ 'Content-Type': 'application/x-www-form-urlencoded',
38
+ },
39
+ });
40
+ const jsonRes = await response.json();
41
+ if (!jsonRes.error) {
42
+ cliOutput(`\nVerify this code on screen: ${chalk.bold.green(jsonRes.user_code)}\n`);
43
+ // Wait for user to press Enter to open browser
44
+ await promptForBrowserPermission();
45
+ openBrowser(jsonRes.verification_uri_complete);
46
+ await exchangeDeviceCodeForToken(jsonRes, selectedScopes);
47
+ }
48
+ else {
49
+ logError('Error', jsonRes);
50
+ process.exit(1);
51
+ }
52
+ }
53
+ catch (err) {
54
+ logError('Error', err);
55
+ process.exit(1);
56
+ }
57
+ }
58
+ function wait(ms) {
59
+ return new Promise((resolve) => setTimeout(resolve, ms));
60
+ }
61
+ function isValidUrl(url) {
62
+ try {
63
+ const parsedUrl = new URL(url);
64
+ // Check for safe protocols
65
+ return ['http:', 'https:'].includes(parsedUrl.protocol);
66
+ }
67
+ catch (error) {
68
+ logError('Error', error);
69
+ return false;
70
+ }
71
+ }
72
+ function openBrowser(url) {
73
+ if (!url || !isValidUrl(url)) {
74
+ logError('Invalid URL provided:', url);
75
+ return;
76
+ }
77
+ open(url)
78
+ .then(() => {
79
+ log('Browser opened successfully');
80
+ })
81
+ .catch((err) => {
82
+ logError('Failed to open browser:', err);
83
+ });
84
+ }
85
+ async function exchangeDeviceCodeForToken(deviceCode, selectedScopes) {
86
+ const config = getConfig(selectedScopes);
87
+ startSpinner('Waiting for authorization...');
88
+ while (true) {
89
+ try {
90
+ const response = await fetch(`https://${config.tenant}/oauth/token`, {
91
+ method: 'POST',
92
+ body: new URLSearchParams({
93
+ client_id: config.clientId,
94
+ device_code: deviceCode.device_code,
95
+ grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
96
+ }),
97
+ headers: {
98
+ Accept: 'application/json',
99
+ 'Content-Type': 'application/x-www-form-urlencoded',
100
+ },
101
+ });
102
+ const jsonRes = await response.json();
103
+ if (!jsonRes.error) {
104
+ fetchUserInfo(jsonRes); // Success case
105
+ break; // Exit loop once successful
106
+ }
107
+ else if (['authorization_pending', 'slow_down'].includes(jsonRes.error)) {
108
+ await wait(5000); // Wait before polling again
109
+ }
110
+ else {
111
+ stopSpinner();
112
+ logError('Unexpected error:', jsonRes.error);
113
+ break; // Exit loop on unknown error
114
+ }
115
+ }
116
+ catch (err) {
117
+ stopSpinner();
118
+ logError('Error in token exchange:', err);
119
+ break; // Exit loop on fetch failure
120
+ }
121
+ }
122
+ stopSpinner();
123
+ }
124
+ async function fetchUserInfo(tokenSet) {
125
+ const tenantName = getTenantFromToken(tokenSet.access_token);
126
+ // Store tokens in keychain
127
+ await keychain.setToken(tokenSet.access_token);
128
+ await keychain.setDomain(tenantName);
129
+ if (tokenSet.refresh_token) {
130
+ await keychain.setRefreshToken(tokenSet.refresh_token);
131
+ log('Refresh token stored in keychain');
132
+ }
133
+ if (tokenSet.expires_in) {
134
+ const expiresAt = Date.now() + tokenSet.expires_in * 1000;
135
+ await keychain.setTokenExpiresAt(expiresAt);
136
+ log(`Token expires at: ${new Date(expiresAt).toISOString()}`);
137
+ }
138
+ }
139
+ export async function refreshAccessToken(selectedScopes) {
140
+ try {
141
+ log('Attempting to refresh access token');
142
+ const refreshToken = await keychain.getRefreshToken();
143
+ if (!refreshToken) {
144
+ log('No refresh token found in keychain');
145
+ return null;
146
+ }
147
+ const config = getConfig(selectedScopes);
148
+ const response = await fetch(`https://${config.tenant}/oauth/token`, {
149
+ method: 'POST',
150
+ body: new URLSearchParams({
151
+ grant_type: 'refresh_token',
152
+ client_id: config.clientId,
153
+ refresh_token: refreshToken,
154
+ }),
155
+ headers: {
156
+ 'Content-Type': 'application/x-www-form-urlencoded',
157
+ },
158
+ });
159
+ const tokenSet = await response.json();
160
+ if (tokenSet.error) {
161
+ log(`Error refreshing token: ${tokenSet.error}`);
162
+ return null;
163
+ }
164
+ // Store new tokens
165
+ const tenantName = getTenantFromToken(tokenSet.access_token);
166
+ await keychain.setToken(tokenSet.access_token);
167
+ await keychain.setDomain(tenantName);
168
+ if (tokenSet.refresh_token) {
169
+ await keychain.setRefreshToken(tokenSet.refresh_token);
170
+ }
171
+ if (tokenSet.expires_in) {
172
+ const expiresAt = Date.now() + tokenSet.expires_in * 1000;
173
+ await keychain.setTokenExpiresAt(expiresAt);
174
+ }
175
+ log('Successfully refreshed access token');
176
+ return tokenSet.access_token;
177
+ }
178
+ catch (error) {
179
+ log('Error refreshing access token:', error);
180
+ return null;
181
+ }
182
+ }
183
+ /**
184
+ * Revokes the refresh token that is previously set within keychain when offline_access is requested.
185
+ * Returns true if the call is successful or if the refresh token does not exist.
186
+ * @returns {Promise<boolean>}
187
+ */
188
+ export async function revokeRefreshToken() {
189
+ try {
190
+ log('Attempting to revoke refresh token');
191
+ const refreshToken = await keychain.getRefreshToken();
192
+ if (!refreshToken) {
193
+ log('No refresh token found in keychain');
194
+ return true;
195
+ }
196
+ const config = getConfig();
197
+ const response = await fetch(`https://${config.tenant}/oauth/revoke`, {
198
+ method: 'POST',
199
+ body: new URLSearchParams({
200
+ client_id: config.clientId,
201
+ token: refreshToken,
202
+ }),
203
+ headers: {
204
+ 'Content-Type': 'application/x-www-form-urlencoded',
205
+ },
206
+ });
207
+ if (response.status === 200) {
208
+ log('Refresh token successfully revoked');
209
+ return true;
210
+ }
211
+ else {
212
+ log('Error calling revoke API: ', response.statusText);
213
+ return false;
214
+ }
215
+ }
216
+ catch (error) {
217
+ log('Error revoking refresh token:', error);
218
+ return false;
219
+ }
220
+ }
221
+ /**
222
+ * Determines if the current access token is expired or will expire soon.
223
+ *
224
+ * This security check is crucial for maintaining continuous authenticated access
225
+ * to Auth0 APIs. It includes a configurable buffer time to proactively detect
226
+ * tokens that will expire soon, preventing potential disruptions during operations
227
+ * that might span multiple API calls. This proactive approach allows the system to
228
+ * initiate refresh flows before actual expiration occurs.
229
+ *
230
+ * The function considers a token expired in the following cases:
231
+ * - No expiration time is found in the keychain via `keychain.getTokenExpiresAt()`
232
+ * - Current time + buffer exceeds the token's expiration time
233
+ * - Error occurs during expiration check (fails secure)
234
+ *
235
+ * This function is used both by `validateAuthorization()` in `run.ts` for user-friendly
236
+ * startup validation and by `validateConfig()` for continuous runtime validation.
237
+ *
238
+ * @param {number} bufferSeconds - Seconds before actual expiration to consider token expired (default: 300s/5min)
239
+ * @returns {Promise<boolean>} True if token is expired or will expire within the buffer period
240
+ */
241
+ export async function isTokenExpired(bufferSeconds = 300) {
242
+ try {
243
+ const expiresAt = await keychain.getTokenExpiresAt();
244
+ if (!expiresAt) {
245
+ log('No token expiration time found');
246
+ return true;
247
+ }
248
+ const now = Date.now();
249
+ const isExpired = now + bufferSeconds * 1000 >= expiresAt;
250
+ if (isExpired) {
251
+ log(`Token is expired or will expire soon. Expires at: ${new Date(expiresAt).toISOString()}`);
252
+ }
253
+ return isExpired;
254
+ }
255
+ catch (error) {
256
+ log('Error checking token expiration:', error);
257
+ return true;
258
+ }
259
+ }
260
+ /**
261
+ * Retrieves a valid access token for OpenZiti Controller Management API operations.
262
+ *
263
+ * This function serves as the main entry point for credential retrieval,
264
+ * ensuring that only valid, non-expired tokens are provided to API operations.
265
+ * It implements a critical security checkpoint that prevents operations from
266
+ * proceeding with invalid authentication, which could lead to API failures
267
+ * or unpredictable behavior.
268
+ *
269
+ * The function performs these key security checks:
270
+ * 1. Verifies token expiration status using isTokenExpired
271
+ * 2. Provides clear guidance to users when re-authentication is needed
272
+ * 3. Handles errors gracefully with a fail-secure approach
273
+ *
274
+ * @returns {Promise<string|null>} A valid access token, or null if no valid token is available
275
+ */
276
+ export async function getValidAccessToken() {
277
+ try {
278
+ const expired = await isTokenExpired();
279
+ if (expired) {
280
+ log('Token is expired. Please authenticate again using `npx @openziti/openziti-mcp-server init`');
281
+ return null;
282
+ }
283
+ return await keychain.getToken();
284
+ }
285
+ catch (error) {
286
+ log('Error getting valid access token:', error);
287
+ return null;
288
+ }
289
+ }
290
+ export { requestAuthorization };
291
+ //# sourceMappingURL=device-auth-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-auth-flow.js","sourceRoot":"","sources":["../../src/auth/device-auth-flow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import type { ClientOptions } from '../utils/types.js';
2
+ import type { ServerConfig, ClientConfig, ClientManager, ClientType } from './types.js';
3
+ /**
4
+ * Abstract base class providing common functionality for all supported MCP client managers.
5
+ *
6
+ * Subclasses should extend this class to handle client-specific configuration paths and custom behaviors.
7
+ */
8
+ export declare abstract class BaseClientManager implements ClientManager {
9
+ protected readonly clientType: ClientType;
10
+ readonly displayName: string;
11
+ protected readonly capabilities?: string[];
12
+ /**
13
+ * Initializes a new BaseClientManager instance.
14
+ *
15
+ * @param options - Configuration options including client type, display name, and optional capabilities.
16
+ */
17
+ constructor(options: {
18
+ clientType: ClientType;
19
+ displayName: string;
20
+ capabilities?: string[];
21
+ });
22
+ /**
23
+ * Returns the absolute path to the client's configuration file.
24
+ *
25
+ * Subclasses must implement this method to provide client-specific path resolution.
26
+ * Implementations are responsible for ensuring any necessary directories exist.
27
+ *
28
+ * @returns The resolved configuration file path.
29
+ */
30
+ abstract getConfigPath(): string;
31
+ /**
32
+ * Updates the client’s configuration with OpenZiti MCP server settings.
33
+ *
34
+ * Loads the existing configuration, applies updates for the MCP server,
35
+ * and writes the updated configuration back to disk.
36
+ *
37
+ * @param options - Client configuration options such as enabled tools and read-only mode.
38
+ */
39
+ configure(options: ClientOptions): Promise<void>;
40
+ /**
41
+ * Creates an MCP server configuration entry based on the provided client options.
42
+ *
43
+ * This method transforms the user’s options into a command, arguments,
44
+ * environment variables, and optional capabilities that the client will use to start the MCP server.
45
+ *
46
+ * Subclasses may override this method if additional customization of the server config is needed.
47
+ *
48
+ * @param options - Options controlling server configuration, such as selected tools and read-only mode.
49
+ * @returns A fully-formed ServerConfig object.
50
+ * @protected
51
+ */
52
+ protected createServerConfig(options: ClientOptions): ServerConfig;
53
+ /**
54
+ * Loads the client’s configuration from disk.
55
+ *
56
+ * Attempts to read and parse the configuration file at the given path.
57
+ * Returns a default configuration object if the file is missing or cannot be read.
58
+ *
59
+ * @param configPath - Path to the client’s configuration file.
60
+ * @returns A parsed ClientConfig object.
61
+ * @protected
62
+ */
63
+ protected readConfig(configPath: string): ClientConfig;
64
+ /**
65
+ * Writes the provided configuration object to disk.
66
+ *
67
+ * Serializes the configuration to formatted JSON and saves it at the specified path.
68
+ *
69
+ * @param configPath - Path where the configuration should be saved.
70
+ * @param config - Configuration object to serialize and write.
71
+ * @protected
72
+ */
73
+ protected writeConfig(configPath: string, config: ClientConfig): void;
74
+ }
@@ -0,0 +1,109 @@
1
+ import * as fs from 'fs';
2
+ import chalk from 'chalk';
3
+ import { log } from '../utils/logger.js';
4
+ import { cliOutput } from '../utils/terminal.js';
5
+ import { packageName } from '../utils/package.js';
6
+ import { MCP_SERVER_NAME } from '../utils/constants.js';
7
+ /**
8
+ * Abstract base class providing common functionality for all supported MCP client managers.
9
+ *
10
+ * Subclasses should extend this class to handle client-specific configuration paths and custom behaviors.
11
+ */
12
+ export class BaseClientManager {
13
+ clientType;
14
+ displayName;
15
+ capabilities;
16
+ /**
17
+ * Initializes a new BaseClientManager instance.
18
+ *
19
+ * @param options - Configuration options including client type, display name, and optional capabilities.
20
+ */
21
+ constructor(options) {
22
+ this.clientType = options.clientType;
23
+ this.displayName = options.displayName;
24
+ this.capabilities = options.capabilities;
25
+ }
26
+ /**
27
+ * Updates the client’s configuration with OpenZiti MCP server settings.
28
+ *
29
+ * Loads the existing configuration, applies updates for the MCP server,
30
+ * and writes the updated configuration back to disk.
31
+ *
32
+ * @param options - Client configuration options such as enabled tools and read-only mode.
33
+ */
34
+ async configure(options) {
35
+ const configPath = this.getConfigPath();
36
+ const config = this.readConfig(configPath);
37
+ const mcpServers = config.mcpServers || {};
38
+ const serverConfig = this.createServerConfig(options);
39
+ mcpServers[MCP_SERVER_NAME] = serverConfig;
40
+ config.mcpServers = mcpServers;
41
+ this.writeConfig(configPath, config);
42
+ log(`Updated ${this.displayName} config file at: ${configPath}`);
43
+ cliOutput(`\n${chalk.green('✓')} OpenZiti MCP server configured. ${chalk.yellow(`Restart ${this.displayName}`)} to apply changes.\n`);
44
+ }
45
+ /**
46
+ * Creates an MCP server configuration entry based on the provided client options.
47
+ *
48
+ * This method transforms the user’s options into a command, arguments,
49
+ * environment variables, and optional capabilities that the client will use to start the MCP server.
50
+ *
51
+ * Subclasses may override this method if additional customization of the server config is needed.
52
+ *
53
+ * @param options - Options controlling server configuration, such as selected tools and read-only mode.
54
+ * @returns A fully-formed ServerConfig object.
55
+ * @protected
56
+ */
57
+ createServerConfig(options) {
58
+ const args = ['-y', packageName, 'run', '--tools', `${options.tools.join(',')}`];
59
+ if (options.readOnly) {
60
+ args.push('--read-only');
61
+ }
62
+ const config = {
63
+ command: 'npx',
64
+ args,
65
+ env: {
66
+ DEBUG: 'ziti-mcp',
67
+ },
68
+ };
69
+ if (this.capabilities?.length) {
70
+ config.capabilities = this.capabilities;
71
+ }
72
+ return config;
73
+ }
74
+ /**
75
+ * Loads the client’s configuration from disk.
76
+ *
77
+ * Attempts to read and parse the configuration file at the given path.
78
+ * Returns a default configuration object if the file is missing or cannot be read.
79
+ *
80
+ * @param configPath - Path to the client’s configuration file.
81
+ * @returns A parsed ClientConfig object.
82
+ * @protected
83
+ */
84
+ readConfig(configPath) {
85
+ if (fs.existsSync(configPath)) {
86
+ try {
87
+ const data = fs.readFileSync(configPath, 'utf-8');
88
+ return JSON.parse(data);
89
+ }
90
+ catch (err) {
91
+ log(`Warning: Could not read config at ${configPath}: ${err}`);
92
+ }
93
+ }
94
+ return { mcpServers: {} };
95
+ }
96
+ /**
97
+ * Writes the provided configuration object to disk.
98
+ *
99
+ * Serializes the configuration to formatted JSON and saves it at the specified path.
100
+ *
101
+ * @param configPath - Path where the configuration should be saved.
102
+ * @param config - Configuration object to serialize and write.
103
+ * @protected
104
+ */
105
+ writeConfig(configPath, config) {
106
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
107
+ }
108
+ }
109
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/clients/base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { BaseClientManager } from './base.js';
2
+ /**
3
+ * Client manager implementation for Claude Desktop.
4
+ *
5
+ * Responsible for configuring and managing the MCP server integration
6
+ * for the Claude Desktop application.
7
+ *
8
+ * @see {@link https://claude.ai/download | Claude Desktop Download}
9
+ */
10
+ export declare class ClaudeClientManager extends BaseClientManager {
11
+ constructor();
12
+ /**
13
+ * Returns the path to the Claude Desktop configuration file.
14
+ *
15
+ * Resolves the platform-specific configuration directory,
16
+ * ensures the directory exists on disk, and constructs the full path
17
+ * to the Claude Desktop configuration file.
18
+ *
19
+ * @returns The absolute path to the configuration file.
20
+ */
21
+ getConfigPath(): string;
22
+ }