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

  1. Ensure the pasted JSON is an object with `mcpServers` at the TOP level: {"mcpServers":{"name":{"command":"npx","args":[...]}}}
  2. If copying from a nested settings file, extract only the mcpServers object before pasting
  3. 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)
  4. 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

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.