multicorn-shield 1.3.6 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/multicorn-proxy.js +51 -18
- package/dist/multicorn-shield.js +51 -18
- package/dist/shield-extension.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
- Bump `version` in `package.json` before publishing to npm.
|
|
11
11
|
|
|
12
|
+
## [1.4.0] - 2026-05-08
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Hosted proxy wizard now prompts for upstream MCP server authentication (header name and value) when the target server requires credentials
|
|
17
|
+
- Helpful examples shown during hosted proxy setup: common MCP server URLs (GitHub, Supabase, Atlassian, Stripe) with links to where to find tokens
|
|
18
|
+
- Upstream auth headers are stored encrypted and forwarded by the proxy to the target MCP server on every request
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- Target MCP server URL prompt now shows common examples instead of a generic placeholder
|
|
23
|
+
- "govern" replaced with "control" in all user-facing copy
|
|
24
|
+
- "upstream auth" replaced with "server credentials" in all user-facing copy
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- Hosted proxy connections to MCP servers requiring authentication (e.g. GitHub, Supabase) now work end-to-end - previously the proxy forwarded requests without credentials
|
|
29
|
+
|
|
12
30
|
## [1.3.6] - 2026-05-08
|
|
13
31
|
|
|
14
32
|
### Fixed
|
package/dist/multicorn-proxy.js
CHANGED
|
@@ -1500,8 +1500,8 @@ async function promptProxyConfig(ask, agentName) {
|
|
|
1500
1500
|
while (targetUrl.length === 0) {
|
|
1501
1501
|
process.stderr.write(
|
|
1502
1502
|
"\n" + style.bold("Target MCP server URL:") + "\n" + style.dim(
|
|
1503
|
-
"
|
|
1504
|
-
) + "\n"
|
|
1503
|
+
"This is the URL of the MCP server you want Shield to control. Common examples:"
|
|
1504
|
+
) + "\n" + style.dim(" GitHub: https://api.githubcopilot.com/mcp/") + "\n" + style.dim(" Supabase: https://mcp.supabase.com/sse") + "\n" + style.dim(" Atlassian: https://mcp.atlassian.com/v1/sse") + "\n" + style.dim(" Stripe: https://mcp.stripe.com/v1/sse") + "\n" + style.dim("Check your MCP server's documentation for the correct URL.") + "\n"
|
|
1505
1505
|
);
|
|
1506
1506
|
const input = await ask("URL: ");
|
|
1507
1507
|
if (input.trim().length === 0) {
|
|
@@ -1521,10 +1521,44 @@ async function promptProxyConfig(ask, agentName) {
|
|
|
1521
1521
|
targetUrl = input.trim();
|
|
1522
1522
|
}
|
|
1523
1523
|
const shortName = normalizeAgentName(agentName) || "shield-mcp";
|
|
1524
|
-
|
|
1524
|
+
process.stderr.write(
|
|
1525
|
+
"\n" + style.bold("Does this MCP server require authentication?") + "\n" + style.dim(
|
|
1526
|
+
"Most MCP servers need a token or API key. Check the server's docs for how to get one:"
|
|
1527
|
+
) + "\n" + style.dim(" GitHub: Settings > Developer Settings > Personal Access Tokens") + "\n" + style.dim(
|
|
1528
|
+
" Supabase: Project Settings > API > anon or scoped key (service role bypasses RLS; avoid for most MCP)"
|
|
1529
|
+
) + "\n" + style.dim(" Atlassian: id.atlassian.com > API Tokens") + "\n" + style.dim(" Stripe: Dashboard > Developers > API Keys") + "\n"
|
|
1530
|
+
);
|
|
1531
|
+
const authReply = await ask("(y/N): ");
|
|
1532
|
+
const authNorm = authReply.trim().toLowerCase();
|
|
1533
|
+
const wantsAuth = authNorm === "y" || authNorm === "yes";
|
|
1534
|
+
let upstreamHeaders;
|
|
1535
|
+
if (wantsAuth) {
|
|
1536
|
+
process.stderr.write(
|
|
1537
|
+
"\n" + style.bold("Enter the Authorization header value.") + "\n" + style.dim(" For Bearer tokens: Bearer ghp_xxxxxxxxxxxx") + "\n" + style.dim(" For API keys: Bearer sk-xxxxxxxxxxxx") + "\n"
|
|
1538
|
+
);
|
|
1539
|
+
const headerVal = await ask("Value: ");
|
|
1540
|
+
const trimmed = headerVal.trim();
|
|
1541
|
+
if (trimmed.length > 0) {
|
|
1542
|
+
upstreamHeaders = { Authorization: trimmed };
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
return {
|
|
1546
|
+
targetUrl,
|
|
1547
|
+
shortName,
|
|
1548
|
+
...upstreamHeaders !== void 0 ? { upstreamHeaders } : {}
|
|
1549
|
+
};
|
|
1525
1550
|
}
|
|
1526
|
-
async function createProxyConfig(baseUrl, apiKey, agentName, targetUrl, serverName, platform) {
|
|
1551
|
+
async function createProxyConfig(baseUrl, apiKey, agentName, targetUrl, serverName, platform, upstreamHeaders) {
|
|
1527
1552
|
let response;
|
|
1553
|
+
const body = {
|
|
1554
|
+
server_name: serverName,
|
|
1555
|
+
target_url: targetUrl,
|
|
1556
|
+
platform,
|
|
1557
|
+
agent_name: agentName
|
|
1558
|
+
};
|
|
1559
|
+
if (upstreamHeaders !== void 0 && Object.keys(upstreamHeaders).length > 0) {
|
|
1560
|
+
body["upstream_headers"] = upstreamHeaders;
|
|
1561
|
+
}
|
|
1528
1562
|
try {
|
|
1529
1563
|
response = await fetch(`${baseUrl}/api/v1/proxy/config`, {
|
|
1530
1564
|
method: "POST",
|
|
@@ -1532,12 +1566,7 @@ async function createProxyConfig(baseUrl, apiKey, agentName, targetUrl, serverNa
|
|
|
1532
1566
|
"Content-Type": "application/json",
|
|
1533
1567
|
"X-Multicorn-Key": apiKey
|
|
1534
1568
|
},
|
|
1535
|
-
body: JSON.stringify(
|
|
1536
|
-
server_name: serverName,
|
|
1537
|
-
target_url: targetUrl,
|
|
1538
|
-
platform,
|
|
1539
|
-
agent_name: agentName
|
|
1540
|
-
}),
|
|
1569
|
+
body: JSON.stringify(body),
|
|
1541
1570
|
signal: AbortSignal.timeout(1e4)
|
|
1542
1571
|
});
|
|
1543
1572
|
} catch (error) {
|
|
@@ -2445,7 +2474,7 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2445
2474
|
}
|
|
2446
2475
|
}
|
|
2447
2476
|
} else {
|
|
2448
|
-
const { targetUrl, shortName } = await promptProxyConfig(ask, agentName);
|
|
2477
|
+
const { targetUrl, shortName, upstreamHeaders } = await promptProxyConfig(ask, agentName);
|
|
2449
2478
|
let proxyUrl = "";
|
|
2450
2479
|
let created = false;
|
|
2451
2480
|
while (!created) {
|
|
@@ -2457,7 +2486,8 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2457
2486
|
agentName,
|
|
2458
2487
|
targetUrl,
|
|
2459
2488
|
shortName,
|
|
2460
|
-
selectedPlatform
|
|
2489
|
+
selectedPlatform,
|
|
2490
|
+
upstreamHeaders
|
|
2461
2491
|
);
|
|
2462
2492
|
spinner.stop(true, "Proxy config created!");
|
|
2463
2493
|
created = true;
|
|
@@ -2538,7 +2568,7 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2538
2568
|
}
|
|
2539
2569
|
}
|
|
2540
2570
|
} else {
|
|
2541
|
-
const { targetUrl, shortName } = await promptProxyConfig(ask, agentName);
|
|
2571
|
+
const { targetUrl, shortName, upstreamHeaders } = await promptProxyConfig(ask, agentName);
|
|
2542
2572
|
let proxyUrl = "";
|
|
2543
2573
|
let created = false;
|
|
2544
2574
|
while (!created) {
|
|
@@ -2550,7 +2580,8 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2550
2580
|
agentName,
|
|
2551
2581
|
targetUrl,
|
|
2552
2582
|
shortName,
|
|
2553
|
-
selectedPlatform
|
|
2583
|
+
selectedPlatform,
|
|
2584
|
+
upstreamHeaders
|
|
2554
2585
|
);
|
|
2555
2586
|
spinner.stop(true, "Proxy config created!");
|
|
2556
2587
|
created = true;
|
|
@@ -2625,7 +2656,7 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2625
2656
|
}
|
|
2626
2657
|
}
|
|
2627
2658
|
} else {
|
|
2628
|
-
const { targetUrl, shortName } = await promptProxyConfig(ask, agentName);
|
|
2659
|
+
const { targetUrl, shortName, upstreamHeaders } = await promptProxyConfig(ask, agentName);
|
|
2629
2660
|
let proxyUrl = "";
|
|
2630
2661
|
let created = false;
|
|
2631
2662
|
while (!created) {
|
|
@@ -2637,7 +2668,8 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2637
2668
|
agentName,
|
|
2638
2669
|
targetUrl,
|
|
2639
2670
|
shortName,
|
|
2640
|
-
selectedPlatform
|
|
2671
|
+
selectedPlatform,
|
|
2672
|
+
upstreamHeaders
|
|
2641
2673
|
);
|
|
2642
2674
|
spinner.stop(true, "Proxy config created!");
|
|
2643
2675
|
created = true;
|
|
@@ -2675,7 +2707,7 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2675
2707
|
}
|
|
2676
2708
|
}
|
|
2677
2709
|
} else {
|
|
2678
|
-
const { targetUrl, shortName } = await promptProxyConfig(ask, agentName);
|
|
2710
|
+
const { targetUrl, shortName, upstreamHeaders } = await promptProxyConfig(ask, agentName);
|
|
2679
2711
|
let proxyUrl = "";
|
|
2680
2712
|
let created = false;
|
|
2681
2713
|
while (!created) {
|
|
@@ -2687,7 +2719,8 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2687
2719
|
agentName,
|
|
2688
2720
|
targetUrl,
|
|
2689
2721
|
shortName,
|
|
2690
|
-
selectedPlatform
|
|
2722
|
+
selectedPlatform,
|
|
2723
|
+
upstreamHeaders
|
|
2691
2724
|
);
|
|
2692
2725
|
spinner.stop(true, "Proxy config created!");
|
|
2693
2726
|
created = true;
|
package/dist/multicorn-shield.js
CHANGED
|
@@ -1571,8 +1571,8 @@ async function promptProxyConfig(ask, agentName) {
|
|
|
1571
1571
|
while (targetUrl.length === 0) {
|
|
1572
1572
|
process.stderr.write(
|
|
1573
1573
|
"\n" + style.bold("Target MCP server URL:") + "\n" + style.dim(
|
|
1574
|
-
"
|
|
1575
|
-
) + "\n"
|
|
1574
|
+
"This is the URL of the MCP server you want Shield to control. Common examples:"
|
|
1575
|
+
) + "\n" + style.dim(" GitHub: https://api.githubcopilot.com/mcp/") + "\n" + style.dim(" Supabase: https://mcp.supabase.com/sse") + "\n" + style.dim(" Atlassian: https://mcp.atlassian.com/v1/sse") + "\n" + style.dim(" Stripe: https://mcp.stripe.com/v1/sse") + "\n" + style.dim("Check your MCP server's documentation for the correct URL.") + "\n"
|
|
1576
1576
|
);
|
|
1577
1577
|
const input = await ask("URL: ");
|
|
1578
1578
|
if (input.trim().length === 0) {
|
|
@@ -1592,10 +1592,44 @@ async function promptProxyConfig(ask, agentName) {
|
|
|
1592
1592
|
targetUrl = input.trim();
|
|
1593
1593
|
}
|
|
1594
1594
|
const shortName = normalizeAgentName(agentName) || "shield-mcp";
|
|
1595
|
-
|
|
1595
|
+
process.stderr.write(
|
|
1596
|
+
"\n" + style.bold("Does this MCP server require authentication?") + "\n" + style.dim(
|
|
1597
|
+
"Most MCP servers need a token or API key. Check the server's docs for how to get one:"
|
|
1598
|
+
) + "\n" + style.dim(" GitHub: Settings > Developer Settings > Personal Access Tokens") + "\n" + style.dim(
|
|
1599
|
+
" Supabase: Project Settings > API > anon or scoped key (service role bypasses RLS; avoid for most MCP)"
|
|
1600
|
+
) + "\n" + style.dim(" Atlassian: id.atlassian.com > API Tokens") + "\n" + style.dim(" Stripe: Dashboard > Developers > API Keys") + "\n"
|
|
1601
|
+
);
|
|
1602
|
+
const authReply = await ask("(y/N): ");
|
|
1603
|
+
const authNorm = authReply.trim().toLowerCase();
|
|
1604
|
+
const wantsAuth = authNorm === "y" || authNorm === "yes";
|
|
1605
|
+
let upstreamHeaders;
|
|
1606
|
+
if (wantsAuth) {
|
|
1607
|
+
process.stderr.write(
|
|
1608
|
+
"\n" + style.bold("Enter the Authorization header value.") + "\n" + style.dim(" For Bearer tokens: Bearer ghp_xxxxxxxxxxxx") + "\n" + style.dim(" For API keys: Bearer sk-xxxxxxxxxxxx") + "\n"
|
|
1609
|
+
);
|
|
1610
|
+
const headerVal = await ask("Value: ");
|
|
1611
|
+
const trimmed = headerVal.trim();
|
|
1612
|
+
if (trimmed.length > 0) {
|
|
1613
|
+
upstreamHeaders = { Authorization: trimmed };
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
return {
|
|
1617
|
+
targetUrl,
|
|
1618
|
+
shortName,
|
|
1619
|
+
...upstreamHeaders !== void 0 ? { upstreamHeaders } : {}
|
|
1620
|
+
};
|
|
1596
1621
|
}
|
|
1597
|
-
async function createProxyConfig(baseUrl, apiKey, agentName, targetUrl, serverName, platform) {
|
|
1622
|
+
async function createProxyConfig(baseUrl, apiKey, agentName, targetUrl, serverName, platform, upstreamHeaders) {
|
|
1598
1623
|
let response;
|
|
1624
|
+
const body = {
|
|
1625
|
+
server_name: serverName,
|
|
1626
|
+
target_url: targetUrl,
|
|
1627
|
+
platform,
|
|
1628
|
+
agent_name: agentName
|
|
1629
|
+
};
|
|
1630
|
+
if (upstreamHeaders !== void 0 && Object.keys(upstreamHeaders).length > 0) {
|
|
1631
|
+
body["upstream_headers"] = upstreamHeaders;
|
|
1632
|
+
}
|
|
1599
1633
|
try {
|
|
1600
1634
|
response = await fetch(`${baseUrl}/api/v1/proxy/config`, {
|
|
1601
1635
|
method: "POST",
|
|
@@ -1603,12 +1637,7 @@ async function createProxyConfig(baseUrl, apiKey, agentName, targetUrl, serverNa
|
|
|
1603
1637
|
"Content-Type": "application/json",
|
|
1604
1638
|
"X-Multicorn-Key": apiKey
|
|
1605
1639
|
},
|
|
1606
|
-
body: JSON.stringify(
|
|
1607
|
-
server_name: serverName,
|
|
1608
|
-
target_url: targetUrl,
|
|
1609
|
-
platform,
|
|
1610
|
-
agent_name: agentName
|
|
1611
|
-
}),
|
|
1640
|
+
body: JSON.stringify(body),
|
|
1612
1641
|
signal: AbortSignal.timeout(1e4)
|
|
1613
1642
|
});
|
|
1614
1643
|
} catch (error) {
|
|
@@ -2525,7 +2554,7 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2525
2554
|
}
|
|
2526
2555
|
}
|
|
2527
2556
|
} else {
|
|
2528
|
-
const { targetUrl, shortName } = await promptProxyConfig(ask, agentName);
|
|
2557
|
+
const { targetUrl, shortName, upstreamHeaders } = await promptProxyConfig(ask, agentName);
|
|
2529
2558
|
let proxyUrl = "";
|
|
2530
2559
|
let created = false;
|
|
2531
2560
|
while (!created) {
|
|
@@ -2537,7 +2566,8 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2537
2566
|
agentName,
|
|
2538
2567
|
targetUrl,
|
|
2539
2568
|
shortName,
|
|
2540
|
-
selectedPlatform
|
|
2569
|
+
selectedPlatform,
|
|
2570
|
+
upstreamHeaders
|
|
2541
2571
|
);
|
|
2542
2572
|
spinner.stop(true, "Proxy config created!");
|
|
2543
2573
|
created = true;
|
|
@@ -2618,7 +2648,7 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2618
2648
|
}
|
|
2619
2649
|
}
|
|
2620
2650
|
} else {
|
|
2621
|
-
const { targetUrl, shortName } = await promptProxyConfig(ask, agentName);
|
|
2651
|
+
const { targetUrl, shortName, upstreamHeaders } = await promptProxyConfig(ask, agentName);
|
|
2622
2652
|
let proxyUrl = "";
|
|
2623
2653
|
let created = false;
|
|
2624
2654
|
while (!created) {
|
|
@@ -2630,7 +2660,8 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2630
2660
|
agentName,
|
|
2631
2661
|
targetUrl,
|
|
2632
2662
|
shortName,
|
|
2633
|
-
selectedPlatform
|
|
2663
|
+
selectedPlatform,
|
|
2664
|
+
upstreamHeaders
|
|
2634
2665
|
);
|
|
2635
2666
|
spinner.stop(true, "Proxy config created!");
|
|
2636
2667
|
created = true;
|
|
@@ -2705,7 +2736,7 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2705
2736
|
}
|
|
2706
2737
|
}
|
|
2707
2738
|
} else {
|
|
2708
|
-
const { targetUrl, shortName } = await promptProxyConfig(ask, agentName);
|
|
2739
|
+
const { targetUrl, shortName, upstreamHeaders } = await promptProxyConfig(ask, agentName);
|
|
2709
2740
|
let proxyUrl = "";
|
|
2710
2741
|
let created = false;
|
|
2711
2742
|
while (!created) {
|
|
@@ -2717,7 +2748,8 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2717
2748
|
agentName,
|
|
2718
2749
|
targetUrl,
|
|
2719
2750
|
shortName,
|
|
2720
|
-
selectedPlatform
|
|
2751
|
+
selectedPlatform,
|
|
2752
|
+
upstreamHeaders
|
|
2721
2753
|
);
|
|
2722
2754
|
spinner.stop(true, "Proxy config created!");
|
|
2723
2755
|
created = true;
|
|
@@ -2755,7 +2787,7 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2755
2787
|
}
|
|
2756
2788
|
}
|
|
2757
2789
|
} else {
|
|
2758
|
-
const { targetUrl, shortName } = await promptProxyConfig(ask, agentName);
|
|
2790
|
+
const { targetUrl, shortName, upstreamHeaders } = await promptProxyConfig(ask, agentName);
|
|
2759
2791
|
let proxyUrl = "";
|
|
2760
2792
|
let created = false;
|
|
2761
2793
|
while (!created) {
|
|
@@ -2767,7 +2799,8 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2767
2799
|
agentName,
|
|
2768
2800
|
targetUrl,
|
|
2769
2801
|
shortName,
|
|
2770
|
-
selectedPlatform
|
|
2802
|
+
selectedPlatform,
|
|
2803
|
+
upstreamHeaders
|
|
2771
2804
|
);
|
|
2772
2805
|
spinner.stop(true, "Proxy config created!");
|
|
2773
2806
|
created = true;
|
package/dist/shield-extension.js
CHANGED
|
@@ -22417,7 +22417,7 @@ async function writeExtensionBackup(claudeDesktopConfigPath, mcpServers) {
|
|
|
22417
22417
|
|
|
22418
22418
|
// package.json
|
|
22419
22419
|
var package_default = {
|
|
22420
|
-
version: "1.
|
|
22420
|
+
version: "1.4.0"};
|
|
22421
22421
|
|
|
22422
22422
|
// src/package-meta.ts
|
|
22423
22423
|
var PACKAGE_VERSION = package_default.version;
|
package/package.json
CHANGED