Skip to content

Keryx – One TypeScript action class, five transports (HTTP, WS, CLI, MCP, tasks)

keryxjs.com
10 pointsevantahler2 comments
On HN

Comments

Hi HN, I’m Evan. I’ve been building API frameworks in JavaScript and Typescript for over a decade (I created Actionhero), and Keryx is the distillation of everything I’ve learned, rebuilt from scratch on Bun and TypeScript.

The big idea: you write one action class with a Zod schema, and the framework serves it as an HTTP endpoint, a WebSocket handler, a CLI command, a background task, and an MCP tool with the same validation, same middleware, same `run()` method. The only thing that changes is how the request arrives.

The MCP part is what pushed me to build this. I work on AI agent infrastructure at Arcade (we do authorization and tooling for AI agents), and I kept seeing folks bolt MCP servers onto existing APIs as a separate layer with duplicated auth, duplicated schemas, and duplicated error handling. Keryx makes your API an MCP server by default — OAuth 2.1 + PKCE built in, per-session isolation, and typed errors that agents can actually distinguish.

The stack is opinionated: Bun, Zod, Drizzle ORM, Redis (for Resque-based background tasks and PubSub), PostgreSQL. No compilation step, sub-second startup.

You can try it right now:

  bunx keryx new my-app
  cd my-app
  cp .env.example .env
  bun install
  bun dev

Requires Bun, PostgreSQL, and Redis running locally (and a `createdb bun` for the default DB).

Some things I’d love feedback on:

- Is the “one action, every transport” abstraction too magical, or does it feel natural once you use it? - The MCP-native approach — is this how you’d want to add agent support to a new project? - Anything missing from the comparison table on the homepage?

Code is MIT licensed: https://github.com/actionhero/keryx

Happy to answer questions about the architecture, the MCP integration, or why I think Bun is ready for this kind of framework.

Nice. I'm still working on a gunshi-mcp, a Gunshi plugin for cli + MCP. Keryx here going considerably further is neat!

It's wild how many ways we have to run subprocesses!

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.