Askr documentation
Server & APIs

Node Runtime

Node Runtime at the Askr server boundary, with validated input and explicit failure states.

Example

Create the platform service at the application composition root and pass its provider-neutral contract into routes or components.

import { createI18n } from '@askrjs/i18n';

export const i18n = createI18n('en', {
  en: { greeting: (name: string) => 'Hello, ' + name },
  fr: { greeting: (name: string) => 'Bonjour, ' + name },
});

<i18n.Scope locale="en">
  {i18n.text('greeting', 'Askr')}
</i18n.Scope>

Server adapter

createNodeHandler(app, options) converts a ServerApp into a Node-compatible (req, res, next?) => void handler — options is a required second argument, not optional, even if you have nothing to configure and pass {}, so it drops straight into an existing http.createServer callback or a Connect/Express-style middleware chain. The optional baseUrl lets you tell the adapter where the app is mounted when it isn't serving from the root path. Everything else about request handling — routing, loaders, actions — stays inside the ServerApp itself; this layer just bridges Node's I/O types to it.

MCP adapter

connectMcpStdio(mcp, options), exported from @askrjs/node/mcp, runs an @askrjs/server McpServer over stdio instead of HTTP — the shape you need when the client is a local MCP host rather than a browser. You supply dependencies directly, along with optional input/output/diagnostics streams and an auth value or resolver function for authenticating the connection. The returned McpStdioConnection exposes a closed promise and a close() method, so you can shut the process down cleanly instead of just letting the pipes drop.

Signals and shutdown

serve accepts a signals option — an array of NodeJS.Signals to listen for, or false to disable the behavior entirely — and installs handlers that call your app's optional close() and then resolve serve's returned promise. listen, the lower-level function, instead accepts a plain AbortSignal if you want to control shutdown from your own lifecycle logic rather than OS signals. Either way, the goal is the same: give in-flight requests a chance to finish before the process exits.

Deployment

serve(app, options) is the one-call path for a standalone process: it binds a port and host, optionally serves static assets from an assets.root directory, and returns a ServedApplication with the live server, its resolved url, and a close() method. For finer control — custom TLS setup, a shared HTTP server, integration with an existing process manager — call listen or createNodeHandler directly instead. Nothing in this package assumes a particular host provider; it's plain Node http, so it runs anywhere Node runs.