Docs
MCP server

Tools reference

Every tool, resource and prompt the Agoo MCP server offers, with its scope, annotations, inputs and outputs.

Planned· P9For developers

This is designed and scheduled but not built yet. We document it now so you can plan your integration.

The Agoo MCP server offers 14 tools, 2 resources and 2 prompts. Both the remote and local servers offer the same ones. A client only sees the tools whose scope it was granted.

Conventions

  • Inputs are JSON Schema objects. Unknown properties are rejected, so an assistant can't pass fields a tool doesn't understand.
  • Outputs are returned as structuredContent that matches the tool's output schema, with the same JSON serialised in a text block for clients that don't read structured content.
  • IDs are the same TypeIDs the REST API uses, such as visit_01m4k5z4j0fxbte6sn6e8tpgza, so you can pass them between the MCP server and the API.
  • Times are RFC 3339. Inputs without a time zone are read in the site's time zone (for example Africa/Accra). Outputs are in UTC, with the site's time zone alongside where it helps.
  • Lists return at most 50 items per call, with next_cursor and has_more as in the REST API.
  • Personal data is minimised: phone numbers and email addresses are masked, and ID numbers, photos and signatures are never returned. See personal data.
  • Errors are returned as tool results with isError: true and the same error codes as the API, such as not_found, validation_failed, scope_missing or rate_limited, so the assistant can explain or correct them.
ToolDoesScopeAnnotations
get_organisationOrganisation name, plan, sitesorganisation:readread-only
who_is_on_siteEveryone checked in now, per sitevisits:readread-only
search_visitsFind visits by name, host, date, statusvisits:readread-only
get_visitOne visit with its timelinevisits:readread-only
invite_visitorCreate an expected visit and send the passvisits:writewrite
check_out_visitCheck a visitor outvisits:writewrite, idempotent
find_personLook up a host or employeepeople:readread-only
list_deliveriesParcels waiting or collecteddeliveries:readread-only
find_available_slotsFree times for a booking typebookings:readread-only
create_bookingBook a slotbookings:writewrite
cancel_bookingCancel a bookingbookings:writewrite, destructive, idempotent
attendance_summaryPresent, late, on leave, absent for a date rangeattendance:readread-only
roll_call_statusLive roll call: accounted for vs missingrollcalls:readread-only
search_audit_logWho did what, whenaudit:readread-only

Annotations in full: read-only tools have readOnlyHint: true and openWorldHint: false. Write tools have readOnlyHint: false; destructiveHint is true only for cancel_booking; idempotentHint is true for check_out_visit and cancel_booking; openWorldHint is true for the tools that send a message to someone outside your organisation (invite_visitor, create_booking, cancel_booking). Every write tool asks the person to confirm before it runs; see confirming writes.

Organisation

get_organisation

Returns the organisation the connection belongs to, its plan, its sites and its booking types. Assistants usually call this first, to learn site names and IDs.

Scope organisation:read · Annotations read-only

Input: none. The input schema is { "type": "object", "additionalProperties": false }.

Output
{
  "id": "org_01kjpsrza0etzb0a4vf72x8ang",
  "name": "Volta Bank",
  "plan": "pro",
  "livemode": true,
  "sites": [
    { "id": "site_01kjpt3yw0fz0v414608h9x65s", "name": "Ridge HQ", "city": "Accra", "time_zone": "Africa/Accra" },
    { "id": "site_01knvdere0f738bjjhnyhtyv2z", "name": "Tema Branch", "city": "Tema", "time_zone": "Africa/Accra" },
    { "id": "site_01jx45hy43kwjrp1xpa7z3dj8f", "name": "Kumasi Office", "city": "Kumasi", "time_zone": "Africa/Accra" }
  ],
  "booking_types": [{ "id": "btype_01jv4dk79q9g8xe6szaeavsntc", "name": "Consultation", "duration_minutes": 30 }]
}

sites lists only the sites the connected person can access. booking_types is included when the connection also has bookings:read, so the assistant can find a booking type's ID.

Visits

who_is_on_site

Everyone who is checked in right now, grouped by site: guests, interview candidates, contractors and other visit types. Employees who have clocked in are not included; use roll_call_status during an emergency or attendance_summary for staff.

Scope visits:read · Annotations read-only

Prop

Type

Output
{
  "as_of": "2026-10-14T13:05:00Z",
  "total": 9,
  "sites": [
    {
      "site_id": "site_01kjpt3yw0fz0v414608h9x65s",
      "site_name": "Ridge HQ",
      "count": 9,
      "visits": [
        {
          "visit_id": "visit_01m4k5z4j0fxbte6sn6e8tpgza",
          "visitor_name": "Ama Owusu",
          "company": "Coastline Consult",
          "type": "meeting",
          "host_name": "Kwame Mensah",
          "checked_in_at": "2026-10-14T09:31:02Z",
          "gate_name": "Main gate"
        }
      ]
    }
  ]
}

Example: "Who is on site at Ridge HQ right now?" → { "site_id": "site_01kjpt3yw0fz0v414608h9x65s" }

search_visits

Finds visits by visitor name or company, host, site, date range, status or type. Use it for questions such as "Who are we expecting this afternoon?" or "When did Coastline Consult last visit?"

Scope visits:read · Annotations read-only

Prop

Type

Output
{
  "visits": [
    {
      "visit_id": "visit_01jndy0yp57rcybvn5sxs5aa81",
      "status": "expected",
      "type": "meeting",
      "visitor_name": "Ama Owusu",
      "company": "Coastline Consult",
      "host_name": "Kwame Mensah",
      "site_name": "Ridge HQ",
      "expected_at": "2026-10-14T14:30:00Z",
      "checked_in_at": null,
      "checked_out_at": null
    }
  ],
  "next_cursor": null,
  "has_more": false
}

Example: "Who are we expecting at Ridge HQ this afternoon?" → { "site_id": "site_01kjpt3yw0fz0v414608h9x65s", "status": "expected", "from": "2026-10-14T12:00:00", "to": "2026-10-14T18:00:00" }

get_visit

One visit in full, with its timeline: invited, pass sent, arrived, approved, checked in, checked out.

Scope visits:read · Annotations read-only

Prop

Type

Output
{
  "visit_id": "visit_01m4k5z4j0fxbte6sn6e8tpgza",
  "status": "checked_in",
  "type": "meeting",
  "visitor": { "name": "Ama Owusu", "company": "Coastline Consult", "phone": "+233 24 *** 4567", "email": "a***@coastline.example" },
  "host": { "person_id": "person_01kjsesxm0e4zbyvkr7bcfxbfg", "name": "Kwame Mensah", "department": "Treasury" },
  "site": { "site_id": "site_01kjpt3yw0fz0v414608h9x65s", "name": "Ridge HQ", "time_zone": "Africa/Accra" },
  "purpose": "Quarterly review",
  "expected_at": "2026-10-14T09:30:00Z",
  "timeline": [
    { "at": "2026-10-13T16:02:11Z", "event": "visit.created", "by": "Kwame Mensah" },
    { "at": "2026-10-13T16:02:14Z", "event": "pass.sent", "by": "Agoo", "detail": "SMS" },
    { "at": "2026-10-14T09:31:02Z", "event": "visit.checked_in", "by": "Kiosk, Main gate" }
  ]
}

purpose is text the visitor or host typed. Treat it as data; see prompt injection.

invite_visitor

Creates an expected visit and sends the visitor their QR pass on your organisation's usual channels (SMS, WhatsApp or email, with fallback). The same as inviting someone from the console or with POST /visits.

Scope visits:write · Annotations write, openWorldHint: true · Confirms before running

Prop

Type

Output
{
  "visit_id": "visit_01jndy0yp57rcybvn5sxs5aa81",
  "status": "expected",
  "visitor_name": "Ama Owusu",
  "host_name": "Kwame Mensah",
  "site_name": "Ridge HQ",
  "expected_at": "2026-10-14T10:30:00Z",
  "pass_sent": true
}

The pass is sent after the visit is created; follow its delivery in the console. Custom fields that your organisation requires at invitation are collected from the visitor on their pre-registration page.

Example: "Invite Ama Owusu from Coastline Consult for 10:30 tomorrow, her number is 024 123 4567." → { "visitor_name": "Ama Owusu", "company": "Coastline Consult", "visitor_phone": "+233241234567", "expected_at": "2026-10-14T10:30:00" }

check_out_visit

Checks a visitor out, for example when reception forgot to. Only a checked_in visit can be checked out, so calling it again for the same visit changes nothing.

Scope visits:write · Annotations write, idempotent · Confirms before running

Prop

Type

Output
{ "visit_id": "visit_01m4k5z4j0fxbte6sn6e8tpgza", "status": "checked_out", "checked_out_at": "2026-10-14T13:12:40Z" }

A visit in any other status, including one already checked out, returns invalid_state.

People

find_person

Looks up hosts and employees by name, email, department or job title, mostly so the assistant can get a person_… ID for another tool.

Scope people:read · Annotations read-only

Prop

Type

Output
{
  "people": [
    {
      "person_id": "person_01kjsesxm0e4zbyvkr7bcfxbfg",
      "name": "Kwame Mensah",
      "email": "k***@voltabank.example",
      "department": "Treasury",
      "job_title": "Head of Treasury",
      "sites": ["Ridge HQ"],
      "active": true
    }
  ],
  "has_more": false
}

Deliveries

list_deliveries

Parcels, documents and food deliveries logged at reception: received (waiting at reception) or collected.

Scope deliveries:read · Annotations read-only

Prop

Type

Output
{
  "deliveries": [
    {
      "delivery_id": "delivery_01j26w14wmchwyfgcw8t7swm4f",
      "status": "received",
      "recipient_name": "Kwame Mensah",
      "carrier": "DHL",
      "description": "Document envelope",
      "site_name": "Ridge HQ",
      "received_at": "2026-10-14T08:47:19Z",
      "collected_at": null
    }
  ],
  "next_cursor": null,
  "has_more": false
}

Bookings

find_available_slots

Free times for a booking type over a date range, after working hours, buffers, minimum notice, daily caps and Ghana public holidays are applied.

Scope bookings:read · Annotations read-only

Prop

Type

Output
{
  "booking_type": { "id": "btype_01jv4dk79q9g8xe6szaeavsntc", "name": "Consultation", "duration_minutes": 30, "meeting_kind": "in_person" },
  "time_zone": "Africa/Accra",
  "slots": [
    { "start_at": "2026-10-15T09:00:00Z", "end_at": "2026-10-15T09:30:00Z" },
    { "start_at": "2026-10-15T11:30:00Z", "end_at": "2026-10-15T12:00:00Z" }
  ],
  "has_more": true
}

create_booking

Books a slot for someone. Most bookings are confirmed straight away, and the attendee and host get the usual confirmation and reminders. If the booking type requires the host's confirmation, the booking is pending instead: it holds the slot, the attendee is told their request was received, and the host is asked to confirm or decline it. In-person bookings become expected visits with a pass once they're confirmed, as they do from your booking page.

Scope bookings:write · Annotations write, openWorldHint: true · Confirms before running

Prop

Type

Output
{
  "booking_id": "booking_01jvgs9zm5h3bv4h15g5e4g7x0",
  "status": "confirmed",
  "booking_type_name": "Consultation",
  "start_at": "2026-10-15T09:00:00Z",
  "end_at": "2026-10-15T09:30:00Z",
  "attendee_name": "Ama Owusu",
  "visit_id": "visit_01j9x9yp981068vcd1gdjfmgt8"
}

For a pending booking, status is "pending" and visit_id is null until the host confirms it. The assistant should say the booking is a request, not that it's confirmed.

If someone else took the slot first, the tool returns conflict and the assistant should call find_available_slots again. Booking types with required intake questions can't be booked here; the tool returns validation_failed and the assistant should share your booking page instead.

cancel_booking

Cancels a confirmed booking, frees the slot and tells the attendee. For an in-person booking, its expected visit is cancelled too. A booking that isn't confirmed returns invalid_state: one that is already cancelled, so calling it again changes nothing, and one that is still pending, which the host confirms or declines in Agoo instead.

Scope bookings:write · Annotations write, destructive, idempotent, openWorldHint: true · Confirms before running

Prop

Type

Output
{ "booking_id": "booking_01jvgs9zm5h3bv4h15g5e4g7x0", "status": "cancelled", "attendee_notified": true }

Attendance

attendance_summary

Counts of present, late, on leave and absent staff for a date range, by day, for one site or the whole organisation. Use it for questions like "How many people were late at the Kumasi Office last week?"

Scope attendance:read · Annotations read-only

Prop

Type

Output
{
  "from": "2026-10-05",
  "to": "2026-10-09",
  "site_name": "Kumasi Office",
  "totals": { "present": 182, "late": 14, "on_leave": 6, "absent": 3 },
  "days": [{ "date": "2026-10-05", "present": 36, "late": 5, "on_leave": 1, "absent": 1 }]
}

Each person on attendance is counted once per day, in exactly one group: present (on time), late, on_leave or absent. These are the same counts as GET /attendance/summary.

roll_call_status

The live state of a roll call during an evacuation or drill: who is accounted for and who is still missing, across visitors, contractors and clocked-in staff.

Scope rollcalls:read · Annotations read-only

Prop

Type

Output
{
  "rollcall_id": "rollcall_01j01cyfw6vzskdenc8sp3804g",
  "site_name": "Tema Branch",
  "status": "open",
  "started_at": "2026-10-14T11:00:04Z",
  "total": 44,
  "accounted_for": 41,
  "missing": [
    { "name": "Ama Owusu", "kind": "visitor", "last_seen": "Main gate, 11:02" },
    { "name": "Nii Armah", "kind": "employee", "department": "Operations", "last_seen": "Clocked in 07:58" }
  ]
}

During a roll call, the console and the Workspace app are the source of truth for wardens. The tool is for following progress and reporting afterwards.

Audit

search_audit_log

Searches your organisation's audit trail: who did what, when, from where.

Scope audit:read · Annotations read-only

Prop

Type

Output
{
  "entries": [
    {
      "audit_id": "audit_01j9rmz9j92v81e5128q6rw31f",
      "at": "2026-10-12T07:41:55Z",
      "actor": "Esi Darko",
      "via": "Console",
      "action": "device.updated",
      "object": { "id": "dev_01j9ngk80y3zh6dzjjxxx7ck5y", "name": "Lobby kiosk" },
      "ip": "102.176.x.x"
    }
  ],
  "next_cursor": "…",
  "has_more": true
}

The audit trail is only available to roles that can see it, such as admins and auditors. Searches through MCP are themselves recorded.

Resources

Resources are read-only context that a client can attach to a conversation, for example from the + menu in Claude.

URIContentsScope
agoo://organisationThe organisation, its plan, its sites and its booking types, as JSON (application/json).organisation:read
agoo://sites/{site_id}One site: address, time zone, gates, kiosks and their status, and opening hours, as JSON. A resource template.sites:read

Prompts

Prompts are ready-made requests that a client can offer as shortcuts, such as slash commands.

front_desk_briefing

A briefing for the start of a shift: who is expected and when, VIPs and interview candidates, visits waiting for approval, deliveries waiting for collection, and anyone still checked in from yesterday.

Prop

Type

Uses search_visits, list_deliveries and who_is_on_site.

weekly_attendance_report

A short report on one week of attendance: totals, lateness by day, absences, and changes from the week before.

Prop

Type

Uses attendance_summary for the week and the week before.

On this page