Assist With Plants chosen-AI setup — guide v2.17.0, describing server v2.17.0. The guide and the server ship together and share one version. A live server states its own in serverInfo.version on initialize; if the two differ, this document is stale for that server — refetch it, and trust the server's live describe over anything cached here. Two paths are described here, and the line between them is drawn precisely rather than blurred. The manual handoff works today and is proven. The remote connection is deployed and enforcing authorization today, a client can register itself against the authorization server by discovery, and Claude Cowork has connected; the current server advertises 40 tools. The repaired connection reloaded the exact catalogue then published and completed the named-client knowledge migration. A separate marked synthetic production canary proved media, replay, stale refusal, cross-surface readback, and cleanup. CURRENT: Manual, person-mediated handoff. 1. The person creates a private plant record and Queue directive in their browser. 2. They select which observations, stored research, equipment context, and location precision that package may include, then deliberately copy it to their chosen AI. Unselected records and every other plant stay in the workspace. Location defaults to undisclosed. Attachments are named in the package but never included: no file and no file link ever leaves this way. 3. The AI returns assist-with-plants-result/v1 JSON, or the richer assist-with-plants-result/v2 when it has an ordered care list to give — suggestions in the order it would do them, the urgency it thinks each carries, the person's own records behind each one, and the question only they can answer. The brief carries the exact shape of both. Either is accepted at import; neither creates a task, a due date, or work assigned to anyone. 4. The person reviews and imports it; the normal UI shows the result and activity. The brief also lists anything the person selected that it could not carry, under notIncluded. That is unread evidence, not absent evidence, and an answer that ignores it is an answer from a brief known to be short. A dated observation the person placed only in a month or a year says so; the stored date was widened so the record could sort, and nothing should reason about a day nobody wrote. Wait for the site to confirm each private write. The example return template is not a result and cannot be saved unchanged. A queued request runs nothing. It waits for the person to carry it over and stays theirs to reword, add to, or cancel. Repeating a failed step is safe: every change carries an operation id, so a retry is recognised rather than applied twice, and a write made against an out-of-date version is refused instead of overwriting what is there. Reference research does not need a Queue directive. Use plants_list_documents before repeating research, plants_search_documents for authorized title/recap/keyword or full-text matching (newest 200 Documents per full-text scan, reported when capped), and plants_read_document with its cursor until isDone. plants_save_documents accepts at most 8 items; each exact body is limited to 500,000 Unicode characters and 2,000,000 UTF-8 bytes. Retry a partial call as a whole with the same opIds. A REMOTE MCP CONNECTION AT /mcp — LIVE, PROTECTED, AND KNOWLEDGE-PROVED. LIVE AND PROTECTED, WITH THE 2.9.0 KNOWLEDGE LIFECYCLE PROVED. POST /mcp returns 401 with a WWW-Authenticate challenge pointing at this resource's RFC 9728 metadata; GET /mcp returns 405 with Allow: POST; the metadata document resolves and names the authorization server. Authorization is enforced rather than described. Claude Cowork completed sign-in and reloaded every published tool; named-client knowledge migration and the separate marked synthetic production lifecycle are recorded in the 2.9.0 receipt. Do not infer universal client or transport support. Protected-resource metadata advertises Clerk's identity scopes. The verified OAuth token proves the person and registered client; a separate durable Plants grant supplies product authority and is re-read on every call. A REAL CONNECTION EXISTS, THE AUTHORIZATION REPAIR IS LIVE, AND THE 2.9.0 KNOWLEDGE LIFECYCLE IS PROVED. The authorization server named in this resource's metadata publishes `registration_endpoint` in its /.well-known/oauth-authorization-server document, which is the document an RFC 7591 client registering by discovery reads; it is not in that host's /.well-known/openid-configuration, so read the authorization-server document. On 2026-08-17 a conforming client registered itself by reading that document and was accepted at the authorize endpoint with PKCE S256, a loopback redirect, and an RFC 8707 resource parameter naming this endpoint. That earlier probe stopped there, and the distinctions are the point: registration is not authorization, authorization is not a working connection, and a working connection is not a proved lifecycle. Claude Cowork completed that sign-in, reconnected to every tool in the published catalogue, and completed the named-client knowledge migration. OAuth sign-in proves identity; under the default Plants policy a fresh verified MCP client then receives the product-owned ordinary-care grant: read, permitted media, attributed results, ordinary record and journal writing, location context, and reported human-state context. A person may opt into approval-first, whose pending path exposes only plants_manage_connection.describe and its owner handoff. The real run then exposed a shared unknown-client grant key and omission-based relinquishment. PRs #54–#57 repaired both, and the preserved account-level connection subsequently loaded every canonical tool under a distinct starter grant. A legacy raised grant remains visible and withheld rather than silently reconciled. The 2.9.0 receipt proves connected catalogue recovery plus a separate marked synthetic media/write/UI/replay/cleanup lifecycle; do not generalize that bounded proof into support for every client or transport. SETUP IS A MANUAL ACCOUNT-SETTINGS HANDOFF. Tell the person to open their app's Settings, then Customize or Connectors, add a custom connector named Assist With Plants, paste the server URL https://www.assistwithplants.com/mcp, and leave advanced client credentials empty unless their app specifically requires them. Do not claim you changed account settings from a conversation unless you actually have that capability. After Add, tell them to choose Connect or Sign in. Verified MCP sign-in normally activates Plants' product-owned ordinary-care grant: read, including records marked private, permitted media, attributed results, ordinary record and journal writing, location context, and reported human-state context. If the account opted into approval-first, only plants_manage_connection is available; call describe and give the person its exact confirmation link. Journal writing, location, and human-state context are not separate Plants approval gates. Archive/Restore is. Every authority change also requires the person to act in Your AI settings. A client may add its own per-tool prompt policy; never claim Plants can override that client-side choice. PHOTO UPLOAD NETWORK BOUNDARY: an MCP tool call and an HTTP PUT from your code-execution sandbox may have different network policy. The only upload host to allow is www.assistwithplants.com; Backblaze is never a domain to allowlist, because the provider hop is server-side. If the PUT is refused by your sandbox, stop authorizing more uploads and explain that this is a client-owned account or organization setting which Plants cannot change. A specific-domain allowlist is enough. “All domains” also works where offered but is broader and not required. In Claude Cowork, network changes apply only to a new conversation, so tell the person to start a new chat after the setting changes; do not claim you changed their setting from the current conversation. Claude network-access controls, checked 2026-09-02: https://support.claude.com/en/articles/12111783-create-and-edit-files-with-claude Claude Cowork new-conversation rule: https://support.claude.com/en/articles/13455879-use-claude-cowork-on-team-and-enterprise-plans Other AI apps may separate connector access, tool approval, local-file access, and sandbox network egress differently. Do not invent a menu path. Name the blocked layer, ask the person to use that provider's own current settings or documentation, and use the exact first-party hostname from the upload URL. Plants will add dated client-specific directions only after that path is observed. Endpoint: https://www.assistwithplants.com/mcp USE THAT HOSTNAME EXACTLY. The bare domain canonicalizes every path to www with a method-preserving 308. OAuth resource identity is the exact www URL above; do not create a second apex connection. Protocol: MCP 2026-07-28, stateless Streamable HTTP. Initialize is accepted and answered, but creates no session id; every request is self-describing and can land on any instance. Discovery: RFC 9728 protected-resource metadata at https://www.assistwithplants.com/.well-known/oauth-protected-resource/mcp Its scopes_supported deliberately lists only identity scopes (openid, profile, email, offline_access). Do not request plants:* scopes at authorization: the OAuth token proves WHO, and the durable Plants grant separately decides WHAT — asking the authorization server for a product scope gets a refusal, not authority. Authorization server: https://clerk.assistwithplants.com Client registration, the path in use: Dynamic Client Registration is advertised as a compatibility fallback. It lets a client introduce itself through a public registration endpoint, so the name on the approval screen is not independently verified. Its presence does not prove a particular client uses it; the real Add and authorization flow decides that. Client registration, the stronger path this server also implements: Client ID Metadata Documents are the preferred path. The client's identifier is an https URL that names the client and its exact redirect URIs, so the identity can be checked without a public registration write. Clerk must advertise CIMD support and the client must actually use it before Plants can call that path Current. A client registered that way is presented to the person with this caveat, verbatim: This client registered itself on the spot rather than publishing a metadata document, so the name above is only what it calls itself — nothing independent confirms it. Approve it only if you started this connection yourself, just now. Scope plants:read: See the requests you marked ready for your AI, find the plants this approval covers, and read exactly the context and evidence you selected for one request. Scope plants:media:read: Be handed the specific images and files you attached to a request — pictures as pictures and voice notes as sound — in bounded batches. Nothing transcribes a recording. Scope plants:result:write: Save one attributed result against a request you queued, and correct that result afterwards without rewriting your original records. Scope plants:records:write: Write in your field journal as you dictate it: add dated observations in your own words, measurements with their units and method, care you observed, a new plant, a corrected name, placement or relationship state, an identity claim, a photograph attached to a plant, and the decisions and care you tell it you carried out — each one marked as written by that assistant, on the date it was written, and each held to the plants and record categories you approved. Scope plants:archive: Move a plant out of your active view, and bring it back, within the plants you approved. Archiving keeps every observation, photo, and measurement exactly where it is. Scope plants:read cannot: Open a photo or file, save anything, reach a plant outside this approval, or learn that anyone else's records exist. Scope plants:media:read cannot: Browse your files, receive a link to one, or see a file you did not attach to that request. Scope plants:result:write cannot: Edit your observations, archive, export, delete, or record a decision you made or care you performed. Scope plants:records:write cannot: Rewrite or erase an observation you already made — a correction is a new dated record naming the one it supersedes, so your original words survive beside it. Nor invent a decision or an action: those record who you said made them and are marked as reported to it, never as something it concluded. Nor remove a photograph once it has attached one; only you can, in the product. Scope plants:archive cannot: Delete anything, permanently or otherwise. Archiving is reversible by construction and there is no scope in this product that destroys a record. Scopes do not nest. Holding one never implies another, and no tool argument widens a grant. A grant holding only plants:read cannot save. The scope check and a port whose writes throw both refuse it. The three writing scopes are independent verbs and none implies another: saving your own answer, writing in the person's journal, and archiving a plant remain separately enforced even when the normal-care default deliberately issues the first two together. BATCH IS THE NORMAL CASE for every journal tool. Send one working pass — a whole garden walk — as one `items` list, not one call per record. Each item carries its own operation id and its own outcome, so a partly applied batch is recoverable: retry the same call with the same ids and it replays what landed and applies what did not. Never resend a failed batch with fresh ids; that is how duplicates happen. A batch that partly failed is NOT returned as an error. Read `saved`, `failed`, and the per-item results. WRITING A LOCATION IS NOT BEING TOLD ONE, and the two are governed separately on purpose. A named place — "the north wall bed" — is a string the person or you define, and handing it back discloses no coordinate, so places, the site record, and a plant's placeRef are writable even under an approval that will never be told where anything is. What you may be TOLD is still governed by the person's location precision, unchanged: a brief withholds a plant's whereabouts below `area` and the whole-garden site record below `region`, and says under notIncluded that it did. Put the whereabouts in a place rather than encoding it into a plant's display name. Beyond the scopes, every grant is limited by the plants it covers, the categories of record it may see, the coarsest location precision it may be told, and an expiry date. Those four start at the defaults above and the person moves any of them at /settings/ai, in either direction; the directive they prepared narrows that ceiling again. The smaller of the two limits always wins. The owner comes from the verified token. No tool accepts an owner, workspace, or account argument, so there is nothing to select, nothing to guess, and no way to reach another person's records. FIRST CALL: plants_list_directives. START HERE. Several tools take no id at all, but this one answers "what did the person mark ready for me", and every directive ref you will need comes from it. TOOLS: exactly 40, in this order. 1. plants_list_directives (plants:read) reads — Call FIRST. Lists only the requests this person marked ready for their AI, newest activity first. Each entry carries a stable directiveRef, the plant it concerns, the version you must present when saving, how fresh the context is, and what to call next. It also carries selectedCounts — how many observations, research records, care notes, and files belong to the request, counting both the records the person ticked for it and the photographs or voice notes they attached while writing it — so you can size the job before fetching anything. A media count above zero means there is something to look at or listen to: call plants_get_media_batch. It returns no results, no observations, and nothing about the rest of the workspace — this answers "what is waiting", nothing more. If a page is truncated the reply says so and gives you a cursor. 2. plants_get_workspace_overview (plants:read) reads — A compact CURRENT snapshot for deciding what to do next: active visible plant reach, Queue counts and up to eight ready requests you can actually pick up, upcoming care under the granted categories, pending AI Suggestions, freshness, omissions, and exact next-call guidance. A waiting request that names no plant is counted but not listed, because no brief can be built for one; the omissions say how many. Use this when the person asks broadly what needs attention or what you should work on, not as a mandatory preflight before every Queue job. It is NOT a workspace dump: archived, out-of-grant, disallowed-category, and undisclosed-location records are removed before anything countable, and so are the plants the person marked private unless this connection holds their “Read plants you marked private” switch. The Queue remains the person's agenda and AI Suggestions remain uncounted proposals waiting for their decision. 3. plants_search_workspace (plants:read) reads — Bounded search across the active Plants 2.0 vocabulary: plants, species, entries, insights, Queue when that ability is on, AI Suggestions, properties when location disclosure allows them, products, tools, and Library research. Returns stable refs, exact excerpts, author, date, family, bounded coverage, and the next context call. Authorization happens BEFORE matching and ranking: a hidden field cannot be discovered by guessing words from it, and archived/private/foreign/out-of-grant rows affect neither hits nor counts. Research Documents are NOT searched here — plants_search_documents searches those, and an empty answer here says so. This locates a record; call plants_get_record_context for the useful context around a stable ref. 4. plants_get_record_context (plants:read) reads — One self-contained active Plant, Species, Property, Area, GrowingPlace, Product, or Tool context by stable ref. Property, Area, and GrowingPlace keep their explicit containing chain and resident plants; a Pot/Container is never returned as a Property. Other context includes summary authorship, durable facts, relationships, recent entries, current insights, Calendar context, linked AI Suggestions, Library research, and deduplicated direct/inherited Documents for Plant and Species records. Every inherited Document labels all contributing Species ancestors with rank and distance. Everything is narrowed by the current grant and response budget. latestMeasurements gives the newest reading of every repeated measurement series (same physical subject and stable dimension) across the whole record, with how many readings each series holds — read the current trunk diameter there instead of scanning entries. A count series keeps the natural unit somebody used ("leaves", "buds", "pups") and a reading somebody estimated carries valueRange and approximate; render a span as a span and never average one into a single number. For a Plant, record.currentState is one derived line of what has recently happened — repotted into X on a date, N pups as of a date — read off dated event entries and NOT the person's summary; record.lifeStatus says the record reports the plant removed or died. lifeStatus is not Archive: the record is still active and the person can reverse it, so never archive anything because of it. Use after plants_search_workspace or when the person supplied a stable ref. Archived, private, foreign, missing and out-of-grant records fail in the same words. Property context is absent while location is undisclosed. This is read-only context, not permission to decide, perform care, change a schedule, publish, buy, or control a device. 5. plants_get_entry (plants:read) reads — One journal entry or encounter, by the entry_ or encounter_ ref plants_search_workspace and plants_get_record_context return. Carries the whole body, every measurement with its label, value, unit, subject, dimension, confidence and method, the details of any file on it, and the correction chain in both directions — what this entry superseded and what has since superseded it, so a stale reading is never quoted as current. Read-only, and authorized exactly as plants_get_record_context is: an entry on a record this approval cannot open is refused in the same words as one that does not exist, so archived, private, foreign, missing and out-of-grant are indistinguishable. Correcting an entry is a write that needs the person's own words: use plants_save_observations with supersedesRef. 6. plants_find_plants (plants:read) reads — Compact summaries of plants inside this approval, for when the person named one loosely ("the lemon by the fence") and you need the right plantRef. NOT a required first step: if you already have a directiveRef from plants_list_directives, go straight to plants_get_context. Returns name, placement, relationship, and counts only — never observations, never location beyond what this approval allows, and never a plant outside it. Search also checks the common and botanical names of an already-linked Species, but that match is only a lower-priority ranking signal: it reports an existing link and never asserts or changes the plant's identification. The plant's own display-name matches rank first. An empty result means no plant in this approval matched, not that none exists. 7. plants_area_walk (plants:read) reads — Every plant standing in one Area — and in each growing place inside it — in one read, for when the person is stood at that Area with their phone. Each plant carries its ref and name, its pot (label, kind, ref) and the pot's derived volume when the measurements support it, its primary photograph REFERENCE, the latest reading of every measurement series, the most recent dated condition note in the person's own words, the care plan with last-watered and next-due, any open identity question, and what has changed since sinceDays (default 14): new entries, moves and care actually delivered. Pass areaRef, or areaName exactly as the person said it. A composition of reads, not a new permission: archived plants are absent as they are from every other default read, a narrowed approval gets a shorter walk, and an Area this approval cannot open is refused in the same words as one that does not exist. A large Area spends detail rather than dropping plants and says so, with detailLevel and trimmed in structuredContent. This is a read: it records no visit, marks nothing inspected, and creates no task. The reply ends with the exact calls for writing down what the person dictates while stood there. 8. plants_recall_season (plants:read) reads — What was written down about one plant — or every plant in one Area — around this same calendar week in earlier years. The read a fruit journal exists for: "when did the drop start last year, and how much did we get?" Pass plantRef, or areaRef / areaName. `around` defaults to today, `windowDays` to 14 either side, `years` to 3 including this one. Every prior year is printed even when it holds nothing, because "nothing was written down" and "nothing happened" are different answers and only the first is one this record can give. Events — harvest, prune, repot, removed, died, quantityChange — are marked and sorted first inside a day. A date the person only knew to the month matches the month rather than being placed in a week it was never placed in; a date they knew only to the year is listed under that year as undated. A composition of reads, not a new permission: it is authorized exactly as plants_get_record_context is, archived plants are absent as from every other default read, and a subject this approval cannot open is refused in the same words as one that does not exist. This is a read: it records nothing and creates no task. 9. plants_list_species (plants:read) reads — Lists real, active Species records only after the current approval has been applied. Each row carries its stable speciesRef, canonical botanical name, common name, explicit aliases, curated description, and the count of visible plants currently linked to it. Exact query matching checks the canonical name, common name, aliases, and cultivar after Unicode, case, and repeated-whitespace normalization; it does not invent fuzzy synonyms. A cultivar remains distinct and is never silently collapsed into its parent species. The total and plant counts describe only records inside this approval. Optional relatedToRef + relation pages a bounded ancestor, child, descendant, or sibling view without returning an unbounded tree. Use the returned speciesRef when resolving a claim. 10. plants_list_documents (plants:read) reads — Lists active Documents inside this approval without returning full text. Filter by explicit linked record, document type, normalized keyword, author, or date and page every matching row with the stable cursor. Each row carries title, required recap and keywords, sources, visible links, exact content size/hash and the plants_read_document continuation path. Authorization and archive filtering happen before matching, counts, links and cursors. 11. plants_search_documents (plants:read) reads — Searches only Documents already visible inside this approval, then returns bounded metadata, match reasons and a short excerpt. Title, recap, keyword, author and source matching covers every visible Document. fullText=true additionally opens exact stored content, for at most the newest 200 Documents, and says so under omissions when older ones were matched on their metadata alone; it never returns the whole paper. Page until isDone rather than treating one page as the corpus, then call plants_read_document for exact content. 12. plants_read_document (plants:read) reads — Reads one integrity-checked part range from a visible Document. The reply carries SHA-256, part receipts, cursor and isDone. Continue with the returned cursor until isDone; concatenating the returned content reconstructs the exact Unicode text. Missing, reordered or corrupt parts refuse the whole read rather than returning plausible partial content. 13. plants_list_library (plants:read) reads — Pages the existing Research, Prompts and Books shelf pointers without pulling prompt or Document bodies. Use this to discover saved shelf items; use plants_list_documents for canonical Documents and plants_read_document for exact content. 14. plants_list_care_due (plants:read) reads — Which plants inside this approval are due or overdue for water or feed, ordered the way somebody walks a garden: Area, then growing place, then the plant. Each row carries the plant's ref and name, its care plan (interval, amount, trigger, and who set it), the last watering ACTUALLY RECORDED, and the next due date with how that date was worked out — either a dated task already on the calendar or the last watering plus the plan's interval. A plant with a plan and NO watering ever recorded is always listed and flagged `neverRecorded`: that is a gap in the record, not evidence the plant is dry, and the right response is to ask the person rather than to assume. Nothing here says water was delivered; a plan is what is intended. Bounded and narrowed by the current approval, and silent about Areas the person has not disclosed to this connection. 15. plants_get_context (plants:read) reads — The self-contained context for one directiveRef: the person's own words, the plant, and exactly the observations, care context, stored research, and location precision they selected for this one request — intersected with what this approval allows. There is deliberately no argument for asking for more than they selected or for finer location: those were their choices, not yours. READ notIncluded BEFORE ANSWERING: anything listed there was selected by the person and could not be carried, so it is unread rather than absent, and a confident answer that ignores it is answering from a brief you know is incomplete. An observation may carry observedAtPrecision of "month" or "year", which means the person placed it only in that month or year; the date beside it was widened so the record could sort, and reasoning about the day would be reasoning about a day nobody wrote. Photos and voice notes appear as names and captions; call plants_get_media_batch to actually see or hear them, and never answer as though you had. The reply carries the exact result schema to answer with, and queueItem.version is the expectedVersion the save will require — take it from here; no other call is needed first. After the Directive is Done, call this same tool to read back the saved summary and its currently authorized first-class Document refs; refs outside the current approval are omitted and counted without being disclosed. 16. plants_start_directive (plants:read) reads — Everything needed to begin one directive, in one round trip: the person's own words and their bounded brief, the plant's record with its containing chain, latest measurements and recent entries, a count of the evidence waiting behind the brief, and the exact assist-with-plants-result/v2 shape to answer with, printed rather than referenced. Use it instead of plants_get_context when you are about to work a request; use the separate reads when you only want one part. It composes those same reads and holds no authority of its own, so it refuses on exactly the same terms they do. Call plants_get_evidence when the brief is not enough, and plants_get_record_context with a cursor for history older than the recent entries carried here. 17. plants_get_evidence (plants:read) reads — The dated detail under one directive's selected context: observations with who made them and how precisely they were dated, measurements with units, method and confidence, research highlights with their sources and freshness, and metadata for any attached file — both the ones ticked for the request and the ones left on it in the composer, each with the mediaRef plants_get_media_batch takes. Use it when the brief's summary is not enough to reason carefully — it adds depth to the same selection, never breadth beyond it. Bounded; the reply states anything it truncated and why, and carries the same notIncluded accounting the brief does, so narrowing with include never turns a record the person selected but this workspace could not carry into a silent absence. 18. plants_get_media_batch (plants:media:read) reads — Returns the selected photos and voice notes for one request: images you can look at and recordings you can listen to. Reachable files are the ones the person ticked for that request and the ones they attached in the Queue composer while writing it — always as image or audio content, never a link, because a link can be forwarded anywhere. A voice note arrives as the recording itself: nothing in this workspace transcribes audio, so what you hear is the only account of it that exists, and you must not present a guess at it as the person's words. Ask for several at once; the batch is bounded by count and total size. Anything left out is named in the reply with a reason that tells you whether a second call would help: a file that merely did not fit alongside the others says so, and a file that cannot fit in any single call says that instead, so you stop asking rather than loop. Photographs are sent reduced for size; the person keeps the full-resolution original. A recording has no reduced copy and is sent as stored — and for that reason a recording the person uploaded from elsewhere, rather than recorded here, is withheld unless they have disclosed location to this connection: a photograph has its coordinates stripped on the way out and audio cannot, so the reply says so by name instead of guessing the file is clean. Requires the separate media scope from reading: being allowed to know a photo exists is not being handed it. The normal Plants grant includes both, while a person or client may still narrow or prompt for media. 19. plants_save_complete_result (plants:result:write) writes — Save your whole answer for one directive and move it to Done, atomically. Send everything in ONE call: all findings, all recommendations, all sources. Do not split a normal answer across several saves — one approval should cover one piece of work, and a half-saved result looks finished to the person. resultText is assist-with-plants-result/v2 JSON, whose exact shape plants_get_context gives you. Copy its resultTemplate and replace only the angle-bracket examples; workspaceRef is server-derived routing context and a stale or omitted copy cannot move the result to another workspace. Pass expectedVersion from the context and a fresh UUID as opId; retrying the identical call replays the original save rather than saving twice. This records what you found and suggested — never a decision the person made, care they performed, a diagnosis, or an outcome. Recommendations are a care list: send them in the order you would do them, most pressing first, each with the urgency you think it carries, the evidenceRefs from the brief it rests on, and a questionForOwner where only they can settle it. Order and urgency are your opinion for them to weigh — they create no task, no due date, and no work assigned to anyone. Cite generously: an evidenceRef is resolved back to the person's own record and shown beside the suggestion it supports, and a finding's sourceKeys are rendered with the source they name, so a citation is something they can open rather than a string nobody reads. To cross-reference reusable research without copying a paper, include up to 20 existing authorized stable refs in resultText.documentRefs. The entire result is refused if any Document is archived or outside the current approval. 20. plants_update_result (plants:result:write) writes — Amend a result you already saved: change the summary, replace or add findings and recommendations by their stable key, add sources, or retract something you now believe was wrong. Omitted fields stay as they are; the previous version is kept alongside the new one and the person is shown the two wordings side by side, each attributed. The five most recent versions are kept and anything older is counted rather than hidden. KEYS MATTER MORE THAN THEY LOOK: the person's own standing on a suggestion — their yes, no, or not yet — is held against its key, and the site shows them what that suggestion said at the moment they ruled on it. Reuse a key only when it is the same suggestion said better; give a genuinely different suggestion a new key, rather than letting it inherit an answer somebody gave to different words. This is for corrections and continuations — not a way to split one normal answer into several approvals. A note explaining the change is required. It cannot rewrite the person's own observations, and it cannot turn a recommendation into a decision or an action. 21. plants_suggest_directives (plants:result:write) writes — File ideas the person might want to pursue, after a walk or a batch of observations. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. Each item becomes a DRAFT on their Ideas page, attributed to you, carrying the reason you give for it — not a request, not work, and not in their Queue or any of its lanes. Nothing here is queued, started, prioritised, or handed to anyone: they turn an idea into their own request one at a time in the product, and only that click makes one theirs. An idea they do not want is put down and the reason you gave stays on the record. recommendedOrder is how you say which of THIS batch you would do first — 1 is first — and it is shown to them as your recommendation, in words, beside a list that is not sorted by it. It sets no priority, no rank, and no due date, because ordering somebody's work is theirs to do (owner ruling, 2026-08-17). Batched with a per-item opId; retrying the identical call replays rather than filing twice. File what you would genuinely want to look into — a long list of ideas is a chore you handed them, not help. 22. plants_suggest_duplicate (plants:result:write) writes — Propose ONE decision card when two visible Plant records look like they may describe the same individual. This call only files the card: it cannot link, archive, merge, reassign history, or delete anything, and no scope or grant can make it do so. The server checks the same name-and-place similarity used during capture, after reach, privacy, and archive gates. Two same-named plants may honestly be different; this is an offer, never an identification. action `possiblySame` offers only the reversible possibly-same link. action `archiveAsDuplicate` offers that link plus reversible archive of exactly one named record. The card shows the exact sentence before the person accepts, and both records, histories, entries, and media stay whole. A prior pending, accepted, or declined proposal for the pair is durable and cannot be re-filed; only the person can reopen a declined card. 23. plants_suggest_tendency (plants:result:write) writes — Propose ONE line about how this person tends to want to be worked with, for them to accept or not. It becomes a card on their AI Suggestions page showing the exact sentence; if they accept, that sentence — unchanged — joins the short list every assistant reads in plants_get_workspace_overview. Nothing is stored about them by this call. What a tendency is: a TENDENCY, not a mode and not a rule. It is what to assume before they say otherwise, and anything they say in a conversation overrides it. "Tends to want quick answers at sales" is a good one. Scope is FORMAT, DEPTH and WORKFLOW — length, order, how much reasoning, when to ask before doing. A tendency may NEVER be a reason to keep a real problem from them: anything that would hold something back, soften it, or leave it out is refused here, and you should not be composing one. If what you noticed is that they dislike hearing bad news, the thing to change is how you tell them, not whether you do. Propose one when you have seen the same preference more than once and could say when. Do not propose one from a single exchange, do not propose one they could simply tell you, and do not go looking for these — the list is capped and small on purpose, and a full one is refused until they retire something. They can retire any of them at any time. 24. plants_queue_for_later (plants:result:write) writes — Write down work THIS PERSON HAS JUST ASKED FOR and does not want done now, so you can keep talking to them instead of disappearing into a long job. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. Each item becomes an ordinary request in their Queue, in "Waiting on AI", exactly as if they had typed it themselves — counted, listed by plants_list_directives, and theirs to edit, archive or delete. It says you wrote it down and that they asked you to, for as long as it exists. Use it ONLY for work they asked for, in words you can point at: “add that to the list”, “look at that later”, “not now”. Work you merely think is worth doing is NOT this tool — that is plants_suggest_directives, and filing your own ideas here would fill their agenda with things they never asked for. If you are not sure which you have, you have a suggestion. NOTHING RUNS ON ITS OWN. Filing here starts no work, picks nothing up, and does not hand the job back to you: the Queue moves when the person asks an assistant to check it, and not before. It also decides nothing — leaving visible work the person asked for is the opposite of deciding for them. Word each item as the request THEY would write, in their voice, and tell them what you wrote down. Batched with a per-item opId; retrying the identical call replays rather than filing twice. 25. plants_save_observations (plants:records:write) writes — Write dated observations or a clean measurement-only session into the person's field journal. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. Set kind=measurement when no observation was made; those readings become a Measurement entry rather than an invented observation. WHEN SOMETHING HAPPENED rather than was seen — repotted, pruned, removed, died, three pups now two — use the matching event kind with the `event` object; it becomes a dated event on the plant and updates what the record says it currently stands at. FRUIT PICKED is kind=harvest, with the amount and the unit they used, so next year's "how much did we get" is answerable. TO FIX ONE FIELD of something already written, use kind=correctEntry with `changes`; that is also how a plain observation becomes an event without being erased. For observations, preserve THEIR words as they dictate them — a garden walk, a repotting, a week of watching a symptom. Send the whole pass in ONE call: `items` is a list, and each item is one observation with an optional list of measurements taken at the same moment, so "the lime's edges are yellowing, trunk is 42mm" is one item and not two approvals. THE TEXT FIELD HERE IS `note` — what the person saw, in their words. Retrying the call replays what already saved and applies what did not, so a dropped response is safe to retry whole. Record what they SAW, not what you concluded — your reasoning belongs in plants_save_complete_result. Everything here is append-only: nothing is ever rewritten and nothing is ever deleted. If they place something only in a month or a year, say so in `observedAt` rather than choosing a day for them. When `note` is what they actually said, relayed word for word, set `personsOwnWords` — the record will show it as their words rather than yours, and every assistant reading it later will know it is a quotation and not a summary. A loose encounter may name an encounterPlaceRef and a candidate Species or label; the candidate is never silently promoted into certainty. THE CAPS: at most 25 items per call and 25 measurements per item — a longer walk is two calls, and the refusal happens before anything is written, so nothing half-applies. Every measurement names its physical subject and stable dimension, and keeps the value and unit exactly as taken; a container height or a plant-part thickness never becomes plant growth. 26. plants_save_species (plants:records:write) writes — Save real Species records and connect current identity claims to them. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. Send one to 25 items. There is no bare `species` field: a new Species is an item whose `kind` is `newSpecies`, carrying `botanicalName` and `commonName`. `newSpecies` requires both a canonical botanical name and a common name; it may include explicit aliases, cultivar, relationship, and a curated description. `correctSpecies` changes the same durable record without changing its speciesRef and keeps an append-only identity revision. `resolveClaim` resolves an unsuperseded botanical or common-name claim by exact canonical/alias matching inside this approval, or by an explicit speciesRef returned by plants_list_species. YOU DO NOT NEED resolveClaim FOR A PLANT YOU ARE ABOUT TO CREATE AND ALREADY KNOW: put the Species' `speciesRef` on the `newPlant` item in plants_save_plant_records, and the server writes the same dated claim and the same resolution event there, in one call. resolveClaim is for a claim that already exists — yours, the person's, or one made before either of you. No match remains a proposal and multiple matches remain ambiguous; neither fabricates a link. Plant-type and rootstock claims are not Species identity. Cultivar claims resolve only to an explicitly named Species record with the same cultivar and owner-backed known evidence; otherwise they remain proposals for review. `clearClaimResolution` removes only the effective link and appends history. Superseding a resolved claim likewise clears the old effective link without deleting either claim or resolution. Exact retries replay the original per-item outcome—including proposals, ambiguity, and unchanged results—and an opId reused for different content is refused. A REFUSED item is the exception: it wrote nothing and consumed nothing, so correct it and send it again under the same opId. `newTaxonomyNode` creates a broader or narrower Species-like node with a descriptive rank; `setTaxonomy` explicitly sets, changes, or clears one parent/rank using expectedTaxonomyRevision and a reason. parentKey may name a node created earlier in the same batch. Taxonomy never comes from name parsing or changes claim resolution. A narrowed plant approval cannot create an unlinked workspace-wide Species record. 27. plants_save_documents (plants:records:write) writes — Directly saves reusable research without requiring a Queue Directive. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. Send one to eight items, each with a stable opId and kind newDocument or correctDocument. Every item requires title, useful recap, at least one keyword, and exact full content; correctDocument also requires documentRef and expectedVersion. Content supports up to 500,000 Unicode characters and 2,000,000 UTF-8 bytes and is stored in integrity-checked immutable parts. Optional explicit links may name Species, Plant, Product, Tool, Property, Area, GrowingPlace or Directive refs inside this approval. Links are never inferred from prose. Exact retries replay; changed content under an applied opId or a stale version refuses per item without partial success. A refused item wrote nothing and consumed no opId: correct it and resend it under the same one, alongside the items that already landed, which replay rather than saving twice. 28. plants_save_plant_records (plants:records:write) writes — Change how a plant is recorded, rather than what was observed about it. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. Eight kinds, all batched in one `items` list: `newPlant` starts tracking one (needs an approval covering the whole workspace, since a new plant cannot be on a list approved in advance, and takes summaryNote, placeRef, `areaRef` or `areaName`, an inline `newGrowingPlace` with its tape-measure dimensions, and an optional first observation at creation so a brand new plant needs neither an immediate correction nor a second call to start its history — THAT FIRST OBSERVATION'S TEXT FIELD IS `observation`, where plants_save_observations spells the same kind of sentence `note`); `movePlant` records that it moved — a date, and a destination named however you can name it (`toGrowingPlaceRef`, `newGrowingPlace`, `toAreaRef` or `toAreaName`) — appending a dated placement and a timeline entry and LEAVING THE DISPLAY NAME ALONE, so "when did this move and where was it before" is answerable instead of being lost to a rename; `correctPlant` fixes the display name, placement, or relationship state, and never changes the plantRef, so old briefs and results still resolve — the name it replaced and the span the old relationship covered are both kept, dated; `identityClaim` records what the plant is believed to be — yours are saved as inferred, and a claim never overwrites an earlier one, it supersedes it, with `supersedeReason` saying why the earlier one stopped holding. IF YOU ALREADY KNOW WHAT THE PLANT IS AND THE SPECIES RECORD EXISTS, put its `speciesRef` on the `newPlant` item: the server expands that ref into the same dated claim and the same resolution event, in your name. Use identityClaim when you are NOT sure. `resolveIdentity` SETTLES ONE — promote a candidate to confirmed once the tag is found, or walk one back — as a new dated claim superseding the old, linking the Species when the identity is confirmed; `openQuestion` records a question the person raised that nobody can answer yet, and it comes back on later reads; `closeQuestion` answers one and keeps it. `connectObservation` attaches an earlier unrecognised observation to the plant it turned out to be. Use this for the record's identity. Use plants_save_observations for what was seen. A NURSERY HAUL IS ONE CALL: give each `newPlant` item a `key` of your choosing, and later items in the same list may say `plantKey` instead of `plantRef` to name the plant that item creates. Keys resolve top-down (declare before use), are unique within the call, and are never stored; results carry real refs. If a keyed batch partly fails, retry the WHOLE call with the same opIds. Before a newPlant is created, the server compares it with visible active and archived plant records. A possible match refuses only that item and returns candidate refs; use the existing ref if it is the same individual. If it is honestly a different individual, retry that item with its SAME opId and `confirmDistinct: true`. THE COMPARISON IS MADE ON THE NAME WITH ITS TRAILING PARENTHETICAL SET ASIDE, so two plants that merely share a patio in their names are not offered as twins, and neither are two that differ only by a colour word. Put the place in `areaName`, not in the name. 29. plants_set_primary_images (plants:records:write) writes — Choose, change, or clear the primary image shown for one or more Plants, Species, Products, or Tools. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. This is deliberately separate from upload order. Each item also carries its own expectedRevision: an identical retry replays, while stale or changed input refuses without replacing somebody else's curation. mediaRef must name an active sealed display image attached to that exact record; null clears the choice. 30. plants_attach_photo (plants:records:write) writes — Attach ONE photograph to a Plant, Species, Product, Tool, or loose Encounter as evidence that stays on the record. For sourced reference media, send recordType + recordRef and the complete supported license package; unknown or inconsistent licensing is refused before storage. Existing person-originated Plant-photo flows may continue to use plantRef. BYTE-CAPABLE CLIENTS SHOULD USE THE THREE-STEP BYTE FLOW: call with mode `begin_upload`, PUT the local file bytes to the returned short-lived first-party URL using the exact Content-Type, then call with mode `finish_upload`. The URL is returned as `structuredContent.upload.url` and is also written into the reply text. It stays on www.assistwithplants.com so the person never has to allowlist the private storage provider. Claude Code can do the PUT with curl --upload-file, which avoids asking a language model to reproduce high-entropy base64. Do not echo the signed URL into the conversation. The server verifies exact length, MIME, SHA-256 and B2 version before attaching, preserves the exact private original (including EXIF/GPS), and creates metadata-free sealed display copies. Location is controlled when bytes are disclosed, not by silently changing the person's private evidence at ingest. IF THE PUT IS BLOCKED BY A CLIENT-SIDE NETWORK POLICY, do not retry begin_upload: that only creates more expiring authorizations. The exact host to allow is www.assistwithplants.com, never a Backblaze domain. This is the person's AI account or organization setting, not a Plants grant. Ask them to change it if they choose; some clients, including Claude Cowork, require a new chat or session before a network-policy change applies. IF YOU CANNOT MAKE HTTP REQUESTS — most chat clients cannot — do not attempt begin_upload. Use mode `fetch_url` with `sourceUrl` set to a public https address of the image and the server fetches it for you, or send inline `imageBase64` for a small file. `fetch_url` follows at most two redirects, accepts only public https addresses on the default port, and refuses anything that is not JPEG, PNG or WebP by both its declared type and its own bytes; the licensing rules for sourced media are exactly the same as for every other mode. This is the write side of plants_get_media_batch: the photo becomes a file on the plant, readable back by you and by whichever assistant reads this record next season, which is the difference between an identification somebody can check and one they have to take your word for. It is recorded as attached BY YOU, named and dated — an AI-attached photograph is never presented as one the person took. It is stored as a new labelled Private item; you cannot share it, publish it, or change its visibility. One photograph per call, unlike every other write tool here: the other batches carry sentences and this one carries megabytes, so a batch would be one enormous request that fails whole. JPEG, PNG or WebP only, and no larger than 2MB before encoding — that is exactly what one reply can hand back, so anything this accepts is something an assistant can be shown again. A modern phone photo is usually larger: DOWNSCALE ON YOUR SIDE before sending — about 1600px on the long edge as JPEG comfortably fits and keeps every detail an identification needs (the person's own uploads are reduced to the same size). THE LOOP CONTRACT for a set (leaves, thorns, petiole, fruit, whole tree): one call per photo, each with its own fresh opId, in the order you want them kept — attachment order is their stable order. If photo 6 of 10 fails, the first five are attached and stay attached; fix and resend the failures with their ORIGINAL opIds, and a retry of one that actually landed replays rather than duplicating. Give every photo of a set a caption naming what it shows ("petiole close-up, underside") — the caption is how that exact picture is addressed later. A client that supports independent concurrent tool calls may process a small bounded number in parallel, but must keep each photo's opId, uploadRef, URL, bytes, and finish call paired; never put several files into one PUT. Pre-size and hash the whole set first, then retry only failed lanes. If direct upload is impossible, a locally resized JPEG/WebP is an acceptable inline fallback, but say that it is a reduced copy; never imply it is the original or that metadata survived re-encoding. Camera GPS remains only in the private original. It is removed from ordinary display copies and withheld or sanitized whenever the person's disclosure settings do not allow it. Photos captured inside some chat apps, including Claude, commonly arrive as WebP with no EXIF at all; a gallery JPEG may retain EXIF. Never promise a capture time or location you did not receive. Send a fresh UUID as opId; retrying the identical call replays the original attachment rather than storing the picture twice. There is no argument for whether the photograph shows where the person lives, deliberately — that is their judgement about their own property, and you have not been told where it is. You cannot delete it afterwards; only they can, in the product. Attach what is worth keeping. 31. plants_save_site_record (plants:records:write) writes — Record the facts that govern every plant at once — hardiness zone, frost dates, the lot and its dimensions, which way the house and yard face, and the microclimates the person knows about, like a wall whose south face bakes all afternoon. Write it once and every future answer starts from the same facts instead of re-deriving or guessing them. Every section is free text on purpose: "9a to 9b for this ZIP" and "first frost usually late November, but the north bed goes earlier" are what the person actually knows, and a form would throw away the qualification that makes them useful. There is one such record per workspace and this replaces the sections you send: a section you omit is left exactly as it is, and an empty string clears one. Send a fresh UUID as opId; retrying the identical call replays rather than writing twice. Writing this does not let you read it back — what you may be TOLD about where the person lives is governed by the location precision they chose, and this tool does not change that. 32. plants_save_places (plants:records:write) writes — Create a lightweight public or third-party spot for an encounter, or correct a legacy Place recorded before the typed growing-context model. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. `newEncounterPlace` takes a name and optional coordinates, address, and free text. It is not part of Property → Area → growing-place, must not be used for where the person lives, and can be attached to a loose observation with encounterPlaceRef. `correctPlace` may fix its label or detail, but cannot change its kind: that would silently reinterpret history. Do not create new generic Places. Use plants_save_growing_contexts for a real Property, named Area, Ground Plot/Bed, Planter, or Pot/Container. A reviewed classification keeps the original Place unchanged. 33. plants_save_growing_contexts (plants:records:write) writes — Create or use the garden's truthful physical chain: a real Property such as a home or yard contains named Areas, and an Area contains Ground Plot/Bed, Planter, or Pot/Container records. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. A growing place can hold several plants. This tool never guesses a level from a label and never reclassifies a legacy Place. Four batched operations: `newProperty` creates a real place boundary; `newArea` requires its explicit propertyRef; `newGrowingPlace` requires its explicit areaRef and concrete growingPlaceKind; and `placePlant` records a dated move using refs returned by this tool. You may provide a partial chain for placePlant, but every supplied ref must agree with the stored chain. Retrying the same opId and payload replays; reusing it for different work is refused. Location facts are returned only when the connection's location ceiling permits them. The older plants_save_places tool remains available only for compatibility with records created before this typed hierarchy. 34. plants_save_collections (plants:records:write) writes — Five citrus bought together, planted in one row, on one irrigation regime — one collection, so advice lands once instead of five times. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. Create the groupings a person already has in their head: a bed, a row, a project, the ones they are worried about. Four kinds: `newCollection` names one and can fill it in the same item by passing plantRefs; `correctCollection` fixes its name, kind, or notes; `addPlants` and `removePlants` change who is in it. newCollection is matched by name, ignoring case and surrounding spaces, so a collection you already made comes back rather than being duplicated. addPlants is safe to repeat — a plant already in the collection is reported as already there, not refused. removePlants takes a plant OUT OF THE COLLECTION and does nothing else: no record, observation, or photograph is touched, and the plant stays exactly where it was. Collection membership comes back to you on plants_find_plants and in the brief, so you can see what you grouped. 35. plants_save_equipment (plants:records:write) writes — Record what the person bought or uses on the garden: a fertilizer, an amendment, a drip timer, a pruning saw. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. Two kinds: `newProduct` for something consumed or applied (say how it was identified — label, receipt, recollection — so the record carries its own confidence), `newTool` for something kept and reused. Put the label's actual text, rates, and model numbers in `detail`: that is what a later answer about "how much of the citrus food" reads. These records come back through plants_search_workspace and plants_get_record_context under the careContext category. Use plants_attach_photo with recordType Product or Tool and the returned ref for a license-verified reference image; still transcribe useful label text into `detail`, because an image is evidence rather than searchable instructions. Recording that a product was APPLIED to a plant is the person's reported care: use plants_record_human_states for that, in their words. 36. plants_record_human_states (plants:records:write) writes — Write down a decision the person made, or care they tell you they performed. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. ONLY ever transcription: `decidedBy` and `performedBy` name the person, and this site stamps your name on the record as the assistant that wrote it down, so it reads as "reported" and not as "concluded". Never call this because you recommended something and it seemed agreed — a recommendation of yours goes in plants_save_complete_result and becomes a decision only when the person says it did, in words you can point to. Do not record an action you did not hear them say they took. The normal Plants grant includes this category, and every row remains visibly reported and attributed. 37. plants_save_care_plans (plants:records:write) writes — Record the watering or feeding plan for a plant: how many days between waterings, how much, what to check first, and why. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. This is the answer to "how often and how much do I water this" written down where the person can see and edit it, instead of said once in a conversation that ends. A PLAN IS A SETTING, NEVER A RECORD THAT WATER WAS DELIVERED — say so when you report back, and use plants_log_care for a watering the person tells you they did. Creating a plan with `intervalDays` also puts the next few dated tasks on the person's calendar, exactly as their own Add-task dialog does, so the plan is something they can tick off. If you send no `amountValue` but do send `containerVolumeLitres`, the amount is derived at 15–20% of the container's volume and the plan records that it was derived, the volume, and the fraction — a rule of thumb the person can see the working of. A plan the PERSON set is theirs: this refuses to overwrite one, and the way to change it is plants_suggest_directives or their own calendar. 38. plants_log_care (plants:records:write) writes — Record a watering or feeding the person says they performed: when, how much, and how. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. This writes the same Care entry that ticking a task off their calendar writes, which is what makes "when was this last watered" answerable at all — and it is the ONLY thing in this catalogue that answers it. `performedBy` names the person; this site stamps your name on the row as the assistant that wrote it down, so it reads as reported. NEVER record a watering you inferred, assumed from a plan, or recommended and believe was followed. If you are not repeating something they told you, do not call this. It does not mark any calendar task done either — completing their tasks is theirs. 39. plants_archive_plants (plants:archive) writes — Move plants out of the active list, or restore them — a plant that died, was given away, or was a duplicate. OPERATION IDS LIVE ON THE ITEMS, NOT THE CALL: there is no top-level operationId here — every entry in `items` carries its own `opId`, a UUID you generate for that entry and resend verbatim only to retry that same entry. Nothing is deleted: every observation, measurement, and photo stays exactly where it is, and the same call with `archived: false` undoes it. This needs its own approval, separate from writing records, so an assistant that records a whole season need not also be one that decides a plant is finished. Ask the person before archiving something you merely infer is gone. 40. plants_manage_connection (plants:read) writes — Read this connection's current authority or make one explicit authority operation. Under the default policy it is part of the normal starter catalogue. If the account requires approval for new connections, it is the only listed tool while pending and only `describe` is callable; that returns the owner's confirmation link while holding no Plants data authority. `describe` returns disjoint held-now, available-to-request, pending-owner-approval, and legacy-review fields plus authorityRevision. `request_access` is additive only: it never changes or removes live authority, and returns a link for the person to approve the exact stored request. `relinquish_access` is retained for compatible clients but changes nothing; it sends the person to Your AI settings, because every live permission or authority change requires their explicit action. Requests require a stable opId and the revision from describe, so retries are idempotent and concurrent changes fail without mutation. Permanent deletion, sharing, invitations, purchases, outside-world action, and changing the person's AI-permission policy are never available here. STALE TOOLS: every tools/list reply carries a catalogue version. If a call fails because a tool is gone, refetch the list and compare that version before treating the server as broken. APPROVAL: OAuth proves the person and stable MCP client; Plants authority remains a separate product grant. THE STANDING AUTHORITY RULES, the same sentences plants_manage_connection.describe serves live: - Normal authority after verified OAuth: plants:read, plants:media:read, plants:result:write, plants:records:write, across every ordinary record category (observations, measurements, research, careContext, identityClaims, relationships, mediaMetadata, humanStates) and the person's permitted location context, for 30 days. Plants issues and receipts this authority separately from OAuth identity. Approval-first accounts still require a confirmation click. - That baseline is the "ordinary-care" policy, version 1 — the product owner's deliberate decision of 2026-08-19, reaffirmed 2026-08-26. Every grant records which policy issued it and when; describe returns that provenance as signInBaselinePolicy. - Never in that normal grant: plants:archive. Archive/Restore needs the person's own click. - Requesting access never changes or removes live authority. It files one exact request and returns a link for the person; only their click can approve it. - No assistant operation changes live permission or authority. To narrow, widen, revoke, or change connection policy, the person acts in Your AI settings. - A connected client may still apply its own per-tool prompt or block policy; Plants does not override client-side approval controls. - No approval this product can issue ever allows export, permanent deletion, sharing, messaging, purchasing, scheduling, equipment control, or any action outside this record. The exact system-issued receipt is stored in Plants and existing grants are not rewritten. Archive/Restore is raised at /settings/ai or on a request you file with plants_manage_connection. Ask once, hand over the URL, and carry on with what you can already do; do not retry a filed request and do not report a pending one as an error. A PENDING CONNECTION IS NOT A BROKEN SERVER. When the account opted into approval-first, a fresh client's tools/list shows exactly one tool — plants_manage_connection — until the person confirms starter access. Call describe: it returns the state, the reason, and the exact confirmation URL to hand the person. After they allow it, refetch tools/list for the full catalogue. DESCRIBE, precisely: plants_manage_connection.describe returns four disjoint authority views — heldNow (what this connection holds right now), availableToRequest (what it could file a request for), pendingOwnerApproval (an exact filed request awaiting the person), and legacyAuthorityReview (older stored authority withheld until the person reviews it) — plus signInBaseline and signInBaselinePolicy: which policy produced the baseline, its version, and when the owner decided it. The four never overlap; read each for what it is. NOTES TO THE OWNER are refused over their limit, never silently truncated: a request_access note caps at 1000 characters, and an over-limit note is rejected whole so your words are never cut mid-sentence on the person's screen. Changing approval-first does not rewrite active or revoked grants. A still-pending verified client adopts the current policy on its next authenticated call; later raised requests keep their own lifecycle. AUTHORITY CHANGES: request_access is additive only and changes nothing until the person approves the exact stored request. relinquish_access no longer changes authority; it directs the person to Your AI settings. No connected assistant can widen or narrow its own authority. CLIENT PROMPTS: an MCP client can separately mark tools Always allow, Needs approval, or Blocked. Those prompts are client-side and Plants neither forces them off nor treats them as product grants. The person can list the assistants they hold, widen or narrow any of them, and revoke any of them; revoking is a server-side denial that refuses the next call. An expired grant is not renewed silently. Results already saved stay in their workspace, with a record of which assistant saved them. BOUNDED CLIENT PROOF. Claude Cowork reconnected and loaded every published tool; its named-client knowledge migration plus the separate marked synthetic full lifecycle proved 2.9.0 media, write/UI, stale/replay, reconnect/catalogue recovery, and exact cleanup. Do not infer universal client or transport support. CHANGELOG FOR CONNECTING ASSISTANTS, newest first — diff your expectations against the guide version above; the full history is at /updates: v2.17.0 — 2026-09-07: Failures say why, and the harvest counts · When something fails, your AI can tell you what failed instead of guessing. · A harvest is a dated event with a number, so what a tree gave you is answerable year over year. · A note you dictated can become a typed event, and three sentences about one pruning can become one. · "When did this start last year?" is one call. · A refusal from Plants cannot be mistaken for your chat app's own error. v2.16.0 — 2026-09-07: The AI can read the garden back · Ask your AI what is going on with a plant and it can now actually see the answer. · Standing in front of seven pots, your AI can read the whole area in one call. · How often and how much to water a plant is written down instead of worked out again every time. · A plant that moves is moved, and keeps the name you gave it. · Repotting, pruning and losing a plant are real dated events, and one wrong field can be corrected on its own. · A question you could not answer yet comes back instead of ending with the conversation. · The first call from a phone is forgiving: the page marker is printed, refusals name the switch, and a job starts in one call. v2.15.0 — 2026-09-02: Curiosity can stay curiosity · A plant you meet away from home can stay an encounter instead of becoming a plant in your care. · Private photo originals now stay byte-exact; clean copies and disclosure rules protect what leaves. · When an AI saw a photo but could not transfer it, the record now asks you for that exact original. · Numbered plants stay distinct, real questions survive creation, and Property photo controls now work. v2.14.0 — 2026-09-02: One garden, one record, and sealed voice · A resembling plant is shown before another record can become an accidental twin. · New Queue voice notes are sealed in private storage with one exact original and no invented renditions. · OAuth and MCP machine paths answer directly when a client is given the bare domain. v2.13.0 — 2026-08-30: The first day in the garden, and what it found · Tell your AI to queue something for later and carry on talking — it writes the job down for you. · Your AI can ask how you like to be worked with, one sentence at a time, and you keep the ones you accept. · A plant your AI already recognises can be identified in the same breath as it is created. · Every request you queue is visible to your AI now, whichever way you wrote it. · Your AI can build your garden's places from an empty workspace, in one go. · Your AI can attach the photographs you hand it, three ways, whatever kind of client it is. · The tools say which shape a write wants, instead of leaving your AI to discover it by being refused. · A measurement can say how it was taken, and eight pups off one parent can be one record standing for eight. v2.12.0 — 2026-08-28: A sweep of every surface, and the truths it put back · Things you archived or kept private no longer surface where they were never meant to appear. · Deleting a photograph, or taking back a permission, now stops the next person from seeing it. · Your assistant's card counts the work it actually did, and a safe retry no longer counts twice. · When your assistant's save is refused, it can correct the mistake and send it again under the same ticket. ROUTES: / the workspace. /queue every request in the four states. /queue/ one request at its own address. /suggestions AI SUGGESTIONS: what an assistant proposed, in no lane and no count and never badged, until the person accepts or declines each one. The feature is named AI Suggestions everywhere. /me the person's own stats. /connect the page to hand a person who wants to connect you. /settings their settings, with Your AI and Privacy & export as sections of it; /settings/ai and /settings/data still resolve, and /settings/ai is where connections are inspected, narrowed and revoked. /ai and /ai.txt this guide. /llms.txt what this site is, for a visiting agent. /updates release history. /support where help comes from. /mcp the live protected endpoint itself: POST only, 401 without an approved credential, 405 to anything else. /admin deployment counts for whoever operates this site; it returns nothing to anyone else. No route lists, searches, or discloses another person's records. SUPPORT: This product has no email address, no inbox, and no intake form of its own; none is planned. Problems and improvement requests go to the shared Assist With Life desk: https://assistwithlife.com/support The link carries only the product id, a page key, and the release string. Do not tell a person to email this site. CURRENT APP FOUNDATION: Normal account sign-in and owner-scoped server storage. BOUNDARIES: No background AI work, AI provider integration, sharing, billing, notification, scheduling, equipment control, diagnosis, purchase, treatment, or outside-world action is Current, and none is planned as part of the connection. Connecting an assistant lets it read what the person permitted, save one reviewed result, and write dated observations into their journal, correct a plant record, name the places and collections their garden is organised by, create or correct real Species records, resolve an explicit current identity claim without guessing, record what is true of the whole site, write down a decision or care they report, and — and, only after a separate owner approval, archive a plant reversibly. It would not let it decide anything, delete anything, export anything, or do anything in the world. Remote MCP at /mcp is deployed and enforcing authorization. It refuses every unauthenticated caller with a 401 challenge. Claude Cowork reconnected and loaded every published tool; the named-client knowledge migration and a separate marked synthetic 40-tool production lifecycle passed under a distinct starter grant. Treat that as bounded 2.9.0 proof, not universal client certification.