Read Kisi places, doors, users, groups, access rights and access logs (no unlocking).
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
The Kisi user the API key belongs to (id, name, email, organization). Good first call. GET /user.
This tool takes no arguments.
The Kisi user the API key belongs to (id, name, email, organization). Good first call. GET /user.
No arguments.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {}
}Read an event set from kisi_search_events: its status and events. Pass the previous page's cursor for the next page. GET /event_sets/{id}.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Events per page (default 50). |
| cursor | string | The cursor from the previous page. |
| event_set_id* | integer | The event set id (numeric). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"event_set_id"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 250,
"minimum": 1,
"description": "Events per page (default 50)."
},
"cursor": {
"type": "string",
"description": "The cursor from the previous page."
},
"event_set_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "The event set id (numeric).",
"exclusiveMinimum": 0
}
}
}One access group by id (name, description, place, member/lock counts, restrictions). GET /groups/{id}.
| Argument | Type | Description |
|---|---|---|
| group_id* | integer | The group id (numeric). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"group_id"
],
"properties": {
"group_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "The group id (numeric).",
"exclusiveMinimum": 0
}
}
}One lock/door by id: online/unlocked/locked-down state, place, floor, settings. GET /locks/{id}.
| Argument | Type | Description |
|---|---|---|
| lock_id* | integer | The lock id (numeric). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"lock_id"
],
"properties": {
"lock_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "The lock id (numeric).",
"exclusiveMinimum": 0
}
}
}The current Kisi organization (name, domain, settings summary). GET /organization.
No arguments.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {}
}One place by id, including lockdown state. GET /places/{id}.
| Argument | Type | Description |
|---|---|---|
| place_id* | integer | The place id (numeric). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"place_id"
],
"properties": {
"place_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "The place id (numeric).",
"exclusiveMinimum": 0
}
}
}One user by id. GET /users/{id}.
| Argument | Type | Description |
|---|---|---|
| user_id* | integer | The user id (numeric). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"user_id"
],
"properties": {
"user_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "The user id (numeric).",
"exclusiveMinimum": 0
}
}
}List access cards with status (activated/deactivated/unassigned), assignee and last use. GET /cards.
| Argument | Type | Description |
|---|---|---|
| ids | string | Comma-separated list of ids to fetch. |
| sort | string | Sort by last use. |
| limit | integer | Max results to return (1-250). |
| offset | integer | Results to skip (offset paging; use pagination.next_offset). |
| status | string | Filter by status. |
| user_id | integer | Only cards of this user. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"ids": {
"type": "string",
"description": "Comma-separated list of ids to fetch."
},
"sort": {
"enum": [
"last_used_at",
"-last_used_at"
],
"type": "string",
"description": "Sort by last use."
},
"limit": {
"type": "integer",
"maximum": 250,
"minimum": 1,
"description": "Max results to return (1-250)."
},
"offset": {
"type": "integer",
"maximum": 20000,
"minimum": 0,
"description": "Results to skip (offset paging; use pagination.next_offset)."
},
"status": {
"enum": [
"activated",
"deactivated",
"unassigned"
],
"type": "string",
"description": "Filter by status."
},
"user_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only cards of this user.",
"exclusiveMinimum": 0
}
}
}Kisi controllers (door hardware hubs) with online/offline status. Filter by place, lock or status. GET /controllers.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Max results to return (1-250). |
| query | string | Free-text search over name, device id and token. |
| offset | integer | Results to skip (offset paging; use pagination.next_offset). |
| status | string | Filter by status. |
| lock_id | integer | Only the controller of this lock. |
| place_id | integer | Only controllers in this place. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"limit": {
"type": "integer",
"maximum": 250,
"minimum": 1,
"description": "Max results to return (1-250)."
},
"query": {
"type": "string",
"description": "Free-text search over name, device id and token."
},
"offset": {
"type": "integer",
"maximum": 20000,
"minimum": 0,
"description": "Results to skip (offset paging; use pagination.next_offset)."
},
"status": {
"enum": [
"online",
"offline"
],
"type": "string",
"description": "Filter by status."
},
"lock_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only the controller of this lock.",
"exclusiveMinimum": 0
},
"place_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only controllers in this place.",
"exclusiveMinimum": 0
}
}
}All event type names usable as the type filter of kisi_search_events (e.g. lock.unlock). GET /events/types.
No arguments.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {}
}The locks/doors an access group opens. GET /group_locks?group_id=.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Max results to return (1-250). |
| query | string | Free-text search over lock name. |
| offset | integer | Results to skip (offset paging; use pagination.next_offset). |
| group_id* | integer | The group id (numeric). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"group_id"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 250,
"minimum": 1,
"description": "Max results to return (1-250)."
},
"query": {
"type": "string",
"description": "Free-text search over lock name."
},
"offset": {
"type": "integer",
"maximum": 20000,
"minimum": 0,
"description": "Results to skip (offset paging; use pagination.next_offset)."
},
"group_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "The group id (numeric).",
"exclusiveMinimum": 0
}
}
}List access groups (who-can-open-what bundles of doors). Filter by place or by a lock to see which groups open that door. GET /groups.
| Argument | Type | Description |
|---|---|---|
| ids | string | Comma-separated list of ids to fetch. |
| sort | string | Sort order. |
| limit | integer | Max results to return (1-250). |
| query | string | Free-text search over group name. |
| scope | string | Organization-wide or place-scoped groups. |
| offset | integer | Results to skip (offset paging; use pagination.next_offset). |
| lock_id | integer | Only groups that include this lock. |
| place_id | integer | Only groups of this place. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"ids": {
"type": "string",
"description": "Comma-separated list of ids to fetch."
},
"sort": {
"enum": [
"name",
"-name"
],
"type": "string",
"description": "Sort order."
},
"limit": {
"type": "integer",
"maximum": 250,
"minimum": 1,
"description": "Max results to return (1-250)."
},
"query": {
"type": "string",
"description": "Free-text search over group name."
},
"scope": {
"enum": [
"organization",
"place"
],
"type": "string",
"description": "Organization-wide or place-scoped groups."
},
"offset": {
"type": "integer",
"maximum": 20000,
"minimum": 0,
"description": "Results to skip (offset paging; use pagination.next_offset)."
},
"lock_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only groups that include this lock.",
"exclusiveMinimum": 0
},
"place_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only groups of this place.",
"exclusiveMinimum": 0
}
}
}List locks/doors with their state: online, unlocked, locked_down, configured, place and floor. Filter to find offline or locked-down doors. GET /locks.
| Argument | Type | Description |
|---|---|---|
| ids | string | Comma-separated list of ids to fetch. |
| sort | string | Sort order. |
| limit | integer | Max results to return (1-250). |
| query | string | Free-text search over lock name. |
| offset | integer | Results to skip (offset paging; use pagination.next_offset). |
| online | boolean | Filter by online (true) / offline (false). |
| floor_id | integer | Only locks on this floor. |
| place_id | integer | Only locks in this place. |
| unlocked | boolean | Filter by currently unlocked (true) / locked (false). |
| configured |
List places (sites/buildings) in the organization with address, time zone and lock/member counts. GET /places.
| Argument | Type | Description |
|---|---|---|
| ids | string | Comma-separated list of ids to fetch. |
| sort | string | Sort order. |
| limit | integer | Max results to return (1-250). |
| query | string | Free-text search over place name. |
| offset | integer | Results to skip (offset paging; use pagination.next_offset). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"ids": {
"type": "string",
"description": "Comma-separated list of ids to fetch."
},
"sort": {
"enum": [
"name",
"-name"
],
"type": "string",
"description": "Sort order."
},
"limit": {
"type": "integer",
"maximum": 250,
"minimum": 1,
"description": "Max results to return (1-250)."
},
"query": {
"type": "string",
"description": "Free-text search over place name."
},
"offset": {
"type": "integer",
"maximum": 20000,
"minimum": 0,
"description": "Results to skip (offset paging; use pagination.next_offset)."
}
}
}Who was present at a place on a given day (derived from unlocks): actor, first/last unlock, last door. GET /presences.
| Argument | Type | Description |
|---|---|---|
| date* | string | The day: a date (2026-10-08) or an RFC 3339 date-time with offset (2026-10-08T09:00:00+02:00). Kisi reads it as a day in the place's time zone; a bare date is sent as noon UTC of that day. |
| limit | integer | Max results to return (1-250). |
| offset | integer | Results to skip (offset paging; use pagination.next_offset). |
| place_id* | integer | The place id (numeric). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"place_id",
"date"
],
"properties": {
"date": {
"type": "string",
"description": "The day: a date (2026-10-08) or an RFC 3339 date-time with offset (2026-10-08T09:00:00+02:00). Kisi reads it as a day in the place's time zone; a bare date is sent as noon UTC of that day."
},
"limit": {
"type": "integer",
"maximum": 250,
"minimum": 1,
"description": "Max results to return (1-250)."
},
"offset": {
"type": "integer",
"maximum": 20000,
"minimum": 0,
"description": "Results to skip (offset paging; use pagination.next_offset)."
},
"place_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "The place id (numeric).",
"exclusiveMinimum": 0
}
}
}Kisi readers (card/phone readers at doors) with model and online/offline status. GET /readers.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Max results to return (1-250). |
| query | string | Free-text search over name, device id and token. |
| offset | integer | Results to skip (offset paging; use pagination.next_offset). |
| status | string | Filter by status. |
| lock_id | integer | Only readers of this lock. |
| place_id | integer | Only readers in this place. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"limit": {
"type": "integer",
"maximum": 250,
"minimum": 1,
"description": "Max results to return (1-250)."
},
"query": {
"type": "string",
"description": "Free-text search over name, device id and token."
},
"offset": {
"type": "integer",
"maximum": 20000,
"minimum": 0,
"description": "Results to skip (offset paging; use pagination.next_offset)."
},
"status": {
"enum": [
"online",
"offline"
],
"type": "string",
"description": "Filter by status."
},
"lock_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only readers of this lock.",
"exclusiveMinimum": 0
},
"place_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only readers in this place.",
"exclusiveMinimum": 0
}
}
}Who holds which role where: a user/team/guest's role on the organization, a place or a group (group members = door access). Filter by user, group, place or role. GET /role_assignments.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Max results to return (1-250). |
| query | string | Free-text search over user email and name. |
| scope | string | Filter by scope. |
| offset | integer | Results to skip (offset paging; use pagination.next_offset). |
| role_id | string | Filter by role id, e.g. group_basic, group_manager, place_owner, organization_administrator. |
| user_id | integer | Only assignments of this user. |
| group_id | integer | Only assignments on this group. |
| place_id | integer | Only assignments on this place. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"limit": {
"type": "integer",
"maximum": 250,
"minimum": 1,
"description": "Max results to return (1-250)."
},
"query": {
"type": "string",
"description": "Free-text search over user email and name."
},
"scope": {
"enum": [
"organization",
"place",
"group",
"team"
],
"type": "string",
"description": "Filter by scope."
},
"offset": {
"type": "integer",
"maximum": 20000,
"minimum": 0,
"description": "Results to skip (offset paging; use pagination.next_offset)."
},
"role_id": {
"type": "string",
"description": "Filter by role id, e.g. group_basic, group_manager, place_owner, organization_administrator."
},
"user_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only assignments of this user.",
"exclusiveMinimum": 0
},
"group_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only assignments on this group.",
"exclusiveMinimum": 0
},
"place_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only assignments on this place.",
"exclusiveMinimum": 0
}
}
}Time rules: when a group's access is allowed, when doors auto-unlock (unlock timer), first-to-arrive, elevator permit timers. Filter by consequence or by the group/lock it applies to. GET /schedules.
| Argument | Type | Description |
|---|---|---|
| ids | string | Comma-separated list of ids to fetch. |
| limit | integer | Max results to return (1-250). |
| offset | integer | Results to skip (offset paging; use pagination.next_offset). |
| consequence | string | Filter by what the schedule does. |
| scheduleable_id | integer | Id of the group/lock/elevator stop (use with scheduleable_type). |
| scheduleable_type | string | Type of the object (use with scheduleable_id). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"ids": {
"type": "string",
"description": "Comma-separated list of ids to fetch."
},
"limit": {
"type": "integer",
"maximum": 250,
"minimum": 1,
"description": "Max results to return (1-250)."
},
"offset": {
"type": "integer",
"maximum": 20000,
"minimum": 0,
"description": "Results to skip (offset paging; use pagination.next_offset)."
},
"consequence": {
"enum": [
"allow",
"first_to_arrive",
"permit",
"unlock"
],
"type": "string",
"description": "Filter by what the schedule does."
},
"scheduleable_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Id of the group/lock/elevator stop (use with scheduleable_type).",
"exclusiveMinimum": 0
},
"scheduleable_type": {
"enum": [
"Group",
"Lock",
"ElevatorStop"
],
"type": "string",
"description": "Type of the object (use with scheduleable_id)."
}
}
}List users (members) of the organization. Filter by group or place (users with access there), email, or free text over name/email/notes. Sort by last unlock. GET /users.
| Argument | Type | Description |
|---|---|---|
| ids | string | Comma-separated list of ids to fetch. |
| sort | string | Sort order; 'unlock' = by last unlock. |
| string | Exact email filter. | |
| limit | integer | Max results to return (1-100). |
| query | string | Free-text search over user email, name and notes. |
| offset | integer | Results to skip (offset paging; use pagination.next_offset). |
| group_id | integer | Only members of this group. |
| place_id | integer | Only users with access to this place. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"ids": {
"type": "string",
"description": "Comma-separated list of ids to fetch."
},
"sort": {
"enum": [
"name",
"-name",
"unlock",
"-unlock",
"access_enabled",
"-access_enabled"
],
"type": "string",
"description": "Sort order; 'unlock' = by last unlock."
},
"email": {
"type": "string",
"description": "Exact email filter."
},
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "Max results to return (1-100)."
},
"query": {
"type": "string",
"description": "Free-text search over user email, name and notes."
},
"offset": {
"type": "integer",
"maximum": 20000,
"minimum": 0,
"description": "Results to skip (offset paging; use pagination.next_offset)."
},
"group_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only members of this group.",
"exclusiveMinimum": 0
},
"place_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only users with access to this place.",
"exclusiveMinimum": 0
}
}
}Search the access log (unlocks, denied attempts, lockdowns, admin changes) and return the first page. This CREATES a temporary saved search in Kisi (an event set, cursor-paginated, kept ~24 h); it changes no door, user or access right. Defaults to the past 90 days, the maximum width. If status is still in_progress or cursor is set, call kisi_get_event_set with the returned id. POST /event_sets.
| Argument | Type | Description |
|---|---|---|
| type | string | Event type(s), comma-separated, e.g. lock.unlock (see kisi_list_event_types). |
| success | boolean | Only successful (true) or failed/denied (false) events. |
| actor_id | integer | Only events by this actor (e.g. a user id). |
| interval | string | ISO 8601 interval on event time, max 90 days: start/end (2026-10-01T00:00:00Z/2026-10-08T00:00:00Z), start/duration (2026-10-01T00:00:00Z/P7D) or duration/end (P1D/2026-10-08T00:00:00Z). |
| place_id | integer | Only events at this place. |
| object_id | integer | Only events about this object (e.g. a lock id). |
| actor_type | string | Actor type (use with actor_id). |
| object_type | string | Object type, e.g. Lock, Place, Group, User (use with object_id). |
| boolean |
| Filter by whether the lock is configured. |
| locked_down | boolean | Filter by lockdown state. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"ids": {
"type": "string",
"description": "Comma-separated list of ids to fetch."
},
"sort": {
"enum": [
"name",
"-name"
],
"type": "string",
"description": "Sort order."
},
"limit": {
"type": "integer",
"maximum": 250,
"minimum": 1,
"description": "Max results to return (1-250)."
},
"query": {
"type": "string",
"description": "Free-text search over lock name."
},
"offset": {
"type": "integer",
"maximum": 20000,
"minimum": 0,
"description": "Results to skip (offset paging; use pagination.next_offset)."
},
"online": {
"type": "boolean",
"description": "Filter by online (true) / offline (false)."
},
"floor_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only locks on this floor.",
"exclusiveMinimum": 0
},
"place_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only locks in this place.",
"exclusiveMinimum": 0
},
"unlocked": {
"type": "boolean",
"description": "Filter by currently unlocked (true) / locked (false)."
},
"configured": {
"type": "boolean",
"description": "Filter by whether the lock is configured."
},
"locked_down": {
"type": "boolean",
"description": "Filter by lockdown state."
}
}
}{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"type": {
"type": "string",
"description": "Event type(s), comma-separated, e.g. lock.unlock (see kisi_list_event_types)."
},
"success": {
"type": "boolean",
"description": "Only successful (true) or failed/denied (false) events."
},
"actor_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only events by this actor (e.g. a user id).",
"exclusiveMinimum": 0
},
"interval": {
"type": "string",
"description": "ISO 8601 interval on event time, max 90 days: start/end (2026-10-01T00:00:00Z/2026-10-08T00:00:00Z), start/duration (2026-10-01T00:00:00Z/P7D) or duration/end (P1D/2026-10-08T00:00:00Z)."
},
"place_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only events at this place.",
"exclusiveMinimum": 0
},
"object_id": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Only events about this object (e.g. a lock id).",
"exclusiveMinimum": 0
},
"actor_type": {
"enum": [
"User",
"Guest",
"GroupLink",
"MarketplaceInstallation"
],
"type": "string",
"description": "Actor type (use with actor_id)."
},
"object_type": {
"type": "string",
"description": "Object type, e.g. Lock, Place, Group, User (use with object_id)."
}
}
}