Setting up the stack pointer before jumping to main is important. Arranging for argc/argv to work. Waking init array or section for global constructors.
There's also libc which is roughly a pile of more-or-less useful functions, some of them implemented in terms of syscalls. That one is nominally optional.
There's probably a compiler runtime involved as well, libgcc or libclang_rt.builtins or similar, which is likely to be cyclically dependent on libc. Compiler-dependent whether that is optional, and thus likely whether libc is optional in practice.