Skip to main content
Glama

Create client intake

define_intake
Idempotent

Create a new client intake request at project start to collect logos, copy, files, and credentials via a branded portal, with automatic invites and reminders.

Instructions

Create a new client intake request — a branded portal where the client submits logos, copy, files, credentials, and other assets. BriefGate sends the invite email and chases the client automatically until all items are collected.

Call this once at the start of a project, after you know what assets you need. Returns { intake_id, portal_url, status, follow_up }. Save intake_id — you need it for all follow-up calls.

The server cannot notify this conversation when the client finishes (MCP is request/response), so the returned follow_up block describes how completion will be learned:

  • follow_up.recommended = "webhook" — the account has an active webhook endpoint; completion events are delivered there.

  • follow_up.recommended = "schedule" — no endpoint is registered. follow_up.schedule gives the cadence for checking with get_intake_status (every_hours) and the date to stop (until). An account that runs a public HTTPS service can register an endpoint with manage_webhook instead.

Example: { "project_name": "Website for John Finance", "client": { "email": "john@example.com", "name": "John", "language": "cs" }, "due_date": "2026-08-15", "branding": { "accent_color": "#1B2A4A", "sender_name": "Radim" }, "items": [ { "key": "logo", "type": "image", "label": "Company logo", "constraints": { "formats": ["svg","png"], "min_width": 512 } }, { "key": "hero_copy", "type": "longtext", "label": "Homepage headline (2–3 sentences)", "constraints": { "max_chars": 400 } }, { "key": "wp_admin", "type": "secret", "label": "WordPress admin credentials" }, { "key": "photos", "type": "file_list", "label": "Photos (5–10 images)", "constraints": { "formats": ["jpg","png","heic"], "min_count": 5, "max_count": 15 } } ] }

Item types: text, longtext, file, file_list, image, color_list, select (one of options[]), multiselect (several of options[]; min_count/max_count in constraints), boolean, url, secret (encrypted; the value is shown only on the first retrieval), structured (requires schema with JSON Schema).

DECISIONS — questions for the account holder, not the client. An item with assignee="owner" and type select/multiselect is a question only the account holder can answer ("does the discounted plan cost 19 or 29?"). It can carry an optional "proposed" answer, e.g. proposed = { value: "19", rationale: "matches the competitor we benchmarked" }, which is stored separately from the account holder's answer and clearly labelled as a proposal.

get_intake_results returns the current answer with meta..decided_by: "owner" when the account holder answered in the dashboard, "agent_proposal" while only the proposal exists. A proposal cannot be confirmed through this API; only the account holder answers it. Item keys must be snake_case (e.g. "logo", "hero_copy", "ga4_id") — they become property names in get_intake_results.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sendNoWhether to send the invite email immediately. Default: true. Set to false to create a draft and call /v1/intakes/:id/send later.
itemsYesList of assets to collect. Each item has key, type, label, and optional constraints.
clientYesClient contact details.
brandingNoOverride account-level branding for this intake.
due_dateNoDeadline in YYYY-MM-DD format. Shown in the portal and used to escalate chase cadence.
templateNoTemplate slug to pre-populate items (e.g. "restaurant-website", "consulting-firm").
folder_idNoPut this intake in an existing folder from list_folders instead of leaving it unfiled. Folders group intakes by client or project — reuse one for a returning client rather than creating a duplicate with create_folder.
retentionNoHow long BriefGate keeps this intake after it is finished. Default: purged 90 days after the client completes. Use mode "on_delivery" when the intake holds anything sensitive (credentials, personal photos): the contents are then removed shortly after YOU collect them with get_intake_results, because at that point you already have the files and there is no reason for a copy to sit on our server. An intake you never collect still expires on the day count, so this can only ever delete data earlier, never later. Example: { "mode": "on_delivery" } — or { "mode": "days", "days": 7 } to just shorten the window.
email_copyNoYour own subject and intro lines, overriding the built-in translation for this intake. Placeholders: {sender}, {project}, {client}, {count}, {minutes}, {due}. An unknown placeholder is rejected rather than rendered literally to the client. Layout, button and footer stay as they are.
client_briefNoFree-text brief shown to the client at the top of the portal, above the requested items — information from you to them: an offer, instructions, or context for why you are asking for these items. Up to 5000 characters. Documents attached to the brief go through the REST endpoint POST /v1/intakes/:id/brief/files (dashboard or REST — not available through this MCP tool set).
project_nameYesHuman-readable project name shown in the invite email and portal heading.
chase_at_timeNoLocal time of day to send reminders at, "HH:MM" in the client's timezone (e.g. "07:00"). Anchors the cadence to a clock time instead of counting from the invite, and needs an interval measured in whole days. Naming a time deliberately overrides quiet hours, so "07:00" stays 07:00.
max_remindersNoReminders to send before the intake is marked stalled and handed back to you (default 3). An integer from 1 to 1000, or the string "unlimited" to keep reminding until the client finishes. Raise it for a rapid cadence, which would otherwise exhaust three attempts in minutes. A bounce or spam complaint always cancels the remaining reminders, whatever this is set to.
chase_intervalNoHow often to remind, only with chase_schedule="custom". Pair with chase_interval_unit. Defaults to every 3 days when omitted. The interval must work out to at least 5 minutes and at most 90 days.
chase_scheduleNoAutomated reminder cadence. default=T+2d,T+5d,T+9d,weekly. gentle=T+3d,T+8d,biweekly. aggressive=T+1d,T+3d,T+5d,every-other-day. custom=every chase_interval chase_interval_unit. off=no auto reminders.
auto_approve_hoursNoHours after submission before an item is auto-approved without agent review. Default: 72. Set to 0 to require explicit approval.
chase_interval_unitNoUnit for chase_interval. Defaults to "days".
respect_quiet_hoursNoHold reminders to the client's 08:00-19:00 local window (default true). A cadence of minutes or hours pauses overnight and resumes in the morning; set false to send around the clock.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
statusNo
noticesNoCadence caveats, present only when chase_schedule="custom" makes them relevant.
follow_upNoHow to learn this intake is done — present unless a webhook already covers it. Mirrors FollowUpAdvice in client.ts.
intake_idNo
portal_urlNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv0.10.5
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "properties": {
      +    "follow_up": {
      +      "description": "How to learn this intake is done — present unless a webhook already covers it. Mirrors FollowUpAdvice in client.ts.",
      +      "properties": {
      +        "reason": {
      +          "type": "string"
      +        },
      +        "recommended": {
      +          "enum": [
      +            "webhook",
      +            "schedule"
      +          ],
      +          "type": "string"
      +        },
      +        "schedule": {
      +          "properties": {
      +            "check_with": {
      +              "type": "string"
      +            },
      +            "every_hours": {
      +              "type": "number"
      +            },
      +            "until": {
      +              "type": "string"
      +            }
      +          },
      +          "type": "object"
      +        },
      +        "webhook": {
      +          "properties": {
      +            "active_endpoints": {
      +              "type": "number"
      +            },
      +            "events": {
      +              "items": {
      +                "type": "string"
      +              },
      +              "type": "array"
      +            },
      +            "register_with": {
      +              "type": "string"
      +            }
      +          },
      +          "type": "object"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "intake_id": {
      +      "type": "string"
      +    },
      +    "notices": {
      +      "description": "Cadence caveats, present only when chase_schedule=\"custom\" makes them relevant.",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    "portal_url": {
      +      "type": "string"
      +    },
      +    "status": {
      +      "enum": [
      +        "draft",
      +        "sent",
      +        "in_progress",
      +        "completed",
      +        "archived"
      +      ],
      +      "type": "string"
      +    }
      +  },
      +  "type": "object"
      +}
  2. Changed7 schema fields changedv0.9.0
    • addedInput schema / properties / client / properties / also_notify
      Added value: +{
      +  "description": "Other people who should receive the same invitation and the same reminders, through the same portal link — two directors of one company, say, where it does not matter which of them supplies the material. Each address gets its own message (nobody sees the others) and its own bounce state, so one dead address does not stop the rest being chased. At most 4, on top of the primary client.",
      +  "items": {
      +    "properties": {
      +      "email": {
      +        "description": "Their email address.",
      +        "type": "string"
      +      },
      +      "name": {
      +        "description": "Their name, used to address their copy.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "email"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedInput schema / properties / client / properties / name / description
      Previous value: -"Client name for personalised emails."New value: +"Client name (required). Every email opens by addressing them by name, so a blank one sends \"Hello,\" to someone being asked for their admin password."
    • changedInput schema / properties / client / required
      Previous value: -[
      -  "email"
      -]New value: +[
      +  "email",
      +  "name"
      +]
    • addedInput schema / properties / client_brief
      Added value: +{
      +  "description": "Free-text brief shown to the client at the top of the portal, above the requested items — information from you to them: an offer, instructions, or context for why you are asking for these items. Up to 5000 characters. Documents attached to the brief go through the REST endpoint POST /v1/intakes/:id/brief/files (dashboard or REST — not available through this MCP tool set).",
      +  "maxLength": 5000,
      +  "type": "string"
      +}
    • addedInput schema / properties / folder_id
      Added value: +{
      +  "description": "Put this intake in an existing folder from list_folders instead of leaving it unfiled. Folders group intakes by client or project — reuse one for a returning client rather than creating a duplicate with create_folder.",
      +  "type": "string"
      +}
    • addedInput schema / properties / items / items / properties / assignee
      Added value: +{
      +  "description": "Who owes this. \"client\" (the default) is something the client fills in through the portal. \"owner\" is a private to-do for the account holder, e.g. \"call the client\": it never appears in the client portal, is never mentioned in a reminder, and never holds up completion of the intake. Use type \"boolean\" for a plain tick-off task. Owner items cannot use type file, file_list, image or secret.",
      +  "enum": [
      +    "client",
      +    "owner"
      +  ],
      +  "type": "string"
      +}
    • changedInput schema / properties / items / items / properties / type / enum
      Previous value: -[
      -  "text",
      -  "longtext",
      -  "file",
      -  "file_list",
      -  "image",
      -  "color_list",
      -  "select",
      -  "boolean",
      -  "url",
      -  "secret",
      -  "structured"
      -]New value: +[
      +  "text",
      +  "longtext",
      +  "file",
      +  "file_list",
      +  "image",
      +  "color_list",
      +  "select",
      +  "multiselect",
      +  "boolean",
      +  "url",
      +  "secret",
      +  "structured"
      +]
  3. First observedv0.2.1

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=true, openWorldHint=true), but the description goes much further: it discloses the MCP request/response limitation, the two follow_up outcomes (webhook vs schedule with cadence and stop date), the secrecy rule for type 'secret', and that owner items never appear in the client portal or block completion. This is exactly the behavioral context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well front-loaded — purpose, when to call, return shape, and the follow_up model come before the long example and type glossary. It is long, and the item-type list plus the DECISIONS paragraph restate portions of the schema (enum values, constraints), which is some duplication, but the structural headers and example make it navigable rather than bloated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need no prose, and the description still explains the one thing the schema cannot: how completion is learned given MCP's request/response nature, including the follow_up.recommended branch and the until/every_hours cadence. Given 18 parameters and nested objects, this is complete enough for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% across 18 parameters, so the baseline is 3, but the description adds real semantic value beyond it: the enumerated item types with parenthetical meanings, the DECISIONS concept (assignee=owner + select becomes an owner-only question with an optional 'proposed' answer), and the meta.<key>.decided_by values returned by get_intake_results. The worked JSON example and snake_case key rule with an explicit reason ('become property names in get_intake_results') reinforce this.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource and a concrete scope: 'Create a new client intake request — a branded portal where the client submits logos, copy, files, credentials.' The follow-on sentence about BriefGate sending the invite and chasing the client differentiates it from siblings like update_intake and add_items without needing to name them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States the trigger condition explicitly ('Call this once at the start of a project, after you know what assets you need') and routes to an alternative for the webhook gap ('an account that runs a public HTTPS service can register an endpoint with manage_webhook instead'). Both when-to-use and the alternative path are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.