@countfinancial/cli 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +5 -28
  2. package/dist/__tests__/localCallbackServer.test.js +20 -0
  3. package/dist/__tests__/localCallbackServer.test.js.map +1 -1
  4. package/dist/__tests__/mcpLauncher.test.d.ts +1 -0
  5. package/dist/__tests__/mcpLauncher.test.js +40 -0
  6. package/dist/__tests__/mcpLauncher.test.js.map +1 -0
  7. package/dist/commands/mcp.command.js +1 -3
  8. package/dist/commands/mcp.command.js.map +1 -1
  9. package/dist/constants.d.ts +1 -0
  10. package/dist/constants.js +6 -0
  11. package/dist/constants.js.map +1 -1
  12. package/dist/index.js +2 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/partner-mcp/config.d.ts +6 -0
  15. package/dist/partner-mcp/config.js +25 -0
  16. package/dist/partner-mcp/config.js.map +1 -0
  17. package/dist/partner-mcp/index.d.ts +2 -0
  18. package/dist/partner-mcp/index.js +17 -0
  19. package/dist/partner-mcp/index.js.map +1 -0
  20. package/dist/partner-mcp/partnerApiClient.d.ts +34 -0
  21. package/dist/partner-mcp/partnerApiClient.js +233 -0
  22. package/dist/partner-mcp/partnerApiClient.js.map +1 -0
  23. package/dist/partner-mcp/resources/registerResources.d.ts +8 -0
  24. package/dist/partner-mcp/resources/registerResources.js +70 -0
  25. package/dist/partner-mcp/resources/registerResources.js.map +1 -0
  26. package/dist/partner-mcp/server.d.ts +7 -0
  27. package/dist/partner-mcp/server.js +17 -0
  28. package/dist/partner-mcp/server.js.map +1 -0
  29. package/dist/partner-mcp/signing.d.ts +22 -0
  30. package/dist/partner-mcp/signing.js +20 -0
  31. package/dist/partner-mcp/signing.js.map +1 -0
  32. package/dist/partner-mcp/tokenPersistence.d.ts +7 -0
  33. package/dist/partner-mcp/tokenPersistence.js +19 -0
  34. package/dist/partner-mcp/tokenPersistence.js.map +1 -0
  35. package/dist/partner-mcp/tools/definitions.d.ts +7 -0
  36. package/dist/partner-mcp/tools/definitions.js +1158 -0
  37. package/dist/partner-mcp/tools/definitions.js.map +1 -0
  38. package/dist/partner-mcp/tools/registerTools.d.ts +8 -0
  39. package/dist/partner-mcp/tools/registerTools.js +173 -0
  40. package/dist/partner-mcp/tools/registerTools.js.map +1 -0
  41. package/dist/partner-mcp/tools/schemas.d.ts +32 -0
  42. package/dist/partner-mcp/tools/schemas.js +47 -0
  43. package/dist/partner-mcp/tools/schemas.js.map +1 -0
  44. package/dist/partner-mcp/types.d.ts +48 -0
  45. package/dist/partner-mcp/types.js +2 -0
  46. package/dist/partner-mcp/types.js.map +1 -0
  47. package/dist/services/localCallbackServer.service.js +41 -15
  48. package/dist/services/localCallbackServer.service.js.map +1 -1
  49. package/dist/services/mcpLauncher.service.d.ts +2 -4
  50. package/dist/services/mcpLauncher.service.js +12 -16
  51. package/dist/services/mcpLauncher.service.js.map +1 -1
  52. package/dist/services/oauthLogin.service.js +3 -1
  53. package/dist/services/oauthLogin.service.js.map +1 -1
  54. package/package.json +4 -3
package/README.md CHANGED
@@ -1,36 +1,13 @@
1
- # COUNT CLI (`@count/cli`)
1
+ # COUNT CLI (`@countfinancial/cli`)
2
2
 
3
3
  Command-line tool for partner integrations that need **low-friction OAuth login** and a **local MCP server** for Claude Code, Cursor, and other agent runtimes.
4
4
 
5
- ## Install
6
-
7
- When `@count/partner-mcp` is published to npm:
8
-
9
- ```bash
10
- npm install
11
- npm run build
12
- npm link
13
- ```
5
+ The MCP server is bundled inside this package — no separate npm install required.
14
6
 
15
- Until then, link `@count/partner-mcp` from the [count-api](https://github.com/NotAllTalk/count-api) monorepo:
16
-
17
- ```bash
18
- cd /path/to/count-api
19
- npm install
20
- npm run mcp:count:build
21
- npm link --workspace @count/partner-mcp
22
-
23
- cd /path/to/count-cli
24
- npm link @count/partner-mcp
25
- npm install
26
- npm run build
27
- npm link
28
- ```
29
-
30
- When published to npm:
7
+ ## Install
31
8
 
32
9
  ```bash
33
- npm install -g @count/cli
10
+ npm install -g @countfinancial/cli
34
11
  ```
35
12
 
36
13
  ## Quick start
@@ -79,7 +56,7 @@ count mcp print-config
79
56
  | `count login` | Browser OAuth login + token storage |
80
57
  | `count logout` | Delete `~/.count/credentials.json` |
81
58
  | `count status` | Show whether credentials/tokens are present |
82
- | `count mcp` | Start the local `@count/partner-mcp` stdio server |
59
+ | `count mcp` | Start the local COUNT Partner MCP stdio server |
83
60
  | `count mcp print-config` | Emit MCP JSON for Claude Code / Cursor |
84
61
 
85
62
  ## Environment
@@ -27,6 +27,26 @@ describe('localCallbackServer', () => {
27
27
  await callbackServer.close();
28
28
  }
29
29
  });
30
+ it('closes quickly after a successful callback even when close is called twice', async () => {
31
+ const callbackServer = await startLocalCallbackServer({
32
+ host: '127.0.0.1',
33
+ port: 0,
34
+ callbackPath: '/callback',
35
+ expectedState: 'expected-state',
36
+ timeoutMs: 5000,
37
+ });
38
+ const waitPromise = callbackServer.waitForCallback();
39
+ const callbackUrl = new URL(callbackServer.redirectUri);
40
+ callbackUrl.searchParams.set('code', 'auth-code');
41
+ callbackUrl.searchParams.set('state', 'expected-state');
42
+ await fetch(callbackUrl.toString());
43
+ await waitPromise;
44
+ const closeStartedAt = Date.now();
45
+ await callbackServer.close();
46
+ await callbackServer.close();
47
+ const closeDurationMs = Date.now() - closeStartedAt;
48
+ assert.ok(closeDurationMs < 1000, `expected close to finish quickly, took ${closeDurationMs}ms`);
49
+ });
30
50
  it('ignores a malformed callback before accepting a valid redirect', async () => {
31
51
  const callbackServer = await startLocalCallbackServer({
32
52
  host: '127.0.0.1',
@@ -1 +1 @@
1
- {"version":3,"file":"localCallbackServer.test.js","sourceRoot":"","sources":["../../src/__tests__/localCallbackServer.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"localCallbackServer.test.js","sourceRoot":"","sources":["../../src/__tests__/localCallbackServer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,40 @@
1
+ import assert from 'node:assert/strict';
2
+ import fs from 'node:fs/promises';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { describe, it } from 'node:test';
6
+ import { buildClaudeCodeMcpConfig, resolveCliEntryPath } from '../services/mcpLauncher.service.js';
7
+ import * as tokenPersistence from '../partner-mcp/tokenPersistence.js';
8
+ describe('mcpLauncher', () => {
9
+ it('builds MCP config that delegates to the CLI without embedding secrets', () => {
10
+ const configuration = buildClaudeCodeMcpConfig();
11
+ const countServerConfiguration = configuration.mcpServers.count;
12
+ assert.equal(countServerConfiguration.command, process.execPath);
13
+ assert.deepEqual(countServerConfiguration.args, [resolveCliEntryPath(), 'mcp']);
14
+ assert.equal(countServerConfiguration.env, undefined);
15
+ });
16
+ });
17
+ describe('tokenPersistence', () => {
18
+ it('updates access and refresh tokens in the credentials file', async () => {
19
+ const temporaryHomeDirectory = await fs.mkdtemp(path.join(os.tmpdir(), 'count-cli-token-home-'));
20
+ const credentialsFilePath = path.join(temporaryHomeDirectory, 'credentials.json');
21
+ await fs.writeFile(credentialsFilePath, `${JSON.stringify({
22
+ apiBaseUrl: 'https://api.getcount.com',
23
+ clientId: 'client-id',
24
+ clientSecret: 'client-secret',
25
+ accessToken: 'old-access-token',
26
+ refreshToken: 'old-refresh-token',
27
+ requestTimeoutMs: 30000,
28
+ }, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
29
+ await tokenPersistence.persistRefreshedTokens({
30
+ credentialsFilePath,
31
+ accessToken: 'new-access-token',
32
+ refreshToken: 'new-refresh-token',
33
+ });
34
+ const reloadedCredentials = JSON.parse(await fs.readFile(credentialsFilePath, 'utf8'));
35
+ assert.equal(reloadedCredentials.accessToken, 'new-access-token');
36
+ assert.equal(reloadedCredentials.refreshToken, 'new-refresh-token');
37
+ assert.equal(reloadedCredentials.clientId, 'client-id');
38
+ });
39
+ });
40
+ //# sourceMappingURL=mcpLauncher.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpLauncher.test.js","sourceRoot":"","sources":["../../src/__tests__/mcpLauncher.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACnG,OAAO,KAAK,gBAAgB,MAAM,oCAAoC,CAAC;AAEvE,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAC/E,MAAM,aAAa,GAAG,wBAAwB,EAAE,CAAC;QACjD,MAAM,wBAAwB,GAAI,aAAa,CAAC,UAAsD,CAAC,KAAK,CAAC;QAE7G,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjE,MAAM,CAAC,SAAS,CAAC,wBAAwB,CAAC,IAAI,EAAE,CAAC,mBAAmB,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;QAChF,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,sBAAsB,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,uBAAuB,CAAC,CAAC,CAAC;QACjG,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,sBAAsB,EAAE,kBAAkB,CAAC,CAAC;QAClF,MAAM,EAAE,CAAC,SAAS,CAChB,mBAAmB,EACnB,GAAG,IAAI,CAAC,SAAS,CACf;YACE,UAAU,EAAE,0BAA0B;YACtC,QAAQ,EAAE,WAAW;YACrB,YAAY,EAAE,eAAe;YAC7B,WAAW,EAAE,kBAAkB;YAC/B,YAAY,EAAE,mBAAmB;YACjC,gBAAgB,EAAE,KAAK;SACxB,EACD,IAAI,EACJ,CAAC,CACF,IAAI,EACL,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAClC,CAAC;QAEF,MAAM,gBAAgB,CAAC,sBAAsB,CAAC;YAC5C,mBAAmB;YACnB,WAAW,EAAE,kBAAkB;YAC/B,YAAY,EAAE,mBAAmB;SAClC,CAAC,CAAC;QAEH,MAAM,mBAAmB,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAIpF,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;QAClE,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,YAAY,EAAE,mBAAmB,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -15,9 +15,7 @@ export async function runMcpStartCommand() {
15
15
  process.exit(exitCode);
16
16
  }
17
17
  export async function runMcpPrintConfigCommand() {
18
- const credentials = await loadCredentials();
19
- assertLoggedInCredentials(credentials);
20
- const configuration = buildClaudeCodeMcpConfig({ credentials });
18
+ const configuration = buildClaudeCodeMcpConfig();
21
19
  process.stdout.write(`${JSON.stringify(configuration, null, 2)}\n`);
22
20
  }
23
21
  //# sourceMappingURL=mcp.command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.command.js","sourceRoot":"","sources":["../../src/commands/mcp.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AACtG,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAEzE,SAAS,yBAAyB,CAChC,WAAwD;IAExD,IAAI,CAAC,WAAW,EAAE,QAAQ,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;IAED,IAAI,CAAC,WAAW,CAAC,WAAW,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,WAAW,GAAG,MAAM,eAAe,EAAE,CAAC;IAC5C,yBAAyB,CAAC,WAAW,CAAC,CAAC;IAEvC,MAAM,QAAQ,GAAG,MAAM,sBAAsB,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IAC/D,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB;IAC5C,MAAM,WAAW,GAAG,MAAM,eAAe,EAAE,CAAC;IAC5C,yBAAyB,CAAC,WAAW,CAAC,CAAC;IAEvC,MAAM,aAAa,GAAG,wBAAwB,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC"}
1
+ {"version":3,"file":"mcp.command.js","sourceRoot":"","sources":["../../src/commands/mcp.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AACtG,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAEzE,SAAS,yBAAyB,CAChC,WAAwD;IAExD,IAAI,CAAC,WAAW,EAAE,QAAQ,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;IAED,IAAI,CAAC,WAAW,CAAC,WAAW,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,WAAW,GAAG,MAAM,eAAe,EAAE,CAAC;IAC5C,yBAAyB,CAAC,WAAW,CAAC,CAAC;IAEvC,MAAM,QAAQ,GAAG,MAAM,sBAAsB,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IAC/D,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB;IAC5C,MAAM,aAAa,GAAG,wBAAwB,EAAE,CAAC;IACjD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC"}
@@ -1,3 +1,4 @@
1
+ export declare const CLI_VERSION: string;
1
2
  export declare const DEFAULT_API_BASE_URL = "https://api.getcount.com";
2
3
  export declare const DEFAULT_CALLBACK_HOST = "127.0.0.1";
3
4
  export declare const DEFAULT_CALLBACK_PORT = 17845;
package/dist/constants.js CHANGED
@@ -1,3 +1,9 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ const packageJsonPath = path.join(path.dirname(fileURLToPath(import.meta.url)), '../package.json');
5
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
6
+ export const CLI_VERSION = packageJson.version;
1
7
  export const DEFAULT_API_BASE_URL = 'https://api.getcount.com';
2
8
  export const DEFAULT_CALLBACK_HOST = '127.0.0.1';
3
9
  export const DEFAULT_CALLBACK_PORT = 17845;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAC/D,MAAM,CAAC,MAAM,qBAAqB,GAAG,WAAW,CAAC;AACjD,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAC3C,MAAM,CAAC,MAAM,qBAAqB,GAAG,WAAW,CAAC;AACjD,MAAM,CAAC,MAAM,6BAA6B,GAAG,QAAQ,CAAC;AACtD,MAAM,CAAC,MAAM,wBAAwB,GAAG,kBAAkB,CAAC;AAC3D,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,CAAC;AAChD,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,yCAAyC,CAAC;AAC7E,MAAM,CAAC,MAAM,kBAAkB,GAAG,iCAAiC,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;AACnG,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAwB,CAAC;AAE7F,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC,OAAO,CAAC;AAC/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAC/D,MAAM,CAAC,MAAM,qBAAqB,GAAG,WAAW,CAAC;AACjD,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAC3C,MAAM,CAAC,MAAM,qBAAqB,GAAG,WAAW,CAAC;AACjD,MAAM,CAAC,MAAM,6BAA6B,GAAG,QAAQ,CAAC;AACtD,MAAM,CAAC,MAAM,wBAAwB,GAAG,kBAAkB,CAAC;AAC3D,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,CAAC;AAChD,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,yCAAyC,CAAC;AAC7E,MAAM,CAAC,MAAM,kBAAkB,GAAG,iCAAiC,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
+ import { CLI_VERSION } from './constants.js';
2
3
  import { createCli } from './cli.js';
3
4
  async function main() {
4
- const program = createCli({ version: '0.1.0' });
5
+ const program = createCli({ version: CLI_VERSION });
5
6
  await program.parseAsync(process.argv);
6
7
  }
7
8
  main().catch((error) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAChD,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,OAAO,IAAI,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;IACpD,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,OAAO,IAAI,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { CountPartnerMcpConfig } from './types.js';
2
+ interface LoadConfigParams {
3
+ environment?: NodeJS.ProcessEnv;
4
+ }
5
+ export declare function loadConfig(params?: LoadConfigParams): CountPartnerMcpConfig;
6
+ export {};
@@ -0,0 +1,25 @@
1
+ import { z } from 'zod';
2
+ const optionalNonEmptyString = z.preprocess((_value) => (_value === '' ? undefined : _value), z.string().trim().min(1).optional());
3
+ const environmentSchema = z.object({
4
+ COUNT_API_URL: z.string().trim().min(1).default('https://api.getcount.com'),
5
+ COUNT_CLIENT_ID: z.string().trim().min(1),
6
+ COUNT_CLIENT_SECRET: z.string().trim().min(1),
7
+ COUNT_ACCESS_TOKEN: optionalNonEmptyString,
8
+ COUNT_REFRESH_TOKEN: optionalNonEmptyString,
9
+ COUNT_REQUEST_TIMEOUT_MS: z.coerce.number().int().positive().default(30000),
10
+ COUNT_CREDENTIALS_FILE: optionalNonEmptyString,
11
+ });
12
+ export function loadConfig(params = {}) {
13
+ const { environment = process.env } = params;
14
+ const parsedEnvironment = environmentSchema.parse(environment);
15
+ return {
16
+ apiBaseUrl: parsedEnvironment.COUNT_API_URL.replace(/\/+$/, ''),
17
+ clientId: parsedEnvironment.COUNT_CLIENT_ID,
18
+ clientSecret: parsedEnvironment.COUNT_CLIENT_SECRET,
19
+ accessToken: parsedEnvironment.COUNT_ACCESS_TOKEN,
20
+ refreshToken: parsedEnvironment.COUNT_REFRESH_TOKEN,
21
+ requestTimeoutMs: parsedEnvironment.COUNT_REQUEST_TIMEOUT_MS,
22
+ credentialsFilePath: parsedEnvironment.COUNT_CREDENTIALS_FILE,
23
+ };
24
+ }
25
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/partner-mcp/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,sBAAsB,GAAG,CAAC,CAAC,UAAU,CACzC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,EAChD,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CACpC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,0BAA0B,CAAC;IAC3E,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzC,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7C,kBAAkB,EAAE,sBAAsB;IAC1C,mBAAmB,EAAE,sBAAsB;IAC3C,wBAAwB,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAC3E,sBAAsB,EAAE,sBAAsB;CAC/C,CAAC,CAAC;AAMH,MAAM,UAAU,UAAU,CAAC,SAA2B,EAAE;IACtD,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC;IAC7C,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAE/D,OAAO;QACL,UAAU,EAAE,iBAAiB,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QAC/D,QAAQ,EAAE,iBAAiB,CAAC,eAAe;QAC3C,YAAY,EAAE,iBAAiB,CAAC,mBAAmB;QACnD,WAAW,EAAE,iBAAiB,CAAC,kBAAkB;QACjD,YAAY,EAAE,iBAAiB,CAAC,mBAAmB;QACnD,gBAAgB,EAAE,iBAAiB,CAAC,wBAAwB;QAC5D,mBAAmB,EAAE,iBAAiB,CAAC,sBAAsB;KAC9D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import 'dotenv/config';
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ import 'dotenv/config';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { loadConfig } from './config.js';
5
+ import { createServer } from './server.js';
6
+ async function main() {
7
+ const config = loadConfig();
8
+ const server = createServer({ config });
9
+ const transport = new StdioServerTransport();
10
+ await server.connect(transport);
11
+ }
12
+ main().catch((error) => {
13
+ const message = error instanceof Error ? error.message : String(error);
14
+ process.stderr.write(`COUNT partner MCP server failed to start: ${message}\n`);
15
+ process.exit(1);
16
+ });
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/partner-mcp/index.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6CAA6C,OAAO,IAAI,CAAC,CAAC;IAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { CountPartnerMcpConfig, RequestParams } from './types.js';
2
+ interface PartnerApiClientParams {
3
+ config: CountPartnerMcpConfig;
4
+ fetchImplementation?: typeof fetch;
5
+ currentTimeMs?: () => number;
6
+ }
7
+ export declare class PartnerApiError extends Error {
8
+ readonly statusCode: number;
9
+ readonly responseBody: unknown;
10
+ constructor(message: string, statusCode: number, responseBody: unknown);
11
+ }
12
+ export declare class PartnerApiClient {
13
+ private readonly config;
14
+ private readonly fetchImplementation;
15
+ private readonly currentTimeMs;
16
+ private accessToken?;
17
+ private refreshToken?;
18
+ constructor(params: PartnerApiClientParams);
19
+ getAuthState(): Record<string, boolean | string>;
20
+ request<TResponse = unknown>(params: RequestParams): Promise<TResponse>;
21
+ refreshAccessToken(): Promise<void>;
22
+ private performRequest;
23
+ private buildUrl;
24
+ private buildHeaders;
25
+ private buildRequestBody;
26
+ private parseResponseBody;
27
+ private getErrorMessage;
28
+ private shouldRefreshAfterError;
29
+ }
30
+ interface ToPartnerRouterPathParams {
31
+ path: string;
32
+ }
33
+ export declare function toPartnerRouterPath(params: ToPartnerRouterPathParams): string;
34
+ export {};
@@ -0,0 +1,233 @@
1
+ import { computePartnerSignature } from './signing.js';
2
+ import * as tokenPersistence from './tokenPersistence.js';
3
+ export class PartnerApiError extends Error {
4
+ statusCode;
5
+ responseBody;
6
+ constructor(message, statusCode, responseBody) {
7
+ super(message);
8
+ this.name = 'PartnerApiError';
9
+ this.statusCode = statusCode;
10
+ this.responseBody = responseBody;
11
+ }
12
+ }
13
+ export class PartnerApiClient {
14
+ config;
15
+ fetchImplementation;
16
+ currentTimeMs;
17
+ accessToken;
18
+ refreshToken;
19
+ constructor(params) {
20
+ const { config, fetchImplementation = fetch, currentTimeMs = Date.now } = params;
21
+ this.config = config;
22
+ this.fetchImplementation = fetchImplementation;
23
+ this.currentTimeMs = currentTimeMs;
24
+ this.accessToken = config.accessToken;
25
+ this.refreshToken = config.refreshToken;
26
+ }
27
+ getAuthState() {
28
+ return {
29
+ apiBaseUrl: this.config.apiBaseUrl,
30
+ hasClientId: Boolean(this.config.clientId),
31
+ hasClientSecret: Boolean(this.config.clientSecret),
32
+ hasAccessToken: Boolean(this.accessToken),
33
+ hasRefreshToken: Boolean(this.refreshToken),
34
+ };
35
+ }
36
+ async request(params) {
37
+ const { method, path, signaturePath, query, body, requiresUserAuth = true, retryOnUnauthorized = true, } = params;
38
+ const response = await this.performRequest({
39
+ method,
40
+ path,
41
+ signaturePath,
42
+ query,
43
+ body,
44
+ requiresUserAuth,
45
+ });
46
+ if (!(response instanceof PartnerApiError)) {
47
+ return response;
48
+ }
49
+ if (requiresUserAuth &&
50
+ retryOnUnauthorized &&
51
+ this.refreshToken &&
52
+ this.shouldRefreshAfterError({ error: response })) {
53
+ await this.refreshAccessToken();
54
+ const retryResponse = await this.performRequest({
55
+ method,
56
+ path,
57
+ signaturePath,
58
+ query,
59
+ body,
60
+ requiresUserAuth,
61
+ });
62
+ if (!(retryResponse instanceof PartnerApiError)) {
63
+ return retryResponse;
64
+ }
65
+ throw retryResponse;
66
+ }
67
+ throw response;
68
+ }
69
+ async refreshAccessToken() {
70
+ if (!this.refreshToken) {
71
+ throw new PartnerApiError('No refresh token is configured for this MCP server.', 401, {
72
+ message: 'Missing COUNT_REFRESH_TOKEN',
73
+ });
74
+ }
75
+ const response = await this.request({
76
+ method: 'POST',
77
+ path: '/partners/refresh-user-access-token',
78
+ body: {
79
+ grantType: 'refresh_token',
80
+ refreshToken: this.refreshToken,
81
+ },
82
+ requiresUserAuth: false,
83
+ retryOnUnauthorized: false,
84
+ });
85
+ const tokenSet = response.data?.result;
86
+ if (!tokenSet?.accessToken || !tokenSet.refreshToken) {
87
+ throw new PartnerApiError('Refresh token response did not include a token set.', 502, response);
88
+ }
89
+ this.accessToken = tokenSet.accessToken;
90
+ this.refreshToken = tokenSet.refreshToken;
91
+ if (this.config.credentialsFilePath) {
92
+ await tokenPersistence.persistRefreshedTokens({
93
+ credentialsFilePath: this.config.credentialsFilePath,
94
+ accessToken: tokenSet.accessToken,
95
+ refreshToken: tokenSet.refreshToken,
96
+ });
97
+ }
98
+ }
99
+ async performRequest(params) {
100
+ const { method, path, signaturePath, query, body, requiresUserAuth = true } = params;
101
+ const url = this.buildUrl({ path, query });
102
+ const abortController = new AbortController();
103
+ const timeout = setTimeout(() => abortController.abort(), this.config.requestTimeoutMs);
104
+ try {
105
+ const response = await this.fetchImplementation(url, {
106
+ method,
107
+ headers: this.buildHeaders({ method, path, signaturePath, body, requiresUserAuth }),
108
+ body: this.buildRequestBody({ method, body }),
109
+ signal: abortController.signal,
110
+ });
111
+ const responseBody = await this.parseResponseBody({ response });
112
+ if (!response.ok) {
113
+ return new PartnerApiError(this.getErrorMessage({ statusCode: response.status, responseBody }), response.status, responseBody);
114
+ }
115
+ return responseBody;
116
+ }
117
+ catch (error) {
118
+ if (error instanceof PartnerApiError) {
119
+ return error;
120
+ }
121
+ if (error instanceof Error && error.name === 'AbortError') {
122
+ return new PartnerApiError(`COUNT API request timed out after ${this.config.requestTimeoutMs}ms.`, 408, {
123
+ message: error.message,
124
+ });
125
+ }
126
+ const message = error instanceof Error ? error.message : String(error);
127
+ return new PartnerApiError(`COUNT API request failed: ${message}`, 502, { message });
128
+ }
129
+ finally {
130
+ clearTimeout(timeout);
131
+ }
132
+ }
133
+ buildUrl(params) {
134
+ const { path, query } = params;
135
+ const url = new URL(path, this.config.apiBaseUrl);
136
+ for (const [key, value] of Object.entries(query ?? {})) {
137
+ if (value === undefined || value === null) {
138
+ continue;
139
+ }
140
+ if (Array.isArray(value)) {
141
+ for (const item of value) {
142
+ url.searchParams.append(key, String(item));
143
+ }
144
+ continue;
145
+ }
146
+ url.searchParams.set(key, String(value));
147
+ }
148
+ return url.toString();
149
+ }
150
+ buildHeaders(params) {
151
+ const { method, path, signaturePath, body, requiresUserAuth } = params;
152
+ const timestamp = String(this.currentTimeMs());
153
+ const signature = computePartnerSignature({
154
+ method,
155
+ path: signaturePath ?? toPartnerRouterPath({ path }),
156
+ timestamp,
157
+ body,
158
+ clientSecret: this.config.clientSecret,
159
+ });
160
+ const headers = {
161
+ accept: 'application/json',
162
+ 'x-client-id': this.config.clientId,
163
+ 'x-timestamp': timestamp,
164
+ 'x-signature': signature,
165
+ };
166
+ if (method === 'POST' || method === 'PUT' || method === 'PATCH') {
167
+ headers['content-type'] = 'application/json';
168
+ }
169
+ if (requiresUserAuth) {
170
+ if (!this.accessToken) {
171
+ throw new PartnerApiError('No access token is configured for this MCP server.', 401, {
172
+ message: 'Missing COUNT_ACCESS_TOKEN',
173
+ });
174
+ }
175
+ headers.authorization = `Bearer ${this.accessToken}`;
176
+ }
177
+ return headers;
178
+ }
179
+ buildRequestBody(params) {
180
+ const { method, body } = params;
181
+ if (method !== 'POST' && method !== 'PUT' && method !== 'PATCH') {
182
+ return undefined;
183
+ }
184
+ return JSON.stringify(body ?? {});
185
+ }
186
+ async parseResponseBody(params) {
187
+ const { response } = params;
188
+ const contentType = response.headers.get('content-type') ?? '';
189
+ const text = await response.text();
190
+ if (!text) {
191
+ return null;
192
+ }
193
+ if (contentType.includes('application/json')) {
194
+ try {
195
+ return JSON.parse(text);
196
+ }
197
+ catch {
198
+ return text;
199
+ }
200
+ }
201
+ return text;
202
+ }
203
+ getErrorMessage(params) {
204
+ const { statusCode, responseBody } = params;
205
+ if (responseBody && typeof responseBody === 'object') {
206
+ const errorBody = responseBody;
207
+ return errorBody.error_description ?? errorBody.message ?? `COUNT API returned ${statusCode}.`;
208
+ }
209
+ return `COUNT API returned ${statusCode}.`;
210
+ }
211
+ shouldRefreshAfterError(params) {
212
+ const { error } = params;
213
+ if (error.statusCode !== 401) {
214
+ return false;
215
+ }
216
+ if (!error.responseBody || typeof error.responseBody !== 'object') {
217
+ return true;
218
+ }
219
+ const errorBody = error.responseBody;
220
+ return errorBody.error === 'invalid_token' || errorBody.error_description === 'The access token expired';
221
+ }
222
+ }
223
+ export function toPartnerRouterPath(params) {
224
+ const { path } = params;
225
+ if (path === '/partners') {
226
+ return '/';
227
+ }
228
+ if (path.startsWith('/partners/')) {
229
+ return path.slice('/partners'.length);
230
+ }
231
+ return path;
232
+ }
233
+ //# sourceMappingURL=partnerApiClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partnerApiClient.js","sourceRoot":"","sources":["../../src/partner-mcp/partnerApiClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { PartnerApiClient } from '../partnerApiClient.js';
3
+ interface RegisterResourcesParams {
4
+ server: McpServer;
5
+ client: PartnerApiClient;
6
+ }
7
+ export declare function registerResources(params: RegisterResourcesParams): void;
8
+ export {};
@@ -0,0 +1,70 @@
1
+ const resources = [
2
+ {
3
+ name: 'COUNT_chart_of_accounts',
4
+ uri: 'count://chart-of-accounts',
5
+ title: 'COUNT Chart of Accounts',
6
+ description: 'Read-only snapshot of the authenticated workspace chart of accounts.',
7
+ path: '/partners/chart-of-accounts',
8
+ },
9
+ {
10
+ name: 'COUNT_customers',
11
+ uri: 'count://customers',
12
+ title: 'COUNT Customers',
13
+ description: 'Read-only snapshot of customers in the authenticated workspace.',
14
+ path: '/partners/customers',
15
+ },
16
+ {
17
+ name: 'COUNT_vendors',
18
+ uri: 'count://vendors',
19
+ title: 'COUNT Vendors',
20
+ description: 'Read-only snapshot of vendors in the authenticated workspace.',
21
+ path: '/partners/vendors',
22
+ },
23
+ {
24
+ name: 'COUNT_products',
25
+ uri: 'count://products',
26
+ title: 'COUNT Products',
27
+ description: 'Read-only snapshot of products and services in the authenticated workspace.',
28
+ path: '/partners/products',
29
+ },
30
+ {
31
+ name: 'COUNT_people',
32
+ uri: 'count://people',
33
+ title: 'COUNT People',
34
+ description: 'Read-only snapshot of people records in the authenticated workspace.',
35
+ path: '/partners/people',
36
+ },
37
+ {
38
+ name: 'COUNT_recurring_invoice_templates',
39
+ uri: 'count://recurring-invoice-templates',
40
+ title: 'COUNT Recurring Invoice Templates',
41
+ description: 'Read-only snapshot of recurring invoice templates in the authenticated workspace.',
42
+ path: '/partners/recurring-invoice-templates',
43
+ },
44
+ ];
45
+ export function registerResources(params) {
46
+ const { server, client } = params;
47
+ for (const resource of resources) {
48
+ server.registerResource(resource.name, resource.uri, {
49
+ title: resource.title,
50
+ description: resource.description,
51
+ mimeType: 'application/json',
52
+ }, async (uri) => {
53
+ const response = await client.request({
54
+ method: 'GET',
55
+ path: resource.path,
56
+ requiresUserAuth: true,
57
+ });
58
+ return {
59
+ contents: [
60
+ {
61
+ uri: uri.href,
62
+ mimeType: 'application/json',
63
+ text: JSON.stringify(response, null, 2),
64
+ },
65
+ ],
66
+ };
67
+ });
68
+ }
69
+ }
70
+ //# sourceMappingURL=registerResources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registerResources.js","sourceRoot":"","sources":["../../../src/partner-mcp/resources/registerResources.ts"],"names":[],"mappings":"AAgBA,MAAM,SAAS,GAAyB;IACtC;QACE,IAAI,EAAE,yBAAyB;QAC/B,GAAG,EAAE,2BAA2B;QAChC,KAAK,EAAE,yBAAyB;QAChC,WAAW,EAAE,sEAAsE;QACnF,IAAI,EAAE,6BAA6B;KACpC;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,GAAG,EAAE,mBAAmB;QACxB,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,iEAAiE;QAC9E,IAAI,EAAE,qBAAqB;KAC5B;IACD;QACE,IAAI,EAAE,eAAe;QACrB,GAAG,EAAE,iBAAiB;QACtB,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,+DAA+D;QAC5E,IAAI,EAAE,mBAAmB;KAC1B;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,GAAG,EAAE,kBAAkB;QACvB,KAAK,EAAE,gBAAgB;QACvB,WAAW,EAAE,6EAA6E;QAC1F,IAAI,EAAE,oBAAoB;KAC3B;IACD;QACE,IAAI,EAAE,cAAc;QACpB,GAAG,EAAE,gBAAgB;QACrB,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,sEAAsE;QACnF,IAAI,EAAE,kBAAkB;KACzB;IACD;QACE,IAAI,EAAE,mCAAmC;QACzC,GAAG,EAAE,qCAAqC;QAC1C,KAAK,EAAE,mCAAmC;QAC1C,WAAW,EAAE,mFAAmF;QAChG,IAAI,EAAE,uCAAuC;KAC9C;CACF,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,MAA+B;IAC/D,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAElC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,CAAC,gBAAgB,CACrB,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,GAAG,EACZ;YACE,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,QAAQ,EAAE,kBAAkB;SAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;gBACpC,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,gBAAgB,EAAE,IAAI;aACvB,CAAC,CAAC;YAEH,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,GAAG,CAAC,IAAI;wBACb,QAAQ,EAAE,kBAAkB;wBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;qBACxC;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;IACJ,CAAC;AACH,CAAC"}