mcp

Model Context Protocol endpoint (JSON-RPC 2.0 over HTTP)

Stateless Streamable HTTP transport in JSON-response mode: one JSON-RPC request (or batch) per POST, one JSON response, no server-sent stream and no Mcp-Session-Id. Supported protocol revisions, newest first: 2026-07-28, 2025-06-18, 2025-03-26 (the server negotiates DOWN to the newest revision at or below the one requested). Send Accept: application/json (and optionally text/event-stream); send the negotiated revision in MCP-Protocol-Version on every request after initialize.

Authenticate with a Bearer token: an OAuth access token from /api/oauth/token, or a personal access token minted in Settings, then Connections (365-day lifetime). The handshake and the public resources need no token: initialize, ping, resources/list, resources/templates/list, resources/read and notifications are served anonymously (rate limited per container). Every other method without a valid token answers 401 with a WWW-Authenticate: Bearer resource_metadata="..." challenge (RFC 9728 §5.1). Authorization is re-checked live on every call: subscription state, the integrations.mcp plan feature, and the caller's current role. OAuth tokens also need a client that has not been disabled and a grant inside its 90-day lifetime; personal access tokens stop working once their owner's Microsoft Entra account is disabled or deleted (checked about hourly).

Methods: initialize, ping, tools/list, tools/call, prompts/list, prompts/get, resources/list, resources/templates/list, resources/read. Every tool is a pure read (readOnlyHint: true) and the tool list varies by plan and role, so call tools/list rather than assuming the catalog below. Resources are the public documents (llms.txt, the documentation pages as Markdown, this OpenAPI description); each URI is the document's real URL on the website. Tool results carry the payload both as text and as structuredContent. Dates are ISO 8601; durations are seconds.

Rate limits (token bucket, 2x burst): 60 requests per minute per grant and 300 per minute per tenant. A 429 carries Retry-After. The edge also caps each client IP at 2,000 requests per 5 minutes across the whole site; over it, CloudFront answers 429 with a text/html page (not JSON-RPC), Retry-After: 300 and no RateLimit fields. Edge security rules can also refuse a request with a text/html 403 before it reaches the app, for example a request without a User-Agent header or with a body over 8 KB.

Catalog (subject to plan/role gating):

  • get_workspace_info: Returns the connected Presify workspace at a glance: workspace name, plan tier with seat and retention limits, subscription and trial state, monitored-user counts (active, paused, pending enrollment), presence-collection health, and what the connected person may see. Call this first to orient yourself.
  • list_monitored_users: Lists the people monitored in this Presify workspace with their status, department, timezone, business hours, and flags (collection paused, legal hold). Filter by monitoring status (active by default; former users appear under removed statuses), department, or a name/email search. Paginated: up to 200 per page with offset. Use this to find a person before calling per-user tools.
  • get_user: Returns one monitored person: profile (name, email, department, timezone, business hours, monitoring status, flags), their latest presence reading (latestReading.at is when it last changed; when latestReading.atIsLowerBound is true it is the start of the workspace retention window, which moves forward each day, so describe the status as unchanged since at least that date), and their last 7 daily presence totals (nightly rollups, so today is never included). Accepts a name, email, or Microsoft user id. For deeper trends use get_user_stats.
  • get_user_stats: Computes rich presence statistics for one person over the last 14 weeks (bounded by plan retention): this week and month with honest same-elapsed-point comparisons to the prior period, a weekly trend, business-hours versus after-hours split, typical day rhythm (median start and end, drift), uninterrupted focus blocks, meeting time, state mix, and longest online stretch. Time when Presify could not read presence counts as No data, never as Offline, and time when collection was off on purpose is not counted as possible time. Accepts a name, email, or Microsoft user id.
  • get_user_timeline: Returns one person's presence timeline for one local calendar day: ordered segments with local start and end times, duration in seconds, and the presence status held in each ("Available", "Busy", "In a call", "Away", "Offline", and so on). "No data" marks spans where collection was not running, which is different from a confirmed Offline reading. Times are wall-clock in the person's own timezone; the response names the zone and the business-hours window. Days outside the plan retention window return no segments.
  • get_current_presence: Returns the latest Microsoft Teams presence reading for each actively monitored person: availability, activity, presence bucket, when it last changed (lastChangeAt), and whether they count as online right now (fresh reading within the last few minutes). When lastChangeIsLowerBound is true the status has not changed for longer than the workspace retention window: lastChangeAt is the start of that window, which moves forward each day, so describe it as unchanged since at least that date, never as a change at that time. Includes data-freshness info so you can caveat stale results. Optionally filter by department. Up to 500 people per call.
  • get_presence_summary: Sums presence time over a date range from nightly per-person daily rollups, grouped by person or by day. Returns seconds in each presence bucket (online, away, offline or no signal, out of office); Busy, Do Not Disturb, in a call and Presenting count as online. Grouped by person, rows are in name order and include everyone with presence data in the range: daysWithData counts the days Presify holds a status for that person for at least part of the day (a status carried from an earlier reading counts, so quiet Offline days and today so far count, but never across an interruption to collection of 15 minutes or more), the Member presence report's Days with data, in each person's own time zone; daysTotaled counts the days whose nightly rollups are summed into the seconds, so the two can differ until the latest days are rolled up; sort them by any column when asked. Grouped by day, rows are the dates that have rollups, so today is never listed. Use for questions like "how much was the team online last week" or "show daily totals for June". Range up to 366 days; optionally restrict to specific people (Microsoft user ids) or one department. Days outside the plan retention window have no data.
  • compare_users: Compares 2 to 10 people side by side over a date range using whole-day presence totals from the nightly rollups: online, away, offline or no signal, and out-of-office seconds (Busy, Do Not Disturb, in a call and Presenting count as online), days with online time, and the average online per day with online time (quiet Offline days do not lower it); daysTotaled is how many days those rollups cover. daysWithData counts the days Presify holds a status for the person for at least part of the day (a status carried from an earlier reading counts, so quiet Offline days and today so far count, but never across an interruption to collection of 15 minutes or more), the Member presence report's Days with data, in each person's own time zone, so it can differ from daysTotaled until the latest days are rolled up. People come back in the order you list them. Range up to 92 days. Each entry accepts a name, email, or Microsoft user id. Note: totals are whole-day, not clipped to business hours; the Team presence report on the Presify Reports page counts only inside the hours it is run with (by default each person's own working hours, in their own time zone), so its numbers differ from these.
  • get_coverage: Builds a typical-week coverage grid: for each weekday hour, how many of the selected people are typically online (fractional headcount and percent of team), plus best and thinnest hours. Answers "when is the team reachable" and "where are our coverage gaps". Each cell also carries observed and possible minutes and their ratio (confidence): time Presify could not read presence is unobserved, never offline, and time when collection was off on purpose (a person paused or stopped, a paused or read-only workspace, a canceled subscription) is left out of possible, so confidence measures only unplanned loss. Hard caps: at most 31 days of history and 50 people per call; scope the users list or department for bigger teams. Requires a plan with the Coverage feature.
  • get_connection_health: Reports the health of this workspace connection to Microsoft 365: whether presence collection is running (active, delayed, paused for reconsent, or suspended), the last successful poll time, how reliably Microsoft Graph has been answering over the chosen window (overall and per day), and the interruptions to collection of 15 minutes or more in the window with their cause (Microsoft 365 access, a delay in Presify collection, or collection off on purpose). Presence figures show the time in those interruptions when Presify could not read presence as No data (a Microsoft 365 access problem while presence was still being read leaves them as they are), and time when collection was off on purpose does not count against coverage. It also reports directory access: which Microsoft directory reads (users, group membership) are failing, since when, and the fix. Use when data looks missing or stale, new people are not showing up, or for an operations checkup. Window up to 90 days. Every credentials field except note is always null: Presify manages the Microsoft app credential, so there is nothing for this workspace to renew.
  • list_notifications: Lists recent in-app workspace notices for admins: billing events, connection health changes, enrollment reminders, digest highlights. Up to 50, newest first; optionally unread only. Useful for "anything needing attention in Presify?".
  • list_anomalies: Lists flagged presence patterns (anomalies) with factual descriptions of what was measured: unbroken Available runs, missing idle time, overnight presence, no activity variation, robotic regularity, weekend uniformity. Filter by person, pattern type, date range, or open/dismissed. Up to 200, newest first. Descriptions state the observed pattern and computation only, never a cause or intent. To inspect a flagged day the way the app does, follow up with get_user_timeline using the entry's person and date.
  • get_anomaly_summary: Counts flagged presence patterns by type over a date range (open and dismissed separately), with the latest detection per type. Use for triage and trend questions like "are overnight flags increasing". Range up to 366 days.
  • list_reports: Lists recently generated report jobs (Member presence report PDFs and Excel workbooks): type, status, who requested them, when. Up to 50, newest first. Use get_report_download for a finished report file link.
  • get_report_download: Returns a fresh download link for a completed report by reportId (from list_reports). Links are valid for 15 minutes and are generated per request; ask again if one expires.
  • list_scheduled_reports: Lists this workspace recurring report schedules: report type, cadence in plain words, window, recipients, status, and the next run time. Answers "when does my next report go out".
  • list_audit_events: Lists this workspace audit trail: who did what and when (settings changes, enrollments, report requests, connections). Filter by action prefix or date range. Up to 100, newest first. Owner only, on plans with the audit log feature.
  • search: Searches this Presify workspace across monitored people (name, email, department), flagged presence patterns, and generated reports. Returns up to 20 results with namespaced ids for fetch. Built for research-style clients; prefer the specific tools when you know what you need.
  • fetch: Fetches the full record behind a search result id (user:, anomaly:, or report: prefixed). Companion to search for research-style clients.
post/api/mcp

Request

  • Base URL: https://app.presify.io
  • URL: https://app.presify.io/api/mcp
  • Auth: one of:
    • OAuth 2 (authorization code, authorization URL https://app.presify.io/api/oauth/authorize, token URL https://app.presify.io/api/oauth/token, scopes: presify:read)
    • HTTP bearer

Headers

MCP-Protocol-Versionstring

The negotiated protocol revision (YYYY-MM-DD). Any date-shaped value is accepted; the response echoes the revision the server is serving.

Request body

OR

Response

JSON-RPC response (or batch). Tool-level failures are JSON-RPC results with isError, transport-level failures are JSON-RPC errors.

OR

Changes

No recorded changes to this operation across all 1 revision of this API.