tideways-mcp-server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +447 -0
  2. package/bin/cli.js +156 -0
  3. package/dist/config/index.d.ts +6 -0
  4. package/dist/config/index.d.ts.map +1 -0
  5. package/dist/config/index.js +55 -0
  6. package/dist/config/index.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +18 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/lib/errors.d.ts +22 -0
  12. package/dist/lib/errors.d.ts.map +1 -0
  13. package/dist/lib/errors.js +97 -0
  14. package/dist/lib/errors.js.map +1 -0
  15. package/dist/lib/logger.d.ts +12 -0
  16. package/dist/lib/logger.d.ts.map +1 -0
  17. package/dist/lib/logger.js +54 -0
  18. package/dist/lib/logger.js.map +1 -0
  19. package/dist/lib/tideways-client.d.ts +36 -0
  20. package/dist/lib/tideways-client.d.ts.map +1 -0
  21. package/dist/lib/tideways-client.js +203 -0
  22. package/dist/lib/tideways-client.js.map +1 -0
  23. package/dist/server.d.ts +10 -0
  24. package/dist/server.d.ts.map +1 -0
  25. package/dist/server.js +94 -0
  26. package/dist/server.js.map +1 -0
  27. package/dist/tools/definitions.d.ts +6 -0
  28. package/dist/tools/definitions.d.ts.map +1 -0
  29. package/dist/tools/definitions.js +158 -0
  30. package/dist/tools/definitions.js.map +1 -0
  31. package/dist/tools/handlers/historical-handler.d.ts +4 -0
  32. package/dist/tools/handlers/historical-handler.d.ts.map +1 -0
  33. package/dist/tools/handlers/historical-handler.js +12 -0
  34. package/dist/tools/handlers/historical-handler.js.map +1 -0
  35. package/dist/tools/handlers/issues-handler.d.ts +4 -0
  36. package/dist/tools/handlers/issues-handler.d.ts.map +1 -0
  37. package/dist/tools/handlers/issues-handler.js +11 -0
  38. package/dist/tools/handlers/issues-handler.js.map +1 -0
  39. package/dist/tools/handlers/performance-handler.d.ts +4 -0
  40. package/dist/tools/handlers/performance-handler.d.ts.map +1 -0
  41. package/dist/tools/handlers/performance-handler.js +11 -0
  42. package/dist/tools/handlers/performance-handler.js.map +1 -0
  43. package/dist/tools/handlers/performance-summary-handler.d.ts +4 -0
  44. package/dist/tools/handlers/performance-summary-handler.d.ts.map +1 -0
  45. package/dist/tools/handlers/performance-summary-handler.js +11 -0
  46. package/dist/tools/handlers/performance-summary-handler.js.map +1 -0
  47. package/dist/tools/handlers/traces-handler.d.ts +4 -0
  48. package/dist/tools/handlers/traces-handler.d.ts.map +1 -0
  49. package/dist/tools/handlers/traces-handler.js +30 -0
  50. package/dist/tools/handlers/traces-handler.js.map +1 -0
  51. package/dist/tools/registry.d.ts +3 -0
  52. package/dist/tools/registry.d.ts.map +1 -0
  53. package/dist/tools/registry.js +20 -0
  54. package/dist/tools/registry.js.map +1 -0
  55. package/dist/types/error.d.ts +7 -0
  56. package/dist/types/error.d.ts.map +1 -0
  57. package/dist/types/error.js +2 -0
  58. package/dist/types/error.js.map +1 -0
  59. package/dist/types/index.d.ts +6 -0
  60. package/dist/types/index.d.ts.map +1 -0
  61. package/dist/types/index.js +6 -0
  62. package/dist/types/index.js.map +1 -0
  63. package/dist/types/logging.d.ts +11 -0
  64. package/dist/types/logging.d.ts.map +1 -0
  65. package/dist/types/logging.js +2 -0
  66. package/dist/types/logging.js.map +1 -0
  67. package/dist/types/mcp.d.ts +32 -0
  68. package/dist/types/mcp.d.ts.map +1 -0
  69. package/dist/types/mcp.js +2 -0
  70. package/dist/types/mcp.js.map +1 -0
  71. package/dist/types/tideways-api.d.ts +151 -0
  72. package/dist/types/tideways-api.d.ts.map +1 -0
  73. package/dist/types/tideways-api.js +2 -0
  74. package/dist/types/tideways-api.js.map +1 -0
  75. package/dist/types/tideways-config.d.ts +15 -0
  76. package/dist/types/tideways-config.d.ts.map +1 -0
  77. package/dist/types/tideways-config.js +2 -0
  78. package/dist/types/tideways-config.js.map +1 -0
  79. package/dist/utils/date-utils.d.ts +4 -0
  80. package/dist/utils/date-utils.d.ts.map +1 -0
  81. package/dist/utils/date-utils.js +16 -0
  82. package/dist/utils/date-utils.js.map +1 -0
  83. package/package.json +86 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACvC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAc,CAAC,CAAC;QACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;IACnB,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;IAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { ErrorCategory, TidewaysError } from '../types/index.js';
2
+ export declare class TidewaysAPIError extends Error implements TidewaysError {
3
+ category: ErrorCategory;
4
+ statusCode?: number;
5
+ retryAfter?: number;
6
+ constructor(message: string, category: ErrorCategory, statusCode?: number, retryAfter?: number);
7
+ }
8
+ export declare class ErrorHandler {
9
+ /**
10
+ * Handle API errors and convert them to user-friendly messages
11
+ */
12
+ static handleApiError(error: any): TidewaysAPIError;
13
+ static handleValidationError(message: string): TidewaysAPIError;
14
+ static formatErrorForUser(error: TidewaysAPIError): string;
15
+ /**
16
+ * Handle partial failures gracefully
17
+ */
18
+ static handlePartialFailure(errors: TidewaysAPIError[], partialData?: any): string;
19
+ static isRetryable(error: TidewaysAPIError): boolean;
20
+ static getRetryDelay(error: TidewaysAPIError, attempt: number): number;
21
+ }
22
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEjE,qBAAa,gBAAiB,SAAQ,KAAM,YAAW,aAAa;IAC3D,QAAQ,EAAE,aAAa,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;gBAEf,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAS/F;AAED,qBAAa,YAAY;IACvB;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,gBAAgB;IAoEnD,MAAM,CAAC,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB;IAK/D,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM;IA4B1D;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,EAAE,EAAE,WAAW,CAAC,EAAE,GAAG,GAAG,MAAM;IAUlF,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO;IAQpD,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;CAOvE"}
@@ -0,0 +1,97 @@
1
+ import { logger } from './logger.js';
2
+ export class TidewaysAPIError extends Error {
3
+ category;
4
+ statusCode;
5
+ retryAfter;
6
+ constructor(message, category, statusCode, retryAfter) {
7
+ super(message);
8
+ this.name = 'TidewaysAPIError';
9
+ this.category = category;
10
+ this.statusCode = statusCode;
11
+ this.retryAfter = retryAfter;
12
+ Error.captureStackTrace(this, TidewaysAPIError);
13
+ }
14
+ }
15
+ export class ErrorHandler {
16
+ /**
17
+ * Handle API errors and convert them to user-friendly messages
18
+ */
19
+ static handleApiError(error) {
20
+ logger.error('API error occurred', error, {
21
+ url: error.config?.url,
22
+ method: error.config?.method,
23
+ status: error.response?.status,
24
+ });
25
+ if (error.response?.status === 429) {
26
+ const resetTime = error.response.headers['x-ratelimit-reset'];
27
+ const retryAfter = resetTime ? parseInt(resetTime, 10) * 1000 : undefined;
28
+ return new TidewaysAPIError('Rate limit exceeded. Please try again later.', 'rate_limit', 429, retryAfter);
29
+ }
30
+ if (error.response?.status === 401) {
31
+ return new TidewaysAPIError('Authentication failed. Please check your API token.', 'auth', 401);
32
+ }
33
+ if (error.response?.status === 403) {
34
+ return new TidewaysAPIError('Access denied. Your token may not have the required scopes for this operation.', 'auth', 403);
35
+ }
36
+ if (error.response?.status === 404) {
37
+ return new TidewaysAPIError('Resource not found. Please check your organization and project settings.', 'api', 404);
38
+ }
39
+ if (error.response?.status >= 500) {
40
+ return new TidewaysAPIError('Tideways API server error. Please try again later.', 'api', error.response.status);
41
+ }
42
+ if (error.code === 'ECONNREFUSED' || error.code === 'ENOTFOUND') {
43
+ return new TidewaysAPIError('Network error: Unable to connect to Tideways API. Please check your internet connection.', 'network');
44
+ }
45
+ if (error.code === 'ECONNABORTED') {
46
+ return new TidewaysAPIError('Request timeout: Tideways API took too long to respond.', 'network');
47
+ }
48
+ return new TidewaysAPIError(`Unexpected error: ${error.message}`, 'unknown');
49
+ }
50
+ static handleValidationError(message) {
51
+ logger.warn('Validation error', { message });
52
+ return new TidewaysAPIError(message, 'validation');
53
+ }
54
+ static formatErrorForUser(error) {
55
+ const baseMessage = error.message;
56
+ switch (error.category) {
57
+ case 'rate_limit':
58
+ if (error.retryAfter) {
59
+ const retryDate = new Date(Date.now() + error.retryAfter);
60
+ return `${baseMessage} Rate limit resets at: ${retryDate.toISOString()}`;
61
+ }
62
+ return `${baseMessage} Please wait a few minutes before trying again.`;
63
+ case 'auth':
64
+ return `${baseMessage}\n\nSuggestions:\n• Verify your TIDEWAYS_TOKEN environment variable\n• Check that your token has the required scopes (metrics, issues, traces)\n• Ensure your token hasn't expired`;
65
+ case 'network':
66
+ return `${baseMessage}\n\nSuggestions:\n• Check your internet connection\n• Verify Tideways API is accessible from your network\n• Try again in a few minutes`;
67
+ case 'api':
68
+ return `${baseMessage}\n\nSuggestions:\n• Verify your TIDEWAYS_ORG and TIDEWAYS_PROJECT settings\n• Check if the resource exists in your Tideways dashboard\n• Try again in a few minutes if this is a temporary server issue`;
69
+ case 'validation':
70
+ return `${baseMessage}\n\nPlease check your input parameters and try again.`;
71
+ default:
72
+ return `${baseMessage}\n\nIf this error persists, please check the server logs for more details.`;
73
+ }
74
+ }
75
+ /**
76
+ * Handle partial failures gracefully
77
+ */
78
+ static handlePartialFailure(errors, partialData) {
79
+ const errorSummary = errors.map(err => `• ${err.category}: ${err.message}`).join('\n');
80
+ if (partialData && Object.keys(partialData).length > 0) {
81
+ return `⚠️ Partial data available (some sources failed):\n\nIssues encountered:\n${errorSummary}\n\nNote: Analysis may be incomplete. Try again in a few minutes.`;
82
+ }
83
+ return `❌ Unable to retrieve performance data:\n\n${errorSummary}\n\nSuggestions:\n• Check your internet connection\n• Verify API token permissions\n• Try again in a few minutes (may be temporary API issue)`;
84
+ }
85
+ static isRetryable(error) {
86
+ return (error.category === 'network' ||
87
+ (error.category === 'api' && error.statusCode && error.statusCode >= 500) ||
88
+ error.category === 'rate_limit');
89
+ }
90
+ static getRetryDelay(error, attempt) {
91
+ if (error.retryAfter) {
92
+ return error.retryAfter;
93
+ }
94
+ return Math.min(1000 * Math.pow(2, attempt), 30000);
95
+ }
96
+ }
97
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAClC,QAAQ,CAAgB;IACxB,UAAU,CAAU;IACpB,UAAU,CAAU;IAE3B,YAAY,OAAe,EAAE,QAAuB,EAAE,UAAmB,EAAE,UAAmB;QAC5F,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAE7B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IAClD,CAAC;CACF;AAED,MAAM,OAAO,YAAY;IACvB;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,KAAU;QAC9B,MAAM,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,EAAE;YACxC,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,GAAG;YACtB,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM;YAC5B,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM;SAC/B,CAAC,CAAC;QAEH,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,EAAE,CAAC;YACnC,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;YAC9D,MAAM,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;YAE1E,OAAO,IAAI,gBAAgB,CACzB,8CAA8C,EAC9C,YAAY,EACZ,GAAG,EACH,UAAU,CACX,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,EAAE,CAAC;YACnC,OAAO,IAAI,gBAAgB,CACzB,qDAAqD,EACrD,MAAM,EACN,GAAG,CACJ,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,EAAE,CAAC;YACnC,OAAO,IAAI,gBAAgB,CACzB,gFAAgF,EAChF,MAAM,EACN,GAAG,CACJ,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,EAAE,CAAC;YACnC,OAAO,IAAI,gBAAgB,CACzB,0EAA0E,EAC1E,KAAK,EACL,GAAG,CACJ,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,EAAE,CAAC;YAClC,OAAO,IAAI,gBAAgB,CACzB,oDAAoD,EACpD,KAAK,EACL,KAAK,CAAC,QAAQ,CAAC,MAAM,CACtB,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAChE,OAAO,IAAI,gBAAgB,CACzB,0FAA0F,EAC1F,SAAS,CACV,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAClC,OAAO,IAAI,gBAAgB,CACzB,yDAAyD,EACzD,SAAS,CACV,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,gBAAgB,CAAC,qBAAqB,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IAC/E,CAAC;IAED,MAAM,CAAC,qBAAqB,CAAC,OAAe;QAC1C,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC7C,OAAO,IAAI,gBAAgB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,CAAC,kBAAkB,CAAC,KAAuB;QAC/C,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC;QAElC,QAAQ,KAAK,CAAC,QAAQ,EAAE,CAAC;YACvB,KAAK,YAAY;gBACf,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;oBACrB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;oBAC1D,OAAO,GAAG,WAAW,0BAA0B,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC3E,CAAC;gBACD,OAAO,GAAG,WAAW,iDAAiD,CAAC;YAEzE,KAAK,MAAM;gBACT,OAAO,GAAG,WAAW,oLAAoL,CAAC;YAE5M,KAAK,SAAS;gBACZ,OAAO,GAAG,WAAW,yIAAyI,CAAC;YAEjK,KAAK,KAAK;gBACR,OAAO,GAAG,WAAW,yMAAyM,CAAC;YAEjO,KAAK,YAAY;gBACf,OAAO,GAAG,WAAW,uDAAuD,CAAC;YAE/E;gBACE,OAAO,GAAG,WAAW,4EAA4E,CAAC;QACtG,CAAC;IACH,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,MAA0B,EAAE,WAAiB;QACvE,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEvF,IAAI,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvD,OAAO,4EAA4E,YAAY,mEAAmE,CAAC;QACrK,CAAC;QAED,OAAO,6CAA6C,YAAY,+IAA+I,CAAC;IAClN,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,KAAuB;QACxC,OAAO,CACL,KAAK,CAAC,QAAQ,KAAK,SAAS;YAC5B,CAAC,KAAK,CAAC,QAAQ,KAAK,KAAK,IAAI,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,IAAI,GAAG,CAAC;YACzE,KAAK,CAAC,QAAQ,KAAK,YAAY,CAChC,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,aAAa,CAAC,KAAuB,EAAE,OAAe;QAC3D,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC,UAAU,CAAC;QAC1B,CAAC;QAED,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ import { Logger, LogContext } from '../types/index.js';
2
+ declare class ConsoleLogger implements Logger {
3
+ private shouldLog;
4
+ private formatMessage;
5
+ debug(message: string, context?: LogContext): void;
6
+ info(message: string, context?: LogContext): void;
7
+ warn(message: string, context?: LogContext): void;
8
+ error(message: string, error?: Error, context?: LogContext): void;
9
+ }
10
+ export declare const logger: ConsoleLogger;
11
+ export {};
12
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAY,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEjE,cAAM,aAAc,YAAW,MAAM;IACnC,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,aAAa;IAWrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAMlD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAMjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAMjD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;CAelE;AAED,eAAO,MAAM,MAAM,eAAsB,CAAC"}
@@ -0,0 +1,54 @@
1
+ class ConsoleLogger {
2
+ shouldLog(level) {
3
+ const logLevel = process.env.LOG_LEVEL?.toLowerCase() || 'info';
4
+ const levels = {
5
+ debug: 0,
6
+ info: 1,
7
+ warn: 2,
8
+ error: 3,
9
+ };
10
+ return levels[level] >= levels[logLevel];
11
+ }
12
+ formatMessage(level, message, context) {
13
+ const timestamp = new Date().toISOString();
14
+ const logEntry = {
15
+ timestamp,
16
+ level,
17
+ message,
18
+ ...(context && { context }),
19
+ };
20
+ return JSON.stringify(logEntry);
21
+ }
22
+ debug(message, context) {
23
+ if (this.shouldLog('debug')) {
24
+ process.stderr.write(this.formatMessage('debug', message, context) + '\n');
25
+ }
26
+ }
27
+ info(message, context) {
28
+ if (this.shouldLog('info')) {
29
+ process.stderr.write(this.formatMessage('info', message, context) + '\n');
30
+ }
31
+ }
32
+ warn(message, context) {
33
+ if (this.shouldLog('warn')) {
34
+ process.stderr.write(this.formatMessage('warn', message, context) + '\n');
35
+ }
36
+ }
37
+ error(message, error, context) {
38
+ if (this.shouldLog('error')) {
39
+ const errorContext = {
40
+ ...context,
41
+ ...(error && {
42
+ error: {
43
+ message: error.message,
44
+ stack: error.stack,
45
+ name: error.name,
46
+ },
47
+ }),
48
+ };
49
+ process.stderr.write(this.formatMessage('error', message, errorContext) + '\n');
50
+ }
51
+ }
52
+ }
53
+ export const logger = new ConsoleLogger();
54
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAEA,MAAM,aAAa;IACT,SAAS,CAAC,KAAe;QAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,MAAM,CAAC;QAChE,MAAM,MAAM,GAA6B;YACvC,KAAK,EAAE,CAAC;YACR,IAAI,EAAE,CAAC;YACP,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,CAAC;SACT,CAAC;QACF,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,QAAoB,CAAC,CAAC;IACvD,CAAC;IAEO,aAAa,CAAC,KAAe,EAAE,OAAe,EAAE,OAAoB;QAC1E,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAG;YACf,SAAS;YACT,KAAK;YACL,OAAO;YACP,GAAG,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,CAAC;SAC5B,CAAC;QACF,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,OAAoB;QACzC,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,OAAoB;QACxC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,OAAoB;QACxC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,KAAa,EAAE,OAAoB;QACxD,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,YAAY,GAAG;gBACnB,GAAG,OAAO;gBACV,GAAG,CAAC,KAAK,IAAI;oBACX,KAAK,EAAE;wBACL,OAAO,EAAE,KAAK,CAAC,OAAO;wBACtB,KAAK,EAAE,KAAK,CAAC,KAAK;wBAClB,IAAI,EAAE,KAAK,CAAC,IAAI;qBACjB;iBACF,CAAC;aACH,CAAC;YACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,GAAG,IAAI,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;CACF;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { TidewaysConfig, TidewaysPerformanceData, TidewaysPerformanceSummaryData, TidewaysIssuesResponse, TidewaysTracesResponse, TidewaysHistoryResponse, GetPerformanceMetricsParams, GetPerformanceSummaryParams } from '../types/index.js';
2
+ export declare class TidewaysClient {
3
+ private client;
4
+ private config;
5
+ private rateLimiter;
6
+ constructor(config: TidewaysConfig);
7
+ private setupInterceptors;
8
+ fetch<T>(endpoint: string, params?: Record<string, any>): Promise<T>;
9
+ getPerformanceMetrics(params?: GetPerformanceMetricsParams): Promise<TidewaysPerformanceData>;
10
+ getPerformanceSummary(params?: GetPerformanceSummaryParams): Promise<TidewaysPerformanceSummaryData>;
11
+ getIssues(params?: {
12
+ issue_type?: string;
13
+ status?: string;
14
+ page?: number;
15
+ }): Promise<TidewaysIssuesResponse>;
16
+ getTraces(params?: {
17
+ env?: string;
18
+ s?: string;
19
+ transaction_name?: string;
20
+ has_callgraph?: boolean;
21
+ search?: string;
22
+ min_date?: string;
23
+ max_date?: string;
24
+ min_response_time_ms?: number;
25
+ max_response_time_ms?: number;
26
+ sort_by?: string;
27
+ sort_order?: string;
28
+ }): Promise<TidewaysTracesResponse>;
29
+ getHistoricalData(date: string, granularity?: string): Promise<TidewaysHistoryResponse>;
30
+ healthCheck(): Promise<{
31
+ status: 'healthy' | 'unhealthy';
32
+ message: string;
33
+ details?: any;
34
+ }>;
35
+ }
36
+ //# sourceMappingURL=tideways-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tideways-client.d.ts","sourceRoot":"","sources":["../../src/lib/tideways-client.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,8BAA8B,EAC9B,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,2BAA2B,EAC3B,2BAA2B,EAC5B,MAAM,mBAAmB,CAAC;AAuC3B,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,WAAW,CAAc;gBAErB,MAAM,EAAE,cAAc;IAiBlC,OAAO,CAAC,iBAAiB;IAkDnB,KAAK,CAAC,CAAC,EACX,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC3B,OAAO,CAAC,CAAC,CAAC;IA+BP,qBAAqB,CAAC,MAAM,CAAC,EAAE,2BAA2B,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAsB7F,qBAAqB,CAAC,MAAM,CAAC,EAAE,2BAA2B,GAAG,OAAO,CAAC,8BAA8B,CAAC;IAcpG,SAAS,CAAC,MAAM,CAAC,EAAE;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAc7B,SAAS,CAAC,MAAM,CAAC,EAAE;QACvB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,CAAC,CAAC,EAAE,MAAM,CAAC;QACX,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAK7B,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,GAAE,MAAc,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAqB9F,WAAW,IAAI,OAAO,CAAC;QAC3B,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;QAChC,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,GAAG,CAAC;KACf,CAAC;CAiCH"}
@@ -0,0 +1,203 @@
1
+ import axios from 'axios';
2
+ import { ErrorHandler, TidewaysAPIError } from './errors.js';
3
+ import { logger } from './logger.js';
4
+ class RateLimiter {
5
+ requests = [];
6
+ maxRequests;
7
+ windowMs;
8
+ constructor(maxRequests = 900, windowMs = 3600000) {
9
+ this.maxRequests = maxRequests;
10
+ this.windowMs = windowMs;
11
+ }
12
+ async acquire() {
13
+ const now = Date.now();
14
+ this.requests = this.requests.filter(timestamp => now - timestamp < this.windowMs);
15
+ if (this.requests.length >= this.maxRequests) {
16
+ const oldestRequest = Math.min(...this.requests);
17
+ const waitTime = this.windowMs - (now - oldestRequest);
18
+ logger.warn('Rate limit reached, waiting', { waitTimeMs: waitTime });
19
+ await new Promise(resolve => setTimeout(resolve, waitTime));
20
+ return this.acquire(); // Try again after waiting
21
+ }
22
+ this.requests.push(now);
23
+ }
24
+ updateLimits(remaining, resetTime) {
25
+ if (remaining === 0) {
26
+ const waitTime = resetTime * 1000 - Date.now();
27
+ logger.warn('API rate limit exhausted', { resetTime, waitTimeMs: waitTime });
28
+ }
29
+ }
30
+ }
31
+ export class TidewaysClient {
32
+ client;
33
+ config;
34
+ rateLimiter;
35
+ constructor(config) {
36
+ this.config = config;
37
+ this.rateLimiter = new RateLimiter();
38
+ this.client = axios.create({
39
+ baseURL: config.baseUrl,
40
+ timeout: config.requestTimeout,
41
+ headers: {
42
+ Authorization: `Bearer ${config.token}`,
43
+ 'Content-Type': 'application/json',
44
+ 'User-Agent': 'Tideways-MCP-Server/0.1.0',
45
+ },
46
+ });
47
+ this.setupInterceptors();
48
+ }
49
+ setupInterceptors() {
50
+ this.client.interceptors.request.use(async (config) => {
51
+ await this.rateLimiter.acquire();
52
+ const safeHeaders = { ...config.headers };
53
+ if (safeHeaders.Authorization) {
54
+ safeHeaders.Authorization = 'Bearer [REDACTED]';
55
+ }
56
+ const sensitiveHeaders = ['X-API-Key', 'X-Auth-Token', 'Cookie', 'Set-Cookie'];
57
+ sensitiveHeaders.forEach(header => {
58
+ if (safeHeaders[header]) {
59
+ safeHeaders[header] = '[REDACTED]';
60
+ }
61
+ });
62
+ logger.debug('API request', {
63
+ method: config.method?.toUpperCase(),
64
+ url: config.url,
65
+ params: config.params,
66
+ headers: safeHeaders,
67
+ });
68
+ return config;
69
+ });
70
+ this.client.interceptors.response.use(response => {
71
+ const remaining = response.headers['x-ratelimit-remaining'];
72
+ const resetTime = response.headers['x-ratelimit-reset'];
73
+ if (remaining && resetTime) {
74
+ this.rateLimiter.updateLimits(parseInt(remaining, 10), parseInt(resetTime, 10));
75
+ }
76
+ logger.debug('API response', {
77
+ status: response.status,
78
+ url: response.config.url,
79
+ rateLimitRemaining: remaining,
80
+ });
81
+ return response;
82
+ }, error => {
83
+ return Promise.reject(ErrorHandler.handleApiError(error));
84
+ });
85
+ }
86
+ async fetch(endpoint, params) {
87
+ let lastError = null;
88
+ const maxRetries = this.config.maxRetries || 3;
89
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
90
+ try {
91
+ const response = await this.client.get(endpoint, { params });
92
+ return response.data;
93
+ }
94
+ catch (error) {
95
+ lastError = error;
96
+ if (!ErrorHandler.isRetryable(lastError) || attempt >= maxRetries) {
97
+ break;
98
+ }
99
+ const delay = ErrorHandler.getRetryDelay(lastError, attempt);
100
+ logger.warn('Retrying API request', {
101
+ endpoint,
102
+ attempt: attempt + 1,
103
+ maxRetries,
104
+ delayMs: delay,
105
+ error: lastError.message,
106
+ });
107
+ await new Promise(resolve => setTimeout(resolve, delay));
108
+ }
109
+ }
110
+ throw lastError || new TidewaysAPIError('Unknown error occurred', 'unknown');
111
+ }
112
+ async getPerformanceMetrics(params) {
113
+ const apiParams = {
114
+ env: params?.env || 'production',
115
+ s: params?.s || 'web',
116
+ };
117
+ if (params?.ts) {
118
+ apiParams.ts = params.ts;
119
+ }
120
+ if (params?.m) {
121
+ apiParams.m = params.m;
122
+ }
123
+ logger.debug('Performance metrics parameters', {
124
+ input_params: params,
125
+ api_params: apiParams,
126
+ });
127
+ const endpoint = `/${this.config.organization}/${this.config.project}/performance`;
128
+ return this.fetch(endpoint, apiParams);
129
+ }
130
+ async getPerformanceSummary(params) {
131
+ const apiParams = {
132
+ s: params?.s || 'web',
133
+ };
134
+ logger.debug('Performance summary parameters', {
135
+ input_params: params,
136
+ api_params: apiParams,
137
+ });
138
+ const endpoint = `/${this.config.organization}/${this.config.project}/summary`;
139
+ return this.fetch(endpoint, apiParams);
140
+ }
141
+ async getIssues(params) {
142
+ const apiParams = {
143
+ status: params?.status || 'open',
144
+ page: params?.page || 1,
145
+ };
146
+ if (params?.issue_type && params.issue_type !== 'all') {
147
+ apiParams.issueType = params.issue_type;
148
+ }
149
+ const endpoint = `/${this.config.organization}/${this.config.project}/issues`;
150
+ return this.fetch(endpoint, apiParams);
151
+ }
152
+ async getTraces(params) {
153
+ const endpoint = `/${this.config.organization}/${this.config.project}/traces`;
154
+ return this.fetch(endpoint, params);
155
+ }
156
+ async getHistoricalData(date, granularity = 'day') {
157
+ const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
158
+ if (!dateRegex.test(date)) {
159
+ throw ErrorHandler.handleValidationError(`Invalid date format. Expected YYYY-MM-DD, got: ${date}`);
160
+ }
161
+ const validGranularities = ['day', 'week', 'month'];
162
+ if (!validGranularities.includes(granularity)) {
163
+ throw ErrorHandler.handleValidationError(`Invalid granularity. Expected one of: ${validGranularities.join(', ')}, got: ${granularity}`);
164
+ }
165
+ let endpoint = `/${this.config.organization}/${this.config.project}/history/${date}`;
166
+ if (granularity !== 'day') {
167
+ endpoint += `/${granularity}`;
168
+ }
169
+ logger.debug('Fetching historical data', { date, granularity, endpoint });
170
+ return this.fetch(endpoint, {});
171
+ }
172
+ async healthCheck() {
173
+ try {
174
+ const response = await this.client.get('/_token');
175
+ if (response.data && response.data.scopes) {
176
+ logger.info('Tideways API token verified', {
177
+ scopes: response.data.scopes,
178
+ projects: response.data.projects?.length || 0,
179
+ });
180
+ return {
181
+ status: 'healthy',
182
+ message: 'Successfully connected to Tideways API',
183
+ };
184
+ }
185
+ return {
186
+ status: 'healthy',
187
+ message: 'Connected to Tideways API',
188
+ };
189
+ }
190
+ catch (error) {
191
+ const tidewaysError = error;
192
+ return {
193
+ status: 'unhealthy',
194
+ message: ErrorHandler.formatErrorForUser(tidewaysError),
195
+ details: {
196
+ category: tidewaysError.category,
197
+ statusCode: tidewaysError.statusCode,
198
+ },
199
+ };
200
+ }
201
+ }
202
+ }
203
+ //# sourceMappingURL=tideways-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tideways-client.js","sourceRoot":"","sources":["../../src/lib/tideways-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export declare class TidewaysMCPServer {
2
+ private server;
3
+ private tidewaysClient;
4
+ private config;
5
+ constructor();
6
+ private setupHandlers;
7
+ start(): Promise<void>;
8
+ private shutdown;
9
+ }
10
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAcA,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,MAAM,CAAe;;IAoB7B,OAAO,CAAC,aAAa;IAyCf,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YA6Bd,QAAQ;CAKvB"}
package/dist/server.js ADDED
@@ -0,0 +1,94 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
4
+ import { TidewaysClient } from './lib/tideways-client.js';
5
+ import { logger } from './lib/logger.js';
6
+ import { loadConfig } from './config/index.js';
7
+ import { ErrorHandler, TidewaysAPIError } from './lib/errors.js';
8
+ import { getToolDefinitions } from './tools/definitions.js';
9
+ import { executeTool } from './tools/registry.js';
10
+ export class TidewaysMCPServer {
11
+ server;
12
+ tidewaysClient;
13
+ config;
14
+ constructor() {
15
+ this.config = loadConfig();
16
+ this.tidewaysClient = new TidewaysClient(this.config);
17
+ this.server = new Server({
18
+ name: 'tideways-mcp-server',
19
+ version: '0.1.0',
20
+ }, {
21
+ capabilities: {
22
+ tools: {},
23
+ },
24
+ });
25
+ this.setupHandlers();
26
+ }
27
+ setupHandlers() {
28
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
29
+ return {
30
+ tools: getToolDefinitions(),
31
+ };
32
+ });
33
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
34
+ const { name, arguments: args } = request.params;
35
+ logger.info('Tool called', { toolName: name, arguments: args });
36
+ try {
37
+ const result = await executeTool(name, args, this.tidewaysClient);
38
+ return {
39
+ content: [
40
+ {
41
+ type: 'text',
42
+ text: result,
43
+ },
44
+ ],
45
+ };
46
+ }
47
+ catch (error) {
48
+ logger.error('Tool execution failed', error, { toolName: name, arguments: args });
49
+ const tidewaysError = error instanceof TidewaysAPIError
50
+ ? error
51
+ : ErrorHandler.handleApiError(error);
52
+ return {
53
+ content: [
54
+ {
55
+ type: 'text',
56
+ text: `Error: ${ErrorHandler.formatErrorForUser(tidewaysError)}`,
57
+ },
58
+ ],
59
+ };
60
+ }
61
+ });
62
+ }
63
+ async start() {
64
+ logger.info('Starting Tideways MCP Server', {
65
+ version: '0.1.0',
66
+ organization: this.config.organization,
67
+ project: this.config.project,
68
+ });
69
+ try {
70
+ const health = await this.tidewaysClient.healthCheck();
71
+ if (health.status === 'healthy') {
72
+ logger.info('Tideways API connection verified');
73
+ }
74
+ else {
75
+ logger.warn('Tideways API health check failed, but starting server anyway', health);
76
+ }
77
+ }
78
+ catch (error) {
79
+ logger.warn('Tideways API health check failed, but starting server anyway', {
80
+ error: error.message,
81
+ });
82
+ }
83
+ const transport = new StdioServerTransport();
84
+ await this.server.connect(transport);
85
+ logger.info('Tideways MCP Server started successfully');
86
+ process.on('SIGINT', () => this.shutdown());
87
+ process.on('SIGTERM', () => this.shutdown());
88
+ }
89
+ async shutdown() {
90
+ logger.info('Shutting down Tideways MCP Server');
91
+ process.exit(0);
92
+ }
93
+ }
94
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Tool } from '@modelcontextprotocol/sdk/types.js';
2
+ export declare const TRACE_CONFIG: {
3
+ readonly MAX_DATE_RANGE_DAYS: 90;
4
+ };
5
+ export declare function getToolDefinitions(): Tool[];
6
+ //# sourceMappingURL=definitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/tools/definitions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC1D,eAAO,MAAM,YAAY;;CAEf,CAAC;AAEX,wBAAgB,kBAAkB,IAAI,IAAI,EAAE,CA8J3C"}