Documentation

Croft as a Claude connector

Croft is a home for the software your agent writes. You describe a recurring task in a sentence, Claude writes a workflow in TypeScript, and Croft runs it on a schedule or on demand — on our machines, with the connections it needs, whether or not you are online. This page is everything you need to connect it and get a workflow running.

Add this to Claude

https://croft.now/mcp
Transport
Streamable HTTP
Authentication
OAuth 2.1 — dynamic client registration, PKCE (S256). No API key to paste.

What Croft is

Agents can write working software in minutes. What they cannot do is keep it running. Croft is the part that keeps it running.

You describe a recurring task in your own words. Claude writes a workflow — ordinary TypeScript against the Croft SDK, not a drag-and-drop diagram and not a DSL — and Croft stores it, compiles it, and runs it: on a schedule, on a webhook, on a poll, or on demand as something Claude can call back later. It runs on our machines, with the connections it needs, whether or not you are online and whether or not anything else broke that day.

A workflow is a repeatable sequence of steps that takes a process from its start to a finished goal. If you have ever written “every month: first do this, then this” on the back of an envelope, you have written one down already. The only difference here is that something else does the steps.

Durable means something specific. Every awaited effect in a workflow is a step, recorded in the run’s step log the first time it happens. If the machine dies mid-run, the run re-executes and every recorded step returns its result instantly instead of happening twice — no duplicate email, no duplicate charge. A workflow that calls ctx.sleep("7 days") is not a process holding a timer for a week; it is a database row and a checkpoint, woken on time.

Croft is not a chat product and not an agent. It is the layer your agent stands on.

Before you start

You need three things, and only the first takes any time.

A Croft account. Go to croft.now and enter your email address. There is no password anywhere in Croft — logging in means proving you can read mail at an address. We send one email containing both a magic link and a six-digit code; either half works, and redeeming either one retires the other. Credentials are good for fifteen minutes, and you can have at most five live ones per address per hour. Typing an address nobody has used before creates the account; signing up and logging in are the same act, and there is no waitlist, invite code, or approval step.

A workspace, and its address. Your first successful login provisions an org and a workspace called Personal inside it, and drops you on the canvas at https://croft.now/{org}/{workspace}. Those two slugs are the workspace’s address — acme/personal, say — and you will need that exact string, written as {org}/{workspace}, because every Croft tool takes it as a required scope argument. Read it out of the URL. (If you arrived through an invitation you land in the inviting org instead, and no personal workspace is made for you.)

Claude, with custom connectors available. Nothing to install, and no API key to paste — the connection is set up over OAuth.

You do not need a connected Google account, Slack, or anything else to start. Those are only needed once a workflow actually has to reach one of them, and connecting them is a separate, human step.

Connect it to Claude

In Claude, open Settings → Connectors, choose Add custom connector, and give it the server URL:

https://croft.now/mcp

Transport is streamable HTTP. There is nothing else to fill in: Croft’s authorization server supports dynamic client registration (RFC 7591), so Claude registers itself. Your browser will open a Croft consent screen; sign in if you are not already, read what is being granted, and approve. That is the whole setup.

To confirm it worked, ask Claude:

List my Croft workspaces.

You should get back one row per workspace you can open, each with the {org}/{workspace} scope string you will use in every later request. That answer comes from the croft://workspaces resource, and getting it is proof that discovery, registration, the OAuth round trip, and the token all worked.

For a reviewer checking the protocol

  • An unauthenticated tools/list against https://croft.now/mcp returns 401 with a WWW-Authenticate: Bearer resource_metadata=... challenge pointing at /.well-known/oauth-protected-resource.
  • Authorization server metadata is at /.well-known/oauth-authorization-server (RFC 8414). It advertises the scopes listed below, the /oauth/authorize, /oauth/token, /oauth/register, /oauth/revoke and /oauth/introspect endpoints, and PKCE with S256.
  • A token authenticates a person, not a workspace. One connection therefore spans every workspace its user can open, and each call’s scope argument picks which one. Membership is re-checked on every single call, so losing access to a workspace takes effect on the caller’s next request — there is no token to hunt down and revoke.
  • tools/list is filtered per request against the caller’s granted scopes, so a tool a caller cannot use is invisible rather than advertised and refused.
  • A scope naming a workspace you cannot reach returns exactly the same not-found as a workspace that does not exist. So does a malformed UUID, and so does someone else’s UUID. The error is never an oracle.

Headless clients that cannot do a browser round trip can use a workspace API key instead; a key is an agent identity, fixed to one workspace.

What each permission grants

Nine scopes are declared, and the consent screen collapses read/write pairs into one sentence each. In plain language:

Scope What it lets an agent do
workflows:read See your workflows and their source — the workspace index, a workflow’s config and files, its derived graph, its tests, and its recent runs.
workflows:write Create, edit, run, and delete workflows. Also mints sibling workspaces.
runs:read Inspect run history — a run, its steps, and each step’s input and output.
runs:write Resume a parked or failed run, replay one in shadow mode, pin one as a test, and run a test suite.
data:read Read documents, record streams, and files, and run read-only SQL over the streams.
data:write Write and delete documents, append records, and write files.
connections:read See which external accounts are connected.
artifacts:write Create, update, and delete hosted artifact pages.
hooks:respond Answer a workflow that is parked waiting on a human.

Nothing here grants an agent the ability to create a connection to a third-party service or to grant itself one. That is human-only, by construction — see Connecting your other accounts.

Your first workflow

Ten minutes, start to finish, assuming you have an account.

  1. Get your scope string. Open https://croft.now, sign in, and read the two slugs out of the URL you land on. That is your {org}/{workspace}.

  2. Give the workflow something to work with. Ask Claude:

    In Croft workspace acme/personal, create a records stream called orders with these rows: 2026-08-27, widget, 3, 45.00; 2026-08-27, gasket, 1, 12.50; 2026-08-26, widget, 2, 30.00.

    Claude calls records_append, which creates the stream on first write.

  3. Ask for the workflow.

    In acme/personal, write me a Croft workflow that runs every weekday at 8am UTC, totals yesterday’s rows from the orders stream, and emails me a one-line summary at [email protected].

    Claude will read croft://sdk/reference for the SDK, then call workflow_write. Claude will ask you to confirm — that is expected, and why is worth reading once.

  4. Read the diagnostics. The write comes back with compile errors, analyzer lints, the derived graph, test results, and any connection problems, all in one envelope. Claude iterates against that rather than compiling separately, so a workflow that does not compile is usually fixed before you see it.

  5. Run it now. Ask “run it once so I can see it work”. Claude calls workflow_run; approve the confirmation.

  6. Look at it. Open https://croft.now/{org}/{workspace}. The workflow is there, its schedule is armed, and the run you just triggered is on the run rail with every step it took.

If step 3 comes back saying the email connection is missing, that is the system working as designed — go to Connecting your other accounts.

Example prompts and what to expect

These are the shapes that actually compose the tools well.

“Write me a workflow that pulls yesterday’s orders and emails a summary every morning.” Claude reads the SDK reference, calls workflow_write with a schedule trigger and an email connection, and shows you the diagnostics envelope. On a clean compile the bundle goes live immediately and the schedule is armed — there is no separate deploy. You should see the workflow appear on your canvas within seconds.

“Show me my Croft workspaces.” Reads croft://workspaces. Returns each workspace’s name, org, and scope string. This is the right first prompt after connecting.

“What’s in workspace acme/personal?” Reads croft://acme/personal: workflows, the connections this workspace can actually reach, document names, record streams, files, artifacts, and usage counters.

“Run the weekly report now.” workflow_run. Claude will ask to confirm, because running a workflow performs real effects. Pass an idempotency key if you are retrying something you are not sure landed — the same key returns the same run marked duplicate rather than starting a second one.

“Why did last night’s run fail?” Reads the workflow’s recent runs, then the failing run, then walks to the failing step’s recorded input and output. Claude proposes a fix, and can shadow-replay recent runs against the candidate before you accept it — a run_fork never sends anything.

“The summary is missing refunds. Fix it.” workflow_edit — exact-string replacement, the same semantics as an editor’s find-and-replace, with the same diagnostics envelope coming back. Compiling runs the workflow’s pinned test suite, so you find out in the same reply whether the fix broke a case you had pinned.

“Pin last night’s good run as a test.” run_pin_as_test freezes that run’s recorded results as fixtures, so every later compile checks against it.

“Ask me before it sends anything.” Claude rewrites the workflow to park on a hook. The run stops at that point and waits; the pending hook shows on the run page and on the run resource. When you answer — in chat, on the canvas, or by pressing a button on a hosted page — hook_resume relays your answer, it is validated against the hook’s schema, and the run continues from where it stopped.

“Query the orders stream: what did we sell most of last week?” records_query runs read-only SQL over your record streams, each mounted as a view named after the stream. Read the limits before you rely on the shape of the result.

“Make a page my team can open with this week’s numbers.” artifact_create returns a hosted, shareable URL. Artifacts are single self-contained HTML pages that can read the workspace data they declare up front — an undeclared read is refused at request time — and they default to workspace-members-only.

Tool reference

Eighteen tools, and only eighteen: the vocabulary is fixed rather than growing a verb per feature. Every tool takes a required scope string in {org}/{workspace} form; it is left out of the parameter notes below because it is on all of them.

Read

Tool Title Scope What it does
records_query Query records data:read Read-only SQL over the workspace’s record streams, each mounted as a view named after its stream.

That really is the only read tool. Everything else you read comes from resources, which is where the workflows:read, runs:read and data:read scopes do their work.

Write

Tool Title Scope Confirms? What it does
workflow_write Write workflow code workflows:write yes Whole-file write of TypeScript. Omit the workflow id to create a new one.
workflow_edit Edit workflow code workflows:write yes Exact-string replacement in one file of an existing workflow.
workflow_run Run workflow workflows:write yes Manual trigger, and the only way to invoke a callable workflow.
workflow_delete Delete workflow workflows:write yes Deletes a workflow.
run_resume Resume run runs:write yes Continues a parked or failed run from a given step.
run_fork Replay run runs:write no Shadow-mode what-if replay, optionally against a candidate bundle.
run_pin_as_test Pin run as test runs:write no Freezes a run’s recorded results as a test fixture.
test_run Run tests runs:write no Runs a workflow’s suite, or a single pinned case.
hook_resume Answer paused run hooks:respond yes Relays a human’s answer into a run parked on a hook.
data_put Save document data:write yes Writes one named document. Not for tabular data.
data_delete Delete document data:write yes Deletes a workspace-level document by name.
records_append Append records data:write no Appends rows to a records stream; the first call creates the stream.
file_put Save file data:write yes Writes a blob at a path in workspace file storage.
artifact_create Create artifact artifacts:write no Creates a hosted, shareable page and returns its URL.
artifact_update Update artifact artifacts:write yes Replaces an artifact’s content or settings.
artifact_delete Delete artifact artifacts:write yes Permanently deletes an artifact; its URLs stop resolving.
workspace_create Create workspace workflows:write no Creates a sibling workspace in your org and mints an agent identity in it.

Why some of these ask you first

A tool marked destructive always prompts in Claude. That is expected, and it is worth knowing which ones are marked and why, so you can approve them without squinting:

  • workflow_write and workflow_edit are destructive, which surprises people, because writing code sounds harmless. It is not, here: a successful compile immediately runs the workflow’s pinned test suite, and those tests execute the workflow’s real steps against real providers. Writing code can send an email. They are also marked open-world for the same reason.
  • workflow_run, run_resume and hook_resume all cause real effects to happen — starting, continuing, or releasing a run.
  • data_put, data_delete, file_put, artifact_update, artifact_delete and workflow_delete overwrite or remove something that was there.
  • run_fork and test_run are open-world (they can reach outside Croft) but not destructive; a fork is a shadow replay and sends nothing.
  • records_query is the one tool marked read-only.

Two of the unmarked ones deserve a second look anyway, because Claude will not stop to ask about them: records_append creates a stream that no tool can delete, and workspace_create mints an API key that is shown once and is not recoverable.

Resources and prompts

Reading is done through MCP resources under croft://, not through tools. Slugs scope; UUIDs identify.

Not tied to a workspace

URI What it is
croft://sdk/reference The current @croft/sdk documentation, versioned with the SDK. This is what Claude reads before writing a workflow.
croft://sdk/examples Canonical example workflows as annotated source.
croft://workspaces Every workspace this token can open, each with its scope string.

Inside a workspace ({org} and {ws} are your two slugs)

URI template What it returns
croft://{org}/{ws} The workspace index: workflows, this identity’s connection grants, document names, record streams, files, artifacts, usage counters.
croft://{org}/{ws}/workflows/{id} One workflow: config, files, connections, input schema, status, live bundle hash.
croft://{org}/{ws}/workflows/{id}/files/{path} One source file.
croft://{org}/{ws}/workflows/{id}/graph The derived graph — nodes, edges, dynamic regions.
croft://{org}/{ws}/workflows/{id}/graph.svg The same graph as a standalone SVG.
croft://{org}/{ws}/workflows/{id}/tests Pinned test cases, their fixtures and assertions, and the last result.
croft://{org}/{ws}/workflows/{id}/runs The workflow’s recent runs, newest first.
croft://{org}/{ws}/runs/{id} One run: its steps, its hooks, and the pending hook hoisted to the top.
croft://{org}/{ws}/runs/{id}/steps/{n} One step’s full input, output, and metadata.
croft://{org}/{ws}/data/{name} One document, and whether it resolved at workspace or org level.
croft://{org}/{ws}/records/{stream} A stream’s stats and its inferred columns.
croft://{org}/{ws}/files/{path} One workspace file.
croft://{org}/{ws}/artifacts/{id} An artifact’s declaration, hosted URL, share URL, and visibility.

Prompts. Seven, each a starting point you can pick in Claude rather than typing the whole framing yourself. Where you can reach exactly one workspace, its slugs are filled in for you.

Prompt Arguments What it does
solve problem (optional) The flagship: read the problem, check the workspace, iterate until a workflow is live.
create-workflow goal, trigger, delivery The structured version of solve, for when you already know what you want.
improve-workflow workflow, feedback Read a workflow’s source and recent traces, apply feedback, show the shadow diff and test results before updating.
debug-run run Fetch a run, walk to the failing step’s input and output, propose a fix, shadow-fork recent runs against it.
add-test workflow, expectation Pin the latest good run as fixtures and turn a stated expectation into assertions.
import-data description Take data out of the conversation into documents or records, then suggest the workflows it enables.
create-artifact purpose, data (optional) Design and ship a hosted, shareable page.

Connecting your other accounts

A workflow that only touches Croft’s own data needs no connections. One that reads your inbox or writes to a spreadsheet needs a connection: a stored credential, held by Croft, that a workflow refers to by alias. The workflow’s own config lists the aliases it may use, and anything else is denied at execute time whatever the code says. Connector calls run in Elixir, never inside the workflow sandbox, so credentials never enter workflow memory, and revoking a connection stops the next call cold.

What exists today, honestly:

Connector State
Email Real. Markdown in, HTML out, delivered through Croft’s mail provider, with an outbox row you can read.
GitHub Real, read-only actions.
Google Sheets Real, connected through a browser OAuth flow.
Attio Real, connected through a browser OAuth flow.
Stripe Real, connected through a browser OAuth flow. Payments, billing, refunds and disputes, plus an incremental read of the money ledger.
HTTP Real, and default-deny: it will only call URL prefixes you have allowed. An empty allowlist denies everything.
Slack Real when a token is configured; otherwise it runs in stub mode and reports that it did.
Web search Real, and off until you switch it on. One lookup against a search index (Google Programmable Search by default, Brave optionally). No account to connect — the switch is the whole setup.
X Stub in v1. Returns deterministic canned metrics, not real API data.
sheets Deprecated stub. Use google_sheets.

The three with a browser connect flow today are Google, Attio and Stripe. The rest are configured with credentials rather than through a consent screen.

An agent cannot connect an account to itself, and that is deliberate. There is no tool in the eighteen that creates a connection. A human member adds them on https://croft.now/{org}/{ws}/connections, and connecting requires org owner or admin. A plain member sees the same page read-only.

Reach is decided per workspace, not per agent. Every agent identity in a workspace can use every connection that workspace can see: the ones connected there, plus any org-level connection an org admin has exposed to it. There is no second, per-identity approval step — the human who connects the account is the authorization, and the way to limit a connection’s reach is to control which workspaces have it.

What the agent gets instead is a clear report: when a workflow names a connection its workspace does not have, the diagnostics envelope comes back with a connection_issues entry marked not_found, naming the alias. Claude will tell you which connection is missing. Then you connect it, and ask Claude to compile again.

One thing worth knowing: a workspace with no email connection configured at all can still send email to an address that belongs to a member of the workspace or its org. It cannot mail strangers.

Web search is the one you switch on rather than connect. The API key belongs to the server, not to your workspace, so its row on the connections page is a plain on/off switch and it starts off. An owner or admin presses Enable once and every workflow in the workspace can call ctx.web_search.search({ query }); Disable turns it back off and the next call stops cold, exactly like revoking any other connection. It is off by default on purpose: every search costs the server a metered query and sends your phrasing to a search engine, which is a decision worth making rather than inheriting.

It is a search index, not a model. One lookup, one ranked list of { title, url, snippet }, and the same query returns the same results — nothing reads your query and decides what it meant. That matters when an AI is writing the queries: the step replays identically, and what comes back is what the index actually holds rather than a model’s recollection of the web. If you want the results summarised, hand them to ctx.ai yourself; you will be able to see and replay both halves.

A workspace can supply its own API key if it would rather bill searching to its own quota than the server’s. That is the only thing its credentials ever hold — turning the connector on requires nothing.

Two things it will tell you rather than paper over. If a workflow asks for a domain outside the ones the connection allows, the call fails with domain_not_allowed rather than quietly searching everywhere. And a rate limit comes back as rate_limited with the index’s own retry_after, so the run parks and picks up later instead of burning the rest of the day’s quota retrying.

Known limits

Straight answers, because you will hit these.

Records

  • records_query truncates results to 200 rows, and flags when it did.
  • Its result columns come back alphabetized, not in SELECT order — address them by name, never by position.
  • A zero-row result has an empty columns list, so do not infer the schema from an empty answer.
  • Mutating and DDL keywords (INSERT, UPDATE, DELETE, CREATE, COPY, ATTACH, PRAGMA, and similar) are rejected.
  • records_append takes flat maps only — scalar values, no nested objects or arrays — and rejects the call otherwise. Stream names are lowercase letters, digits, _ and -. Column drift between appends is unioned by name.
  • There is no tool to delete a record stream once created. Choose stream names deliberately.

Documents and files

  • A document value is capped at 5 MB encoded; a file at 100 MB.
  • data_delete only removes a workspace-level document. An org-level document of the same name survives and remains the read-side fallback.

Workflows and runs

  • workflow_delete refuses an active workflow — it must be paused or done first. There is no MCP tool that pauses a workflow, so today pausing is a button on the workflow page and deleting an active workflow needs a human.
  • On a new workflow, workflow_write always saves the file as index.ts, whatever path you pass.
  • workflow_edit requires old_string to match exactly once; otherwise it reports the match count and changes nothing. replace_all opts out.
  • Both accept an expected_hash and return a conflict rather than a lost update if someone else wrote in between.
  • A multi-file workflow’s first write cannot compile, because index.ts imports a sibling that has not been written yet. Expect an error, write the sibling, and it goes green.
  • A write that does not compile leaves the live bundle untouched, so a workflow mid-refactor keeps running its last good version.
  • run_resume truncates the run at the step you name and continues live, which produces a new run id.
  • The sandbox has no ambient network, filesystem, or entropy; the clock is virtual and randomness is seeded per run. This is what makes replay safe, and it means a workflow cannot reach the internet except through a connector.

Workspaces and artifacts

  • workspace_create only makes a sibling workspace in your own org — an agent identity never reaches outside it. The new workspace starts with no connections, and an org-level connection does not follow it there, so its identity reaches nothing outside croft until a human connects something.
  • The API key it returns is shown once and cannot be recovered.
  • Artifacts are versioned and content-hashed, but there is no instant rollback, and artifact_delete is permanent — the hosted and share URLs stop resolving.

Not there yet

  • There is no resource that lists the providers you could connect. What an agent can see is the connections its own workspace can already reach, in the workspace resource.
  • There is no workspace-wide run list; runs are listed per workflow.
  • Croft does not charge anyone today. There is no paid plan and no billing system. Usage is counted per workspace so we know what the service costs, and account holders will be told by email before that ever changes.

When something goes wrong

Claude says it cannot find the workspace. The scope argument is {org}/{workspace} — two slugs from the canvas URL, separated by a slash, not the workspace’s display name. A scope you cannot reach and a scope that does not exist return the same error on purpose, so the message will not tell you which it was. Ask Claude to list your workspaces and copy the string it gives you.

A tool you expected is missing. tools/list is filtered against your granted scopes. If you approved a narrower set at the consent screen, the tools those scopes cover simply are not there. Reconnect and approve the ones you need.

The workflow compiles but reports a connection problem. That is connection_issues, and it means the alias the workflow names has no connection in this workspace. Fix it on the connections page; the agent cannot.

A run is sitting there not finishing. Check whether it is parked on a hook waiting for a human. The pending hook is hoisted to the top of the run resource for exactly this reason. Answer it in chat and Claude will relay it.

A workflow deletes fine in your head but not over MCP. Pause it on its page first; workflow_delete refuses an active workflow.

Privacy, terms, and support

The privacy policy says exactly what Croft holds and what it does with it, including how connected-account credentials are encrypted and what deletion removes. The terms cover the rest of the deal, including the part specific to a product whose code is model-written: a generated workflow is not guaranteed to be correct, and it acts with the access you gave it.

For anything about this connector or the product, email [email protected]. For a privacy or data question specifically, [email protected].