Skip to content
简体中文

Tools

Public MCP exposes five tools, all read-only. Every tool takes the same code parameter: the full scanned URL, such as https://qr71.cn/okDISU/qssTnoy.

ToolQuestion it answers
entity_getWhat is this code?
entity_records_listWhat has happened to this thing?
entity_actions_listWhat can be done right now?
entity_action_getWhich fields does this action require?
entity_bindings_listWhich things has this code pointed at?

Note: examples on this page come from a public demo code; they are abridged and personal names have been replaced. The live service returns field values in Chinese — the examples here are translated for illustration. Real responses also carry representations (URLs of other renderings such as Markdown), category, description, dateCreated, dateModified and items; the full structure is defined by schema.json.

entity_get

Returns the whole entity in one call, including previews of actions and records. Start here.

Parameters

ParameterTypeRequiredDescription
codestringYesCode URL
formatsstring[]NoWhich representations to return: json, markdown, jsonld, og. When omitted, returns json

Response

The response is an object keyed by format name. By default it has a single json key holding the ObjectCard:

json
{
  "json": {
    "$schema": "https://a2a.objqr.com/ext/caoliao-entity/v2/schema.json",
    "objectCardVersion": "2.0",
    "generatedAt": "2026-08-12T17:14:13.264Z",
    "thing": {
      "id": "thg_qssTnoy",
      "idScheme": "code-derived",
      "name": "CNC Lathe A08-03-06",
      "type": { "id": "generic", "additionalType": "https://schema.org/Thing" }
    },
    "code": {
      "id": "qssTnoy",
      "uri": "https://qr71.cn/okDISU/qssTnoy",
      "status": "bound"
    },
    "binding": {
      "boundAt": "2025-03-20T17:25:06.000Z",
      "historyCount": 1,
      "historyVia": "entity_bindings_list"
    },
    "org": { "id": "okDISU", "name": "Caoliao" },
    "properties": [
      { "name": "Equipment", "value": "CNC Lathe" },
      { "name": "Asset No.", "value": "A08-03-06" },
      { "name": "Location", "value": "Hydraulic Remanufacturing Workshop" }
    ],
    "states": [
      {
        "machine": "state_8985306",
        "name": "Operating status",
        "current": "Normal",
        "updatedAt": "2026-06-23T02:26:36.000Z",
        "derivedFrom": "records",
        "byRecord": "rec_460807516"
      }
    ],
    "records": {
      "count": 1,
      "preview": [
        {
          "id": "rec_460807516",
          "type": "inspection",
          "label": "Inspection form",
          "at": "2026-06-23T02:26:36.000Z",
          "result": "pass",
          "resultLabel": "Normal",
          "by": { "name": "Zhang" }
        }
      ],
      "listVia": "entity_records_list"
    },
    "actions": [
      {
        "action": "record:1556557",
        "label": "Inspection form",
        "requiresAuth": true,
        "formSchemaVia": "entity_action_get",
        "humanUrl": "https://qr71.cn/okDISU/qssTnoy"
      }
    ],
    "plans": [
      { "action": "record:1556556", "label": "Maintenance record", "cycle": "Weekly", "status": "running" }
    ],
    "endpoints": {
      "mcp": { "url": "https://mcp.objqr.com/mcp", "transport": "streamable-http" },
      "a2a": {
        "url": "https://a2a.objqr.com",
        "agentCard": "https://a2a.objqr.com/.well-known/agent-card.json"
      }
    },
    "contract": {
      "profile": "read-only-public",
      "rules": {
        "readOnly": true,
        "publicOnly": true,
        "singleOrgView": true,
        "actionsExecutable": false
      }
    }
  }
}

formats determines exactly which keys the response contains — it replaces the set, it does not add to it. Passing ["markdown"] alone returns no json key and no ObjectCard; when you still need the structured card, include "json" in the array, e.g. ["json", "markdown"]. markdown is a human-readable rendering of the same entity; jsonld is a JSON-LD (schema.org vocabulary) representation; og is Open Graph metadata — useful for search and sharing integrations.

Main blocks

FieldDescription
thingThe thing itself: name and type
codeThe code: identifier, URL, code status (bound active / disabled)
bindingHow the code is bound to the thing, and when
propertiesProperty fields, taken from the QR code's content modules
relationsRelation slots: located in, belongs to, responsible by, part of. An empty object {} until resolvable into structured references
statesBusiness states. derivedFrom explains where a state came from
recordsThe record ledger (inspections, repairs, maintenance): count is the total, preview holds the most recent entries
mediaImages and attachments
actionsActions available right now — listed, never executed
plansRecurring plans, such as weekly maintenance
endpointsWhere this entity is reachable over Public MCP and A2A
representationsURLs of other renderings of this entity (HTML / Markdown, …)
contractThe boundaries this response honors

Top-level blocks are always present (the schema marks them required): when untracked they hold null, {} or [], all of which read as "not tracked" — never as a negative. "Absence" semantics apply to optional sub-fields inside blocks; see consumption rule 2 below.

Four consumption rules

Important: these four affect how you store the data. Read them before you write code.

  1. thing.id is a transitional, code-derived identifier (idScheme is code-derived). Do not persist a dependency on it. The stable identifier to store is code.uri.
  2. An absent sub-field, or a block holding null / {} / [], means "not tracked" or "cannot be resolved". It does not mean false or "does not exist". Never read either as a negative answer.
  3. code.status is the status of the code; states are business states. They are different things.
  4. Ledger entries can currently be edited by the owning organization. An immutable ledger is the target state; this contract does not promise immutability — do not persist records as tamper-proof audit evidence.

entity_records_list

Returns the full ledger — inspections, repairs, maintenance — newest first, cursor-paginated. entity_get only previews the latest few; use this to page through history.

Parameters

ParameterTypeRequiredDescription
codestringYesCode URL
sizenumberNoPage size, default 20, maximum 50
page_tokenstringNoThe nextPageToken from the previous page. Leave empty for the first page

Response

json
{
  "url": "https://qr71.cn/okDISU/qssTnoy",
  "records": [
    {
      "id": "rec_460807516",
      "type": "inspection",
      "label": "Inspection form",
      "at": "2026-06-23T02:26:36.000Z",
      "result": "pass",
      "resultLabel": "Normal",
      "summary": "Inspection result: normal",
      "by": { "name": "Zhang" },
      "snapshot": { "codeId": "qssTnoy", "thingId": "thg_qssTnoy" }
    }
  ],
  "hasMore": false,
  "total": 1
}

Each entry carries a snapshot of the code and thing as they were when the record was created. All timestamps are ISO 8601 with timezone.

When hasMore is true, the response also carries a top-level nextPageToken field (absent when hasMore is false, which is why the example above has none); pass it as page_token on the next call.

entity_actions_list

Lists the actions available right now — which forms can be filled in, which state changes exist. Listing only, never execution.

Parameters

ParameterTypeRequiredDescription
codestringYesCode URL

Response

json
{
  "url": "https://qr71.cn/okDISU/qssTnoy",
  "actions": [
    {
      "action": "record:1556557",
      "label": "Inspection form",
      "requiresAuth": true,
      "annotations": {
        "readonly": false,
        "destructive": false,
        "idempotent": "by_request_key",
        "confirm": "none"
      },
      "precondition": null,
      "formSchemaVia": "entity_action_get",
      "humanUrl": "https://qr71.cn/okDISU/qssTnoy"
    },
    {
      "action": "record:1556556",
      "label": "Maintenance record",
      "requiresAuth": true,
      "annotations": {
        "readonly": false,
        "destructive": false,
        "idempotent": "by_request_key",
        "confirm": "none"
      },
      "precondition": null,
      "formSchemaVia": "entity_action_get",
      "humanUrl": "https://qr71.cn/okDISU/qssTnoy"
    }
  ]
}
FieldDescription
actionAction identifier such as record:1556557; pass it to entity_action_get
requiresAuthWhether submitting this action requires authorization
annotationsAction nature: read-only, destructive, idempotency mode, confirmation
humanUrlWhere a person executes this action in a browser

Important: Public MCP does not perform writes. To actually submit a record, hand humanUrl to a person to complete on the Caoliao page.

entity_action_get

Returns the complete field schema of one action. entity_actions_list lists actions without fields; use this before filling a form.

Parameters

ParameterTypeRequiredDescription
codestringYesCode URL
actionstringOne of the twoAction identifier from entity_actions_list
tpl_idnumberOne of the twoForm template id

You must provide either action or tpl_id; omitting both returns an error.

Response

json
{
  "url": "https://qr71.cn/okDISU/qssTnoy",
  "tplId": 1556557,
  "fields": [
    {
      "id": 10098724,
      "title": "Inspection checklist",
      "type": "checklist",
      "required": true,
      "choices": [
        { "id": 53279777, "label": "No abnormal noise, operates normally" },
        { "id": 53279779, "label": "Brakes, gearbox and oil tank normal" }
      ],
      "desc": "Tick when normal, cross when abnormal, and explain any abnormality"
    },
    {
      "id": 10098730,
      "title": "Inspection result",
      "type": "radio",
      "required": true,
      "choices": [
        { "id": 53279846, "label": "Normal" },
        { "id": 53279847, "label": "Abnormal" }
      ]
    },
    {
      "id": 10098732,
      "title": "Inspector",
      "type": "name",
      "required": true
    }
  ]
}

Reading the field schema requires no authorization; submitting does.

entity_bindings_list

Returns which things this code has pointed at, for audit purposes.

Parameters

ParameterTypeRequiredDescription
codestringYesCode URL

Response

json
{
  "url": "https://qr71.cn/okDISU/qssTnoy",
  "bindings": [
    {
      "thingId": "thg_qssTnoy",
      "current": true,
      "boundAt": "2025-03-20T17:25:06.000Z"
    }
  ],
  "note": "..."
}

Important: Caoliao does not support rebinding today — a code maps to exactly one thing. This tool currently always returns a single current binding, and the note field says so explicitly. Once rebinding ships, this will return a real sequence of binding events. The response shape will not change, so you can write against it now.

Typical call order

entity_get                  whole entity; check records.count and actions
  ├─ many records          → entity_records_list (page through)
  ├─ need to fill a form   → entity_action_get (fields) → hand humanUrl to a person
  └─ audit code ownership  → entity_bindings_list

Next