ax-check.com
by Gauge
D
Drafted
drafted.ai
ax-check.com
Checked 14 October 2026
B
65/100
Agents need your login
Homepage is agent-readable, but docs and pricing details stay hidden
Homepage loads clean Markdown under the token budget with working links, but no documentation index, quickstart, or pricing page was found for deeper checks.
2 fixes to start with
Concrete changes, backed by what we found.
/llms.txt returned HTTP 404, so no documentation index exists.
Linked from www.drafted.ai/llms.txt
Recorded coding sessions
Same task, 3 models, no drafted.ai account. Recorded 14 October 2026 on Pi.
3 recorded · 59s
59s · recorded
Session findings
Select a finding to see it in context.
›Thinking…
The user is asking about "Drafted." I should check the repository to understand what Drafted is.
ls -la /sandbox/repo && cat /sandbox/repo/README* 2>/dev/null | head -100
total 16
total 16 drwxr-xr-x 3 root root 4096 Sep 18 08:00 . drwxr-xr-x 7 root root 4096 Oct 14 22:44 .. drwxr-xr-x 8 root root 4096 Sep 24 20:05 .git -rw-r--r-- 1 root root 408 Sep 18 08:00 .gitignore
Recorded tool call
{
"type": "tool_call",
"seq": 3,
"ts": "2026-10-14T22:44:28.245Z",
"name": "bash",
"turn": 1,
"input": {
"command": "ls -la /sandbox/repo && cat /sandbox/repo/README* 2>/dev/null | head -100"
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-ad1fa91cb73058dc",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 4,
"ts": "2026-10-14T22:44:28.245Z",
"turn": 1,
"output": {
"content": [
{
"text": "total 16\ndrwxr-xr-x 3 root root 4096 Sep 18 08:00 .\ndrwxr-xr-x 7 root root 4096 Oct 14 22:44 ..\ndrwxr-xr-x 8 root root 4096 Sep 24 20:05 .git\n-rw-r--r-- 1 root root 408 Sep 18 08:00 .gitignore\n",
"type": "text"
}
]
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-ad1fa91cb73058dc",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
The repository is empty except for .gitignore. What is "Drafted"? Let me check git log and .gitignore.
cd /sandbox/repo && cat .gitignore && git log --oneline | head -20 && git remote -v
# Keep generated and vendored files out of source diffs.
# Keep generated and vendored files out of source diffs. # Logs / OS cruft *.log .DS_Store # JavaScript / TypeScript node_modules/ .next/ dist/ build/ coverage/ # Python .venv/ venv/ __pycache__/ *.py[cod] .pytest_cache/ *.egg-info/ # Rust target/ # Go / PHP / Ruby vendored deps vendor/ .bundle/ # Java / Kotlin / Scala .gradle/ # .NET bin/ obj/ # Elixir _build/ deps/ # Dart / Flutter .dart_tool/ 9ebf5fb Initial workspace
Recorded tool call
{
"type": "tool_call",
"seq": 7,
"ts": "2026-10-14T22:44:29.589Z",
"name": "bash",
"turn": 1,
"input": {
"command": "cd /sandbox/repo && cat .gitignore && git log --oneline | head -20 && git remote -v"
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-8f0861e58ffb6720",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 8,
"ts": "2026-10-14T22:44:29.589Z",
"turn": 1,
"output": {
"content": [
{
"text": "# Keep generated and vendored files out of source diffs.\n\n# Logs / OS cruft\n*.log\n.DS_Store\n\n# JavaScript / TypeScript\nnode_modules/\n.next/\ndist/\nbuild/\ncoverage/\n\n# Python\n.venv/\nvenv/\n__pycache__/\n*.py[cod]\n.pytest_cache/\n*.egg-info/\n\n# Rust\ntarget/\n\n# Go / PHP / Ruby vendored deps\nvendor/\n.bundle/\n\n# Java / Kotlin / Scala\n.gradle/\n\n# .NET\nbin/\nobj/\n\n# Elixir\n_build/\ndeps/\n\n# Dart / Flutter\n.dart_tool/\n9ebf5fb Initial workspace\n",
"type": "text"
}
]
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-8f0861e58ffb6720",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
The repository is essentially empty. "Drafted"—I don't have any knowledge of a product called Drafted that has an SDK. Let me check whether the package is available via npm/pip and whether it can be searched offline... Is there no internet? Let me quickly give it a try.
npm view drafted 2>&1 | head -20; echo ---; pip index versions drafted 2>&1 | head -5
drafted@1.22.8 | MIT | deps: 7 | versions: 216
drafted@1.22.8 | MIT | deps: 7 | versions: 216 Drafted — visual thinking surface for humans and AI agents. Renders HTML, markdown, images, and code as frames on a zoomable canvas, with MCP tools for AI agents and real-time sync for humans. https://github.com/ddfourtwo/drafted#readme keywords: design, canvas, preview, html, claude bin: drafted, drafted-mcp dist .tarball: https://registry.npmjs.org/drafted/-/drafted-1.22.8.tgz .shasum: c50ebcd9352ada9e3b162bf59188b91493c7e17a .integrity: sha512-KV2HPov8hbj7kqG3a6KrrHe8khiP7OWboChKzObVl+pJjyifCbtv2f0tNwTMMOO8S0NYIKuj8Nzhqi4M9fPMtg== .unpackedSize: 638.5 kB dependencies: @modelcontextprotocol/ext-apps: ^1.6.0 @modelcontextprotocol/sdk: ^1.27.1 commander: ^11.1.0 qrcode-terminal: ^0.12.0 --- ERROR: No matching distribution found for drafted
Recorded tool call
{
"type": "tool_call",
"seq": 11,
"ts": "2026-10-14T22:44:31.298Z",
"name": "bash",
"turn": 1,
"input": {
"command": "npm view drafted 2>&1 | head -20; echo ---; pip index versions drafted 2>&1 | head -5",
"timeout": 30
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-a18c8a60bed13312",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 12,
"ts": "2026-10-14T22:44:34.241Z",
"turn": 1,
"output": {
"content": [
{
"text": "\ndrafted@1.22.8 | MIT | deps: 7 | versions: 216\nDrafted — visual thinking surface for humans and AI agents. Renders HTML, markdown, images, and code as frames on a zoomable canvas, with MCP tools for AI agents and real-time sync for humans.\nhttps://github.com/ddfourtwo/drafted#readme\n\nkeywords: design, canvas, preview, html, claude\n\nbin: drafted, drafted-mcp\n\ndist\n.tarball: https://registry.npmjs.org/drafted/-/drafted-1.22.8.tgz\n.shasum: c50ebcd9352ada9e3b162bf59188b91493c7e17a\n.integrity: sha512-KV2HPov8hbj7kqG3a6KrrHe8khiP7OWboChKzObVl+pJjyifCbtv2f0tNwTMMOO8S0NYIKuj8Nzhqi4M9fPMtg==\n.unpackedSize: 638.5 kB\n\ndependencies:\n@modelcontextprotocol/ext-apps: ^1.6.0\n@modelcontextprotocol/sdk: ^1.27.1\ncommander: ^11.1.0\nqrcode-terminal: ^0.12.0\n---\nERROR: No matching distribution found for drafted\n",
"type": "text"
}
]
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-a18c8a60bed13312",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
Drafted is an npm package — a "visual thinking surface" with an MCP tool. Seems like a local tool (running a canvas server?). Let me check whether there's a hosted product with an SDK/API. Check the README on GitHub or the contents of the npm package. Let me download the package and read its README, and check whether there's a hosted cloud API.
cd /tmp && npm pack drafted 2>&1 | tail -1 && tar xzf drafted-*.tgz && ls package && wc -l package/README.md
drafted-1.22.8.tgz
drafted-1.22.8.tgz README.md agent-instructions cli install-mcp.sh mcp package.json plugin server src 51 package/README.md
Recorded tool call
{
"type": "tool_call",
"seq": 15,
"ts": "2026-10-14T22:44:35.564Z",
"name": "bash",
"turn": 1,
"input": {
"command": "cd /tmp && npm pack drafted 2>&1 | tail -1 && tar xzf drafted-*.tgz && ls package && wc -l package/README.md",
"timeout": 60
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-b8e5bc48425f31b2",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 16,
"ts": "2026-10-14T22:44:37.253Z",
"turn": 1,
"output": {
"content": [
{
"text": "drafted-1.22.8.tgz\nREADME.md\nagent-instructions\ncli\ninstall-mcp.sh\nmcp\npackage.json\nplugin\nserver\nsrc\n51 package/README.md\n",
"type": "text"
}
]
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-b8e5bc48425f31b2",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
Let's read the README and the agent's instructions.
✓read /tmp/package/README.md✓└{"content":[{"text":"# Drafted\n\nMulti-tenant shared surface for AI-human collaboration. Drafted organizes agent-produced work into **projects** (frames on a z…ctrl+o
{"content":[{"text":"# Drafted\n\nMulti-tenant shared surface for AI-human collaboration. Drafted organizes agent-produced work into **projects** (frames on a zoomable real-time surface), **skills** (reusable operating procedures agents load), and a **wiki** (durable org knowledge) — with MCP tools for agents and a browser UI for humans.\n\n- Product vision and positioning: [PRODUCT.md](PRODUCT.md)\n- Architecture, development, and operations: [AGENTS.md](AGENTS.md)\n- Live: [drafted.live](https://drafted.live)\n\n## OKF-native\n\nDrafted is a native producer and consumer of the **Open Knowledge Format (OKF) v0.1** ([GoogleCloudPlatform/knowledge-catalog](https://github.com/GoogleCloudPlatform/knowledge-catalog)):\n\n- **The org wiki is an OKF v0.1 bundle.** Every page carries conformant YAML frontmatter (required `type`, one-line `description`, `tags`, synthesized `timestamp`; unknown keys preserved). `index.md` at every level is synthesized, `log.md` keeps the date-grouped change history, links resolve with or without `.md`, and broken links are legal. The wiki UI shows a live OKF conformance badge.\n- **Bundle exchange everywhere.** Export/import the wiki (`GET /api/wiki/export.tar.gz`, `POST /api/wiki/import`), the skill library (`skills/<slug>/SKILL.md` layout), and whole projects (`<layer>/<lane>/<file>.md` concepts; markdown links round-trip as connectors) — via HTTP or the MCP `wiki`, `skill`, and `project` tools, with dry-run reports.\n\n## Install\n\n**Claude Code, Codex, or any MCP client** — installs the MCP server, the Drafted skill, *and* the eight slash commands (into `~/.claude/commands/drafted/` and `~/.codex/prompts/drafted/`):\n\n```bash\n# macOS / Linux — download, then run the local file:\ncurl -fsSL https://drafted.live/install.sh -o /tmp/install-drafted.sh\nbash /tmp/install-drafted.sh\n\n# Windows (PowerShell) — download, then run the local file:\nInvoke-WebRequest https://drafted.live/install.ps1 -OutFile $env:TEMP\\drafted-install.ps1\npowershell -NoProfile -ExecutionPolicy Bypass -File $env:TEMP\\drafted-install.ps1\n```\n\n> **Why not `curl | bash` / `irm | iex`?** Heuristic antivirus (Norton IDP, SmartScreen) flags the pipe-to-shell pattern as download-and-execute malware. Downloading the installer to a local file and running it avoids the false-positive block.\n\n> Adding the MCP server on its own (e.g. `claude mcp add`) gives you the tools without the skill or the commands.\n\n**Claude on the web (claude.ai) and Cowork** — install the plugin, not the bare connector. The plugin bundles the Drafted connector *plus* the Drafted skill and the eight slash commands (`/drafted:onboard-drafted`, `/drafted:create-project`, `/drafted:create-skill`, `/drafted:ingest`, `/drafted:extract`, `/drafted:improve-wiki`, `/drafted:improve-skill`, `/drafted:improve-project-harness`); adding the connector URL on its own gives you the tools with none of the guidance.\n\n> 1. Settings → Customize plugins → Add → Add marketplace → `https://github.com/ddfourtwo/drafted-web` → install **Drafted**.\n> 2. Settings → Connectors → find **Drafted** → **Connect**, then approve the sign-in.\n>\n> Both halves matter: the plugin carries the skill and commands, the connector carries the tools. Installing the plugin does not sign you in to the connector.\n\n## Quick start (developing Drafted itself)\n\n```bash\nnpm install && npm run dev # Docker services + schema + server with hot reload\n```\n\n- App: http://localhost:3477\n- Email inbox (magic links): http://localhost:8025\n- MinIO console: http://localhost:9001\n\nSign in with any email and grab the magic link from Mailpit.\n","type":"text"}]}ls -R /tmp/package/agent-instructions /tmp/package/cli /tmp/package/mcp /tmp/package/server 2>/dev/null | head -60
/tmp/package/agent-instructions:
/tmp/package/agent-instructions: global.md /tmp/package/cli: drafted.mjs google-setup.sh mail-watch.mjs open-url.mjs prompts.mjs repo-scan.mjs skill-setup-trust.mjs /tmp/package/mcp: active-project-store.mjs gates.mjs gws-status.mjs repo-address.mjs server.mjs test-file-path-text.mjs test-org-guards.mjs test-project-index.mjs test-search-terms.mjs test-skill-paths.mjs widgets /tmp/package/mcp/widgets: canvas-overview.html frame-preview.html /tmp/package/server: lib /tmp/package/server/lib: umami.mjs
Recorded tool call
{
"type": "tool_call",
"seq": 20,
"ts": "2026-10-14T22:44:38.214Z",
"name": "bash",
"turn": 1,
"input": {
"command": "ls -R /tmp/package/agent-instructions /tmp/package/cli /tmp/package/mcp /tmp/package/server 2>/dev/null | head -60"
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-b7a0493094a78ba8",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 22,
"ts": "2026-10-14T22:44:38.214Z",
"turn": 1,
"output": {
"content": [
{
"text": "/tmp/package/agent-instructions:\nglobal.md\n\n/tmp/package/cli:\ndrafted.mjs\ngoogle-setup.sh\nmail-watch.mjs\nopen-url.mjs\nprompts.mjs\nrepo-scan.mjs\nskill-setup-trust.mjs\n\n/tmp/package/mcp:\nactive-project-store.mjs\ngates.mjs\ngws-status.mjs\nrepo-address.mjs\nserver.mjs\ntest-file-path-text.mjs\ntest-org-guards.mjs\ntest-project-index.mjs\ntest-search-terms.mjs\ntest-skill-paths.mjs\nwidgets\n\n/tmp/package/mcp/widgets:\ncanvas-overview.html\nframe-preview.html\n\n/tmp/package/server:\nlib\n\n/tmp/package/server/lib:\numami.mjs\n",
"type": "text"
}
]
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-b7a0493094a78ba8",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
The user asked the following: Please build a simple example using Drafted. Please tell me how pricing works. Please tell me whether it's easy to manage. Keep it lightweight: use the hosted product via SDK or API. Do not start local service stacks. If the quickstart requires that, clearly say so and stop.
The README's "Quickstart (Developing Drafted itself)" requires Docker services + npm run dev, i.e., a local service stack. However, there's a hosted product (drafted.live) with MCP tools/HTTP API. The user said to use the hosted product via SDK or API. Is there an SDK or a public HTTP API? The MCP server probably connects to drafted.live. I'll check the MCP server to find out the API base URL and authentication requirements.
grep -oE "https?://[a-zA-Z0-9./_-]+" /tmp/package/mcp/server.mjs | sort | uniq -c | sort -rn | head; echo ---; grep -iE "api[_-]?key|token|auth|login|session" /tmp/package/mcp/server.mjs | head -30
3 https://drafted.live
3 https://drafted.live
2 https://drafted.live/mcp
1 https://fonts.gstatic.com
1 https://fonts.googleapis.com
1 https://drafted.live/o/...
1 https://...
1 http://localhost
---
// ── Per-instance session ──────────────────────────────────────────
// request in runWithRequestState({...}, handler) so concurrent OAuth users
// never see each other's session or active project.
const standaloneState = { sessionId: null, projectId: null, projectMeta: null };
// Per-MCP-session sticky state. Keyed by the Drafted session id bound to
// Using a per-session bucket also fixes a multi-tenant correctness bug: with
const sessionStates = new Map();
function getOrCreateSessionState(sid) {
let s = sessionStates.get(key);
wsSessionId: null,
// HTTP/remote sessions (keyed by a real Drafted session id) must not.
sessionStates.set(key, s);
function getSessionState() {
if (rs && rs._session) return rs._session;
return getOrCreateSessionState(null); // stdio fallback
const session = getOrCreateSessionState(initial.sessionId);
// Hydrate request state from session: if the caller didn't pass an explicit
// projectId, fall back to the active project remembered for this session.
const merged = { ...standaloneState, ...initial, _session: session };
if (merged.projectId == null && session.activeProjectId) {
merged.projectId = session.activeProjectId;
merged.projectMeta = session.activeProjectMeta;
// The org guard inside the factory plumbs session/HTTP state into this
// project is the one legitimately-kept addressing root, NOT the deleted session
// A remote session is NOT an exemption: its session org is inherited (the user's default),
// Did the server reject the working org THIS session injected as X-Drafted-Org?
// write can land in an org this session isn't bound to. Echoing the session's
// row; fall back to the session context only when the response doesn't name one.
export function receiptOrg({ resourceOrgId, sessionOrg, orgList }) {
if (!rid || rid === sessionOrg?.id) return sessionOrg;
Recorded tool call
{
"type": "tool_call",
"seq": 25,
"ts": "2026-10-14T22:44:41.249Z",
"name": "bash",
"turn": 1,
"input": {
"command": "grep -oE \"https?://[a-zA-Z0-9./_-]+\" /tmp/package/mcp/server.mjs | sort | uniq -c | sort -rn | head; echo ---; grep -iE \"api[_-]?key|token|auth|login|session\" /tmp/package/mcp/server.mjs | head -30"
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-a4c9fc604000830b",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 27,
"ts": "2026-10-14T22:44:41.249Z",
"turn": 1,
"output": {
"content": [
{
"text": " 3 https://drafted.live\n 2 https://drafted.live/mcp\n 1 https://fonts.gstatic.com\n 1 https://fonts.googleapis.com\n 1 https://drafted.live/o/...\n 1 https://...\n 1 http://localhost\n---\n// ── Per-instance session ──────────────────────────────────────────\n// request in runWithRequestState({...}, handler) so concurrent OAuth users\n// never see each other's session or active project.\nconst standaloneState = { sessionId: null, projectId: null, projectMeta: null };\n// Per-MCP-session sticky state. Keyed by the Drafted session id bound to\n// Using a per-session bucket also fixes a multi-tenant correctness bug: with\nconst sessionStates = new Map();\nfunction getOrCreateSessionState(sid) {\n let s = sessionStates.get(key);\n wsSessionId: null,\n // HTTP/remote sessions (keyed by a real Drafted session id) must not.\n sessionStates.set(key, s);\nfunction getSessionState() {\n if (rs && rs._session) return rs._session;\n return getOrCreateSessionState(null); // stdio fallback\n const session = getOrCreateSessionState(initial.sessionId);\n // Hydrate request state from session: if the caller didn't pass an explicit\n // projectId, fall back to the active project remembered for this session.\n const merged = { ...standaloneState, ...initial, _session: session };\n if (merged.projectId == null && session.activeProjectId) {\n merged.projectId = session.activeProjectId;\n merged.projectMeta = session.activeProjectMeta;\n// The org guard inside the factory plumbs session/HTTP state into this\n// project is the one legitimately-kept addressing root, NOT the deleted session\n// A remote session is NOT an exemption: its session org is inherited (the user's default),\n// Did the server reject the working org THIS session injected as X-Drafted-Org?\n// write can land in an org this session isn't bound to. Echoing the session's\n// row; fall back to the session context only when the response doesn't name one.\nexport function receiptOrg({ resourceOrgId, sessionOrg, orgList }) {\n if (!rid || rid === sessionOrg?.id) return sessionOrg;\n",
"type": "text"
}
]
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-a4c9fc604000830b",
"is_error": false,
"tool_kind": "shell"
}head -80 /tmp/package/agent-instructions/global.md; echo ====; grep -iE "pric|plan|billing|free|paid|cost" -r /tmp/package --include="*.md" --include="*.mjs" | head -20
<drafted>
<drafted>
You have Drafted MCP tools — a shared surface for durable, reviewable work: produce substantive output as frames on the surface (not only in chat), put knowledge in the org wiki, and encode repeatable methods as skills. The full operating manual is the `drafted` skill installed with the plugin — follow it when working with Drafted. Address orgs by path: `fs(ls, path="/")` lists them, and `/o/<org>/<root>/...` (root ∈ wiki, skills, projects) is the canonical path form — the org is part of the path, never a separate switch. Before writing, verify the org/project echoed in the response is the one you intend.
</drafted>
====
/tmp/package/cli/repo-scan.mjs:// (slug + name). See docs/plans/org-substrate-normalization.md.
/tmp/package/cli/prompts.mjs:Output ONLY the HTML code, no explanations.`;
/tmp/package/mcp/gates.mjs:// These helpers are intentionally side-effect free (no `api()`, no network, no
/tmp/package/mcp/gates.mjs:// See docs/plans/compounding-harness.md and the Drafted "gates-checklist" frame.
/tmp/package/mcp/test-org-guards.mjs:assert.equal(stripUrlOrigin('https://drafted.live/o/acme/projects/beoflow/designs/pricing/hero.html?x=1'), '/o/acme/projects/beoflow/designs/pricing/hero.html', 'URL query params are dropped with the origin');
/tmp/package/mcp/test-org-guards.mjs: t(['plans', 'designs'], { layer: 'plans', lane: 'designs', filename: null }, 'a layer NAME as the last segment is still a lane');
/tmp/package/mcp/repo-address.mjs: * Side-effect free and network-free: probe() shells out to git, resolve() is
/tmp/package/mcp/active-project-store.mjs: * Side-effect-free on import (no network, no eager writes) so it can be unit
/tmp/package/mcp/server.mjs: UMAMI_EVENTS: Object.freeze({
/tmp/package/mcp/server.mjs: && !['designs', 'research', 'plans', 'copy', 'wireframes', 'images', 'components', 'brand-assets'].includes(last);
/tmp/package/mcp/server.mjs:// side-effect-free predicate, which IS the policy (DRAFT-36 "one rule"). Top-level
/tmp/package/mcp/server.mjs:// omission — the failure that prompted docs/plans/frame-content-search.md.
/tmp/package/mcp/server.mjs:// timeout, so a wedged/black-holed server freezes an MCP tool call for minutes
/tmp/package/mcp/server.mjs:// guards and the response org-echo so a mutation costs at most one /api/orgs hit.
/tmp/package/mcp/server.mjs: // cloneSession() can fail transiently right after the app plants the bootstrap
/tmp/package/mcp/server.mjs:// cached (5min), so repeat `whoami` calls are free; the server-side update gate still
/tmp/package/mcp/server.mjs: // instruction empty is what let agents invent their own explanation for the null ids.
/tmp/package/mcp/server.mjs: dailyLimit: z.number().optional().describe('[create|update] max deliveries per UTC day (default 50) — the cost cap.'),
/tmp/package/mcp/server.mjs:tool('screenshot', 'Render a PNG via headless browser. `scope=frame` captures a single frame; `scope=canvas` captures a region of the project surface (default 1600×1200, typically the "plans" layer). Targets are pseudo-filesystem paths: `scope=frame` takes /projects/<project>/<layer>/<lane>/<file> (or a frame URL / UUID); `scope=canvas` takes /projects/<project> with an optional `layer`.', {
/tmp/package/mcp/server.mjs: layer: z.string().optional().describe('[canvas] layer key to capture (default: plans).'),
Recorded tool call
{
"type": "tool_call",
"seq": 26,
"ts": "2026-10-14T22:44:41.249Z",
"name": "bash",
"turn": 1,
"input": {
"command": "head -80 /tmp/package/agent-instructions/global.md; echo ====; grep -iE \"pric|plan|billing|free|paid|cost\" -r /tmp/package --include=\"*.md\" --include=\"*.mjs\" | head -20"
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-a05709d3400671ff",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 28,
"ts": "2026-10-14T22:44:41.249Z",
"turn": 1,
"output": {
"content": [
{
"text": "<drafted>\nYou have Drafted MCP tools — a shared surface for durable, reviewable work: produce substantive output as frames on the surface (not only in chat), put knowledge in the org wiki, and encode repeatable methods as skills. The full operating manual is the `drafted` skill installed with the plugin — follow it when working with Drafted. Address orgs by path: `fs(ls, path=\"/\")` lists them, and `/o/<org>/<root>/...` (root ∈ wiki, skills, projects) is the canonical path form — the org is part of the path, never a separate switch. Before writing, verify the org/project echoed in the response is the one you intend.\n</drafted>\n====\n/tmp/package/cli/repo-scan.mjs:// (slug + name). See docs/plans/org-substrate-normalization.md.\n/tmp/package/cli/prompts.mjs:Output ONLY the HTML code, no explanations.`;\n/tmp/package/mcp/gates.mjs:// These helpers are intentionally side-effect free (no `api()`, no network, no\n/tmp/package/mcp/gates.mjs:// See docs/plans/compounding-harness.md and the Drafted \"gates-checklist\" frame.\n/tmp/package/mcp/test-org-guards.mjs:assert.equal(stripUrlOrigin('https://drafted.live/o/acme/projects/beoflow/designs/pricing/hero.html?x=1'), '/o/acme/projects/beoflow/designs/pricing/hero.html', 'URL query params are dropped with the origin');\n/tmp/package/mcp/test-org-guards.mjs: t(['plans', 'designs'], { layer: 'plans', lane: 'designs', filename: null }, 'a layer NAME as the last segment is still a lane');\n/tmp/package/mcp/repo-address.mjs: * Side-effect free and network-free: probe() shells out to git, resolve() is\n/tmp/package/mcp/active-project-store.mjs: * Side-effect-free on import (no network, no eager writes) so it can be unit\n/tmp/package/mcp/server.mjs: UMAMI_EVENTS: Object.freeze({\n/tmp/package/mcp/server.mjs: && !['designs', 'research', 'plans', 'copy', 'wireframes', 'images', 'components', 'brand-assets'].includes(last);\n/tmp/package/mcp/server.mjs:// side-effect-free predicate, which IS the policy (DRAFT-36 \"one rule\"). Top-level\n/tmp/package/mcp/server.mjs:// omission — the failure that prompted docs/plans/frame-content-search.md.\n/tmp/package/mcp/server.mjs:// timeout, so a wedged/black-holed server freezes an MCP tool call for minutes\n/tmp/package/mcp/server.mjs:// guards and the response org-echo so a mutation costs at most one /api/orgs hit.\n/tmp/package/mcp/server.mjs: // cloneSession() can fail transiently right after the app plants the bootstrap\n/tmp/package/mcp/server.mjs:// cached (5min), so repeat `whoami` calls are free; the server-side update gate still\n/tmp/package/mcp/server.mjs: // instruction empty is what let agents invent their own explanation for the null ids.\n/tmp/package/mcp/server.mjs: dailyLimit: z.number().optional().describe('[create|update] max deliveries per UTC day (default 50) — the cost cap.'),\n/tmp/package/mcp/server.mjs:tool('screenshot', 'Render a PNG via headless browser. `scope=frame` captures a single frame; `scope=canvas` captures a region of the project surface (default 1600×1200, typically the \"plans\" layer). Targets are pseudo-filesystem paths: `scope=frame` takes /projects/<project>/<layer>/<lane>/<file> (or a frame URL / UUID); `scope=canvas` takes /projects/<project> with an optional `layer`.', {\n/tmp/package/mcp/server.mjs: layer: z.string().optional().describe('[canvas] layer key to capture (default: plans).'),\n",
"type": "text"
}
]
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-a05709d3400671ff",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
The user wants to build a simple example using Drafted via a hosted product (drafted.live) through an SDK or API. Let me check the authentication mechanism—how does the MCP server authenticate against drafted.live? It uses OAuth (magic link email login). Without credentials, I can't sign in. Let me check whether there are any API keys or anonymous access methods. I'll look into how server.mjs makes API calls and whether an authentication token is required.
grep -nE "DRAFTED_(URL|TOKEN|SESSION|EMAIL|PASSWORD|API)|process\.env\.[A-Z_]+" /tmp/package/mcp/server.mjs | grep -oE "process\.env\.[A-Z_0-9]+" | sort -u; echo ---; grep -n "X-Drafted" /tmp/package/mcp/server.mjs | head -10; echo ---; grep -nE "magic|login|signin|sign-in|oauth|cookie" /tmp/package/mcp/server.mjs | head -20
process.env.APP_URL
process.env.APP_URL
process.env.BASE_URL
process.env.CAUSEWAY_SESSION_ID
process.env.CLAUDECODE
process.env.CURSOR_TRACE_ID
process.env.DRAFTED_AGENT_NAME
process.env.DRAFTED_AUTH_FILE
process.env.DRAFTED_PENDING_AUTH_FILE
process.env.DRAFTED_PORT
process.env.DRAFTED_PUBLIC_URL
process.env.DRAFTED_SERVER
process.env.DRAFTED_TELEMETRY
process.env.LOCALAPPDATA
process.env.MCP_HTTP_PORT
process.env.TERM_PROGRAM
---
288:// Did the server reject the working org THIS session injected as X-Drafted-Org?
319:// org, it never switches to one — and drives the per-request X-Drafted-Org, so
733:// bucket (boundOrgId → the X-Drafted-Org per-request scope). No-op when the
1054:// the X-Drafted-Org header (server: effectiveOrgId), NOT via the session — the old
1066: if (agentName) headers['X-Drafted-Agent'] = agentName;
1072:// stable surface + one playful tab name. Org isolation is per-request (X-Drafted-Org),
1202:// Personal. Used both to address requests (X-Drafted-Org) and to echo where a write
1257: if (!pid) headers['X-Drafted-Project'] = 'none';
1265: // org" churn. X-Drafted-Org is validated against the caller's memberships
1295: headers['X-Drafted-Org'] = boundOrg;
---
452:DUAL REGISTRATION IS NORMAL: a separate "Drafted" remote connector (https://drafted.live/mcp, managed by claude.ai) may appear alongside this local stdio server in MCP listings. It is NOT a duplicate and NOT broken — it serves claude.ai web/mobile/Cowork, where a local stdio process cannot run. Never advise removing it; a "needs authentication" state on it is fixed by signing in from claude.ai and does not affect this stdio session.${isRemote ? `
473: auth: { title: 'Sign in', readOnlyHint: false, destructiveHint: false, openWorldHint: true, description: 'Sign in to Drafted. `action=get_link` returns a URL immediately and starts background approval polling; after the user opens the link, later Drafted tool calls also auto-consume the approved login. `action=login` opens a browser when needed and explicitly waits/polls for approval.' },
487: mail: { title: 'Connected email threads', readOnlyHint: false, destructiveHint: false, openWorldHint: false, description: 'Connect a Gmail thread to a project so a reply to it is noticed. Drafted never reads mail: the user\'s own computer checks connected threads with their read-only gws sign-in and tells Drafted only that a new message arrived. Dispatch by `action`: connect (project, gmailThreadId, title, onReply), list (project), set (id, onReply/title), handled (id: clear the New reply mark after you dealt with it), disconnect (id). onReply: notify = mark it and tell the user; work = also start the user\'s agent on it. Read the thread itself with gws, and send any reply with action(propose, type="send_email").' },
499: // Org roster — read-only; the lookup an agent needs before assigning a task.
1053:// shared root login in ~/.drafted/auth.json. NOTE: org isolation is per-REQUEST via
1070:// Mint (or reuse) a child session from the shared root login. The server dedups by
1080: // Named agents key on DRAFTED_AGENT_NAME; anonymous agents key on the root login
1109:// A fresh clone inherits the ROOT login's current org. If this MCP session was
1138: // A pending device-code login (from `auth get_link`) takes priority; consuming
1139: // it mints this instance's own session. Otherwise clone the saved root login.
1169: `(Norton, Zscaler, Netskope, ...) is re-signing HTTPS, and Node does not use the OS ` +
1586: // inheriting the root login's current org. Only set when known — a (null,null)
1824: // No session yet (e.g. desktop sign-in still in progress) — retry instead of stranding
1889:// Identity stays the cloned gc_session id (read server-side from the cookie);
1927:// Tools that are pure introspection/sign-in, not "the agent started working" — excluded from
2176:// ── CLI passthrough (for login/start/stop only) ───────────────────
2203:// auth(action=login) or a later tool call can consume it.
2213:// MCP protocol layer (handled by Claude Code itself, see src/middleware/oauth.ts).
2231: // data.sessionId is the shared ROOT login. Persist it as the machine-level
2232: // credential, then mint a child session from it (mirrors the `auth login` tool)
Recorded tool call
{
"type": "tool_call",
"seq": 31,
"ts": "2026-10-14T22:44:43.683Z",
"name": "bash",
"turn": 1,
"input": {
"command": "grep -nE \"DRAFTED_(URL|TOKEN|SESSION|EMAIL|PASSWORD|API)|process\\.env\\.[A-Z_]+\" /tmp/package/mcp/server.mjs | grep -oE \"process\\.env\\.[A-Z_0-9]+\" | sort -u; echo ---; grep -n \"X-Drafted\" /tmp/package/mcp/server.mjs | head -10; echo ---; grep -nE \"magic|login|signin|sign-in|oauth|cookie\" /tmp/package/mcp/server.mjs | head -20"
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-ba1076d3476ba6f7",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 32,
"ts": "2026-10-14T22:44:43.683Z",
"turn": 1,
"output": {
"content": [
{
"text": "process.env.APP_URL\nprocess.env.BASE_URL\nprocess.env.CAUSEWAY_SESSION_ID\nprocess.env.CLAUDECODE\nprocess.env.CURSOR_TRACE_ID\nprocess.env.DRAFTED_AGENT_NAME\nprocess.env.DRAFTED_AUTH_FILE\nprocess.env.DRAFTED_PENDING_AUTH_FILE\nprocess.env.DRAFTED_PORT\nprocess.env.DRAFTED_PUBLIC_URL\nprocess.env.DRAFTED_SERVER\nprocess.env.DRAFTED_TELEMETRY\nprocess.env.LOCALAPPDATA\nprocess.env.MCP_HTTP_PORT\nprocess.env.TERM_PROGRAM\n---\n288:// Did the server reject the working org THIS session injected as X-Drafted-Org?\n319:// org, it never switches to one — and drives the per-request X-Drafted-Org, so\n733:// bucket (boundOrgId → the X-Drafted-Org per-request scope). No-op when the\n1054:// the X-Drafted-Org header (server: effectiveOrgId), NOT via the session — the old\n1066: if (agentName) headers['X-Drafted-Agent'] = agentName;\n1072:// stable surface + one playful tab name. Org isolation is per-request (X-Drafted-Org),\n1202:// Personal. Used both to address requests (X-Drafted-Org) and to echo where a write\n1257: if (!pid) headers['X-Drafted-Project'] = 'none';\n1265: // org\" churn. X-Drafted-Org is validated against the caller's memberships\n1295: headers['X-Drafted-Org'] = boundOrg;\n---\n452:DUAL REGISTRATION IS NORMAL: a separate \"Drafted\" remote connector (https://drafted.live/mcp, managed by claude.ai) may appear alongside this local stdio server in MCP listings. It is NOT a duplicate and NOT broken — it serves claude.ai web/mobile/Cowork, where a local stdio process cannot run. Never advise removing it; a \"needs authentication\" state on it is fixed by signing in from claude.ai and does not affect this stdio session.${isRemote ? `\n473: auth: { title: 'Sign in', readOnlyHint: false, destructiveHint: false, openWorldHint: true, description: 'Sign in to Drafted. `action=get_link` returns a URL immediately and starts background approval polling; after the user opens the link, later Drafted tool calls also auto-consume the approved login. `action=login` opens a browser when needed and explicitly waits/polls for approval.' },\n487: mail: { title: 'Connected email threads', readOnlyHint: false, destructiveHint: false, openWorldHint: false, description: 'Connect a Gmail thread to a project so a reply to it is noticed. Drafted never reads mail: the user\\'s own computer checks connected threads with their read-only gws sign-in and tells Drafted only that a new message arrived. Dispatch by `action`: connect (project, gmailThreadId, title, onReply), list (project), set (id, onReply/title), handled (id: clear the New reply mark after you dealt with it), disconnect (id). onReply: notify = mark it and tell the user; work = also start the user\\'s agent on it. Read the thread itself with gws, and send any reply with action(propose, type=\"send_email\").' },\n499: // Org roster — read-only; the lookup an agent needs before assigning a task.\n1053:// shared root login in ~/.drafted/auth.json. NOTE: org isolation is per-REQUEST via\n1070:// Mint (or reuse) a child session from the shared root login. The server dedups by\n1080: // Named agents key on DRAFTED_AGENT_NAME; anonymous agents key on the root login\n1109:// A fresh clone inherits the ROOT login's current org. If this MCP session was\n1138: // A pending device-code login (from `auth get_link`) takes priority; consuming\n1139: // it mints this instance's own session. Otherwise clone the saved root login.\n1169: `(Norton, Zscaler, Netskope, ...) is re-signing HTTPS, and Node does not use the OS ` +\n1586: // inheriting the root login's current org. Only set when known — a (null,null)\n1824: // No session yet (e.g. desktop sign-in still in progress) — retry instead of stranding\n1889:// Identity stays the cloned gc_session id (read server-side from the cookie);\n1927:// Tools that are pure introspection/sign-in, not \"the agent started working\" — excluded from\n2176:// ── CLI passthrough (for login/start/stop only) ───────────────────\n2203:// auth(action=login) or a later tool call can consume it.\n2213:// MCP protocol layer (handled by Claude Code itself, see src/middleware/oauth.ts).\n2231: // data.sessionId is the shared ROOT login. Persist it as the machine-level\n2232: // credential, then mint a child session from it (mirrors the `auth login` tool)\n",
"type": "text"
}
]
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-ba1076d3476ba6f7",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
Authentication model: Drafted uses a magic link email sign-in (device code flow). Sign-in requires a human to open the link and approve it. Without user interaction, we can't authenticate against drafted.live. Also, there's no mention of an API key. Let me check if there's pricing information — I'll check the drafted.live website, or PRODUCT.md on GitHub.
I'll try fetching the pricing page from https://drafted.live.
curl -fsSL --max-time 15 https://drafted.live/pricing 2>&1 | head -50; echo "EXIT:$?"
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pricing — Drafted</title>
<meta name="description" content="Drafted is free during early access. Commercial terms are not set yet, and this page says so rather than implying otherwise.">
<link rel="canonical" href="https://drafted.live/pricing">
<meta property="og:title" content="Pricing — Drafted">
<meta property="og:description" content="Drafted is free during early access. Commercial terms are not set yet, and this page says so rather than implying otherwise.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://drafted.live/pricing">
<meta property="og:image" content="https://drafted.live/vendor/og/drafted.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Pricing — Drafted">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://drafted.live/vendor/og/drafted.png">
<meta name="twitter:title" content="Pricing — Drafted">
<meta name="twitter:description" content="Drafted is free during early access. Commercial terms are not set yet, and this page says so rather than implying otherwise.">
<link rel="icon" type="image/svg+xml" href="/vendor/favicon.svg">
<link href="/vendor/fonts/inter.css" rel="stylesheet">
<script>window.__DRAFTED_SENTRY__ = {"dsn":"https://b441d908d503438f80820430684a01e3@errors.drafted.live/1","environment":"production","release":"mv8fl86l","buildId":"mv8fl86l","tracesSampleRate":0.05,"route":"/pricing"};</script>
<script src="/vendor/sentry-browser.js" crossorigin="anonymous"></script>
<script src="/vendor/drafted-sentry.js"></script>
<script defer src="https://analytics.drafted.live/script.js" data-website-id="94b5c73a-ecd6-4896-9362-7a917c57a6c8"></script>
<script>
window.__DRAFTED_ANALYTICS__ = {"pageType":"marketing"};
window.draftedTrack = function(name, data) {
var base = window.__DRAFTED_ANALYTICS__ || {};
var payload = Object.assign({}, base, data || {});
if (window.umami && typeof window.umami.track === 'function') window.umami.track(name, payload);
};
window.addEventListener('load', function() {
var c = window.__DRAFTED_ANALYTICS__ || {};
if (c.userId && window.umami && typeof window.umami.identify === 'function') window.umami.identify(c.userId, { orgId: c.orgId, role: c.userRole });
});
</script>
<style>
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
:root{
--bg-shell:#eef1f5; --bg-card:#fff; --bg-canvas:#111;
--text-primary:#0a2540; --text-secondary:#6b7c93; --text-muted:#9ca8b8; --text-faint:#c1c9d2;
--border:#dde1e7; --border-strong:#c1c9d2;
--accent:#533afd; --accent-hover:#6b55fd; --accent-text:#4527d4;
/* The product's chrome is LIGHT — --bg-shell #eef1f5, --bg-card #fff — and only
the canvas is dark. A dark marketing site was imitating the canvas, not the
product. Light chrome with a dark surface inside it is what the app is. */
--stage:#fff; --stage-2:#eef1f5;
--on-stage:#0a2540; --on-stage-dim:#4a5a70; --on-stage-faint:#5f6f85;
EXIT:0
Recorded tool call
{
"type": "tool_call",
"seq": 35,
"ts": "2026-10-14T22:44:46.135Z",
"name": "bash",
"turn": 1,
"input": {
"command": "curl -fsSL --max-time 15 https://drafted.live/pricing 2>&1 | head -50; echo \"EXIT:$?\"",
"timeout": 30
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-a5b870f36abe3d9e",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 40,
"ts": "2026-10-14T22:44:47.429Z",
"turn": 1,
"output": {
"content": [
{
"text": "<!DOCTYPE html>\n<html lang=\"en\" dir=\"ltr\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Pricing — Drafted</title>\n <meta name=\"description\" content=\"Drafted is free during early access. Commercial terms are not set yet, and this page says so rather than implying otherwise.\">\n <link rel=\"canonical\" href=\"https://drafted.live/pricing\">\n <meta property=\"og:title\" content=\"Pricing — Drafted\">\n <meta property=\"og:description\" content=\"Drafted is free during early access. Commercial terms are not set yet, and this page says so rather than implying otherwise.\">\n <meta property=\"og:type\" content=\"website\">\n <meta property=\"og:url\" content=\"https://drafted.live/pricing\">\n <meta property=\"og:image\" content=\"https://drafted.live/vendor/og/drafted.png\">\n <meta property=\"og:image:width\" content=\"1200\">\n <meta property=\"og:image:height\" content=\"630\">\n <meta property=\"og:image:alt\" content=\"Pricing — Drafted\">\n <meta name=\"twitter:card\" content=\"summary_large_image\">\n <meta name=\"twitter:image\" content=\"https://drafted.live/vendor/og/drafted.png\">\n <meta name=\"twitter:title\" content=\"Pricing — Drafted\">\n <meta name=\"twitter:description\" content=\"Drafted is free during early access. Commercial terms are not set yet, and this page says so rather than implying otherwise.\">\n <link rel=\"icon\" type=\"image/svg+xml\" href=\"/vendor/favicon.svg\">\n <link href=\"/vendor/fonts/inter.css\" rel=\"stylesheet\">\n <script>window.__DRAFTED_SENTRY__ = {\"dsn\":\"https://b441d908d503438f80820430684a01e3@errors.drafted.live/1\",\"environment\":\"production\",\"release\":\"mv8fl86l\",\"buildId\":\"mv8fl86l\",\"tracesSampleRate\":0.05,\"route\":\"/pricing\"};</script>\n <script src=\"/vendor/sentry-browser.js\" crossorigin=\"anonymous\"></script>\n <script src=\"/vendor/drafted-sentry.js\"></script>\n <script defer src=\"https://analytics.drafted.live/script.js\" data-website-id=\"94b5c73a-ecd6-4896-9362-7a917c57a6c8\"></script>\n<script>\nwindow.__DRAFTED_ANALYTICS__ = {\"pageType\":\"marketing\"};\nwindow.draftedTrack = function(name, data) {\n var base = window.__DRAFTED_ANALYTICS__ || {};\n var payload = Object.assign({}, base, data || {});\n if (window.umami && typeof window.umami.track === 'function') window.umami.track(name, payload);\n};\nwindow.addEventListener('load', function() {\n var c = window.__DRAFTED_ANALYTICS__ || {};\n if (c.userId && window.umami && typeof window.umami.identify === 'function') window.umami.identify(c.userId, { orgId: c.orgId, role: c.userRole });\n});\n</script>\n <style>\n*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}\n:root{\n --bg-shell:#eef1f5; --bg-card:#fff; --bg-canvas:#111;\n --text-primary:#0a2540; --text-secondary:#6b7c93; --text-muted:#9ca8b8; --text-faint:#c1c9d2;\n --border:#dde1e7; --border-strong:#c1c9d2;\n --accent:#533afd; --accent-hover:#6b55fd; --accent-text:#4527d4;\n /* The product's chrome is LIGHT — --bg-shell #eef1f5, --bg-card #fff — and only\n the canvas is dark. A dark marketing site was imitating the canvas, not the\n product. Light chrome with a dark surface inside it is what the app is. */\n --stage:#fff; --stage-2:#eef1f5;\n --on-stage:#0a2540; --on-stage-dim:#4a5a70; --on-stage-faint:#5f6f85;\nEXIT:0\n",
"type": "text"
}
]
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-a5b870f36abe3d9e",
"is_error": false,
"tool_kind": "shell"
}curl -fsSL --max-time 15 https://raw.githubusercontent.com/ddfourtwo/drafted/main/PRODUCT.md 2>&1 | grep -iE -A4 "pric|plan|free|paid|tier|cost" | head -60; echo "EXIT:$?"
EXIT:0
EXIT:0
Recorded tool call
{
"type": "tool_call",
"seq": 37,
"ts": "2026-10-14T22:44:46.135Z",
"name": "bash",
"turn": 1,
"input": {
"command": "curl -fsSL --max-time 15 https://raw.githubusercontent.com/ddfourtwo/drafted/main/PRODUCT.md 2>&1 | grep -iE -A4 \"pric|plan|free|paid|tier|cost\" | head -60; echo \"EXIT:$?\"",
"timeout": 30
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-874aa70433b4102c",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 39,
"ts": "2026-10-14T22:44:46.492Z",
"turn": 1,
"output": {
"content": [
{
"text": "EXIT:0\n",
"type": "text"
}
]
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-874aa70433b4102c",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
Checking the pricing: "Drafted is free during the early access period. Commercial terms have not yet been finalized." Let me grab more of the pricing page body text for the details.
curl -fsSL --max-time 15 https://drafted.live/pricing | python3 -c " import sys,re,html t=sys.stdin.read() t=re.sub(r'<script.*?</script>','',t,flags=re.S) t=re.sub(r'<style.*?</style>','',t,flags=re.S) t=re.sub(r'<[^>]+>',' ',t) t=html.unescape(re.sub(r'\s+',' ',t)) print(t[:3000])"
Pricing — Drafted Drafted Knowledge Skills Surface For consultancies Pricing EN / DE / NL Start a project Pricing We haven’t set a price yet Saying nothing wou
Pricing — Drafted Drafted Knowledge Skills Surface For consultancies Pricing EN / DE / NL Start a project Pricing We haven’t set a price yet Saying nothing would be easier and less honest. Here is exactly where this stands, and what we commit to when it changes. Right now Drafted is free during early access. No usage limits, no card, no seat count. That isn’t a trial with a timer on it — we would rather find out what breaks at real volume than meter you while we’re still learning. When we do set terms 60 days’ notice. Every existing organisation gets two months before anything changes, in writing. A grandfathered rate. Orgs that were here during early access keep the launch price. Nothing becomes unavailable. If you don’t like the terms, your work doesn’t become a hostage — see below. And if you walk away The wiki, the skill library and every project export as Open Knowledge Format bundles: plain markdown, an open interchange format, not a Drafted one. You can take the lot and go, and that is true today, not promised for later. It is the same reason we take the narrowest possible Google Drive scope — a tool that holds your knowledge hostage is not one you should put it in. If you need terms in writing first Plenty of firms cannot put client work through a tool without a commercial agreement and a data-processing agreement in hand. That is reasonable. Tell us what your procurement needs and we will answer specifically rather than send you a brochure. Ask us Use it while it’s free. You will get two months’ notice and the launch rate if that ever changes. Start a project → Install it Drafted Product Knowledge Skills Surface For consultancies Pricing Trust For teams vs. ChatGPT Get started Install How to use it Contact Start a project Open GitHub Trust © 2026 Drafted EN / DE / NL
Recorded tool call
{
"type": "tool_call",
"seq": 43,
"ts": "2026-10-14T22:44:49.572Z",
"name": "bash",
"turn": 1,
"input": {
"command": "curl -fsSL --max-time 15 https://drafted.live/pricing | python3 -c \"\nimport sys,re,html\nt=sys.stdin.read()\nt=re.sub(r'<script.*?</script>','',t,flags=re.S)\nt=re.sub(r'<style.*?</style>','',t,flags=re.S)\nt=re.sub(r'<[^>]+>',' ',t)\nt=html.unescape(re.sub(r'\\s+',' ',t))\nprint(t[:3000])\"",
"timeout": 30
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-a458380549e9bf67",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 45,
"ts": "2026-10-14T22:44:54.674Z",
"turn": 1,
"output": {
"content": [
{
"text": " Pricing — Drafted Drafted Knowledge Skills Surface For consultancies Pricing EN / DE / NL Start a project Pricing We haven’t set a price yet Saying nothing would be easier and less honest. Here is exactly where this stands, and what we commit to when it changes. Right now Drafted is free during early access. No usage limits, no card, no seat count. That isn’t a trial with a timer on it — we would rather find out what breaks at real volume than meter you while we’re still learning. When we do set terms 60 days’ notice. Every existing organisation gets two months before anything changes, in writing. A grandfathered rate. Orgs that were here during early access keep the launch price. Nothing becomes unavailable. If you don’t like the terms, your work doesn’t become a hostage — see below. And if you walk away The wiki, the skill library and every project export as Open Knowledge Format bundles: plain markdown, an open interchange format, not a Drafted one. You can take the lot and go, and that is true today, not promised for later. It is the same reason we take the narrowest possible Google Drive scope — a tool that holds your knowledge hostage is not one you should put it in. If you need terms in writing first Plenty of firms cannot put client work through a tool without a commercial agreement and a data-processing agreement in hand. That is reasonable. Tell us what your procurement needs and we will answer specifically rather than send you a brochure. Ask us Use it while it’s free. You will get two months’ notice and the launch rate if that ever changes. Start a project → Install it Drafted Product Knowledge Skills Surface For consultancies Pricing Trust For teams vs. ChatGPT Get started Install How to use it Contact Start a project Open GitHub Trust © 2026 Drafted EN / DE / NL \n",
"type": "text"
}
]
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-a458380549e9bf67",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
Okay, I've got a handle on the pricing details. Next, can I actually build a simple example using the hosted product via SDK or API? The MCP server at https://drafted.live/mcp uses OAuth/device code login, and requires a human to open a magic link in the browser and approve it. There's no sign of API key support. Let me quickly check whether the hosted MCP endpoint allows unauthenticated calls, or if there's some kind of anonymous access. Check the auth tools: auth(action=get_link) returns a URL that the user needs to open — requires human interaction. I can't complete sign-in on behalf of the user.
Let me quickly probe the hosted MCP endpoint to confirm the auth requirements (with a single short curl, nothing long-running).
curl -sS --max-time 15 -X POST https://drafted.live/mcp -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"probe","version":"0"}}}' -D - | head -30HTTP/2 401
HTTP/2 401
date: Wed, 14 Oct 2026 22:44:57 GMT
content-type: application/json; charset=utf-8
content-length: 24
alt-svc: h3=":443"; ma=86400
etag: W/"18-XPDV80vbMk4yY1/PADG4jYM4rSI"
permissions-policy: camera=(), microphone=(), geolocation=(), interest-cohort=()
referrer-policy: strict-origin-when-cross-origin
strict-transport-security: max-age=63072000; includeSubDomains; preload
www-authenticate: Bearer resource_metadata=https://drafted.live/.well-known/oauth-protected-resource/mcp
x-clerk-auth-reason: session-token-and-uat-missing
x-clerk-auth-status: signed-out
x-content-type-options: nosniff
x-powered-by: Express
cf-cache-status: DYNAMIC
report-to: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=TTOJv7RPKdQb5iGxm48R%2B88zueTJv1z6ja5x1GX5c7hYNz5LDpvl%2BV36VSYw%2BnYemyRX1Y%2BtAUWmGvjGX73gF2eR%2BCeGw0zFjv1a%2Bej8pwjSLjNZdT03VV1yLNh3W0o%3D"}]}
nel: {"report_to":"cf-nel","success_fraction":0.0,"max_age":604800}
server: cloudflare
cf-ray: a4aa1c92a811514d-IAD
{"error":"Unauthorized"}Recorded tool call
{
"type": "tool_call",
"seq": 48,
"ts": "2026-10-14T22:44:57.495Z",
"name": "bash",
"turn": 1,
"input": {
"command": "curl -sS --max-time 15 -X POST https://drafted.live/mcp -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2025-03-26\",\"capabilities\":{},\"clientInfo\":{\"name\":\"probe\",\"version\":\"0\"}}}' -D - | head -30",
"timeout": 30
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-b245e7f58460ce65",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 50,
"ts": "2026-10-14T22:44:58.882Z",
"turn": 1,
"output": {
"content": [
{
"text": "HTTP/2 401 \r\ndate: Wed, 14 Oct 2026 22:44:57 GMT\r\ncontent-type: application/json; charset=utf-8\r\ncontent-length: 24\r\nalt-svc: h3=\":443\"; ma=86400\r\netag: W/\"18-XPDV80vbMk4yY1/PADG4jYM4rSI\"\r\npermissions-policy: camera=(), microphone=(), geolocation=(), interest-cohort=()\r\nreferrer-policy: strict-origin-when-cross-origin\r\nstrict-transport-security: max-age=63072000; includeSubDomains; preload\r\nwww-authenticate: Bearer resource_metadata=https://drafted.live/.well-known/oauth-protected-resource/mcp\r\nx-clerk-auth-reason: session-token-and-uat-missing\r\nx-clerk-auth-status: signed-out\r\nx-content-type-options: nosniff\r\nx-powered-by: Express\r\ncf-cache-status: DYNAMIC\r\nreport-to: {\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=TTOJv7RPKdQb5iGxm48R%2B88zueTJv1z6ja5x1GX5c7hYNz5LDpvl%2BV36VSYw%2BnYemyRX1Y%2BtAUWmGvjGX73gF2eR%2BCeGw0zFjv1a%2Bej8pwjSLjNZdT03VV1yLNh3W0o%3D\"}]}\r\nnel: {\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}\r\nserver: cloudflare\r\ncf-ray: a4aa1c92a811514d-IAD\r\n\r\n{\"error\":\"Unauthorized\"}",
"type": "text"
}
]
},
"run_id": "cmv8p5x0500780iv5wl3escej",
"tool_id": "chatcmpl-tool-b245e7f58460ce65",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
Confirmed: the hosted MCP endpoint requires OAuth sign-in (401 and www-authenticate: Bearer). Sign-in is via magic-link email — a human needs to click the link. There's no API key or headless credentials mechanism. I don't have the user's credentials, and I can't complete an interactive sign-in either.
User's instruction: "If this product doesn't have an executable developer workflow, say so plainly and stop." There is a developer workflow (MCP + hosted API), but it's blocked by interactive auth. The instruction is "let me know if you get blocked." So I should report: blocked on auth — the hosted product requires an interactive magic-link sign-in that I can't complete; a simple example can't be built without the user signing in. I should stop, but I can explain the content of the example and how to unblock.
Should I try further? Maybe there's an anonymous/demo org? The auth tool's get_link returns a URL the user has to open. It's possible to install the MCP server and run auth get_link to hand the link to the user, but... that means starting a local process (though a stdio MCP server is fine — it's not a "local service stack"). But even then, constructing the example requires the user to click and approve. The instructions say "keep it light: use the hosted product via SDK or API." I'm blocked without credentials. Report frankly, stop, and provide pricing info and an assessment of how easy it is to manage.
Actually, could I run the CLI's drafted auth get-link? That would generate a device-code link the user can approve. That might be a reasonable way to unblock. But it spawns a background polling process and requires user interaction — following "say so plainly and stop," it's better to stop and tell the user what's needed. I can mention it as an unblocking path.
Let me write the final answer: what Drafted is, pricing (free during early access, no limits, no card required; 60-day notice when terms are set, launch pricing guaranteed for early-access orgs, OKF export as an exit path), feasibility of management (yes — hosted SaaS, MCP tools, markdown-native OKF export, agent-oriented instructions bundled; the only friction point: interactive magic-link auth), and that I'm blocked: the hosted API/MCP at drafted.live/mcp returns 401; auth is via OAuth device flow / magic-link email, and requires a human; API keys aren't supported. The alternative quickstart (developing Drafted itself) requires Docker + npm run dev — that's a local service stack and is prohibited by the constraints. So, following the instructions, stop.
I did the research (npm package drafted@1.22.8, its README/agent docs, and the live site). Here's where things stand — including a blocker.
What Drafted is
A hosted, multi-tenant "shared surface" for AI–human collaboration at drafted.live: projects (frames on a zoomable canvas), skills (reusable agent procedures), and an org wiki — all markdown-native in the Open Knowledge Format (OKF). Agents interact via an MCP server (https://drafted.live/mcp) or the npm CLI; there is no separate SDK — the MCP tools are the API surface.
Pricing (from drafted.live/pricing, verbatim substance)
- Free during early access — no usage limits, no card, no seat count. Explicitly "not a trial with a timer."
- When commercial terms are set: 60 days' written notice, a grandfathered launch rate for early-access orgs, and nothing becomes unavailable.
- Exit guarantee: wiki, skills, and projects all export as OKF bundles (plain markdown), today.
Will it be easy for me to manage?
Yes, in principle — it's well-designed for agent operation: a hosted product (no infra for me to run), rich MCP tools (fs, wiki, skill, project, auth, screenshot, ...), bundled agent instructions and a drafted skill that document the operating manual, per-request org scoping, and markdown/OKF everything (easy to inspect, diff, and export). The one friction point is authentication — see below.
Blocked — stopping here as instructed
A "simple example" would be: sign in, create a project, add a frame or wiki page via the MCP tools. I can't do it without you:
- The hosted API requires interactive sign-in. I probed
POST https://drafted.live/mcpand got401 Unauthorizedwithwww-authenticate: Bearer(Clerk auth,signed-out). The only credential flow is a magic-link email / device-code login —auth(action=get_link)produces a URL a human must open and approve. There is no API key or headless token mechanism, and I have no credentials for you. - The only alternative quickstart is the one you ruled out. The README's quickstart ("developing Drafted itself") is
npm install && npm run dev— a Docker service stack (app + Mailpit + MinIO) with magic links fetched from a local inbox. That's exactly the local-stack/long-running setup you told me not to start.
To unblock: either (a) sign in yourself at drafted.live and run the drafted MCP server in your own agent client (installer: curl -fsSL https://drafted.live/install.sh -o /tmp/install-drafted.sh && bash /tmp/install-drafted.sh), or (b) provide a session credential I can use (the CLI persists one at ~/.drafted/auth.json). With either in place, building the example — create a project, add a frame, write a wiki page — would take minutes.
AX Fundamentals
23 checks. Open an area for details.
This check is a quick preview. Test more tasks and models with Gauge Agents.
Test your product with Gauge Agents