siyuan-note/siyuan · error

command is required for stdio server

Error message

command is required for stdio server

What it means

Returned by `connectStdio` when a server of type `"stdio"` has an empty `Command` field. The stdio transport spawns the server via `exec.Command(server.Command, server.Args...)`, so a missing command leaves nothing to launch; the guard fails fast before attempting the spawn.

Source

Thrown at kernel/mcp/client/mcp.go:450

			logging.LogInfof("mcp: server [%s] tool list changed, reconnecting", server.Name)
			go reconnectMCPServer(server.ID)
		},
	})

	switch server.Type {
	case "stdio":
		session, cmd, err := connectStdio(ctx, c, server)
		return session, cmd, nil, err
	case "http":
		return connectHTTP(ctx, c, server, interactive)
	default:
		return nil, nil, nil, fmt.Errorf("unsupported server type: %s", server.Type)
	}
}

func connectStdio(ctx context.Context, client *mcp.Client, server conf.MCPServer) (*mcp.ClientSession, *exec.Cmd, error) {
	if server.Command == "" {
		return nil, nil, fmt.Errorf("command is required for stdio server")
	}

	cmd := exec.Command(server.Command, server.Args...)
	cmdEnv, err := buildStdioEnvironment(server, os.LookupEnv, func(value string) string {
		if model.Conf == nil {
			return value
		}
		return conf.ResolveSecretsVars(model.Conf.Secrets, model.Conf.Variables, value)
	}, runtime.GOOS)
	if err != nil {
		return nil, nil, fmt.Errorf("environment: %w", err)
	}
	cmd.Env = cmdEnv
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return nil, nil, fmt.Errorf("stdin pipe: %w", err)
	}
	stdout, err := cmd.StdoutPipe()

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Provide a non-empty `command` for the stdio server, e.g. `"command": "npx"`.
  2. If the server is HTTP-based, set `type` to `"http"` and fill `url` instead of `command`.
  3. Validate the config that any `stdio` entry has both a `command` and (optionally) `args`.

Example fix

// before
{ "name": "srv", "type": "stdio", "args": ["-m", "my_server"] }
// after
{ "name": "srv", "type": "stdio", "command": "python", "args": ["-m", "my_server"] }
Defensive patterns

Strategy: validation

Validate before calling

// Validate stdio server entries before attempting to connect:
if server.Type == "stdio" && strings.TrimSpace(server.Command) == "" {
    return fmt.Errorf("command is required for stdio server")
}

Type guard

func isValidStdioServer(s conf.MCPServer) bool {
    return s.Type == "stdio" && strings.TrimSpace(s.Command) != ""
}

Prevention

When it happens

Trigger: A `stdio` MCP server config where `command` is omitted or empty, even though `args` may be present. The check `server.Command == ""` is the first thing `connectStdio` does.

Common situations: Configuring only `args` and forgetting `command`; a templated config whose `$COMMAND` variable expanded to empty; a server entry meant to be `http` but mistyped as `stdio`.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/ab0427c15d43f989. Report an issue: GitHub.