Skip to main content
Handlers access request-scoped capabilities through an ambient context — no prop-drilling. Call server.getContext() anywhere in the call tree during a live request:
server.tool({ name: 'summarize', input: z.object({ text: z.string() }) }, async ({ text }) => {
  const ctx = server.getContext()
  await ctx.info('Sending document to LLM')
  await ctx.reportProgress(0, 1, 'Sampling…')
  const { content } = await ctx.sample({
    messages: [{ role: 'user', content: { type: 'text', text: `Summarize:\n${text}` } }],
    maxTokens: 512,
  })
  return content.text
})
This page is under construction. The outline below sketches what it will cover.
  • How context works — ambient via AsyncLocalStorage; getContext() throws outside a live request handler; available in tool, resource, and prompt handlers.
  • Logging and progresslog(level, message) plus RFC 5424 shorthands (debug/info/warning/error/…); reportProgress(progress, total?, message?) (a no-op when the request carries no progress token).
  • Client round-tripssample(params) for LLM inference, elicit(message, schema) for user input forms, listRoots() — each throws if the client lacks the corresponding capability.
  • Per-session stategetState/setState/deleteState, scoped per HTTP session (one shared map for stdio); plus auth and requestId fields.