Keryx is a small, self-hosted gateway that exposes the same tool definitions through three interfaces:
- Model Context Protocol (MCP) over stateless Streamable HTTP.
- OpenAPI 3.1 and generated REST routes.
- Apple Siri Shortcuts generated by the legacy module.
The design goal is one source of truth for tool metadata, input validation, authentication mode, and handler behavior.
Client
│
├── POST /mcp
├── POST /api/tools/<tool>
└── GET /openapi.json
│
▼
Express transport layer
- request ID
- security headers
- CORS and MCP Origin validation
- rate limiting and JSON limits
- per-tool authentication
│
▼
ToolRegistry
name, description, module,
auth mode, Zod input, handler
│
▼
Domain/tool implementation
│
├── local result
├── bounded HTTPS upstream request
└── temporary one-time Shortcut artifact
Validates all process configuration at startup. Production uses fail-closed rules: HTTPS public URL, strong gateway token, explicit CORS configuration, and HTTPS upstream URLs.
Defines ToolDefinition, ToolContext, and ToolRegistry. A registry is created per Express app instance, which makes application construction deterministic and test-safe.
Parses bearer credentials, performs timing-safe gateway-token comparison, and applies the selected auth model:
gateway: Keryx validatesKERYX_API_TOKEN.forward: Keryx requires a caller bearer and forwards it to the fixed upstream service, which remains the authorization authority.
Generates the OpenAPI document from the registry. REST routes and MCP tools use the same Zod schemas, so protocol descriptions cannot silently drift from runtime validation.
Builds a stateless MCP server for each request. The Express layer validates the request Origin before the MCP SDK receives the request.
Contains the built-in next-generation tools. Upstream responses are timeout-bounded, redirect-disabled, content-type checked, and size-limited before JSON parsing.
Compiles Apple Shortcuts and stores generated binary files only in memory. Capability URLs are random, short-lived, and single-use.
A tool should:
- Use a stable snake_case name.
- Validate every caller-controlled field with Zod.
- Choose
gatewayorforwardauth explicitly. - Avoid accepting arbitrary upstream URLs; prefer operator-configured endpoints.
- Apply time, response-size, and redirect limits to network calls.
- Return JSON-serializable data.
- Add tests and update the README/OpenAPI examples.
See docs/ADDING_TOOLS.md.
MCP and REST execution are stateless. The only in-process state is the temporary Shortcut store. Consequently:
- ordinary tool traffic can be load-balanced without sticky sessions;
- a generated Shortcut must be downloaded from the same instance unless a shared artifact store is introduced;
- horizontal scaling should either disable the legacy artifact flow or replace the store through a future storage interface.
Keryx is not an identity provider, policy engine, secret vault, generic forward proxy, or long-term artifact store. Those responsibilities remain with the upstream application and deployment platform.