1Panel-dev/1Panel · warning · Error
aiTools.mcp.importMcpJsonError
Error message
aiTools.mcp.importMcpJsonError
What it means
In the MCP-server import dialog (frontend/src/views/ai/mcp/server/import/index.vue:56), the parsed JSON must contain a top-level `mcpServers` object; anything else throws aiTools.mcp.importMcpJsonError. Note the local try/catch immediately swallows the thrown Error and returns, so the user sees no feedback and the dialog simply does not proceed — the message currently never surfaces.
Source
Thrown at frontend/src/views/ai/mcp/server/import/index.vue:56
<script lang="ts" setup>
import i18n from '@/lang';
import { ref } from 'vue';
const submitVisible = ref(false);
const mcpServerJson = ref();
const mcpServerConfig = ref();
const acceptParams = (): void => {
mcpServerJson.value = '';
submitVisible.value = true;
};
const emit = defineEmits(['confirm', 'cancel']);
const onConfirm = async () => {
try {
const data = JSON.parse(mcpServerJson.value);
if (!data.mcpServers || typeof data.mcpServers !== 'object') {
throw new Error(i18n.global.t('aiTools.mcp.importMcpJsonError'));
}
mcpServerConfig.value = Object.entries(data.mcpServers).map(([name, config]: any) => ({
name,
command: [config.command, ...config.args].join(' '),
environments: config.env ? Object.entries(config.env).map(([key, value]) => ({ key, value })) : [],
ssePath: '/' + name,
containerName: name,
}));
} catch (error) {
return;
}
emit('confirm', mcpServerConfig.value);
submitVisible.value = false;
};
const onCancel = async () => {
emit('cancel');
submitVisible.value = false;View on GitHub (pinned to 5ac7c80881)
Solutions
- Ensure the pasted JSON is an object with `mcpServers` at the TOP level: {"mcpServers":{"name":{"command":"npx","args":[...]}}}
- If copying from a nested settings file, extract only the mcpServers object before pasting
- Also confirm each entry has `command` (string) and optionally `args` (array) and `env` (object), since `[config.command, ...config.args]` throws for malformed entries (also swallowed)
- Fix the swallowed-error UX: display the caught error (e.g. Message.error) instead of a bare return, so invalid input is visible
Example fix
// before (nested — throws, silently swallowed)
{ "projects": { "mcpServers": { "foo": { "command": "npx" } } } }
// after
{ "mcpServers": { "foo": { "command": "npx", "args": ["-y", "foo"] } } }
// component fix: surface the error
// catch (error) { Message.error(error instanceof Error ? error.message : 'import failed'); return; } Defensive patterns
Strategy: validation
Validate before calling
const isMcpImportShape = (v: unknown): v is { mcpServers: Record<string, { command: string; args?: string[]; env?: Record<string, string> }> } =>
typeof v === 'object' && v !== null &&
typeof (v as any).mcpServers === 'object' && (v as any).mcpServers !== null &&
Object.values((v as any).mcpServers).every((s: any) => typeof s?.command === 'string' && Array.isArray(s?.args ?? [])); Type guard
// see validationCode — isMcpImportShape narrows the parsed JSON before mapping
Try / catch
try { const data = JSON.parse(raw); if (!isMcpImportShape(data)) throw new Error(t('aiTools.mcp.importMcpJsonError')); }
catch (e) { Message.error(e instanceof Error ? e.message : t('aiTools.mcp.importMcpJsonError')); return; } // show, don't swallow Prevention
- Keep mcpServers at the top level of the pasted JSON
- Validate per-entry command/args shapes before Object.entries mapping
- Replace the silent `catch { return; }` with a visible error toast so users know why nothing happened
When it happens
Trigger: Pasting a Claude/Cursor config whose root key is `mcpServers` nested under another key (e.g. a full settings.json with `mcpServers` at depth 2); pasting `{"servers": {...}}`; pasting a JSON array; passing invalid JSON (caught by the same catch).
Common situations: Exporting from a client that wraps servers under a different root (e.g. `mcpServers` inside `projects` in some Claude configs); hand-written configs; extra commas/BOM breaking JSON.parse.
Related errors
AI-assisted analysis of 1Panel-dev/1Panel@5ac7c80881 (2026-08-15).
Data as JSON: /api/errors/becae0f4ed62b7dd.
Report an issue: GitHub.