User-scoped MCP access

HipTrip's MCP endpoint accepts x-api-key at /api/mcp. Users create and revoke keys under Profile → AI assistant access. Only a SHA-256 digest is stored; the plaintext key appears once in the creation response.

Default user scopes

  • trips:read, packing:read: list/read owned and accepted shared resources.
  • trips:write, packing:write: propose changes and apply them after confirmation. Shared resources require edit permission.
  • Editorial scopes are never granted by the user UI: catalog:read, editorial:read, places:search, editorial:write, editorial:delete.

Tool discovery is scope-filtered. Every handler also filters by the key's userId; IDs supplied by a client never bypass ownership/share checks.

Mutations

propose_itinerary_day_update, propose_itinerary_update, propose_itinerary_archive, and propose_packing_list_update store a 15-minute pending change and return a readable before/after diff. The client must show that diff and obtain explicit user confirmation before calling apply_pending_change(change_id, confirmed: true). Archiving is owner-only; an editor on a shared itinerary cannot archive the owner's trip.

Apply is one-time and checks the resource's updatedAt captured when proposed. Expired, replayed, cross-key, revoked-access, and stale proposals fail. Successful reads, proposals, and applies create attributed audit events.

MCP day application reuses the same low-level resolveActivitiesForDay and resolveTransferActivity pipeline as the built-in editor. Its orchestration remains separate because MCP must resolve external place/route calls outside its short optimistic transaction, while the server action is session-bound.

Operations

Apply prisma/migrations/026_user_scoped_mcp/migration.sql manually to Aurora DSQL, one transaction at a time. The legacy HIPTRIP_MCP_KEY remains supported for editorial automation only and carries no user identity, so it cannot access user trip tools.