# Node Runtime

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

Source: [https://askrjs.com/docs/platform-services/node-runtime](https://askrjs.com/docs/platform-services/node-runtime)

Status: stable. Packages: @askrjs/node.

**Published packages are authoritative.** Examples may lag behind a published contract. When guidance differs, verify the exports and TypeScript declarations in your installed package, then file an issue.

## Example

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

```tsx
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.

## Documentation navigation

[Previous](https://askrjs.com/docs/platform-services/index.md) | [Next](https://askrjs.com/docs/platform-services/internationalization/index.md)
