Intents

Intents are named shortcuts for parameter-level constraints. An intent encodes a common provider-specific convention - "post to Slack channel," "create a Linear issue," "read a Stripe customer" - and expands server-side into the underlying constraint array. The passport carries the expanded constraints; intents are the user-facing shape.

Use intents when you want policy to read like product language. Fall back to raw constraints when you need something the catalog does not cover.

Shape

An intent reference is a name plus params:

json
{
  "name": "slack.post_to_channel",
  "params": { "channel": ["C0123", "C0456"] }
}

Expansion

At grant and issue time the server resolves each intent in the catalog, validates the params against the intent's zod schema, and emits the equivalent constraint array. The example above expands to:

json
[
  { "path": "url.pathname", "op": "eq", "value": "/api/chat.postMessage" },
  { "path": "body.channel", "op": "in", "value": ["C0123", "C0456"] }
]

Raw constraints and intents can be combined in the same grant or passport. The two arrays are concatenated; the AND semantics of constraint evaluation make duplicates harmless.

Catalog

STACK ships over 2,000 intents across 100+ providers, covering comms, dev platforms, infrastructure, observability, CRM, commerce, finance, storage, AI, analytics, identity, and more. The full list is retrievable at runtime via the MCP tool stack_list_intents or by reading the intent registry in the @stack/shared package.

Categories covered

  • Comms - slack, discord, ms_teams, twilio, zoom, telegram, whatsapp_business, loom
  • Email - gmail, outlook, resend, sendgrid, mailchimp, brevo, intercom, zendesk
  • Dev + hosting - github, gitlab, bitbucket, vercel, netlify, fly_io, render, railway
  • Infra - cloudflare, digitalocean, hetzner, linode, aws, gcp, azure
  • Monitoring - sentry, datadog, new_relic, pagerduty, grafana, snyk
  • Project mgmt - linear, jira, notion, asana, clickup, trello, shortcut, confluence, basecamp
  • Docs + storage - google_docs, google_sheets, google_drive, dropbox, box, airtable
  • CRM + HR - hubspot, salesforce, gusto, bamboohr
  • Finance + commerce - stripe, quickbooks, xero, paypal, square, brex, wise, coinbase, shopify, bigcommerce, woocommerce, gumroad, lemonsqueezy
  • Analytics - google_analytics, mixpanel, amplitude, posthog, hotjar, plausible
  • AI - openai, anthropic, replicate, hugging_face, mistral, qdrant, langsmith
  • Database - neon, planetscale, upstash, mongodb_atlas, turso, supabase
  • Object storage - aws_s3, r2, backblaze, wasabi
  • Calendar - google_calendar, calendly, cal_com
  • Auth - auth0, clerk, okta
  • Social - twitter, linkedin, reddit, youtube, instagram, tiktok, spotify
  • Design + CMS - figma, canva, contentful, sanity, strapi, webflow, wordpress, typeform
  • custom - generic verbs against arbitrary hosts

Listing intents programmatically

bash
# Via MCP
echo '{ "method": "tools/call", "params": { "name": "stack_list_intents", "arguments": {} } }' \
  | mcp-cli --server stack
json
[
  {
    "name": "slack.post_to_channel",
    "description": "Send a message to a specific Slack channel",
    "params": { "channel": "string | string[]" }
  },
  {
    "name": "github.create_issue",
    "description": "Create an issue in a specific repository",
    "params": { "owner": "string", "repo": "string" }
  }
  // …
]

Failure modes

  • Unknown intent name → grant or issue rejected with 400 INVALID_REQUEST
  • Params fail the intent's zod schema → 400 with the zod error message
  • Expanded constraints exceed 32 per ServiceScope → 400 FORBIDDEN on the specific scope

When to use intents vs constraints

Prefer intents for anything in the catalog - they encode provider API conventions so your policy stays readable as APIs evolve. Reach for raw constraints when you need custom path matching, regex predicates, or rules that do not correspond to a named verb.

stack | docs