{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://a2ui.org/specification/v1_0/catalogs/mcp/catalog.json",
  "protocolVersion": "1.0",
  "title": "A2UI MCP Catalog",
  "description": "A2UI catalog for Model Context Protocol (MCP) integrations. It defines the `callMcpTool` function, the data functions that turn a tool result into data model updates, and the `McpApp` component that renders a sandboxed MCP App connected to the host through the MCP Apps bridge.",
  "catalogId": "https://a2ui.org/specification/v1_0/catalogs/mcp/catalog.json",
  "components": {
    "McpApp": {
      "type": "object",
      "description": "Renders a sandboxed Model Context Protocol application using double-iframe isolation. The application talks to the host over the MCP Apps JSON-RPC bridge; tool calls it is allowed to make are dispatched as A2UI actions.",
      "properties": {
        "component": {
          "const": "McpApp"
        },
        "htmlContent": {
          "$ref": "common_types.json#/$defs/DynamicString",
          "description": "The HTML content of the app, rendered via srcdoc inside the sandbox. A value prefixed with `url_encoded:` is decoded with decodeURIComponent before rendering."
        },
        "title": {
          "$ref": "common_types.json#/$defs/DynamicString",
          "description": "The title of the app, used as the accessible title of the frame."
        },
        "allowedTools": {
          "type": "array",
          "description": "The names of the MCP tools the app is allowed to call. The host dispatches an authorized `tools/call` request as an A2UI action named after the tool, with the tool arguments as its context, and rejects any other tool call.",
          "items": {
            "type": "string"
          }
        },
        "allowedFunctions": {
          "type": "object",
          "description": "A map of authorized host client function names to JSON Schemas describing their expected arguments. The host rejects a `ui/requests/function-call` request whose function is not listed or whose arguments fail validation. The functions must exist in the surface's catalog.",
          "additionalProperties": {
            "type": "object",
            "description": "A JSON Schema. The host validates the matching payload against it before acting on the message; an empty object accepts any value."
          }
        },
        "data": {
          "type": "object",
          "description": "Data binding configuration for the component. Reserved keys `toolInput`, `toolResult`, and `modelContext` map to standard MCP Apps `ui/notifications/tool-input`, `ui/notifications/tool-result`, and `ui/update-model-context` messages.",
          "properties": {
            "paths": {
              "type": "object",
              "description": "A dictionary mapping custom state keys (or reserved keys `toolInput`, `toolResult`, `modelContext`) to distinct JSON Pointer paths in the data model. The host pushes a `ui/notifications/data-model-update` notification whenever a bound value changes and writes authorized `ui/notifications/data-model-change` notifications back to the path.",
              "additionalProperties": {
                "type": "string"
              }
            }
          },
          "required": ["paths"],
          "additionalProperties": false
        },
        "csp": {
          "type": "object",
          "description": "Per-resource Content Security Policy domain allowlists from `_meta.ui.csp`.",
          "properties": {
            "connectDomains": {
              "type": "array",
              "description": "Origins allowed in `connect-src` (fetch, XHR, WebSocket).",
              "items": {
                "type": "string"
              }
            },
            "resourceDomains": {
              "type": "array",
              "description": "Origins allowed for scripts, styles, images, fonts, and media.",
              "items": {
                "type": "string"
              }
            },
            "frameDomains": {
              "type": "array",
              "description": "Origins allowed for nested iframes (`frame-src`).",
              "items": {
                "type": "string"
              }
            },
            "baseUriDomains": {
              "type": "array",
              "description": "Origins allowed for document `base-uri`.",
              "items": {
                "type": "string"
              }
            }
          },
          "additionalProperties": false
        },
        "permissions": {
          "type": "object",
          "description": "Browser capability permissions delegated to the inner sandboxed iframe from `_meta.ui.permissions`.",
          "properties": {
            "camera": {
              "type": ["boolean", "object"],
              "description": "Delegates `camera` access via the iframe `allow` attribute."
            },
            "microphone": {
              "type": ["boolean", "object"],
              "description": "Delegates `microphone` access via the iframe `allow` attribute."
            },
            "geolocation": {
              "type": ["boolean", "object"],
              "description": "Delegates `geolocation` access via the iframe `allow` attribute."
            },
            "clipboardWrite": {
              "type": ["boolean", "object"],
              "description": "Delegates `clipboard-write` access via the iframe `allow` attribute."
            }
          },
          "additionalProperties": false
        }
      },
      "required": ["component", "htmlContent"]
    }
  },
  "functions": {
    "callMcpTool": {
      "type": "object",
      "description": "Invokes a tool on a connected Model Context Protocol (MCP) server and returns a payload with `toolName`, `toolInput`, `toolResult` (the raw result), `structuredContent` (when the server sends one), `text` (the text blocks joined with newlines) and `json` (the parsed value of `text` when it is a JSON object or array; otherwise, for a result with several text blocks, the array of the parsed values of the blocks that are JSON, absent when none is), plus `resourceUri`, `html`, `csp` and `permissions` when the result has an MCP App resource. A result flagged `isError` fails the call and writes nothing.",
      "returnType": "any",
      "properties": {
        "@call": {
          "const": "callMcpTool"
        },
        "args": {
          "type": "object",
          "properties": {
            "name": {
              "$ref": "common_types.json#/$defs/DynamicString",
              "description": "The name of the MCP tool to execute."
            },
            "arguments": {
              "type": "object",
              "description": "The arguments to pass to the MCP tool: an object of dynamic values, or a function call that returns one.",
              "additionalProperties": {
                "$ref": "common_types.json#/$defs/DynamicValue"
              }
            },
            "targetDataPath": {
              "$ref": "common_types.json#/$defs/DynamicString",
              "description": "Optional JSON Pointer path on the surface data model where the payload of each successful call is written, replacing the object at that path. A call whose response arrives after a newer call to the same path has started does not write, so the latest call wins."
            }
          },
          "required": ["name"],
          "additionalProperties": false
        }
      },
      "required": ["@call", "args"]
    },
    "transformData": {
      "type": "object",
      "description": "Evaluates a JMESPath expression (https://jmespath.org/specification.html) against `data`. Standard JMESPath only, no extensions.",
      "returnType": "any",
      "properties": {
        "@call": {
          "const": "transformData"
        },
        "args": {
          "type": "object",
          "properties": {
            "jmespath": {
              "$ref": "common_types.json#/$defs/DynamicString",
              "description": "A JMESPath expression (https://jmespath.org/specification.html) evaluated against `data`. Standard JMESPath only, no extensions."
            },
            "data": {
              "$ref": "common_types.json#/$defs/DynamicValue",
              "description": "The input data to evaluate the expression against."
            }
          },
          "required": ["jmespath", "data"],
          "additionalProperties": false
        }
      },
      "required": ["@call", "args"]
    },
    "updateDataModel": {
      "type": "object",
      "description": "Writes key-value pairs to the surface data model.",
      "returnType": "any",
      "properties": {
        "@call": {
          "const": "updateDataModel"
        },
        "args": {
          "type": "object",
          "properties": {
            "updates": {
              "$ref": "common_types.json#/$defs/DynamicValue",
              "description": "An object mapping data model paths to the values to write (e.g., {\"/entries\": [...], \"/title\": \"Home\"}). Paths starting with \"/\" are absolute; relative paths resolve against the current data context."
            }
          },
          "required": ["updates"],
          "additionalProperties": false
        }
      },
      "required": ["@call", "args"]
    },
    "split": {
      "type": "object",
      "description": "Splits a string into an array of substrings using a literal separator.",
      "returnType": "any",
      "properties": {
        "@call": {
          "const": "split"
        },
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "common_types.json#/$defs/DynamicValue",
              "description": "The string or array of strings to split."
            },
            "separator": {
              "$ref": "common_types.json#/$defs/DynamicString",
              "description": "The delimiter string to split on. An empty string splits into individual characters (Unicode code points)."
            }
          },
          "required": ["value", "separator"],
          "additionalProperties": false
        }
      },
      "required": ["@call", "args"]
    },
    "regexCapture": {
      "type": "object",
      "description": "Extracts capture groups from the first regular expression match.",
      "returnType": "any",
      "properties": {
        "@call": {
          "const": "regexCapture"
        },
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "common_types.json#/$defs/DynamicValue",
              "description": "The string or array of strings to match against."
            },
            "pattern": {
              "$ref": "common_types.json#/$defs/DynamicString",
              "description": "A regular expression in the A2UI regex dialect: a portable subset of ECMAScript pattern syntax in Unicode mode with no flags. Returns an array of capture groups from the first match, or null if there is no match. Unmatched optional groups return empty strings."
            }
          },
          "required": ["value", "pattern"],
          "additionalProperties": false
        }
      },
      "required": ["@call", "args"]
    }
  },
  "$defs": {
    "anyComponent": {
      "oneOf": [
        {
          "$ref": "#/components/McpApp"
        }
      ],
      "discriminator": {
        "propertyName": "component"
      }
    },
    "anyFunction": {
      "oneOf": [
        {
          "$ref": "#/functions/callMcpTool"
        },
        {
          "$ref": "#/functions/transformData"
        },
        {
          "$ref": "#/functions/updateDataModel"
        },
        {
          "$ref": "#/functions/split"
        },
        {
          "$ref": "#/functions/regexCapture"
        }
      ]
    }
  }
}
