mcp-miro
by evalstate
- mcp-miro
- src
import fetch from 'node-fetch';
interface MiroBoard {
id: string;
name: string;
description?: string;
}
interface MiroBoardsResponse {
data: MiroBoard[];
total: number;
size: number;
offset: number;
}
interface MiroItem {
id: string;
type: string;
[key: string]: any;
}
interface MiroItemsResponse {
data: MiroItem[];
cursor?: string;
}
export class MiroClient {
constructor(private token: string) {}
private async fetchApi(path: string, options: { method?: string; body?: any } = {}) {
const response = await fetch(`https://api.miro.com/v2${path}`, {
method: options.method || 'GET',
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
},
...(options.body ? { body: JSON.stringify(options.body) } : {})
});
if (!response.ok) {
throw new Error(`Miro API error: ${response.status} ${response.statusText}`);
}
return response.json();
}
async getBoards(): Promise<MiroBoard[]> {
const response = await this.fetchApi('/boards') as MiroBoardsResponse;
return response.data;
}
async getBoardItems(boardId: string): Promise<MiroItem[]> {
const response = await this.fetchApi(`/boards/${boardId}/items?limit=50`) as MiroItemsResponse;
return response.data;
}
async createStickyNote(boardId: string, data: any): Promise<MiroItem> {
return this.fetchApi(`/boards/${boardId}/sticky_notes`, {
method: 'POST',
body: data
}) as Promise<MiroItem>;
}
async bulkCreateItems(boardId: string, items: any[]): Promise<MiroItem[]> {
const response = await fetch(`https://api.miro.com/v2/boards/${boardId}/items/bulk`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(items)
});
if (!response.ok) {
const error = await response.json() as { message?: string };
throw new Error(`Miro API error: ${error.message || response.statusText}`);
}
const result = await response.json() as { data: MiroItem[] };
return result.data || [];
}
async getFrames(boardId: string): Promise<MiroItem[]> {
const response = await this.fetchApi(`/boards/${boardId}/items?type=frame&limit=50`) as MiroItemsResponse;
return response.data;
}
async getItemsInFrame(boardId: string, frameId: string): Promise<MiroItem[]> {
const response = await this.fetchApi(`/boards/${boardId}/items?parent_item_id=${frameId}&limit=50`) as MiroItemsResponse;
return response.data;
}
async createShape(boardId: string, data: any): Promise<MiroItem> {
return this.fetchApi(`/boards/${boardId}/shapes`, {
method: 'POST',
body: data
}) as Promise<MiroItem>;
}
}