nexup-mcp-server 1.0.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 (66) hide show
  1. package/README.md +41 -0
  2. package/dist/client/auth.d.ts +6 -0
  3. package/dist/client/auth.d.ts.map +1 -0
  4. package/dist/client/auth.js +14 -0
  5. package/dist/client/auth.js.map +1 -0
  6. package/dist/client/http-client.d.ts +33 -0
  7. package/dist/client/http-client.d.ts.map +1 -0
  8. package/dist/client/http-client.js +149 -0
  9. package/dist/client/http-client.js.map +1 -0
  10. package/dist/config.d.ts +7 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +19 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +108 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/resources/crm-resources.d.ts +8 -0
  19. package/dist/resources/crm-resources.d.ts.map +1 -0
  20. package/dist/resources/crm-resources.js +501 -0
  21. package/dist/resources/crm-resources.js.map +1 -0
  22. package/dist/resources/index.d.ts +2 -0
  23. package/dist/resources/index.d.ts.map +1 -0
  24. package/dist/resources/index.js +2 -0
  25. package/dist/resources/index.js.map +1 -0
  26. package/dist/tools/customers.d.ts +221 -0
  27. package/dist/tools/customers.d.ts.map +1 -0
  28. package/dist/tools/customers.js +207 -0
  29. package/dist/tools/customers.js.map +1 -0
  30. package/dist/tools/index.d.ts +883 -0
  31. package/dist/tools/index.d.ts.map +1 -0
  32. package/dist/tools/index.js +38 -0
  33. package/dist/tools/index.js.map +1 -0
  34. package/dist/tools/notifications.d.ts +16 -0
  35. package/dist/tools/notifications.d.ts.map +1 -0
  36. package/dist/tools/notifications.js +47 -0
  37. package/dist/tools/notifications.js.map +1 -0
  38. package/dist/tools/prospects.d.ts +478 -0
  39. package/dist/tools/prospects.d.ts.map +1 -0
  40. package/dist/tools/prospects.js +336 -0
  41. package/dist/tools/prospects.js.map +1 -0
  42. package/dist/tools/tickets.d.ts +83 -0
  43. package/dist/tools/tickets.d.ts.map +1 -0
  44. package/dist/tools/tickets.js +171 -0
  45. package/dist/tools/tickets.js.map +1 -0
  46. package/dist/tools/transcripts.d.ts +97 -0
  47. package/dist/tools/transcripts.d.ts.map +1 -0
  48. package/dist/tools/transcripts.js +188 -0
  49. package/dist/tools/transcripts.js.map +1 -0
  50. package/dist/utils/errors.d.ts +9 -0
  51. package/dist/utils/errors.d.ts.map +1 -0
  52. package/dist/utils/errors.js +28 -0
  53. package/dist/utils/errors.js.map +1 -0
  54. package/dist/utils/formatters.d.ts +5 -0
  55. package/dist/utils/formatters.d.ts.map +1 -0
  56. package/dist/utils/formatters.js +21 -0
  57. package/dist/utils/formatters.js.map +1 -0
  58. package/dist/utils/logger.d.ts +4 -0
  59. package/dist/utils/logger.d.ts.map +1 -0
  60. package/dist/utils/logger.js +43 -0
  61. package/dist/utils/logger.js.map +1 -0
  62. package/dist/validation/schemas.d.ts +424 -0
  63. package/dist/validation/schemas.d.ts.map +1 -0
  64. package/dist/validation/schemas.js +114 -0
  65. package/dist/validation/schemas.js.map +1 -0
  66. package/package.json +34 -0
package/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # MCP Server for NexUp CRM
2
+
3
+ Model Context Protocol server that enables Claude to operate as a first-class CRM user.
4
+
5
+ ## Setup
6
+
7
+ 1. Install dependencies:
8
+ ```bash
9
+ cd mcp-server
10
+ npm install
11
+ ```
12
+
13
+ 2. Build the server:
14
+ ```bash
15
+ npm run build
16
+ ```
17
+
18
+ 3. Configure Claude Desktop (see `/docs/MCP_SETUP.md` for details)
19
+
20
+ ## Development
21
+
22
+ Run in development mode with auto-reload:
23
+ ```bash
24
+ npm run dev
25
+ ```
26
+
27
+ ## Environment Variables
28
+
29
+ Required environment variables (set in Claude Desktop config):
30
+ - `MCP_API_URL` - Next.js API URL (e.g., http://localhost:3000 or https://nexup-crm.vercel.app)
31
+ - `MCP_API_KEY` - Your MCP API key from Settings → MCP Setup
32
+ - `MCP_LOG_LEVEL` - (Optional) Logging level (debug|info|warn|error, default: info)
33
+
34
+ ## Architecture
35
+
36
+ - **stdio transport** - Communicates with Claude Desktop via stdin/stdout
37
+ - **HTTP client** - Calls Next.js API with Clerk authentication
38
+ - **Per-user isolation** - Each user runs their own MCP server instance
39
+ - **Full audit trail** - All operations logged with user attribution
40
+
41
+ See `/docs/MCP_TOOLS_REFERENCE.md` for complete tool documentation.
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Auth helper to verify Clerk session token is valid
3
+ * This is a simple check - actual auth is handled by the API
4
+ */
5
+ export declare function validateAuth(): void;
6
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/client/auth.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAQnC"}
@@ -0,0 +1,14 @@
1
+ import { config } from '../config.js';
2
+ /**
3
+ * Auth helper to verify Clerk session token is valid
4
+ * This is a simple check - actual auth is handled by the API
5
+ */
6
+ export function validateAuth() {
7
+ if (!config.clerkSessionToken) {
8
+ throw new Error('Clerk session token is required');
9
+ }
10
+ if (!config.userEmail) {
11
+ throw new Error('User email is required for audit logging');
12
+ }
13
+ }
14
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/client/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC"}
@@ -0,0 +1,33 @@
1
+ export declare class HttpClient {
2
+ private client;
3
+ private retryAttempts;
4
+ private retryDelay;
5
+ constructor();
6
+ /**
7
+ * Make a GET request with retry logic
8
+ */
9
+ get<T = any>(endpoint: string, params?: Record<string, any>): Promise<T>;
10
+ /**
11
+ * Make a POST request with retry logic
12
+ */
13
+ post<T = any>(endpoint: string, data: any, toolName?: string): Promise<T>;
14
+ /**
15
+ * Make a PATCH request with retry logic
16
+ */
17
+ patch<T = any>(endpoint: string, data: any, toolName?: string): Promise<T>;
18
+ /**
19
+ * Make a DELETE request with retry logic
20
+ */
21
+ delete<T = any>(endpoint: string, toolName?: string): Promise<T>;
22
+ /**
23
+ * Request with exponential backoff retry logic
24
+ */
25
+ private requestWithRetry;
26
+ /**
27
+ * Handle and format errors
28
+ */
29
+ private handleError;
30
+ private sleep;
31
+ }
32
+ export declare const httpClient: HttpClient;
33
+ //# sourceMappingURL=http-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../../src/client/http-client.ts"],"names":[],"mappings":"AAOA,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,UAAU,CAAQ;;IAe1B;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAI9E;;OAEG;IACG,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAQ/E;;OAEG;IACG,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAQhF;;OAEG;IACG,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAQtE;;OAEG;YACW,gBAAgB;IAoD9B;;OAEG;IACH,OAAO,CAAC,WAAW;IAkFnB,OAAO,CAAC,KAAK;CAGd;AAGD,eAAO,MAAM,UAAU,YAAmB,CAAC"}
@@ -0,0 +1,149 @@
1
+ import axios from 'axios';
2
+ import { config } from '../config.js';
3
+ import { McpError } from '../utils/errors.js';
4
+ import { logger } from '../utils/logger.js';
5
+ const MCP_VERSION = '1.0.0';
6
+ export class HttpClient {
7
+ client;
8
+ retryAttempts = 3;
9
+ retryDelay = 1000; // ms
10
+ constructor() {
11
+ this.client = axios.create({
12
+ baseURL: config.apiUrl,
13
+ headers: {
14
+ 'Content-Type': 'application/json',
15
+ 'Authorization': `Bearer ${config.apiKey}`,
16
+ 'X-MCP-Client': 'true',
17
+ 'X-MCP-Version': MCP_VERSION,
18
+ },
19
+ timeout: 30000, // 30 seconds
20
+ });
21
+ }
22
+ /**
23
+ * Make a GET request with retry logic
24
+ */
25
+ async get(endpoint, params) {
26
+ return this.requestWithRetry('GET', endpoint, undefined, params);
27
+ }
28
+ /**
29
+ * Make a POST request with retry logic
30
+ */
31
+ async post(endpoint, data, toolName) {
32
+ const headers = {};
33
+ if (toolName) {
34
+ headers['X-MCP-Tool'] = toolName;
35
+ }
36
+ return this.requestWithRetry('POST', endpoint, data, undefined, headers);
37
+ }
38
+ /**
39
+ * Make a PATCH request with retry logic
40
+ */
41
+ async patch(endpoint, data, toolName) {
42
+ const headers = {};
43
+ if (toolName) {
44
+ headers['X-MCP-Tool'] = toolName;
45
+ }
46
+ return this.requestWithRetry('PATCH', endpoint, data, undefined, headers);
47
+ }
48
+ /**
49
+ * Make a DELETE request with retry logic
50
+ */
51
+ async delete(endpoint, toolName) {
52
+ const headers = {};
53
+ if (toolName) {
54
+ headers['X-MCP-Tool'] = toolName;
55
+ }
56
+ return this.requestWithRetry('DELETE', endpoint, undefined, undefined, headers);
57
+ }
58
+ /**
59
+ * Request with exponential backoff retry logic
60
+ */
61
+ async requestWithRetry(method, endpoint, data, params, additionalHeaders) {
62
+ let lastError;
63
+ for (let attempt = 1; attempt <= this.retryAttempts; attempt++) {
64
+ try {
65
+ const response = await this.client.request({
66
+ method,
67
+ url: endpoint,
68
+ data,
69
+ params,
70
+ headers: additionalHeaders,
71
+ });
72
+ return response.data;
73
+ }
74
+ catch (error) {
75
+ lastError = error;
76
+ if (axios.isAxiosError(error)) {
77
+ const axiosError = error;
78
+ // Don't retry on client errors (4xx) except for 429 (rate limit)
79
+ if (axiosError.response?.status && axiosError.response.status < 500 && axiosError.response.status !== 429) {
80
+ throw this.handleError(axiosError);
81
+ }
82
+ // Log retry attempt
83
+ if (attempt < this.retryAttempts) {
84
+ const delay = this.retryDelay * Math.pow(2, attempt - 1);
85
+ logger.warn(`Request failed, retrying in ${delay}ms (attempt ${attempt}/${this.retryAttempts})`, {
86
+ endpoint,
87
+ method,
88
+ error: axiosError.message,
89
+ });
90
+ await this.sleep(delay);
91
+ }
92
+ }
93
+ else {
94
+ // Non-Axios error, don't retry
95
+ throw error;
96
+ }
97
+ }
98
+ }
99
+ // All retries exhausted
100
+ throw this.handleError(lastError);
101
+ }
102
+ /**
103
+ * Handle and format errors
104
+ */
105
+ handleError(error) {
106
+ if (axios.isAxiosError(error)) {
107
+ const status = error.response?.status;
108
+ const data = error.response?.data;
109
+ // Auth errors
110
+ if (status === 401) {
111
+ return new McpError('Authentication failed. Your MCP API key may be invalid or revoked. Please check your API key in Settings → MCP Setup.', 'AUTH_ERROR', 401);
112
+ }
113
+ if (status === 403) {
114
+ return new McpError(data?.error || 'You do not have permission to perform this action.', 'PERMISSION_DENIED', 403);
115
+ }
116
+ // Validation errors
117
+ if (status === 400) {
118
+ return new McpError(data?.error || 'Invalid request data.', 'VALIDATION_ERROR', 400, data);
119
+ }
120
+ // Not found
121
+ if (status === 404) {
122
+ return new McpError(data?.error || 'Resource not found.', 'NOT_FOUND', 404);
123
+ }
124
+ // Conflict (duplicate)
125
+ if (status === 409) {
126
+ return new McpError(data?.error || 'Resource already exists.', 'CONFLICT', 409);
127
+ }
128
+ // Server errors
129
+ if (status && status >= 500) {
130
+ return new McpError('The CRM API is experiencing issues. Please try again later.', 'SERVER_ERROR', status);
131
+ }
132
+ // Network/timeout errors
133
+ if (error.code === 'ECONNREFUSED') {
134
+ return new McpError(`Cannot connect to CRM API at ${config.apiUrl}. Make sure the Next.js dev server is running.`, 'CONNECTION_ERROR');
135
+ }
136
+ if (error.code === 'ETIMEDOUT' || error.code === 'ECONNABORTED') {
137
+ return new McpError('Request timed out. The API is taking too long to respond.', 'TIMEOUT_ERROR');
138
+ }
139
+ }
140
+ // Generic error
141
+ return new McpError(error.message || 'An unexpected error occurred.', 'UNKNOWN_ERROR');
142
+ }
143
+ sleep(ms) {
144
+ return new Promise(resolve => setTimeout(resolve, ms));
145
+ }
146
+ }
147
+ // Singleton instance
148
+ export const httpClient = new HttpClient();
149
+ //# sourceMappingURL=http-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-client.js","sourceRoot":"","sources":["../../src/client/http-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface Config {
2
+ apiUrl: string;
3
+ apiKey: string;
4
+ logLevel: 'debug' | 'info' | 'warn' | 'error';
5
+ }
6
+ export declare const config: Config;
7
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;CAC/C;AAUD,eAAO,MAAM,MAAM,EAAE,MAIpB,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,19 @@
1
+ import dotenv from 'dotenv';
2
+ dotenv.config();
3
+ function getRequiredEnv(key) {
4
+ const value = process.env[key];
5
+ if (!value) {
6
+ throw new Error(`Missing required environment variable: ${key}`);
7
+ }
8
+ return value;
9
+ }
10
+ export const config = {
11
+ apiUrl: getRequiredEnv('MCP_API_URL'),
12
+ apiKey: getRequiredEnv('MCP_API_KEY'),
13
+ logLevel: process.env.MCP_LOG_LEVEL || 'info',
14
+ };
15
+ // Log configuration on startup for debugging (must use stderr, stdout is for MCP JSON-RPC)
16
+ console.error('[MCP Server] Configuration loaded:');
17
+ console.error('[MCP Server] API URL:', config.apiUrl);
18
+ console.error('[MCP Server] Log Level:', config.logLevel);
19
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,CAAC,MAAM,EAAE,CAAC;AAQhB,SAAS,cAAc,CAAC,GAAW;IACjC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,0CAA0C,GAAG,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAW;IAC5B,MAAM,EAAE,cAAc,CAAC,aAAa,CAAC;IACrC,MAAM,EAAE,cAAc,CAAC,aAAa,CAAC;IACrC,QAAQ,EAAG,OAAO,CAAC,GAAG,CAAC,aAAoC,IAAI,MAAM;CACtE,CAAC;AAEF,2FAA2F;AAC3F,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;AACpD,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;AACtD,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
+ import { config } from './config.js';
6
+ import { logger } from './utils/logger.js';
7
+ import { formatError, isAuthError } from './utils/errors.js';
8
+ import { allTools, handleToolCall } from './tools/index.js';
9
+ import { allResources, handleResourceRead } from './resources/index.js';
10
+ // Log startup configuration
11
+ logger.info('MCP Server starting', {
12
+ apiUrl: config.apiUrl,
13
+ apiKeyPrefix: config.apiKey.substring(0, 7) + '...',
14
+ });
15
+ // Create MCP server
16
+ const server = new Server({
17
+ name: 'nexup-crm',
18
+ version: '1.0.0',
19
+ }, {
20
+ capabilities: {
21
+ tools: {},
22
+ resources: {},
23
+ },
24
+ });
25
+ // List available tools
26
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
27
+ return {
28
+ tools: allTools,
29
+ };
30
+ });
31
+ // Handle tool calls
32
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
33
+ const { name, arguments: params } = request.params;
34
+ logger.info('Tool call received', { tool: name, params });
35
+ try {
36
+ const result = await handleToolCall(name, params || {});
37
+ return result;
38
+ }
39
+ catch (error) {
40
+ logger.error('Tool call failed', {
41
+ tool: name,
42
+ error: formatError(error),
43
+ });
44
+ // Provide user-friendly error messages
45
+ if (isAuthError(error)) {
46
+ return {
47
+ content: [
48
+ {
49
+ type: 'text',
50
+ text: `❌ Authentication Error: ${formatError(error)}\n\nPlease check your MCP API key in Settings → MCP Setup.`,
51
+ },
52
+ ],
53
+ isError: true,
54
+ };
55
+ }
56
+ return {
57
+ content: [
58
+ {
59
+ type: 'text',
60
+ text: `❌ Error: ${formatError(error)}`,
61
+ },
62
+ ],
63
+ isError: true,
64
+ };
65
+ }
66
+ });
67
+ // List available resources
68
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
69
+ return {
70
+ resources: allResources,
71
+ };
72
+ });
73
+ // Handle resource reads
74
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
75
+ const { uri } = request.params;
76
+ logger.info('Resource read received', { uri });
77
+ try {
78
+ const result = await handleResourceRead(uri);
79
+ return result;
80
+ }
81
+ catch (error) {
82
+ logger.error('Resource read failed', {
83
+ uri,
84
+ error: formatError(error),
85
+ });
86
+ throw error;
87
+ }
88
+ });
89
+ // Start server
90
+ async function main() {
91
+ const transport = new StdioServerTransport();
92
+ await server.connect(transport);
93
+ logger.info('MCP Server connected via stdio', {
94
+ tools: allTools.length,
95
+ resources: allResources.length,
96
+ });
97
+ // Handle graceful shutdown
98
+ process.on('SIGINT', async () => {
99
+ logger.info('Shutting down MCP server');
100
+ await server.close();
101
+ process.exit(0);
102
+ });
103
+ }
104
+ main().catch((error) => {
105
+ logger.error('Fatal error', { error: formatError(error) });
106
+ process.exit(1);
107
+ });
108
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare const allResources: {
2
+ uri: string;
3
+ name: string;
4
+ description: string;
5
+ mimeType: string;
6
+ }[];
7
+ export declare function handleResourceRead(uri: string): Promise<any>;
8
+ //# sourceMappingURL=crm-resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crm-resources.d.ts","sourceRoot":"","sources":["../../src/resources/crm-resources.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,YAAY;;;;;GAyExB,CAAC;AAEF,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CA+DlE"}