Writ Cloud

Read, crawl and act on websites, signed in as the user, and turn any site into an API.

사용해야 할까요

품질 및 안전성

B
설명 품질
99%
스키마 완전성
85%
이름 품질
80%
오염 위험
80%
권한 일치
40%
프로토콜 준수
100%

발견 사항 (8)

  • HIGHTool poisoning patterns detected
  • LOWTool description contains role marker that could confuse chat modelswrit_browser_ask_user에서
  • LOWTool 'writ_browser_context' suggests web access but openWorldHint=falsewrit_browser_context에서
  • LOWTool 'writ_browser_network' suggests web access but openWorldHint=falsewrit_browser_network에서
  • LOWTool 'writ_browser_cancel' suggests web access but openWorldHint=falsewrit_browser_cancel에서
  • LOWTool 'writ_browser_sessions' suggests web access but openWorldHint=falsewrit_browser_sessions에서
  • LOWTool 'writ_diagnose_http_workflow' suggests web access but openWorldHint=falsewrit_diagnose_http_workflow에서
  • LOWTool 'writ_list_webhooks' suggests web access but openWorldHint=falsewrit_list_webhooks에서

도구 정의와 프로토콜 준수에 대한 자동 분석을 기반으로 합니다.

컨텍스트 비용

~7,694토큰 (도구 정의)
~995 B일반적인 응답 크기
상당한 주의 영향 (128k 컨텍스트의 6.01%)

이는 서버의 도구가 모델의 컨텍스트에 로드될 때마다 소비되는 대략적인 토큰 수입니다. 수치가 높을수록 다른 작업에 사용할 수 있는 주의가 줄어듭니다.

설치

원클릭 설치

`claude_desktop_config.json` 파일에 다음을 추가하세요:

{
  "mcpServers": {
    "writ-cloud": {
      "command": "npx",
      "args": [
        "writ-mcp"
      ]
    }
  }
}

실행 가능한 패키지

npmwrit-mcp1.2.0stdio

원격 엔드포인트

https://api.usewrit.app/mcpstreamable-http

할 수 있는 일

도구 목록

도구 (40)

🟢 읽기 전용🟡 쓰기🔴 삭제⚪ 알 수 없음
🔴writ_browser_use(url, persona_id, goal, use_residential, execution_target)

A REAL CLOUD BROWSER FOR A TASK ON A SITE: the user's signed-in account (a persona_id from writ_personas: the password stays sealed in Writ, and sessions never ask for a password), a click, form, submit or search inside an app, or a page a plain fetch cannot open (login wall, 403, CAPTCHA). Opens the browser and returns the first page; writ_browser_act drives it (Writ runs no model here). Recording is always on: writ_browser_save turns the session into a workflow that replays without a browser, writ_browser_cancel closes it (an open browser bills). The start answer carries the action vocabulary, the recording rules and, with a persona, the 2FA rules. NOT FOR: reading pages (writ_scrape) or building an API (writ_website_to_api).

입력 스키마

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string"
    },
    "persona_id": {
      "type": [
        "integer",
        "string"
      ]
    },
    "goal": {
      "type": "string"
    },
    "use_residential": {
      "type": "boolean",
      "description": "Open on the residential network (bot walls, CAPTCHAs)."
    },
    "execution_target": {
      "type": "string",
      "description": "cloud | auto | local (the user's own desktop app)."
    }
  },
  "required": [
    "url"
  ]
}
🔴writ_record_website(goal, url, persona_id, use_residential)

Records a repeatable task on a site as a workflow (goal + start url): the same session as writ_browser_use, labelled with its goal, driven with writ_browser_act and saved with writ_browser_save. A goal that asks for an API goes to writ_website_to_api's build instead.

입력 스키마

{
  "type": "object",
  "properties": {
    "goal": {
      "type": "string"
    },
    "url": {
      "type": "string"
    },
    "persona_id": {
      "type": [
        "integer",
        "string"
      ]
    },
    "use_residential": {
      "type": "boolean",
      "description": "Residential network (bot walls)."
    }
  },
  "required": [
    "goal",
    "url"
  ]
}
🔴writ_website_to_api(url, goal, save_as, persona_id, mode, ...)

TURNS A WEBSITE INTO A CALLABLE API (named functions with inputs, returning JSON) for a service with no practical official API. 3 calls: (1) this tool with url = the page that already shows the rows (a search-results or listing URL, not the home page) and goal = the inputs and fields wanted; (2) writ_discovery_status(build_id, wait=true); (3) on success, its run_example (writ_run_workflow with function_name). Writ builds it itself (an AI fast path in a real browser, each function live-tested) and first proposes the user's matching saved workflows and marketplace APIs (skip_existing / skip_marketplace build fresh). A sign-in wall answers persona_needed. NOT FOR: reading content (writ_scrape) or a one-off task (writ_browser_use). Modes and the guided build: writ_help('writ_website_to_api').

입력 스키마

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string"
    },
    "goal": {
      "type": "string"
    },
    "save_as": {
      "type": "string"
    },
    "persona_id": {
      "type": "integer"
    },
    "mode": {
      "type": "string",
      "enum": [
        "intelligent",
        "guided",
        "auto",
        "fast",
        "crawl",
        "browser",
        "regular",
        "deep"
      ],
      "description": "intelligent (default, Writ builds it) | guided (the caller drives) | auto | fast | crawl | browser."
    },
    "build_id": {
      "type": "integer"
    },
    "skip_existing": {
      "type": "boolean",
      "description": "Skip the proposal of the user's own matching workflows."
    },
    "skip_marketplace": {
      "type": "boolean",
      "description": "Skip the marketplace proposals."
    }
  }
}
🟢writ_discovery_status(build_id, wait, timeout_seconds)

Status of a writ_website_to_api build. wait=true is one held call (up to 75 s) that follows the build to its newest rung and returns when it is done or parked. Answers: succeeded (workflow_id, functions, run_example), failed, cancelled, or needs_guidance (the build is the caller's to finish with writ_website_to_api mode=guided build_id=<id>; its map comes with it).

입력 스키마

{
  "type": "object",
  "properties": {
    "build_id": {
      "type": "integer"
    },
    "wait": {
      "type": "boolean",
      "description": "One held call until done or parked."
    },
    "timeout_seconds": {
      "type": "integer",
      "description": "Ceiling for wait=true (up to 75)."
    }
  },
  "required": [
    "build_id"
  ]
}
🔴writ_browser_act(session_id, actions, inputs, max_chars)

Runs one batch of actions on an open session and returns the fresh page. Each action is an object, e.g. {"action":"click","selector":"#go"}. DRIVE: navigate, click, fill, type_text, select, check, hover, submit, press_key, scroll, back, wait, wait_for. SEE: query_dom, find_text, read_text, count, get_attributes, inspect, list_candidates, get_dom, get_screenshot. NETWORK: capture_network, get_request, rotate_exit. CODE: evaluate_js, search_scripts, read_script. RECORD: extract {variable,script}, api_call, login_post, probe_write, confirm_write. 2FA: twofa {challenge_method}. A value written {{name}} with its real value in `inputs` becomes a workflow input. Each action's arguments: the session's start answer, or writ_help('writ_browser_act').

입력 스키마

{
  "type": "object",
  "properties": {
    "session_id": {
      "type": "string"
    },
    "actions": {
      "type": "array",
      "items": {
        "type": "object"
      },
      "description": "Ordered action objects, e.g. [{\"action\":\"click\",\"selector\":\"#login\"}]."
    },
    "inputs": {
      "type": "object"
    },
    "max_chars": {
      "type": "integer",
      "description": "Clip of the returned page (default 40000)."
    }
  },
  "required": [
    "session_id",
    "actions"
  ]
}
🟢writ_browser_context(session_id, section)

Re-reads an open session: section=page (url, fields, buttons, cleaned DOM), lists (the page's repeating rows with a live-tested define_function payload for writ_browser_compose), map (the evidence of the build the session is bound to).

입력 스키마

{
  "type": "object",
  "properties": {
    "session_id": {
      "type": "string"
    },
    "section": {
      "type": "string",
      "enum": [
        "page",
        "lists",
        "map",
        "explorer",
        "concierge_api"
      ],
      "description": "page (default) | lists | map | explorer | concierge_api."
    }
  },
  "required": [
    "session_id"
  ]
}
🟢writ_browser_network(session_id, operation, query, method, index)

Searches (operation=search, query, method) or reads in full (operation=detail, index) the backend requests the page made after capture_network: the site's real API. An index feeds writ_browser_compose define_function from_index.

입력 스키마

{
  "type": "object",
  "properties": {
    "session_id": {
      "type": "string"
    },
    "operation": {
      "type": "string",
      "enum": [
        "search",
        "detail"
      ],
      "description": "search (default) | detail."
    },
    "query": {
      "type": "string",
      "description": "Substring filter."
    },
    "method": {
      "type": "string",
      "description": "HTTP method filter."
    },
    "index": {
      "type": "integer",
      "minimum": 0,
      "description": "detail: which call."
    }
  },
  "required": [
    "session_id"
  ]
}
🔴writ_browser_compose(session_id, operation, payload)

Authors the workflow in an open session beyond a recording: named API functions (define_function from a captured call's index or a lists payload, live-tested as defined; compile_function for an authenticated request), set_inputs, add_steps, test_function, remove_function, remove_step, list. Payload shapes: writ_help('writ_browser_compose').

입력 스키마

{
  "type": "object",
  "properties": {
    "session_id": {
      "type": "string"
    },
    "operation": {
      "type": "string",
      "enum": [
        "list",
        "define_function",
        "compile_function",
        "test_function",
        "remove_function",
        "add_steps",
        "remove_step",
        "set_inputs"
      ],
      "description": "list | define_function | compile_function | test_function | remove_function | add_steps | remove_step | set_inputs."
    },
    "payload": {
      "type": "object",
      "description": "The operation's arguments."
    }
  },
  "required": [
    "session_id",
    "operation"
  ]
}
🔴writ_browser_save(session_id, name, description, allow_no_data)

Saves the open session as a replayable workflow and closes the browser. Composed functions become callable API functions, declared inputs become its parameters. The answer carries the steps, the inputs and a run_example; the workflow runs at zero AI cost through writ_run_workflow. A save that references something no run could resolve is refused with the reasons, and the browser stays open.

입력 스키마

{
  "type": "object",
  "properties": {
    "session_id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "description": {
      "type": "string"
    },
    "allow_no_data": {
      "type": "boolean",
      "description": "Save a workflow that returns no data, on purpose."
    }
  },
  "required": [
    "session_id"
  ]
}
🟢writ_browser_ask_user(session_id, kind, question, wait_seconds)

Hands an open session to the Writ user: kind='captcha' (they complete a security check in the live browser), 'twofa' (they supply the one-time code and Writ types it; the code never reaches this conversation), or 'question' (their text answer). Holds up to 60 s; answers answered, waiting_for_user (the same call again) or expired.

입력 스키마

{
  "type": "object",
  "properties": {
    "session_id": {
      "type": "string"
    },
    "kind": {
      "type": "string",
      "enum": [
        "captcha",
        "question",
        "twofa"
      ],
      "description": "captcha | twofa | question."
    },
    "question": {
      "type": "string",
      "description": "kind='question': one short sentence."
    },
    "wait_seconds": {
      "type": "integer",
      "description": "Hold up to this long (1-60)."
    }
  },
  "required": [
    "session_id"
  ]
}
🔴writ_browser_cancel(session_id, discard)

Closes an open browser session (an open cloud browser bills until it is closed). Unsaved work that did more than visit pages is auto-saved first and the reply names it; discard=true keeps nothing.

입력 스키마

{
  "type": "object",
  "properties": {
    "session_id": {
      "type": "string"
    },
    "discard": {
      "type": "boolean",
      "description": "Throw away unsaved steps instead of auto-saving."
    }
  },
  "required": [
    "session_id"
  ]
}
🟢writ_browser_sessions(limit)

Lists the account's open cloud browser sessions (each resumable by its session_id).

입력 스키마

{
  "type": "object",
  "properties": {
    "limit": {
      "type": "integer"
    }
  }
}
🟡writ_personas(action, domain, link_id, persona_id, why)

The user's own accounts on websites (personas): how Writ signs in as them. No password passes through this tool or the conversation, and its answers never ask for one: credentials are typed only into a Writ window. action='list' domain=<site> shows the personas usable there; with none it answers persona_needed: a tell_user for the user, a create_url (a small Writ window with only the sign-in form, pre-filled for the site) and a link_id. action='wait' link_id=<id> is one held call that answers when the user saves it, with its persona_id. Also get, request (a link for another account), sign_in (refresh the session) and record_login. A persona_id works on writ_scrape, writ_crawl_site, writ_browser_use and writ_run_workflow; a desktop persona ('device:...') signs in on that desktop, from its own vault.

입력 스키마

{
  "type": "object",
  "properties": {
    "action": {
      "type": "string",
      "enum": [
        "list",
        "get",
        "request",
        "wait",
        "sign_in",
        "record_login"
      ],
      "description": "list (default) | get | request | wait | sign_in | record_login."
    },
    "domain": {
      "type": "string",
      "description": "list: personas usable on this site. request: the site."
    },
    "link_id": {
      "type": "string",
      "description": "wait: the link_id of a persona_needed / request answer."
    },
    "persona_id": {
      "type": "integer"
    },
    "why": {
      "type": "string",
      "description": "request: one line the user sees in the window."
    }
  },
  "required": [
    "action"
  ]
}
🔴writ_payment(action, site, max_amount, purpose, grant_id, ...)

Pays on a site with one of the user's cards; card numbers never reach this conversation. request (site, max_amount, purpose) returns a tell_user and an open_url where the user approves; wait (grant_id or confirmation_id); checkout pauses at the order button for the user's confirmation, then Writ places the order; fill; list (card handles only). Details: writ_help('writ_payment').

입력 스키마

{
  "type": "object",
  "properties": {
    "action": {
      "type": "string",
      "enum": [
        "request",
        "wait",
        "checkout",
        "fill",
        "list"
      ],
      "description": "request | wait | checkout | fill | list."
    },
    "site": {
      "type": "string",
      "description": "request: the store's domain."
    },
    "max_amount": {
      "type": "number",
      "description": "The most it may charge."
    },
    "purpose": {
      "type": "string",
      "description": "One line the user reads."
    },
    "grant_id": {
      "type": "string"
    },
    "confirmation_id": {
      "type": "string"
    },
    "session": {
      "type": "string",
      "description": "The browser session on the checkout page."
    },
    "commit_selector": {
      "type": "string",
      "description": "checkout: the place-order button."
    }
  },
  "required": [
    "action"
  ]
}
⚪writ_devices(action, device)

The user's linked Writ desktops: list, use (scope this connection to one: runs, browsers, personas and monitors then target it), clear, monitors, datasets.

입력 스키마

{
  "type": "object",
  "properties": {
    "action": {
      "type": "string",
      "enum": [
        "list",
        "use",
        "clear",
        "monitors",
        "datasets"
      ],
      "description": "list (default) | use | clear | monitors | datasets."
    },
    "device": {
      "type": "string",
      "description": "use: the desktop's agent_id or name."
    }
  }
}
🟢writ_list_workflows(search)

Lists the workflows saved in the Writ account; each runs on demand without live browsing. Returns id, name, declared inputs, schedule, and whether it is pinned as its own run_<name> tool.

입력 스키마

{
  "type": "object",
  "properties": {
    "search": {
      "type": "string",
      "description": "Name/description filter, e.g. a site."
    }
  }
}
🔴writ_run_workflow(workflow_id, workflow, inputs, function_name, persona_id, ...)

Runs a saved workflow by workflow_id or name and returns its extracted data (it waits by default). Inputs go as top-level fields or under `inputs`; function_name runs one function of a multi-function API (with the sign-in it needs). max_age reuses a recent result at no cost. A write function previews with mutation_mode='dry_run'. Runs sign in as the workflow's persona or persona_id; no password is ever passed. Venue, network, files and output shape: writ_help('writ_run_workflow').

입력 스키마

{
  "type": "object",
  "properties": {
    "workflow_id": {
      "type": [
        "integer",
        "string"
      ],
      "description": "A number, or 'local:<id>' (a workflow on the user's desktop)."
    },
    "workflow": {
      "type": "string",
      "description": "Workflow name (or workflow_id)."
    },
    "inputs": {
      "type": "object",
      "description": "Run inputs (top-level fields work too)."
    },
    "function_name": {
      "type": "string",
      "description": "One function of a multi-function workflow."
    },
    "persona_id": {
      "type": [
        "integer",
        "string"
      ],
      "description": "Run as this saved identity."
    },
    "max_age": {
      "type": "integer",
      "minimum": 0,
      "description": "Reuse a result younger than this many seconds (free). 0 = fresh."
    },
    "mutation_mode": {
      "type": "string",
      "enum": [
        "live",
        "dry_run",
        "private_test"
      ],
      "description": "live (default) | dry_run (preview, nothing sent) | private_test."
    },
    "execution_target": {
      "type": "string",
      "description": "cloud | auto | local (the user's own desktop app)."
    }
  }
}
🔴writ_update_workflow(workflow_id)

Inspects or edits a saved workflow: an outline, one function's source, targeted function or step edits, a settings patch. Every option: writ_help('writ_update_workflow').

입력 스키마

{
  "type": "object",
  "properties": {
    "workflow_id": {
      "type": "integer"
    }
  }
}
🔴writ_create_http_extraction(goal, workflow_id, apply)

Drafts or revises a multi-request browserless HTTP extraction (loops, GraphQL, cursor pagination) from captured requests and a plain-language goal. Every option: writ_help('writ_create_http_extraction').

입력 스키마

{
  "type": "object",
  "properties": {
    "goal": {
      "type": "string"
    },
    "workflow_id": {
      "type": "integer"
    },
    "apply": {
      "type": "boolean",
      "description": "false (default) drafts; true writes."
    }
  },
  "required": [
    "goal"
  ]
}
🟢writ_diagnose_http_workflow(workflow_id, task_id)

Explains why a saved workflow's run returned nothing or failed: HTTP-lane readiness and, with task_id, the run's requests and responses.

입력 스키마

{
  "type": "object",
  "properties": {
    "workflow_id": {
      "type": "integer"
    },
    "task_id": {
      "type": "integer"
    }
  }
}
⚪writ_pin_workflow_tool(workflow_id, pinned)

Pins (or unpins) a saved workflow as its own run_<name> tool on this server.

입력 스키마

{
  "type": "object",
  "properties": {
    "workflow_id": {
      "type": "integer"
    },
    "pinned": {
      "type": "boolean"
    }
  }
}
🟢writ_workflow_data(workflow_id, q, run_id, limit, refs)

Reads a saved workflow's collected data as a table: q filters, run_id picks one run, refs returns full records.

입력 스키마

{
  "type": "object",
  "properties": {
    "workflow_id": {
      "type": "integer"
    },
    "q": {
      "type": "string"
    },
    "run_id": {
      "type": "integer"
    },
    "limit": {
      "type": "integer"
    },
    "refs": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Full records by '<run_id>:<record_index>'."
    }
  }
}
🟢writ_search_data(q, workflow_id, limit)

Searches everything the account's workflows already collected for a term, without running anything.

입력 스키마

{
  "type": "object",
  "properties": {
    "q": {
      "type": "string"
    },
    "workflow_id": {
      "type": "integer"
    },
    "limit": {
      "type": "integer"
    }
  },
  "required": [
    "q"
  ]
}
🟢writ_export_data(workflow_id, format)

Exports a workflow's full data table as CSV or JSON.

입력 스키마

{
  "type": "object",
  "properties": {
    "workflow_id": {
      "type": "integer"
    },
    "format": {
      "type": "string",
      "description": "csv (default) | json."
    }
  }
}
🟢writ_workflow_runs(workflow_id, status, limit)

Run history (status, timing, errors, venue) of one workflow or all of them.

입력 스키마

{
  "type": "object",
  "properties": {
    "workflow_id": {
      "type": "integer"
    },
    "status": {
      "type": "string",
      "description": "Filter by status."
    },
    "limit": {
      "type": "integer"
    }
  }
}
🔴writ_set_schedule(workflow_id, every_minutes, kind, time, days, ...)

Schedules a saved workflow: every_minutes, or kind='daily'/'weekly' with time (HH:MM) and days. functions + inputs schedule chosen functions of a multi-function API.

입력 스키마

{
  "type": "object",
  "properties": {
    "workflow_id": {
      "type": "integer"
    },
    "every_minutes": {
      "type": "integer",
      "description": "Interval in minutes."
    },
    "kind": {
      "type": "string",
      "description": "interval | daily | weekly."
    },
    "time": {
      "type": "string",
      "description": "HH:MM (daily/weekly)."
    },
    "days": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "description": "Weekdays 1=Mon..7=Sun (weekly)."
    },
    "tz": {
      "type": "string",
      "description": "IANA timezone."
    }
  }
}
🟡writ_expose_workflow_api(workflow_id, label)

Publishes a saved workflow as a REST endpoint (a POST URL that waits and returns its JSON). Repeated calls reuse it.

입력 스키마

{
  "type": "object",
  "properties": {
    "workflow_id": {
      "type": "integer"
    },
    "label": {
      "type": "string"
    }
  }
}
🔴writ_crawl_site(url, intent, rank_cap, seed_urls, page_budget, ...)

COLLECTS a site or a section into a queryable, change-tracked dataset (one row per page). Scope: intent (a section, in plain words), rank_cap=N (the top N items of a listing), seed_urls (known pages), or the whole site capped by page_budget. Modes: markdown (default, no AI), extract_mode='schema' (uniform records), executor='ai' + extract_prompt (per-page understanding, 5x the page rate). A bounded crawl answers with its rows; an open one returns a crawl_id for writ_crawl_status wait=true. NOT FOR: reading a few pages now (writ_scrape). Every option: writ_help('writ_crawl_site').

입력 스키마

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string"
    },
    "intent": {
      "type": "string",
      "description": "The section wanted, in plain words; the server derives paths and depth."
    },
    "rank_cap": {
      "type": "integer",
      "minimum": 1,
      "maximum": 50,
      "description": "Top N items of a listing (one page per agent, in parallel)."
    },
    "seed_urls": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Exact pages to collect (no discovery)."
    },
    "page_budget": {
      "type": "integer",
      "description": "Cap on pages fetched."
    },
    "extract_mode": {
      "type": "string",
      "description": "markdown (default) | schema | html."
    },
    "executor": {
      "type": "string",
      "description": "regular (default, no AI) | ai (5x the page rate)."
    },
    "extract_prompt": {
      "type": "string",
      "description": "With executor=ai: what to extract from each page."
    },
    "persona_id": {
      "type": [
        "integer",
        "string"
      ]
    },
    "save_as": {
      "type": "string"
    },
    "wait": {
      "type": "boolean",
      "description": "Hold until done and return the rows (default true when bounded)."
    }
  },
  "required": [
    "url"
  ]
}
🟢writ_saved_crawls(limit)

Lists the crawls saved for re-running, with their scope.

입력 스키마

{
  "type": "object",
  "properties": {
    "limit": {
      "type": "integer"
    }
  }
}
🔴writ_update_saved_crawl(crawl, settings)

Inspects or changes a saved crawl's settings in place.

입력 스키마

{
  "type": "object",
  "properties": {
    "crawl": {
      "type": "string"
    },
    "settings": {
      "type": "object",
      "description": "Sparse settings patch."
    }
  },
  "required": [
    "crawl"
  ]
}
⚪writ_run_saved_crawl(crawl, max_age, wait)

Runs a saved crawl; max_age returns its recent data at no cost instead of re-crawling.

입력 스키마

{
  "type": "object",
  "properties": {
    "crawl": {
      "type": "string"
    },
    "max_age": {
      "type": "integer",
      "minimum": 0,
      "description": "Reuse a run younger than this (seconds)."
    },
    "wait": {
      "type": "boolean",
      "description": "Hold until done."
    }
  },
  "required": [
    "crawl"
  ]
}
🟢writ_saved_crawl_data(crawl, limit)

Reads the data a saved crawl collected on its last completed run, without crawling.

입력 스키마

{
  "type": "object",
  "properties": {
    "crawl": {
      "type": "string"
    },
    "limit": {
      "type": "integer"
    }
  },
  "required": [
    "crawl"
  ]
}
🟢writ_scrape(url, urls, top_n, format, render_mode, ...)

READ PAGES NOW, no browser session: one page (url), up to 20 pages in parallel (urls), or a listing plus its top N item pages (url + top_n). Returns clean markdown in 2-10 s, including pages a plain fetch cannot read: rendered by JavaScript (render_mode='browser'; a read that only got the page's shell says so and gives the retry), behind a bot wall or 403 (an automatic residential retry), or behind the user's sign-in (persona_id). Discussion threads keep their comments. format='html' returns the raw HTML for selectors. NOT FOR: a site-wide dataset (writ_crawl_site) or clicking and typing (writ_browser_use).

입력 스키마

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string"
    },
    "urls": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Up to 20 known pages, read in parallel."
    },
    "top_n": {
      "type": "integer",
      "minimum": 1,
      "maximum": 20,
      "description": "With url = a listing: also read its N top-ranked item pages (max 20)."
    },
    "format": {
      "type": "string",
      "enum": [
        "markdown",
        "html",
        "both"
      ],
      "description": "markdown (default) | html (raw HTML) | both."
    },
    "render_mode": {
      "type": "string",
      "description": "auto (default: HTTP, a browser when the page needs JS) | http | browser."
    },
    "persona_id": {
      "type": [
        "integer",
        "string"
      ],
      "description": "Read signed in as this saved identity (writ_personas)."
    },
    "use_residential": {
      "type": "boolean",
      "description": "Residential network for a bot wall (automatic retry when refused)."
    }
  }
}
🟢writ_crawl_status(crawl_id, wait, limit)

Status of a crawl by crawl_id; wait=true holds up to 75 s and returns the collected rows when it converges.

입력 스키마

{
  "type": "object",
  "properties": {
    "crawl_id": {
      "type": "integer"
    },
    "wait": {
      "type": "boolean",
      "description": "Hold until done and inline the rows."
    },
    "limit": {
      "type": "integer"
    }
  },
  "required": [
    "crawl_id"
  ]
}
🟢writ_crawl_files(crawl_id, crawl)

The original files (PDFs, office documents, images, CSVs) a crawl captured, with short-lived download URLs.

입력 스키마

{
  "type": "object",
  "properties": {
    "crawl_id": {
      "type": "integer"
    },
    "crawl": {
      "type": "string"
    }
  }
}
🟡writ_create_automation(name, when, schedule, on_workflow, target_id, ...)

Creates an automation: on an event (a workflow or crawl completed, a monitor change, a webhook, a schedule) it runs a workflow, sends a notification templated over the event's data, and/or wakes an AI agent. Event, template and webhook options: writ_help('writ_create_automation').

입력 스키마

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "when": {
      "type": "string",
      "enum": [
        "workflow_completed",
        "workflow_started",
        "crawl_completed",
        "crawl_failed",
        "ai_session_completed",
        "ai_session_started",
        "change_detected",
        "webhook_received",
        "scheduled"
      ],
      "description": "workflow_completed | crawl_completed | change_detected | webhook_received | scheduled | ..."
    },
    "schedule": {
      "type": "object",
      "description": "when='scheduled': {kind, interval_minutes | time, days, tz}."
    },
    "on_workflow": {
      "type": "string",
      "description": "Source workflow for workflow_* events."
    },
    "target_id": {
      "type": "integer",
      "description": "change_detected: the monitor_id."
    },
    "run_workflow": {
      "type": "string",
      "description": "Workflow to run."
    },
    "notify": {
      "type": "string",
      "description": "Message template, e.g. {{result.extracted_data.0.title}}."
    },
    "channels": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Notification channels."
    },
    "ai_prompt": {
      "type": "string",
      "description": "Wake an AI agent with this task."
    }
  },
  "required": [
    "name"
  ]
}
🟢writ_list_webhooks(webhook_trigger_id)

The account's inbound webhook URLs and the automations they fire.

입력 스키마

{
  "type": "object",
  "properties": {
    "webhook_trigger_id": {
      "type": "integer",
      "description": "Only this webhook."
    }
  }
}
🟡writ_create_monitor(url, interval, selector, extract, watch, ...)

WATCHES a page for changes: Writ checks it on a schedule and fires change_detected when the page, a CSS selector's text, a value read by `extract`, or a visual zone changes. Returns the monitor_id that writ_wire_monitor connects to an alert, a workflow or an AI task (a price watch takes a threshold there). Without `interval` the answer is needs_input: this plan's options and a tell_user for the user, nothing created. The page is read first: a sign-in answers needs_persona, a bot check offers use_residential.

입력 스키마

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string"
    },
    "interval": {
      "type": [
        "string",
        "integer"
      ],
      "description": "How often: an option id from needs_input ('5m', '1h', '24h') or seconds."
    },
    "selector": {
      "type": "string",
      "description": "CSS selector whose text is watched (unset = whole page / uptime)."
    },
    "extract": {
      "type": [
        "object",
        "string"
      ],
      "description": "Browserless read instead of a selector, e.g. {\"from\":\"html_css\",\"selector\":\".price\"}."
    },
    "watch": {
      "type": "string",
      "enum": [
        "content",
        "price"
      ],
      "description": "content (default) | price (the value must hold a number)."
    },
    "session_id": {
      "type": "string"
    },
    "persona_id": {
      "type": [
        "integer",
        "string"
      ]
    },
    "use_residential": {
      "type": "boolean",
      "description": "Check through a residential exit (bot walls)."
    }
  },
  "required": [
    "url"
  ]
}
🟡writ_wire_monitor(monitor_id, action, channels, recipients, threshold, ...)

Connects a monitor's change_detected event to an action: action='notify' (channels and recipients the account has configured), 'workflow' (runs a saved workflow), or 'ai_task' (an AI agent opens the page and works `prompt`). A price watch takes `threshold` (+ threshold_op): the action then runs once, when a check reads a price at or below it. Buying at a price (`buy`): writ_help('writ_wire_monitor').

입력 스키마

{
  "type": "object",
  "properties": {
    "monitor_id": {
      "type": "integer"
    },
    "action": {
      "type": "string",
      "enum": [
        "workflow",
        "notify",
        "ai_task"
      ],
      "description": "notify | workflow | ai_task."
    },
    "channels": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Notification channels, e.g. [\"email\",\"pushover\"]."
    },
    "recipients": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "e.g. [\"email:3\"]; omitted = every enabled recipient."
    },
    "threshold": {
      "type": [
        "number",
        "string"
      ],
      "description": "Price watch: act once when the price reaches this number."
    },
    "threshold_op": {
      "type": "string",
      "enum": [
        "lt",
        "lte",
        "gt",
        "gte"
      ],
      "description": "lte (default) | lt | gte | gt."
    },
    "workflow": {
      "type": "string"
    },
    "prompt": {
      "type": "string",
      "description": "action='ai_task': what the agent does."
    },
    "buy": {
      "type": "object",
      "description": "Run the workflow or task as a purchase (saved as a rehearsal until armed)."
    }
  },
  "required": [
    "monitor_id",
    "action"
  ]
}
🟢writ_help(topic)

The full reference of any Writ tool (every parameter and its rules) and the complete guide. topic = a tool name (e.g. 'writ_browser_compose', a 'run_<workflow>' tool), 'guide' for the manual (recurring digests, HTTP flow building, buying on a price, crawl and build modes), 'actions' / 'recording' / '2fa' for the browser rules, or empty for the list of topics.

입력 스키마

{
  "type": "object",
  "properties": {
    "topic": {
      "type": "string",
      "description": "A tool name, 'guide', 'actions', 'recording', '2fa', or empty."
    }
  }
}

커뮤니티

이 서버 평가하기

증거

최근 관측

검증됨버전이 기록되지 않음도구 40개