Connect an AI client to your workspace.
Claude, Cursor and VS Code can work in your ProductCraft workspace over the Model Context Protocol — approved in a browser, scoped by policy, and logged line by line.
What it is
One endpoint, your API as tools
ProductCraft runs an MCP server at https://mcp.productcraft.co/mcp. Point a client at it and the workspace's API becomes tools the model can call: read a waitlist, look up why a delivery bounced, send a transactional email, kick off a web extraction.
Nothing is pasted. There is no API key in a config file. The client registers itself, opens a browser, and you approve the connection on a ProductCraft consent screen that names the client, the workspace and exactly what it may do. The credential lives in the client's own store and can be revoked from your account at any time.
The tool list is filtered to what you approved. A connection scoped to email sees email tools and nothing else — so the model is never choosing between hundreds of tools it would only get a 403 from.
Step 1
Add the server to your client
Every client speaks the same transport (Streamable HTTP) and the same auth (OAuth 2.1 with PKCE). Pick yours.
claude mcp add --transport http productcraft https://mcp.productcraft.co/mcp
# then, inside Claude Code:
/mcp # pick "productcraft" and follow the browser promptNote what is not in any of those snippets: a token, a key, a client id, a secret. The only configuration is the URL.
Step 2
Approve the connection
The client sends you to auth.productcraft.co. What you do there is the whole security model.
- Sign in with your ProductCraft account, if you are not already.
- Pick the workspace this connection acts in. One connection, one workspace.
- Choose what it may do. Start from a preset and narrow it — you can always grant less than the client asked for.
- Approve. The browser hands the client a token and you are done.
The screen marks every dynamically-registered client unverified, because that is what it is: the client chose its own name when it registered. Trust the app you just installed, not the string on the screen. Consent is per client — a second client, even one with the same name, faces the same screen and gets nothing from your earlier approval.
Scopes
Presets, and the ceiling above them
A connection carries a policy document, not a coarse scope. Presets are named starting points the consent screen can render in one line.
| Preset | What it grants |
|---|---|
| readonly | Read-only across the workspace: settings, members, email, waitlists, communities and web-extraction jobs. Changes nothing. |
| Read and send email from your verified domains, and manage suppression lists. Email cannot be unsent. | |
| support | Everything read-only, plus the day-to-day actions a support assistant needs: sending email, updating waitlist entries, moderating posts and running extraction jobs. |
| full | Every action the workspace exposes, except credential minting, role and policy editing, and the other privilege-escalating actions below. |
A connection can never do more than you can. Whatever you approve is intersected with your own permissions on that workspace — and re-checked on every single call, not frozen when you approved it. Lose a permission, and the connection loses it at the next call. Leave the workspace, and every connection you made stops working, with nobody having to remember to revoke it.
Escalation
The actions no preset contains
Some actions create authority that outlives the connection itself. They are excluded from every preset and called out in their own section of the consent screen — you have to tick them deliberately, one at a time.
- Minting credentials — API keys, machine-to-machine clients, webhook signing secrets, end-user password-reset and verification codes. A new key outlives this connection, its policy and its expiry.
- Editing roles and policies — rewriting the ceiling rather than working under it.
- Handing somebody a seat — workspace invites, tenant member management, and waitlist invite-to-app. An invite to an address someone else controls is standing access.
- Emailing outside your verified domains — a separate action from ordinary sending, because it is the one that reaches strangers.
Limits
What a runaway client cannot do
Limits are per connection and per workspace — never per IP address, because every client of a given vendor shares one.
| Tool kind | Per connection | Per workspace |
|---|---|---|
| Reads | 120 / min | 600 / min |
| Writes | 30 / min | 120 / min |
| Sending email | 5 / min | 20 / min |
Sending is also capped at 20 emails per connection per hour, and a send counts against the write budget as well as its own. Results are capped at 128 KB and every list tool pages with a cursor, so one question cannot pull your whole mailbox into a model's context. Hit a limit and the tool answers with a retry_after the client can wait on.
Content that came from outside — email bodies, waitlist notes, extracted web pages — is returned to the model wrapped and labelled as data, never as instructions. That is the containment boundary for prompt injection: a message in your inbox does not get to tell your assistant what to do. API keys, tokens and signing secrets are stripped from every tool result.
Audit
Every call is on the record
Each tool call — including the ones that were refused — lands in the workspace audit log the console already shows.
The row records you as the actor, because the authority is yours, and marks the actor type mcp_client so that "you did this" and "an AI client acting as you did this" are visibly different rows. It carries the client's id, whether it was verified, the tool name, the outcome, and the arguments — redacted and bounded, because an audit row is not a place a secret should end up.
Refusals count. A feed that only recorded what succeeded could not show you the hour somebody spent probing.
Revoke
Disconnecting a client
Revocation kills the whole family at once — the grant, its refresh tokens and every live access token — in one transaction. The client stops working on its next call.
The quickest way is the console. Connected apps under your account lists everything you have connected, and the same page under Workspace settings lists every connection any member has made against the workspace — the offboarding view. Both have a disconnect button; the API below is the same thing for scripts.
# List the clients you have connected
curl https://api.platform-auth.productcraft.co/v1/oauth/connections \
-H "Authorization: Bearer <your session token>"
# Disconnect one
curl -X DELETE \
https://api.platform-auth.productcraft.co/v1/oauth/connections/<grant_id> \
-H "Authorization: Bearer <your session token>"Workspace owners and admins have the other half of the lever: every connection made against the workspace by any member, including people who have since left. That is the Connected apps page under Workspace settings, and these endpoints underneath it.
GET /v1/oauth/workspaces/{workspace_id}/connections
DELETE /v1/oauth/workspaces/{workspace_id}/connections/{grant_id}Those require workspace.connection.read and workspace.connection.revoke, which owners and admins hold by default. Removing a member also revokes every connection they made — offboarding does not depend on anybody remembering this page.
Troubleshooting
If the client cannot connect
- It asks you to authenticate again and again. The connection was revoked, or your access to the workspace changed. Approve it again from the client.
- A tool you expected is missing. The tool list is filtered by what you approved. Reconnect and grant the missing area — or check whether the action is in the escalation list above, which no preset includes.
- A tool answers "not permitted". Your own role on the workspace is the ceiling. If you lost a permission, the connection lost it too.
Everything the server does with a workspace goes through the same policy engine as the rest of the platform — see the Platform docs for how roles, policies and workspace API keys fit together.