What the policy touches¶
3.1 Data paths¶
The layer (cloudg/mcp/layer.py) runs the caller's output pipeline over everything that carries data out, and the input pipeline over everything that carries data in. Every adapter (native, mcp SDK, fastmcp) goes through the layer, so the transport makes no difference.
| Direction | Path | What is transformed |
|---|---|---|
| out | Tool result returned as a plain value (the catalog's case) | The JSON-ready value, as structuredContent. The text content is rendered from the transformed value. |
| out | Tool result returned as a ToolResult |
structured, each TextContent.text, the text of each EmbeddedResource holding TextResourceContents, each ResourceLink (uri, name, title, description), and result.meta as a whole. |
| out | Resource links attached through ctx.links |
uri, name, title, description. |
| out | Tool errors | The message text of every isError result (handler exceptions, NotFoundError, access denials, rate limits, bad arguments) and its _meta["cloudg/error_data"]. |
| out | Resource reads | JSON values and plain strings; for handlers that return TextResourceContents, each item's text. |
| out | Prompts | Each message's TextContent.text, the text of an EmbeddedResource holding TextResourceContents, and ResourceLink fields. |
| out | Completions | Each suggested value, wrapped as {<argument name>: value} before the pipeline runs so that key rules recognise it (a bare list of strings has no keys, and names are only caught by key rules). |
| in | Tool arguments | The whole arguments object, recursively. |
| in | Resource template variables | The variables parsed from the URI (so cloudg://assets/<pseudonymised ARN> resolves). |
| in | Prompt arguments | All arguments. |
| in | Completions | The partial value and the context arguments. |
What is not transformed:
- Binary resource contents (
BlobResourceContents) and image content. - Tool, resource and prompt definitions: names, descriptions, input schemas, annotations, and the server
instructions. These come from code, never from cloud data. - The prompt result's
descriptionfield. - Layer bookkeeping in
_meta:cloudg/transforms(added after the pipeline ran),cloudg/duration_ms,cloudg/error_code,cloudg/cache,cloudg/retries. - Keys the redactor skips by default:
_meta,_annotations,cursor,next_cursor.
3.2 outputSchema is withheld¶
Masking, dropping and projection change the shape of structuredContent, and MCP clients reject a result that does not validate against the tool's advertised outputSchema. CloudGMCPLayer.tools_wire() therefore leaves outputSchema out of a tool's tools/list entry whenever that caller's output pipeline for the tool is non-empty. In practice the schema is advertised only under open, or for a tool whose transform_hints skip every transform (preview_transform). Measured on the catalog, get_asset carries an outputSchema under open and none under any other built-in profile.
3.3 The life of a tool call¶
get_tool(name, principal)looks the tool up. If the policy denies it andhide_deniedis true, the call fails withUnknown tool: <name>(a protocol error, code -32602), exactly as if the tool did not exist. The policy records the attempt as anot_founddecision (section 15.1).- The middleware chain runs, outermost first (with
cloudg mcp serve: the audit log, metrics, the concurrency limit and the cache, each when configured). Resource reads, prompts and completions go through the same chain. policy.check_call()decides access, applies rate limits and records the decision (section 7, 9, 15). A denial or rate limit becomes anisErrorresult.- The input pipeline runs over the arguments: secret guard first, then the depseudonymiser. If it refuses the call, the decision recorded in step 3 is changed to
rejected. - Arguments are validated against the handler signature.
- The handler runs (sync handlers in a worker thread) under the tool's timeout.
- The output pipeline runs over the result. The text rendering is capped at
max_output_chars(200,000 by default) with... [truncated by cloudg mcp layer]. - Attached resource links are transformed and appended.
- The transform report is attached as
_meta["cloudg/transforms"].
Resource reads and prompts follow the same order, except that a denied resource or prompt raises instead of returning an isError result.
When cloudg mcp serve stops, it calls policy.save_vault() so that pseudonyms issued during the session are written to the vault file, if the policy has one (section 13.5).