cozi-client.ts•2.1 kB
/**
* Cozi API client for MCP server
*/
import type { CoziList, CoziItem } from './types';
const COZI_API_BASE = 'https://rest.cozi.com/api/ext/2207';
export class CoziClient {
constructor(
private accessToken: string,
private accountId: string
) {}
private async request<T>(path: string, options?: RequestInit): Promise<T> {
const url = `${COZI_API_BASE}${path}`;
const response = await fetch(url, {
...options,
headers: {
...options?.headers,
'Authorization': `Bearer ${this.accessToken}`,
'User-Agent': 'FamilyCast MCP Server',
},
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Cozi API error: ${response.status} ${errorText}`);
}
return response.json();
}
async getLists(): Promise<CoziList[]> {
return this.request<CoziList[]>(`/${this.accountId}/list/`);
}
async getList(listId: string): Promise<CoziList> {
return this.request<CoziList>(`/${this.accountId}/list/${listId}`);
}
async addItem(listId: string, text: string): Promise<void> {
await this.request(`/${this.accountId}/list/${listId}/item/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text }),
});
}
async removeItem(listId: string, itemId: string): Promise<void> {
await this.request(`/${this.accountId}/list/${listId}/item/${itemId}`, {
method: 'DELETE',
});
}
async markItem(listId: string, itemId: string, completed: boolean): Promise<void> {
await this.request(`/${this.accountId}/list/${listId}/item/${itemId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ status: completed ? 'complete' : 'incomplete' }),
});
}
async editItem(listId: string, itemId: string, text: string): Promise<void> {
await this.request(`/${this.accountId}/list/${listId}/item/${itemId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text }),
});
}
}