MCP Tools Reference
BriefGate ships as an MCP server so coding agents can orchestrate client intake without leaving their context. All 7 tools map 1:1 to REST endpoints under https://api.briefgate.dev/v1/. Install the server with npm install -g @briefgate/mcp and configure your API key as described in quickstart.md.
define_intake
Creates a new intake and immediately sends the client an email with their portal link.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
project_name |
string | Yes | Human-readable project title shown in the portal and all emails. |
client.email |
string | Yes | Client's email address. |
client.name |
string | No | Client's display name, used in greeting lines. |
client.language |
string | No | BCP 47 language code for the portal UI and emails (default: en). |
items |
array | Yes | Ordered list of item definitions. See item-types.md. |
chase_schedule |
string | No | One of default, gentle, aggressive (default: default). |
due_date |
string | No | ISO 8601 date. Shown in the portal and email subject. |
send |
boolean | No | Set to false to create a draft without emailing the client. Call add_items or POST /v1/intakes/:id/send to send later. Default: true. |
retention |
object | No | { mode: "days"|"on_delivery", days?: number, anonymize?: boolean }. Default: purge 90 days after intake.completed. Use mode: "on_delivery" for intakes containing credentials — contents are removed ~24 h after you call get_intake_results. |
Example — restaurant website project
{
"project_name": "Bella Napoli — Website",
"client": {
"email": "[email protected]",
"name": "Marco Esposito",
"language": "en"
},
"items": [
{
"key": "logo",
"label": "Restaurant logo",
"help": "SVG or PNG with transparent background, minimum 512px.",
"type": "image",
"required": true,
"constraints": {
"formats": ["svg", "png"],
"min_width": 512,
"transparent_background": true
}
},
{
"key": "brand_colors",
"label": "Brand colors",
"help": "Pick the primary and secondary brand colors.",
"type": "color_list",
"required": true
},
{
"key": "hero_copy",
"label": "Hero tagline",
"type": "longtext",
"required": true,
"constraints": { "max_chars": 400 }
},
{
"key": "has_existing_site",
"label": "Do you have an existing website?",
"type": "boolean",
"required": true
},
{
"key": "existing_site_url",
"label": "Existing website URL",
"help": "Only required if you answered Yes above.",
"type": "url",
"required": false
},
{
"key": "platform",
"label": "Preferred platform",
"type": "select",
"required": true,
"options": [
{ "value": "wordpress", "label": "WordPress" },
{ "value": "webflow", "label": "Webflow" },
{ "value": "custom", "label": "Custom / I'm not sure" }
]
},
{
"key": "cms_password",
"label": "Admin credentials",
"help": "Existing CMS admin login (if migrating). Stored encrypted, one-time reveal.",
"type": "secret",
"required": false
},
{
"key": "opening_hours",
"label": "Opening hours",
"type": "structured",
"required": true,
"schema": {
"type": "object",
"required": ["mon_fri", "sat", "sun"],
"properties": {
"mon_fri": { "type": "string" },
"sat": { "type": "string" },
"sun": { "type": "string" }
}
}
}
],
"chase_schedule": "default"
}Response
{
"intake_id": "in_8f3kQmR2",
"portal_url": "https://app.briefgate.dev/portal/in_8f3kQmR2",
"status": "sent",
"items": [
{ "key": "logo", "status": "pending" },
{ "key": "brand_colors","status": "pending" }
]
}get_intake_status
Returns a lightweight snapshot of the intake's current state: which items are complete, which are pending, and the full chase history. Prefer this over get_intake_results when you only need to check progress.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
intake_id |
string | Yes | The intake_id returned by define_intake. |
Response
{
"status": "in_progress",
"due_date": "2024-04-01",
"client_last_seen": "2024-03-16T14:05:33Z",
"progress": {
"submitted": 5,
"total": 8,
"outstanding": 3,
"percent": 62
},
"items": [
{ "key": "logo", "status": "approved", "submitted_at": "2024-03-16T10:00:00Z", "label": "Restaurant logo" },
{ "key": "brand_colors", "status": "approved", "submitted_at": "2024-03-16T10:05:00Z", "label": "Brand colors" },
{ "key": "hero_copy", "status": "needs_revision", "submitted_at": "2024-03-16T10:10:00Z", "label": "Hero tagline" },
{ "key": "has_existing_site","status": "approved", "submitted_at": "2024-03-16T10:15:00Z", "label": "Do you have an existing website?" },
{ "key": "existing_site_url","status": "approved", "submitted_at": "2024-03-16T10:15:00Z", "label": "Existing website URL" },
{ "key": "platform", "status": "approved", "submitted_at": "2024-03-16T10:20:00Z", "label": "Preferred platform" },
{ "key": "cms_password", "status": "pending", "submitted_at": null, "label": "Admin credentials" },
{ "key": "opening_hours", "status": "pending", "submitted_at": null, "label": "Opening hours" }
],
"chases": [
{ "channel": "email", "sent_at": "2024-03-17T09:00:00Z", "status": "sent", "attempt_no": 1 },
{ "channel": "email", "sent_at": "2024-03-20T09:00:00Z", "status": "sent", "attempt_no": 2 },
{ "channel": "email", "sent_at": null, "status": "scheduled", "attempt_no": 3 }
]
}Item statuses
| Status | Meaning |
|---|---|
pending |
Not yet submitted by client. |
submitted |
Uploaded or filled in; awaiting agent review or auto-approval. |
needs_revision |
Agent requested a revision via request_revision. |
approved |
Accepted (explicitly or via 72-hour auto-approval). |
get_intake_results
Returns the typed content of all approved (or all submitted) items. Use this once the intake is complete, or incrementally as items are approved using only_new: true.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
intake_id |
string | Yes | The intake to retrieve results from. |
only_new |
boolean | No | If true, returns only items approved since the last call. Useful for streaming incremental processing. |
include_pending |
boolean | No | If true, also returns items that are submitted but not yet approved. |
Response
{
"intake_id": "in_8f3kQmR2",
"status": "completed",
"results": {
"logo": {
"url": "https://files.briefgate.dev/in_8f3kQmR2/logo.png?token=sig_abc&expires=1710615600",
"filename": "bella-napoli-logo.png",
"mime": "image/png",
"width": 1024,
"height": 512,
"size": 48210
},
"brand_colors": ["#1B2A4A", "#E8E2D9", "#C8382E"],
"hero_copy": "Since 1987, handcrafted Neapolitan pizza in the heart of the city. Come hungry, leave happy.",
"has_existing_site": true,
"existing_site_url": "https://old.bellanapoli.com",
"platform": "wordpress",
"cms_password": {
"value": "admin:s3cr3tP@ssw0rd",
"one_time": true,
"first_reveal": true,
"expires_at": "2024-04-15T10:22:00Z"
},
"opening_hours": {
"mon_fri": "12:00-22:00",
"sat": "12:00-23:00",
"sun": "13:00-21:00"
}
}
}Notes on specific types:
- Images and files —
urlis a signed URL with 24-hour validity. Fetch it promptly or re-request results to get a fresh URL. - Secrets — the
valuefield contains the decrypted plaintext on the first call only (first_reveal: true). On all subsequent callsvalueis absent. Store the secret immediately. Auto-expire after 30 days. Requires thesecrets:readoradminscope on the API key.
request_revision
Marks an item as needs_revision and sends the client an email notification explaining what needs to be fixed. The item returns to pending on the client's side, and the cycle restarts.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
intake_id |
string | Yes | The intake containing the item. |
item_key |
string | Yes | The key of the item to revise (e.g. "logo"). |
note |
string | Yes | Human-readable explanation sent to the client. Be specific. |
Example
{
"intake_id": "in_8f3kQmR2",
"item_key": "logo",
"note": "The logo appears to be exported at 320px. Please re-export at a minimum of 512px on the shortest side, ideally as an SVG vector file."
}Response
{
"intake_id": "in_8f3kQmR2",
"item_key": "logo",
"status": "needs_revision",
"client_notified": true
}The client receives an email with your note. Their portal highlights the flagged item. When they resubmit, the item transitions back to submitted and the 72-hour auto-approval timer resets.
send_chase
Manually triggers a chase message outside the automatic schedule. Use this to escalate to SMS after emails have bounced, or to send a personal nudge before a deadline.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
intake_id |
string | Yes | The intake to chase. |
channel |
string | No | "email" or "sms". Defaults to "email". SMS requires a phone number on the account or on the client record. |
Example
{
"intake_id": "in_8f3kQmR2",
"channel": "sms"
}Response
{
"intake_id": "in_8f3kQmR2",
"channel": "sms",
"sent_at": "2024-03-22T08:15:00Z"
}When to use this tool
- The deadline is tomorrow and the client has not responded to the automatic emails.
- Email bounced (you will see this in the chase array from
get_intake_status) and you want to try SMS. - The client is unresponsive after the automatic email chain and you want to escalate to SMS.
list_intakes
Returns a paginated list of intakes, optionally filtered by status or client email. Useful for building dashboards or checking which projects need attention.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status |
string | No | Filter by intake status: draft, sent, in_progress, completed, archived. |
client_email |
string | No | Filter to intakes belonging to a specific client. |
limit |
integer | No | Number of results per page (default 20, max 100). |
offset |
integer | No | Pagination offset (default 0). |
Response
{
"total": 47,
"intakes": [
{
"id": "in_8f3kQmR2",
"projectName": "Bella Napoli — Website",
"clientEmail": "[email protected]",
"status": "in_progress",
"createdAt": "2024-03-15T10:22:00Z"
},
{
"id": "in_4p2nWxY7",
"projectName": "Green Leaf Cafe — Rebrand",
"clientEmail": "[email protected]",
"status": "completed",
"createdAt": "2024-03-10T09:00:00Z"
}
]
}add_items
Appends new items to an existing intake that has already been sent. The client receives a notification that new items have been added. Use this when scope expands after the initial intake is live.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
intake_id |
string | Yes | The intake to extend. |
items |
array | Yes | Array of item definitions in the same format used in define_intake. |
Example — adding a favicon request after the initial intake was sent
{
"intake_id": "in_8f3kQmR2",
"items": [
{
"key": "favicon",
"label": "Favicon",
"help": "A square icon at least 32x32px, ideally 512x512px. Used in browser tabs and bookmarks.",
"type": "image",
"required": true,
"constraints": {
"formats": ["png", "svg"],
"min_width": 32,
"min_height": 32
}
}
]
}Response
{
"intake_id": "in_8f3kQmR2",
"items_added": [
{ "key": "favicon", "status": "pending" }
]
}The client's portal immediately shows the new item.
Idempotency
Network errors can cause define_intake to be called twice, which would send the client two emails and create two intakes. The MCP package automatically derives a stable idempotency key from the project_name, client.email, and a hash of the items array — retrying with identical arguments returns the original response without creating a second intake.
When calling the REST API directly, pass an Idempotency-Key header:
curl -X POST https://api.briefgate.dev/v1/intakes \
-H "Authorization: Bearer bg_live_xxxxx" \
-H "Idempotency-Key: bella-napoli-2024-01" \
-H "Content-Type: application/json" \
-d '{ ... }'If the key was seen before, BriefGate returns the original response unchanged (HTTP 200, not 201). Keys expire after 24 hours.
Test mode
API keys prefixed with bg_test_ activate sandbox mode:
- Emails are routed to a sandbox provider (visible in the BriefGate dashboard under Test Inbox) and never delivered to real addresses.
- SMS is silently dropped.
- Webhooks fire normally against your configured endpoint, so you can test your webhook handler end-to-end.
- File uploads are accepted and stored temporarily but are purged after 7 days.
Switch to a bg_live_ key before going to production.
Tool call example in Claude Code
When Claude Code invokes a BriefGate tool, the underlying MCP call looks like this:
{
"type": "tool_use",
"id": "toolu_01XyzAbc",
"name": "briefgate__define_intake",
"input": {
"project_name": "Bella Napoli — Website",
"client": {
"email": "[email protected]",
"name": "Marco Esposito",
"language": "en"
},
"items": [
{
"key": "logo",
"label": "Restaurant logo",
"type": "image",
"required": true,
"constraints": {
"formats": ["svg", "png"],
"min_width": 512
}
}
],
"chase_schedule": "default"
}
}The tool name is prefixed with the MCP server name (briefgate__). Claude Code handles the JSON serialization and transport automatically — you just describe what you need in natural language and the agent constructs the call.