{
  "markdown": "# Indraft\n\n**A CRM your AI agent can actually run.** Connect Claude, ChatGPT, Cursor or any\nMCP client and it can read and write companies, contacts, opportunities, tasks\nand interactions from the first request, with no schema to design first.\n\nMCP server: `https://api.indraft.io/mcp` · [indraft.io](https://indraft.io) ·\n[Docs](https://indraft.io/docs)\n\n---\n\n## Connect it\n\n### Claude\n\n```\nclaude mcp add --transport http indraft https://api.indraft.io/mcp\n```\n\nClaude opens a browser to authorize. Nothing to paste, no API key to store.\n\nIn Claude Desktop or claude.ai, add it as a custom connector with the same URL.\n\n### ChatGPT\n\nSettings → Connectors → Add custom connector, URL `https://api.indraft.io/mcp`.\nIt authorizes over OAuth.\n\n### Cursor, Windsurf, VS Code, and other MCP clients\n\nAny client that speaks Streamable HTTP and OAuth 2.1 works. Point it at\n`https://api.indraft.io/mcp`.\n\nThen paste this and your agent will set itself up:\n\n> Set up Indraft for my business. Read its CRM schema first, then tell me what\n> you think we do and how you plan to model it, and wait for my answer before you\n> write anything.\n\nIt reads the schema before it writes, so it learns the object types, the limits\nand what it is allowed to do without you explaining any of it.\n\n---\n\n## Why this exists\n\nMost CRMs were built for a person clicking through forms, and an agent using one\nis doing screen-scraping with extra steps: guessing field names, inventing\nrecords, and overwriting things somebody already checked.\n\nIndraft is built the other way round.\n\n**Every value records who asserted it and how.** Observed, inferred, imported,\nsupplied by a person, or confirmed by a person. Those rank, and a weaker claim\ncannot quietly overwrite a stronger one, so your agent's guess never overwrites\nwhat you checked. A write that was held says so rather than reporting success.\n\n**Every change is on the record.** The actor, the surface it arrived through,\nand the field-level diff. Most changes can be undone.\n\n**It is populated from the first request.** Companies, contacts, opportunities,\ntasks and interactions exist before you configure anything, with a pipeline that\ncan actually close a deal. Custom fields and your own object types are there when\nyou need them, defined by asking.\n\n**It refuses rather than guessing.** A total that crosses currencies is refused\nunless you have stated a rate, and every converted answer names the rate it used\nand who asserted it. There is no bulk delete.\n\n---\n\n## The tools\n\n45, covering reading, writing, schema changes, merges, bulk imports and\naggregation. An agent is only shown the ones its credential can actually call.\n\nFull reference, generated from the server's own catalogue: **[TOOLS.md](./TOOLS.md)**\n\nEvery tool carries a human-readable `title` and the applicable `readOnlyHint`,\n`destructiveHint` and `openWorldHint`, so a client can tell a read from a write\nbefore it calls one.\n\n---\n\n## TypeScript SDK\n\nFor your own service, when you want the REST API rather than MCP. The source is\nin [`sdk/`](./sdk); an npm release follows.\n\n```ts\nimport { IndraftClient } from \"./sdk\";\n\nconst indraft = new IndraftClient({ token: process.env.INDRAFT_TOKEN });\n\nconst { record } = await indraft.upsertCompany({\n  name: \"Halden Freight\",\n  domain: \"halden.example\",\n  industry: \"Logistics\",\n  // Say how you know. An import is weaker than a person, and Indraft enforces\n  // that rather than trusting the last writer.\n  assertionKind: \"imported\",\n  idempotencyKey: \"nightly-sync-halden\",\n});\n```\n\nErrors are typed and carry a recovery hint rather than a status code alone:\n\n```ts\nimport { IndraftError } from \"./sdk\";\n\ntry {\n  await indraft.upsertCompany({ name: \"Halden Freight\", industry: \"Retail\", overrideStanding: true });\n} catch (error) {\n  if (error instanceof IndraftError && error.code === \"standing_override_refused\") {\n    // This workspace does not permit overrideStanding. Send the write again\n    // without it: it applies to every field it is strong enough to move and\n    // reports the rest in `held[]`, and a person can confirm a contested value.\n    console.error(error.recoveryHint);\n  }\n}\n```\n\nA cross-currency total is not an error, it is a different answer. Ask for a sum\nover deals in several currencies with no rate on file and the aggregate comes\nback grouped per currency rather than summed, because a total that silently\nmixes currencies is the failure this product refuses to commit.\n\nSee [`sdk/`](./sdk) for the source. MIT.\n\n---\n\n## Also available\n\n- **REST API** with a published [OpenAPI description](https://api.indraft.io/v1/openapi.json)\n- **Official MCP registry**: `io.indraft/mcp`\n- **Export everything, any time**: one spreadsheet per table, the whole workspace\n  as JSON, and a README explaining how the files join up. Nothing is left out and\n  nothing is trimmed to fit.\n\n---\n\n## Status\n\nIndraft is live at [indraft.io](https://indraft.io). Free tier, no card.\n\nIssues and questions are welcome here. Security reports go to\n`koshea@justicebid.com` rather than a public issue.\n\n## License\n\nMIT for the SDK and everything in this repository. The hosted service has its own\n[terms](https://indraft.io/legal/terms) and [privacy policy](https://indraft.io/legal/privacy).\n",
  "bytes": 5246,
  "sha": "da9a9c0d48478a568f93a0a6f7766de8df7789104266028802c79b29daa669f1",
  "repo_slug": "indraftio/indraft",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_indraft_mcp_0fd7a92c/readme"
}