nanocoai/nanoclaw · error · Error
type "stdio" requires command
Error message
type "stdio" requires command
What it means
Thrown by parseMcpServerConfig when an MCP server entry declares type "stdio" but omits the required `command` field. A stdio MCP server is launched by executing a local binary, so the command is mandatory; the config is rejected before it can reach the container spec.
Source
Thrown at src/container-config.ts:138
/**
* Parse one CLI or approval payload into the persisted MCP config shape.
* Duplicated in container/agent-runner/src/mcp-tools/self-mod.ts
* (parseMcpServerInput) — no shared modules across the host/container
* boundary; keep the two in sync.
*/
export function parseMcpServerConfig(input: Record<string, unknown>): McpServerConfig {
const command = typeof input.command === 'string' && input.command.trim() ? input.command : undefined;
const url = typeof input.url === 'string' && input.url.trim() ? input.url.trim() : undefined;
// A declared transport is honored; absence keeps the legacy CLI inference
// (url → http, command → stdio). "streamable-http" is the Agent Plugins
// spelling of the internal "http".
const type = input.type === 'streamable-http' ? 'http' : input.type;
if (type === 'sse') throw new Error('unsupported transport "sse"');
if (type !== undefined && type !== 'stdio' && type !== 'http') {
throw new Error('type must be "stdio", "http", or "streamable-http"');
}
if (type === 'stdio' && !command) throw new Error('type "stdio" requires command');
if (type === 'http' && !url) throw new Error('type "http" requires url');
const instructions = input.instructions;
if (instructions !== undefined && typeof instructions !== 'string') {
throw new Error('MCP instructions must be a string');
}
if (url !== undefined) {
if (command !== undefined) throw new Error('Provide exactly one of command or url');
if (input.args !== undefined || input.env !== undefined || input.cwd !== undefined) {
throw new Error('args, env, and cwd are only valid with command');
}
let parsed: URL;
try {
parsed = new URL(url);
} catch (err) {
throw new Error('url must be a valid HTTP(S) URL', { cause: err });
}View on GitHub (pinned to 294ef2aee8)
Solutions
- Add a `command` field naming the executable, e.g. {"type":"stdio","command":"npx","args":["-y","some-mcp-server"]}
- If you meant a remote server, use type "http"/"streamable-http" with a url instead
- Verify the JSON you passed with ncl groups config get to see the parsed entry
Example fix
// before
{"type":"stdio","args":["-y","server"]}
// after
{"type":"stdio","command":"npx","args":["-y","server"]} Defensive patterns
Strategy: validation
Validate before calling
const srv = input; // before parseMcpServerConfig
if (srv.type === 'stdio' && !srv.command) throw new UserError('stdio MCP entry needs command'); Type guard
function isValidStdioEntry(e: any): e is {type:'stdio'; command:string} {
return e?.type === 'stdio' && typeof e.command === 'string' && e.command.length > 0;
} Try / catch
catch (err) { if (err instanceof Error && err.message.includes('requires command')) showFieldError('command', err); else throw err; } Prevention
- Build MCP entries in a typed object (McpServerConfig) instead of raw JSON
- Validate entries with ncl groups config get after every add-mcp-server
When it happens
Trigger: Calling ncl groups config add-mcp-server (or the add_mcp_server self-mod MCP tool) with --type stdio and only a url, or with no command/url at all; also any programmatic call to parseMcpServerConfig with {type:'stdio'} lacking command.
Common situations: Copy-pasting an HTTP server config and changing type to stdio without replacing url with command; assuming a default command exists; omitting command because the server 'name' looks executable.
Related errors
- type "http" requires url
- server name must be 1-64 characters of letters, digits, "_"
- unsupported transport "sse"
- type must be "stdio", "http", or "streamable-http"
- MCP instructions must be a string
AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28).
Data as JSON: /api/errors/49059761e4353fa8.
Report an issue: GitHub.