@ankimcp/anki-mcp-server 0.18.5 → 0.19.1

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 (231) hide show
  1. package/README.md +204 -139
  2. package/bin/ankimcp.js +10 -1
  3. package/dist/app-config.service.d.ts +20 -0
  4. package/dist/app-config.service.js +73 -0
  5. package/dist/app-config.service.js.map +1 -0
  6. package/dist/app.module.d.ts +4 -2
  7. package/dist/app.module.js +99 -11
  8. package/dist/app.module.js.map +1 -1
  9. package/dist/bootstrap.d.ts +6 -1
  10. package/dist/bootstrap.js +7 -2
  11. package/dist/bootstrap.js.map +1 -1
  12. package/dist/cli/__tests__/cli-output.manual.d.ts +2 -0
  13. package/dist/cli/__tests__/cli-output.manual.js +14 -0
  14. package/dist/cli/__tests__/cli-output.manual.js.map +1 -0
  15. package/dist/cli/args.d.ts +16 -0
  16. package/dist/{cli.js → cli/args.js} +46 -19
  17. package/dist/cli/args.js.map +1 -0
  18. package/dist/cli/cli-output.d.ts +18 -0
  19. package/dist/cli/cli-output.js +74 -0
  20. package/dist/cli/cli-output.js.map +1 -0
  21. package/dist/cli/index.d.ts +3 -0
  22. package/dist/cli/index.js +20 -0
  23. package/dist/cli/index.js.map +1 -0
  24. package/dist/cli/spinner.d.ts +1 -0
  25. package/dist/cli/spinner.js +16 -0
  26. package/dist/cli/spinner.js.map +1 -0
  27. package/dist/config/config.factory.d.ts +13 -0
  28. package/dist/config/config.factory.js +32 -0
  29. package/dist/config/config.factory.js.map +1 -0
  30. package/dist/config/config.schema.d.ts +31 -0
  31. package/dist/config/config.schema.js +54 -0
  32. package/dist/config/config.schema.js.map +1 -0
  33. package/dist/config/index.d.ts +3 -0
  34. package/dist/config/index.js +11 -0
  35. package/dist/config/index.js.map +1 -0
  36. package/dist/http/guards/origin-validation.guard.d.ts +1 -0
  37. package/dist/http/guards/origin-validation.guard.js +5 -3
  38. package/dist/http/guards/origin-validation.guard.js.map +1 -1
  39. package/dist/main-http.js +23 -11
  40. package/dist/main-http.js.map +1 -1
  41. package/dist/main-stdio.js +10 -9
  42. package/dist/main-stdio.js.map +1 -1
  43. package/dist/main-tunnel.d.ts +1 -0
  44. package/dist/main-tunnel.js +27 -0
  45. package/dist/main-tunnel.js.map +1 -0
  46. package/dist/mcp/clients/anki-connect.client.js +3 -3
  47. package/dist/mcp/clients/anki-connect.client.js.map +1 -1
  48. package/dist/mcp/primitives/essential/index.d.ts +1 -0
  49. package/dist/mcp/primitives/essential/index.js +8 -1
  50. package/dist/mcp/primitives/essential/index.js.map +1 -1
  51. package/dist/mcp/primitives/essential/tools/add-note.tool.d.ts +2 -3
  52. package/dist/mcp/primitives/essential/tools/add-note.tool.js +2 -9
  53. package/dist/mcp/primitives/essential/tools/add-note.tool.js.map +1 -1
  54. package/dist/mcp/primitives/essential/tools/add-notes.tool.d.ts +1 -2
  55. package/dist/mcp/primitives/essential/tools/add-notes.tool.js +2 -23
  56. package/dist/mcp/primitives/essential/tools/add-notes.tool.js.map +1 -1
  57. package/dist/mcp/primitives/essential/tools/add-tags.tool.d.ts +1 -2
  58. package/dist/mcp/primitives/essential/tools/add-tags.tool.js +2 -4
  59. package/dist/mcp/primitives/essential/tools/add-tags.tool.js.map +1 -1
  60. package/dist/mcp/primitives/essential/tools/change-deck.tool.d.ts +1 -2
  61. package/dist/mcp/primitives/essential/tools/change-deck.tool.js +2 -4
  62. package/dist/mcp/primitives/essential/tools/change-deck.tool.js.map +1 -1
  63. package/dist/mcp/primitives/essential/tools/clear-unused-tags.tool.d.ts +1 -2
  64. package/dist/mcp/primitives/essential/tools/clear-unused-tags.tool.js +2 -4
  65. package/dist/mcp/primitives/essential/tools/clear-unused-tags.tool.js.map +1 -1
  66. package/dist/mcp/primitives/essential/tools/collection-stats/collection-stats.tool.d.ts +1 -2
  67. package/dist/mcp/primitives/essential/tools/collection-stats/collection-stats.tool.js +2 -12
  68. package/dist/mcp/primitives/essential/tools/collection-stats/collection-stats.tool.js.map +1 -1
  69. package/dist/mcp/primitives/essential/tools/create-deck.tool.d.ts +1 -2
  70. package/dist/mcp/primitives/essential/tools/create-deck.tool.js +2 -4
  71. package/dist/mcp/primitives/essential/tools/create-deck.tool.js.map +1 -1
  72. package/dist/mcp/primitives/essential/tools/create-model.tool.d.ts +1 -2
  73. package/dist/mcp/primitives/essential/tools/create-model.tool.js +2 -6
  74. package/dist/mcp/primitives/essential/tools/create-model.tool.js.map +1 -1
  75. package/dist/mcp/primitives/essential/tools/deck-stats.tool.d.ts +1 -2
  76. package/dist/mcp/primitives/essential/tools/deck-stats.tool.js +3 -7
  77. package/dist/mcp/primitives/essential/tools/deck-stats.tool.js.map +1 -1
  78. package/dist/mcp/primitives/essential/tools/delete-media-file.tool.d.ts +1 -2
  79. package/dist/mcp/primitives/essential/tools/delete-media-file.tool.js +2 -4
  80. package/dist/mcp/primitives/essential/tools/delete-media-file.tool.js.map +1 -1
  81. package/dist/mcp/primitives/essential/tools/delete-notes.tool.d.ts +2 -3
  82. package/dist/mcp/primitives/essential/tools/delete-notes.tool.js +2 -6
  83. package/dist/mcp/primitives/essential/tools/delete-notes.tool.js.map +1 -1
  84. package/dist/mcp/primitives/essential/tools/find-notes.tool.d.ts +1 -2
  85. package/dist/mcp/primitives/essential/tools/find-notes.tool.js +2 -6
  86. package/dist/mcp/primitives/essential/tools/find-notes.tool.js.map +1 -1
  87. package/dist/mcp/primitives/essential/tools/get-cards.tool.d.ts +1 -2
  88. package/dist/mcp/primitives/essential/tools/get-cards.tool.js +2 -6
  89. package/dist/mcp/primitives/essential/tools/get-cards.tool.js.map +1 -1
  90. package/dist/mcp/primitives/essential/tools/get-due-cards.tool.d.ts +1 -2
  91. package/dist/mcp/primitives/essential/tools/get-due-cards.tool.js +2 -6
  92. package/dist/mcp/primitives/essential/tools/get-due-cards.tool.js.map +1 -1
  93. package/dist/mcp/primitives/essential/tools/get-media-files-names.tool.d.ts +1 -2
  94. package/dist/mcp/primitives/essential/tools/get-media-files-names.tool.js +2 -4
  95. package/dist/mcp/primitives/essential/tools/get-media-files-names.tool.js.map +1 -1
  96. package/dist/mcp/primitives/essential/tools/get-tags.tool.d.ts +1 -2
  97. package/dist/mcp/primitives/essential/tools/get-tags.tool.js +2 -6
  98. package/dist/mcp/primitives/essential/tools/get-tags.tool.js.map +1 -1
  99. package/dist/mcp/primitives/essential/tools/list-decks.tool.d.ts +1 -2
  100. package/dist/mcp/primitives/essential/tools/list-decks.tool.js +2 -4
  101. package/dist/mcp/primitives/essential/tools/list-decks.tool.js.map +1 -1
  102. package/dist/mcp/primitives/essential/tools/model-field-names.tool.d.ts +1 -2
  103. package/dist/mcp/primitives/essential/tools/model-field-names.tool.js +2 -7
  104. package/dist/mcp/primitives/essential/tools/model-field-names.tool.js.map +1 -1
  105. package/dist/mcp/primitives/essential/tools/model-names.tool.d.ts +1 -2
  106. package/dist/mcp/primitives/essential/tools/model-names.tool.js +2 -6
  107. package/dist/mcp/primitives/essential/tools/model-names.tool.js.map +1 -1
  108. package/dist/mcp/primitives/essential/tools/model-styling.tool.d.ts +1 -2
  109. package/dist/mcp/primitives/essential/tools/model-styling.tool.js +2 -6
  110. package/dist/mcp/primitives/essential/tools/model-styling.tool.js.map +1 -1
  111. package/dist/mcp/primitives/essential/tools/notes-info.tool.d.ts +1 -2
  112. package/dist/mcp/primitives/essential/tools/notes-info.tool.js +2 -6
  113. package/dist/mcp/primitives/essential/tools/notes-info.tool.js.map +1 -1
  114. package/dist/mcp/primitives/essential/tools/present-card.tool.d.ts +2 -3
  115. package/dist/mcp/primitives/essential/tools/present-card.tool.js +2 -5
  116. package/dist/mcp/primitives/essential/tools/present-card.tool.js.map +1 -1
  117. package/dist/mcp/primitives/essential/tools/rate-card.tool.d.ts +1 -2
  118. package/dist/mcp/primitives/essential/tools/rate-card.tool.js +2 -5
  119. package/dist/mcp/primitives/essential/tools/rate-card.tool.js.map +1 -1
  120. package/dist/mcp/primitives/essential/tools/remove-tags.tool.d.ts +1 -2
  121. package/dist/mcp/primitives/essential/tools/remove-tags.tool.js +2 -4
  122. package/dist/mcp/primitives/essential/tools/remove-tags.tool.js.map +1 -1
  123. package/dist/mcp/primitives/essential/tools/replace-tags.tool.d.ts +1 -2
  124. package/dist/mcp/primitives/essential/tools/replace-tags.tool.js +2 -4
  125. package/dist/mcp/primitives/essential/tools/replace-tags.tool.js.map +1 -1
  126. package/dist/mcp/primitives/essential/tools/retrieve-media-file.tool.d.ts +1 -2
  127. package/dist/mcp/primitives/essential/tools/retrieve-media-file.tool.js +2 -4
  128. package/dist/mcp/primitives/essential/tools/retrieve-media-file.tool.js.map +1 -1
  129. package/dist/mcp/primitives/essential/tools/review-stats/review-stats.tool.d.ts +1 -2
  130. package/dist/mcp/primitives/essential/tools/review-stats/review-stats.tool.js +2 -8
  131. package/dist/mcp/primitives/essential/tools/review-stats/review-stats.tool.js.map +1 -1
  132. package/dist/mcp/primitives/essential/tools/store-media-file.tool.d.ts +1 -2
  133. package/dist/mcp/primitives/essential/tools/store-media-file.tool.js +2 -4
  134. package/dist/mcp/primitives/essential/tools/store-media-file.tool.js.map +1 -1
  135. package/dist/mcp/primitives/essential/tools/sync.tool.d.ts +1 -2
  136. package/dist/mcp/primitives/essential/tools/sync.tool.js +2 -4
  137. package/dist/mcp/primitives/essential/tools/sync.tool.js.map +1 -1
  138. package/dist/mcp/primitives/essential/tools/update-model-styling.tool.d.ts +2 -3
  139. package/dist/mcp/primitives/essential/tools/update-model-styling.tool.js +2 -6
  140. package/dist/mcp/primitives/essential/tools/update-model-styling.tool.js.map +1 -1
  141. package/dist/mcp/primitives/essential/tools/update-note-fields.tool.d.ts +1 -2
  142. package/dist/mcp/primitives/essential/tools/update-note-fields.tool.js +2 -5
  143. package/dist/mcp/primitives/essential/tools/update-note-fields.tool.js.map +1 -1
  144. package/dist/mcp/primitives/gui/index.d.ts +1 -0
  145. package/dist/mcp/primitives/gui/index.js +8 -1
  146. package/dist/mcp/primitives/gui/index.js.map +1 -1
  147. package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.d.ts +1 -2
  148. package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.js +2 -5
  149. package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.js.map +1 -1
  150. package/dist/mcp/primitives/gui/tools/gui-browse.tool.d.ts +1 -2
  151. package/dist/mcp/primitives/gui/tools/gui-browse.tool.js +2 -4
  152. package/dist/mcp/primitives/gui/tools/gui-browse.tool.js.map +1 -1
  153. package/dist/mcp/primitives/gui/tools/gui-current-card.tool.d.ts +1 -2
  154. package/dist/mcp/primitives/gui/tools/gui-current-card.tool.js +2 -4
  155. package/dist/mcp/primitives/gui/tools/gui-current-card.tool.js.map +1 -1
  156. package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.d.ts +1 -2
  157. package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.js +2 -4
  158. package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.js.map +1 -1
  159. package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.d.ts +1 -2
  160. package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.js +2 -4
  161. package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.js.map +1 -1
  162. package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.d.ts +1 -2
  163. package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.js +2 -4
  164. package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.js.map +1 -1
  165. package/dist/mcp/primitives/gui/tools/gui-select-card.tool.d.ts +1 -2
  166. package/dist/mcp/primitives/gui/tools/gui-select-card.tool.js +2 -4
  167. package/dist/mcp/primitives/gui/tools/gui-select-card.tool.js.map +1 -1
  168. package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.d.ts +1 -2
  169. package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.js +2 -4
  170. package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.js.map +1 -1
  171. package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.d.ts +1 -2
  172. package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.js +2 -4
  173. package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.js.map +1 -1
  174. package/dist/mcp/primitives/gui/tools/gui-show-question.tool.d.ts +1 -2
  175. package/dist/mcp/primitives/gui/tools/gui-show-question.tool.js +2 -4
  176. package/dist/mcp/primitives/gui/tools/gui-show-question.tool.js.map +1 -1
  177. package/dist/mcp/primitives/gui/tools/gui-undo.tool.d.ts +1 -2
  178. package/dist/mcp/primitives/gui/tools/gui-undo.tool.js +2 -4
  179. package/dist/mcp/primitives/gui/tools/gui-undo.tool.js.map +1 -1
  180. package/dist/services/ngrok.service.d.ts +1 -0
  181. package/dist/services/ngrok.service.js +5 -3
  182. package/dist/services/ngrok.service.js.map +1 -1
  183. package/dist/test-fixtures/mock-data.d.ts +8 -0
  184. package/dist/test-fixtures/mock-data.js +8 -0
  185. package/dist/test-fixtures/mock-data.js.map +1 -1
  186. package/dist/tunnel/commands/index.d.ts +3 -0
  187. package/dist/tunnel/commands/index.js +10 -0
  188. package/dist/tunnel/commands/index.js.map +1 -0
  189. package/dist/tunnel/commands/login.command.d.ts +2 -0
  190. package/dist/tunnel/commands/login.command.js +29 -0
  191. package/dist/tunnel/commands/login.command.js.map +1 -0
  192. package/dist/tunnel/commands/logout.command.d.ts +2 -0
  193. package/dist/tunnel/commands/logout.command.js +25 -0
  194. package/dist/tunnel/commands/logout.command.js.map +1 -0
  195. package/dist/tunnel/commands/perform-login.d.ts +9 -0
  196. package/dist/tunnel/commands/perform-login.js +72 -0
  197. package/dist/tunnel/commands/perform-login.js.map +1 -0
  198. package/dist/tunnel/commands/tunnel.command.d.ts +3 -0
  199. package/dist/tunnel/commands/tunnel.command.js +227 -0
  200. package/dist/tunnel/commands/tunnel.command.js.map +1 -0
  201. package/dist/tunnel/credentials.service.d.ts +23 -0
  202. package/dist/tunnel/credentials.service.js +152 -0
  203. package/dist/tunnel/credentials.service.js.map +1 -0
  204. package/dist/tunnel/device-flow.service.d.ts +46 -0
  205. package/dist/tunnel/device-flow.service.js +230 -0
  206. package/dist/tunnel/device-flow.service.js.map +1 -0
  207. package/dist/tunnel/in-memory.transport.d.ts +14 -0
  208. package/dist/tunnel/in-memory.transport.js +63 -0
  209. package/dist/tunnel/in-memory.transport.js.map +1 -0
  210. package/dist/tunnel/index.d.ts +6 -0
  211. package/dist/tunnel/index.js +31 -0
  212. package/dist/tunnel/index.js.map +1 -0
  213. package/dist/tunnel/tunnel-mcp.service.d.ts +15 -0
  214. package/dist/tunnel/tunnel-mcp.service.js +100 -0
  215. package/dist/tunnel/tunnel-mcp.service.js.map +1 -0
  216. package/dist/tunnel/tunnel.client.d.ts +60 -0
  217. package/dist/tunnel/tunnel.client.js +386 -0
  218. package/dist/tunnel/tunnel.client.js.map +1 -0
  219. package/dist/tunnel/tunnel.protocol.d.ts +67 -0
  220. package/dist/tunnel/tunnel.protocol.js +25 -0
  221. package/dist/tunnel/tunnel.protocol.js.map +1 -0
  222. package/dist/version.d.ts +2 -0
  223. package/dist/version.js +21 -0
  224. package/dist/version.js.map +1 -0
  225. package/package.json +31 -22
  226. package/dist/anki-config.service.d.ts +0 -11
  227. package/dist/anki-config.service.js +0 -46
  228. package/dist/anki-config.service.js.map +0 -1
  229. package/dist/cli.d.ts +0 -10
  230. package/dist/cli.js.map +0 -1
  231. package/dist/tsconfig.build.tsbuildinfo +0 -1
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ var DeviceFlowService_1;
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.DeviceFlowService = exports.DeviceFlowError = void 0;
47
+ const common_1 = require("@nestjs/common");
48
+ const ky_1 = __importStar(require("ky"));
49
+ const app_config_service_1 = require("../app-config.service");
50
+ class DeviceFlowError extends Error {
51
+ code;
52
+ description;
53
+ constructor(message, code, description) {
54
+ super(message);
55
+ this.code = code;
56
+ this.description = description;
57
+ this.name = "DeviceFlowError";
58
+ }
59
+ }
60
+ exports.DeviceFlowError = DeviceFlowError;
61
+ function isDeviceFlowErrorResponse(data) {
62
+ return (typeof data === "object" &&
63
+ data !== null &&
64
+ "error" in data &&
65
+ typeof data.error === "string");
66
+ }
67
+ let DeviceFlowService = DeviceFlowService_1 = class DeviceFlowService {
68
+ config;
69
+ client;
70
+ logger = new common_1.Logger(DeviceFlowService_1.name);
71
+ deviceEndpoint;
72
+ tokenEndpoint;
73
+ constructor(config) {
74
+ this.config = config;
75
+ const tunnelUrl = this.config.tunnelServerUrl;
76
+ const httpUrl = tunnelUrl
77
+ .replace(/^wss:/, "https:")
78
+ .replace(/^ws:/, "http:");
79
+ this.deviceEndpoint = `${httpUrl}/auth/device`;
80
+ this.tokenEndpoint = `${httpUrl}/auth/token`;
81
+ this.client = ky_1.default.create({
82
+ timeout: 10000,
83
+ headers: {
84
+ "Content-Type": "application/x-www-form-urlencoded",
85
+ },
86
+ retry: {
87
+ limit: 0,
88
+ },
89
+ hooks: {
90
+ beforeRequest: [
91
+ ({ request }) => {
92
+ this.logger.debug(`Device Flow request: ${request.method} ${request.url}`);
93
+ },
94
+ ],
95
+ },
96
+ });
97
+ }
98
+ async requestDeviceCode() {
99
+ try {
100
+ this.logger.log("Requesting device code from tunnel service");
101
+ const response = await this.client
102
+ .post(this.deviceEndpoint, {
103
+ body: new URLSearchParams({
104
+ client_id: this.config.authClientId,
105
+ scope: "openid offline_access",
106
+ }).toString(),
107
+ })
108
+ .json();
109
+ this.logger.log("Device code received successfully");
110
+ this.logger.debug(`User code: ${response.user_code}`);
111
+ return response;
112
+ }
113
+ catch (error) {
114
+ throw this.handleError(error, "requestDeviceCode");
115
+ }
116
+ }
117
+ async pollForToken(deviceCode, interval, expiresIn) {
118
+ const startTime = Date.now();
119
+ const expiresAt = startTime + expiresIn * 1000;
120
+ let currentInterval = interval * 1000;
121
+ this.logger.log("Starting token polling");
122
+ this.logger.debug(`Polling interval: ${interval}s, expires in: ${expiresIn}s`);
123
+ while (Date.now() < expiresAt) {
124
+ await this.sleep(currentInterval);
125
+ try {
126
+ const response = await this.client
127
+ .post(this.tokenEndpoint, {
128
+ timeout: 5000,
129
+ body: new URLSearchParams({
130
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
131
+ device_code: deviceCode,
132
+ client_id: this.config.authClientId,
133
+ }).toString(),
134
+ })
135
+ .json();
136
+ this.logger.log("Token received successfully");
137
+ return response;
138
+ }
139
+ catch (error) {
140
+ if (error instanceof ky_1.HTTPError &&
141
+ isDeviceFlowErrorResponse(error.data)) {
142
+ const errorResponse = error.data;
143
+ switch (errorResponse.error) {
144
+ case "authorization_pending":
145
+ this.logger.debug("Authorization pending, continuing poll...");
146
+ continue;
147
+ case "slow_down":
148
+ currentInterval += 5000;
149
+ this.logger.debug(`Slow down requested, new interval: ${currentInterval / 1000}s`);
150
+ continue;
151
+ case "expired_token":
152
+ throw new DeviceFlowError("Device code has expired. Please restart the login process.", "expired_token", errorResponse.error_description);
153
+ case "access_denied":
154
+ throw new DeviceFlowError("User denied authorization.", "access_denied", errorResponse.error_description);
155
+ default:
156
+ throw new DeviceFlowError(`Authorization failed: ${errorResponse.error}`, errorResponse.error, errorResponse.error_description);
157
+ }
158
+ }
159
+ throw this.handleError(error, "pollForToken");
160
+ }
161
+ }
162
+ throw new DeviceFlowError("Polling timeout: device code expired before user authorization.", "expired_token");
163
+ }
164
+ async refreshToken(refreshToken) {
165
+ try {
166
+ this.logger.log("Refreshing access token via tunnel service");
167
+ const response = await this.client
168
+ .post(this.tokenEndpoint, {
169
+ body: new URLSearchParams({
170
+ grant_type: "refresh_token",
171
+ refresh_token: refreshToken,
172
+ client_id: this.config.authClientId,
173
+ }).toString(),
174
+ })
175
+ .json();
176
+ this.logger.log("Token refreshed successfully");
177
+ return response;
178
+ }
179
+ catch (error) {
180
+ if (error instanceof ky_1.HTTPError &&
181
+ error.response.status === 400 &&
182
+ isDeviceFlowErrorResponse(error.data) &&
183
+ error.data.error === "invalid_grant") {
184
+ throw new DeviceFlowError("Refresh token is invalid or expired. Please login again.", "invalid_grant", error.data.error_description);
185
+ }
186
+ throw this.handleError(error, "refreshToken");
187
+ }
188
+ }
189
+ sleep(ms) {
190
+ return new Promise((resolve) => setTimeout(resolve, ms));
191
+ }
192
+ handleError(error, operation) {
193
+ this.logger.error(`Error in ${operation}:`, error);
194
+ if (error instanceof ky_1.HTTPError) {
195
+ const status = error.response.status;
196
+ if (status === 401 || status === 403) {
197
+ return new DeviceFlowError("Authentication failed. Invalid client configuration.", "auth_failed");
198
+ }
199
+ if (status >= 500) {
200
+ return new DeviceFlowError("Tunnel service error. Please try again later.", "server_error");
201
+ }
202
+ return new DeviceFlowError(`HTTP error ${status}: ${error.message}`, "http_error");
203
+ }
204
+ if (error instanceof ky_1.TimeoutError) {
205
+ return new DeviceFlowError("Request timeout. Please check your network connection.", "timeout");
206
+ }
207
+ if (error instanceof Error) {
208
+ if (error.message.includes("fetch") ||
209
+ error.message.includes("network")) {
210
+ return new DeviceFlowError(`Cannot connect to tunnel service (${this.config.tunnelServerUrl}). Please check your internet connection.`, "network_error");
211
+ }
212
+ }
213
+ if (error instanceof DeviceFlowError) {
214
+ return error;
215
+ }
216
+ return new DeviceFlowError(`Unexpected error during ${operation}: ${error instanceof Error ? error.message : String(error)}`, "unknown_error");
217
+ }
218
+ getConfig() {
219
+ return {
220
+ tunnelUrl: this.config.tunnelServerUrl,
221
+ clientId: this.config.authClientId,
222
+ };
223
+ }
224
+ };
225
+ exports.DeviceFlowService = DeviceFlowService;
226
+ exports.DeviceFlowService = DeviceFlowService = DeviceFlowService_1 = __decorate([
227
+ (0, common_1.Injectable)(),
228
+ __metadata("design:paramtypes", [app_config_service_1.AppConfigService])
229
+ ], DeviceFlowService);
230
+ //# sourceMappingURL=device-flow.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-flow.service.js","sourceRoot":"","sources":["../../src/tunnel/device-flow.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
2
+ import { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
3
+ export declare class InMemoryTransport implements Transport {
4
+ private readonly logger;
5
+ private pendingRequests;
6
+ private closed;
7
+ onclose?: () => void;
8
+ onerror?: (error: Error) => void;
9
+ onmessage?: (message: JSONRPCMessage) => void;
10
+ start(): Promise<void>;
11
+ close(): Promise<void>;
12
+ send(message: JSONRPCMessage): Promise<void>;
13
+ handleRequest(request: JSONRPCMessage): Promise<JSONRPCMessage | null>;
14
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InMemoryTransport = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ class InMemoryTransport {
6
+ logger = new common_1.Logger(InMemoryTransport.name);
7
+ pendingRequests = new Map();
8
+ closed = false;
9
+ onclose;
10
+ onerror;
11
+ onmessage;
12
+ async start() {
13
+ }
14
+ async close() {
15
+ this.closed = true;
16
+ for (const [_id, pending] of this.pendingRequests) {
17
+ clearTimeout(pending.timeout);
18
+ pending.reject(new Error("Transport closed"));
19
+ }
20
+ this.pendingRequests.clear();
21
+ this.onclose?.();
22
+ }
23
+ async send(message) {
24
+ if ("id" in message && message.id !== undefined) {
25
+ const pending = this.pendingRequests.get(message.id);
26
+ if (pending) {
27
+ clearTimeout(pending.timeout);
28
+ pending.resolve(message);
29
+ this.pendingRequests.delete(message.id);
30
+ }
31
+ else {
32
+ this.logger.warn(`Received response for unknown request ID: ${message.id}`);
33
+ }
34
+ }
35
+ }
36
+ async handleRequest(request) {
37
+ if (this.closed) {
38
+ throw new Error("Transport is closed");
39
+ }
40
+ if (!this.onmessage) {
41
+ throw new Error("Transport not connected - call McpServer.connect() first");
42
+ }
43
+ if (!("id" in request) || request.id === undefined) {
44
+ this.onmessage(request);
45
+ return null;
46
+ }
47
+ return new Promise((resolve, reject) => {
48
+ const pending = {
49
+ resolve,
50
+ reject,
51
+ timeout: null,
52
+ };
53
+ this.pendingRequests.set(request.id, pending);
54
+ pending.timeout = setTimeout(() => {
55
+ this.pendingRequests.delete(request.id);
56
+ reject(new Error("MCP request timeout"));
57
+ }, 30000);
58
+ this.onmessage(request);
59
+ });
60
+ }
61
+ }
62
+ exports.InMemoryTransport = InMemoryTransport;
63
+ //# sourceMappingURL=in-memory.transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory.transport.js","sourceRoot":"","sources":["../../src/tunnel/in-memory.transport.ts"],"names":[],"mappings":";;;AAEA,2CAAwC;AAQxC,MAAa,iBAAiB;IACX,MAAM,GAAG,IAAI,eAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACrD,eAAe,GAAG,IAAI,GAAG,EAA6B,CAAC;IACvD,MAAM,GAAG,KAAK,CAAC;IAEvB,OAAO,CAAc;IACrB,OAAO,CAA0B;IACjC,SAAS,CAAqC;IAE9C,KAAK,CAAC,KAAK;IAEX,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAGnB,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YAClD,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC9B,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAE7B,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;IACnB,CAAC;IAMD,KAAK,CAAC,IAAI,CAAC,OAAuB;QAChC,IAAI,IAAI,IAAI,OAAO,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YAChD,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACrD,IAAI,OAAO,EAAE,CAAC;gBACZ,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBAC9B,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACzB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,6CAA6C,OAAO,CAAC,EAAE,EAAE,CAC1D,CAAC;YACJ,CAAC;QACH,CAAC;IAEH,CAAC;IAMD,KAAK,CAAC,aAAa,CAAC,OAAuB;QACzC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CACb,0DAA0D,CAC3D,CAAC;QACJ,CAAC;QAGD,IAAI,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YACnD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAGrC,MAAM,OAAO,GAAmB;gBAC9B,OAAO;gBACP,MAAM;gBACN,OAAO,EAAE,IAAW;aACrB,CAAC;YACF,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAAe,EAAE,OAAO,CAAC,CAAC;YAG3D,OAAO,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;gBAChC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,EAAe,CAAC,CAAC;gBACrD,MAAM,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC;YAC3C,CAAC,EAAE,KAAK,CAAC,CAAC;YAIV,IAAI,CAAC,SAAU,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAvFD,8CAuFC"}
@@ -0,0 +1,6 @@
1
+ export { DeviceFlowService, DeviceFlowError, type DeviceCodeResponse, type TokenResponse, type DeviceFlowErrorResponse, } from "./device-flow.service";
2
+ export { CredentialsService } from "./credentials.service";
3
+ export type { TunnelCredentials } from "./credentials.service";
4
+ export { TunnelClient, TunnelClientError, type McpRequestHandler, } from "./tunnel.client";
5
+ export * from "./tunnel.protocol";
6
+ export { handleLogin, handleLogout, handleTunnel } from "./commands";
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.handleTunnel = exports.handleLogout = exports.handleLogin = exports.TunnelClientError = exports.TunnelClient = exports.CredentialsService = exports.DeviceFlowError = exports.DeviceFlowService = void 0;
18
+ var device_flow_service_1 = require("./device-flow.service");
19
+ Object.defineProperty(exports, "DeviceFlowService", { enumerable: true, get: function () { return device_flow_service_1.DeviceFlowService; } });
20
+ Object.defineProperty(exports, "DeviceFlowError", { enumerable: true, get: function () { return device_flow_service_1.DeviceFlowError; } });
21
+ var credentials_service_1 = require("./credentials.service");
22
+ Object.defineProperty(exports, "CredentialsService", { enumerable: true, get: function () { return credentials_service_1.CredentialsService; } });
23
+ var tunnel_client_1 = require("./tunnel.client");
24
+ Object.defineProperty(exports, "TunnelClient", { enumerable: true, get: function () { return tunnel_client_1.TunnelClient; } });
25
+ Object.defineProperty(exports, "TunnelClientError", { enumerable: true, get: function () { return tunnel_client_1.TunnelClientError; } });
26
+ __exportStar(require("./tunnel.protocol"), exports);
27
+ var commands_1 = require("./commands");
28
+ Object.defineProperty(exports, "handleLogin", { enumerable: true, get: function () { return commands_1.handleLogin; } });
29
+ Object.defineProperty(exports, "handleLogout", { enumerable: true, get: function () { return commands_1.handleLogout; } });
30
+ Object.defineProperty(exports, "handleTunnel", { enumerable: true, get: function () { return commands_1.handleTunnel; } });
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tunnel/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAKA,6DAM+B;AAL7B,wHAAA,iBAAiB,OAAA;AACjB,sHAAA,eAAe,OAAA;AAMjB,6DAA2D;AAAlD,yHAAA,kBAAkB,OAAA;AAI3B,iDAIyB;AAHvB,6GAAA,YAAY,OAAA;AACZ,kHAAA,iBAAiB,OAAA;AAKnB,oDAAkC;AAGlC,uCAAqE;AAA5D,uGAAA,WAAW,OAAA;AAAE,wGAAA,YAAY,OAAA;AAAE,wGAAA,YAAY,OAAA"}
@@ -0,0 +1,15 @@
1
+ import { OnApplicationBootstrap } from "@nestjs/common";
2
+ import { ModuleRef } from "@nestjs/core";
3
+ import { McpRegistryDiscoveryService } from "@rekog/mcp-nest";
4
+ export declare class TunnelMcpService implements OnApplicationBootstrap {
5
+ private readonly moduleRef;
6
+ private readonly registry;
7
+ private readonly logger;
8
+ private mcpServer;
9
+ private transport;
10
+ private mcpModuleId;
11
+ constructor(moduleRef: ModuleRef, registry: McpRegistryDiscoveryService);
12
+ onApplicationBootstrap(): Promise<void>;
13
+ handleRequest(body: string): Promise<string>;
14
+ private buildMcpCapabilities;
15
+ }
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var TunnelMcpService_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.TunnelMcpService = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const core_1 = require("@nestjs/core");
16
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
17
+ const mcp_nest_1 = require("@rekog/mcp-nest");
18
+ const in_memory_transport_1 = require("./in-memory.transport");
19
+ const version_1 = require("../version");
20
+ let TunnelMcpService = TunnelMcpService_1 = class TunnelMcpService {
21
+ moduleRef;
22
+ registry;
23
+ logger = new common_1.Logger(TunnelMcpService_1.name);
24
+ mcpServer;
25
+ transport;
26
+ mcpModuleId;
27
+ constructor(moduleRef, registry) {
28
+ this.moduleRef = moduleRef;
29
+ this.registry = registry;
30
+ }
31
+ async onApplicationBootstrap() {
32
+ this.logger.log("Bootstrapping MCP for tunnel mode...");
33
+ const moduleIds = this.registry.getMcpModuleIds();
34
+ if (moduleIds.length === 0) {
35
+ throw new Error("No MCP modules found - ensure McpModule is imported");
36
+ }
37
+ this.mcpModuleId = moduleIds[0];
38
+ this.logger.debug(`Using MCP module ID: ${this.mcpModuleId}`);
39
+ const capabilities = this.buildMcpCapabilities();
40
+ this.logger.debug("Built MCP capabilities:", capabilities);
41
+ this.mcpServer = new mcp_js_1.McpServer({ name: "anki-mcp-server", version: (0, version_1.getVersion)() }, { capabilities });
42
+ const contextId = core_1.ContextIdFactory.create();
43
+ const executor = await this.moduleRef.resolve(mcp_nest_1.McpExecutorService, contextId, { strict: false });
44
+ executor.registerRequestHandlers(this.mcpServer, {});
45
+ this.transport = new in_memory_transport_1.InMemoryTransport();
46
+ await this.mcpServer.connect(this.transport);
47
+ this.logger.log("MCP tunnel service ready");
48
+ }
49
+ async handleRequest(body) {
50
+ let rawMessage;
51
+ try {
52
+ rawMessage = JSON.parse(body);
53
+ }
54
+ catch (error) {
55
+ return JSON.stringify({
56
+ jsonrpc: "2.0",
57
+ id: null,
58
+ error: {
59
+ code: -32700,
60
+ message: "Parse error",
61
+ data: error instanceof Error ? error.message : String(error),
62
+ },
63
+ });
64
+ }
65
+ if (Array.isArray(rawMessage)) {
66
+ const responses = await Promise.all(rawMessage.map((msg) => this.transport.handleRequest(msg)));
67
+ const nonNullResponses = responses.filter((r) => r !== null);
68
+ return JSON.stringify(nonNullResponses);
69
+ }
70
+ const response = await this.transport.handleRequest(rawMessage);
71
+ return response ? JSON.stringify(response) : "";
72
+ }
73
+ buildMcpCapabilities() {
74
+ const capabilities = {};
75
+ if (this.registry.getTools(this.mcpModuleId).length > 0) {
76
+ capabilities.tools = {
77
+ listChanged: true,
78
+ };
79
+ }
80
+ if (this.registry.getResources(this.mcpModuleId).length > 0 ||
81
+ this.registry.getResourceTemplates(this.mcpModuleId).length > 0) {
82
+ capabilities.resources = {
83
+ listChanged: true,
84
+ };
85
+ }
86
+ if (this.registry.getPrompts(this.mcpModuleId).length > 0) {
87
+ capabilities.prompts = {
88
+ listChanged: true,
89
+ };
90
+ }
91
+ return capabilities;
92
+ }
93
+ };
94
+ exports.TunnelMcpService = TunnelMcpService;
95
+ exports.TunnelMcpService = TunnelMcpService = TunnelMcpService_1 = __decorate([
96
+ (0, common_1.Injectable)(),
97
+ __metadata("design:paramtypes", [core_1.ModuleRef,
98
+ mcp_nest_1.McpRegistryDiscoveryService])
99
+ ], TunnelMcpService);
100
+ //# sourceMappingURL=tunnel-mcp.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel-mcp.service.js","sourceRoot":"","sources":["../../src/tunnel/tunnel-mcp.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { EventEmitter } from "events";
2
+ import { CredentialsService, TunnelCredentials } from "./credentials.service";
3
+ import { DeviceFlowService } from "./device-flow.service";
4
+ export interface McpRequestHandler {
5
+ handle(request: {
6
+ method: string;
7
+ path: string;
8
+ headers: Record<string, string>;
9
+ body: string;
10
+ }): Promise<{
11
+ status: number;
12
+ headers?: Record<string, string>;
13
+ body: string;
14
+ }>;
15
+ }
16
+ export declare class TunnelClientError extends Error {
17
+ readonly code: string;
18
+ readonly originalError?: unknown | undefined;
19
+ constructor(message: string, code: string, originalError?: unknown | undefined);
20
+ }
21
+ export declare class TunnelClient extends EventEmitter {
22
+ private readonly mcpHandler;
23
+ private readonly credentialsService;
24
+ private readonly deviceFlowService;
25
+ private readonly tunnelUrl;
26
+ private readonly logger;
27
+ private ws;
28
+ private reconnectAttempts;
29
+ private reconnectTimer;
30
+ private isConnecting;
31
+ private isManualDisconnect;
32
+ private currentTunnelUrl;
33
+ private credentials;
34
+ private connectionTimeout;
35
+ private lastServerPingTime;
36
+ private healthCheckInterval;
37
+ private pongTimeout;
38
+ constructor(mcpHandler: McpRequestHandler, credentialsService: CredentialsService, deviceFlowService: DeviceFlowService, tunnelUrl: string);
39
+ connect(initialCredentials?: TunnelCredentials): Promise<string>;
40
+ disconnect(): void;
41
+ isConnected(): boolean;
42
+ getTunnelUrl(): string | null;
43
+ private establishConnection;
44
+ private handleMessage;
45
+ private handleRequest;
46
+ private handlePing;
47
+ private handleError;
48
+ private handleUrlChanged;
49
+ private sendResponse;
50
+ private sendPong;
51
+ private handleReconnection;
52
+ private startHealthCheck;
53
+ private stopHealthCheck;
54
+ private checkConnectionHealth;
55
+ private handlePong;
56
+ private refreshTokenAndSave;
57
+ private clearReconnectTimer;
58
+ private clearConnectionTimeout;
59
+ private wrapError;
60
+ }