@briefgate/mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| BRIEFGATE_API_KEY | Yes | API key (`bg_live_...` or `bg_test_...`). Obtain from the BriefGate dashboard. | |
| BRIEFGATE_BASE_URL | No | Override for staging or local development. | https://api.briefgate.dev |
| BRIEFGATE_MCP_HTTP | No | Set to `1` to start Streamable HTTP instead of stdio. | |
| BRIEFGATE_MCP_PORT | No | Port for HTTP mode. | 3000 |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| define_intakeA | 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:
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. |
| get_intake_statusA | Check the completion status of a client intake — which items are submitted, pending, or need revision; the history of automated chase emails sent; and when the client last opened the portal. Use this to decide whether to send a manual reminder (send_chase), request a revision (request_revision), or fetch results (get_intake_results). Returns per-item status and chase history. This is also the call a scheduled check should make when no webhook is registered — see follow_up in the define_intake response for the cadence. When status becomes "completed", fetch the results with get_intake_results and carry on with the work that was waiting on them. |
| get_intake_resultsA | Retrieve the typed submitted values from a client intake. Files are returned as signed download URLs that expire after 24 hours. Secrets (type=secret, e.g. passwords, API keys) are decrypted and included only in the first retrieval. Later calls return first_reveal: false in meta and omit the value, so the user should be ready to receive a secret before this tool is called on an intake that contains one. Use only_new=true to get only items submitted since the last call (useful in webhook-driven workflows). Use include_pending=true to also return partially filled items. Returns { results: { : }, meta: { : { type, status, submitted_at, first_reveal? } } }. For a DECISION item (assignee=owner, type select/multiselect), results holds the current answer and meta..decided_by is "owner" (answered by the account holder) or "agent_proposal" (only a proposal exists). Proposals are returned even without include_pending. A proposal does not bump revision, so only_new returns decisions the account holder has answered or changed since the last call. |
| request_revisionA | Ask the client to resubmit a specific item with a note explaining what is wrong. Use this after reviewing get_intake_results and finding an item that does not meet requirements — for example a blurry logo, copy that is too long, or a broken URL. The client is notified automatically and the item status moves to needs_revision. Returns { status: "revision_requested", item_key }. |
| send_chaseA | Send a manual reminder to the client outside the automatic schedule. Use when a deadline is approaching and the client has not responded to automatic reminders, or when you want to send an SMS after email attempts have failed. The automatic chase schedule continues after this call — this is an extra nudge, not a replacement. Returns { sent: true }. |
| list_intakesA | List all intakes in your account, optionally filtered by status, client email, folder, or a text search. Use this to get an overview of active projects, find a specific intake by the client's email when you have lost the intake_id, check how many intakes are currently in progress, or see what's in a folder from list_folders. Returns { intakes: [...], total } where each intake includes intake_id, project_name, status, created_at, due_date, folder_id, and portal_url. |
| add_itemsA | Add new items to an already-sent intake — for example, when you realise mid-project that you also need a favicon, social media assets, or additional credentials. The client is notified about the new items. Existing items and their submitted values are not affected. Returns the updated intake object. Items must follow the same key/type/label rules as define_intake (snake_case keys, type-specific constraints). |
| update_itemA | Change one item on an intake that is already with the client — its type, label, hint, whether it is required, and which file formats it accepts. Reach for this when the field turns out to be the wrong shape: you asked for an image and the client only has their logo as a PDF, or what you asked for as a line of text is really a file. Widening the accepted formats or switching the type unblocks them without adding a duplicate item and waiving the original. The item key cannot be changed — results come back under it, so renaming would break whatever reads them. Add a new item instead. If the client has already answered and the change would make their answer invalid, the call fails and nothing is touched. Repeat it with discard_submitted_value: true to clear the answer and ask them again. A change that leaves their answer valid (a new label, a wider limit) never discards anything. |
| update_intakeA | Change settings on an intake that has already been sent — project name, due date, reminder cadence, quiet hours, which folder it's in, the client brief, or the client's name, phone, language, and timezone. Use this instead of deleting and recreating the intake when a deadline moves or the chase cadence needs to change. If any of chase_schedule, chase_interval, chase_interval_unit, chase_at_time, max_reminders, respect_quiet_hours, due_date, or client.timezone is included, every pending reminder is cancelled and the schedule is re-planned from now — reminders already sent still count toward max_reminders. Raising max_reminders (or setting it to "unlimited") past the number already sent on a stalled intake reactivates it and resumes chasing. The client's e-mail address cannot be changed here — the portal link and login are bound to it. Use manage_recipients to add, remove, or reinstate an address. folder_id moves the intake to a different folder (an id from list_folders); set it to null to remove the intake from any folder. It never touches the chase schedule. client_brief replaces the free-text brief shown to the client above the requested items; set it to null to clear it. Documents attached to the brief are managed via the dashboard or the REST endpoint POST /v1/intakes/:id/brief/files, not through this tool. Fails if the intake is archived. At least one field must be given. Returns the full, updated intake object. |
| manage_recipientsA | Add, remove, or reinstate a person who receives an intake's invite and reminders, alongside or instead of the primary client. action="add" invites another address the same way also_notify does at define_intake time — its own message, its own bounce state; pass name to address it by name. action="remove" stops future reminders to that address. action="reinstate" is for a bounce that was wrong — the person did get the e-mail — and clears the bounce flag so reminders resume; if that address was the only one still being chased, the schedule is re-planned from now. Fails if the address is not on the intake, or — for reinstate — if it never bounced in the first place. |
| manage_webhookA | Register, list, or remove a webhook endpoint: a public HTTPS URL on the user's own service that BriefGate POSTs intake events to, as an alternative to polling get_intake_status. Webhook reference: https://briefgate.dev/docs/webhooks The endpoint must be reachable from the internet over HTTPS. A URL that cannot receive (for example a process that runs only in a local terminal) produces failing deliveries while the intake looks watched, so without such a service polling get_intake_status is the working option. action="create" returns a signing "secret" exactly once. The receiving service needs it to verify the signature on every delivery (verifyWebhookSignature from @briefgate/mcp/webhook), and it cannot be shown again. If it is ever exposed, there is no rotation in place — delete the endpoint and create a new one, which issues a fresh secret. Events: intake.completed (all required items in — the one to act on), item.submitted (a single item arrived), client.viewed (the client opened the portal), chase.bounced (a reminder failed to deliver), intake.overdue (the due date passed with required items outstanding — the one to act on when work is blocked), intake.stalled (fires only when the intake sets max_reminders; without it this event never arrives). |
| list_foldersA | List the folders in your account, used to group intakes by client or project. Call this before create_folder or before setting folder_id on define_intake, update_intake, or list_intakes — reuse an existing folder for a returning client instead of creating a duplicate. Returns { folders: [{ id, name, sort_order, intake_count, created_at }] }. |
| create_folderA | Create a new folder to group intakes, e.g. one per client. Call list_folders first and reuse a matching folder — only create one when none of the existing folders fits. Fails with folder_exists if a folder with this name already exists; use list_folders to find it instead. Returns the created folder { id, name, sort_order, intake_count, created_at }. |
| loginA | Sign in without pasting an API key, the same way Call this whenever a tool reports "Not signed in" or that the stored key was revoked or expired. This is a TWO-PHASE tool because approval can take minutes — longer than a single tool call should block for:
Do not wait silently for minutes on one call — call this tool again after telling the user to approve, and again if they say they've clicked Allow. Has no effect if a key is already supplied via the |
| logoutA | Remove the API key |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 15 tools
Most tools have clearly distinct purposes tied to specific resources (intake status vs results, add_items vs update_item vs update_intake), and transitions are documented. Minor potential confusion between get_intake_status and get_intake_results, and the two generic 'manage_*' tools, but descriptions resolve these well.
Predominantly consistent snake_case verb_noun pattern (define_intake, list_intakes, update_item, request_revision, create_folder). Deviations are minor: login/logout lack a noun, and verbs vary slightly (define_ vs create_, get_ vs list_) though usage is intuitive.
15 tools is well-scoped for a client-intake lifecycle product; each tool maps to a distinct operation (intake CRUD, items, recipients, folders, webhooks, auth) with no filler.
Strong lifecycle coverage: create, list, update, status, results, revisions, chases, recipients, folders, webhooks, auth. Minor gaps remain — no archive/delete intake tool (archive state is referenced but not settable) and no remove-item operation, and owner decisions cannot be answered via API.