Files
operations/docs/response-envelopes.md

2.9 KiB

Response Envelopes

All operation results are wrapped in a ResponseEnvelope<T> that carries transport metadata alongside the data. This provides a uniform result type regardless of whether the operation ran locally, over HTTP, or via MCP.

Structure

interface ResponseEnvelope<T = unknown> {
  data: T;
  meta: ResponseMeta;
}

meta.source is the discriminant:

Source Type Carries
"local" LocalResponseMeta operationId, timestamp
"http" HTTPResponseMeta statusCode, headers, contentType
"mcp" MCPResponseMeta isError, content[], structuredContent?, _meta?

Creating Envelopes

localEnvelope

For in-process results:

import { localEnvelope } from "@alkdev/operations";

const env = localEnvelope({ id: "123", title: "My task" }, "task.create");

httpEnvelope

For HTTP-sourced results (e.g., OpenAPI adapter):

import { httpEnvelope } from "@alkdev/operations";

const env = httpEnvelope(data, {
  statusCode: 200,
  headers: { "content-type": "application/json" },
  contentType: "application/json",
});

mcpEnvelope

For MCP-sourced results:

import { mcpEnvelope } from "@alkdev/operations";

const env = mcpEnvelope(data, {
  isError: false,
  content: [{ type: "text", text: "Done" }],
});

Unwrapping

import { unwrap } from "@alkdev/operations";

const result = unwrap(envelope);

Returns envelope.data, discarding transport metadata.

Detecting Envelopes

import { isResponseEnvelope } from "@alkdev/operations";

if (isResponseEnvelope(maybeEnvelope)) {
  // TypeScript narrows to ResponseEnvelope
}

Checks that the value has data and meta with a recognized source ("local" | "http" | "mcp") and the appropriate source-specific fields.

Automatic Wrapping

When an operation handler returns a plain value (not a ResponseEnvelope), registry.execute() and subscribe() wrap it in a localEnvelope() automatically. If the handler already returns a ResponseEnvelope, it passes through unchanged.

MCP Content Blocks

MCP responses include structured content blocks:

type MCPContentBlock =
  | { type: "text"; text: string; annotations?: MCPAnnotations }
  | { type: "image"; data: string; mimeType: string; annotations?: MCPAnnotations }
  | { type: "audio"; data: string; mimeType: string; annotations?: MCPAnnotations }
  | { type: "resource"; resource: MCPResourceContent; annotations?: MCPAnnotations }
  | { type: "resource_link"; uri: string; name: string; description?: string; mimeType?: string }

TypeBox Schemas

Both ResponseEnvelopeSchema and ResponseMetaSchema are available for runtime validation:

import { ResponseEnvelopeSchema, ResponseMetaSchema } from "@alkdev/operations";
import { Value } from "@alkdev/typebox/value";

if (Value.Check(ResponseEnvelopeSchema, value)) {
  // valid envelope
}