Envelope contract¶
Every MCP tool in the suite returns a uniform shape:
class Envelope[T]:
status: Literal["ok", "error"]
data: T | None
warnings: list[str]
metadata: dict[str, Any] # tool_version, runtime_sec, etc.
error: str | None
Why a uniform shape¶
Predictability matters more than minimalism here. An LLM agent calls forty different tools across three servers and needs a contract it can rely on for routing logic ("did the call succeed?", "what's the runtime?", "are there warnings I should propagate?"). The envelope gives it that without per-tool special cases.
Construction helpers¶
Structured response envelope for every MCP tool in the suite.
Every tool returns the same shape so agents (and humans) can rely on a
predictable contract: status, data, warnings, and
metadata. When a tool fails, status="error" and error is
populated with a human-readable message; data is None.
Envelope
¶
Bases: BaseModel, Generic[T]
Uniform tool response.
Tools should never raise to the MCP transport layer. They catch
their own exceptions and convert to error() envelopes so the
agent can reason about the failure.
Timer()
¶
ok(data, *, warnings=None, metadata=None, tool_version=_DEFAULT_TOOL_VERSION, runtime_sec=None)
¶
Build a successful envelope.
Source code in packages/rf-mcp-common/src/rf_mcp_common/envelope.py
error(message, *, warnings=None, metadata=None, tool_version=_DEFAULT_TOOL_VERSION)
¶
Build a failure envelope with a human-readable message.
Returns Envelope[Any] rather than Envelope[None]: a failure
carries data=None regardless of what the tool would have returned
on success, so the envelope has to be assignable to every tool's
declared Envelope[X] return type.