@danainnovations/cortex-mcp 1.0.29 → 1.0.31

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/cli.js CHANGED
@@ -41,7 +41,7 @@ var AVAILABLE_MCPS = [
41
41
  {
42
42
  name: "m365",
43
43
  displayName: "Microsoft 365",
44
- description: "Email, calendar, OneDrive, Teams, meetings (11 tools)",
44
+ description: "Email, calendar, OneDrive, Teams, meetings, contacts, tasks, notes (32 tools)",
45
45
  serverName: "cortex-m365",
46
46
  authMode: "personal"
47
47
  },
@@ -58,6 +58,20 @@ var AVAILABLE_MCPS = [
58
58
  description: "Boards, items, groups, updates, workspaces (18 tools)",
59
59
  serverName: "cortex-monday",
60
60
  authMode: "personal"
61
+ },
62
+ {
63
+ name: "slack",
64
+ displayName: "Slack",
65
+ description: "Messaging, channels, search, reactions, bookmarks (22 tools)",
66
+ serverName: "cortex-slack",
67
+ authMode: "personal"
68
+ },
69
+ {
70
+ name: "bestbuy",
71
+ displayName: "Best Buy",
72
+ description: "Product search, pricing, reviews, store locations (7 tools)",
73
+ serverName: "cortex-bestbuy",
74
+ authMode: "company"
61
75
  }
62
76
  ];
63
77
  var MCP_NAMES = AVAILABLE_MCPS.map((m) => m.name);
@@ -964,6 +978,7 @@ async function runConfigure(options) {
964
978
  }
965
979
 
966
980
  // src/proxy/stdio-server.ts
981
+ import { readFileSync as readFileSync4, statSync } from "fs";
967
982
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
968
983
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
969
984
  import {
@@ -1074,6 +1089,179 @@ var CortexHttpClient = class {
1074
1089
  };
1075
1090
 
1076
1091
  // src/proxy/stdio-server.ts
1092
+ var UPLOAD_TOOLS = /* @__PURE__ */ new Set(["upload_file", "upload_file_to_sharepoint"]);
1093
+ var INLINE_UPLOAD_MAX = 3.5 * 1024 * 1024;
1094
+ function overrideUploadToolSchema(tool) {
1095
+ const name = tool.name;
1096
+ const baseName = name.includes("__") ? name.split("__").pop() : name;
1097
+ if (baseName === "upload_file") {
1098
+ return {
1099
+ ...tool,
1100
+ description: "Upload a local file to the user's OneDrive. Provide the absolute local file path \u2014 the file is read and uploaded automatically. Works with any file size.",
1101
+ inputSchema: {
1102
+ type: "object",
1103
+ required: ["file_path", "path"],
1104
+ properties: {
1105
+ file_path: {
1106
+ type: "string",
1107
+ description: "Absolute path to the local file to upload (e.g. '/Users/name/Documents/report.xlsx')"
1108
+ },
1109
+ path: {
1110
+ type: "string",
1111
+ description: "Destination path in OneDrive (e.g. 'Documents/report.xlsx')"
1112
+ },
1113
+ content_type: {
1114
+ type: "string",
1115
+ description: "MIME type. Defaults to 'application/octet-stream'"
1116
+ }
1117
+ }
1118
+ }
1119
+ };
1120
+ }
1121
+ if (baseName === "upload_file_to_sharepoint") {
1122
+ return {
1123
+ ...tool,
1124
+ description: "Upload a local file to a SharePoint document library. Provide the absolute local file path \u2014 the file is read and uploaded automatically.",
1125
+ inputSchema: {
1126
+ type: "object",
1127
+ required: ["file_path", "site_id", "path"],
1128
+ properties: {
1129
+ file_path: {
1130
+ type: "string",
1131
+ description: "Absolute path to the local file to upload"
1132
+ },
1133
+ site_id: {
1134
+ type: "string",
1135
+ description: "SharePoint site ID"
1136
+ },
1137
+ path: {
1138
+ type: "string",
1139
+ description: "Destination path in the site drive (e.g. 'Shared Documents/report.pdf')"
1140
+ },
1141
+ content_type: {
1142
+ type: "string",
1143
+ description: "MIME type. Defaults to 'application/octet-stream'"
1144
+ }
1145
+ }
1146
+ }
1147
+ };
1148
+ }
1149
+ return tool;
1150
+ }
1151
+ async function handleLocalFileUpload(cortex, toolName, args) {
1152
+ const filePath = args.file_path;
1153
+ let fileSize;
1154
+ try {
1155
+ fileSize = statSync(filePath).size;
1156
+ } catch {
1157
+ return {
1158
+ content: [{ type: "text", text: JSON.stringify({
1159
+ success: false,
1160
+ error: `File not found: ${filePath}`
1161
+ }) }],
1162
+ isError: true
1163
+ };
1164
+ }
1165
+ if (fileSize <= INLINE_UPLOAD_MAX) {
1166
+ const fileBuffer2 = readFileSync4(filePath);
1167
+ const base64Content = fileBuffer2.toString("base64");
1168
+ const forwardArgs = { ...args, content: base64Content };
1169
+ delete forwardArgs.file_path;
1170
+ console.error(
1171
+ `[cortex-mcp] ${toolName}: reading local file (${(fileSize / 1024).toFixed(1)}KB), forwarding as base64`
1172
+ );
1173
+ const response = await cortex.callTool(toolName, forwardArgs);
1174
+ if (response.error) {
1175
+ return {
1176
+ content: [{ type: "text", text: response.error.message }],
1177
+ isError: true
1178
+ };
1179
+ }
1180
+ return response.result;
1181
+ }
1182
+ console.error(
1183
+ `[cortex-mcp] ${toolName}: large file (${(fileSize / 1024 / 1024).toFixed(1)}MB), using upload session`
1184
+ );
1185
+ const prefix = toolName.includes("__") ? toolName.split("__")[0] + "__" : "";
1186
+ const sessionResponse = await cortex.callTool(`${prefix}create_upload_session`, {
1187
+ path: args.path
1188
+ });
1189
+ if (sessionResponse.error) {
1190
+ return {
1191
+ content: [{ type: "text", text: sessionResponse.error.message }],
1192
+ isError: true
1193
+ };
1194
+ }
1195
+ const sessionResult = sessionResponse.result;
1196
+ let sessionData;
1197
+ try {
1198
+ sessionData = JSON.parse(sessionResult.content[0].text);
1199
+ } catch {
1200
+ return {
1201
+ content: [{ type: "text", text: JSON.stringify({
1202
+ success: false,
1203
+ error: "Failed to parse upload session response from backend"
1204
+ }) }],
1205
+ isError: true
1206
+ };
1207
+ }
1208
+ const uploadUrl = sessionData.uploadUrl;
1209
+ if (!uploadUrl) {
1210
+ return {
1211
+ content: [{ type: "text", text: JSON.stringify({
1212
+ success: false,
1213
+ error: "Backend did not return an uploadUrl"
1214
+ }) }],
1215
+ isError: true
1216
+ };
1217
+ }
1218
+ const fileBuffer = readFileSync4(filePath);
1219
+ const chunkSize = 10 * 1024 * 1024;
1220
+ const total = fileBuffer.length;
1221
+ let lastResponse = null;
1222
+ for (let start = 0; start < total; start += chunkSize) {
1223
+ const end = Math.min(start + chunkSize, total);
1224
+ const chunk = fileBuffer.subarray(start, end);
1225
+ console.error(
1226
+ `[cortex-mcp] Uploading chunk ${start}-${end - 1}/${total}`
1227
+ );
1228
+ lastResponse = await fetch(uploadUrl, {
1229
+ method: "PUT",
1230
+ headers: {
1231
+ "Content-Length": String(chunk.length),
1232
+ "Content-Range": `bytes ${start}-${end - 1}/${total}`
1233
+ },
1234
+ body: chunk,
1235
+ signal: AbortSignal.timeout(12e4)
1236
+ // 2 min per chunk
1237
+ });
1238
+ if (!lastResponse.ok && lastResponse.status !== 202) {
1239
+ const errText = await lastResponse.text();
1240
+ return {
1241
+ content: [{ type: "text", text: JSON.stringify({
1242
+ success: false,
1243
+ error: `Upload chunk failed (${lastResponse.status}): ${errText.slice(0, 200)}`
1244
+ }) }],
1245
+ isError: true
1246
+ };
1247
+ }
1248
+ }
1249
+ let driveItem = {};
1250
+ if (lastResponse) {
1251
+ try {
1252
+ driveItem = await lastResponse.json();
1253
+ } catch {
1254
+ }
1255
+ }
1256
+ return {
1257
+ content: [{ type: "text", text: JSON.stringify({
1258
+ success: true,
1259
+ file: driveItem,
1260
+ message: `Uploaded '${args.path}' (${(fileSize / 1024).toFixed(1)}KB) via upload session`
1261
+ }) }],
1262
+ isError: false
1263
+ };
1264
+ }
1077
1265
  async function startStdioServer(options) {
1078
1266
  const { serverUrl, apiKey, endpoint = "cortex" } = options;
1079
1267
  const cortex = new CortexHttpClient(serverUrl, apiKey, endpoint);
@@ -1101,12 +1289,18 @@ async function startStdioServer(options) {
1101
1289
  throw new Error(response.error.message);
1102
1290
  }
1103
1291
  const result = response.result;
1104
- return { tools: result.tools || [] };
1292
+ const tools = (result.tools || []).map(overrideUploadToolSchema);
1293
+ return { tools };
1105
1294
  });
1106
1295
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
1107
1296
  await ensureInitialized();
1108
1297
  const { name, arguments: args } = request.params;
1109
- const response = await cortex.callTool(name, args ?? {});
1298
+ const typedArgs = args ?? {};
1299
+ const baseName = name.includes("__") ? name.split("__").pop() : name;
1300
+ if (UPLOAD_TOOLS.has(baseName) && typedArgs.file_path) {
1301
+ return handleLocalFileUpload(cortex, name, typedArgs);
1302
+ }
1303
+ const response = await cortex.callTool(name, typedArgs);
1110
1304
  if (response.error) {
1111
1305
  return {
1112
1306
  content: [{ type: "text", text: response.error.message }],