2 comments

  • evantahler 4 days ago ago

    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.

  • jauntywundrkind 3 days ago ago

    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!