Askr
Server & APIs

Primitives

Use primitives with the current published Askr packages.

  • @askrjs/askr0.0.59

How to use primitives

Start with this complete primitives shape, then replace the example data and application service with your own.

  1. Import the published @askrjs/askr entrypoint.
  2. Keep primitives configuration next to the component, route, or server composition root that owns it.
  3. Handle pending, unavailable, cancellation, and failure states, then verify the production path.
const mcp = createMcpServer({ name: 'project-tools', version: '1.0.0' })
  .tool('lookup-project', { input: projectInput }, async (context, input) => {
    return { content: [{ type: 'text', text: await lookup(input.id) }] };
  });

Tools

A tool is registered with `server.tool(name, { input, output, auth, ... }, handler)`; the handler receives an `McpContext` and the parsed input, and returns `{ content, structuredContent, isError }`. If you declare an `output` schema and the handler sets `structuredContent`, the result is validated with `safeParse` too — a mismatch produces a JSON-RPC internal error rather than a silently wrong response. `tools/list` returns each tool's name, its declared options, `inputSchema`, and `outputSchema` when present, paginated with a numeric-string cursor.

Resources

`server.resource(uri, options, handler)` registers an exact-match URI; `resources/read` looks it up directly and calls the handler with the parsed `URL`. The handler can return a single `McpContent` object or a readonly array — the server normalizes either into a `contents` array in the response. `resources/list` returns `{ uri, name, ...options }` for every visible resource, where `name` defaults to the URI itself if you don't set `options.name`.

Resource templates

`server.resourceTemplate(template, options, handler)` accepts a URI pattern with `{name}` placeholders; incoming reads are matched against every registered template with a generated regular expression, and the first match supplies the extracted variables to your handler. Templates also support an optional `complete(argument, value)` function used by `completion/complete` to return argument suggestions — the server caps returned values at 100 and reports `hasMore` if there were more. Unlike exact resources, template matching happens on every `resources/read` call whose URI isn't an exact registry hit, so keep templates reasonably specific to avoid ambiguous matches.

Prompts

`server.prompt(name, options, handler)` registers a named prompt whose `arguments` schema (an `ObjectSchema`, defaulting to empty) is parsed before the handler runs, mirroring tool input validation. The handler returns `{ description?, messages }`, and `prompts/list` derives each argument's `name`, `description`, and `required` flag directly from the schema's JSON Schema `properties` and `required` array — there's no separate argument-metadata API to keep in sync. Invalid prompt arguments produce a `-32602` JSON-RPC error with the schema's `issues` attached, the same shape tools use for invalid input.