# Protocol and tool reference

## Tenant action coverage

External MCP and in-app Ask AI now use the same reviewed business-action
definitions and editable-field schemas. Use `tools/list` or the public JSON
catalogue for the complete current inventory rather than a hard-coded count.

Depending on the connection's selected modules and permissions, this includes:

- Budget versions, duplication, current-budget selection, approval submission,
  approver configuration, line-item ordering, assignment and bid-cost sync.
- Task and RFI comments, reusable template creation/editing/cloning/application,
  custom fields and options, tenant configuration and scheduling actions.
- Document sharing/visibility, folder moves and utility document attachments.
- Notification inbox actions, tenant webhooks, and supported connected-product
  status, location creation, sync previews and retry actions.
- Report definitions and execution, plus CSV, Excel XLSX and PDF file exports.
- General-project task creation/editing/deletion (including parent tasks,
  assignment and due dates), project note title/content maintenance, and project
  team membership management.
- Task-to-budget line-item linking/unlinking and linked-task counts.
- Milestone matrix status and date edits, plus administrator-only column ordering.
- Administrator-only team invitation creation, resend and revocation. Tokens
  and acceptance links are not returned to AI clients.
- Entity-specific bid, RFP, budget and invoice business approval requests:
  lookup, submission, explicit approve/reject decisions and submitter cancellation.

These are tenant actions, not platform administration. Credential management,
payment execution and direct approval-state edits are not exposed. Explicit
approval decisions use the actual actor's normal business workflow: only a
current-step approver can decide, personal and step amount ceilings still apply,
and a completed step does not bypass later approvers. Writes are reviewed under
the connection's existing approval policy; Ask AI always leaves changes pending
in-app confirmation. Decision/cancellation previews are bound to the current
request state, expire with their approval and cannot be replayed.
Normal business workflow approvals remain in force. No connection is upgraded to additional
modules or given a wider explicit tool allowlist by this update.

### General-project tasks and financial links

General-project tasks are not site tasks. Use `create_project_task`,
`update_project_task` and `delete_project_task` with `projectId` and, for existing
tasks, `projectTaskId`. Create accepts `title`, `description`, `status`, `priority`,
`assignedToUserId`, `parentId` and `dueDate`. Parent tasks must belong to the same
project, cycles are rejected, and deleting a parent can delete its children.
Use actual created IDs when planning dependent changes.

`link_task_budget_line_item` accepts `taskId` and `data.lineItemId`;
`unlink_task_budget_line_item` accepts `taskId` and `lineItemId`. Both records and
the parent budget must belong to the same tenant and site. Linking does not
change financial amounts or approve a budget.

Completing a template-backed matrix phase through
`update_site_milestone_status` may also complete its child tasks through the
screen's business service. Clients must disclose this consequence in the preview.
Use `get_milestone_matrix` to obtain real site/column IDs; `templateId` optionally
selects a tenant task template.

### Report files

`run_report` is a read-only POST operation and is available to appropriately
scoped read-only connections. Consult `get_report_registry` for datasets,
field IDs and filters. Its result includes the report service's `data` array
and the equivalent normalized `rows` array.

`export_report` accepts `name`, report `args`, `format` (`csv`, `xlsx`, `pdf`),
`allPages` (default false), and `maxRows` (default 500, maximum 1,000).
Lower organization/connection row and response-size limits always win.
Each page is re-authorized and field-masked; caller-supplied column labels
cannot bypass masks on the original fields.

The result contains readable text, file metadata in `structuredContent.data`,
and a standard MCP embedded resource with `mimeType` and a base64 `blob`.
It is self-contained, not a public URL, persistent download link or signed
storage URL. File display/download controls depend on the host's support for
MCP embedded resources. Clients must disclose `truncated` and `rowLimit`.
Large reports may need smaller requests because binary encoding also counts
toward response and download-volume limits.

Both the connection and organization must allow exports. A module grant alone
does not enable downloads. Explicit allowlists must include `export_report`
and its dependency `run_report`. No approval is required for these read-only
tools, but all current sharing permissions and usage quotas apply.

### Readable results and source previews

Ordinary tools return bounded Markdown text alongside unchanged structured
results. Clients should present short headings, lists and tables rather than
dumping raw JSON or claiming a pending action succeeded.

Actions with source previews, such as budget duplication and template cloning,
bind the human approval to the reviewed source state. If the source changes,
execution stops before the mutation and requires a new review. Review-source
read tools must also be allowed by the connection; write permission does not
implicitly grant permission to read the source.

## Transport

Endpoint: `/api/mcp`. Stateless Streamable HTTP, POST only, JSON responses through the official MCP TypeScript server SDK. This is not a legacy SSE subscription service. GET/DELETE return 405 for an authenticated connection. JSON-RPC batch arrays are rejected with 400. There is no persistent MCP session ID to store.

Initialize with a protocol version supported by your client and process the version returned by the server. The runnable example requests `2025-11-25`, matching the integration harness. Send `notifications/initialized` afterward; notifications may return an empty 202 response. Send the negotiated protocol header on subsequent requests.

## Discovery

| Method | Use |
| --- | --- |
| `tools/list` | Connection-specific names, descriptions, input schemas, annotations and UI metadata |
| `tools/call` | Call one advertised tool with its exact arguments |
| `resources/list` / `resources/read` | Inspect connection, catalogue and shared UI resources |
| `prompts/list` / `prompts/get` | Obtain operational and budget-review prompts |

Resources: `retailhardhat://connection`, `retailhardhat://tools`, and `ui://retailhardhat/operations-v1.html`. The UI resource MIME type is `text/html;profile=mcp-app`. Prompts: `operations_review`, `budget_review`.

## Authoritative tool definitions

The public `/api/mcp-public/reference` JSON contains all business/outcome tool definitions and the two approval controls. It is generated from the implemented catalogue rather than a manually maintained list. The `/api/mcp-public/catalogue` endpoint retains its business/outcome-only contract.

Module grants, read/write access and per-connection action/tool restrictions narrow atomic tool advertising. Outcome helpers enforce restrictions at execution and may remain advertised even when denied. Record/document/export policies can deny a tool that was successfully discovered. `sensitive` describes the default approval classification, not the final organization/connection rule.

## Results and failures

Atomic tools normally return:

```json
{
  "result": {
    "content": [{"type": "text", "text": "{\"name\":\"Example location\"}"}],
    "structuredContent": {"data": {"name": "Example location"}}
  }
}
```

Outcome and native-view helpers use their own structured snapshots, rather than universally wrapping them in `data`. Inspect each response; do not discard warnings, incomplete-scan flags or panel errors. Secret-like fields are removed before release; configured field masks apply in addition.

An HTTP 200 is **not** proof of success. Check the JSON-RPC `error`, then tool `result.isError`, then business status. Tool errors commonly contain a text explanation. HTTP transport errors use an `error` message; management errors commonly use `message`.

| HTTP status | Typical cause |
| --- | --- |
| 400 | Invalid management payload, malformed protocol request or batch request |
| 401 | Missing/invalid bearer, expired access/grant, revoked connection or inactive issuer |
| 403 | Organization disabled, registration restriction or transport-level policy denial |
| 405 | Non-POST MCP transport |
| 429 | Durable request/concurrency quota or a global rate limiter; transport may include Retry-After |

Tool-level permission, size, change/download quota and scope failures can instead be returned as `isError` at HTTP 200. Unknown/unadvertised tools and schema failures can be JSON-RPC errors. Do not match only one status code to decide whether authorization succeeded.

## Approval controls

`get_approval_status` accepts `{"approvalId":"UUID"}` and returns the request owned by this connection. Statuses include pending, approved, rejected, expired, executing, executed and failed.

`execute_approved_action` accepts only that approval UUID, not replacement business arguments. It requires guarded-write access, current permissions, an unexpired approved request and the same tenant/connection. It claims the approval atomically and returns:

```json
{"status":"executed","approvalId":"UUID","data":{"id":"RECORD_UUID"}}
```

The underlying write is never triggered by reading/rendering pending approvals. Policy edits invalidate pending and approved requests. A consumed or uncertain execution cannot be reused.

If a write commits but its detailed result cannot be shared, the server can return a minimal `completed` receipt explaining that the response was withheld. Do not retry that completed mutation to obtain its details; inspect the app.

## Files and business boundaries

File tools require both organization and connection document grants. Managed upload requests specify MIME type and exact bytes, with an upload ceiling of 50 MiB and a 15-minute upload URL. Attaching an unclaimed upload requires the same connection and attachment within one hour. Approval follows current rules at each write.

Managed document reads are capped at 2 MiB, may be further restricted by response/download quotas, and verify tenant ownership. Raw attachment gateways deny configured record scopes they cannot safely evaluate. Larger downloads belong in the application.

Masking JSON fields does not redact file contents. Never persist signed URLs or attachment contents in approval records, activity, examples or support logs.

Financial tools do not move money, mark invoices paid, bypass budget locks, self-approve change requests or manage integration secrets. LeaseCommand remains authoritative; lease tools read synchronized data or request refresh through an existing configured integration.
