mcp-creatio 0.4.0 → 0.5.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 (215) hide show
  1. package/README.md +252 -212
  2. package/dist/cli.d.ts +5 -0
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +18 -11
  5. package/dist/cli.js.map +1 -1
  6. package/dist/creatio/auth/auth.d.ts +2 -0
  7. package/dist/creatio/auth/auth.d.ts.map +1 -1
  8. package/dist/creatio/auth/auth.js.map +1 -1
  9. package/dist/creatio/auth/providers/base-provider.d.ts +1 -0
  10. package/dist/creatio/auth/providers/base-provider.d.ts.map +1 -1
  11. package/dist/creatio/auth/providers/base-provider.js +3 -0
  12. package/dist/creatio/auth/providers/base-provider.js.map +1 -1
  13. package/dist/creatio/auth/providers/oauth2-code-provider.d.ts +3 -0
  14. package/dist/creatio/auth/providers/oauth2-code-provider.d.ts.map +1 -1
  15. package/dist/creatio/auth/providers/oauth2-code-provider.js +30 -24
  16. package/dist/creatio/auth/providers/oauth2-code-provider.js.map +1 -1
  17. package/dist/creatio/providers/configuration-provider.d.ts +3 -2
  18. package/dist/creatio/providers/configuration-provider.d.ts.map +1 -1
  19. package/dist/creatio/providers/crud-provider.d.ts +2 -0
  20. package/dist/creatio/providers/crud-provider.d.ts.map +1 -1
  21. package/dist/creatio/services/configuration-service-provider.d.ts.map +1 -1
  22. package/dist/creatio/services/configuration-service-provider.js +11 -3
  23. package/dist/creatio/services/configuration-service-provider.js.map +1 -1
  24. package/dist/creatio/services/http-client.d.ts.map +1 -1
  25. package/dist/creatio/services/http-client.js +0 -1
  26. package/dist/creatio/services/http-client.js.map +1 -1
  27. package/dist/creatio/services/metadata-store.d.ts +5 -0
  28. package/dist/creatio/services/metadata-store.d.ts.map +1 -1
  29. package/dist/creatio/services/metadata-store.js +18 -6
  30. package/dist/creatio/services/metadata-store.js.map +1 -1
  31. package/dist/creatio/services/odata-crud-provider.d.ts +3 -1
  32. package/dist/creatio/services/odata-crud-provider.d.ts.map +1 -1
  33. package/dist/creatio/services/odata-crud-provider.js +31 -8
  34. package/dist/creatio/services/odata-crud-provider.js.map +1 -1
  35. package/dist/server/http/creatio-oauth-handlers.d.ts +0 -1
  36. package/dist/server/http/creatio-oauth-handlers.d.ts.map +1 -1
  37. package/dist/server/http/creatio-oauth-handlers.js +30 -23
  38. package/dist/server/http/creatio-oauth-handlers.js.map +1 -1
  39. package/dist/server/http/httpServer.d.ts +9 -0
  40. package/dist/server/http/httpServer.d.ts.map +1 -1
  41. package/dist/server/http/httpServer.js +34 -11
  42. package/dist/server/http/httpServer.js.map +1 -1
  43. package/dist/server/http/mcp-handlers.d.ts.map +1 -1
  44. package/dist/server/http/mcp-handlers.js +4 -1
  45. package/dist/server/http/mcp-handlers.js.map +1 -1
  46. package/dist/server/http/mcp-oauth-handlers.d.ts.map +1 -1
  47. package/dist/server/http/mcp-oauth-handlers.js +18 -6
  48. package/dist/server/http/mcp-oauth-handlers.js.map +1 -1
  49. package/dist/server/http/middleware.d.ts +7 -0
  50. package/dist/server/http/middleware.d.ts.map +1 -1
  51. package/dist/server/http/middleware.js +23 -0
  52. package/dist/server/http/middleware.js.map +1 -1
  53. package/dist/server/http/rate-limiter.d.ts +24 -0
  54. package/dist/server/http/rate-limiter.d.ts.map +1 -0
  55. package/dist/server/http/rate-limiter.js +42 -0
  56. package/dist/server/http/rate-limiter.js.map +1 -0
  57. package/dist/server/mcp/creatio-rest.d.ts +44 -0
  58. package/dist/server/mcp/creatio-rest.d.ts.map +1 -0
  59. package/dist/server/mcp/creatio-rest.js +26 -0
  60. package/dist/server/mcp/creatio-rest.js.map +1 -0
  61. package/dist/server/mcp/crtmcp/crt-mcp-client.d.ts +55 -0
  62. package/dist/server/mcp/crtmcp/crt-mcp-client.d.ts.map +1 -0
  63. package/dist/server/mcp/crtmcp/crt-mcp-client.js +67 -0
  64. package/dist/server/mcp/crtmcp/crt-mcp-client.js.map +1 -0
  65. package/dist/server/mcp/crtmcp/crt-mcp-tool-preparer.d.ts +20 -0
  66. package/dist/server/mcp/crtmcp/crt-mcp-tool-preparer.d.ts.map +1 -0
  67. package/dist/server/mcp/crtmcp/crt-mcp-tool-preparer.js +74 -0
  68. package/dist/server/mcp/crtmcp/crt-mcp-tool-preparer.js.map +1 -0
  69. package/dist/server/mcp/dataforge/dataforge-client.d.ts +64 -0
  70. package/dist/server/mcp/dataforge/dataforge-client.d.ts.map +1 -0
  71. package/dist/server/mcp/dataforge/dataforge-client.js +130 -0
  72. package/dist/server/mcp/dataforge/dataforge-client.js.map +1 -0
  73. package/dist/server/mcp/dataforge/dataforge-tool-preparer.d.ts +17 -0
  74. package/dist/server/mcp/dataforge/dataforge-tool-preparer.d.ts.map +1 -0
  75. package/dist/server/mcp/dataforge/dataforge-tool-preparer.js +42 -0
  76. package/dist/server/mcp/dataforge/dataforge-tool-preparer.js.map +1 -0
  77. package/dist/server/mcp/filters.d.ts.map +1 -1
  78. package/dist/server/mcp/filters.js +20 -4
  79. package/dist/server/mcp/filters.js.map +1 -1
  80. package/dist/server/mcp/globalsearch/globalsearch-client.d.ts +50 -0
  81. package/dist/server/mcp/globalsearch/globalsearch-client.d.ts.map +1 -0
  82. package/dist/server/mcp/globalsearch/globalsearch-client.js +118 -0
  83. package/dist/server/mcp/globalsearch/globalsearch-client.js.map +1 -0
  84. package/dist/server/mcp/globalsearch/globalsearch-tool-preparer.d.ts +16 -0
  85. package/dist/server/mcp/globalsearch/globalsearch-tool-preparer.d.ts.map +1 -0
  86. package/dist/server/mcp/globalsearch/globalsearch-tool-preparer.js +34 -0
  87. package/dist/server/mcp/globalsearch/globalsearch-tool-preparer.js.map +1 -0
  88. package/dist/server/mcp/json-schema-to-zod.d.ts +3 -0
  89. package/dist/server/mcp/json-schema-to-zod.d.ts.map +1 -0
  90. package/dist/server/mcp/json-schema-to-zod.js +54 -0
  91. package/dist/server/mcp/json-schema-to-zod.js.map +1 -0
  92. package/dist/server/mcp/server.d.ts +18 -0
  93. package/dist/server/mcp/server.d.ts.map +1 -1
  94. package/dist/server/mcp/server.js +93 -25
  95. package/dist/server/mcp/server.js.map +1 -1
  96. package/dist/server/mcp/tool-preparer.d.ts +26 -0
  97. package/dist/server/mcp/tool-preparer.d.ts.map +1 -0
  98. package/dist/server/mcp/tool-preparer.js +11 -0
  99. package/dist/server/mcp/tool-preparer.js.map +1 -0
  100. package/dist/server/mcp/tools-data.d.ts +69 -10
  101. package/dist/server/mcp/tools-data.d.ts.map +1 -1
  102. package/dist/server/mcp/tools-data.js +222 -32
  103. package/dist/server/mcp/tools-data.js.map +1 -1
  104. package/dist/server/oauth/oauth-server.d.ts +0 -1
  105. package/dist/server/oauth/oauth-server.d.ts.map +1 -1
  106. package/dist/server/oauth/oauth-server.js +11 -21
  107. package/dist/server/oauth/oauth-server.js.map +1 -1
  108. package/dist/server/oauth/storage.d.ts +0 -2
  109. package/dist/server/oauth/storage.d.ts.map +1 -1
  110. package/dist/server/oauth/storage.js +0 -6
  111. package/dist/server/oauth/storage.js.map +1 -1
  112. package/dist/server/oauth/validators.d.ts +6 -0
  113. package/dist/server/oauth/validators.d.ts.map +1 -1
  114. package/dist/server/oauth/validators.js +28 -0
  115. package/dist/server/oauth/validators.js.map +1 -1
  116. package/dist/services/session-context.d.ts +8 -7
  117. package/dist/services/session-context.d.ts.map +1 -1
  118. package/dist/services/session-context.js +7 -27
  119. package/dist/services/session-context.js.map +1 -1
  120. package/package.json +18 -9
  121. package/.dockerignore +0 -12
  122. package/.editorconfig +0 -14
  123. package/.eslintrc.cjs +0 -18
  124. package/.gitattributes +0 -8
  125. package/.github/workflows/docker-publish.yml +0 -50
  126. package/.prettierignore +0 -3
  127. package/.prettierrc +0 -9
  128. package/.vscode/launch.json +0 -23
  129. package/.vscode/mcp.json +0 -13
  130. package/.vscode/settings.json +0 -16
  131. package/Agent.md +0 -190
  132. package/Debug.md +0 -32
  133. package/Dockerfile +0 -23
  134. package/docs/coding-style.md +0 -30
  135. package/eslint.config.cjs +0 -95
  136. package/src/cli.ts +0 -162
  137. package/src/config-builder.ts +0 -76
  138. package/src/consts.ts +0 -3
  139. package/src/creatio/auth/auth-manager.ts +0 -27
  140. package/src/creatio/auth/auth.ts +0 -31
  141. package/src/creatio/auth/index.ts +0 -3
  142. package/src/creatio/auth/providers/base-oauth2-provider.ts +0 -62
  143. package/src/creatio/auth/providers/base-provider.ts +0 -42
  144. package/src/creatio/auth/providers/index.ts +0 -4
  145. package/src/creatio/auth/providers/legacy-provider.ts +0 -70
  146. package/src/creatio/auth/providers/oauth2-code-provider.ts +0 -252
  147. package/src/creatio/auth/providers/oauth2-provider.ts +0 -91
  148. package/src/creatio/auth/providers/type.ts +0 -5
  149. package/src/creatio/client-config.ts +0 -34
  150. package/src/creatio/engines/admin-operation/admin-operation-engine.ts +0 -44
  151. package/src/creatio/engines/configuration/configuration-engine.ts +0 -26
  152. package/src/creatio/engines/crud/crud-engine.ts +0 -47
  153. package/src/creatio/engines/engine-manager.ts +0 -157
  154. package/src/creatio/engines/engine-registry.ts +0 -39
  155. package/src/creatio/engines/engine.ts +0 -3
  156. package/src/creatio/engines/feature/feature-engine.ts +0 -20
  157. package/src/creatio/engines/index.ts +0 -10
  158. package/src/creatio/engines/process/process-engine.ts +0 -20
  159. package/src/creatio/engines/sys-settings/sys-settings-engine.ts +0 -41
  160. package/src/creatio/engines/user/user-engine.ts +0 -20
  161. package/src/creatio/index.ts +0 -6
  162. package/src/creatio/provider-context.ts +0 -21
  163. package/src/creatio/providers/admin-operation-provider.ts +0 -34
  164. package/src/creatio/providers/configuration-provider.ts +0 -22
  165. package/src/creatio/providers/crud-provider.ts +0 -45
  166. package/src/creatio/providers/feature-provider.ts +0 -10
  167. package/src/creatio/providers/index.ts +0 -7
  168. package/src/creatio/providers/process-provider.ts +0 -15
  169. package/src/creatio/providers/sys-settings-provider.ts +0 -63
  170. package/src/creatio/providers/user-provider.ts +0 -12
  171. package/src/creatio/services/admin-operation-service-provider.ts +0 -115
  172. package/src/creatio/services/configuration-service-provider.ts +0 -127
  173. package/src/creatio/services/creatio-service-context.ts +0 -55
  174. package/src/creatio/services/feature-service-provider.ts +0 -60
  175. package/src/creatio/services/http-client.ts +0 -174
  176. package/src/creatio/services/index.ts +0 -10
  177. package/src/creatio/services/metadata-store.ts +0 -181
  178. package/src/creatio/services/odata-crud-provider.ts +0 -210
  179. package/src/creatio/services/process-service-provider.ts +0 -76
  180. package/src/creatio/services/sys-settings-service-provider.ts +0 -192
  181. package/src/creatio/services/user-info-provider.ts +0 -41
  182. package/src/index.ts +0 -44
  183. package/src/log.ts +0 -183
  184. package/src/server/http/creatio-oauth-handlers.ts +0 -146
  185. package/src/server/http/httpServer.ts +0 -150
  186. package/src/server/http/index.ts +0 -5
  187. package/src/server/http/mcp-handlers.ts +0 -92
  188. package/src/server/http/mcp-oauth-handlers.ts +0 -108
  189. package/src/server/http/middleware.ts +0 -91
  190. package/src/server/index.ts +0 -2
  191. package/src/server/mcp/filters.ts +0 -97
  192. package/src/server/mcp/index.ts +0 -1
  193. package/src/server/mcp/prompts-data.ts +0 -1292
  194. package/src/server/mcp/server.ts +0 -442
  195. package/src/server/mcp/tools-data.ts +0 -748
  196. package/src/server/oauth/client-manager.ts +0 -47
  197. package/src/server/oauth/index.ts +0 -6
  198. package/src/server/oauth/oauth-server.ts +0 -185
  199. package/src/server/oauth/storage.ts +0 -106
  200. package/src/server/oauth/token-manager.ts +0 -80
  201. package/src/server/oauth/types.ts +0 -55
  202. package/src/server/oauth/validators.ts +0 -56
  203. package/src/services/index.ts +0 -2
  204. package/src/services/session-context.ts +0 -232
  205. package/src/services/token-refresh-scheduler.ts +0 -68
  206. package/src/types/index.ts +0 -1
  207. package/src/types/network.ts +0 -7
  208. package/src/utils/context.ts +0 -49
  209. package/src/utils/env.ts +0 -12
  210. package/src/utils/index.ts +0 -5
  211. package/src/utils/mcp.ts +0 -8
  212. package/src/utils/network.ts +0 -65
  213. package/src/utils/pkce.ts +0 -39
  214. package/src/version.ts +0 -15
  215. package/tsconfig.json +0 -28
@@ -1,62 +0,0 @@
1
- import { OAuth2AuthConfig, OAuth2CodeAuthConfig } from '../../client-config';
2
- import { EXPIRES_MARGIN_SECONDS, buildHeaders } from '../auth';
3
-
4
- import { BaseProvider } from './base-provider';
5
-
6
- type OAuthConfig = OAuth2AuthConfig | OAuth2CodeAuthConfig;
7
-
8
- export abstract class BaseOAuth2Provider<
9
- T extends OAuthConfig = OAuthConfig,
10
- > extends BaseProvider<T> {
11
- protected abstract readonly authErrorCode: string;
12
-
13
- protected accessToken: string | undefined;
14
-
15
- protected accessTokenExpiryMs: number | undefined;
16
-
17
- protected abstract ensureAccessToken(force?: boolean): Promise<string | undefined>;
18
-
19
- protected computeExpiryMs(expiresInSeconds: number, minSeconds: number = 1): number {
20
- return Date.now() + Math.max(minSeconds, expiresInSeconds - EXPIRES_MARGIN_SECONDS) * 1000;
21
- }
22
-
23
- protected getIdentityBase(): string {
24
- if (this.authConfig.idBaseUrl) {
25
- let base = String(this.authConfig.idBaseUrl).replace(/\/$/, '');
26
- if (!/\/0$/.test(base)) {
27
- base = base + '/0';
28
- }
29
- return base;
30
- }
31
- let base = this.config.baseUrl.replace(/\/$/, '');
32
- if (!/\/0$/.test(base)) {
33
- base = base + '/0';
34
- }
35
- return base;
36
- }
37
-
38
- protected storageKey(userKey: string): string {
39
- const base = this.getIdentityBase();
40
- const kind = (this.config as any)?.auth?.kind ?? 'unknown';
41
- const clientId = (this.config as any)?.auth?.clientId ?? 'noclient';
42
- return `${kind}|${base}|${clientId}|${userKey}`;
43
- }
44
-
45
- protected throwNoTokenError(): void {
46
- throw new Error(this.authErrorCode);
47
- }
48
-
49
- public async getHeaders(accept: string, isJson?: boolean): Promise<Record<string, string>> {
50
- const token = await this.ensureAccessToken(false);
51
- if (!token) {
52
- this.throwNoTokenError();
53
- }
54
- return buildHeaders(accept, Boolean(isJson), token);
55
- }
56
-
57
- public async refresh(): Promise<void> {
58
- this.accessToken = undefined;
59
- this.accessTokenExpiryMs = undefined;
60
- await this.ensureAccessToken(true);
61
- }
62
- }
@@ -1,42 +0,0 @@
1
- import { CreatioClientAuthConfig, CreatioClientConfig } from '../../client-config';
2
- import { ICreatioAuthProvider } from '../auth';
3
-
4
- import { AuthProviderType } from './type';
5
-
6
- export abstract class BaseProvider<
7
- T extends CreatioClientAuthConfig = CreatioClientAuthConfig,
8
- > implements ICreatioAuthProvider {
9
- protected readonly config: CreatioClientConfig;
10
-
11
- protected get authConfig(): T {
12
- return this.config.auth as T;
13
- }
14
-
15
- public get type(): AuthProviderType {
16
- return this.authConfig.kind;
17
- }
18
-
19
- constructor(config: CreatioClientConfig) {
20
- this.config = config;
21
- }
22
-
23
- public getHeaders(accept: string, isJson?: boolean): Promise<Record<string, string>> {
24
- throw new Error('Method not implemented.');
25
- }
26
-
27
- public refresh(): Promise<void> {
28
- throw new Error('Method not implemented.');
29
- }
30
-
31
- public revoke(): Promise<void> {
32
- throw new Error('Method not implemented.');
33
- }
34
-
35
- public getAuthorizeUrl(state: string): Promise<string> {
36
- throw new Error('Method not implemented.');
37
- }
38
-
39
- public finishAuthorization(code: string): Promise<void> {
40
- throw new Error('Method not implemented.');
41
- }
42
- }
@@ -1,4 +0,0 @@
1
- export * from './legacy-provider';
2
- export * from './oauth2-provider';
3
- export * from './oauth2-code-provider';
4
- export * from './type';
@@ -1,70 +0,0 @@
1
- import log from '../../../log';
2
- import { JSON_ACCEPT } from '../../../types';
3
- import { parseSetCookie } from '../../../utils';
4
- import { LegacyAuthConfig } from '../../client-config';
5
- import { buildHeaders } from '../auth';
6
-
7
- import { BaseProvider } from './base-provider';
8
-
9
- export class LegacyProvider extends BaseProvider<LegacyAuthConfig> {
10
- private _bpmCsrf: string | undefined;
11
-
12
- private _cookieHeader: string | undefined;
13
-
14
- private async _ensureSession() {
15
- if (this._cookieHeader) {
16
- return;
17
- }
18
- const url = `${this.config.baseUrl.replace(/\/$/, '')}/ServiceModel/AuthService.svc/Login`;
19
- const body = JSON.stringify({
20
- UserName: this.authConfig.login,
21
- UserPassword: this.authConfig.password,
22
- });
23
- log.creatioAuthStart(this.config.baseUrl, 'legacy');
24
- const res = await fetch(url, {
25
- method: 'POST',
26
- headers: buildHeaders(JSON_ACCEPT, true),
27
- body,
28
- redirect: 'manual',
29
- });
30
- if (!res.ok) {
31
- const responseText = await res.text().catch(() => '');
32
- log.creatioAuthFailed(this.config.baseUrl, `${res.status} ${responseText}`, 'legacy');
33
- throw new Error(`auth_failed:${res.status} ${responseText}`);
34
- }
35
- log.creatioAuthOk(this.config.baseUrl, 'legacy');
36
- let setCookie: string[] = [];
37
- if (typeof (res.headers as any).getSetCookie === 'function') {
38
- setCookie = (res.headers as any).getSetCookie();
39
- } else if ((res.headers as any).raw && (res.headers as any).raw()['set-cookie']) {
40
- setCookie = (res.headers as any).raw()['set-cookie'];
41
- } else {
42
- setCookie = [];
43
- }
44
- const pairs = parseSetCookie(setCookie);
45
- if (!pairs.length) {
46
- throw new Error('auth_failed:no_set_cookie');
47
- }
48
- this._cookieHeader = pairs.map((c) => `${c.name}=${c.value}`).join('; ');
49
- const csrf = pairs.find((c) => c.name.toUpperCase() === 'BPMCSRF')?.value;
50
- if (csrf) {
51
- this._bpmCsrf = csrf;
52
- }
53
- }
54
-
55
- public async getHeaders(accept: string, isJson?: boolean): Promise<Record<string, string>> {
56
- await this._ensureSession();
57
- const h = buildHeaders(accept, Boolean(isJson));
58
- h['ForceUseSession'] = 'true';
59
- h['Cookie'] = this._cookieHeader!;
60
- if (this._bpmCsrf) {
61
- h['BPMCSRF'] = this._bpmCsrf;
62
- }
63
- return h;
64
- }
65
-
66
- public async refresh(): Promise<void> {
67
- this._cookieHeader = undefined;
68
- await this._ensureSession();
69
- }
70
- }
@@ -1,252 +0,0 @@
1
- import { HTTP_MCP_PORT } from '../../../consts';
2
- import log from '../../../log';
3
- import { SessionContext, TokenRefreshScheduler, type UserTokens } from '../../../services';
4
- import { getEffectiveUserKey, getUserKey } from '../../../utils';
5
- import { CreatioClientConfig, OAuth2CodeAuthConfig } from '../../client-config';
6
- import { AUTHORIZE_ENDPOINT, REVOCATION_ENDPOINT, TOKEN_ENDPOINT } from '../auth';
7
-
8
- import { BaseOAuth2Provider } from './base-oauth2-provider';
9
-
10
- export class OAuth2CodeProvider extends BaseOAuth2Provider<OAuth2CodeAuthConfig> {
11
- private readonly _sessionContext = SessionContext.instance;
12
- private readonly _tokenRefreshScheduler = new TokenRefreshScheduler();
13
-
14
- protected readonly authErrorCode = 'oauth2_code_need_consent';
15
-
16
- private get _scope() {
17
- return this.authConfig.scope || 'offline_access';
18
- }
19
-
20
- constructor(config: CreatioClientConfig) {
21
- super(config);
22
- this._tokenRefreshScheduler.setRefreshCallback(this.refreshUserTokens.bind(this));
23
- }
24
-
25
- private async _exchangeCodeForTokens(code: string): Promise<UserTokens> {
26
- const idBase = this.getIdentityBase();
27
- const url = idBase + TOKEN_ENDPOINT;
28
- const body = new URLSearchParams();
29
- body.set('grant_type', 'authorization_code');
30
- body.set('client_id', this.authConfig.clientId);
31
- if (this.authConfig.clientSecret) {
32
- body.set('client_secret', this.authConfig.clientSecret);
33
- }
34
- body.set('code', code);
35
- body.set('redirect_uri', this.authConfig.redirectUri);
36
- body.set('scope', this._scope);
37
- log.creatioAuthStart(this.config.baseUrl, 'oauth2_code');
38
- const res = await fetch(url, {
39
- method: 'POST',
40
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
41
- body: body.toString(),
42
- });
43
- const txt = await res.text().catch(() => '');
44
- if (!res.ok || !txt) {
45
- log.creatioAuthFailed(this.config.baseUrl, `token:${res.status} ${txt}`, 'oauth2_code');
46
- throw new Error(`oauth2_code_token_error:${res.status}`);
47
- }
48
- let j: any;
49
- try {
50
- j = JSON.parse(txt);
51
- } catch {
52
- log.creatioAuthFailed(this.config.baseUrl, 'token_parse_failed', 'oauth2_code');
53
- throw new Error('oauth2_code_token_parse_failed');
54
- }
55
- if (!j.access_token) {
56
- throw new Error('oauth2_code_no_access_token');
57
- }
58
- const expiresIn = Number(j.expires_in) || 180;
59
- const accessTokenExpiryMs = this.computeExpiryMs(expiresIn, 1);
60
- log.creatioAuthOk(this.config.baseUrl, 'oauth2_code');
61
- return {
62
- accessToken: String(j.access_token),
63
- accessTokenExpiryMs,
64
- refreshToken: j.refresh_token ? String(j.refresh_token) : undefined,
65
- };
66
- }
67
-
68
- private async _refreshTokens(refreshToken: string): Promise<UserTokens> {
69
- const idBase = this.getIdentityBase();
70
- const url = idBase + TOKEN_ENDPOINT;
71
- log.info('oauth2_code.refresh_attempt', { url, refreshTokenLength: refreshToken.length });
72
- const body = new URLSearchParams();
73
- body.set('grant_type', 'refresh_token');
74
- body.set('client_id', this.authConfig.clientId);
75
- if (this.authConfig.clientSecret) {
76
- body.set('client_secret', this.authConfig.clientSecret);
77
- }
78
- body.set('refresh_token', refreshToken);
79
- body.set('redirect_uri', this.authConfig.redirectUri);
80
- body.set('scope', this._scope);
81
- const res = await fetch(url, {
82
- method: 'POST',
83
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
84
- body: body.toString(),
85
- });
86
- const txt = await res.text().catch(() => '');
87
- log.info('oauth2_code.refresh_response', {
88
- status: res.status,
89
- hasBody: !!txt,
90
- bodyLength: txt.length,
91
- });
92
- if (!res.ok || !txt) {
93
- log.error('oauth2_code.refresh_failed', {
94
- status: res.status,
95
- body: txt.substring(0, 200),
96
- });
97
- throw new Error(`oauth2_code_refresh_error:${res.status}`);
98
- }
99
- let j: any;
100
- try {
101
- j = JSON.parse(txt);
102
- } catch {
103
- throw new Error('oauth2_code_refresh_parse_failed');
104
- }
105
- if (!j.access_token) {
106
- throw new Error('oauth2_code_refresh_no_access_token');
107
- }
108
- const expiresIn = Number(j.expires_in) || 180;
109
- const accessTokenExpiryMs = this.computeExpiryMs(expiresIn, 1);
110
- const newTokens = {
111
- accessToken: String(j.access_token),
112
- accessTokenExpiryMs,
113
- refreshToken: j.refresh_token ? String(j.refresh_token) : refreshToken,
114
- };
115
- log.info('oauth2_code.refresh_success', {
116
- hasNewRefreshToken: !!j.refresh_token,
117
- expiresIn,
118
- accessTokenLength: newTokens.accessToken.length,
119
- });
120
- return newTokens;
121
- }
122
-
123
- protected throwNoTokenError(): void {
124
- const userKey = getEffectiveUserKey();
125
- const errorMessage = userKey
126
- ? `${this.authErrorCode}:http://localhost:${HTTP_MCP_PORT}/oauth/start?userKey=${encodeURIComponent(userKey)}`
127
- : this.authErrorCode;
128
- throw new Error(errorMessage);
129
- }
130
-
131
- protected async ensureAccessToken(force = false): Promise<string | undefined> {
132
- log.info('oauth2_code.ensure_access_token.start', { force });
133
- const now = Date.now();
134
- if (
135
- !force &&
136
- this.accessToken &&
137
- this.accessTokenExpiryMs &&
138
- now < this.accessTokenExpiryMs
139
- ) {
140
- return this.accessToken;
141
- }
142
- const userKey = getEffectiveUserKey();
143
- if (!userKey) {
144
- log.warn('oauth2_code.no_user_key');
145
- return undefined;
146
- }
147
- const saved = await this._sessionContext.getTokensForUser(userKey);
148
- if (!saved) {
149
- log.warn('oauth2_code.no_saved_tokens', { userKey });
150
- return undefined;
151
- }
152
- if (
153
- !force &&
154
- saved.accessToken &&
155
- saved.accessTokenExpiryMs &&
156
- now < saved.accessTokenExpiryMs
157
- ) {
158
- this.accessToken = saved.accessToken;
159
- this.accessTokenExpiryMs = saved.accessTokenExpiryMs;
160
- return this.accessToken;
161
- }
162
- if (saved.refreshToken) {
163
- const updated = await this._refreshTokens(saved.refreshToken);
164
- await this._sessionContext.setTokensForUser(userKey, updated);
165
- this.accessToken = updated.accessToken;
166
- this.accessTokenExpiryMs = updated.accessTokenExpiryMs;
167
- return this.accessToken;
168
- }
169
- await this._sessionContext.deleteTokensForUser(userKey);
170
- return undefined;
171
- }
172
-
173
- public async finishAuthorization(code: string): Promise<void> {
174
- const userKey = getEffectiveUserKey();
175
- log.info('oauth2_code.finish_authorization', { userKey, hasCode: !!code });
176
- if (!userKey) {
177
- throw new Error('oauth2_code_missing_user');
178
- }
179
- const tokens = await this._exchangeCodeForTokens(code);
180
- await this._sessionContext.setTokensForUser(userKey, tokens);
181
- this.accessToken = tokens.accessToken;
182
- this.accessTokenExpiryMs = tokens.accessTokenExpiryMs;
183
- this._tokenRefreshScheduler.scheduleRefresh(userKey);
184
- log.info('oauth2_code.authorization_complete', { userKey });
185
- }
186
-
187
- public async getAuthorizeUrl(state: string): Promise<string> {
188
- const idBase = this.getIdentityBase();
189
- const u = new URL(idBase + AUTHORIZE_ENDPOINT);
190
- u.searchParams.set('client_id', this.authConfig.clientId);
191
- u.searchParams.set('redirect_uri', this.authConfig.redirectUri);
192
- u.searchParams.set('response_type', 'code');
193
- u.searchParams.set('state', state);
194
- const scopeParam = encodeURIComponent(this._scope);
195
- u.search += '&scope=' + scopeParam;
196
- log.info('oauth2_code.authorize_url', {
197
- idBase,
198
- url: u.toString(),
199
- });
200
- return u.toString();
201
- }
202
-
203
- public async revoke(): Promise<void> {
204
- try {
205
- const userKey = getUserKey();
206
- if (!userKey) {
207
- return;
208
- }
209
- const saved = await this._sessionContext.getTokensForUser(userKey);
210
- if (!saved?.refreshToken) {
211
- await this._sessionContext.deleteTokensForUser(userKey);
212
- return;
213
- }
214
- const idBase = this.getIdentityBase();
215
- const url = idBase + REVOCATION_ENDPOINT;
216
- const body = new URLSearchParams();
217
- body.set('client_id', this.authConfig.clientId);
218
- if (this.authConfig.clientSecret) {
219
- body.set('client_secret', this.authConfig.clientSecret);
220
- }
221
- body.set('token', saved.refreshToken);
222
- body.set('token_type_hint', 'refresh_token');
223
- const res = await fetch(url, {
224
- method: 'POST',
225
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
226
- body: body.toString(),
227
- });
228
- if (!res.ok) {
229
- const t = await res.text().catch(() => '');
230
- log.error('oauth2_code.revoke_failed', { status: res.status, t });
231
- }
232
- } finally {
233
- const userKey = getUserKey();
234
- if (userKey) {
235
- await this._sessionContext.deleteTokensForUser(userKey);
236
- this._tokenRefreshScheduler.cancelRefresh(userKey);
237
- }
238
- this.accessToken = undefined;
239
- this.accessTokenExpiryMs = undefined;
240
- }
241
- }
242
-
243
- public async refreshUserTokens(userKey: string): Promise<void> {
244
- const saved = await this._sessionContext.getTokensForUser(userKey);
245
- if (!saved?.refreshToken) {
246
- throw new Error('oauth2_no_refresh_token');
247
- }
248
- const updated = await this._refreshTokens(saved.refreshToken);
249
- await this._sessionContext.setTokensForUser(userKey, updated);
250
- log.info('oauth2_code.background_refresh_success', { userKey });
251
- }
252
- }
@@ -1,91 +0,0 @@
1
- import log from '../../../log';
2
- import { CreatioClientConfig, OAuth2AuthConfig } from '../../client-config';
3
- import { TOKEN_BODY_SNIPPET_MAX, TOKEN_ENDPOINT } from '../auth';
4
-
5
- import { BaseOAuth2Provider } from './base-oauth2-provider';
6
-
7
- export class OAuth2Provider extends BaseOAuth2Provider<OAuth2AuthConfig> {
8
- private readonly _config: CreatioClientConfig;
9
-
10
- protected readonly authErrorCode = 'oauth2_auth_failed';
11
-
12
- constructor(config: CreatioClientConfig) {
13
- super(config);
14
- this._config = config;
15
- }
16
-
17
- protected async ensureAccessToken(): Promise<string | undefined> {
18
- const now = Date.now();
19
- if (this.accessToken && this.accessTokenExpiryMs && now < this.accessTokenExpiryMs) {
20
- return this.accessToken;
21
- }
22
- const url = `${this.getIdentityBase()}${TOKEN_ENDPOINT}`;
23
- const body = new URLSearchParams();
24
- body.set('grant_type', 'client_credentials');
25
- body.set('client_id', this.authConfig.clientId);
26
- body.set('client_secret', this.authConfig.clientSecret);
27
- try {
28
- log.creatioAuthStart(this._config.baseUrl, 'oauth2');
29
- const response = await fetch(url, {
30
- method: 'POST',
31
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
32
- body: body.toString(),
33
- });
34
- const responseText = await response.text().catch(() => '');
35
- const contentType = (response.headers as any)?.get?.('content-type') ?? '';
36
- const bodySnippet =
37
- responseText && responseText.length > TOKEN_BODY_SNIPPET_MAX
38
- ? responseText.slice(0, TOKEN_BODY_SNIPPET_MAX) + '\n... [truncated]'
39
- : responseText;
40
- if (!response.ok) {
41
- log.error('oauth.token.error', {
42
- url,
43
- status: response.status,
44
- contentType,
45
- bodySnippet,
46
- });
47
- log.creatioAuthFailed(
48
- this._config.baseUrl,
49
- `token_error:${response.status}`,
50
- 'oauth2',
51
- );
52
- throw new Error(`oauth2_token_error:${response.status}`);
53
- }
54
- if (!responseText) {
55
- log.error('oauth.token.empty_body', { url, status: response.status, contentType });
56
- log.creatioAuthFailed(this._config.baseUrl, 'empty_response_body', 'oauth2');
57
- throw new Error('oauth2_empty_token_response');
58
- }
59
- let tokenResponse: any = null;
60
- try {
61
- tokenResponse = JSON.parse(responseText);
62
- } catch (err) {
63
- log.error('oauth.token.parse_failed', {
64
- url,
65
- status: response.status,
66
- contentType,
67
- bodySnippet,
68
- });
69
- log.creatioAuthFailed(this._config.baseUrl, 'token_parse_failed', 'oauth2');
70
- throw new Error('oauth2_token_parse_failed');
71
- }
72
- if (!tokenResponse || !tokenResponse.access_token) {
73
- log.creatioAuthFailed(
74
- this._config.baseUrl,
75
- 'no_access_token_in_response',
76
- 'oauth2',
77
- );
78
- throw new Error('oauth2_no_access_token');
79
- }
80
- this.accessToken = String(tokenResponse.access_token);
81
- const expiresIn = Number(tokenResponse.expires_in) || 3600;
82
- this.accessTokenExpiryMs = this.computeExpiryMs(expiresIn, 1);
83
- log.creatioAuthOk(this._config.baseUrl, 'oauth2');
84
- return this.accessToken;
85
- } catch (e: any) {
86
- log.error('oauth.token.exception', { error: String(e?.message ?? e) });
87
- log.creatioAuthFailed(this._config.baseUrl, String(e?.message ?? e), 'oauth2');
88
- return undefined;
89
- }
90
- }
91
- }
@@ -1,5 +0,0 @@
1
- export enum AuthProviderType {
2
- Legacy = 'legacy',
3
- OAuth2 = 'oauth2',
4
- OAuth2Code = 'oauth2_code',
5
- }
@@ -1,34 +0,0 @@
1
- import { AuthProviderType } from './auth/providers';
2
-
3
- interface ICreatioAuthConfig {
4
- kind: AuthProviderType;
5
- }
6
-
7
- export interface LegacyAuthConfig extends ICreatioAuthConfig {
8
- kind: AuthProviderType.Legacy;
9
- login: string;
10
- password: string;
11
- }
12
-
13
- interface BaseOAuthConfig extends ICreatioAuthConfig {
14
- clientId: string;
15
- clientSecret: string;
16
- scope?: string;
17
- idBaseUrl?: string;
18
- }
19
-
20
- export interface OAuth2AuthConfig extends BaseOAuthConfig {
21
- kind: AuthProviderType.OAuth2;
22
- }
23
-
24
- export interface OAuth2CodeAuthConfig extends BaseOAuthConfig {
25
- kind: AuthProviderType.OAuth2Code;
26
- redirectUri: string;
27
- }
28
-
29
- export type CreatioClientAuthConfig = LegacyAuthConfig | OAuth2AuthConfig | OAuth2CodeAuthConfig;
30
-
31
- export interface CreatioClientConfig {
32
- baseUrl: string;
33
- auth: CreatioClientAuthConfig;
34
- }
@@ -1,44 +0,0 @@
1
- import {
2
- AdminOperationProvider,
3
- AdminOperationServiceResult,
4
- SetAdminOperationGranteeRequest,
5
- UpsertAdminOperationRequest,
6
- UpsertAdminOperationResult,
7
- } from '../../providers';
8
- import { CreatioEngine } from '../engine';
9
-
10
- export class AdminOperationEngine implements CreatioEngine {
11
- private readonly _provider: AdminOperationProvider;
12
-
13
- public readonly name = 'admin-operation';
14
-
15
- constructor(provider: AdminOperationProvider) {
16
- this._provider = provider;
17
- }
18
-
19
- public get kind(): string {
20
- return this._provider.kind;
21
- }
22
-
23
- public upsertAdminOperation(
24
- request: UpsertAdminOperationRequest,
25
- ): Promise<UpsertAdminOperationResult> {
26
- return this._provider.upsertAdminOperation(request);
27
- }
28
-
29
- public deleteAdminOperation(recordIds: string[]): Promise<AdminOperationServiceResult> {
30
- return this._provider.deleteAdminOperation(recordIds);
31
- }
32
-
33
- public setAdminOperationGrantee(
34
- request: SetAdminOperationGranteeRequest,
35
- ): Promise<AdminOperationServiceResult> {
36
- return this._provider.setAdminOperationGrantee(request);
37
- }
38
-
39
- public deleteAdminOperationGrantee(
40
- recordIds: string[],
41
- ): Promise<AdminOperationServiceResult> {
42
- return this._provider.deleteAdminOperationGrantee(recordIds);
43
- }
44
- }
@@ -1,26 +0,0 @@
1
- import {
2
- CallConfigurationServiceRequest,
3
- CallConfigurationServiceResult,
4
- ConfigurationProvider,
5
- } from '../../providers';
6
- import { CreatioEngine } from '../engine';
7
-
8
- export class ConfigurationEngine implements CreatioEngine {
9
- private readonly _provider: ConfigurationProvider;
10
-
11
- public readonly name = 'configuration';
12
-
13
- constructor(provider: ConfigurationProvider) {
14
- this._provider = provider;
15
- }
16
-
17
- public get kind(): string {
18
- return this._provider.kind;
19
- }
20
-
21
- public call(
22
- request: CallConfigurationServiceRequest,
23
- ): Promise<CallConfigurationServiceResult> {
24
- return this._provider.call(request);
25
- }
26
- }
@@ -1,47 +0,0 @@
1
- import {
2
- CrudDeleteParams,
3
- CrudProvider,
4
- CrudReadParams,
5
- CrudUpdateParams,
6
- CrudWriteParams,
7
- EntitySchemaDescription,
8
- } from '../../providers';
9
- import { CreatioEngine } from '../engine';
10
-
11
- export class CrudEngine implements CreatioEngine {
12
- private readonly _provider: CrudProvider;
13
-
14
- public readonly name = 'crud';
15
-
16
- constructor(provider: CrudProvider) {
17
- this._provider = provider;
18
- }
19
-
20
- public get kind(): string {
21
- return this._provider.kind;
22
- }
23
-
24
- public listEntitySets(): Promise<string[]> {
25
- return this._provider.listEntitySets();
26
- }
27
-
28
- public describeEntity(entitySet: string): Promise<EntitySchemaDescription> {
29
- return this._provider.describeEntity(entitySet);
30
- }
31
-
32
- public read(params: CrudReadParams): Promise<any> {
33
- return this._provider.read(params);
34
- }
35
-
36
- public create(params: CrudWriteParams): Promise<any> {
37
- return this._provider.create(params);
38
- }
39
-
40
- public update(params: CrudUpdateParams): Promise<any> {
41
- return this._provider.update(params);
42
- }
43
-
44
- public delete(params: CrudDeleteParams): Promise<any> {
45
- return this._provider.delete(params);
46
- }
47
- }