84 lines
4.3 KiB
Markdown
84 lines
4.3 KiB
Markdown
# Assistant access (MCP)
|
||
|
||
Open **Albums → Assistants** (`/dashboard/assistants`) and create a connection.
|
||
The endpoint is `https://ma.hadlock.tech/api/mcp`, using Streamable HTTP. Configure
|
||
your MCP client to send `Authorization: Bearer <token>` on every request. Tokens
|
||
are displayed once, stored only as SHA-256 hashes, expire after 1–365 days, and
|
||
can be revoked in that screen. Keep them in the client's secret storage, never
|
||
in prompts or source control. This version uses bearer tokens, not OAuth discovery;
|
||
clients must support custom authorization headers. No public/anonymous access.
|
||
|
||
## Permissions
|
||
|
||
Tokens default to read-only statistics/discovery permissions. Enable only the
|
||
existing event, group, and platform permissions needed by that assistant.
|
||
Selections are a ceiling: the same current memberships/roles used by the web UI
|
||
are re-evaluated for every action. Selecting platform permissions never makes an
|
||
ordinary account a platform administrator. Removing a role restricts existing
|
||
tokens; revoking a token blocks new requests, not work already executing.
|
||
|
||
Private photo access is separately restricted by `photos.private.read`, including
|
||
when the token belongs to an owner/admin. Read-only tokens cannot call write tools
|
||
even if they include management permissions for reading associated data.
|
||
|
||
The explicit tool allowlist covers platform stats/settings/users/roles/allowances,
|
||
groups and memberships, events and schedules, photos/submission/note moderation,
|
||
guest lists and notification emails, invitations, exports, and banner/sign workflows.
|
||
It does not expose sessions, token management, guest authentication, SQL, arbitrary
|
||
HTTP requests, or shell commands. New application procedures require explicit review
|
||
before being added to the MCP catalog.
|
||
|
||
## Calling tools
|
||
|
||
Tool names use underscores, for example `manager_stats` and `group_rename`.
|
||
Existing application input goes under `input`. Dates are ISO-8601 strings.
|
||
|
||
```json
|
||
{"name":"manager_stats","arguments":{"input":{"eventId":"EVENT_UUID"}}}
|
||
```
|
||
|
||
Every write requires `confirm: true` in addition to a write-enabled token and the
|
||
required permissions. This is an explicit API acknowledgement, not proof that a
|
||
human approved the action; configure your assistant to ask before destructive
|
||
actions or sending messages.
|
||
|
||
```json
|
||
{"name":"group_rename","arguments":{"input":{"groupId":"GROUP_UUID","name":"Wedding team"},"confirm":true}}
|
||
```
|
||
|
||
Do not automatically retry writes after an ambiguous connection failure. Re-read
|
||
state first: mutations may have succeeded and are not universally idempotent.
|
||
List outputs are paginated with top-level `offset` and `limit` (default 50, max
|
||
100), returning `items`, `total`, and `nextOffset`. Application-specific filters
|
||
and page fields remain inside `input`. Some application queries impose their own
|
||
limits; `total` then reflects that result set rather than all database records.
|
||
|
||
Uploads still go directly to storage using signed URLs. MCP never proxies original
|
||
files. Tool results may contain personal data or signed URLs according to the
|
||
selected permissions—treat the connected assistant as a data recipient. Guest
|
||
notes, names, and other content returned by tools are untrusted data, not instructions.
|
||
|
||
Calls have per-client and per-token rate limits, a 64 KiB request-body cap, origin
|
||
validation, and no-cache responses. Tool audit entries record token/user ids,
|
||
tool name and success, not raw arguments, credentials, or guest data. Existing
|
||
mutation audit entries remain unchanged. No production token is created automatically.
|
||
|
||
## Verification
|
||
|
||
```sh
|
||
MCP_INTEGRATION=1 bun --env-file=.env test apps/web/src/server/mcp/mcp.integration.test.ts
|
||
```
|
||
|
||
The integration test refuses non-local databases and does not send email.
|
||
|
||
## Coolify health checks
|
||
|
||
Both Compose definitions use `/api/health/ready` for web readiness (bounded DB
|
||
probe) and a loopback-only worker `/health` endpoint on port 3001. The worker
|
||
checks DB connectivity and loop heartbeats; a loop stalled for 15 minutes is
|
||
unhealthy. Long exports can exceed this threshold and should be investigated.
|
||
`/api/health` remains process liveness. Responses omit internal dependency details.
|
||
Checks run every 30 seconds, with a 5-second timeout and three retries. No worker
|
||
health port is published. Docker health status by itself does not automatically
|
||
restart an unhealthy container; it supplies readiness information to Coolify.
|