I don't think the article was talking writing a "Redis Server" in the sense of writing something that tries to
do what redis-server does — i.e. to be a "data-structure server" that has a root-level keyspace of variously-typed values, and commands that atomically build up and query those data structures. Maybe they used that as an
example of what you can do, but it's not the most
useful example. (If that's what you wanted, why not just use a regular redis-server deployment?)
I think the article was instead just using the term "Redis server" to mean "any server that speaks the server side of the client-server protocol that redis-server speaks" (without implication that it stores data ala redis-server) — in the same way that an "HTTP server" is "any server that speaks the server side of the client-server protocol that HTTP servers speak" (without implication that it serves HTML files, generates directory indices, and supports per-user multitenant shares, ala default-configuration Apache.)
Note that the command set of Redis isn't part of the Redis protocol. A "Redis protocol" server could have an entirely novel set of commands, none of which have anything to do with keys or data-structures. It's just another way of exposing an API to clients. Your application-layer protocol over the Redis wire protocol could be "an API for triggering webhooks", or "a group-chat software protocol ala IRC/XMPP", etc.; and in none of those cases do you need to implement GET/SET/DEL/etc., or to describe your own use-case in terms of GET/SET/DEL/etc.†
The only thing the Redis wire-protocol necessitates, IIRC, is that each command start with a verb; that verbs consist of ASCII characters, with a certain maximum length; and that each verb have a fixed "schema" for the members of its parameter list, that pre-determines the encoding a client should use to send an instance of that command over the text or binary wire-protocols, without any connection-time schema discovery.
And yes, most Redis clients do have some way of sending custom commands to the server, with the schema for those commands specified at runtime (at least over the Redis text protocol), even if they don't have syntax sugar for doing it the way they do for the redis-server built-in commands. Even if a Redis client's aim is only to talk to redis-server deployments, they still have to support custom commands, because individual redis-server deployments are extensible with https://redis.io/modules that expose arbitrary commands, and client libraries can't possibly know about those modules at compile-time. So they have to support potentially any command at runtime, somehow or another.
-----
† Mind you, just like HTTP has "REST" (which basically means "using the default HTTP verbs for analogous purposes in your own API, instead of totally abusing theirs semantics or inventing your own verbs"), there could be a similar convention on top of the Redis wire protocol, where you implement your API in terms of the built-in redis-server verbs GET/SET/DEL/etc. Then you could use the full syntax-sugared default commands built into Redis-protocol clients, to talk to your server, instead of needing to rely on the runtime custom-command support. However, unlike with REST, I don't think this use-case is very useful — the schema of redis-server's built-in command verbs has pretty tight tolerances, and doesn't allow for too many use-cases that aren't just "building a data-structure server."