RetailHardHat Developer docs

MCP documentation

Security policies and management API

RetailHardHat MCP authentication, tools, security and integration guidance.

Effective access

Access is bounded by the real issuer's current permissions, original tenant/module/read-write grant, organization policy, connection policy, record authorization, underlying business rules and usage limits. Narrowing policy cannot enlarge the original grant. Enforcement is checked again at execution, including approved writes.

In Settings → MCP → Security, use Organization policy for tenant-wide controls and Connection permissions for narrower grants. Monitoring exposes accountable users, last activity, expiry, alerts, affected-record references and quota usage.

Policy replacement semantics

Policy PUT endpoints replace writable policy fields: they are not PATCH. Missing writable properties reset to validator defaults. Unknown properties and invalid tool/rule names are rejected. Always GET the latest policy, merge your intended changes locally and PUT the full writable result. An incomplete {enabled:false} also resets other writable policy fields to defaults.

Exception: platform-managed usage ceilings are preserved. Omit organizationLimits, userLimits and connectionLimits from tenant PUT requests. Older clients may echo unchanged values, but attempting to change these fields (including sending stale ceilings) returns 403. This prevents an ordinary security edit from changing or resetting platform allocations.

Platform-managed usage budgets

Adaptive server protection

Platform Admin → MCP Administration → Server protection manages a separate platform-wide admission policy through GET/PUT /api/platform/mcp/protection. Tenant admins cannot read or change this configuration. A shared PostgreSQL token bucket and expiring, heartbeated request leases cap admission across server instances; local rate, IP and concurrency guards run before body parsing and authentication. MCP transport, OAuth and MCP file paths receive this protection. Management controls remain available when admission is paused.

Every two seconds, each instance samples event-loop delay/utilization, memory pressure and database queuing. Busy instances reduce their own throughput, burst and concurrency capacity by 30% per busy sample, with a 10% minimum. Healthy samples recover five percentage points at a time. Severe pressure rejects new admission entirely. Live telemetry is explicitly for the responding instance; shared admission counts and burst tokens are global. These guards do not replace the organization's, user's or connection's persistent usage budgets.

Rate/concurrency refusals return 429 with Retry-After; platform pause or an unavailable shared admission store returns 503. Body reads have an absolute 15-second deadline and requests have a configurable HTTP deadline. An HTTP timeout does not prove an already-running business write was cancelled: check activity/approval status before retrying a mutation. Transport work retains its capacity until its handler settles, including after client disconnect.

Configuration is persisted and audited. The new table is created only through normal schema migrations/Publish, never deployment-time or request-time DDL.

Platform Admin → MCP Administration → Usage budgets lets platform administrators select an organization and manage its organization, per-user and per-connection ceilings for requests/minute, concurrent operations, changes/hour and download bytes/hour. Existing allocations are retained; this ownership change does not reset them. Individual connection policies can impose tighter limits, and runtime enforcement always applies the platform ceilings.

GET /api/platform/tenants/{tenantId}/mcp-usage-limits returns tenantId, tenantName, organizationLimits, userLimits and connectionLimits. PUT at the same endpoint accepts the three limit groups only, validates them, preserves the organization's other security rules, and records before/after values and the actor in MCP activity. Authentication and platform authorization are required; normal tenant admins cannot use either endpoint. Existing platform API-key scope restrictions also apply.

The exact machine-readable validators and defaults are available at /api/mcp-public/security-schema and /api/mcp-public/reference. Use these rather than copying a stale schema from this guide.

Connection policy fields

FieldsMeaning / default
modulesFurther narrowing; empty means retain the original module grant
actionsread/create/update/delete; all four default to eligible, bounded by original read/guarded-write access
allowedTools, deniedToolsExact tool names; empty allowedTools means no extra allowlist; denial wins
siteIds, projectIds, recordIdsUUID allowlists; recordIds maps module names to record UUIDs; empty lists impose no extra narrowing
approvalRulesExact tool, action or sensitive/ordinary family → required or not_required
allowDocuments, allowExportsBoth default false on a connection; organization must also permit sharing
maskedFieldsUp to 50 case-insensitive JSON keys/dotted paths returned as [masked]
maxExportRows500 by default; maximum 10,000
maxResponseBytes2,097,152 by default and maximum
maxBatchChanges25 by default; maximum 100
limitsPersistent request/concurrency/change/download budgets

UUID scope lists allow at most 200 entries each. Unsupported scopes fail closed: a child/document/report operation that cannot safely relate its records to the allowlist is denied, not broadened. Exact existing-record scopes do not authorize creating arbitrary new records. Scoped lists omit an unfiltered global total. Use both scope-filtered pagination and warnings accurately.

Field masks recursively match object keys or dotted paths; array positions are not part of those paths. Organization and connection masks are combined. Masks do not redact attachment contents or guarantee that a separately named aggregate cannot reveal a derived fact.

Array results exceeding 100 entries require both export grants. Row/response caps still apply when exports are enabled. Oversized datasets are rejected rather than silently truncated by the security layer. Outcome reports may independently disclose bounded/incomplete scans.

Organization policy

Organization fields include enabled, restrictClients, approvedClientIds, approvalRules, approvalExpiryMinutes, allowDocuments, allowExports, maskedFields, row/response/batch caps, organizationLimits, userLimits and connectionLimits.

Defaults: enabled true, client restriction false, approved clients empty, approval expiry 1,440 minutes (maximum 24 hours), organization document/export eligibility true. This eligibility does not opt connections into sharing.

When enabled, client restriction permits only approved actual OAuth registration IDs. Names and redirect labels are self-declared, not brand verification. Manual bearer connections are blocked under that restriction.

Approval precedence

For a mutation the first matching rule wins:

  1. Connection exact tool.
  2. Connection action.
  3. Connection sensitive/ordinary family.
  4. Organization exact tool.
  5. Organization action.
  6. Organization sensitive/ordinary family.
  7. Implemented tool's default sensitive classification.

Reads do not require MCP human approval. GET is classified read; DELETE and delete_/remove_ names are delete; PATCH and replace_/update_/assign_/set_/reorder_/send_ names are update; other mutations are create.

Users may explicitly select not_required for chosen changes. This only disables the extra MCP review—not existing business approvals, locks or validation. A required approval binds immutable arguments, expires at the configured interval and is single-use. Organization or connection policy updates reject pending/approved requests so they require fresh review.

Persistent quota defaults

ScopeRequests/minuteConcurrent client RPCsChanges/hourDownload bytes/hour
Organization60020500209,715,200
Issuing user2408200104,857,600
Connection120410052,428,800

All relevant dimensions must have capacity. Connection limits cannot exceed organization connection ceilings. Requests use fixed one-minute buckets; changes and bytes use fixed one-hour buckets, not rolling windows. Concurrency uses durable expiring leases with renewal. Global app/IP rate limits also remain in force.

Change volume is charged before executing a mutation, so failed attempts can consume budget. Batch volume uses the largest submitted top-level array, not a recursive count of all affected database rows. JSON output accounting conservatively doubles serialized bytes for text/structured representations; managed file downloads are charged separately. These are enforcement budgets, not provider token or billing counts.

Management endpoints

All endpoints below require a signed-in owner/admin browser session in the selected tenant. Obtain/send CSRF according to the app's existing session flow. Do not use an MCP bearer token, invent a tenant ID, or embed a privileged admin session in an AI widget.

Method and pathPayload / result
GET /api/mcp-admin/overviewConnections, open/recent approvals, activity, tool definitions, provider readiness
POST /api/mcp-admin/connectionsname, access (read/guarded_write), modules, expiresInDays (1–90), optional connection policy; returns {connection,token} once
POST /api/mcp-admin/connections/:id/revokeNo replacement credential; returns revoked status
POST /api/mcp-admin/approvals/:id/review{decision:"approve"} or {decision:"reject",reason:"..."}; reviews without executing
GET /api/mcp-admin/security{policy,connections,alerts,usage,clients,activity}
PUT /api/mcp-admin/securityFull writable organization policy; platform usage ceilings preserved; returns saved policy
PUT /api/mcp-admin/connections/:id/policyFull connection policy; returns saved policy
POST /api/mcp-admin/security/alerts/:id/acknowledgeReturns acknowledged status; tenant-bound

Security connections/activity use database-style snake_case fields, whereas the older overview uses ORM-style camelCase fields. Alerts/activity are bounded to the latest 200 entries each; usage to 500 recent buckets; registered-client metadata to 500 entries. No credentials or client secrets are returned. Client registrations are server-wide public registrations, not records proving a client's organization.

Example organization update, after fetching the latest policy:

{
  "approvalRules": {"delete":"required","update_task":"not_required"},
  "approvalExpiryMinutes": 60
}

Merge these fields into the fetched full policy before PUT. Likewise merge {"actions":["read"],"allowedTools":["list_sites","get_site"],"maskedFields":["address"]} into the fetched connection policy for a narrowly readable connection.

Shutdown and alerts

Setting enabled:false permanently revokes all existing connections and rejects pending/approved approvals. Re-enabling does not restore tokens; create/link new connections. Revocation does not recall data already shared with a provider or undo an already committed write.

In-app alerts cover repeated denied actions, suspicious expired/revoked/client access, quota exceedance, large downloads and repeated deletion/replace activity. Thresholds are heuristic signals, not a complete intrusion detection guarantee. Alerts can be acknowledged; acknowledgement does not change permissions.

No email, SMS, Slack or external alert delivery is currently provided by this MCP dashboard.

Download this guide as Markdown.