Skip to content

Commit 9deeb1c

Browse files
authored
fix: using the new format for mcp-configs (#132)
We changed the format for mcp configs to be a map on devbox create had to update the cli
1 parent 38b4df5 commit 9deeb1c

6 files changed

Lines changed: 52 additions & 29 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
"dependencies": {
7373
"@js-temporal/polyfill": "^0.5.1",
7474
"@modelcontextprotocol/sdk": "^1.26.0",
75-
"@runloop/api-client": "1.10.2",
75+
"@runloop/api-client": "1.10.3",
7676
"@types/express": "^5.0.6",
7777
"chalk": "^5.6.2",
7878
"commander": "^14.0.2",

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/commands/devbox/create.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -115,25 +115,36 @@ function parseGateways(
115115

116116
function parseMcpSpecs(
117117
specs: string[],
118-
): Array<{ mcp_config: string; secret: string }> {
119-
return specs.map((spec) => {
120-
const commaIndex = spec.indexOf(",");
118+
): Record<string, { mcp_config: string; secret: string }> {
119+
const result: Record<string, { mcp_config: string; secret: string }> = {};
120+
for (const spec of specs) {
121+
const eqIndex = spec.indexOf("=");
122+
if (eqIndex === -1) {
123+
throw new Error(
124+
`Invalid MCP spec format: ${spec}. Expected ENV_VAR_NAME=mcp_config_id_or_name,secret_id_or_name`,
125+
);
126+
}
127+
const envVarName = spec.substring(0, eqIndex);
128+
const valueStr = spec.substring(eqIndex + 1);
129+
130+
const commaIndex = valueStr.indexOf(",");
121131
if (commaIndex === -1) {
122132
throw new Error(
123-
`Invalid MCP spec format: ${spec}. Expected mcp_config_id_or_name,secret_id_or_name`,
133+
`Invalid MCP spec format: ${spec}. Expected ENV_VAR_NAME=mcp_config_id_or_name,secret_id_or_name`,
124134
);
125135
}
126-
const mcpConfig = spec.substring(0, commaIndex);
127-
const secret = spec.substring(commaIndex + 1);
136+
const mcpConfig = valueStr.substring(0, commaIndex);
137+
const secret = valueStr.substring(commaIndex + 1);
128138

129-
if (!mcpConfig || !secret) {
139+
if (!envVarName || !mcpConfig || !secret) {
130140
throw new Error(
131-
`Invalid MCP spec format: ${spec}. Expected mcp_config_id_or_name,secret_id_or_name`,
141+
`Invalid MCP spec format: ${spec}. Expected ENV_VAR_NAME=mcp_config_id_or_name,secret_id_or_name`,
132142
);
133143
}
134144

135-
return { mcp_config: mcpConfig, secret };
136-
});
145+
result[envVarName] = { mcp_config: mcpConfig, secret };
146+
}
147+
return result;
137148
}
138149

139150
export async function createDevbox(options: CreateOptions = {}) {

src/components/DevboxCreatePage.tsx

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ interface GatewaySpec {
8181

8282
// MCP configuration for devbox
8383
interface McpSpec {
84+
envVarName: string; // environment variable name for the MCP token envelope
8485
mcpConfig: string; // MCP config ID or name
8586
mcpConfigName: string; // display name
8687
mcpConfigEndpoint: string; // endpoint URL
@@ -638,7 +639,9 @@ export const DevboxCreatePage = ({
638639
// Attach the configured MCP config to the devbox
639640
const handleAttachMcp = React.useCallback(() => {
640641
if (!pendingMcpConfig || !pendingMcpSecret) return;
642+
const envVarName = `RL_MCP_${pendingMcpConfig.name.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`;
641643
const newMcp: McpSpec = {
644+
envVarName,
642645
mcpConfig: pendingMcpConfig.id,
643646
mcpConfigName: pendingMcpConfig.name,
644647
mcpConfigEndpoint: pendingMcpConfig.endpoint,
@@ -1087,10 +1090,14 @@ export const DevboxCreatePage = ({
10871090

10881091
// Add MCP specifications
10891092
if (formData.mcpConfigs.length > 0) {
1090-
createParams.mcp = formData.mcpConfigs.map((m) => ({
1091-
mcp_config: m.mcpConfig,
1092-
secret: m.secret,
1093-
}));
1093+
const mcp: Record<string, { mcp_config: string; secret: string }> = {};
1094+
for (const m of formData.mcpConfigs) {
1095+
mcp[m.envVarName] = {
1096+
mcp_config: m.mcpConfig,
1097+
secret: m.secret,
1098+
};
1099+
}
1100+
createParams.mcp = mcp;
10941101
}
10951102

10961103
// Add tunnel configuration if not "none"
@@ -2610,8 +2617,9 @@ export const DevboxCreatePage = ({
26102617
<Box marginLeft={2} flexDirection="column">
26112618
{formData.mcpConfigs.map((m, idx) => (
26122619
<Text key={idx} color={colors.textDim} dimColor>
2613-
{figures.pointer} Config: {m.mcpConfigName} (
2614-
{m.mcpConfigEndpoint}) | Secret: {m.secretName}
2620+
{figures.pointer} ENV: {m.envVarName} | Config:{" "}
2621+
{m.mcpConfigName} ({m.mcpConfigEndpoint}) | Secret:{" "}
2622+
{m.secretName}
26152623
</Text>
26162624
))}
26172625
</Box>
@@ -2812,6 +2820,9 @@ export const DevboxCreatePage = ({
28122820
</Text>
28132821
</Box>
28142822
<Box marginLeft={3} flexDirection="column">
2823+
<Text color={colors.textDim} dimColor>
2824+
ENV: {m.envVarName}
2825+
</Text>
28152826
<Text color={colors.textDim} dimColor>
28162827
Endpoint: {m.mcpConfigEndpoint}
28172828
</Text>

src/components/DevboxDetailPage.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ export const DevboxDetailPage = ({ devbox, onBack }: DevboxDetailPageProps) => {
3030
>({});
3131

3232
React.useEffect(() => {
33-
if (!devbox.mcp_specs || devbox.mcp_specs.length === 0) return;
33+
if (!devbox.mcp_specs || Object.keys(devbox.mcp_specs).length === 0) return;
3434

35-
devbox.mcp_specs.forEach((spec) => {
35+
for (const [, spec] of Object.entries(devbox.mcp_specs)) {
3636
getMcpConfig(spec.mcp_config_id)
3737
.then((config) => {
3838
setMcpEndpoints((prev) => ({
@@ -41,7 +41,7 @@ export const DevboxDetailPage = ({ devbox, onBack }: DevboxDetailPageProps) => {
4141
}));
4242
})
4343
.catch(() => {});
44-
});
44+
}
4545
}, [devbox.mcp_specs]);
4646
const [selectedOperationKey, setSelectedOperationKey] = React.useState<
4747
string | null
@@ -311,11 +311,12 @@ export const DevboxDetailPage = ({ devbox, onBack }: DevboxDetailPageProps) => {
311311
}
312312

313313
// MCP Specs
314-
if (devbox.mcp_specs && devbox.mcp_specs.length > 0) {
315-
devbox.mcp_specs.forEach((spec, idx) => {
314+
if (devbox.mcp_specs && Object.keys(devbox.mcp_specs).length > 0) {
315+
const entries = Object.entries(devbox.mcp_specs);
316+
entries.forEach(([envVarName, spec]) => {
316317
const endpoint = mcpEndpoints[spec.mcp_config_id];
317318
detailFields.push({
318-
label: `MCP Config${devbox.mcp_specs!.length > 1 ? ` ${idx + 1}` : ""}`,
319+
label: `MCP (${envVarName})`,
319320
value: (
320321
<Text>
321322
<Text color={colors.success}>{spec.mcp_config_id}</Text>

src/utils/commands.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export function createProgram(): Command {
7171
)
7272
.option(
7373
"--mcp <specs...>",
74-
"MCP configurations (format: mcp_config_id_or_name,secret_id_or_name)",
74+
"MCP configurations (format: ENV_VAR_NAME=mcp_config_id_or_name,secret_id_or_name)",
7575
)
7676
.option(
7777
"-o, --output [format]",

0 commit comments

Comments
 (0)