nanocoai/nanoclaw · error

${parsed.error}

Error message

${parsed.error}

What it means

The self-mod MCP tool `add_mcp_server` rejects the server configuration before submitting it for approval. `parseMcpServerInput` failed to coerce the args into a valid MCP server config (bad/missing transport fields, bad URL, or malformed JSON), so the error string is surfaced verbatim. This is client-side validation inside the agent container, not a host or approval failure.

Source

Thrown at container/agent-runner/src/mcp-tools/self-mod.ts:196

        command: { type: 'string', description: 'Command to run the MCP server' },
        url: {
          type: 'string',
          description: 'Streamable HTTP MCP endpoint (HTTPS; plain HTTP only for localhost / host.docker.internal)',
        },
        args: { type: 'array', items: { type: 'string' }, description: 'Command arguments' },
        env: { type: 'object', description: 'Environment variables for the server' },
      },
      required: ['name'],
    },
  },
  async handler(args) {
    const name = typeof args.name === 'string' ? args.name : '';
    if (!name) return err('name is required');
    if (!MCP_SERVER_NAME_RE.test(name)) {
      return err('server name must be 1-64 characters of letters, digits, "_" or "-"');
    }
    const parsed = parseMcpServerInput(args);
    if ('error' in parsed) return err(parsed.error);

    const requestId = generateId();
    await writeMessageOut({
      id: requestId,
      kind: 'system',
      content: JSON.stringify({
        action: 'add_mcp_server',
        name,
        ...parsed.config,
      }),
    });

    log(`add_mcp_server: ${requestId} → "${name}" (${'url' in parsed.config ? 'HTTP' : parsed.config.command})`);
    return ok(`MCP server request submitted. You will be notified when admin approves or rejects.`);
  },
};

registerTools([installPackages, addMcpServer]);

View on GitHub (pinned to 294ef2aee8)

Solutions

  1. Read the returned message — it names the exact missing/invalid field; fix the args object accordingly
  2. Check parseMcpServerInput's accepted shapes (stdio: {command,args,env}; http: {url,headers}) and match one exactly
  3. Validate the config shape in your own code before invoking the tool
  4. If the shape you used worked before, check for an agent-runner update that tightened the parser

Example fix

// before
await add_mcp_server({ name: 'github', server: { cmd: 'npx -y @modelcontextprotocol/server-github' } });
// after
await add_mcp_server({ name: 'github', server: { command: 'npx', args: ['-y', '@modelcontextprotocol/server-github'], env: { GITHUB_TOKEN: '...' } } });
Defensive patterns

Strategy: validation

Validate before calling

function isValidStdioServer(s) {
  return !!s && typeof s.command === 'string' && s.command.length > 0 &&
    Array.isArray(s.args ?? []) && typeof (s.env ?? {}) === 'object';
}

Type guard

function isMcpServerInput(v: unknown): v is { command: string; args?: string[]; env?: Record<string,string> } {
  if (typeof v !== 'object' || v === null) return false;
  const o = v as Record<string, unknown>;
  return typeof o.command === 'string' && o.command.length > 0;
}

Prevention

When it happens

Trigger: Calling the add_mcp_server MCP tool with args.name valid but args describing the server (command/url, env, args) malformed — e.g. missing `command` for stdio servers, a non-URL `url` for HTTP servers, or wrong types for env/args.

Common situations: Agent constructs the server config from chat text and drops a required field; passing an SSE-style {url} to a stdio shape; env given as an array instead of an object; older callers using a pre-schema field name after an agent-runner update.

Related errors


AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28). Data as JSON: /api/errors/20da2fcd7b853896. Report an issue: GitHub.