@carbonvoice/cv-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.
- package/dist/bootstrap.js +3 -0
- package/dist/carbon-voice.js +20 -0
- package/dist/config/env.js +28 -0
- package/dist/config/index.js +17 -0
- package/dist/constants.js +9 -0
- package/dist/generated/carbon-voice-api/CarbonVoiceSimplifiedAPI.zod.js +1416 -0
- package/dist/generated/carbon-voice-api.js +377 -0
- package/dist/generated/index.js +17 -0
- package/dist/generated/models/AIPrompt.js +2 -0
- package/dist/generated/models/AIPromptControllerGetPromptsOwnerType.js +87 -0
- package/dist/generated/models/AIPromptControllerGetPromptsParams.js +2 -0
- package/dist/generated/models/AIPromptOwnerType.js +87 -0
- package/dist/generated/models/AIPromptResponseFormat.js +86 -0
- package/dist/generated/models/AIPromptWithMessagesResponse.js +2 -0
- package/dist/generated/models/AIPromptWithMessagesResult.js +2 -0
- package/dist/generated/models/AIResponse.js +2 -0
- package/dist/generated/models/AIResponseControllerGetAllResponsesDirection.js +86 -0
- package/dist/generated/models/AIResponseControllerGetAllResponsesParams.js +2 -0
- package/dist/generated/models/AIShareLinkResponse.js +2 -0
- package/dist/generated/models/AddAttachmentsResponse.js +2 -0
- package/dist/generated/models/AddLinkAttachmentPayload.js +80 -0
- package/dist/generated/models/AddMessageToFolderPayload.js +80 -0
- package/dist/generated/models/AllConversationsResponse.js +2 -0
- package/dist/generated/models/App.js +2 -0
- package/dist/generated/models/AppWebhooksAuthenticationHeader.js +80 -0
- package/dist/generated/models/AppWebhooksUrlMode.js +86 -0
- package/dist/generated/models/AsyncConversationStats.js +2 -0
- package/dist/generated/models/Attachment.js +2 -0
- package/dist/generated/models/AttachmentLocation.js +80 -0
- package/dist/generated/models/AttachmentType.js +87 -0
- package/dist/generated/models/AudioModelV2.js +80 -0
- package/dist/generated/models/Conversation.js +2 -0
- package/dist/generated/models/ConversationResponse.js +2 -0
- package/dist/generated/models/ConversationResponseType.js +88 -0
- package/dist/generated/models/ConversationType.js +88 -0
- package/dist/generated/models/ConversationVisibility.js +87 -0
- package/dist/generated/models/CreateAIPrompt.js +2 -0
- package/dist/generated/models/CreateAIPromptOwnerType.js +87 -0
- package/dist/generated/models/CreateAIPromptResponseFormat.js +86 -0
- package/dist/generated/models/CreateAIResponse.js +80 -0
- package/dist/generated/models/CreateConversationMessage.js +2 -0
- package/dist/generated/models/CreateConversationMessageFromMessageType.js +87 -0
- package/dist/generated/models/CreateFolderPayload.js +2 -0
- package/dist/generated/models/CreateFolderPayloadType.js +86 -0
- package/dist/generated/models/CreateShareLinkAIResponse.js +80 -0
- package/dist/generated/models/CreateVoicememoMessage.js +80 -0
- package/dist/generated/models/Folder.js +2 -0
- package/dist/generated/models/FolderType.js +86 -0
- package/dist/generated/models/FolderWithMessages.js +2 -0
- package/dist/generated/models/GetAllRootFoldersParams.js +2 -0
- package/dist/generated/models/GetAllRootFoldersSortBy.js +87 -0
- package/dist/generated/models/GetAllRootFoldersSortDirection.js +86 -0
- package/dist/generated/models/GetAllRootFoldersType.js +86 -0
- package/dist/generated/models/GetByIdDirection.js +85 -0
- package/dist/generated/models/GetByIdParams.js +2 -0
- package/dist/generated/models/GetCountsGroupedByWorkspaceParams.js +2 -0
- package/dist/generated/models/GetCountsGroupedByWorkspaceType.js +86 -0
- package/dist/generated/models/GetFolderByIdDirection.js +86 -0
- package/dist/generated/models/GetFolderByIdParams.js +2 -0
- package/dist/generated/models/GetMessageByIdParams.js +80 -0
- package/dist/generated/models/GetMessageResponse.js +2 -0
- package/dist/generated/models/GetTenRecentAIPromptResponse.js +2 -0
- package/dist/generated/models/GetTenRecentMessagesResponse.js +2 -0
- package/dist/generated/models/GetTenRecentMessagesResponseParams.js +80 -0
- package/dist/generated/models/Label.js +2 -0
- package/dist/generated/models/LabelBehavior.js +87 -0
- package/dist/generated/models/LabelType.js +88 -0
- package/dist/generated/models/Language.js +2 -0
- package/dist/generated/models/ListCountFoldersGroupedByWorkspace.js +2 -0
- package/dist/generated/models/ListFoldersResponse.js +2 -0
- package/dist/generated/models/ListFoldersResponseSortBy.js +87 -0
- package/dist/generated/models/ListFoldersResponseSortDirection.js +86 -0
- package/dist/generated/models/ListFoldersResponseType.js +86 -0
- package/dist/generated/models/ListMessagesFilter.js +2 -0
- package/dist/generated/models/ListMessagesFilterType.js +89 -0
- package/dist/generated/models/ListMessagesParams.js +2 -0
- package/dist/generated/models/ListMessagesResponse.js +2 -0
- package/dist/generated/models/ListMessagesResponseSortDirection.js +86 -0
- package/dist/generated/models/ListMessagesSortDirection.js +86 -0
- package/dist/generated/models/ListMessagesType.js +89 -0
- package/dist/generated/models/Message.js +2 -0
- package/dist/generated/models/MessageStatus.js +95 -0
- package/dist/generated/models/MessageType.js +89 -0
- package/dist/generated/models/MessageV2.js +2 -0
- package/dist/generated/models/MessageV2AudioDelivery.js +86 -0
- package/dist/generated/models/MessageV2Status.js +95 -0
- package/dist/generated/models/MessageV2Type.js +89 -0
- package/dist/generated/models/MessageV2UsersCaughtUp.js +87 -0
- package/dist/generated/models/MessageV2UtmData.js +2 -0
- package/dist/generated/models/MoveFolderPayload.js +80 -0
- package/dist/generated/models/PromptResponse.js +2 -0
- package/dist/generated/models/ReactionSummary.js +2 -0
- package/dist/generated/models/ReactionSummaryReactionCounts.js +80 -0
- package/dist/generated/models/ResponseByLanguage.js +2 -0
- package/dist/generated/models/ResponseByLanguageJson.js +80 -0
- package/dist/generated/models/SearchUserParams.js +80 -0
- package/dist/generated/models/SearchUsersBody.js +80 -0
- package/dist/generated/models/SendDirectMessage.js +2 -0
- package/dist/generated/models/SendDirectMessageFromMessageType.js +87 -0
- package/dist/generated/models/SimplifiedAIPrompt.js +80 -0
- package/dist/generated/models/Stats.js +80 -0
- package/dist/generated/models/SubFolder.js +2 -0
- package/dist/generated/models/SubFolderType.js +86 -0
- package/dist/generated/models/SubscribeUserPayload.js +2 -0
- package/dist/generated/models/SubscribeUserPayloadSubscriptionsItem.js +116 -0
- package/dist/generated/models/SubscribedUser.js +2 -0
- package/dist/generated/models/SubscribedUserSubscriptionsItem.js +116 -0
- package/dist/generated/models/SubscriptionAction.js +2 -0
- package/dist/generated/models/SubscriptionActionActionId.js +85 -0
- package/dist/generated/models/SubscriptionActionEntityType.js +85 -0
- package/dist/generated/models/SubscriptionFilter.js +2 -0
- package/dist/generated/models/SubscriptionFilterOperator.js +87 -0
- package/dist/generated/models/SubscriptionFilterValue.js +80 -0
- package/dist/generated/models/TextModel.js +2 -0
- package/dist/generated/models/TextModelType.js +89 -0
- package/dist/generated/models/TimedText.js +80 -0
- package/dist/generated/models/ToRecipient.js +80 -0
- package/dist/generated/models/UpdateFolderNamePayload.js +80 -0
- package/dist/generated/models/User.js +80 -0
- package/dist/generated/models/UserReaction.js +80 -0
- package/dist/generated/models/UserStats.js +80 -0
- package/dist/generated/models/UsersNotAllowedReceiveNotifications.js +80 -0
- package/dist/generated/models/UsersNotAllowedReceiveNotificationsV2.js +80 -0
- package/dist/generated/models/UtmData.js +80 -0
- package/dist/generated/models/Voice.js +2 -0
- package/dist/generated/models/VoiceGender.js +86 -0
- package/dist/generated/models/VoiceQuality.js +87 -0
- package/dist/generated/models/VoiceType.js +88 -0
- package/dist/generated/models/WorkspaceBasicInfo.js +80 -0
- package/dist/generated/models/index.js +215 -0
- package/dist/index-v1.js +80 -0
- package/dist/interfaces/folder.interface.js +2 -0
- package/dist/interfaces/get-by-id.interface.js +2 -0
- package/dist/interfaces/index.js +20 -0
- package/dist/interfaces/mcp-tool-response.interface.js +2 -0
- package/dist/interfaces/message.interface.js +2 -0
- package/dist/schemas/index.js +17 -0
- package/dist/schemas/message.js +10 -0
- package/dist/server-delete.js +624 -0
- package/dist/server-test.js +93 -0
- package/dist/server.js +365 -0
- package/dist/sse.js +134 -0
- package/dist/sse.v2.js +29 -0
- package/dist/stdio.js +39 -0
- package/dist/utils/axios-instance.js +234 -0
- package/dist/utils/errors.js +22 -0
- package/dist/utils/format-to-mcp-tool-response.js +40 -0
- package/dist/utils/index.js +19 -0
- package/dist/utils/logger.js +111 -0
- package/dist/utils/zod-schema-transformer.js +66 -0
- package/dist/utils/zod-transformer.js +24 -0
- package/package.json +66 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.customAxios = void 0;
|
|
7
|
+
exports.mutator = mutator;
|
|
8
|
+
const axios_1 = __importDefault(require("axios"));
|
|
9
|
+
const logger_1 = require("./logger");
|
|
10
|
+
const config_1 = require("../config");
|
|
11
|
+
// Create the axios instance
|
|
12
|
+
const getAxiosInstance = () => {
|
|
13
|
+
const baseUrl = config_1.env.CARBON_VOICE_BASE_URL || 'https://api.carbonvoice.app';
|
|
14
|
+
if (!config_1.env.CARBON_VOICE_API_KEY) {
|
|
15
|
+
throw {
|
|
16
|
+
statusCode: 0,
|
|
17
|
+
body: {
|
|
18
|
+
error: {
|
|
19
|
+
code: 'CONFIGURATION_ERROR',
|
|
20
|
+
message: 'CARBON_VOICE_API_KEY is not set',
|
|
21
|
+
details: { api_key: config_1.env.CARBON_VOICE_API_KEY },
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const instance = axios_1.default.create({
|
|
27
|
+
baseURL: baseUrl,
|
|
28
|
+
headers: {
|
|
29
|
+
'Content-Type': 'application/json',
|
|
30
|
+
'x-api-key': config_1.env.CARBON_VOICE_API_KEY,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
// Add request interceptor for logging
|
|
34
|
+
instance.interceptors.request.use((config) => {
|
|
35
|
+
logger_1.logger.debug('Making API request', {
|
|
36
|
+
url: config.url,
|
|
37
|
+
method: config.method,
|
|
38
|
+
params: config.params,
|
|
39
|
+
data: config.data,
|
|
40
|
+
headers: { ...config.headers, 'x-api-key': '[REDACTED]' },
|
|
41
|
+
});
|
|
42
|
+
return config;
|
|
43
|
+
}, (error) => {
|
|
44
|
+
var _a, _b;
|
|
45
|
+
logger_1.logger.error('Request setup error', {
|
|
46
|
+
url: (_a = error.config) === null || _a === void 0 ? void 0 : _a.url,
|
|
47
|
+
method: (_b = error.config) === null || _b === void 0 ? void 0 : _b.method,
|
|
48
|
+
message: error.message,
|
|
49
|
+
});
|
|
50
|
+
return Promise.reject(error);
|
|
51
|
+
});
|
|
52
|
+
// Add response interceptor for logging
|
|
53
|
+
instance.interceptors.response.use((response) => {
|
|
54
|
+
logger_1.logger.debug('API response received', {
|
|
55
|
+
url: response.config.url,
|
|
56
|
+
method: response.config.method,
|
|
57
|
+
status: response.status,
|
|
58
|
+
statusText: response.statusText,
|
|
59
|
+
});
|
|
60
|
+
return response;
|
|
61
|
+
}, (error) => {
|
|
62
|
+
var _a, _b, _c, _d, _e, _f;
|
|
63
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
64
|
+
const axiosError = handleAxiosError(error);
|
|
65
|
+
// Log the error with all relevant details
|
|
66
|
+
logger_1.logger.error('API request failed', {
|
|
67
|
+
error: axiosError,
|
|
68
|
+
url: (_a = error.config) === null || _a === void 0 ? void 0 : _a.url,
|
|
69
|
+
method: (_b = error.config) === null || _b === void 0 ? void 0 : _b.method,
|
|
70
|
+
status: (_c = error.response) === null || _c === void 0 ? void 0 : _c.status,
|
|
71
|
+
statusText: (_d = error.response) === null || _d === void 0 ? void 0 : _d.statusText,
|
|
72
|
+
requestData: (_e = error.config) === null || _e === void 0 ? void 0 : _e.data,
|
|
73
|
+
responseData: (_f = error.response) === null || _f === void 0 ? void 0 : _f.data,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
logger_1.logger.error('Unexpected error in API request', error);
|
|
78
|
+
}
|
|
79
|
+
return Promise.reject(error);
|
|
80
|
+
});
|
|
81
|
+
return instance;
|
|
82
|
+
};
|
|
83
|
+
// Error handling function
|
|
84
|
+
function handleAxiosError(error) {
|
|
85
|
+
if (error.response) {
|
|
86
|
+
const statusCode = error.response.status;
|
|
87
|
+
const errorData = error.response.data;
|
|
88
|
+
// Handle different HTTP status codes
|
|
89
|
+
switch (statusCode) {
|
|
90
|
+
case 400:
|
|
91
|
+
return {
|
|
92
|
+
statusCode,
|
|
93
|
+
body: {
|
|
94
|
+
error: {
|
|
95
|
+
code: 'BAD_REQUEST',
|
|
96
|
+
message: (errorData === null || errorData === void 0 ? void 0 : errorData.message) || 'Invalid request parameters',
|
|
97
|
+
details: (errorData === null || errorData === void 0 ? void 0 : errorData.details) || errorData,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
case 401:
|
|
102
|
+
return {
|
|
103
|
+
statusCode,
|
|
104
|
+
body: {
|
|
105
|
+
error: {
|
|
106
|
+
code: 'UNAUTHORIZED',
|
|
107
|
+
message: 'Authentication required',
|
|
108
|
+
details: { reason: 'Invalid or missing API key' },
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
case 403:
|
|
113
|
+
return {
|
|
114
|
+
statusCode,
|
|
115
|
+
body: {
|
|
116
|
+
error: {
|
|
117
|
+
code: 'FORBIDDEN',
|
|
118
|
+
message: 'Access denied',
|
|
119
|
+
details: { reason: 'Insufficient permissions' },
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
case 404:
|
|
124
|
+
return {
|
|
125
|
+
statusCode,
|
|
126
|
+
body: {
|
|
127
|
+
error: {
|
|
128
|
+
code: 'NOT_FOUND',
|
|
129
|
+
message: (errorData === null || errorData === void 0 ? void 0 : errorData.message) || 'Resource not found',
|
|
130
|
+
details: errorData === null || errorData === void 0 ? void 0 : errorData.details,
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
case 429:
|
|
135
|
+
return {
|
|
136
|
+
statusCode,
|
|
137
|
+
body: {
|
|
138
|
+
error: {
|
|
139
|
+
code: 'RATE_LIMITED',
|
|
140
|
+
message: 'Too many requests',
|
|
141
|
+
details: { retryAfter: error.response.headers['retry-after'] },
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
case 500:
|
|
146
|
+
case 502:
|
|
147
|
+
case 503:
|
|
148
|
+
case 504:
|
|
149
|
+
return {
|
|
150
|
+
statusCode,
|
|
151
|
+
body: {
|
|
152
|
+
error: {
|
|
153
|
+
code: 'SERVER_ERROR',
|
|
154
|
+
message: 'Internal server error',
|
|
155
|
+
details: { originalError: errorData },
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
default:
|
|
160
|
+
return {
|
|
161
|
+
statusCode,
|
|
162
|
+
body: {
|
|
163
|
+
error: {
|
|
164
|
+
code: 'UNKNOWN_ERROR',
|
|
165
|
+
message: (errorData === null || errorData === void 0 ? void 0 : errorData.message) || 'An unexpected error occurred',
|
|
166
|
+
details: errorData,
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else if (error.request) {
|
|
173
|
+
return {
|
|
174
|
+
statusCode: 0,
|
|
175
|
+
body: {
|
|
176
|
+
error: {
|
|
177
|
+
code: 'NETWORK_ERROR',
|
|
178
|
+
message: 'No response received from server',
|
|
179
|
+
details: {
|
|
180
|
+
request: error.request,
|
|
181
|
+
message: error.message,
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
return {
|
|
189
|
+
statusCode: 0,
|
|
190
|
+
body: {
|
|
191
|
+
error: {
|
|
192
|
+
code: 'REQUEST_ERROR',
|
|
193
|
+
message: error.message || 'Error setting up the request',
|
|
194
|
+
details: { originalError: error },
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// Create the singleton instance
|
|
201
|
+
const axiosInstance = getAxiosInstance();
|
|
202
|
+
// Define the mutator function that Orval expects
|
|
203
|
+
async function mutator({ url, method, params, data, headers, }) {
|
|
204
|
+
try {
|
|
205
|
+
const response = await axiosInstance({
|
|
206
|
+
url,
|
|
207
|
+
method,
|
|
208
|
+
params,
|
|
209
|
+
data,
|
|
210
|
+
headers,
|
|
211
|
+
});
|
|
212
|
+
return response.data;
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
216
|
+
const axiosError = handleAxiosError(error);
|
|
217
|
+
throw axiosError;
|
|
218
|
+
}
|
|
219
|
+
// Handle non-axios errors
|
|
220
|
+
const errorMessage = error instanceof Error ? error.message : 'An unexpected error occurred';
|
|
221
|
+
throw {
|
|
222
|
+
statusCode: 0,
|
|
223
|
+
body: {
|
|
224
|
+
error: {
|
|
225
|
+
code: 'UNKNOWN_ERROR',
|
|
226
|
+
message: errorMessage,
|
|
227
|
+
details: { originalError: error },
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// Export the instance for other uses
|
|
234
|
+
exports.customAxios = axiosInstance;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// import { ErrorResponse } from '../interfaces';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
// export const handleError = (error: any): ErrorResponse => {
|
|
5
|
+
// const status = error.status;
|
|
6
|
+
// // return {
|
|
7
|
+
// // isError: true,
|
|
8
|
+
// // content: [{ type: 'text', text: `Error: ${error.message}` }],
|
|
9
|
+
// // };
|
|
10
|
+
// const resource = 'user';
|
|
11
|
+
// const id = 'xxx-1234';
|
|
12
|
+
// return {
|
|
13
|
+
// statusCode: 404,
|
|
14
|
+
// body: {
|
|
15
|
+
// error: {
|
|
16
|
+
// code: 'RESOURCE_NOT_FOUND',
|
|
17
|
+
// message: `The requested ${resource} with ID ${id} was not found.`,
|
|
18
|
+
// details: { resource, id },
|
|
19
|
+
// },
|
|
20
|
+
// },
|
|
21
|
+
// } as any;
|
|
22
|
+
// };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatToMCPToolResponse = void 0;
|
|
4
|
+
const logger_1 = require("./logger");
|
|
5
|
+
const isErrorWithDetails = (error) => {
|
|
6
|
+
return typeof error === 'object' && error !== null;
|
|
7
|
+
};
|
|
8
|
+
const formatToMCPToolResponse = (data) => {
|
|
9
|
+
try {
|
|
10
|
+
return {
|
|
11
|
+
content: [{ type: 'text', text: JSON.stringify(data) }],
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
logger_1.logger.error('Error formatting response:', { data, error });
|
|
16
|
+
let code = 'UNKNOWN_ERROR';
|
|
17
|
+
let message = 'Error formatting response';
|
|
18
|
+
let details;
|
|
19
|
+
if (isErrorWithDetails(error)) {
|
|
20
|
+
code = (error === null || error === void 0 ? void 0 : error.code) || code;
|
|
21
|
+
message = (error === null || error === void 0 ? void 0 : error.message) || message;
|
|
22
|
+
details = error === null || error === void 0 ? void 0 : error.details;
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
content: [
|
|
26
|
+
{
|
|
27
|
+
type: 'text',
|
|
28
|
+
text: JSON.stringify({
|
|
29
|
+
error: {
|
|
30
|
+
code,
|
|
31
|
+
message,
|
|
32
|
+
details,
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
exports.formatToMCPToolResponse = formatToMCPToolResponse;
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
__exportStar(require("./logger"), exports);
|
|
18
|
+
__exportStar(require("./format-to-mcp-tool-response"), exports);
|
|
19
|
+
__exportStar(require("./axios-instance"), exports);
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createLogger = exports.stream = exports.logger = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const winston_1 = __importDefault(require("winston"));
|
|
10
|
+
const config_1 = require("../config");
|
|
11
|
+
// Custom log levels
|
|
12
|
+
const levels = {
|
|
13
|
+
error: 0,
|
|
14
|
+
warn: 1,
|
|
15
|
+
info: 2,
|
|
16
|
+
http: 3,
|
|
17
|
+
debug: 4,
|
|
18
|
+
};
|
|
19
|
+
// Colors for console output
|
|
20
|
+
const colors = {
|
|
21
|
+
error: 'red',
|
|
22
|
+
warn: 'yellow',
|
|
23
|
+
info: 'green',
|
|
24
|
+
http: 'magenta',
|
|
25
|
+
debug: 'white',
|
|
26
|
+
};
|
|
27
|
+
// Add colors to winston
|
|
28
|
+
winston_1.default.addColors(colors);
|
|
29
|
+
// Console format with colors
|
|
30
|
+
const consoleFormat = winston_1.default.format.combine(winston_1.default.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss:SSS' }), winston_1.default.format.colorize({ all: true }), winston_1.default.format.printf(({ timestamp, level, message, ...metadata }) => {
|
|
31
|
+
let output = `${timestamp} ${level}: ${message}`;
|
|
32
|
+
if (Object.keys(metadata).length > 0) {
|
|
33
|
+
output += '\n' + JSON.stringify(metadata, null, 2);
|
|
34
|
+
}
|
|
35
|
+
return output;
|
|
36
|
+
}));
|
|
37
|
+
// File format (JSON)
|
|
38
|
+
const fileFormat = winston_1.default.format.combine(winston_1.default.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss:SSS' }), winston_1.default.format.json());
|
|
39
|
+
const getLogLevel = () => {
|
|
40
|
+
return config_1.env.LOG_LEVEL || 'info';
|
|
41
|
+
};
|
|
42
|
+
// Create file transports
|
|
43
|
+
// const logDir = path.join(process.cwd(), 'logs');
|
|
44
|
+
// Prefer env var, fallback to project-relative folder
|
|
45
|
+
const logDir = process.env.LOG_DIR || path_1.default.join(process.cwd(), 'logs');
|
|
46
|
+
if (!fs_1.default.existsSync(logDir)) {
|
|
47
|
+
fs_1.default.mkdirSync(logDir, { recursive: true });
|
|
48
|
+
}
|
|
49
|
+
console.error('logs_dir', logDir);
|
|
50
|
+
if (!fs_1.default.existsSync(logDir)) {
|
|
51
|
+
fs_1.default.mkdirSync(logDir, { recursive: true });
|
|
52
|
+
}
|
|
53
|
+
// Create log files
|
|
54
|
+
const errorLogFile = path_1.default.join(logDir, 'error.log');
|
|
55
|
+
const combinedLogFile = path_1.default.join(logDir, 'combined.log');
|
|
56
|
+
const fileTransports = [
|
|
57
|
+
// Error log file
|
|
58
|
+
new winston_1.default.transports.File({
|
|
59
|
+
filename: errorLogFile,
|
|
60
|
+
level: 'error',
|
|
61
|
+
maxsize: 5 * 1024 * 1024, // 5MB
|
|
62
|
+
maxFiles: 5,
|
|
63
|
+
tailable: true,
|
|
64
|
+
}),
|
|
65
|
+
// Combined log file - set to same level as logger
|
|
66
|
+
new winston_1.default.transports.File({
|
|
67
|
+
filename: combinedLogFile,
|
|
68
|
+
level: getLogLevel(), // Use same level as logger
|
|
69
|
+
maxsize: 5 * 1024 * 1024, // 5MB
|
|
70
|
+
maxFiles: 5,
|
|
71
|
+
tailable: true,
|
|
72
|
+
}),
|
|
73
|
+
];
|
|
74
|
+
const consoleTransport = process.env.MCP_STDIO_MODE === 'true'
|
|
75
|
+
? [
|
|
76
|
+
new winston_1.default.transports.Console({
|
|
77
|
+
format: consoleFormat,
|
|
78
|
+
}),
|
|
79
|
+
]
|
|
80
|
+
: [];
|
|
81
|
+
// Create the logger
|
|
82
|
+
exports.logger = winston_1.default.createLogger({
|
|
83
|
+
level: getLogLevel(),
|
|
84
|
+
levels,
|
|
85
|
+
format: fileFormat,
|
|
86
|
+
transports: [...consoleTransport, ...fileTransports],
|
|
87
|
+
});
|
|
88
|
+
// Add a startup log to verify the logger is working
|
|
89
|
+
// logger.debug('Logger initialized', {
|
|
90
|
+
// currentLevel: getLogLevel(),
|
|
91
|
+
// availableLevels: levels,
|
|
92
|
+
// transports: logger.transports.map((t) => ({
|
|
93
|
+
// level: t.level,
|
|
94
|
+
// })),
|
|
95
|
+
// logDir,
|
|
96
|
+
// logFiles: {
|
|
97
|
+
// error: errorLogFile,
|
|
98
|
+
// combined: combinedLogFile,
|
|
99
|
+
// },
|
|
100
|
+
// });
|
|
101
|
+
// Export a stream object for Morgan
|
|
102
|
+
exports.stream = {
|
|
103
|
+
write: (message) => {
|
|
104
|
+
exports.logger.http(message.trim());
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
// Helper to create child loggers with context
|
|
108
|
+
const createLogger = (context) => {
|
|
109
|
+
return exports.logger.child({ context });
|
|
110
|
+
};
|
|
111
|
+
exports.createLogger = createLogger;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// import { OpenAPIV3 } from 'openapi-types';
|
|
3
|
+
// import { z } from 'zod';
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
// function generateZodSchema(schema: OpenAPIV3.SchemaObject): z.ZodType<any> {
|
|
6
|
+
// if (!schema) {
|
|
7
|
+
// return z.any();
|
|
8
|
+
// }
|
|
9
|
+
// switch (schema.type) {
|
|
10
|
+
// case 'string':
|
|
11
|
+
// return schema.enum
|
|
12
|
+
// ? z.enum(schema.enum as [string, ...string[]])
|
|
13
|
+
// : z.string();
|
|
14
|
+
// case 'number':
|
|
15
|
+
// case 'integer':
|
|
16
|
+
// return z.number();
|
|
17
|
+
// case 'boolean':
|
|
18
|
+
// return z.boolean();
|
|
19
|
+
// case 'array':
|
|
20
|
+
// return z.array(generateZodSchema(schema.items as OpenAPIV3.SchemaObject));
|
|
21
|
+
// case 'object':
|
|
22
|
+
// if (schema.properties) {
|
|
23
|
+
// const shape: { [key: string]: z.ZodType<any> } = {};
|
|
24
|
+
// for (const [key, prop] of Object.entries(schema.properties)) {
|
|
25
|
+
// const isRequired = schema.required?.includes(key);
|
|
26
|
+
// shape[key] = isRequired
|
|
27
|
+
// ? generateZodSchema(prop as OpenAPIV3.SchemaObject)
|
|
28
|
+
// : generateZodSchema(prop as OpenAPIV3.SchemaObject).optional();
|
|
29
|
+
// }
|
|
30
|
+
// return z.object(shape);
|
|
31
|
+
// }
|
|
32
|
+
// return z.record(z.any());
|
|
33
|
+
// default:
|
|
34
|
+
// return z.any();
|
|
35
|
+
// }
|
|
36
|
+
// }
|
|
37
|
+
// export const transformer = async (args: any) => {
|
|
38
|
+
// if (!args || !args.schema) {
|
|
39
|
+
// throw new Error(
|
|
40
|
+
// 'Transformer received undefined or missing schema! Args: ' +
|
|
41
|
+
// JSON.stringify(args),
|
|
42
|
+
// );
|
|
43
|
+
// }
|
|
44
|
+
// const schemas: { [key: string]: z.ZodType<any> } = {};
|
|
45
|
+
// // Process all schemas in the OpenAPI document
|
|
46
|
+
// if (args.schema.components?.schemas) {
|
|
47
|
+
// for (const [name, schema] of Object.entries(
|
|
48
|
+
// args.schema.components.schemas,
|
|
49
|
+
// )) {
|
|
50
|
+
// schemas[name] = generateZodSchema(schema as OpenAPIV3.SchemaObject);
|
|
51
|
+
// }
|
|
52
|
+
// }
|
|
53
|
+
// // Generate the output file content
|
|
54
|
+
// const output = `import { z } from 'zod';
|
|
55
|
+
// // Generated Zod schemas
|
|
56
|
+
// ${Object.entries(schemas)
|
|
57
|
+
// .map(([name, schema]) => `export const ${name}Schema = ${schema.toString()};`)
|
|
58
|
+
// .join('\n')}
|
|
59
|
+
// // Type exports
|
|
60
|
+
// ${Object.entries(schemas)
|
|
61
|
+
// .map(([name]) => `export type ${name} = z.infer<typeof ${name}Schema>;`)
|
|
62
|
+
// .join('\n')}
|
|
63
|
+
// `;
|
|
64
|
+
// return output;
|
|
65
|
+
// };
|
|
66
|
+
// export default transformer;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// import { generateZodClientFromOpenAPI } from 'openapi-zod-client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
// const transformer = async (args: any) => {
|
|
5
|
+
// if (!args || !args.schema) {
|
|
6
|
+
// throw new Error(
|
|
7
|
+
// 'Transformer received undefined or missing schema! Args: ' +
|
|
8
|
+
// JSON.stringify(args),
|
|
9
|
+
// );
|
|
10
|
+
// }
|
|
11
|
+
// if (!args.path) {
|
|
12
|
+
// throw new Error(
|
|
13
|
+
// 'Transformer received undefined or missing path! Args: ' +
|
|
14
|
+
// JSON.stringify(args),
|
|
15
|
+
// );
|
|
16
|
+
// }
|
|
17
|
+
// return generateZodClientFromOpenAPI({
|
|
18
|
+
// openApiDoc: args.schema,
|
|
19
|
+
// distPath: args.path,
|
|
20
|
+
// });
|
|
21
|
+
// };
|
|
22
|
+
// // Use both CommonJS and ESM exports for compatibility
|
|
23
|
+
// module.exports = transformer;
|
|
24
|
+
// export default transformer;
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@carbonvoice/cv-mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for using the Carbon Voice Simplified API",
|
|
5
|
+
"author": "Carbon Voice",
|
|
6
|
+
"license": "ISC",
|
|
7
|
+
"private": false,
|
|
8
|
+
"homepage": "https://getcarbon.app",
|
|
9
|
+
"bugs": "https://github.com/PhononX/cv-mcp-server/issues",
|
|
10
|
+
"main": "dist/stdio.js",
|
|
11
|
+
"bin": {
|
|
12
|
+
"mcp-server-carbonvoice": "./dist/stdio.js"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "rm -rf dist && tsc && chmod 755 dist/stdio.js",
|
|
16
|
+
"start": "node dist/index.js",
|
|
17
|
+
"pre": "npm run build",
|
|
18
|
+
"mcp:inspector": "npx --env-file=.env @modelcontextprotocol/inspector node dist/stdio.js",
|
|
19
|
+
"dev": "dotenv -e .env -- node dist/index.js",
|
|
20
|
+
"debug": "dotenv -e .env -- nodemon --watch src --ext ts --exec \"node --loader ts-node/esm\" src/server.ts",
|
|
21
|
+
"debug:stdio": "dotenv -e .env -- nodemon --watch src --ext ts --exec \"node --loader ts-node/esm\" src/stdio.ts",
|
|
22
|
+
"auto:build": "nodemon --watch src --ext ts --exec npm run build",
|
|
23
|
+
"pregenerate:api": "tsc src/utils/zod-transformer.ts --outDir dist/utils && mv dist/utils/zod-transformer.js dist/utils/zod-transformer.cjs",
|
|
24
|
+
"generate:api": "npm run pregenerate:api && orval --config orval.config.ts",
|
|
25
|
+
"lint:fix": "eslint src --fix"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"keywords": [
|
|
31
|
+
"mcp",
|
|
32
|
+
"mcp-server",
|
|
33
|
+
"mcp-server-carbonvoice",
|
|
34
|
+
"carbonvoice",
|
|
35
|
+
"carbonvoice-mcp-server"
|
|
36
|
+
],
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
39
|
+
"axios": "^1.9.0",
|
|
40
|
+
"dotenv": "^16.5.0",
|
|
41
|
+
"openapi-zod-client": "^1.18.3",
|
|
42
|
+
"winston": "^3.17.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@eslint/js": "^9.29.0",
|
|
46
|
+
"@orval/zod": "^7.9.0",
|
|
47
|
+
"@types/handlebars": "^4.0.40",
|
|
48
|
+
"@types/node": "^22.15.29",
|
|
49
|
+
"@typescript-eslint/eslint-plugin": "^8.33.1",
|
|
50
|
+
"@typescript-eslint/parser": "^8.33.1",
|
|
51
|
+
"eslint": "^9.29.0",
|
|
52
|
+
"eslint-config-prettier": "^10.1.5",
|
|
53
|
+
"eslint-plugin-prettier": "^5.4.1",
|
|
54
|
+
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
55
|
+
"eslint-plugin-unused-imports": "^4.1.4",
|
|
56
|
+
"globals": "^16.2.0",
|
|
57
|
+
"nodemon": "^3.1.10",
|
|
58
|
+
"orval": "^7.9.0",
|
|
59
|
+
"prettier": "^3.5.3",
|
|
60
|
+
"ts-node": "^10.9.2",
|
|
61
|
+
"ts-node-dev": "^2.0.0",
|
|
62
|
+
"typescript": "^5.8.3",
|
|
63
|
+
"typescript-eslint": "^8.34.1",
|
|
64
|
+
"zod": "^3.25.58"
|
|
65
|
+
}
|
|
66
|
+
}
|