import { z } from 'zod';
import * as unifi from '../unifi-client.js';
export const accessTools = {
// ========================================
// Door Listing
// ========================================
list_doors: {
description: 'List all UniFi Access doors for a host',
schema: z.object({
hostId: z.string().describe('The host ID')
}),
handler: async ({ hostId }) => {
const doors = await unifi.listDoors(hostId);
return {
content: [{ type: 'text', text: JSON.stringify(doors, null, 2) }]
};
}
},
get_door: {
description: 'Get details of a specific door',
schema: z.object({
hostId: z.string().describe('The host ID'),
doorId: z.string().describe('The door ID')
}),
handler: async ({ hostId, doorId }) => {
const door = await unifi.getDoor(hostId, doorId);
return {
content: [{ type: 'text', text: JSON.stringify(door, null, 2) }]
};
}
},
// ========================================
// Door Controls
// ========================================
unlock_door: {
description: 'Temporarily unlock a door for a specified duration',
schema: z.object({
hostId: z.string().describe('The host ID'),
doorId: z.string().describe('The door ID'),
duration: z.number().min(1).max(300).optional().default(5).describe('Duration in seconds to keep door unlocked (1-300)'),
confirm: z.boolean().describe('Confirm you want to unlock this door')
}),
handler: async ({ hostId, doorId, duration, confirm }) => {
if (!confirm) {
return {
content: [{
type: 'text',
text: `Door unlock cancelled. Set confirm=true to unlock the door for ${duration} seconds.`
}]
};
}
const result = await unifi.unlockDoor(hostId, doorId, duration);
return {
content: [{
type: 'text',
text: `Door unlocked for ${duration} seconds. It will automatically lock after the duration expires. ${JSON.stringify(result, null, 2)}`
}]
};
}
},
lock_door: {
description: 'Immediately lock a door',
schema: z.object({
hostId: z.string().describe('The host ID'),
doorId: z.string().describe('The door ID')
}),
handler: async ({ hostId, doorId }) => {
const result = await unifi.lockDoor(hostId, doorId);
return {
content: [{ type: 'text', text: `Door locked. ${JSON.stringify(result, null, 2)}` }]
};
}
},
// ========================================
// Door Search
// ========================================
find_door_by_name: {
description: 'Search for doors by name',
schema: z.object({
hostId: z.string().describe('The host ID'),
query: z.string().describe('The search query for door name')
}),
handler: async ({ hostId, query }) => {
const queryLower = query.toLowerCase();
const doorsResponse = await unifi.listDoors(hostId);
const doors = doorsResponse.data || [];
const matches = doors.filter(d => {
const name = (d.name || '').toLowerCase();
return name.includes(queryLower);
});
return {
content: [{
type: 'text',
text: JSON.stringify({
searchQuery: query,
matchCount: matches.length,
matches
}, null, 2)
}]
};
}
},
get_doors_status_summary: {
description: 'Get a summary of all door statuses',
schema: z.object({
hostId: z.string().describe('The host ID')
}),
handler: async ({ hostId }) => {
const doorsResponse = await unifi.listDoors(hostId);
const doors = doorsResponse.data || [];
const summary = {
total: doors.length,
locked: 0,
unlocked: 0,
online: 0,
offline: 0,
doors: []
};
doors.forEach(door => {
// Count lock status
if (door.lockState === 'LOCKED' || door.isLocked) {
summary.locked++;
} else {
summary.unlocked++;
}
// Count connection status
if (door.state === 'CONNECTED' || door.isConnected) {
summary.online++;
} else {
summary.offline++;
}
// Add door info
summary.doors.push({
id: door.id,
name: door.name,
lockState: door.lockState,
state: door.state
});
});
return {
content: [{ type: 'text', text: JSON.stringify(summary, null, 2) }]
};
}
}
};
export default accessTools;