@zooly/mcp-client holds the React pieces of the Zooly MCP connector's consent step: the screen that asks a signed-in person to let an AI client call Zooly tools on their behalf, and its Authorize / Deny controls. It also holds the two other React surfaces the MCP flow renders outside the chat — the demo creator-agreement sheet the campaign's agreement card opens, and the admin scenario-catalog screen. Refusing is a first-class decision — Deny sends the client a clean OAuth error instead of leaving a popup stranded.
Like the other client packages it is pure, framework-agnostic React with Tailwind classes, and every state is driven by props.
@zooly/mcp-clientpackages/mcp/clientapps/zooly-app/app/authorize/page.tsx, the mcp-demo/agreement/[creatorId] page, and /admin/scenarios| Export | Purpose |
|---|---|
McpConsentScreen | The consent screen. Props: params (the OAuth query params, passed through verbatim), sessionEmail, clientName, and error (renders the error instead of the form). |
McpAuthorizeButton | The approve/deny controls. Props: params, disabledReason. |
McpCreatorAgreement | The demo agreement/checkout sheet behind the campaign agreement card. Props: creatorId (from the path) and query (the page's search params, verbatim — the tool wrote them into the link). A demo prop, not a product surface: nothing is charged and no signature is stored. |
ScenarioCatalog | The admin scenario-catalog screen (/admin/scenarios): list versions, edit drafts, publish, disable, create empty or copy. |
McpConsentScreenProps, McpAuthorizeButtonProps, McpCreatorAgreementProps | Prop types. |
auth.zooly.ai with returnTo. The screen only renders what it is given./api/oauth/authorize with action: "approve" | "deny", then follow the redirectUrl the route returns (the client's callback, with ?code=… or ?error=access_denied).mcp-consent-screen, mcp-consent-error, mcp-authorize, mcp-authorize-button, mcp-deny-button, mcp-authorize-disabled, mcp-authorize-error.@zooly/mcp-srvdocs/mcp/zly-1963-chatgpt-mcp-demo.md