@danainnovations/cortex-mcp 1.0.72 → 1.0.73
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/{chunk-KO4SHBAF.js → chunk-D4PD3E6J.js} +8 -1
- package/dist/{chunk-KO4SHBAF.js.map → chunk-D4PD3E6J.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{constants-COUEGU7A.js → constants-QSLA3TAZ.js} +2 -2
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- /package/dist/{constants-COUEGU7A.js.map → constants-QSLA3TAZ.js.map} +0 -0
|
@@ -88,6 +88,13 @@ var AVAILABLE_MCPS = [
|
|
|
88
88
|
description: "Unity Catalog discovery, SQL queries, data dictionary, jobs (18 tools)",
|
|
89
89
|
serverName: "cortex-databricks",
|
|
90
90
|
authMode: "company"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "concur",
|
|
94
|
+
displayName: "SAP Concur",
|
|
95
|
+
description: "Expense reports, entries, receipts, approvals (16 tools)",
|
|
96
|
+
serverName: "cortex-concur",
|
|
97
|
+
authMode: "personal"
|
|
91
98
|
}
|
|
92
99
|
];
|
|
93
100
|
var MCP_NAMES = AVAILABLE_MCPS.map((m) => m.name);
|
|
@@ -108,4 +115,4 @@ export {
|
|
|
108
115
|
CONFIG_FILE_NAME,
|
|
109
116
|
CREDENTIALS_FILE_NAME
|
|
110
117
|
};
|
|
111
|
-
//# sourceMappingURL=chunk-
|
|
118
|
+
//# sourceMappingURL=chunk-D4PD3E6J.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts"],"sourcesContent":["/** Default Cortex server URL */\nexport const DEFAULT_SERVER_URL = \"https://cortex-bice.vercel.app\";\n\n/** MCP protocol version supported by Cortex (Streamable HTTP) */\nexport const PROTOCOL_VERSION = \"2025-03-26\";\n\n/** Available MCPs with their metadata */\nexport const AVAILABLE_MCPS = [\n {\n name: \"m365\",\n displayName: \"Microsoft 365\",\n description: \"Email, calendar, OneDrive, Teams, meetings, contacts, tasks, notes (33 tools)\",\n serverName: \"cortex-m365\",\n authMode: \"personal\" as const,\n },\n {\n name: \"asana\",\n displayName: \"Asana\",\n description: \"Projects, tasks, teams, workspaces (17 tools)\",\n serverName: \"cortex-asana\",\n authMode: \"personal\" as const,\n },\n {\n name: \"github\",\n displayName: \"GitHub\",\n description: \"Repos, PRs, issues, branches, code review (30 tools)\",\n serverName: \"cortex-github\",\n authMode: \"company\" as const,\n },\n {\n name: \"vercel\",\n displayName: \"Vercel\",\n description: \"Deployments, projects, env vars (15 tools)\",\n serverName: \"cortex-vercel\",\n authMode: \"company\" as const,\n },\n {\n name: \"supabase\",\n displayName: \"Supabase\",\n description: \"Database, migrations, edge functions (20+ tools)\",\n serverName: \"cortex-supabase\",\n authMode: \"company\" as const,\n },\n {\n name: \"bestbuy\",\n displayName: \"Best Buy\",\n description: \"Product search, pricing, reviews, store locations (7 tools)\",\n serverName: \"cortex-bestbuy\",\n authMode: \"company\" as const,\n },\n {\n name: \"mailchimp\",\n displayName: \"Mailchimp\",\n description: \"Audiences, contacts, campaigns, templates, analytics (28 tools)\",\n serverName: \"cortex-mailchimp\",\n authMode: \"personal\" as const,\n },\n {\n name: \"salesforce\",\n displayName: \"Salesforce\",\n description: \"CRM queries, records, reports, and org data (14 tools)\",\n serverName: \"cortex-salesforce\",\n authMode: \"personal\" as const,\n },\n {\n name: \"monday\",\n displayName: \"Monday.com\",\n description: \"Boards, items, groups, updates, workspaces (18 tools)\",\n serverName: \"cortex-monday\",\n authMode: \"personal\" as const,\n installUrl: \"https://auth.monday.com/oauth2/authorize?client_id=c8d2c70bd792a4c36c6f023c0b707517&response_type=install\",\n },\n {\n name: \"slack\",\n displayName: \"Slack\",\n description: \"Messaging, channels, search, reactions, bookmarks (22 tools)\",\n serverName: \"cortex-slack\",\n authMode: \"personal\" as const,\n },\n {\n name: \"powerbi\",\n displayName: \"Power BI\",\n description: \"Workspaces, datasets, push data, DAX queries, reports, dashboards (14 tools)\",\n serverName: \"cortex-powerbi\",\n authMode: \"personal\" as const,\n },\n {\n name: \"databricks\",\n displayName: \"Databricks\",\n description: \"Unity Catalog discovery, SQL queries, data dictionary, jobs (18 tools)\",\n serverName: \"cortex-databricks\",\n authMode: \"company\" as const,\n },\n] as const;\n\n/** All available MCP names */\nexport const MCP_NAMES: string[] = AVAILABLE_MCPS.map((m) => m.name);\n\n/** Default MCPs enabled on fresh setup */\nexport const DEFAULT_MCPS: string[] = [...MCP_NAMES];\n\n/** Shared API key embedded in the package (no user prompt needed) */\nexport const DEFAULT_API_KEY =\n \"ctx_07d37a81_9f7be06af38d04753090a4034f907a65ec06cd675ed26f65653898388e2d1709\";\n\n/** Config directory name */\nexport const CONFIG_DIR_NAME = \".cortex-mcp\";\n\n/** Config file name */\nexport const CONFIG_FILE_NAME = \"config.json\";\n\n/** Credentials file name (stores personal API key from login) */\nexport const CREDENTIALS_FILE_NAME = \"credentials.json\";\n"],"mappings":";;;AACO,IAAM,qBAAqB;AAG3B,IAAM,mBAAmB;AAGzB,IAAM,iBAAiB;AAAA,EAC5B;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AACF;AAGO,IAAM,YAAsB,eAAe,IAAI,CAAC,MAAM,EAAE,IAAI;AAG5D,IAAM,eAAyB,CAAC,GAAG,SAAS;AAG5C,IAAM,kBACX;AAGK,IAAM,kBAAkB;AAGxB,IAAM,mBAAmB;AAGzB,IAAM,wBAAwB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts"],"sourcesContent":["/** Default Cortex server URL */\nexport const DEFAULT_SERVER_URL = \"https://cortex-bice.vercel.app\";\n\n/** MCP protocol version supported by Cortex (Streamable HTTP) */\nexport const PROTOCOL_VERSION = \"2025-03-26\";\n\n/** Available MCPs with their metadata */\nexport const AVAILABLE_MCPS = [\n {\n name: \"m365\",\n displayName: \"Microsoft 365\",\n description: \"Email, calendar, OneDrive, Teams, meetings, contacts, tasks, notes (33 tools)\",\n serverName: \"cortex-m365\",\n authMode: \"personal\" as const,\n },\n {\n name: \"asana\",\n displayName: \"Asana\",\n description: \"Projects, tasks, teams, workspaces (17 tools)\",\n serverName: \"cortex-asana\",\n authMode: \"personal\" as const,\n },\n {\n name: \"github\",\n displayName: \"GitHub\",\n description: \"Repos, PRs, issues, branches, code review (30 tools)\",\n serverName: \"cortex-github\",\n authMode: \"company\" as const,\n },\n {\n name: \"vercel\",\n displayName: \"Vercel\",\n description: \"Deployments, projects, env vars (15 tools)\",\n serverName: \"cortex-vercel\",\n authMode: \"company\" as const,\n },\n {\n name: \"supabase\",\n displayName: \"Supabase\",\n description: \"Database, migrations, edge functions (20+ tools)\",\n serverName: \"cortex-supabase\",\n authMode: \"company\" as const,\n },\n {\n name: \"bestbuy\",\n displayName: \"Best Buy\",\n description: \"Product search, pricing, reviews, store locations (7 tools)\",\n serverName: \"cortex-bestbuy\",\n authMode: \"company\" as const,\n },\n {\n name: \"mailchimp\",\n displayName: \"Mailchimp\",\n description: \"Audiences, contacts, campaigns, templates, analytics (28 tools)\",\n serverName: \"cortex-mailchimp\",\n authMode: \"personal\" as const,\n },\n {\n name: \"salesforce\",\n displayName: \"Salesforce\",\n description: \"CRM queries, records, reports, and org data (14 tools)\",\n serverName: \"cortex-salesforce\",\n authMode: \"personal\" as const,\n },\n {\n name: \"monday\",\n displayName: \"Monday.com\",\n description: \"Boards, items, groups, updates, workspaces (18 tools)\",\n serverName: \"cortex-monday\",\n authMode: \"personal\" as const,\n installUrl: \"https://auth.monday.com/oauth2/authorize?client_id=c8d2c70bd792a4c36c6f023c0b707517&response_type=install\",\n },\n {\n name: \"slack\",\n displayName: \"Slack\",\n description: \"Messaging, channels, search, reactions, bookmarks (22 tools)\",\n serverName: \"cortex-slack\",\n authMode: \"personal\" as const,\n },\n {\n name: \"powerbi\",\n displayName: \"Power BI\",\n description: \"Workspaces, datasets, push data, DAX queries, reports, dashboards (14 tools)\",\n serverName: \"cortex-powerbi\",\n authMode: \"personal\" as const,\n },\n {\n name: \"databricks\",\n displayName: \"Databricks\",\n description: \"Unity Catalog discovery, SQL queries, data dictionary, jobs (18 tools)\",\n serverName: \"cortex-databricks\",\n authMode: \"company\" as const,\n },\n {\n name: \"concur\",\n displayName: \"SAP Concur\",\n description: \"Expense reports, entries, receipts, approvals (16 tools)\",\n serverName: \"cortex-concur\",\n authMode: \"personal\" as const,\n },\n] as const;\n\n/** All available MCP names */\nexport const MCP_NAMES: string[] = AVAILABLE_MCPS.map((m) => m.name);\n\n/** Default MCPs enabled on fresh setup */\nexport const DEFAULT_MCPS: string[] = [...MCP_NAMES];\n\n/** Shared API key embedded in the package (no user prompt needed) */\nexport const DEFAULT_API_KEY =\n \"ctx_07d37a81_9f7be06af38d04753090a4034f907a65ec06cd675ed26f65653898388e2d1709\";\n\n/** Config directory name */\nexport const CONFIG_DIR_NAME = \".cortex-mcp\";\n\n/** Config file name */\nexport const CONFIG_FILE_NAME = \"config.json\";\n\n/** Credentials file name (stores personal API key from login) */\nexport const CREDENTIALS_FILE_NAME = \"credentials.json\";\n"],"mappings":";;;AACO,IAAM,qBAAqB;AAG3B,IAAM,mBAAmB;AAGzB,IAAM,iBAAiB;AAAA,EAC5B;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AACF;AAGO,IAAM,YAAsB,eAAe,IAAI,CAAC,MAAM,EAAE,IAAI;AAG5D,IAAM,eAAyB,CAAC,GAAG,SAAS;AAG5C,IAAM,kBACX;AAGK,IAAM,kBAAkB;AAGxB,IAAM,mBAAmB;AAGzB,IAAM,wBAAwB;","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
DEFAULT_SERVER_URL,
|
|
10
10
|
MCP_NAMES,
|
|
11
11
|
PROTOCOL_VERSION
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-D4PD3E6J.js";
|
|
13
13
|
import {
|
|
14
14
|
getAntigravityConfigPath,
|
|
15
15
|
getClaudeDesktopConfigPath,
|
|
@@ -3944,7 +3944,7 @@ program.command("disconnect <provider>").description("Remove your personal OAuth
|
|
|
3944
3944
|
}
|
|
3945
3945
|
});
|
|
3946
3946
|
program.command("connect-mobile").description("Connect Cortex to Claude on mobile \u2014 opens setup page in browser").action(async () => {
|
|
3947
|
-
const { DEFAULT_SERVER_URL: DEFAULT_SERVER_URL3 } = await import("./constants-
|
|
3947
|
+
const { DEFAULT_SERVER_URL: DEFAULT_SERVER_URL3 } = await import("./constants-QSLA3TAZ.js");
|
|
3948
3948
|
const { openBrowser: openBrowser2 } = await import("./browser-WFTDXNKP.js");
|
|
3949
3949
|
const url = `${DEFAULT_SERVER_URL3}/connect`;
|
|
3950
3950
|
console.log("\nOpening Cortex connect page...");
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
DEFAULT_SERVER_URL,
|
|
10
10
|
MCP_NAMES,
|
|
11
11
|
PROTOCOL_VERSION
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-D4PD3E6J.js";
|
|
13
13
|
export {
|
|
14
14
|
AVAILABLE_MCPS,
|
|
15
15
|
CONFIG_DIR_NAME,
|
|
@@ -21,4 +21,4 @@ export {
|
|
|
21
21
|
MCP_NAMES,
|
|
22
22
|
PROTOCOL_VERSION
|
|
23
23
|
};
|
|
24
|
-
//# sourceMappingURL=constants-
|
|
24
|
+
//# sourceMappingURL=constants-QSLA3TAZ.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -187,6 +187,12 @@ declare const AVAILABLE_MCPS: readonly [{
|
|
|
187
187
|
readonly description: "Unity Catalog discovery, SQL queries, data dictionary, jobs (18 tools)";
|
|
188
188
|
readonly serverName: "cortex-databricks";
|
|
189
189
|
readonly authMode: "company";
|
|
190
|
+
}, {
|
|
191
|
+
readonly name: "concur";
|
|
192
|
+
readonly displayName: "SAP Concur";
|
|
193
|
+
readonly description: "Expense reports, entries, receipts, approvals (16 tools)";
|
|
194
|
+
readonly serverName: "cortex-concur";
|
|
195
|
+
readonly authMode: "personal";
|
|
190
196
|
}];
|
|
191
197
|
/** All available MCP names */
|
|
192
198
|
declare const MCP_NAMES: string[];
|
package/dist/index.js
CHANGED
|
@@ -86,6 +86,13 @@ var AVAILABLE_MCPS = [
|
|
|
86
86
|
description: "Unity Catalog discovery, SQL queries, data dictionary, jobs (18 tools)",
|
|
87
87
|
serverName: "cortex-databricks",
|
|
88
88
|
authMode: "company"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "concur",
|
|
92
|
+
displayName: "SAP Concur",
|
|
93
|
+
description: "Expense reports, entries, receipts, approvals (16 tools)",
|
|
94
|
+
serverName: "cortex-concur",
|
|
95
|
+
authMode: "personal"
|
|
89
96
|
}
|
|
90
97
|
];
|
|
91
98
|
var MCP_NAMES = AVAILABLE_MCPS.map((m) => m.name);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts","../src/proxy/http-client.ts","../src/proxy/stdio-server.ts","../src/proxy/local-filesystem.ts","../src/config/storage.ts","../src/utils/platform.ts","../src/config/clients.ts","../src/utils/validation.ts","../src/auth/credentials.ts","../src/client/mcp-namespace.ts","../src/client/cortex-client.ts"],"sourcesContent":["/** Default Cortex server URL */\nexport const DEFAULT_SERVER_URL = \"https://cortex-bice.vercel.app\";\n\n/** MCP protocol version supported by Cortex (Streamable HTTP) */\nexport const PROTOCOL_VERSION = \"2025-03-26\";\n\n/** Available MCPs with their metadata */\nexport const AVAILABLE_MCPS = [\n {\n name: \"m365\",\n displayName: \"Microsoft 365\",\n description: \"Email, calendar, OneDrive, Teams, meetings, contacts, tasks, notes (33 tools)\",\n serverName: \"cortex-m365\",\n authMode: \"personal\" as const,\n },\n {\n name: \"asana\",\n displayName: \"Asana\",\n description: \"Projects, tasks, teams, workspaces (17 tools)\",\n serverName: \"cortex-asana\",\n authMode: \"personal\" as const,\n },\n {\n name: \"github\",\n displayName: \"GitHub\",\n description: \"Repos, PRs, issues, branches, code review (30 tools)\",\n serverName: \"cortex-github\",\n authMode: \"company\" as const,\n },\n {\n name: \"vercel\",\n displayName: \"Vercel\",\n description: \"Deployments, projects, env vars (15 tools)\",\n serverName: \"cortex-vercel\",\n authMode: \"company\" as const,\n },\n {\n name: \"supabase\",\n displayName: \"Supabase\",\n description: \"Database, migrations, edge functions (20+ tools)\",\n serverName: \"cortex-supabase\",\n authMode: \"company\" as const,\n },\n {\n name: \"bestbuy\",\n displayName: \"Best Buy\",\n description: \"Product search, pricing, reviews, store locations (7 tools)\",\n serverName: \"cortex-bestbuy\",\n authMode: \"company\" as const,\n },\n {\n name: \"mailchimp\",\n displayName: \"Mailchimp\",\n description: \"Audiences, contacts, campaigns, templates, analytics (28 tools)\",\n serverName: \"cortex-mailchimp\",\n authMode: \"personal\" as const,\n },\n {\n name: \"salesforce\",\n displayName: \"Salesforce\",\n description: \"CRM queries, records, reports, and org data (14 tools)\",\n serverName: \"cortex-salesforce\",\n authMode: \"personal\" as const,\n },\n {\n name: \"monday\",\n displayName: \"Monday.com\",\n description: \"Boards, items, groups, updates, workspaces (18 tools)\",\n serverName: \"cortex-monday\",\n authMode: \"personal\" as const,\n installUrl: \"https://auth.monday.com/oauth2/authorize?client_id=c8d2c70bd792a4c36c6f023c0b707517&response_type=install\",\n },\n {\n name: \"slack\",\n displayName: \"Slack\",\n description: \"Messaging, channels, search, reactions, bookmarks (22 tools)\",\n serverName: \"cortex-slack\",\n authMode: \"personal\" as const,\n },\n {\n name: \"powerbi\",\n displayName: \"Power BI\",\n description: \"Workspaces, datasets, push data, DAX queries, reports, dashboards (14 tools)\",\n serverName: \"cortex-powerbi\",\n authMode: \"personal\" as const,\n },\n {\n name: \"databricks\",\n displayName: \"Databricks\",\n description: \"Unity Catalog discovery, SQL queries, data dictionary, jobs (18 tools)\",\n serverName: \"cortex-databricks\",\n authMode: \"company\" as const,\n },\n] as const;\n\n/** All available MCP names */\nexport const MCP_NAMES: string[] = AVAILABLE_MCPS.map((m) => m.name);\n\n/** Default MCPs enabled on fresh setup */\nexport const DEFAULT_MCPS: string[] = [...MCP_NAMES];\n\n/** Shared API key embedded in the package (no user prompt needed) */\nexport const DEFAULT_API_KEY =\n \"ctx_07d37a81_9f7be06af38d04753090a4034f907a65ec06cd675ed26f65653898388e2d1709\";\n\n/** Config directory name */\nexport const CONFIG_DIR_NAME = \".cortex-mcp\";\n\n/** Config file name */\nexport const CONFIG_FILE_NAME = \"config.json\";\n\n/** Credentials file name (stores personal API key from login) */\nexport const CREDENTIALS_FILE_NAME = \"credentials.json\";\n","import { PROTOCOL_VERSION } from \"../constants.js\";\n\n/** JSON-RPC 2.0 request */\ninterface JsonRpcRequest {\n jsonrpc: \"2.0\";\n method: string;\n params?: Record<string, unknown>;\n id: string | number;\n}\n\n/** JSON-RPC 2.0 response */\ninterface JsonRpcResponse {\n jsonrpc: \"2.0\";\n result?: unknown;\n error?: { code: number; message: string };\n id: string | number | null;\n}\n\n/**\n * HTTP client that forwards JSON-RPC 2.0 requests to the Cortex server.\n */\nexport class CortexHttpClient {\n private sessionId: string | null = null;\n private requestId = 0;\n\n constructor(\n private serverUrl: string,\n private apiKey: string,\n private endpoint: string = \"cortex\"\n ) {}\n\n /** Send an initialize request to establish a session */\n async initialize(): Promise<JsonRpcResponse> {\n const response = await this.sendRequest(\"initialize\", {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: {},\n clientInfo: { name: \"cortex-mcp-proxy\", version: \"1.0.0\" },\n });\n\n // Send initialized notification (no id = notification, no response expected)\n await this.sendNotification(\"notifications/initialized\", {});\n\n return response;\n }\n\n /** List available tools */\n async listTools(): Promise<JsonRpcResponse> {\n return this.sendRequest(\"tools/list\", {});\n }\n\n /** Call a tool */\n async callTool(\n name: string,\n args: Record<string, unknown>\n ): Promise<JsonRpcResponse> {\n return this.sendRequest(\"tools/call\", { name, arguments: args });\n }\n\n /** Send a JSON-RPC request and return the response */\n private async sendRequest(\n method: string,\n params: Record<string, unknown>\n ): Promise<JsonRpcResponse> {\n const id = String(++this.requestId);\n const body: JsonRpcRequest = { jsonrpc: \"2.0\", method, params, id };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": this.apiKey,\n \"mcp-protocol-version\": PROTOCOL_VERSION,\n \"x-cortex-client\": \"cortex-mcp-stdio\",\n };\n\n if (this.sessionId) {\n headers[\"mcp-session-id\"] = this.sessionId;\n }\n\n const url = `${this.serverUrl}/mcp/${this.endpoint}`;\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(60_000),\n });\n\n // Capture session ID from initialize\n const newSessionId = response.headers.get(\"mcp-session-id\");\n if (newSessionId) {\n this.sessionId = newSessionId;\n }\n\n if (!response.ok) {\n const text = await response.text();\n return {\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: this.humanReadableError(response.status, text),\n },\n id,\n };\n }\n\n return (await response.json()) as JsonRpcResponse;\n }\n\n /** Send a JSON-RPC notification (no response expected) */\n private async sendNotification(\n method: string,\n params: Record<string, unknown>\n ): Promise<void> {\n const body = { jsonrpc: \"2.0\", method, params };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": this.apiKey,\n \"mcp-protocol-version\": PROTOCOL_VERSION,\n \"x-cortex-client\": \"cortex-mcp-stdio\",\n };\n\n if (this.sessionId) {\n headers[\"mcp-session-id\"] = this.sessionId;\n }\n\n const url = `${this.serverUrl}/mcp/${this.endpoint}`;\n\n try {\n await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(10_000),\n });\n } catch {\n // Notifications are fire-and-forget\n }\n }\n\n /** Convert HTTP status codes to user-friendly messages */\n private humanReadableError(status: number, body: string): string {\n switch (status) {\n case 401:\n return \"Invalid API key. Check your key at https://aidentity.app/settings/keys\";\n case 403:\n return \"API key lacks MCP permissions. Create a new key with MCP access.\";\n case 404:\n return \"MCP endpoint not found. The server may be misconfigured.\";\n case 503:\n return \"MCP protocol is disabled on the server.\";\n default:\n return `Server error (${status}): ${body.slice(0, 200)}`;\n }\n }\n}\n","import { readFileSync, statSync } from \"node:fs\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { CortexHttpClient } from \"./http-client.js\";\nimport { FILESYSTEM_TOOLS, handleLocalFilesystemTool } from \"./local-filesystem.js\";\n\ninterface StdioServerOptions {\n serverUrl: string;\n apiKey: string;\n /** Use \"cortex\" for composite endpoint, or a specific MCP name */\n endpoint?: string;\n}\n\n/** Tools that support local file_path → upload interception */\nconst UPLOAD_TOOLS = new Set([\"upload_file\", \"upload_file_to_sharepoint\"]);\n\n/** Max file size for inline base64 upload via JSON-RPC (3MB).\n * 3MB raw → 4MB base64 → safely within Vercel's ~4.5MB body limit. */\nconst INLINE_UPLOAD_MAX = 3 * 1024 * 1024;\n\n/**\n * Override upload tool schemas so the LLM only sees `file_path` (not `content`).\n * This forces the LLM to pass a local file path, which the proxy handles locally\n * — no base64 encoding by the LLM, no truncation, no corruption.\n */\nfunction overrideUploadToolSchema(\n tool: Record<string, unknown>\n): Record<string, unknown> {\n const name = tool.name as string;\n const baseName = name.includes(\"__\") ? name.split(\"__\").pop()! : name;\n\n if (baseName === \"upload_file\") {\n return {\n ...tool,\n description:\n \"Upload a local file to the user's OneDrive. \" +\n \"Provide the absolute local file path — the file is read \" +\n \"and uploaded automatically. Works with any file size.\",\n inputSchema: {\n type: \"object\",\n required: [\"file_path\", \"path\"],\n properties: {\n file_path: {\n type: \"string\",\n description:\n \"Absolute path to the local file to upload \" +\n \"(e.g. '/Users/name/Documents/report.xlsx')\",\n },\n path: {\n type: \"string\",\n description:\n \"Destination path in OneDrive \" +\n \"(e.g. 'Documents/report.xlsx')\",\n },\n content_type: {\n type: \"string\",\n description: \"MIME type. Defaults to 'application/octet-stream'\",\n },\n },\n },\n };\n }\n\n if (baseName === \"upload_file_to_sharepoint\") {\n return {\n ...tool,\n description:\n \"Upload a local file to a SharePoint document library. \" +\n \"Provide the absolute local file path — the file is read \" +\n \"and uploaded automatically.\",\n inputSchema: {\n type: \"object\",\n required: [\"file_path\", \"site_id\", \"path\"],\n properties: {\n file_path: {\n type: \"string\",\n description: \"Absolute path to the local file to upload\",\n },\n site_id: {\n type: \"string\",\n description: \"SharePoint site ID\",\n },\n path: {\n type: \"string\",\n description:\n \"Destination path in the site drive \" +\n \"(e.g. 'Shared Documents/report.pdf')\",\n },\n content_type: {\n type: \"string\",\n description: \"MIME type. Defaults to 'application/octet-stream'\",\n },\n },\n },\n };\n }\n\n return tool;\n}\n\n/**\n * Handle a file upload tool call locally by reading the file from disk.\n *\n * - Small files (≤3MB): base64-encode and forward as `content` param\n * - Large files (>3MB): get an upload session URL from backend, then\n * relay 2.5MB chunks through the backend's `upload_file_chunk` tool\n * (the backend has unrestricted internet; the proxy may be sandboxed)\n */\nasync function handleLocalFileUpload(\n cortex: CortexHttpClient,\n toolName: string,\n args: Record<string, unknown>\n): Promise<{ content: Array<{ type: string; text: string }>; isError: boolean }> {\n const filePath = args.file_path as string;\n\n // Validate file exists\n let fileSize: number;\n try {\n fileSize = statSync(filePath as string).size;\n } catch {\n return {\n content: [{ type: \"text\", text: JSON.stringify({\n success: false,\n error: `File not found: ${filePath}`,\n }) }],\n isError: true,\n };\n }\n\n if (fileSize <= INLINE_UPLOAD_MAX) {\n // Small file: read, base64-encode, and forward via normal JSON-RPC\n const fileBuffer = readFileSync(filePath);\n const base64Content = fileBuffer.toString(\"base64\");\n\n const forwardArgs: Record<string, unknown> = { ...args, content: base64Content };\n delete forwardArgs.file_path;\n\n console.error(\n `[cortex-mcp] ${toolName}: reading local file (${(fileSize / 1024).toFixed(1)}KB), forwarding as base64`\n );\n\n const response = await cortex.callTool(toolName, forwardArgs);\n\n if (response.error) {\n return {\n content: [{ type: \"text\", text: response.error.message }],\n isError: true,\n };\n }\n\n return response.result as {\n content: Array<{ type: string; text: string }>;\n isError: boolean;\n };\n }\n\n // Large file: use upload session to upload directly to Microsoft Graph\n console.error(\n `[cortex-mcp] ${toolName}: large file (${(fileSize / 1024 / 1024).toFixed(1)}MB), using upload session`\n );\n\n // Step 1: Get pre-authenticated upload URL from backend\n // Preserve composite prefix (e.g. \"m365__\") so the backend routes correctly\n const prefix = toolName.includes(\"__\") ? toolName.split(\"__\")[0] + \"__\" : \"\";\n const sessionResponse = await cortex.callTool(`${prefix}create_upload_session`, {\n path: args.path,\n });\n\n if (sessionResponse.error) {\n return {\n content: [{ type: \"text\", text: sessionResponse.error.message }],\n isError: true,\n };\n }\n\n const sessionResult = sessionResponse.result as {\n content: Array<{ type: string; text: string }>;\n };\n\n let sessionData: { uploadUrl?: string };\n try {\n sessionData = JSON.parse(sessionResult.content[0].text);\n } catch {\n return {\n content: [{ type: \"text\", text: JSON.stringify({\n success: false,\n error: \"Failed to parse upload session response from backend\",\n }) }],\n isError: true,\n };\n }\n\n const uploadUrl = sessionData.uploadUrl;\n if (!uploadUrl) {\n return {\n content: [{ type: \"text\", text: JSON.stringify({\n success: false,\n error: \"Backend did not return an uploadUrl\",\n }) }],\n isError: true,\n };\n }\n\n // Step 2: Upload file in chunks through the Cortex backend.\n // We relay via the backend (which has unrestricted internet) instead of\n // uploading directly to Graph — the proxy may be in a sandboxed VM that\n // blocks outbound connections to SharePoint/Microsoft Graph.\n const fileBuffer = readFileSync(filePath);\n const chunkSize = 2.5 * 1024 * 1024; // 2.5MB → ~3.33MB base64 → within Vercel 4.5MB limit\n const total = fileBuffer.length;\n let driveItem: Record<string, unknown> = {};\n\n for (let start = 0; start < total; start += chunkSize) {\n const end = Math.min(start + chunkSize, total);\n const chunk = fileBuffer.subarray(start, end);\n const chunkBase64 = Buffer.from(chunk).toString(\"base64\");\n\n console.error(\n `[cortex-mcp] Uploading chunk ${start}-${end - 1}/${total} via backend relay`\n );\n\n const chunkResponse = await cortex.callTool(`${prefix}upload_file_chunk`, {\n upload_url: uploadUrl,\n chunk: chunkBase64,\n range_start: start,\n range_end: end - 1,\n total_size: total,\n });\n\n if (chunkResponse.error) {\n return {\n content: [{ type: \"text\", text: chunkResponse.error.message }],\n isError: true,\n };\n }\n\n const chunkResult = chunkResponse.result as {\n content: Array<{ type: string; text: string }>;\n };\n\n let chunkData: Record<string, unknown>;\n try {\n chunkData = JSON.parse(chunkResult.content[0].text) as Record<string, unknown>;\n } catch {\n return {\n content: [{ type: \"text\", text: JSON.stringify({\n success: false,\n error: \"Failed to parse chunk upload response from backend\",\n }) }],\n isError: true,\n };\n }\n\n if (!chunkData.success) {\n return {\n content: [{ type: \"text\", text: JSON.stringify(chunkData) }],\n isError: true,\n };\n }\n\n // Final chunk (200/201) contains the DriveItem\n if (chunkData.status === 200 || chunkData.status === 201) {\n driveItem = (chunkData.data as Record<string, unknown>) ?? {};\n }\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify({\n success: true,\n file: driveItem,\n message: `Uploaded '${args.path}' (${(fileSize / 1024 / 1024).toFixed(1)}MB) via upload session`,\n }) }],\n isError: false,\n };\n}\n\n/**\n * Start a stdio MCP server that proxies all requests to the hosted Cortex server.\n * This is used by clients that only support stdio transport (e.g., OpenClaw).\n */\nexport async function startStdioServer(\n options: StdioServerOptions\n): Promise<void> {\n const { serverUrl, apiKey, endpoint = \"cortex\" } = options;\n\n const cortex = new CortexHttpClient(serverUrl, apiKey, endpoint);\n\n const server = new Server(\n { name: \"cortex-mcp\", version: \"1.0.0\" },\n { capabilities: { tools: { listChanged: false } } }\n );\n\n // Lazy initialization — runs on first request, not at startup\n let initialized = false;\n\n async function ensureInitialized(): Promise<void> {\n if (initialized) return;\n try {\n console.error(\"[cortex-mcp] Initializing backend session...\");\n await cortex.initialize();\n console.error(\"[cortex-mcp] Backend session established.\");\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`[cortex-mcp] Backend initialization failed: ${msg}`);\n // Continue anyway — tools/list and tools/call may still work without a session\n }\n initialized = true;\n }\n\n // Forward tools/list to Cortex\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n await ensureInitialized();\n const response = await cortex.listTools();\n\n if (response.error) {\n throw new Error(response.error.message);\n }\n\n const result = response.result as { tools: Record<string, unknown>[] };\n const tools = (result.tools || []).map(overrideUploadToolSchema);\n return { tools };\n });\n\n // Forward tools/call to Cortex (with local file upload interception)\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n await ensureInitialized();\n const { name, arguments: args } = request.params;\n const typedArgs = (args ?? {}) as Record<string, unknown>;\n\n // Intercept upload tools with file_path — handle locally\n // Composite endpoint prefixes tool names with \"{mcp}__\", so match on suffix\n const baseName = name.includes(\"__\") ? name.split(\"__\").pop()! : name;\n if (UPLOAD_TOOLS.has(baseName) && typedArgs.file_path) {\n return handleLocalFileUpload(cortex, name, typedArgs);\n }\n\n // Intercept filesystem tools — execute locally instead of on remote server\n if (FILESYSTEM_TOOLS.has(baseName)) {\n return handleLocalFilesystemTool(name, baseName, typedArgs);\n }\n\n const response = await cortex.callTool(name, typedArgs);\n\n if (response.error) {\n return {\n content: [{ type: \"text\" as const, text: response.error.message }],\n isError: true,\n };\n }\n\n const result = response.result as {\n content: Array<{ type: string; text: string }>;\n isError: boolean;\n };\n\n return result;\n });\n\n // Connect to stdio transport immediately — do NOT block on backend init\n console.error(\"[cortex-mcp] Starting stdio server...\");\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error(\"[cortex-mcp] Stdio server connected.\");\n}\n","/**\n * Local filesystem tool handlers for cortex-mcp.\n *\n * Intercepts filesystem MCP tool calls and executes them locally on the\n * user's machine using Node.js fs APIs, instead of forwarding to the\n * remote Cortex server (which cannot access local files).\n *\n * Response shapes match the server-side FileSystem MCP exactly so that\n * consumers see identical results regardless of execution location.\n */\n\nimport {\n copyFileSync,\n cpSync,\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n rmSync,\n statSync,\n unlinkSync,\n writeFileSync,\n appendFileSync,\n renameSync,\n type Dirent,\n} from \"node:fs\";\nimport { basename, dirname, extname, join, relative, resolve } from \"node:path\";\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\n/** Tools handled locally instead of proxied to the server. */\nexport const FILESYSTEM_TOOLS = new Set([\n \"read_file\",\n \"read_file_lines\",\n \"write_file\",\n \"append_file\",\n \"create_directory\",\n \"delete\",\n \"move\",\n \"copy\",\n \"list_directory\",\n \"exists\",\n \"get_file_info\",\n \"search_files\",\n \"find_in_files\",\n \"get_tree\",\n]);\n\n/** Maximum bytes to read in a single read_file call (50 MB). */\nconst MAX_READ_SIZE = 50 * 1024 * 1024;\n\n/** Bytes to sample for binary detection. */\nconst BINARY_CHECK_SIZE = 8192;\n\n/** Binary file magic byte signatures. */\nconst BINARY_SIGNATURES: Buffer[] = [\n Buffer.from([0x89, 0x50, 0x4e, 0x47]), // PNG\n Buffer.from([0xff, 0xd8, 0xff]), // JPEG\n Buffer.from(\"GIF8\"), // GIF\n Buffer.from([0x50, 0x4b, 0x03, 0x04]), // ZIP / DOCX / XLSX\n Buffer.from(\"%PDF\"), // PDF\n Buffer.from([0x7f, 0x45, 0x4c, 0x46]), // ELF\n Buffer.from([0xfe, 0xed, 0xfa]), // Mach-O\n Buffer.from([0xcf, 0xfa, 0xed, 0xfe]), // Mach-O (reversed)\n Buffer.from(\"MZ\"), // Windows executable\n];\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\ntype ToolResult = {\n content: Array<{ type: string; text: string }>;\n isError: boolean;\n};\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\n/** Resolve a path — absolute paths as-is, relative against cwd. */\nfunction resolvePath(p: string): string {\n return resolve(p);\n}\n\n/** Detect whether a file is binary by checking magic bytes and null bytes. */\nfunction isBinaryFile(filePath: string): boolean {\n try {\n const fd = readFileSync(filePath, { flag: \"r\" });\n const chunk = fd.subarray(0, BINARY_CHECK_SIZE);\n if (chunk.length === 0) return false;\n\n for (const sig of BINARY_SIGNATURES) {\n if (chunk.length >= sig.length && chunk.subarray(0, sig.length).equals(sig)) {\n return true;\n }\n }\n return chunk.includes(0);\n } catch {\n return false;\n }\n}\n\n/** Convert a simple glob pattern to a RegExp (supports *, ?, [...]). */\nfunction globToRegex(pattern: string): RegExp {\n let re = \"^\";\n for (let i = 0; i < pattern.length; i++) {\n const c = pattern[i];\n if (c === \"*\") {\n re += \".*\";\n } else if (c === \"?\") {\n re += \".\";\n } else if (c === \"[\") {\n const close = pattern.indexOf(\"]\", i + 1);\n if (close !== -1) {\n re += \"[\" + pattern.slice(i + 1, close) + \"]\";\n i = close;\n } else {\n re += \"\\\\[\";\n }\n } else if (\".+^${}()|\\\\\".includes(c)) {\n re += \"\\\\\" + c;\n } else {\n re += c;\n }\n }\n re += \"$\";\n return new RegExp(re);\n}\n\n/** Get file type string from stat/dirent. */\nfunction fileType(isDir: boolean, isSymlink: boolean): string {\n if (isSymlink) return \"symlink\";\n if (isDir) return \"directory\";\n return \"file\";\n}\n\n/** Count files and total bytes in a directory tree. */\nfunction countDirectoryContents(dirPath: string): { files: number; bytes: number } {\n let files = 0;\n let bytes = 0;\n try {\n const entries = readdirSync(dirPath, { withFileTypes: true });\n for (const entry of entries) {\n const full = join(dirPath, entry.name);\n if (entry.isDirectory()) {\n const sub = countDirectoryContents(full);\n files += sub.files;\n bytes += sub.bytes;\n } else {\n files += 1;\n try {\n bytes += statSync(full).size;\n } catch { /* skip */ }\n }\n }\n } catch { /* skip */ }\n return { files, bytes };\n}\n\n/** Build success result. */\nfunction ok(data: unknown): ToolResult {\n return {\n content: [{ type: \"text\", text: JSON.stringify(data) }],\n isError: false,\n };\n}\n\n/** Build error result. */\nfunction err(message: string): ToolResult {\n return {\n content: [{ type: \"text\", text: JSON.stringify({ success: false, error: message }) }],\n isError: true,\n };\n}\n\n// ─── Tool Handlers ───────────────────────────────────────────────────────────\n\nfunction handleReadFile(args: Record<string, unknown>): ToolResult {\n const filePath = resolvePath(args.path as string);\n const encoding = (args.encoding as string) || \"utf-8\";\n\n const stat = statSync(filePath);\n if (!stat.isFile()) throw new Error(\"Not a file.\");\n if (stat.size > MAX_READ_SIZE) {\n throw new Error(`File size (${stat.size} bytes) exceeds maximum allowed size (${MAX_READ_SIZE} bytes).`);\n }\n\n if (isBinaryFile(filePath)) {\n const raw = readFileSync(filePath);\n return ok({\n content: raw.toString(\"base64\"),\n is_binary: true,\n size: stat.size,\n encoding: \"base64\",\n path: filePath,\n });\n }\n\n const text = readFileSync(filePath, encoding as BufferEncoding);\n return ok({\n content: text,\n is_binary: false,\n size: stat.size,\n encoding,\n path: filePath,\n });\n}\n\nfunction handleReadFileLines(args: Record<string, unknown>): ToolResult {\n const filePath = resolvePath(args.path as string);\n const encoding = (args.encoding as string) || \"utf-8\";\n const startLine = (args.start_line as number) || 1;\n const endLine = args.end_line as number | undefined;\n\n const stat = statSync(filePath);\n if (!stat.isFile()) throw new Error(\"Not a file.\");\n if (stat.size > MAX_READ_SIZE) {\n throw new Error(`File size (${stat.size} bytes) exceeds maximum allowed size.`);\n }\n\n if (startLine < 1) throw new Error(\"start_line must be >= 1.\");\n if (endLine !== undefined && endLine < startLine) throw new Error(\"end_line must be >= start_line.\");\n\n const text = readFileSync(filePath, encoding as BufferEncoding);\n const allLines = text.split(/\\n/);\n const totalLines = allLines.length;\n\n const startIdx = startLine - 1;\n const endIdx = endLine !== undefined ? endLine : totalLines;\n const selected = allLines.slice(startIdx, endIdx);\n const actualEnd = Math.min(endIdx, totalLines);\n\n return ok({\n content: selected.join(\"\\n\"),\n start_line: startLine,\n end_line: actualEnd,\n total_lines: totalLines,\n size: stat.size,\n path: filePath,\n });\n}\n\nfunction handleWriteFile(args: Record<string, unknown>): ToolResult {\n const filePath = resolvePath(args.path as string);\n const content = args.content as string;\n const encoding = (args.encoding as string) || \"utf-8\";\n const isBinary = (args.is_binary as boolean) || false;\n const overwrite = args.overwrite !== false; // default true\n const createParents = (args.create_parents as boolean) || false;\n\n const created = !existsSync(filePath);\n\n if (!overwrite && !created) {\n throw new Error(\"File already exists.\");\n }\n\n if (createParents) {\n mkdirSync(dirname(filePath), { recursive: true });\n }\n\n let bytesWritten: number;\n let usedEncoding: string;\n\n if (isBinary) {\n const raw = Buffer.from(content, \"base64\");\n writeFileSync(filePath, raw);\n bytesWritten = raw.length;\n usedEncoding = \"base64\";\n } else {\n const encoded = Buffer.from(content, encoding as BufferEncoding);\n writeFileSync(filePath, content, encoding as BufferEncoding);\n bytesWritten = encoded.length;\n usedEncoding = encoding;\n }\n\n return ok({\n path: filePath,\n bytes_written: bytesWritten,\n created,\n encoding: usedEncoding,\n });\n}\n\nfunction handleAppendFile(args: Record<string, unknown>): ToolResult {\n const filePath = resolvePath(args.path as string);\n const content = args.content as string;\n const encoding = (args.encoding as string) || \"utf-8\";\n\n if (!existsSync(filePath)) throw new Error(\"File not found.\");\n\n const encoded = Buffer.from(content, encoding as BufferEncoding);\n appendFileSync(filePath, content, encoding as BufferEncoding);\n const newSize = statSync(filePath).size;\n\n return ok({\n path: filePath,\n bytes_written: encoded.length,\n new_size: newSize,\n });\n}\n\nfunction handleCreateDirectory(args: Record<string, unknown>): ToolResult {\n const dirPath = resolvePath(args.path as string);\n const parents = args.parents !== false; // default true\n\n if (existsSync(dirPath)) {\n return ok({ path: dirPath, created: false });\n }\n\n if (parents) {\n mkdirSync(dirPath, { recursive: true });\n } else {\n mkdirSync(dirPath);\n }\n\n return ok({ path: dirPath, created: true });\n}\n\nfunction handleDelete(args: Record<string, unknown>): ToolResult {\n const targetPath = resolvePath(args.path as string);\n const recursive = (args.recursive as boolean) || false;\n\n if (!existsSync(targetPath)) throw new Error(\"Path not found.\");\n\n const stat = statSync(targetPath, { throwIfNoEntry: false });\n if (!stat) throw new Error(\"Path not found.\");\n\n if (stat.isDirectory()) {\n const { files: filesDeleted, bytes: bytesFreed } = countDirectoryContents(targetPath);\n if (recursive) {\n rmSync(targetPath, { recursive: true });\n } else {\n // rmSync without recursive only removes empty dirs\n rmSync(targetPath);\n }\n return ok({\n path: targetPath,\n type: \"directory\",\n files_deleted: recursive ? filesDeleted : 0,\n bytes_freed: recursive ? bytesFreed : 0,\n });\n }\n\n const size = stat.size;\n unlinkSync(targetPath);\n return ok({\n path: targetPath,\n type: \"file\",\n files_deleted: 1,\n bytes_freed: size,\n });\n}\n\nfunction handleMove(args: Record<string, unknown>): ToolResult {\n const source = resolvePath(args.source as string);\n const destination = resolvePath(args.destination as string);\n const overwrite = (args.overwrite as boolean) || false;\n\n if (!existsSync(source)) throw new Error(\"Source path not found.\");\n if (existsSync(destination) && !overwrite) throw new Error(\"Destination already exists.\");\n\n const stat = statSync(source);\n const type = stat.isDirectory() ? \"directory\" : \"file\";\n const bytesMoved = stat.isDirectory()\n ? countDirectoryContents(source).bytes\n : stat.size;\n\n try {\n renameSync(source, destination);\n } catch (e: unknown) {\n // EXDEV: cross-device rename — fallback to copy + delete\n if ((e as NodeJS.ErrnoException).code === \"EXDEV\") {\n if (stat.isDirectory()) {\n cpSync(source, destination, { recursive: true });\n rmSync(source, { recursive: true });\n } else {\n copyFileSync(source, destination);\n unlinkSync(source);\n }\n } else {\n throw e;\n }\n }\n\n return ok({\n source,\n destination,\n type,\n bytes_moved: bytesMoved,\n });\n}\n\nfunction handleCopy(args: Record<string, unknown>): ToolResult {\n const source = resolvePath(args.source as string);\n const destination = resolvePath(args.destination as string);\n const overwrite = (args.overwrite as boolean) || false;\n\n if (!existsSync(source)) throw new Error(\"Source path not found.\");\n if (existsSync(destination) && !overwrite) throw new Error(\"Destination already exists.\");\n\n const stat = statSync(source);\n\n if (stat.isDirectory()) {\n if (existsSync(destination) && overwrite) {\n rmSync(destination, { recursive: true });\n }\n cpSync(source, destination, { recursive: true });\n const { bytes } = countDirectoryContents(destination);\n return ok({ source, destination, type: \"directory\", bytes_copied: bytes });\n }\n\n copyFileSync(source, destination);\n const bytesCopied = statSync(destination).size;\n return ok({ source, destination, type: \"file\", bytes_copied: bytesCopied });\n}\n\nfunction handleListDirectory(args: Record<string, unknown>): ToolResult {\n const dirPath = resolvePath(args.path as string);\n const recursive = (args.recursive as boolean) || false;\n const maxDepth = (args.max_depth as number) || 1;\n const pattern = args.pattern as string | undefined;\n const includeHidden = (args.include_hidden as boolean) || false;\n\n if (!existsSync(dirPath)) throw new Error(\"Directory not found.\");\n const stat = statSync(dirPath);\n if (!stat.isDirectory()) throw new Error(\"Path is not a directory.\");\n\n const effectiveDepth = recursive ? maxDepth : 1;\n const patternRe = pattern ? globToRegex(pattern) : null;\n\n interface Entry {\n name: string;\n path: string;\n type: string;\n size: number;\n modified_at: string;\n is_hidden: boolean;\n }\n\n const entries: Entry[] = [];\n\n function scan(dir: string, depth: number): void {\n if (depth >= effectiveDepth) return;\n\n let dirents: Dirent[];\n try {\n dirents = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n dirents.sort((a, b) => a.name.localeCompare(b.name));\n\n for (const d of dirents) {\n if (!includeHidden && d.name.startsWith(\".\")) continue;\n\n const fullPath = join(dir, d.name);\n const isDir = d.isDirectory();\n\n // Apply pattern filter\n if (patternRe && !patternRe.test(d.name)) {\n // Still recurse into directories even if name doesn't match\n if (isDir && effectiveDepth > 1) {\n scan(fullPath, depth + 1);\n }\n continue;\n }\n\n let size = 0;\n let mtime = new Date().toISOString();\n try {\n const s = statSync(fullPath);\n size = isDir ? 0 : s.size;\n mtime = new Date(s.mtimeMs).toISOString();\n } catch { /* skip */ }\n\n entries.push({\n name: d.name,\n path: relative(dirPath, fullPath),\n type: fileType(isDir, d.isSymbolicLink()),\n size,\n modified_at: mtime,\n is_hidden: d.name.startsWith(\".\"),\n });\n\n if (isDir && effectiveDepth > 1) {\n scan(fullPath, depth + 1);\n }\n }\n }\n\n scan(dirPath, 0);\n\n return ok({\n path: dirPath,\n entries,\n total_count: entries.length,\n });\n}\n\nfunction handleExists(args: Record<string, unknown>): ToolResult {\n const targetPath = resolvePath(args.path as string);\n const pathExists = existsSync(targetPath);\n\n let type: string | null = null;\n if (pathExists) {\n const stat = statSync(targetPath, { throwIfNoEntry: false });\n if (stat) {\n type = fileType(stat.isDirectory(), stat.isSymbolicLink());\n }\n }\n\n return ok({ exists: pathExists, path: targetPath, type });\n}\n\nfunction handleGetFileInfo(args: Record<string, unknown>): ToolResult {\n const filePath = resolvePath(args.path as string);\n if (!existsSync(filePath)) throw new Error(\"Path not found.\");\n\n const stat = statSync(filePath, { throwIfNoEntry: false });\n if (!stat) throw new Error(\"Path not found.\");\n\n const isDir = stat.isDirectory();\n const isSymlink = stat.isSymbolicLink();\n const name = basename(filePath);\n const ext = isDir ? null : extname(name) || null;\n const binary = !isDir && !isSymlink ? isBinaryFile(filePath) : false;\n\n return ok({\n name,\n path: filePath,\n type: fileType(isDir, isSymlink),\n size: isDir ? 0 : stat.size,\n modified_at: new Date(stat.mtimeMs).toISOString(),\n created_at: stat.birthtimeMs ? new Date(stat.birthtimeMs).toISOString() : null,\n extension: ext,\n is_hidden: name.startsWith(\".\"),\n is_binary: binary,\n });\n}\n\nfunction handleSearchFiles(args: Record<string, unknown>): ToolResult {\n const searchPath = resolvePath(args.path as string);\n const pattern = (args.pattern as string) || \"*\";\n const recursive = args.recursive !== false; // default true\n const includeHidden = (args.include_hidden as boolean) || false;\n const maxResults = (args.max_results as number) || 1000;\n\n if (!existsSync(searchPath)) throw new Error(\"Directory not found.\");\n if (!statSync(searchPath).isDirectory()) throw new Error(\"Path is not a directory.\");\n\n const patternRe = globToRegex(pattern);\n const matches: string[] = [];\n let totalMatches = 0;\n\n function scan(dir: string): void {\n let dirents: Dirent[];\n try {\n dirents = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const d of dirents) {\n if (!includeHidden) {\n if (d.name.startsWith(\".\")) continue;\n }\n\n const fullPath = join(dir, d.name);\n\n if (d.isDirectory()) {\n if (recursive) scan(fullPath);\n continue;\n }\n\n if (patternRe.test(d.name)) {\n totalMatches++;\n if (matches.length < maxResults) {\n matches.push(relative(searchPath, fullPath));\n }\n }\n }\n }\n\n scan(searchPath);\n\n return ok({\n matches,\n total_matches: totalMatches,\n truncated: totalMatches > maxResults,\n search_path: searchPath,\n pattern,\n });\n}\n\nfunction handleFindInFiles(args: Record<string, unknown>): ToolResult {\n const searchPath = resolvePath(args.path as string);\n const query = args.query as string;\n const isRegex = (args.is_regex as boolean) || false;\n const caseSensitive = args.case_sensitive !== false; // default true\n const filePattern = args.pattern as string | undefined;\n const contextLines = (args.context_lines as number) || 0;\n const maxResults = (args.max_results as number) || 500;\n const includeHidden = (args.include_hidden as boolean) || false;\n\n if (!existsSync(searchPath)) throw new Error(\"Directory not found.\");\n if (!statSync(searchPath).isDirectory()) throw new Error(\"Path is not a directory.\");\n\n const flags = caseSensitive ? \"\" : \"i\";\n const re = isRegex\n ? new RegExp(query, flags)\n : new RegExp(query.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"), flags);\n\n const patternRe = filePattern ? globToRegex(filePattern) : null;\n\n interface Match {\n file: string;\n line: number;\n content: string;\n context_before: string[];\n context_after: string[];\n }\n\n const results: Match[] = [];\n let totalMatches = 0;\n let filesSearched = 0;\n let filesWithMatches = 0;\n\n function scan(dir: string): void {\n let dirents: Dirent[];\n try {\n dirents = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const d of dirents) {\n if (!includeHidden && d.name.startsWith(\".\")) continue;\n\n const fullPath = join(dir, d.name);\n\n if (d.isDirectory()) {\n scan(fullPath);\n continue;\n }\n\n if (patternRe && !patternRe.test(d.name)) continue;\n if (isBinaryFile(fullPath)) continue;\n\n filesSearched++;\n let fileHasMatch = false;\n\n let lines: string[];\n try {\n const text = readFileSync(fullPath, \"utf-8\");\n lines = text.split(\"\\n\");\n } catch {\n continue;\n }\n\n for (let i = 0; i < lines.length; i++) {\n if (re.test(lines[i])) {\n totalMatches++;\n fileHasMatch = true;\n\n if (results.length < maxResults) {\n const ctxStart = Math.max(0, i - contextLines);\n const ctxEnd = Math.min(lines.length, i + contextLines + 1);\n\n results.push({\n file: relative(searchPath, fullPath),\n line: i + 1,\n content: lines[i],\n context_before: lines.slice(ctxStart, i),\n context_after: lines.slice(i + 1, ctxEnd),\n });\n }\n }\n }\n\n if (fileHasMatch) filesWithMatches++;\n }\n }\n\n scan(searchPath);\n\n return ok({\n results,\n total_matches: totalMatches,\n files_searched: filesSearched,\n files_with_matches: filesWithMatches,\n truncated: totalMatches > maxResults,\n query,\n });\n}\n\nfunction handleGetTree(args: Record<string, unknown>): ToolResult {\n const rootPath = resolvePath(args.path as string);\n const maxDepth = (args.max_depth as number) || 3;\n const includeHidden = (args.include_hidden as boolean) || false;\n const maxEntries = (args.max_entries as number) || 500;\n\n if (!existsSync(rootPath)) throw new Error(\"Directory not found.\");\n if (!statSync(rootPath).isDirectory()) throw new Error(\"Path is not a directory.\");\n\n const lines: string[] = [];\n let entryCount = 0;\n let truncated = false;\n\n const rootName = basename(rootPath) || rootPath;\n lines.push(rootName + \"/\");\n\n function buildTree(dirPath: string, prefix: string, depth: number): void {\n if (truncated || depth >= maxDepth) return;\n\n let dirents: Dirent[];\n try {\n dirents = readdirSync(dirPath, { withFileTypes: true });\n } catch {\n return;\n }\n\n if (!includeHidden) {\n dirents = dirents.filter((d) => !d.name.startsWith(\".\"));\n }\n dirents.sort((a, b) => a.name.localeCompare(b.name));\n\n for (let i = 0; i < dirents.length; i++) {\n if (truncated) return;\n\n entryCount++;\n if (entryCount > maxEntries) {\n truncated = true;\n lines.push(prefix + \"... (truncated)\");\n return;\n }\n\n const d = dirents[i];\n const isLast = i === dirents.length - 1;\n const connector = isLast ? \"└── \" : \"├── \";\n const childPrefix = prefix + (isLast ? \" \" : \"│ \");\n const fullPath = join(dirPath, d.name);\n\n if (d.isDirectory()) {\n lines.push(prefix + connector + d.name + \"/\");\n buildTree(fullPath, childPrefix, depth + 1);\n } else {\n lines.push(prefix + connector + d.name);\n }\n }\n }\n\n buildTree(rootPath, \"\", 0);\n\n return ok({\n tree: lines.join(\"\\n\"),\n path: rootPath,\n entry_count: entryCount,\n truncated,\n max_depth: maxDepth,\n });\n}\n\n// ─── Dispatcher ──────────────────────────────────────────────────────────────\n\nconst HANDLERS: Record<string, (args: Record<string, unknown>) => ToolResult> = {\n read_file: handleReadFile,\n read_file_lines: handleReadFileLines,\n write_file: handleWriteFile,\n append_file: handleAppendFile,\n create_directory: handleCreateDirectory,\n delete: handleDelete,\n move: handleMove,\n copy: handleCopy,\n list_directory: handleListDirectory,\n exists: handleExists,\n get_file_info: handleGetFileInfo,\n search_files: handleSearchFiles,\n find_in_files: handleFindInFiles,\n get_tree: handleGetTree,\n};\n\n/**\n * Handle a filesystem tool call locally on the user's machine.\n *\n * @param _toolName Full tool name (may include composite prefix like \"filesystem__\")\n * @param baseName Base tool name without prefix (e.g. \"read_file\")\n * @param args Tool arguments from the MCP client\n */\nexport function handleLocalFilesystemTool(\n _toolName: string,\n baseName: string,\n args: Record<string, unknown>,\n): ToolResult {\n console.error(`[cortex-mcp] filesystem.${baseName}: executing locally`);\n\n const handler = HANDLERS[baseName];\n if (!handler) {\n return err(`Unknown filesystem tool: ${baseName}`);\n }\n\n try {\n return handler(args);\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n console.error(`[cortex-mcp] filesystem.${baseName} error: ${message}`);\n return err(message);\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { CONFIG_DIR_NAME, CONFIG_FILE_NAME, DEFAULT_SERVER_URL } from \"../constants.js\";\nimport { getHomeDir } from \"../utils/platform.js\";\nimport type { CortexMcpConfig } from \"./types.js\";\n\n/** Get the config directory path */\nexport function getConfigDir(): string {\n return join(getHomeDir(), CONFIG_DIR_NAME);\n}\n\n/** Get the config file path */\nexport function getConfigPath(): string {\n return join(getConfigDir(), CONFIG_FILE_NAME);\n}\n\n/** Read the current config, or return null if none exists */\nexport function readConfig(): CortexMcpConfig | null {\n const path = getConfigPath();\n if (!existsSync(path)) return null;\n\n try {\n const raw = readFileSync(path, \"utf-8\");\n return JSON.parse(raw) as CortexMcpConfig;\n } catch {\n return null;\n }\n}\n\n/** Write config to disk (creates directory with 700 permissions, file with 600) */\nexport function writeConfig(config: CortexMcpConfig): void {\n const dir = getConfigDir();\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n\n const path = getConfigPath();\n writeFileSync(path, JSON.stringify(config, null, 2) + \"\\n\", {\n mode: 0o600,\n });\n}\n\n/** Create a default config with the given API key and MCPs */\nexport function createConfig(\n apiKey: string,\n mcps: string[]\n): CortexMcpConfig {\n return {\n version: 1,\n server: DEFAULT_SERVER_URL,\n apiKey,\n mcps,\n configuredClients: [],\n };\n}\n","import { homedir, platform } from \"node:os\";\nimport { join } from \"node:path\";\n\n/** Get the user's home directory */\nexport function getHomeDir(): string {\n return homedir();\n}\n\n/** Get the current platform */\nexport function getPlatform(): \"macos\" | \"windows\" | \"linux\" {\n const p = platform();\n if (p === \"darwin\") return \"macos\";\n if (p === \"win32\") return \"windows\";\n return \"linux\";\n}\n\n/**\n * Get the Claude Desktop config file path for the current platform.\n */\nexport function getClaudeDesktopConfigPath(): string {\n const home = getHomeDir();\n const p = getPlatform();\n\n switch (p) {\n case \"macos\":\n return join(\n home,\n \"Library\",\n \"Application Support\",\n \"Claude\",\n \"claude_desktop_config.json\"\n );\n case \"windows\":\n return join(\n process.env.APPDATA || join(home, \"AppData\", \"Roaming\"),\n \"Claude\",\n \"claude_desktop_config.json\"\n );\n case \"linux\":\n return join(home, \".config\", \"Claude\", \"claude_desktop_config.json\");\n }\n}\n\n/**\n * Get the Cursor MCP config file path for the current platform.\n */\nexport function getCursorConfigPath(): string {\n const home = getHomeDir();\n return join(home, \".cursor\", \"mcp.json\");\n}\n\n/**\n * Get the VS Code MCP config file path for the current platform.\n */\nexport function getVSCodeMcpConfigPath(): string {\n const home = getHomeDir();\n return join(home, \".vscode\", \"mcp.json\");\n}\n\n/**\n * Get the Antigravity MCP config file path for the current platform.\n */\nexport function getAntigravityConfigPath(): string {\n const home = getHomeDir();\n return join(home, \".gemini\", \"antigravity\", \"mcp_config.json\");\n}\n\n/**\n * Get the Codex (OpenAI) config file path.\n * Shared by both Codex CLI and Codex IDE extension.\n */\nexport function getCodexConfigPath(): string {\n const home = getHomeDir();\n return join(home, \".codex\", \"config.toml\");\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { mkdirSync } from \"node:fs\";\nimport { execSync } from \"node:child_process\";\nimport { AVAILABLE_MCPS } from \"../constants.js\";\nimport {\n getClaudeDesktopConfigPath,\n getCursorConfigPath,\n getVSCodeMcpConfigPath,\n getAntigravityConfigPath,\n getCodexConfigPath,\n} from \"../utils/platform.js\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { getPlatform } from \"../utils/platform.js\";\nimport type { ClientType, DetectedClient, HttpMcpEntry } from \"./types.js\";\n\n/**\n * Detect which AI clients are installed on this machine.\n */\nexport function detectClients(): DetectedClient[] {\n const clients: DetectedClient[] = [];\n\n // Claude Desktop\n const desktopPath = getClaudeDesktopConfigPath();\n const desktopDir = dirname(desktopPath);\n clients.push({\n type: \"claude-desktop\",\n name: \"Claude (Desktop)\",\n configPath: desktopPath,\n detected: existsSync(desktopDir),\n });\n\n // Claude Code\n let claudeCodeDetected = false;\n try {\n execSync(\"which claude\", { stdio: \"pipe\" });\n claudeCodeDetected = true;\n } catch {\n // claude CLI not in PATH\n }\n clients.push({\n type: \"claude-code\",\n name: \"Claude Code\",\n configPath: null,\n detected: claudeCodeDetected,\n });\n\n // Cursor\n const cursorPath = getCursorConfigPath();\n const cursorDir = dirname(cursorPath);\n clients.push({\n type: \"cursor\",\n name: \"Cursor\",\n configPath: cursorPath,\n detected: existsSync(cursorDir),\n });\n\n // VS Code\n const home = homedir();\n const vscodePath = getVSCodeMcpConfigPath();\n clients.push({\n type: \"vscode\",\n name: \"VS Code\",\n configPath: vscodePath,\n detected: existsSync(join(home, \".vscode\")),\n });\n\n // Antigravity\n const antigravityPath = getAntigravityConfigPath();\n clients.push({\n type: \"antigravity\",\n name: \"Antigravity\",\n configPath: antigravityPath,\n detected: existsSync(join(home, \".antigravity\")),\n });\n\n // Codex (OpenAI) — CLI and IDE extension share ~/.codex/config.toml\n const codexPath = getCodexConfigPath();\n let codexDetected = existsSync(join(home, \".codex\"));\n if (!codexDetected) {\n try {\n execSync(\"which codex\", { stdio: \"pipe\" });\n codexDetected = true;\n } catch {\n // codex CLI not in PATH\n }\n }\n clients.push({\n type: \"codex\",\n name: \"Codex (OpenAI)\",\n configPath: codexPath,\n detected: codexDetected,\n });\n\n // OpenClaw / Stdio (always available — manual copy-paste)\n clients.push({\n type: \"stdio\",\n name: \"OpenClaw (stdio)\",\n configPath: null,\n detected: true,\n });\n\n return clients;\n}\n\n/**\n * Build per-MCP HTTP entries for a given server URL and API key.\n */\nexport function buildHttpEntries(\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): Record<string, HttpMcpEntry> {\n const entries: Record<string, HttpMcpEntry> = {};\n\n for (const mcp of AVAILABLE_MCPS) {\n if (!mcps.includes(mcp.name)) continue;\n entries[mcp.serverName] = {\n url: `${serverUrl}/mcp/${mcp.name}`,\n headers: { \"x-api-key\": apiKey },\n };\n }\n\n return entries;\n}\n\n/**\n * Configure Claude Desktop by merging a stdio proxy entry into its config file.\n * Uses command/args/env format (Claude Desktop does not support HTTP url/headers).\n * Preserves existing non-Cortex entries.\n */\nexport function configureClaudeDesktop(\n _serverUrl: string,\n apiKey: string,\n _mcps: string[]\n): void {\n const configPath = getClaudeDesktopConfigPath();\n const dir = dirname(configPath);\n\n // Ensure directory exists\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Read existing config or start fresh\n let config: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n try {\n config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {\n // Corrupted file — start fresh\n }\n }\n\n // Ensure mcpServers key exists\n if (!config.mcpServers || typeof config.mcpServers !== \"object\") {\n config.mcpServers = {};\n }\n\n const servers = config.mcpServers as Record<string, unknown>;\n\n // Remove existing cortex-* and cortex entries\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\") || key === \"cortex\") {\n delete servers[key];\n }\n }\n\n // Add stdio proxy entry (Claude Desktop only supports command/args)\n // API key is read from ~/.cortex-mcp/credentials.json at runtime by the serve command,\n // so we don't bake it into the env (avoids stale key issues on re-login).\n // On Windows, npx is a .cmd batch file — must invoke via cmd.exe for stdio to work.\n const isWindows = getPlatform() === \"windows\";\n servers[\"cortex\"] = isWindows\n ? {\n command: \"cmd\",\n args: [\"/c\", \"npx\", \"-y\", \"@danainnovations/cortex-mcp@latest\", \"serve\"],\n }\n : {\n command: \"npx\",\n args: [\"-y\", \"@danainnovations/cortex-mcp@latest\", \"serve\"],\n };\n\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\n/**\n * Configure Claude Code by running `claude mcp add` commands.\n */\nexport function configureClaudeCode(\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): void {\n for (const mcp of AVAILABLE_MCPS) {\n if (!mcps.includes(mcp.name)) continue;\n\n const url = `${serverUrl}/mcp/${mcp.name}`;\n\n // Remove existing entry first (ignore errors if it doesn't exist)\n try {\n execSync(`claude mcp remove ${mcp.serverName}`, { stdio: \"pipe\" });\n } catch {\n // Entry didn't exist — fine\n }\n\n execSync(\n `claude mcp add --transport http ${mcp.serverName} ${url} -H \"x-api-key: ${apiKey}\"`,\n { stdio: \"pipe\" }\n );\n }\n}\n\n/**\n * Configure Cursor by writing HTTP MCP entries to its config file.\n * Cursor supports HTTP transport natively.\n */\nexport function configureCursor(\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): void {\n const configPath = getCursorConfigPath();\n const dir = dirname(configPath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n let config: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n try {\n config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {\n // Corrupted file — start fresh\n }\n }\n\n if (!config.mcpServers || typeof config.mcpServers !== \"object\") {\n config.mcpServers = {};\n }\n\n const servers = config.mcpServers as Record<string, unknown>;\n\n // Remove existing cortex-* entries\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\")) {\n delete servers[key];\n }\n }\n\n // Add new HTTP entries\n const entries = buildHttpEntries(serverUrl, apiKey, mcps);\n Object.assign(servers, entries);\n\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\n/**\n * Configure VS Code by writing HTTP MCP entries to its config file.\n */\nexport function configureVSCode(\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): void {\n const configPath = getVSCodeMcpConfigPath();\n const dir = dirname(configPath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n let config: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n try {\n config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {\n // Corrupted file — start fresh\n }\n }\n\n if (!config.mcpServers || typeof config.mcpServers !== \"object\") {\n config.mcpServers = {};\n }\n\n const servers = config.mcpServers as Record<string, unknown>;\n\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\")) {\n delete servers[key];\n }\n }\n\n const entries = buildHttpEntries(serverUrl, apiKey, mcps);\n Object.assign(servers, entries);\n\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\n/**\n * Configure Antigravity by writing HTTP MCP entries to its config file.\n */\nexport function configureAntigravity(\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): void {\n const configPath = getAntigravityConfigPath();\n const dir = dirname(configPath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n let config: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n try {\n config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {\n // Corrupted file — start fresh\n }\n }\n\n if (!config.mcpServers || typeof config.mcpServers !== \"object\") {\n config.mcpServers = {};\n }\n\n const servers = config.mcpServers as Record<string, unknown>;\n\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\")) {\n delete servers[key];\n }\n }\n\n const entries = buildHttpEntries(serverUrl, apiKey, mcps);\n Object.assign(servers, entries);\n\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\n/**\n * Configure Codex (OpenAI) by writing streamable HTTP entries to ~/.codex/config.toml.\n * Codex uses TOML format. The config is shared by both CLI and IDE extension.\n */\nexport function configureCodex(\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): void {\n const configPath = getCodexConfigPath();\n const dir = dirname(configPath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Read existing config to preserve non-cortex entries\n let existingContent = \"\";\n if (existsSync(configPath)) {\n try {\n existingContent = readFileSync(configPath, \"utf-8\");\n } catch {\n // Corrupted file — start fresh\n }\n }\n\n // Remove existing cortex-* MCP server blocks from TOML\n // Matches [mcp_servers.cortex-*] blocks until next section or EOF\n const cleaned = existingContent.replace(\n /\\[mcp_servers\\.cortex-[^\\]]*\\][^[]*(?=\\[|$)/g,\n \"\"\n ).trim();\n\n // Build new cortex MCP server entries in TOML format\n const tomlEntries: string[] = [];\n for (const mcp of AVAILABLE_MCPS) {\n if (!mcps.includes(mcp.name)) continue;\n tomlEntries.push(\n `[mcp_servers.${mcp.serverName}]\\n` +\n `url = \"${serverUrl}/mcp/${mcp.name}\"\\n` +\n `http_headers = { \"x-api-key\" = \"${apiKey}\" }`\n );\n }\n\n const newContent = (cleaned ? cleaned + \"\\n\\n\" : \"\") + tomlEntries.join(\"\\n\\n\") + \"\\n\";\n writeFileSync(configPath, newContent);\n}\n\n/**\n * Generate a stdio config snippet for clients that need it (OpenClaw, etc.)\n */\nexport function generateStdioSnippet(_apiKey: string): string {\n const isWindows = getPlatform() === \"windows\";\n const config = {\n mcpServers: {\n cortex: isWindows\n ? {\n command: \"cmd\",\n args: [\"/c\", \"npx\", \"-y\", \"@danainnovations/cortex-mcp@latest\", \"serve\"],\n }\n : {\n command: \"npx\",\n args: [\"-y\", \"@danainnovations/cortex-mcp@latest\", \"serve\"],\n },\n },\n };\n return JSON.stringify(config, null, 2);\n}\n\n/**\n * Remove all cortex-* MCP entries from Claude Desktop config.\n */\nexport function resetClaudeDesktop(): boolean {\n const configPath = getClaudeDesktopConfigPath();\n if (!existsSync(configPath)) return false;\n\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n if (!config.mcpServers) return false;\n\n const servers = config.mcpServers as Record<string, unknown>;\n let removed = false;\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\") || key === \"cortex\") {\n delete servers[key];\n removed = true;\n }\n }\n\n if (removed) {\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n return removed;\n } catch {\n return false;\n }\n}\n\n/**\n * Remove cortex MCP entries from Cursor config.\n */\nexport function resetCursor(): boolean {\n const configPath = getCursorConfigPath();\n if (!existsSync(configPath)) return false;\n\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n if (!config.mcpServers) return false;\n\n const servers = config.mcpServers as Record<string, unknown>;\n let removed = false;\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\") || key === \"cortex\") {\n delete servers[key];\n removed = true;\n }\n }\n\n if (removed) {\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n return removed;\n } catch {\n return false;\n }\n}\n\n/**\n * Remove cortex MCP entries from Claude Code.\n */\nexport function resetClaudeCode(): boolean {\n let removed = false;\n for (const mcp of AVAILABLE_MCPS) {\n try {\n execSync(`claude mcp remove ${mcp.serverName}`, { stdio: \"pipe\" });\n removed = true;\n } catch {\n // Entry didn't exist\n }\n }\n return removed;\n}\n\n/**\n * Remove cortex MCP entries from VS Code config.\n */\nexport function resetVSCode(): boolean {\n const configPath = getVSCodeMcpConfigPath();\n if (!existsSync(configPath)) return false;\n\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n if (!config.mcpServers) return false;\n\n const servers = config.mcpServers as Record<string, unknown>;\n let removed = false;\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\") || key === \"cortex\") {\n delete servers[key];\n removed = true;\n }\n }\n\n if (removed) {\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n return removed;\n } catch {\n return false;\n }\n}\n\n/**\n * Remove cortex MCP entries from Antigravity config.\n */\nexport function resetAntigravity(): boolean {\n const configPath = getAntigravityConfigPath();\n if (!existsSync(configPath)) return false;\n\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n if (!config.mcpServers) return false;\n\n const servers = config.mcpServers as Record<string, unknown>;\n let removed = false;\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\") || key === \"cortex\") {\n delete servers[key];\n removed = true;\n }\n }\n\n if (removed) {\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n return removed;\n } catch {\n return false;\n }\n}\n\n/**\n * Remove cortex MCP entries from Codex config.\n */\nexport function resetCodex(): boolean {\n const configPath = getCodexConfigPath();\n if (!existsSync(configPath)) return false;\n\n try {\n const content = readFileSync(configPath, \"utf-8\");\n const cleaned = content.replace(\n /\\[mcp_servers\\.cortex-[^\\]]*\\][^[]*(?=\\[|$)/g,\n \"\"\n ).trim();\n\n if (cleaned !== content.trim()) {\n writeFileSync(configPath, cleaned ? cleaned + \"\\n\" : \"\");\n return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * Configure a specific client type.\n */\nexport function configureClient(\n clientType: ClientType,\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): string {\n switch (clientType) {\n case \"claude-desktop\":\n configureClaudeDesktop(serverUrl, apiKey, mcps);\n return \"Claude Desktop configured\";\n case \"claude-code\":\n configureClaudeCode(serverUrl, apiKey, mcps);\n return \"Claude Code configured\";\n case \"cursor\":\n configureCursor(serverUrl, apiKey, mcps);\n return \"Cursor configured\";\n case \"vscode\":\n configureVSCode(serverUrl, apiKey, mcps);\n return \"VS Code configured\";\n case \"antigravity\":\n configureAntigravity(serverUrl, apiKey, mcps);\n return \"Antigravity configured\";\n case \"codex\":\n configureCodex(serverUrl, apiKey, mcps);\n return \"Codex configured\";\n case \"stdio\":\n return (\n \"Add this to your client config:\\n\\n\" +\n generateStdioSnippet(apiKey)\n );\n }\n}\n","/**\n * Validate that a string looks like a Cortex API key.\n * Format: ctx_{id}_{secret}\n */\nexport function isValidApiKey(key: string): boolean {\n return /^ctx_[a-zA-Z0-9]+_[a-zA-Z0-9]+$/.test(key.trim());\n}\n\n/**\n * Validate an API key against the Cortex server by sending an initialize request.\n * Returns true if the server responds with 200, false otherwise.\n */\nexport async function validateApiKeyRemote(\n serverUrl: string,\n apiKey: string\n): Promise<{ valid: boolean; error?: string }> {\n try {\n const response = await fetch(`${serverUrl}/mcp/github`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"mcp-protocol-version\": \"2024-11-05\",\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n method: \"initialize\",\n params: {\n protocolVersion: \"2024-11-05\",\n capabilities: {},\n clientInfo: { name: \"cortex-mcp-setup\", version: \"1.0.0\" },\n },\n id: \"validate\",\n }),\n });\n\n if (response.status === 401 || response.status === 403) {\n return { valid: false, error: \"Invalid or expired API key\" };\n }\n if (!response.ok) {\n return { valid: false, error: `Server returned ${response.status}` };\n }\n return { valid: true };\n } catch {\n return { valid: false, error: \"Could not reach the Cortex server\" };\n }\n}\n","import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { CONFIG_DIR_NAME, CREDENTIALS_FILE_NAME, DEFAULT_API_KEY } from \"../constants.js\";\nimport { readConfig } from \"../config/storage.js\";\nimport { getHomeDir } from \"../utils/platform.js\";\n\n/** Stored credentials from a successful login */\nexport interface CortexCredentials {\n apiKey: string;\n email: string;\n name?: string;\n authenticatedAt: string; // ISO 8601\n}\n\n/** Get the credentials file path (~/.cortex-mcp/credentials.json) */\nexport function getCredentialsPath(): string {\n return join(getHomeDir(), CONFIG_DIR_NAME, CREDENTIALS_FILE_NAME);\n}\n\n/** Read stored credentials, or return null if not logged in */\nexport function readCredentials(): CortexCredentials | null {\n const path = getCredentialsPath();\n if (!existsSync(path)) return null;\n\n try {\n const raw = readFileSync(path, \"utf-8\");\n return JSON.parse(raw) as CortexCredentials;\n } catch {\n return null;\n }\n}\n\n/** Write credentials to disk (creates directory with 700, file with 600 permissions) */\nexport function writeCredentials(creds: CortexCredentials): void {\n const dir = join(getHomeDir(), CONFIG_DIR_NAME);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n\n const path = getCredentialsPath();\n writeFileSync(path, JSON.stringify(creds, null, 2) + \"\\n\", {\n mode: 0o600,\n });\n}\n\n/** Delete stored credentials */\nexport function deleteCredentials(): void {\n const path = getCredentialsPath();\n if (existsSync(path)) {\n unlinkSync(path);\n }\n}\n\n/**\n * Get the effective API key to use.\n * Priority: CORTEX_API_KEY env var > stored credentials > config file > default shared key\n */\nexport function getEffectiveApiKey(): string {\n // 1. Environment variable (highest priority)\n const envKey = process.env.CORTEX_API_KEY;\n if (envKey) return envKey;\n\n // 2. Personal credentials from login\n const creds = readCredentials();\n if (creds?.apiKey) return creds.apiKey;\n\n // 3. Config file (set during setup)\n const config = readConfig();\n if (config?.apiKey) return config.apiKey;\n\n // 4. Shared default key (fallback)\n return DEFAULT_API_KEY;\n}\n","import { CortexHttpClient } from \"../proxy/http-client.js\";\n\n/** Metadata for a single MCP tool */\nexport interface ToolInfo {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n}\n\n/** Base error class for all Cortex SDK errors */\nexport class CortexError extends Error {\n constructor(\n message: string,\n public readonly mcpName?: string\n ) {\n super(message);\n this.name = \"CortexError\";\n }\n}\n\n/**\n * Thrown when a tool executes but returns isError: true\n * (e.g., bad SOQL query, missing OAuth connection, invalid record ID).\n */\nexport class CortexToolError extends CortexError {\n constructor(\n message: string,\n public override readonly mcpName: string,\n public readonly toolName: string\n ) {\n super(message, mcpName);\n this.name = \"CortexToolError\";\n }\n}\n\n/**\n * Thrown on transport/auth failures — the tool never executed\n * (e.g., invalid API key, network error, server down).\n */\nexport class CortexNetworkError extends CortexError {\n constructor(\n message: string,\n public readonly code?: number,\n mcpName?: string\n ) {\n super(message, mcpName);\n this.name = \"CortexNetworkError\";\n }\n}\n\n/**\n * Provides a call interface for a single Cortex MCP.\n * Lazily initializes the underlying HTTP session on first use.\n */\nexport class MCPNamespace {\n private readonly client: CortexHttpClient;\n private initPromise: Promise<void> | null = null;\n\n constructor(\n public readonly mcpName: string,\n serverUrl: string,\n apiKey: string\n ) {\n this.client = new CortexHttpClient(serverUrl, apiKey, mcpName);\n }\n\n private async ensureInitialized(): Promise<void> {\n if (this.initPromise !== null) return this.initPromise;\n this.initPromise = this.doInit();\n return this.initPromise;\n }\n\n private async doInit(): Promise<void> {\n const response = await this.client.initialize();\n if (response.error) {\n this.initPromise = null;\n throw new CortexNetworkError(\n response.error.message,\n response.error.code,\n this.mcpName\n );\n }\n }\n\n /**\n * Call a tool on this MCP. Returns the parsed result.\n *\n * @example\n * const ns = new MCPNamespace('salesforce', serverUrl, apiKey);\n * const result = await ns.call('run_soql_query', {\n * query: 'SELECT Id, Name FROM Account LIMIT 10'\n * });\n */\n async call(\n toolName: string,\n args: Record<string, unknown> = {}\n ): Promise<unknown> {\n await this.ensureInitialized();\n const response = await this.client.callTool(toolName, args);\n\n if (response.error) {\n throw new CortexNetworkError(\n response.error.message,\n response.error.code,\n this.mcpName\n );\n }\n\n const result = response.result as {\n content: Array<{ type: string; text: string }>;\n isError?: boolean;\n };\n\n const text = result?.content?.[0]?.text ?? \"\";\n\n if (result?.isError) {\n throw new CortexToolError(text, this.mcpName, toolName);\n }\n\n return parseText(text);\n }\n\n /** List all tools available on this MCP. */\n async listTools(): Promise<ToolInfo[]> {\n await this.ensureInitialized();\n const response = await this.client.listTools();\n\n if (response.error) {\n throw new CortexNetworkError(\n response.error.message,\n response.error.code,\n this.mcpName\n );\n }\n\n const result = response.result as { tools: ToolInfo[] };\n return result?.tools ?? [];\n }\n\n /** Release the session. The next call() will re-initialize. */\n close(): void {\n this.initPromise = null;\n }\n}\n\n/** Parse text content — attempt JSON, fall back to raw string. */\nfunction parseText(text: string): unknown {\n if (!text) return text;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n","import { getEffectiveApiKey } from \"../auth/credentials.js\";\nimport { DEFAULT_SERVER_URL } from \"../constants.js\";\nimport { MCPNamespace } from \"./mcp-namespace.js\";\n\nexport interface CortexClientOptions {\n /** API key. Defaults to auto-resolved key (env > credentials > config > shared). */\n apiKey?: string;\n /** Cortex server URL. Defaults to https://cortex-bice.vercel.app */\n serverUrl?: string;\n}\n\n/**\n * High-level SDK client for calling Cortex MCP tools from custom apps.\n * Auto-resolves credentials and lazily initializes per-MCP sessions.\n *\n * @example\n * ```typescript\n * import { CortexClient } from '@danainnovations/cortex-mcp';\n *\n * const cortex = new CortexClient();\n *\n * // Salesforce — no Connected App needed\n * const accounts = await cortex.salesforce.call('run_soql_query', {\n * query: 'SELECT Id, Name FROM Account LIMIT 10'\n * });\n *\n * // Microsoft 365\n * const emails = await cortex.m365.call('list_emails', { count: 5 });\n *\n * // GitHub\n * const repos = await cortex.github.call('list_repositories', { per_page: 5 });\n *\n * // Cleanup when done\n * cortex.close();\n * ```\n */\nexport class CortexClient {\n private readonly apiKey: string;\n private readonly serverUrl: string;\n private readonly namespaces = new Map<string, MCPNamespace>();\n\n constructor(options: CortexClientOptions = {}) {\n this.apiKey = options.apiKey ?? getEffectiveApiKey();\n this.serverUrl = options.serverUrl ?? DEFAULT_SERVER_URL;\n }\n\n get asana(): MCPNamespace {\n return this.getNamespace(\"asana\");\n }\n get github(): MCPNamespace {\n return this.getNamespace(\"github\");\n }\n get mailchimp(): MCPNamespace {\n return this.getNamespace(\"mailchimp\");\n }\n get vercel(): MCPNamespace {\n return this.getNamespace(\"vercel\");\n }\n get supabase(): MCPNamespace {\n return this.getNamespace(\"supabase\");\n }\n get m365(): MCPNamespace {\n return this.getNamespace(\"m365\");\n }\n get salesforce(): MCPNamespace {\n return this.getNamespace(\"salesforce\");\n }\n get monday(): MCPNamespace {\n return this.getNamespace(\"monday\");\n }\n get slack(): MCPNamespace {\n return this.getNamespace(\"slack\");\n }\n get powerbi(): MCPNamespace {\n return this.getNamespace(\"powerbi\");\n }\n get bestbuy(): MCPNamespace {\n return this.getNamespace(\"bestbuy\");\n }\n get databricks(): MCPNamespace {\n return this.getNamespace(\"databricks\");\n }\n\n /**\n * Call any MCP tool when the MCP name is determined at runtime.\n *\n * @example\n * const result = await cortex.call('github', 'list_repositories', { per_page: 5 });\n */\n async call(\n mcpName: string,\n toolName: string,\n args: Record<string, unknown> = {}\n ): Promise<unknown> {\n return this.getNamespace(mcpName).call(toolName, args);\n }\n\n /**\n * Release all sessions. Safe to call multiple times.\n * The next call after close() will re-initialize automatically.\n */\n close(): void {\n for (const ns of this.namespaces.values()) {\n ns.close();\n }\n this.namespaces.clear();\n }\n\n private getNamespace(name: string): MCPNamespace {\n let ns = this.namespaces.get(name);\n if (!ns) {\n ns = new MCPNamespace(name, this.serverUrl, this.apiKey);\n this.namespaces.set(name, ns);\n }\n return ns;\n }\n}\n"],"mappings":"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","names":["readFileSync","statSync","statSync","fileBuffer","readFileSync","err","existsSync","mkdirSync","readFileSync","writeFileSync","join","join","join","existsSync","readFileSync","mkdirSync","writeFileSync","existsSync","readFileSync","writeFileSync","dirname","mkdirSync","homedir","join","dirname","existsSync","homedir","join","mkdirSync","readFileSync","writeFileSync","existsSync","mkdirSync","readFileSync","unlinkSync","writeFileSync","join","join","existsSync","readFileSync"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/proxy/http-client.ts","../src/proxy/stdio-server.ts","../src/proxy/local-filesystem.ts","../src/config/storage.ts","../src/utils/platform.ts","../src/config/clients.ts","../src/utils/validation.ts","../src/auth/credentials.ts","../src/client/mcp-namespace.ts","../src/client/cortex-client.ts"],"sourcesContent":["/** Default Cortex server URL */\nexport const DEFAULT_SERVER_URL = \"https://cortex-bice.vercel.app\";\n\n/** MCP protocol version supported by Cortex (Streamable HTTP) */\nexport const PROTOCOL_VERSION = \"2025-03-26\";\n\n/** Available MCPs with their metadata */\nexport const AVAILABLE_MCPS = [\n {\n name: \"m365\",\n displayName: \"Microsoft 365\",\n description: \"Email, calendar, OneDrive, Teams, meetings, contacts, tasks, notes (33 tools)\",\n serverName: \"cortex-m365\",\n authMode: \"personal\" as const,\n },\n {\n name: \"asana\",\n displayName: \"Asana\",\n description: \"Projects, tasks, teams, workspaces (17 tools)\",\n serverName: \"cortex-asana\",\n authMode: \"personal\" as const,\n },\n {\n name: \"github\",\n displayName: \"GitHub\",\n description: \"Repos, PRs, issues, branches, code review (30 tools)\",\n serverName: \"cortex-github\",\n authMode: \"company\" as const,\n },\n {\n name: \"vercel\",\n displayName: \"Vercel\",\n description: \"Deployments, projects, env vars (15 tools)\",\n serverName: \"cortex-vercel\",\n authMode: \"company\" as const,\n },\n {\n name: \"supabase\",\n displayName: \"Supabase\",\n description: \"Database, migrations, edge functions (20+ tools)\",\n serverName: \"cortex-supabase\",\n authMode: \"company\" as const,\n },\n {\n name: \"bestbuy\",\n displayName: \"Best Buy\",\n description: \"Product search, pricing, reviews, store locations (7 tools)\",\n serverName: \"cortex-bestbuy\",\n authMode: \"company\" as const,\n },\n {\n name: \"mailchimp\",\n displayName: \"Mailchimp\",\n description: \"Audiences, contacts, campaigns, templates, analytics (28 tools)\",\n serverName: \"cortex-mailchimp\",\n authMode: \"personal\" as const,\n },\n {\n name: \"salesforce\",\n displayName: \"Salesforce\",\n description: \"CRM queries, records, reports, and org data (14 tools)\",\n serverName: \"cortex-salesforce\",\n authMode: \"personal\" as const,\n },\n {\n name: \"monday\",\n displayName: \"Monday.com\",\n description: \"Boards, items, groups, updates, workspaces (18 tools)\",\n serverName: \"cortex-monday\",\n authMode: \"personal\" as const,\n installUrl: \"https://auth.monday.com/oauth2/authorize?client_id=c8d2c70bd792a4c36c6f023c0b707517&response_type=install\",\n },\n {\n name: \"slack\",\n displayName: \"Slack\",\n description: \"Messaging, channels, search, reactions, bookmarks (22 tools)\",\n serverName: \"cortex-slack\",\n authMode: \"personal\" as const,\n },\n {\n name: \"powerbi\",\n displayName: \"Power BI\",\n description: \"Workspaces, datasets, push data, DAX queries, reports, dashboards (14 tools)\",\n serverName: \"cortex-powerbi\",\n authMode: \"personal\" as const,\n },\n {\n name: \"databricks\",\n displayName: \"Databricks\",\n description: \"Unity Catalog discovery, SQL queries, data dictionary, jobs (18 tools)\",\n serverName: \"cortex-databricks\",\n authMode: \"company\" as const,\n },\n {\n name: \"concur\",\n displayName: \"SAP Concur\",\n description: \"Expense reports, entries, receipts, approvals (16 tools)\",\n serverName: \"cortex-concur\",\n authMode: \"personal\" as const,\n },\n] as const;\n\n/** All available MCP names */\nexport const MCP_NAMES: string[] = AVAILABLE_MCPS.map((m) => m.name);\n\n/** Default MCPs enabled on fresh setup */\nexport const DEFAULT_MCPS: string[] = [...MCP_NAMES];\n\n/** Shared API key embedded in the package (no user prompt needed) */\nexport const DEFAULT_API_KEY =\n \"ctx_07d37a81_9f7be06af38d04753090a4034f907a65ec06cd675ed26f65653898388e2d1709\";\n\n/** Config directory name */\nexport const CONFIG_DIR_NAME = \".cortex-mcp\";\n\n/** Config file name */\nexport const CONFIG_FILE_NAME = \"config.json\";\n\n/** Credentials file name (stores personal API key from login) */\nexport const CREDENTIALS_FILE_NAME = \"credentials.json\";\n","import { PROTOCOL_VERSION } from \"../constants.js\";\n\n/** JSON-RPC 2.0 request */\ninterface JsonRpcRequest {\n jsonrpc: \"2.0\";\n method: string;\n params?: Record<string, unknown>;\n id: string | number;\n}\n\n/** JSON-RPC 2.0 response */\ninterface JsonRpcResponse {\n jsonrpc: \"2.0\";\n result?: unknown;\n error?: { code: number; message: string };\n id: string | number | null;\n}\n\n/**\n * HTTP client that forwards JSON-RPC 2.0 requests to the Cortex server.\n */\nexport class CortexHttpClient {\n private sessionId: string | null = null;\n private requestId = 0;\n\n constructor(\n private serverUrl: string,\n private apiKey: string,\n private endpoint: string = \"cortex\"\n ) {}\n\n /** Send an initialize request to establish a session */\n async initialize(): Promise<JsonRpcResponse> {\n const response = await this.sendRequest(\"initialize\", {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: {},\n clientInfo: { name: \"cortex-mcp-proxy\", version: \"1.0.0\" },\n });\n\n // Send initialized notification (no id = notification, no response expected)\n await this.sendNotification(\"notifications/initialized\", {});\n\n return response;\n }\n\n /** List available tools */\n async listTools(): Promise<JsonRpcResponse> {\n return this.sendRequest(\"tools/list\", {});\n }\n\n /** Call a tool */\n async callTool(\n name: string,\n args: Record<string, unknown>\n ): Promise<JsonRpcResponse> {\n return this.sendRequest(\"tools/call\", { name, arguments: args });\n }\n\n /** Send a JSON-RPC request and return the response */\n private async sendRequest(\n method: string,\n params: Record<string, unknown>\n ): Promise<JsonRpcResponse> {\n const id = String(++this.requestId);\n const body: JsonRpcRequest = { jsonrpc: \"2.0\", method, params, id };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": this.apiKey,\n \"mcp-protocol-version\": PROTOCOL_VERSION,\n \"x-cortex-client\": \"cortex-mcp-stdio\",\n };\n\n if (this.sessionId) {\n headers[\"mcp-session-id\"] = this.sessionId;\n }\n\n const url = `${this.serverUrl}/mcp/${this.endpoint}`;\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(60_000),\n });\n\n // Capture session ID from initialize\n const newSessionId = response.headers.get(\"mcp-session-id\");\n if (newSessionId) {\n this.sessionId = newSessionId;\n }\n\n if (!response.ok) {\n const text = await response.text();\n return {\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: this.humanReadableError(response.status, text),\n },\n id,\n };\n }\n\n return (await response.json()) as JsonRpcResponse;\n }\n\n /** Send a JSON-RPC notification (no response expected) */\n private async sendNotification(\n method: string,\n params: Record<string, unknown>\n ): Promise<void> {\n const body = { jsonrpc: \"2.0\", method, params };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": this.apiKey,\n \"mcp-protocol-version\": PROTOCOL_VERSION,\n \"x-cortex-client\": \"cortex-mcp-stdio\",\n };\n\n if (this.sessionId) {\n headers[\"mcp-session-id\"] = this.sessionId;\n }\n\n const url = `${this.serverUrl}/mcp/${this.endpoint}`;\n\n try {\n await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(10_000),\n });\n } catch {\n // Notifications are fire-and-forget\n }\n }\n\n /** Convert HTTP status codes to user-friendly messages */\n private humanReadableError(status: number, body: string): string {\n switch (status) {\n case 401:\n return \"Invalid API key. Check your key at https://aidentity.app/settings/keys\";\n case 403:\n return \"API key lacks MCP permissions. Create a new key with MCP access.\";\n case 404:\n return \"MCP endpoint not found. The server may be misconfigured.\";\n case 503:\n return \"MCP protocol is disabled on the server.\";\n default:\n return `Server error (${status}): ${body.slice(0, 200)}`;\n }\n }\n}\n","import { readFileSync, statSync } from \"node:fs\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { CortexHttpClient } from \"./http-client.js\";\nimport { FILESYSTEM_TOOLS, handleLocalFilesystemTool } from \"./local-filesystem.js\";\n\ninterface StdioServerOptions {\n serverUrl: string;\n apiKey: string;\n /** Use \"cortex\" for composite endpoint, or a specific MCP name */\n endpoint?: string;\n}\n\n/** Tools that support local file_path → upload interception */\nconst UPLOAD_TOOLS = new Set([\"upload_file\", \"upload_file_to_sharepoint\"]);\n\n/** Max file size for inline base64 upload via JSON-RPC (3MB).\n * 3MB raw → 4MB base64 → safely within Vercel's ~4.5MB body limit. */\nconst INLINE_UPLOAD_MAX = 3 * 1024 * 1024;\n\n/**\n * Override upload tool schemas so the LLM only sees `file_path` (not `content`).\n * This forces the LLM to pass a local file path, which the proxy handles locally\n * — no base64 encoding by the LLM, no truncation, no corruption.\n */\nfunction overrideUploadToolSchema(\n tool: Record<string, unknown>\n): Record<string, unknown> {\n const name = tool.name as string;\n const baseName = name.includes(\"__\") ? name.split(\"__\").pop()! : name;\n\n if (baseName === \"upload_file\") {\n return {\n ...tool,\n description:\n \"Upload a local file to the user's OneDrive. \" +\n \"Provide the absolute local file path — the file is read \" +\n \"and uploaded automatically. Works with any file size.\",\n inputSchema: {\n type: \"object\",\n required: [\"file_path\", \"path\"],\n properties: {\n file_path: {\n type: \"string\",\n description:\n \"Absolute path to the local file to upload \" +\n \"(e.g. '/Users/name/Documents/report.xlsx')\",\n },\n path: {\n type: \"string\",\n description:\n \"Destination path in OneDrive \" +\n \"(e.g. 'Documents/report.xlsx')\",\n },\n content_type: {\n type: \"string\",\n description: \"MIME type. Defaults to 'application/octet-stream'\",\n },\n },\n },\n };\n }\n\n if (baseName === \"upload_file_to_sharepoint\") {\n return {\n ...tool,\n description:\n \"Upload a local file to a SharePoint document library. \" +\n \"Provide the absolute local file path — the file is read \" +\n \"and uploaded automatically.\",\n inputSchema: {\n type: \"object\",\n required: [\"file_path\", \"site_id\", \"path\"],\n properties: {\n file_path: {\n type: \"string\",\n description: \"Absolute path to the local file to upload\",\n },\n site_id: {\n type: \"string\",\n description: \"SharePoint site ID\",\n },\n path: {\n type: \"string\",\n description:\n \"Destination path in the site drive \" +\n \"(e.g. 'Shared Documents/report.pdf')\",\n },\n content_type: {\n type: \"string\",\n description: \"MIME type. Defaults to 'application/octet-stream'\",\n },\n },\n },\n };\n }\n\n return tool;\n}\n\n/**\n * Handle a file upload tool call locally by reading the file from disk.\n *\n * - Small files (≤3MB): base64-encode and forward as `content` param\n * - Large files (>3MB): get an upload session URL from backend, then\n * relay 2.5MB chunks through the backend's `upload_file_chunk` tool\n * (the backend has unrestricted internet; the proxy may be sandboxed)\n */\nasync function handleLocalFileUpload(\n cortex: CortexHttpClient,\n toolName: string,\n args: Record<string, unknown>\n): Promise<{ content: Array<{ type: string; text: string }>; isError: boolean }> {\n const filePath = args.file_path as string;\n\n // Validate file exists\n let fileSize: number;\n try {\n fileSize = statSync(filePath as string).size;\n } catch {\n return {\n content: [{ type: \"text\", text: JSON.stringify({\n success: false,\n error: `File not found: ${filePath}`,\n }) }],\n isError: true,\n };\n }\n\n if (fileSize <= INLINE_UPLOAD_MAX) {\n // Small file: read, base64-encode, and forward via normal JSON-RPC\n const fileBuffer = readFileSync(filePath);\n const base64Content = fileBuffer.toString(\"base64\");\n\n const forwardArgs: Record<string, unknown> = { ...args, content: base64Content };\n delete forwardArgs.file_path;\n\n console.error(\n `[cortex-mcp] ${toolName}: reading local file (${(fileSize / 1024).toFixed(1)}KB), forwarding as base64`\n );\n\n const response = await cortex.callTool(toolName, forwardArgs);\n\n if (response.error) {\n return {\n content: [{ type: \"text\", text: response.error.message }],\n isError: true,\n };\n }\n\n return response.result as {\n content: Array<{ type: string; text: string }>;\n isError: boolean;\n };\n }\n\n // Large file: use upload session to upload directly to Microsoft Graph\n console.error(\n `[cortex-mcp] ${toolName}: large file (${(fileSize / 1024 / 1024).toFixed(1)}MB), using upload session`\n );\n\n // Step 1: Get pre-authenticated upload URL from backend\n // Preserve composite prefix (e.g. \"m365__\") so the backend routes correctly\n const prefix = toolName.includes(\"__\") ? toolName.split(\"__\")[0] + \"__\" : \"\";\n const sessionResponse = await cortex.callTool(`${prefix}create_upload_session`, {\n path: args.path,\n });\n\n if (sessionResponse.error) {\n return {\n content: [{ type: \"text\", text: sessionResponse.error.message }],\n isError: true,\n };\n }\n\n const sessionResult = sessionResponse.result as {\n content: Array<{ type: string; text: string }>;\n };\n\n let sessionData: { uploadUrl?: string };\n try {\n sessionData = JSON.parse(sessionResult.content[0].text);\n } catch {\n return {\n content: [{ type: \"text\", text: JSON.stringify({\n success: false,\n error: \"Failed to parse upload session response from backend\",\n }) }],\n isError: true,\n };\n }\n\n const uploadUrl = sessionData.uploadUrl;\n if (!uploadUrl) {\n return {\n content: [{ type: \"text\", text: JSON.stringify({\n success: false,\n error: \"Backend did not return an uploadUrl\",\n }) }],\n isError: true,\n };\n }\n\n // Step 2: Upload file in chunks through the Cortex backend.\n // We relay via the backend (which has unrestricted internet) instead of\n // uploading directly to Graph — the proxy may be in a sandboxed VM that\n // blocks outbound connections to SharePoint/Microsoft Graph.\n const fileBuffer = readFileSync(filePath);\n const chunkSize = 2.5 * 1024 * 1024; // 2.5MB → ~3.33MB base64 → within Vercel 4.5MB limit\n const total = fileBuffer.length;\n let driveItem: Record<string, unknown> = {};\n\n for (let start = 0; start < total; start += chunkSize) {\n const end = Math.min(start + chunkSize, total);\n const chunk = fileBuffer.subarray(start, end);\n const chunkBase64 = Buffer.from(chunk).toString(\"base64\");\n\n console.error(\n `[cortex-mcp] Uploading chunk ${start}-${end - 1}/${total} via backend relay`\n );\n\n const chunkResponse = await cortex.callTool(`${prefix}upload_file_chunk`, {\n upload_url: uploadUrl,\n chunk: chunkBase64,\n range_start: start,\n range_end: end - 1,\n total_size: total,\n });\n\n if (chunkResponse.error) {\n return {\n content: [{ type: \"text\", text: chunkResponse.error.message }],\n isError: true,\n };\n }\n\n const chunkResult = chunkResponse.result as {\n content: Array<{ type: string; text: string }>;\n };\n\n let chunkData: Record<string, unknown>;\n try {\n chunkData = JSON.parse(chunkResult.content[0].text) as Record<string, unknown>;\n } catch {\n return {\n content: [{ type: \"text\", text: JSON.stringify({\n success: false,\n error: \"Failed to parse chunk upload response from backend\",\n }) }],\n isError: true,\n };\n }\n\n if (!chunkData.success) {\n return {\n content: [{ type: \"text\", text: JSON.stringify(chunkData) }],\n isError: true,\n };\n }\n\n // Final chunk (200/201) contains the DriveItem\n if (chunkData.status === 200 || chunkData.status === 201) {\n driveItem = (chunkData.data as Record<string, unknown>) ?? {};\n }\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify({\n success: true,\n file: driveItem,\n message: `Uploaded '${args.path}' (${(fileSize / 1024 / 1024).toFixed(1)}MB) via upload session`,\n }) }],\n isError: false,\n };\n}\n\n/**\n * Start a stdio MCP server that proxies all requests to the hosted Cortex server.\n * This is used by clients that only support stdio transport (e.g., OpenClaw).\n */\nexport async function startStdioServer(\n options: StdioServerOptions\n): Promise<void> {\n const { serverUrl, apiKey, endpoint = \"cortex\" } = options;\n\n const cortex = new CortexHttpClient(serverUrl, apiKey, endpoint);\n\n const server = new Server(\n { name: \"cortex-mcp\", version: \"1.0.0\" },\n { capabilities: { tools: { listChanged: false } } }\n );\n\n // Lazy initialization — runs on first request, not at startup\n let initialized = false;\n\n async function ensureInitialized(): Promise<void> {\n if (initialized) return;\n try {\n console.error(\"[cortex-mcp] Initializing backend session...\");\n await cortex.initialize();\n console.error(\"[cortex-mcp] Backend session established.\");\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`[cortex-mcp] Backend initialization failed: ${msg}`);\n // Continue anyway — tools/list and tools/call may still work without a session\n }\n initialized = true;\n }\n\n // Forward tools/list to Cortex\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n await ensureInitialized();\n const response = await cortex.listTools();\n\n if (response.error) {\n throw new Error(response.error.message);\n }\n\n const result = response.result as { tools: Record<string, unknown>[] };\n const tools = (result.tools || []).map(overrideUploadToolSchema);\n return { tools };\n });\n\n // Forward tools/call to Cortex (with local file upload interception)\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n await ensureInitialized();\n const { name, arguments: args } = request.params;\n const typedArgs = (args ?? {}) as Record<string, unknown>;\n\n // Intercept upload tools with file_path — handle locally\n // Composite endpoint prefixes tool names with \"{mcp}__\", so match on suffix\n const baseName = name.includes(\"__\") ? name.split(\"__\").pop()! : name;\n if (UPLOAD_TOOLS.has(baseName) && typedArgs.file_path) {\n return handleLocalFileUpload(cortex, name, typedArgs);\n }\n\n // Intercept filesystem tools — execute locally instead of on remote server\n if (FILESYSTEM_TOOLS.has(baseName)) {\n return handleLocalFilesystemTool(name, baseName, typedArgs);\n }\n\n const response = await cortex.callTool(name, typedArgs);\n\n if (response.error) {\n return {\n content: [{ type: \"text\" as const, text: response.error.message }],\n isError: true,\n };\n }\n\n const result = response.result as {\n content: Array<{ type: string; text: string }>;\n isError: boolean;\n };\n\n return result;\n });\n\n // Connect to stdio transport immediately — do NOT block on backend init\n console.error(\"[cortex-mcp] Starting stdio server...\");\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error(\"[cortex-mcp] Stdio server connected.\");\n}\n","/**\n * Local filesystem tool handlers for cortex-mcp.\n *\n * Intercepts filesystem MCP tool calls and executes them locally on the\n * user's machine using Node.js fs APIs, instead of forwarding to the\n * remote Cortex server (which cannot access local files).\n *\n * Response shapes match the server-side FileSystem MCP exactly so that\n * consumers see identical results regardless of execution location.\n */\n\nimport {\n copyFileSync,\n cpSync,\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n rmSync,\n statSync,\n unlinkSync,\n writeFileSync,\n appendFileSync,\n renameSync,\n type Dirent,\n} from \"node:fs\";\nimport { basename, dirname, extname, join, relative, resolve } from \"node:path\";\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\n/** Tools handled locally instead of proxied to the server. */\nexport const FILESYSTEM_TOOLS = new Set([\n \"read_file\",\n \"read_file_lines\",\n \"write_file\",\n \"append_file\",\n \"create_directory\",\n \"delete\",\n \"move\",\n \"copy\",\n \"list_directory\",\n \"exists\",\n \"get_file_info\",\n \"search_files\",\n \"find_in_files\",\n \"get_tree\",\n]);\n\n/** Maximum bytes to read in a single read_file call (50 MB). */\nconst MAX_READ_SIZE = 50 * 1024 * 1024;\n\n/** Bytes to sample for binary detection. */\nconst BINARY_CHECK_SIZE = 8192;\n\n/** Binary file magic byte signatures. */\nconst BINARY_SIGNATURES: Buffer[] = [\n Buffer.from([0x89, 0x50, 0x4e, 0x47]), // PNG\n Buffer.from([0xff, 0xd8, 0xff]), // JPEG\n Buffer.from(\"GIF8\"), // GIF\n Buffer.from([0x50, 0x4b, 0x03, 0x04]), // ZIP / DOCX / XLSX\n Buffer.from(\"%PDF\"), // PDF\n Buffer.from([0x7f, 0x45, 0x4c, 0x46]), // ELF\n Buffer.from([0xfe, 0xed, 0xfa]), // Mach-O\n Buffer.from([0xcf, 0xfa, 0xed, 0xfe]), // Mach-O (reversed)\n Buffer.from(\"MZ\"), // Windows executable\n];\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\ntype ToolResult = {\n content: Array<{ type: string; text: string }>;\n isError: boolean;\n};\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\n/** Resolve a path — absolute paths as-is, relative against cwd. */\nfunction resolvePath(p: string): string {\n return resolve(p);\n}\n\n/** Detect whether a file is binary by checking magic bytes and null bytes. */\nfunction isBinaryFile(filePath: string): boolean {\n try {\n const fd = readFileSync(filePath, { flag: \"r\" });\n const chunk = fd.subarray(0, BINARY_CHECK_SIZE);\n if (chunk.length === 0) return false;\n\n for (const sig of BINARY_SIGNATURES) {\n if (chunk.length >= sig.length && chunk.subarray(0, sig.length).equals(sig)) {\n return true;\n }\n }\n return chunk.includes(0);\n } catch {\n return false;\n }\n}\n\n/** Convert a simple glob pattern to a RegExp (supports *, ?, [...]). */\nfunction globToRegex(pattern: string): RegExp {\n let re = \"^\";\n for (let i = 0; i < pattern.length; i++) {\n const c = pattern[i];\n if (c === \"*\") {\n re += \".*\";\n } else if (c === \"?\") {\n re += \".\";\n } else if (c === \"[\") {\n const close = pattern.indexOf(\"]\", i + 1);\n if (close !== -1) {\n re += \"[\" + pattern.slice(i + 1, close) + \"]\";\n i = close;\n } else {\n re += \"\\\\[\";\n }\n } else if (\".+^${}()|\\\\\".includes(c)) {\n re += \"\\\\\" + c;\n } else {\n re += c;\n }\n }\n re += \"$\";\n return new RegExp(re);\n}\n\n/** Get file type string from stat/dirent. */\nfunction fileType(isDir: boolean, isSymlink: boolean): string {\n if (isSymlink) return \"symlink\";\n if (isDir) return \"directory\";\n return \"file\";\n}\n\n/** Count files and total bytes in a directory tree. */\nfunction countDirectoryContents(dirPath: string): { files: number; bytes: number } {\n let files = 0;\n let bytes = 0;\n try {\n const entries = readdirSync(dirPath, { withFileTypes: true });\n for (const entry of entries) {\n const full = join(dirPath, entry.name);\n if (entry.isDirectory()) {\n const sub = countDirectoryContents(full);\n files += sub.files;\n bytes += sub.bytes;\n } else {\n files += 1;\n try {\n bytes += statSync(full).size;\n } catch { /* skip */ }\n }\n }\n } catch { /* skip */ }\n return { files, bytes };\n}\n\n/** Build success result. */\nfunction ok(data: unknown): ToolResult {\n return {\n content: [{ type: \"text\", text: JSON.stringify(data) }],\n isError: false,\n };\n}\n\n/** Build error result. */\nfunction err(message: string): ToolResult {\n return {\n content: [{ type: \"text\", text: JSON.stringify({ success: false, error: message }) }],\n isError: true,\n };\n}\n\n// ─── Tool Handlers ───────────────────────────────────────────────────────────\n\nfunction handleReadFile(args: Record<string, unknown>): ToolResult {\n const filePath = resolvePath(args.path as string);\n const encoding = (args.encoding as string) || \"utf-8\";\n\n const stat = statSync(filePath);\n if (!stat.isFile()) throw new Error(\"Not a file.\");\n if (stat.size > MAX_READ_SIZE) {\n throw new Error(`File size (${stat.size} bytes) exceeds maximum allowed size (${MAX_READ_SIZE} bytes).`);\n }\n\n if (isBinaryFile(filePath)) {\n const raw = readFileSync(filePath);\n return ok({\n content: raw.toString(\"base64\"),\n is_binary: true,\n size: stat.size,\n encoding: \"base64\",\n path: filePath,\n });\n }\n\n const text = readFileSync(filePath, encoding as BufferEncoding);\n return ok({\n content: text,\n is_binary: false,\n size: stat.size,\n encoding,\n path: filePath,\n });\n}\n\nfunction handleReadFileLines(args: Record<string, unknown>): ToolResult {\n const filePath = resolvePath(args.path as string);\n const encoding = (args.encoding as string) || \"utf-8\";\n const startLine = (args.start_line as number) || 1;\n const endLine = args.end_line as number | undefined;\n\n const stat = statSync(filePath);\n if (!stat.isFile()) throw new Error(\"Not a file.\");\n if (stat.size > MAX_READ_SIZE) {\n throw new Error(`File size (${stat.size} bytes) exceeds maximum allowed size.`);\n }\n\n if (startLine < 1) throw new Error(\"start_line must be >= 1.\");\n if (endLine !== undefined && endLine < startLine) throw new Error(\"end_line must be >= start_line.\");\n\n const text = readFileSync(filePath, encoding as BufferEncoding);\n const allLines = text.split(/\\n/);\n const totalLines = allLines.length;\n\n const startIdx = startLine - 1;\n const endIdx = endLine !== undefined ? endLine : totalLines;\n const selected = allLines.slice(startIdx, endIdx);\n const actualEnd = Math.min(endIdx, totalLines);\n\n return ok({\n content: selected.join(\"\\n\"),\n start_line: startLine,\n end_line: actualEnd,\n total_lines: totalLines,\n size: stat.size,\n path: filePath,\n });\n}\n\nfunction handleWriteFile(args: Record<string, unknown>): ToolResult {\n const filePath = resolvePath(args.path as string);\n const content = args.content as string;\n const encoding = (args.encoding as string) || \"utf-8\";\n const isBinary = (args.is_binary as boolean) || false;\n const overwrite = args.overwrite !== false; // default true\n const createParents = (args.create_parents as boolean) || false;\n\n const created = !existsSync(filePath);\n\n if (!overwrite && !created) {\n throw new Error(\"File already exists.\");\n }\n\n if (createParents) {\n mkdirSync(dirname(filePath), { recursive: true });\n }\n\n let bytesWritten: number;\n let usedEncoding: string;\n\n if (isBinary) {\n const raw = Buffer.from(content, \"base64\");\n writeFileSync(filePath, raw);\n bytesWritten = raw.length;\n usedEncoding = \"base64\";\n } else {\n const encoded = Buffer.from(content, encoding as BufferEncoding);\n writeFileSync(filePath, content, encoding as BufferEncoding);\n bytesWritten = encoded.length;\n usedEncoding = encoding;\n }\n\n return ok({\n path: filePath,\n bytes_written: bytesWritten,\n created,\n encoding: usedEncoding,\n });\n}\n\nfunction handleAppendFile(args: Record<string, unknown>): ToolResult {\n const filePath = resolvePath(args.path as string);\n const content = args.content as string;\n const encoding = (args.encoding as string) || \"utf-8\";\n\n if (!existsSync(filePath)) throw new Error(\"File not found.\");\n\n const encoded = Buffer.from(content, encoding as BufferEncoding);\n appendFileSync(filePath, content, encoding as BufferEncoding);\n const newSize = statSync(filePath).size;\n\n return ok({\n path: filePath,\n bytes_written: encoded.length,\n new_size: newSize,\n });\n}\n\nfunction handleCreateDirectory(args: Record<string, unknown>): ToolResult {\n const dirPath = resolvePath(args.path as string);\n const parents = args.parents !== false; // default true\n\n if (existsSync(dirPath)) {\n return ok({ path: dirPath, created: false });\n }\n\n if (parents) {\n mkdirSync(dirPath, { recursive: true });\n } else {\n mkdirSync(dirPath);\n }\n\n return ok({ path: dirPath, created: true });\n}\n\nfunction handleDelete(args: Record<string, unknown>): ToolResult {\n const targetPath = resolvePath(args.path as string);\n const recursive = (args.recursive as boolean) || false;\n\n if (!existsSync(targetPath)) throw new Error(\"Path not found.\");\n\n const stat = statSync(targetPath, { throwIfNoEntry: false });\n if (!stat) throw new Error(\"Path not found.\");\n\n if (stat.isDirectory()) {\n const { files: filesDeleted, bytes: bytesFreed } = countDirectoryContents(targetPath);\n if (recursive) {\n rmSync(targetPath, { recursive: true });\n } else {\n // rmSync without recursive only removes empty dirs\n rmSync(targetPath);\n }\n return ok({\n path: targetPath,\n type: \"directory\",\n files_deleted: recursive ? filesDeleted : 0,\n bytes_freed: recursive ? bytesFreed : 0,\n });\n }\n\n const size = stat.size;\n unlinkSync(targetPath);\n return ok({\n path: targetPath,\n type: \"file\",\n files_deleted: 1,\n bytes_freed: size,\n });\n}\n\nfunction handleMove(args: Record<string, unknown>): ToolResult {\n const source = resolvePath(args.source as string);\n const destination = resolvePath(args.destination as string);\n const overwrite = (args.overwrite as boolean) || false;\n\n if (!existsSync(source)) throw new Error(\"Source path not found.\");\n if (existsSync(destination) && !overwrite) throw new Error(\"Destination already exists.\");\n\n const stat = statSync(source);\n const type = stat.isDirectory() ? \"directory\" : \"file\";\n const bytesMoved = stat.isDirectory()\n ? countDirectoryContents(source).bytes\n : stat.size;\n\n try {\n renameSync(source, destination);\n } catch (e: unknown) {\n // EXDEV: cross-device rename — fallback to copy + delete\n if ((e as NodeJS.ErrnoException).code === \"EXDEV\") {\n if (stat.isDirectory()) {\n cpSync(source, destination, { recursive: true });\n rmSync(source, { recursive: true });\n } else {\n copyFileSync(source, destination);\n unlinkSync(source);\n }\n } else {\n throw e;\n }\n }\n\n return ok({\n source,\n destination,\n type,\n bytes_moved: bytesMoved,\n });\n}\n\nfunction handleCopy(args: Record<string, unknown>): ToolResult {\n const source = resolvePath(args.source as string);\n const destination = resolvePath(args.destination as string);\n const overwrite = (args.overwrite as boolean) || false;\n\n if (!existsSync(source)) throw new Error(\"Source path not found.\");\n if (existsSync(destination) && !overwrite) throw new Error(\"Destination already exists.\");\n\n const stat = statSync(source);\n\n if (stat.isDirectory()) {\n if (existsSync(destination) && overwrite) {\n rmSync(destination, { recursive: true });\n }\n cpSync(source, destination, { recursive: true });\n const { bytes } = countDirectoryContents(destination);\n return ok({ source, destination, type: \"directory\", bytes_copied: bytes });\n }\n\n copyFileSync(source, destination);\n const bytesCopied = statSync(destination).size;\n return ok({ source, destination, type: \"file\", bytes_copied: bytesCopied });\n}\n\nfunction handleListDirectory(args: Record<string, unknown>): ToolResult {\n const dirPath = resolvePath(args.path as string);\n const recursive = (args.recursive as boolean) || false;\n const maxDepth = (args.max_depth as number) || 1;\n const pattern = args.pattern as string | undefined;\n const includeHidden = (args.include_hidden as boolean) || false;\n\n if (!existsSync(dirPath)) throw new Error(\"Directory not found.\");\n const stat = statSync(dirPath);\n if (!stat.isDirectory()) throw new Error(\"Path is not a directory.\");\n\n const effectiveDepth = recursive ? maxDepth : 1;\n const patternRe = pattern ? globToRegex(pattern) : null;\n\n interface Entry {\n name: string;\n path: string;\n type: string;\n size: number;\n modified_at: string;\n is_hidden: boolean;\n }\n\n const entries: Entry[] = [];\n\n function scan(dir: string, depth: number): void {\n if (depth >= effectiveDepth) return;\n\n let dirents: Dirent[];\n try {\n dirents = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n dirents.sort((a, b) => a.name.localeCompare(b.name));\n\n for (const d of dirents) {\n if (!includeHidden && d.name.startsWith(\".\")) continue;\n\n const fullPath = join(dir, d.name);\n const isDir = d.isDirectory();\n\n // Apply pattern filter\n if (patternRe && !patternRe.test(d.name)) {\n // Still recurse into directories even if name doesn't match\n if (isDir && effectiveDepth > 1) {\n scan(fullPath, depth + 1);\n }\n continue;\n }\n\n let size = 0;\n let mtime = new Date().toISOString();\n try {\n const s = statSync(fullPath);\n size = isDir ? 0 : s.size;\n mtime = new Date(s.mtimeMs).toISOString();\n } catch { /* skip */ }\n\n entries.push({\n name: d.name,\n path: relative(dirPath, fullPath),\n type: fileType(isDir, d.isSymbolicLink()),\n size,\n modified_at: mtime,\n is_hidden: d.name.startsWith(\".\"),\n });\n\n if (isDir && effectiveDepth > 1) {\n scan(fullPath, depth + 1);\n }\n }\n }\n\n scan(dirPath, 0);\n\n return ok({\n path: dirPath,\n entries,\n total_count: entries.length,\n });\n}\n\nfunction handleExists(args: Record<string, unknown>): ToolResult {\n const targetPath = resolvePath(args.path as string);\n const pathExists = existsSync(targetPath);\n\n let type: string | null = null;\n if (pathExists) {\n const stat = statSync(targetPath, { throwIfNoEntry: false });\n if (stat) {\n type = fileType(stat.isDirectory(), stat.isSymbolicLink());\n }\n }\n\n return ok({ exists: pathExists, path: targetPath, type });\n}\n\nfunction handleGetFileInfo(args: Record<string, unknown>): ToolResult {\n const filePath = resolvePath(args.path as string);\n if (!existsSync(filePath)) throw new Error(\"Path not found.\");\n\n const stat = statSync(filePath, { throwIfNoEntry: false });\n if (!stat) throw new Error(\"Path not found.\");\n\n const isDir = stat.isDirectory();\n const isSymlink = stat.isSymbolicLink();\n const name = basename(filePath);\n const ext = isDir ? null : extname(name) || null;\n const binary = !isDir && !isSymlink ? isBinaryFile(filePath) : false;\n\n return ok({\n name,\n path: filePath,\n type: fileType(isDir, isSymlink),\n size: isDir ? 0 : stat.size,\n modified_at: new Date(stat.mtimeMs).toISOString(),\n created_at: stat.birthtimeMs ? new Date(stat.birthtimeMs).toISOString() : null,\n extension: ext,\n is_hidden: name.startsWith(\".\"),\n is_binary: binary,\n });\n}\n\nfunction handleSearchFiles(args: Record<string, unknown>): ToolResult {\n const searchPath = resolvePath(args.path as string);\n const pattern = (args.pattern as string) || \"*\";\n const recursive = args.recursive !== false; // default true\n const includeHidden = (args.include_hidden as boolean) || false;\n const maxResults = (args.max_results as number) || 1000;\n\n if (!existsSync(searchPath)) throw new Error(\"Directory not found.\");\n if (!statSync(searchPath).isDirectory()) throw new Error(\"Path is not a directory.\");\n\n const patternRe = globToRegex(pattern);\n const matches: string[] = [];\n let totalMatches = 0;\n\n function scan(dir: string): void {\n let dirents: Dirent[];\n try {\n dirents = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const d of dirents) {\n if (!includeHidden) {\n if (d.name.startsWith(\".\")) continue;\n }\n\n const fullPath = join(dir, d.name);\n\n if (d.isDirectory()) {\n if (recursive) scan(fullPath);\n continue;\n }\n\n if (patternRe.test(d.name)) {\n totalMatches++;\n if (matches.length < maxResults) {\n matches.push(relative(searchPath, fullPath));\n }\n }\n }\n }\n\n scan(searchPath);\n\n return ok({\n matches,\n total_matches: totalMatches,\n truncated: totalMatches > maxResults,\n search_path: searchPath,\n pattern,\n });\n}\n\nfunction handleFindInFiles(args: Record<string, unknown>): ToolResult {\n const searchPath = resolvePath(args.path as string);\n const query = args.query as string;\n const isRegex = (args.is_regex as boolean) || false;\n const caseSensitive = args.case_sensitive !== false; // default true\n const filePattern = args.pattern as string | undefined;\n const contextLines = (args.context_lines as number) || 0;\n const maxResults = (args.max_results as number) || 500;\n const includeHidden = (args.include_hidden as boolean) || false;\n\n if (!existsSync(searchPath)) throw new Error(\"Directory not found.\");\n if (!statSync(searchPath).isDirectory()) throw new Error(\"Path is not a directory.\");\n\n const flags = caseSensitive ? \"\" : \"i\";\n const re = isRegex\n ? new RegExp(query, flags)\n : new RegExp(query.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"), flags);\n\n const patternRe = filePattern ? globToRegex(filePattern) : null;\n\n interface Match {\n file: string;\n line: number;\n content: string;\n context_before: string[];\n context_after: string[];\n }\n\n const results: Match[] = [];\n let totalMatches = 0;\n let filesSearched = 0;\n let filesWithMatches = 0;\n\n function scan(dir: string): void {\n let dirents: Dirent[];\n try {\n dirents = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const d of dirents) {\n if (!includeHidden && d.name.startsWith(\".\")) continue;\n\n const fullPath = join(dir, d.name);\n\n if (d.isDirectory()) {\n scan(fullPath);\n continue;\n }\n\n if (patternRe && !patternRe.test(d.name)) continue;\n if (isBinaryFile(fullPath)) continue;\n\n filesSearched++;\n let fileHasMatch = false;\n\n let lines: string[];\n try {\n const text = readFileSync(fullPath, \"utf-8\");\n lines = text.split(\"\\n\");\n } catch {\n continue;\n }\n\n for (let i = 0; i < lines.length; i++) {\n if (re.test(lines[i])) {\n totalMatches++;\n fileHasMatch = true;\n\n if (results.length < maxResults) {\n const ctxStart = Math.max(0, i - contextLines);\n const ctxEnd = Math.min(lines.length, i + contextLines + 1);\n\n results.push({\n file: relative(searchPath, fullPath),\n line: i + 1,\n content: lines[i],\n context_before: lines.slice(ctxStart, i),\n context_after: lines.slice(i + 1, ctxEnd),\n });\n }\n }\n }\n\n if (fileHasMatch) filesWithMatches++;\n }\n }\n\n scan(searchPath);\n\n return ok({\n results,\n total_matches: totalMatches,\n files_searched: filesSearched,\n files_with_matches: filesWithMatches,\n truncated: totalMatches > maxResults,\n query,\n });\n}\n\nfunction handleGetTree(args: Record<string, unknown>): ToolResult {\n const rootPath = resolvePath(args.path as string);\n const maxDepth = (args.max_depth as number) || 3;\n const includeHidden = (args.include_hidden as boolean) || false;\n const maxEntries = (args.max_entries as number) || 500;\n\n if (!existsSync(rootPath)) throw new Error(\"Directory not found.\");\n if (!statSync(rootPath).isDirectory()) throw new Error(\"Path is not a directory.\");\n\n const lines: string[] = [];\n let entryCount = 0;\n let truncated = false;\n\n const rootName = basename(rootPath) || rootPath;\n lines.push(rootName + \"/\");\n\n function buildTree(dirPath: string, prefix: string, depth: number): void {\n if (truncated || depth >= maxDepth) return;\n\n let dirents: Dirent[];\n try {\n dirents = readdirSync(dirPath, { withFileTypes: true });\n } catch {\n return;\n }\n\n if (!includeHidden) {\n dirents = dirents.filter((d) => !d.name.startsWith(\".\"));\n }\n dirents.sort((a, b) => a.name.localeCompare(b.name));\n\n for (let i = 0; i < dirents.length; i++) {\n if (truncated) return;\n\n entryCount++;\n if (entryCount > maxEntries) {\n truncated = true;\n lines.push(prefix + \"... (truncated)\");\n return;\n }\n\n const d = dirents[i];\n const isLast = i === dirents.length - 1;\n const connector = isLast ? \"└── \" : \"├── \";\n const childPrefix = prefix + (isLast ? \" \" : \"│ \");\n const fullPath = join(dirPath, d.name);\n\n if (d.isDirectory()) {\n lines.push(prefix + connector + d.name + \"/\");\n buildTree(fullPath, childPrefix, depth + 1);\n } else {\n lines.push(prefix + connector + d.name);\n }\n }\n }\n\n buildTree(rootPath, \"\", 0);\n\n return ok({\n tree: lines.join(\"\\n\"),\n path: rootPath,\n entry_count: entryCount,\n truncated,\n max_depth: maxDepth,\n });\n}\n\n// ─── Dispatcher ──────────────────────────────────────────────────────────────\n\nconst HANDLERS: Record<string, (args: Record<string, unknown>) => ToolResult> = {\n read_file: handleReadFile,\n read_file_lines: handleReadFileLines,\n write_file: handleWriteFile,\n append_file: handleAppendFile,\n create_directory: handleCreateDirectory,\n delete: handleDelete,\n move: handleMove,\n copy: handleCopy,\n list_directory: handleListDirectory,\n exists: handleExists,\n get_file_info: handleGetFileInfo,\n search_files: handleSearchFiles,\n find_in_files: handleFindInFiles,\n get_tree: handleGetTree,\n};\n\n/**\n * Handle a filesystem tool call locally on the user's machine.\n *\n * @param _toolName Full tool name (may include composite prefix like \"filesystem__\")\n * @param baseName Base tool name without prefix (e.g. \"read_file\")\n * @param args Tool arguments from the MCP client\n */\nexport function handleLocalFilesystemTool(\n _toolName: string,\n baseName: string,\n args: Record<string, unknown>,\n): ToolResult {\n console.error(`[cortex-mcp] filesystem.${baseName}: executing locally`);\n\n const handler = HANDLERS[baseName];\n if (!handler) {\n return err(`Unknown filesystem tool: ${baseName}`);\n }\n\n try {\n return handler(args);\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n console.error(`[cortex-mcp] filesystem.${baseName} error: ${message}`);\n return err(message);\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { CONFIG_DIR_NAME, CONFIG_FILE_NAME, DEFAULT_SERVER_URL } from \"../constants.js\";\nimport { getHomeDir } from \"../utils/platform.js\";\nimport type { CortexMcpConfig } from \"./types.js\";\n\n/** Get the config directory path */\nexport function getConfigDir(): string {\n return join(getHomeDir(), CONFIG_DIR_NAME);\n}\n\n/** Get the config file path */\nexport function getConfigPath(): string {\n return join(getConfigDir(), CONFIG_FILE_NAME);\n}\n\n/** Read the current config, or return null if none exists */\nexport function readConfig(): CortexMcpConfig | null {\n const path = getConfigPath();\n if (!existsSync(path)) return null;\n\n try {\n const raw = readFileSync(path, \"utf-8\");\n return JSON.parse(raw) as CortexMcpConfig;\n } catch {\n return null;\n }\n}\n\n/** Write config to disk (creates directory with 700 permissions, file with 600) */\nexport function writeConfig(config: CortexMcpConfig): void {\n const dir = getConfigDir();\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n\n const path = getConfigPath();\n writeFileSync(path, JSON.stringify(config, null, 2) + \"\\n\", {\n mode: 0o600,\n });\n}\n\n/** Create a default config with the given API key and MCPs */\nexport function createConfig(\n apiKey: string,\n mcps: string[]\n): CortexMcpConfig {\n return {\n version: 1,\n server: DEFAULT_SERVER_URL,\n apiKey,\n mcps,\n configuredClients: [],\n };\n}\n","import { homedir, platform } from \"node:os\";\nimport { join } from \"node:path\";\n\n/** Get the user's home directory */\nexport function getHomeDir(): string {\n return homedir();\n}\n\n/** Get the current platform */\nexport function getPlatform(): \"macos\" | \"windows\" | \"linux\" {\n const p = platform();\n if (p === \"darwin\") return \"macos\";\n if (p === \"win32\") return \"windows\";\n return \"linux\";\n}\n\n/**\n * Get the Claude Desktop config file path for the current platform.\n */\nexport function getClaudeDesktopConfigPath(): string {\n const home = getHomeDir();\n const p = getPlatform();\n\n switch (p) {\n case \"macos\":\n return join(\n home,\n \"Library\",\n \"Application Support\",\n \"Claude\",\n \"claude_desktop_config.json\"\n );\n case \"windows\":\n return join(\n process.env.APPDATA || join(home, \"AppData\", \"Roaming\"),\n \"Claude\",\n \"claude_desktop_config.json\"\n );\n case \"linux\":\n return join(home, \".config\", \"Claude\", \"claude_desktop_config.json\");\n }\n}\n\n/**\n * Get the Cursor MCP config file path for the current platform.\n */\nexport function getCursorConfigPath(): string {\n const home = getHomeDir();\n return join(home, \".cursor\", \"mcp.json\");\n}\n\n/**\n * Get the VS Code MCP config file path for the current platform.\n */\nexport function getVSCodeMcpConfigPath(): string {\n const home = getHomeDir();\n return join(home, \".vscode\", \"mcp.json\");\n}\n\n/**\n * Get the Antigravity MCP config file path for the current platform.\n */\nexport function getAntigravityConfigPath(): string {\n const home = getHomeDir();\n return join(home, \".gemini\", \"antigravity\", \"mcp_config.json\");\n}\n\n/**\n * Get the Codex (OpenAI) config file path.\n * Shared by both Codex CLI and Codex IDE extension.\n */\nexport function getCodexConfigPath(): string {\n const home = getHomeDir();\n return join(home, \".codex\", \"config.toml\");\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { mkdirSync } from \"node:fs\";\nimport { execSync } from \"node:child_process\";\nimport { AVAILABLE_MCPS } from \"../constants.js\";\nimport {\n getClaudeDesktopConfigPath,\n getCursorConfigPath,\n getVSCodeMcpConfigPath,\n getAntigravityConfigPath,\n getCodexConfigPath,\n} from \"../utils/platform.js\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { getPlatform } from \"../utils/platform.js\";\nimport type { ClientType, DetectedClient, HttpMcpEntry } from \"./types.js\";\n\n/**\n * Detect which AI clients are installed on this machine.\n */\nexport function detectClients(): DetectedClient[] {\n const clients: DetectedClient[] = [];\n\n // Claude Desktop\n const desktopPath = getClaudeDesktopConfigPath();\n const desktopDir = dirname(desktopPath);\n clients.push({\n type: \"claude-desktop\",\n name: \"Claude (Desktop)\",\n configPath: desktopPath,\n detected: existsSync(desktopDir),\n });\n\n // Claude Code\n let claudeCodeDetected = false;\n try {\n execSync(\"which claude\", { stdio: \"pipe\" });\n claudeCodeDetected = true;\n } catch {\n // claude CLI not in PATH\n }\n clients.push({\n type: \"claude-code\",\n name: \"Claude Code\",\n configPath: null,\n detected: claudeCodeDetected,\n });\n\n // Cursor\n const cursorPath = getCursorConfigPath();\n const cursorDir = dirname(cursorPath);\n clients.push({\n type: \"cursor\",\n name: \"Cursor\",\n configPath: cursorPath,\n detected: existsSync(cursorDir),\n });\n\n // VS Code\n const home = homedir();\n const vscodePath = getVSCodeMcpConfigPath();\n clients.push({\n type: \"vscode\",\n name: \"VS Code\",\n configPath: vscodePath,\n detected: existsSync(join(home, \".vscode\")),\n });\n\n // Antigravity\n const antigravityPath = getAntigravityConfigPath();\n clients.push({\n type: \"antigravity\",\n name: \"Antigravity\",\n configPath: antigravityPath,\n detected: existsSync(join(home, \".antigravity\")),\n });\n\n // Codex (OpenAI) — CLI and IDE extension share ~/.codex/config.toml\n const codexPath = getCodexConfigPath();\n let codexDetected = existsSync(join(home, \".codex\"));\n if (!codexDetected) {\n try {\n execSync(\"which codex\", { stdio: \"pipe\" });\n codexDetected = true;\n } catch {\n // codex CLI not in PATH\n }\n }\n clients.push({\n type: \"codex\",\n name: \"Codex (OpenAI)\",\n configPath: codexPath,\n detected: codexDetected,\n });\n\n // OpenClaw / Stdio (always available — manual copy-paste)\n clients.push({\n type: \"stdio\",\n name: \"OpenClaw (stdio)\",\n configPath: null,\n detected: true,\n });\n\n return clients;\n}\n\n/**\n * Build per-MCP HTTP entries for a given server URL and API key.\n */\nexport function buildHttpEntries(\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): Record<string, HttpMcpEntry> {\n const entries: Record<string, HttpMcpEntry> = {};\n\n for (const mcp of AVAILABLE_MCPS) {\n if (!mcps.includes(mcp.name)) continue;\n entries[mcp.serverName] = {\n url: `${serverUrl}/mcp/${mcp.name}`,\n headers: { \"x-api-key\": apiKey },\n };\n }\n\n return entries;\n}\n\n/**\n * Configure Claude Desktop by merging a stdio proxy entry into its config file.\n * Uses command/args/env format (Claude Desktop does not support HTTP url/headers).\n * Preserves existing non-Cortex entries.\n */\nexport function configureClaudeDesktop(\n _serverUrl: string,\n apiKey: string,\n _mcps: string[]\n): void {\n const configPath = getClaudeDesktopConfigPath();\n const dir = dirname(configPath);\n\n // Ensure directory exists\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Read existing config or start fresh\n let config: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n try {\n config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {\n // Corrupted file — start fresh\n }\n }\n\n // Ensure mcpServers key exists\n if (!config.mcpServers || typeof config.mcpServers !== \"object\") {\n config.mcpServers = {};\n }\n\n const servers = config.mcpServers as Record<string, unknown>;\n\n // Remove existing cortex-* and cortex entries\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\") || key === \"cortex\") {\n delete servers[key];\n }\n }\n\n // Add stdio proxy entry (Claude Desktop only supports command/args)\n // API key is read from ~/.cortex-mcp/credentials.json at runtime by the serve command,\n // so we don't bake it into the env (avoids stale key issues on re-login).\n // On Windows, npx is a .cmd batch file — must invoke via cmd.exe for stdio to work.\n const isWindows = getPlatform() === \"windows\";\n servers[\"cortex\"] = isWindows\n ? {\n command: \"cmd\",\n args: [\"/c\", \"npx\", \"-y\", \"@danainnovations/cortex-mcp@latest\", \"serve\"],\n }\n : {\n command: \"npx\",\n args: [\"-y\", \"@danainnovations/cortex-mcp@latest\", \"serve\"],\n };\n\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\n/**\n * Configure Claude Code by running `claude mcp add` commands.\n */\nexport function configureClaudeCode(\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): void {\n for (const mcp of AVAILABLE_MCPS) {\n if (!mcps.includes(mcp.name)) continue;\n\n const url = `${serverUrl}/mcp/${mcp.name}`;\n\n // Remove existing entry first (ignore errors if it doesn't exist)\n try {\n execSync(`claude mcp remove ${mcp.serverName}`, { stdio: \"pipe\" });\n } catch {\n // Entry didn't exist — fine\n }\n\n execSync(\n `claude mcp add --transport http ${mcp.serverName} ${url} -H \"x-api-key: ${apiKey}\"`,\n { stdio: \"pipe\" }\n );\n }\n}\n\n/**\n * Configure Cursor by writing HTTP MCP entries to its config file.\n * Cursor supports HTTP transport natively.\n */\nexport function configureCursor(\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): void {\n const configPath = getCursorConfigPath();\n const dir = dirname(configPath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n let config: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n try {\n config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {\n // Corrupted file — start fresh\n }\n }\n\n if (!config.mcpServers || typeof config.mcpServers !== \"object\") {\n config.mcpServers = {};\n }\n\n const servers = config.mcpServers as Record<string, unknown>;\n\n // Remove existing cortex-* entries\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\")) {\n delete servers[key];\n }\n }\n\n // Add new HTTP entries\n const entries = buildHttpEntries(serverUrl, apiKey, mcps);\n Object.assign(servers, entries);\n\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\n/**\n * Configure VS Code by writing HTTP MCP entries to its config file.\n */\nexport function configureVSCode(\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): void {\n const configPath = getVSCodeMcpConfigPath();\n const dir = dirname(configPath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n let config: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n try {\n config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {\n // Corrupted file — start fresh\n }\n }\n\n if (!config.mcpServers || typeof config.mcpServers !== \"object\") {\n config.mcpServers = {};\n }\n\n const servers = config.mcpServers as Record<string, unknown>;\n\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\")) {\n delete servers[key];\n }\n }\n\n const entries = buildHttpEntries(serverUrl, apiKey, mcps);\n Object.assign(servers, entries);\n\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\n/**\n * Configure Antigravity by writing HTTP MCP entries to its config file.\n */\nexport function configureAntigravity(\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): void {\n const configPath = getAntigravityConfigPath();\n const dir = dirname(configPath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n let config: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n try {\n config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch {\n // Corrupted file — start fresh\n }\n }\n\n if (!config.mcpServers || typeof config.mcpServers !== \"object\") {\n config.mcpServers = {};\n }\n\n const servers = config.mcpServers as Record<string, unknown>;\n\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\")) {\n delete servers[key];\n }\n }\n\n const entries = buildHttpEntries(serverUrl, apiKey, mcps);\n Object.assign(servers, entries);\n\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\n/**\n * Configure Codex (OpenAI) by writing streamable HTTP entries to ~/.codex/config.toml.\n * Codex uses TOML format. The config is shared by both CLI and IDE extension.\n */\nexport function configureCodex(\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): void {\n const configPath = getCodexConfigPath();\n const dir = dirname(configPath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Read existing config to preserve non-cortex entries\n let existingContent = \"\";\n if (existsSync(configPath)) {\n try {\n existingContent = readFileSync(configPath, \"utf-8\");\n } catch {\n // Corrupted file — start fresh\n }\n }\n\n // Remove existing cortex-* MCP server blocks from TOML\n // Matches [mcp_servers.cortex-*] blocks until next section or EOF\n const cleaned = existingContent.replace(\n /\\[mcp_servers\\.cortex-[^\\]]*\\][^[]*(?=\\[|$)/g,\n \"\"\n ).trim();\n\n // Build new cortex MCP server entries in TOML format\n const tomlEntries: string[] = [];\n for (const mcp of AVAILABLE_MCPS) {\n if (!mcps.includes(mcp.name)) continue;\n tomlEntries.push(\n `[mcp_servers.${mcp.serverName}]\\n` +\n `url = \"${serverUrl}/mcp/${mcp.name}\"\\n` +\n `http_headers = { \"x-api-key\" = \"${apiKey}\" }`\n );\n }\n\n const newContent = (cleaned ? cleaned + \"\\n\\n\" : \"\") + tomlEntries.join(\"\\n\\n\") + \"\\n\";\n writeFileSync(configPath, newContent);\n}\n\n/**\n * Generate a stdio config snippet for clients that need it (OpenClaw, etc.)\n */\nexport function generateStdioSnippet(_apiKey: string): string {\n const isWindows = getPlatform() === \"windows\";\n const config = {\n mcpServers: {\n cortex: isWindows\n ? {\n command: \"cmd\",\n args: [\"/c\", \"npx\", \"-y\", \"@danainnovations/cortex-mcp@latest\", \"serve\"],\n }\n : {\n command: \"npx\",\n args: [\"-y\", \"@danainnovations/cortex-mcp@latest\", \"serve\"],\n },\n },\n };\n return JSON.stringify(config, null, 2);\n}\n\n/**\n * Remove all cortex-* MCP entries from Claude Desktop config.\n */\nexport function resetClaudeDesktop(): boolean {\n const configPath = getClaudeDesktopConfigPath();\n if (!existsSync(configPath)) return false;\n\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n if (!config.mcpServers) return false;\n\n const servers = config.mcpServers as Record<string, unknown>;\n let removed = false;\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\") || key === \"cortex\") {\n delete servers[key];\n removed = true;\n }\n }\n\n if (removed) {\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n return removed;\n } catch {\n return false;\n }\n}\n\n/**\n * Remove cortex MCP entries from Cursor config.\n */\nexport function resetCursor(): boolean {\n const configPath = getCursorConfigPath();\n if (!existsSync(configPath)) return false;\n\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n if (!config.mcpServers) return false;\n\n const servers = config.mcpServers as Record<string, unknown>;\n let removed = false;\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\") || key === \"cortex\") {\n delete servers[key];\n removed = true;\n }\n }\n\n if (removed) {\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n return removed;\n } catch {\n return false;\n }\n}\n\n/**\n * Remove cortex MCP entries from Claude Code.\n */\nexport function resetClaudeCode(): boolean {\n let removed = false;\n for (const mcp of AVAILABLE_MCPS) {\n try {\n execSync(`claude mcp remove ${mcp.serverName}`, { stdio: \"pipe\" });\n removed = true;\n } catch {\n // Entry didn't exist\n }\n }\n return removed;\n}\n\n/**\n * Remove cortex MCP entries from VS Code config.\n */\nexport function resetVSCode(): boolean {\n const configPath = getVSCodeMcpConfigPath();\n if (!existsSync(configPath)) return false;\n\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n if (!config.mcpServers) return false;\n\n const servers = config.mcpServers as Record<string, unknown>;\n let removed = false;\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\") || key === \"cortex\") {\n delete servers[key];\n removed = true;\n }\n }\n\n if (removed) {\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n return removed;\n } catch {\n return false;\n }\n}\n\n/**\n * Remove cortex MCP entries from Antigravity config.\n */\nexport function resetAntigravity(): boolean {\n const configPath = getAntigravityConfigPath();\n if (!existsSync(configPath)) return false;\n\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n if (!config.mcpServers) return false;\n\n const servers = config.mcpServers as Record<string, unknown>;\n let removed = false;\n for (const key of Object.keys(servers)) {\n if (key.startsWith(\"cortex-\") || key === \"cortex\") {\n delete servers[key];\n removed = true;\n }\n }\n\n if (removed) {\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n return removed;\n } catch {\n return false;\n }\n}\n\n/**\n * Remove cortex MCP entries from Codex config.\n */\nexport function resetCodex(): boolean {\n const configPath = getCodexConfigPath();\n if (!existsSync(configPath)) return false;\n\n try {\n const content = readFileSync(configPath, \"utf-8\");\n const cleaned = content.replace(\n /\\[mcp_servers\\.cortex-[^\\]]*\\][^[]*(?=\\[|$)/g,\n \"\"\n ).trim();\n\n if (cleaned !== content.trim()) {\n writeFileSync(configPath, cleaned ? cleaned + \"\\n\" : \"\");\n return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * Configure a specific client type.\n */\nexport function configureClient(\n clientType: ClientType,\n serverUrl: string,\n apiKey: string,\n mcps: string[]\n): string {\n switch (clientType) {\n case \"claude-desktop\":\n configureClaudeDesktop(serverUrl, apiKey, mcps);\n return \"Claude Desktop configured\";\n case \"claude-code\":\n configureClaudeCode(serverUrl, apiKey, mcps);\n return \"Claude Code configured\";\n case \"cursor\":\n configureCursor(serverUrl, apiKey, mcps);\n return \"Cursor configured\";\n case \"vscode\":\n configureVSCode(serverUrl, apiKey, mcps);\n return \"VS Code configured\";\n case \"antigravity\":\n configureAntigravity(serverUrl, apiKey, mcps);\n return \"Antigravity configured\";\n case \"codex\":\n configureCodex(serverUrl, apiKey, mcps);\n return \"Codex configured\";\n case \"stdio\":\n return (\n \"Add this to your client config:\\n\\n\" +\n generateStdioSnippet(apiKey)\n );\n }\n}\n","/**\n * Validate that a string looks like a Cortex API key.\n * Format: ctx_{id}_{secret}\n */\nexport function isValidApiKey(key: string): boolean {\n return /^ctx_[a-zA-Z0-9]+_[a-zA-Z0-9]+$/.test(key.trim());\n}\n\n/**\n * Validate an API key against the Cortex server by sending an initialize request.\n * Returns true if the server responds with 200, false otherwise.\n */\nexport async function validateApiKeyRemote(\n serverUrl: string,\n apiKey: string\n): Promise<{ valid: boolean; error?: string }> {\n try {\n const response = await fetch(`${serverUrl}/mcp/github`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"mcp-protocol-version\": \"2024-11-05\",\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n method: \"initialize\",\n params: {\n protocolVersion: \"2024-11-05\",\n capabilities: {},\n clientInfo: { name: \"cortex-mcp-setup\", version: \"1.0.0\" },\n },\n id: \"validate\",\n }),\n });\n\n if (response.status === 401 || response.status === 403) {\n return { valid: false, error: \"Invalid or expired API key\" };\n }\n if (!response.ok) {\n return { valid: false, error: `Server returned ${response.status}` };\n }\n return { valid: true };\n } catch {\n return { valid: false, error: \"Could not reach the Cortex server\" };\n }\n}\n","import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { CONFIG_DIR_NAME, CREDENTIALS_FILE_NAME, DEFAULT_API_KEY } from \"../constants.js\";\nimport { readConfig } from \"../config/storage.js\";\nimport { getHomeDir } from \"../utils/platform.js\";\n\n/** Stored credentials from a successful login */\nexport interface CortexCredentials {\n apiKey: string;\n email: string;\n name?: string;\n authenticatedAt: string; // ISO 8601\n}\n\n/** Get the credentials file path (~/.cortex-mcp/credentials.json) */\nexport function getCredentialsPath(): string {\n return join(getHomeDir(), CONFIG_DIR_NAME, CREDENTIALS_FILE_NAME);\n}\n\n/** Read stored credentials, or return null if not logged in */\nexport function readCredentials(): CortexCredentials | null {\n const path = getCredentialsPath();\n if (!existsSync(path)) return null;\n\n try {\n const raw = readFileSync(path, \"utf-8\");\n return JSON.parse(raw) as CortexCredentials;\n } catch {\n return null;\n }\n}\n\n/** Write credentials to disk (creates directory with 700, file with 600 permissions) */\nexport function writeCredentials(creds: CortexCredentials): void {\n const dir = join(getHomeDir(), CONFIG_DIR_NAME);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n\n const path = getCredentialsPath();\n writeFileSync(path, JSON.stringify(creds, null, 2) + \"\\n\", {\n mode: 0o600,\n });\n}\n\n/** Delete stored credentials */\nexport function deleteCredentials(): void {\n const path = getCredentialsPath();\n if (existsSync(path)) {\n unlinkSync(path);\n }\n}\n\n/**\n * Get the effective API key to use.\n * Priority: CORTEX_API_KEY env var > stored credentials > config file > default shared key\n */\nexport function getEffectiveApiKey(): string {\n // 1. Environment variable (highest priority)\n const envKey = process.env.CORTEX_API_KEY;\n if (envKey) return envKey;\n\n // 2. Personal credentials from login\n const creds = readCredentials();\n if (creds?.apiKey) return creds.apiKey;\n\n // 3. Config file (set during setup)\n const config = readConfig();\n if (config?.apiKey) return config.apiKey;\n\n // 4. Shared default key (fallback)\n return DEFAULT_API_KEY;\n}\n","import { CortexHttpClient } from \"../proxy/http-client.js\";\n\n/** Metadata for a single MCP tool */\nexport interface ToolInfo {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n}\n\n/** Base error class for all Cortex SDK errors */\nexport class CortexError extends Error {\n constructor(\n message: string,\n public readonly mcpName?: string\n ) {\n super(message);\n this.name = \"CortexError\";\n }\n}\n\n/**\n * Thrown when a tool executes but returns isError: true\n * (e.g., bad SOQL query, missing OAuth connection, invalid record ID).\n */\nexport class CortexToolError extends CortexError {\n constructor(\n message: string,\n public override readonly mcpName: string,\n public readonly toolName: string\n ) {\n super(message, mcpName);\n this.name = \"CortexToolError\";\n }\n}\n\n/**\n * Thrown on transport/auth failures — the tool never executed\n * (e.g., invalid API key, network error, server down).\n */\nexport class CortexNetworkError extends CortexError {\n constructor(\n message: string,\n public readonly code?: number,\n mcpName?: string\n ) {\n super(message, mcpName);\n this.name = \"CortexNetworkError\";\n }\n}\n\n/**\n * Provides a call interface for a single Cortex MCP.\n * Lazily initializes the underlying HTTP session on first use.\n */\nexport class MCPNamespace {\n private readonly client: CortexHttpClient;\n private initPromise: Promise<void> | null = null;\n\n constructor(\n public readonly mcpName: string,\n serverUrl: string,\n apiKey: string\n ) {\n this.client = new CortexHttpClient(serverUrl, apiKey, mcpName);\n }\n\n private async ensureInitialized(): Promise<void> {\n if (this.initPromise !== null) return this.initPromise;\n this.initPromise = this.doInit();\n return this.initPromise;\n }\n\n private async doInit(): Promise<void> {\n const response = await this.client.initialize();\n if (response.error) {\n this.initPromise = null;\n throw new CortexNetworkError(\n response.error.message,\n response.error.code,\n this.mcpName\n );\n }\n }\n\n /**\n * Call a tool on this MCP. Returns the parsed result.\n *\n * @example\n * const ns = new MCPNamespace('salesforce', serverUrl, apiKey);\n * const result = await ns.call('run_soql_query', {\n * query: 'SELECT Id, Name FROM Account LIMIT 10'\n * });\n */\n async call(\n toolName: string,\n args: Record<string, unknown> = {}\n ): Promise<unknown> {\n await this.ensureInitialized();\n const response = await this.client.callTool(toolName, args);\n\n if (response.error) {\n throw new CortexNetworkError(\n response.error.message,\n response.error.code,\n this.mcpName\n );\n }\n\n const result = response.result as {\n content: Array<{ type: string; text: string }>;\n isError?: boolean;\n };\n\n const text = result?.content?.[0]?.text ?? \"\";\n\n if (result?.isError) {\n throw new CortexToolError(text, this.mcpName, toolName);\n }\n\n return parseText(text);\n }\n\n /** List all tools available on this MCP. */\n async listTools(): Promise<ToolInfo[]> {\n await this.ensureInitialized();\n const response = await this.client.listTools();\n\n if (response.error) {\n throw new CortexNetworkError(\n response.error.message,\n response.error.code,\n this.mcpName\n );\n }\n\n const result = response.result as { tools: ToolInfo[] };\n return result?.tools ?? [];\n }\n\n /** Release the session. The next call() will re-initialize. */\n close(): void {\n this.initPromise = null;\n }\n}\n\n/** Parse text content — attempt JSON, fall back to raw string. */\nfunction parseText(text: string): unknown {\n if (!text) return text;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n","import { getEffectiveApiKey } from \"../auth/credentials.js\";\nimport { DEFAULT_SERVER_URL } from \"../constants.js\";\nimport { MCPNamespace } from \"./mcp-namespace.js\";\n\nexport interface CortexClientOptions {\n /** API key. Defaults to auto-resolved key (env > credentials > config > shared). */\n apiKey?: string;\n /** Cortex server URL. Defaults to https://cortex-bice.vercel.app */\n serverUrl?: string;\n}\n\n/**\n * High-level SDK client for calling Cortex MCP tools from custom apps.\n * Auto-resolves credentials and lazily initializes per-MCP sessions.\n *\n * @example\n * ```typescript\n * import { CortexClient } from '@danainnovations/cortex-mcp';\n *\n * const cortex = new CortexClient();\n *\n * // Salesforce — no Connected App needed\n * const accounts = await cortex.salesforce.call('run_soql_query', {\n * query: 'SELECT Id, Name FROM Account LIMIT 10'\n * });\n *\n * // Microsoft 365\n * const emails = await cortex.m365.call('list_emails', { count: 5 });\n *\n * // GitHub\n * const repos = await cortex.github.call('list_repositories', { per_page: 5 });\n *\n * // Cleanup when done\n * cortex.close();\n * ```\n */\nexport class CortexClient {\n private readonly apiKey: string;\n private readonly serverUrl: string;\n private readonly namespaces = new Map<string, MCPNamespace>();\n\n constructor(options: CortexClientOptions = {}) {\n this.apiKey = options.apiKey ?? getEffectiveApiKey();\n this.serverUrl = options.serverUrl ?? DEFAULT_SERVER_URL;\n }\n\n get asana(): MCPNamespace {\n return this.getNamespace(\"asana\");\n }\n get github(): MCPNamespace {\n return this.getNamespace(\"github\");\n }\n get mailchimp(): MCPNamespace {\n return this.getNamespace(\"mailchimp\");\n }\n get vercel(): MCPNamespace {\n return this.getNamespace(\"vercel\");\n }\n get supabase(): MCPNamespace {\n return this.getNamespace(\"supabase\");\n }\n get m365(): MCPNamespace {\n return this.getNamespace(\"m365\");\n }\n get salesforce(): MCPNamespace {\n return this.getNamespace(\"salesforce\");\n }\n get monday(): MCPNamespace {\n return this.getNamespace(\"monday\");\n }\n get slack(): MCPNamespace {\n return this.getNamespace(\"slack\");\n }\n get powerbi(): MCPNamespace {\n return this.getNamespace(\"powerbi\");\n }\n get bestbuy(): MCPNamespace {\n return this.getNamespace(\"bestbuy\");\n }\n get databricks(): MCPNamespace {\n return this.getNamespace(\"databricks\");\n }\n\n /**\n * Call any MCP tool when the MCP name is determined at runtime.\n *\n * @example\n * const result = await cortex.call('github', 'list_repositories', { per_page: 5 });\n */\n async call(\n mcpName: string,\n toolName: string,\n args: Record<string, unknown> = {}\n ): Promise<unknown> {\n return this.getNamespace(mcpName).call(toolName, args);\n }\n\n /**\n * Release all sessions. Safe to call multiple times.\n * The next call after close() will re-initialize automatically.\n */\n close(): void {\n for (const ns of this.namespaces.values()) {\n ns.close();\n }\n this.namespaces.clear();\n }\n\n private getNamespace(name: string): MCPNamespace {\n let ns = this.namespaces.get(name);\n if (!ns) {\n ns = new MCPNamespace(name, this.serverUrl, this.apiKey);\n this.namespaces.set(name, ns);\n }\n return ns;\n }\n}\n"],"mappings":"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","names":["readFileSync","statSync","statSync","fileBuffer","readFileSync","err","existsSync","mkdirSync","readFileSync","writeFileSync","join","join","join","existsSync","readFileSync","mkdirSync","writeFileSync","existsSync","readFileSync","writeFileSync","dirname","mkdirSync","homedir","join","dirname","existsSync","homedir","join","mkdirSync","readFileSync","writeFileSync","existsSync","mkdirSync","readFileSync","unlinkSync","writeFileSync","join","join","existsSync","readFileSync"]}
|
package/package.json
CHANGED
|
File without changes
|