BETA
Skip to content

Connect an assistant ​

Krafter's MCP server is at https://mcp.krafter.dev/mcp. Point your assistant at it and it can read your mail deliveries, form submissions, logs, flags, audit findings and analytics, and make the twelve writes it is given scopes for.

There are two ways to authenticate. Use OAuth unless you are writing a script.

OAuth — the normal path ​

Nothing to paste, and no long-lived secret on disk. Your client discovers the authorisation server, introduces itself, sends you to a consent screen, and stores its own token. Claude and Claude Code introduce themselves by the address of the description they publish (a client ID metadata document); other clients register on the spot. Either way there is nothing for you to set up.

Claude Code ​

sh
claude mcp add --transport http krafter https://mcp.krafter.dev/mcp

Then run /mcp in a session and pick Authenticate. A browser opens on the consent screen.

Claude Desktop, Cursor, and other clients ​

Add a remote MCP server (sometimes called a custom connector or streamable HTTP server) with the URL https://mcp.krafter.dev/mcp and no authorization header. Leaving the header out is what makes the client use OAuth: the server answers an unauthenticated request with a discovery pointer, and a client that speaks OAuth takes it from there.

json
{
  "mcpServers": {
    "krafter": {
      "type": "streamable-http",
      "url": "https://mcp.krafter.dev/mcp"
    }
  }
}

You choose two things.

Which teams. Tick every team the connection may act on — one, several, or all of them. If you belong to several, the screen asks each time you authorise, with your previous choice pre-ticked; it will not guess, because guessing would hand an assistant a team you were not looking at. Re-authorise later to add or remove teams.

Which scopes. Only the ones you tick are granted, and they decide which tools the assistant can even see. Start narrow — mail:read and logs:read cover most questions — and re-authorise later if you need more. Asking for more than you granted brings the screen back rather than silently widening anything.

Working across teams ​

With one team ticked, the assistant works on it straight away. With several, nothing is active until it says which team it means: teams_list shows the teams the connection covers, and teams_select picks one. Every other tool refuses until then, and names those two tools when it does. After that, every call acts on the selected team — and only it — until the assistant selects another. The choice is remembered across sessions.

Selecting a team is an audited action, and every tool call is recorded against the team it acted on, so the trail always says which team was in play.

Managing connections ​

Dashboard → API Keys → Connected applications lists every connection on the team: which app, who approved it, its scopes, and when it was last used. Revoking takes effect on the assistant's very next request, not whenever its token would have expired.

API key — for scripts ​

When there is no browser to approve a consent screen — CI, a cron job, your own service — use a key instead.

  1. Dashboard → API Keys → Create API Key, tick Allow AI agent (MCP) and the scopes you need. A key without that box works on the REST API and the SMTP relay, but /mcp refuses it, so the key your application sends mail with is not also a key an agent can use.
  2. Copy the key. It is shown once.
  3. Send it as a Bearer header:
json
{
  "mcpServers": {
    "krafter": {
      "type": "streamable-http",
      "url": "https://mcp.krafter.dev/mcp",
      "headers": { "Authorization": "Bearer kr_live_YOUR_API_KEY" }
    }
  }
}

An API key is the broader credential of the two: it also opens the REST API and the SMTP relay, and it does not expire on its own. It can, unlike an OAuth connection, be pinned to named resources — one mail domain, one log project — under the key's permissions.

What to expect once connected ​

Ask in plain language:

  • "How many emails bounced this week, and why?"
  • "Show me error logs from the last hour"
  • "Which feature flags are on in production?"
  • "Any unread form submissions?"
  • "Did the nightly cron job succeed?"

The assistant only sees tools your scopes reach, so if it says a tool does not exist, the usual cause is a missing scope. The server tells it which scopes you hold when it connects, so it can name the one it needs.

Deleting a mail domain or a suppression takes two calls: the first returns the measured impact and a confirmation string, the second executes. An assistant cannot delete either by accident.

Publishing mail DNS records from the assistant ​

mail_create_domain returns the DNS records a new sending domain needs — type, name, value, ttl, priority — in the shape a DNS API takes. If the assistant also has a DNS tool, it can publish them itself and then call mail_verify_domain, all in one conversation.

For Cloudflare, use the Code Mode server — https://mcp.cloudflare.com/mcp — and not the Cloudflare Developer Platform connector. That connector is Cloudflare's Workers Bindings server (KV, R2, D1, AI); it has no DNS. The Code Mode server covers the whole Cloudflare API, DNS included.

sh
claude mcp add --transport http cloudflare https://mcp.cloudflare.com/mcp

Two things the assistant is told by the tool itself, and that are worth knowing when reading its output:

  • Every CNAME and MX must be DNS-only on Cloudflare (proxied: false). A proxied DKIM CNAME does not resolve to Amazon's host, and the domain never verifies.
  • Verification runs in the background. mail_verify_domain sets the domain to verifying; the assistant reads the result back with mail_list_domains a minute or two later.

Troubleshooting ​

The client says it cannot authenticate, or never opens a browser. Check the URL is mcp.krafter.dev and not app.krafter.dev. The app host still serves the MCP endpoint for API-key callers, but the authorisation server answers only on mcp.krafter.dev — a client pointed at the app host finds nothing to register with.

A 401 with WWW-Authenticate: Bearer … is normal for an unauthenticated request. That header is how a client learns where the authorisation server is.

A 401 whose error_description says the key "is not enabled for AI agents (MCP)". The key is valid but was created for an application. Create a key with Allow AI agent (MCP) ticked, or connect over OAuth. Existing keys were created before the box existed and have it off.

Tools disappeared after working. Someone revoked the connection, or a key expired. Both show in the dashboard.

Every tool says no team is selected. The connection covers several teams and none is active — ask the assistant to run teams_list and teams_select. If a team you expect is missing from teams_list, you are no longer a member of it.

Everything is refused after a while. An OAuth access token lasts one hour and the client refreshes it silently; if refresh fails, the connection was revoked and you need to authorise again.

Rate limited (429). Each credential gets 300 requests per minute at /mcp, in its own bucket — one assistant looping cannot spend another's budget, or your team's REST budget.

Reference ​

Built by Krafter Studio