This is page 1 of 2. Use http://codebase.md/k-jarzyna/mcp-miro?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .env.template
├── .gitignore
├── Dockerfile
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── smithery.yaml
├── src
│ ├── client.ts
│ ├── index.ts
│ ├── server-response.ts
│ ├── server.ts
│ ├── tool-bootstrapper.ts
│ ├── tool.ts
│ └── tools
│ ├── addProjectMember.ts
│ ├── attachTag.ts
│ ├── copyBoard.ts
│ ├── createAppCardItem.ts
│ ├── createBoard.ts
│ ├── createBoardExportJob.ts
│ ├── createCardItem.ts
│ ├── createConnector.ts
│ ├── createDocumentItem.ts
│ ├── createEmbedItem.ts
│ ├── createFrameItem.ts
│ ├── createGroup.ts
│ ├── createImageItemUsingFileFromDevice.ts
│ ├── createImageItemUsingUrl.ts
│ ├── createItemsInBulk.ts
│ ├── createItemsInBulkUsingFile.ts
│ ├── createMindmapNode.ts
│ ├── createShapeItem.ts
│ ├── createStickyNoteItem.ts
│ ├── createTag.ts
│ ├── createTextItem.ts
│ ├── deleteAppCardItem.ts
│ ├── deleteBoard.ts
│ ├── deleteCardItem.ts
│ ├── deleteConnector.ts
│ ├── deleteDocumentItem.ts
│ ├── deleteEmbedItem.ts
│ ├── deleteFrameItem.ts
│ ├── deleteGroup.ts
│ ├── deleteImageItem.ts
│ ├── deleteItem.ts
│ ├── deleteMindmapNode.ts
│ ├── deleteShapeItem.ts
│ ├── deleteStickyNoteItem.ts
│ ├── deleteTag.ts
│ ├── deleteTextItem.ts
│ ├── detachTag.ts
│ ├── getAllBoardMembers.ts
│ ├── getAllCases.ts
│ ├── getAllGroups.ts
│ ├── getAllLegalHolds.ts
│ ├── getAllTags.ts
│ ├── getAppCardItem.ts
│ ├── getAuditLogs.ts
│ ├── getBoardClassification.ts
│ ├── getBoardContentLogs.ts
│ ├── getBoardExportJobResults.ts
│ ├── getBoardExportJobStatus.ts
│ ├── getCardItem.ts
│ ├── getCase.ts
│ ├── getConnectors.ts
│ ├── getDocumentItem.ts
│ ├── getEmbedItem.ts
│ ├── getFrameItem.ts
│ ├── getGroup.ts
│ ├── getGroupItems.ts
│ ├── getImageItem.ts
│ ├── getItemsOnBoard.ts
│ ├── getItemTags.ts
│ ├── getLegalHold.ts
│ ├── getLegalHoldContentItems.ts
│ ├── getMindmapNode.ts
│ ├── getMindmapNodes.ts
│ ├── getOrganizationInfo.ts
│ ├── getOrganizationMember.ts
│ ├── getOrganizationMembers.ts
│ ├── getProjectMember.ts
│ ├── getShapeItem.ts
│ ├── getSpecificBoard.ts
│ ├── getSpecificBoardMember.ts
│ ├── getSpecificConnector.ts
│ ├── getSpecificItem.ts
│ ├── getStickyNoteItem.ts
│ ├── getTag.ts
│ ├── getTextItem.ts
│ ├── listBoards.ts
│ ├── removeBoardMember.ts
│ ├── removeProjectMember.ts
│ ├── shareBoard.ts
│ ├── ungroupItems.ts
│ ├── updateAppCardItem.ts
│ ├── updateBoard.ts
│ ├── updateBoardClassification.ts
│ ├── updateBoardMember.ts
│ ├── updateCardItem.ts
│ ├── updateConnector.ts
│ ├── updateDocumentItem.ts
│ ├── updateEmbedItem.ts
│ ├── updateFrameItem.ts
│ ├── updateGroup.ts
│ ├── updateImageItem.ts
│ ├── updateImageItemUsingFileFromDevice.ts
│ ├── updateItemPosition.ts
│ ├── updateShapeItem.ts
│ ├── updateStickyNoteItem.ts
│ ├── updateTag.ts
│ └── updateTextItem.ts
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/.env.template:
--------------------------------------------------------------------------------
```
1 | # Miro API Configuration
2 | # Get your access token from https://developers.miro.com/
3 | MIRO_ACCESS_TOKEN=your_miro_access_token_here
4 |
```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
1 | # Dependency directories
2 | node_modules/
3 |
4 | # TypeScript compiled output
5 | build/
6 | dist/
7 |
8 | # Environment files
9 | .env
10 |
11 | # IDE files
12 | .idea/
13 | .vscode/
14 |
15 | # Logs
16 | logs
17 | *.log
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
22 | # OS specific
23 | .DS_Store
24 | Thumbs.db
25 |
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # MCP Miro Server
2 |
3 | [](https://archestra.ai/mcp-catalog/k-jarzyna__mcp-miro)
4 | [](https://smithery.ai/server/@k-jarzyna/mcp-miro)
5 |
6 | Model Context Protocol (MCP) server integrating with the [Miro](https://miro.com/) platform. It enables AI assistants (like Claude) to access Miro boards and manage their content through a standardized interface.
7 |
8 | ---
9 | ### Requirements
10 |
11 | - Node.js v16 or newer installed
12 | - Miro account with API token
13 |
14 | ### Generate Miro Access Token
15 |
16 | 1. Go to the [Miro Developer Portal](https://developers.miro.com/docs)
17 | 2. Create a new app or use an existing one
18 | 3. Make sure to create token with permission selected below
19 | 4. Generate OAuth token by selecting `Install app and get OAuth token`
20 |
21 | | Permission | Required |
22 | |-------------------|:--------:|
23 | | boards:read | ✅ |
24 | | boards:write | ✅ |
25 | | identity:read | ✅ |
26 | | identity:write | ✅ |
27 | | team:read | ✅ |
28 | | team:write | ✅ |
29 | | microphone:listen | ❌ |
30 | | screen:record | ❌ |
31 | | webcam:record | ❌ |
32 | | auditlogs:read | ❌ |
33 | | sessions:delete | ❌ |
34 |
35 | ### Connecting with Claude Desktop
36 |
37 | 1. Install [Claude Desktop](https://claude.ai/download)
38 | 2. Open or create the configuration file:
39 | - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
40 | - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
41 |
42 | 3. Update it to include this server:
43 |
44 | ```json
45 | {
46 | "mcpServers":{
47 | "miro":{
48 | "command":"npx",
49 | "args":[
50 | "-y",
51 | "@k-jarzyna/mcp-miro"
52 | ],
53 | "env":{
54 | "MIRO_ACCESS_TOKEN":"your_miro_access_token"
55 | }
56 | }
57 | }
58 | }
59 | ```
60 |
61 | 4. Restart Claude Desktop
62 |
63 | ---
64 | ## Available Tools and Resources
65 |
66 | #### Tools
67 | | Miro SDK Function | MCP Tool | Available |
68 | |-------------------|----------|-----------|
69 | | List boards | list-boards | ✅ |
70 | | Create board | create-board | ✅ |
71 | | Update board | update-board | ✅ |
72 | | Delete board | delete-board | ✅ |
73 | | Copy board | copy-board | ✅ |
74 | | Get specific board | get-specific-board | ✅ |
75 | | Get items on board | get-items-on-board | ✅ |
76 | | Get specific item | get-specific-item | ✅ |
77 | | Update item position | update-item-position | ✅ |
78 | | Delete item | delete-item | ✅ |
79 | | Create app card item | create-app-card-item | ✅ |
80 | | Get app card item | get-app-card-item | ✅ |
81 | | Update app card item | update-app-card-item | ✅ |
82 | | Delete app card item | delete-app-card-item | ✅ |
83 | | Create card item | create-card-item | ✅ |
84 | | Get card item | get-card-item | ✅ |
85 | | Update card item | update-card-item | ✅ |
86 | | Delete card item | delete-card-item | ✅ |
87 | | Create connector | create-connector | ✅ |
88 | | Get connectors | get-connectors | ✅ |
89 | | Get specific connector | get-specific-connector | ✅ |
90 | | Update connector | update-connector | ✅ |
91 | | Delete connector | delete-connector | ✅ |
92 | | Create sticky note item | create-sticky-note-item | ✅ |
93 | | Get sticky note item | get-sticky-note-item | ✅ |
94 | | Update sticky note item | update-sticky-note-item | ✅ |
95 | | Delete sticky note item | delete-sticky-note-item | ✅ |
96 | | Create frame | create-frame | ✅ |
97 | | Get frame item | get-frame-item | ✅ |
98 | | Update frame item | update-frame-item | ✅ |
99 | | Delete frame item | delete-frame-item | ✅ |
100 | | Create document item | create-document-item | ✅ |
101 | | Get document item | get-document-item | ✅ |
102 | | Update document item | update-document-item | ✅ |
103 | | Delete document item | delete-document-item | ✅ |
104 | | Create text item | create-text-item | ✅ |
105 | | Get text item | get-text-item | ✅ |
106 | | Update text item | update-text-item | ✅ |
107 | | Delete text item | delete-text-item | ✅ |
108 | | Create items in bulk | create-items-in-bulk | ✅ |
109 | | Create image item using URL | create-image-item-using-url | ✅ |
110 | | Create image item using file | create-image-item-using-file | ✅ |
111 | | Get image item | get-image-item | ✅ |
112 | | Update image item | update-image-item | ✅ |
113 | | Update image item using file | update-image-item-using-file | ✅ |
114 | | Delete image item | delete-image-item | ✅ |
115 | | Create shape item | create-shape-item | ✅ |
116 | | Get shape item | get-shape-item | ✅ |
117 | | Update shape item | update-shape-item | ✅ |
118 | | Delete shape item | delete-shape-item | ✅ |
119 | | Create embed item | create-embed-item | ✅ |
120 | | Get embed item | get-embed-item | ✅ |
121 | | Update embed item | update-embed-item | ✅ |
122 | | Delete embed item | delete-embed-item | ✅ |
123 | | Create tag | create-tag | ✅ |
124 | | Get tag | get-tag | ✅ |
125 | | Get all tags | get-all-tags | ✅ |
126 | | Update tag | update-tag | ✅ |
127 | | Delete tag | delete-tag | ✅ |
128 | | Attach tag | attach-tag | ✅ |
129 | | Detach tag | detach-tag | ✅ |
130 | | Get item tags | get-item-tags | ✅ |
131 | | Get all board members | get-all-board-members | ✅ |
132 | | Get specific board member | get-specific-board-member | ✅ |
133 | | Remove board member | remove-board-member | ✅ |
134 | | Share board | share-board | ✅ |
135 | | Update board member | update-board-member | ✅ |
136 | | Create group | create-group | ✅ |
137 | | Get all groups | get-all-groups | ✅ |
138 | | Get group | get-group | ✅ |
139 | | Get group items | get-group-items | ✅ |
140 | | Update group | update-group | ✅ |
141 | | Ungroup items | ungroup-items | ✅ |
142 | | Delete group | delete-group | ✅ |
143 | | Create items in bulk using file | create-items-in-bulk-using-file | ✅ |
144 | | Create mindmap node | create-mindmap-node | ✅ |
145 | | Get mindmap node | get-mindmap-node | ✅ |
146 | | Get mindmap nodes | get-mindmap-nodes | ✅ |
147 | | Delete mindmap node | delete-mindmap-node | ✅ |
148 | | Add project member | add-project-member | ✅ |
149 | | Create board export job | create-board-export-job | ✅ |
150 | | Get all cases | get-all-cases | ✅ |
151 | | Get all legal holds | get-all-legal-holds | ✅ |
152 | | Get audit logs | get-audit-logs | ✅ |
153 | | Get board classification | get-board-classification | ✅ |
154 | | Get board content logs | get-board-content-logs | ✅ |
155 | | Get board export job results | get-board-export-job-results | ✅ |
156 | | Get board export job status | get-board-export-job-status | ✅ |
157 | | Get case | get-case | ✅ |
158 | | Get legal hold | get-legal-hold | ✅ |
159 | | Get legal hold content items | get-legal-hold-content-items | ✅ |
160 | | Get organization info | get-organization-info | ✅ |
161 | | Get organization member | get-organization-member | ✅ |
162 | | Get organization members | get-organization-members | ✅ |
163 | | Get project member | get-project-member | ✅ |
164 | | Remove project member | remove-project-member | ✅ |
165 | | Update board classification | update-board-classification | ✅ |
166 |
167 |
168 | ---
169 | ## Local Development
170 |
171 | 1. Install dependencies:
172 |
173 | ```bash
174 | npm install
175 | ```
176 |
177 | 2. Create a `.env` file based on the template:
178 |
179 | ```bash
180 | cp .env.template .env
181 | ```
182 |
183 | 3. Edit the `.env` file and add your Miro access token
184 |
185 | 4. Build the server:
186 |
187 | ```bash
188 | npm run build
189 | ```
190 |
191 | ### Running the Server
192 |
193 | To run the server:
194 |
195 | ```bash
196 | node build/index.js
197 | ```
198 |
199 | ---
200 | ## License
201 |
202 | Apache License 2.0
203 |
204 | This project is licensed under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for details.
205 |
```
--------------------------------------------------------------------------------
/src/tool.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';
2 | import { ZodRawShape } from 'zod';
3 |
4 | export type ToolSchema = {
5 | name: string;
6 | description: string;
7 | args: ZodRawShape;
8 | fn: ToolCallback<any>;
9 | }
```
--------------------------------------------------------------------------------
/src/server.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2 |
3 | const server = new McpServer({
4 | name: "mcp-miro",
5 | version: "1.0.0",
6 | capabilities: {
7 | tools: { listChanged: true },
8 | resources: { listChanged: true }
9 | }
10 | });
11 |
12 | export default server;
```
--------------------------------------------------------------------------------
/src/tool-bootstrapper.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2 | import { ToolSchema } from './tool.js';
3 |
4 | export class ToolBootstrapper {
5 | constructor(
6 | private readonly server: McpServer
7 | ) {
8 | }
9 |
10 | public register(tool: ToolSchema): this {
11 | this.server.tool(tool.name, tool.description, tool.args, tool.fn);
12 |
13 | return this;
14 | }
15 | }
```
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
1 | # Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
2 | FROM node:lts-alpine
3 |
4 | # Create app directory
5 | WORKDIR /app
6 |
7 | # Install dependencies without running scripts
8 | COPY package.json package-lock.json ./
9 | RUN npm install --ignore-scripts
10 |
11 | # Copy source and build
12 | COPY . .
13 | RUN npm run build
14 |
15 | # Expose no ports; use stdio
16 | CMD ["node", "build/index.js"]
17 |
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "compilerOptions": {
3 | "target": "ES2022",
4 | "module": "Node16",
5 | "moduleResolution": "Node16",
6 | "outDir": "./build",
7 | "rootDir": "./src",
8 | "strict": false,
9 | "esModuleInterop": true,
10 | "skipLibCheck": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "noImplicitAny": false,
13 | "preserveSymlinks": true
14 | },
15 | "include": ["src/**/*"],
16 | "exclude": ["node_modules"]
17 | }
18 |
```
--------------------------------------------------------------------------------
/src/server-response.ts:
--------------------------------------------------------------------------------
```typescript
1 | export class ServerResponse {
2 | content: { type: string, text: string }[];
3 | isError: boolean = false;
4 |
5 | public static text(text: string): any {
6 | return Object.assign(new ServerResponse(), {
7 | content: [
8 | {
9 | type: 'text',
10 | text
11 | }
12 | ]
13 | })
14 | }
15 |
16 | public static error(err: string): any {
17 | return Object.assign(new ServerResponse(), {
18 | content: [
19 | {
20 | type: 'text',
21 | text: typeof err === 'object' ? JSON.stringify(err) : err
22 | },
23 | ],
24 | isError: true
25 | })
26 | }
27 | }
```
--------------------------------------------------------------------------------
/src/client.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { MiroLowlevelApi } from "@mirohq/miro-api";
2 |
3 | export class MiroClient {
4 | private static instance: MiroClient;
5 | private api: MiroLowlevelApi;
6 |
7 | private constructor() {
8 | const accessToken = process.env.MIRO_ACCESS_TOKEN;
9 |
10 | if (!accessToken) {
11 | throw new Error('MIRO_ACCESS_TOKEN environment variable is required');
12 | }
13 |
14 | this.api = new MiroLowlevelApi(accessToken);
15 | }
16 |
17 | public static getApi(): MiroLowlevelApi {
18 | if (!MiroClient.instance) {
19 | MiroClient.instance = new MiroClient();
20 | }
21 |
22 | return MiroClient.instance.api;
23 | }
24 | }
25 |
26 | export default MiroClient;
27 |
```
--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------
```yaml
1 | # Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml
2 |
3 | startCommand:
4 | type: stdio
5 | configSchema:
6 | # JSON Schema defining the configuration options for the MCP.
7 | type: object
8 | required:
9 | - miroAccessToken
10 | properties:
11 | miroAccessToken:
12 | type: string
13 | description: Miro OAuth access token
14 | commandFunction:
15 | # A JS function that produces the CLI command based on the given config to start the MCP on stdio.
16 | |-
17 | (config) => ({ command: 'node', args: ['build/index.js'], env: { MIRO_ACCESS_TOKEN: config.miroAccessToken } })
18 | exampleConfig:
19 | miroAccessToken: your_miro_access_token_here
20 |
```
--------------------------------------------------------------------------------
/src/tools/getOrganizationInfo.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getOrganizationInfoTool: ToolSchema = {
7 | name: "get-organization-info",
8 | description: "Retrieves organization information (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("id of the organization")
11 | },
12 | fn: async ({ orgId }) => {
13 | try {
14 | const response = await MiroClient.getApi().enterpriseGetOrganization(orgId);
15 |
16 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
17 | } catch (error) {
18 | process.stderr.write(`Error retrieving organization info: ${error}\n`);
19 | return ServerResponse.error(error);
20 | }
21 | }
22 | };
23 |
24 | export default getOrganizationInfoTool;
```
--------------------------------------------------------------------------------
/src/tools/listBoards.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const listBoardsTool: ToolSchema = {
7 | name: "list-boards",
8 | description: "List all available Miro boards",
9 | args: {
10 | limit: z.number().optional().nullish().describe("Maximum number of boards to return (default: 50)"),
11 | offset: z.number().optional().nullish().describe("Offset for pagination (default: 0)")
12 | },
13 | fn: async ({ limit = 50, offset = 0 }) => {
14 | try {
15 |
16 | const boardsData = await MiroClient.getApi().getBoards();
17 |
18 | return ServerResponse.text(JSON.stringify(boardsData, null, 2))
19 | } catch (error) {
20 | process.stderr.write(`Error fetching Miro boards: ${error}\n`);
21 |
22 | return ServerResponse.error(error)
23 | }
24 | }
25 | }
26 |
27 | export default listBoardsTool;
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "@k-jarzyna/mcp-miro",
3 | "version": "1.0.9",
4 | "main": "build/index.js",
5 | "type": "module",
6 | "scripts": {
7 | "build": "tsc",
8 | "clean": "rm -rf build/",
9 | "prebuild": "npm run clean",
10 | "postbuild": "chmod +x build/index.js"
11 | },
12 | "bin": {
13 | "mcp-miro": "build/index.js"
14 | },
15 | "keywords": [],
16 | "author": "Konrad Jarzyna",
17 | "license": "Apache-2.0",
18 | "description": "Miro integration for Model Context Protocol",
19 | "dependencies": {
20 | "@mirohq/miro-api": "^2.2.4",
21 | "@modelcontextprotocol/sdk": "^1.8.0",
22 | "dotenv": "^16.4.7",
23 | "zod": "^3.24.2"
24 | },
25 | "devDependencies": {
26 | "@types/node": "^22.14.0",
27 | "typescript": "^5.8.2"
28 | },
29 | "repository": {
30 | "type": "git",
31 | "url": "https://github.com/k-jarzyna/mcp-miro"
32 | },
33 | "files": [
34 | "build"
35 | ],
36 | "homepage": "https://github.com/k-jarzyna/mcp-miro"
37 | }
38 |
```
--------------------------------------------------------------------------------
/src/tools/getCase.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getCaseTool: ToolSchema = {
7 | name: "get-case",
8 | description: "Retrieves information about a specific eDiscovery case (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("The ID of the organization for which you want to retrieve the case information"),
11 | caseId: z.string().describe("The ID of the case you want to retrieve")
12 | },
13 | fn: async ({ orgId, caseId }) => {
14 | try {
15 | const response = await MiroClient.getApi().getCase(orgId, caseId);
16 |
17 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
18 | } catch (error) {
19 | process.stderr.write(`Error retrieving case: ${error}\n`);
20 | return ServerResponse.error(error);
21 | }
22 | }
23 | };
24 |
25 | export default getCaseTool;
```
--------------------------------------------------------------------------------
/src/tools/getSpecificBoard.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getSpecificBoardTool: ToolSchema = {
7 | name: "get-specific-board",
8 | description: "Retrieve information about a specific Miro board by its ID",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that you want to retrieve")
11 | },
12 | fn: async ({ boardId }) => {
13 | try {
14 | if (!boardId) {
15 | return ServerResponse.error("Board ID is required");
16 | }
17 |
18 | const boardData = await MiroClient.getApi().getSpecificBoard(boardId);
19 |
20 | return ServerResponse.text(JSON.stringify(boardData, null, 2));
21 | } catch (error) {
22 | process.stderr.write(`Error fetching specific Miro board: ${error}\n`);
23 |
24 | return ServerResponse.error(error);
25 | }
26 | }
27 | }
28 |
29 | export default getSpecificBoardTool;
```
--------------------------------------------------------------------------------
/src/tools/getOrganizationMember.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getOrganizationMemberTool: ToolSchema = {
7 | name: "get-organization-member",
8 | description: "Retrieves information about a specific organization member (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("id of the organization"),
11 | memberId: z.string().describe("id of the organization member")
12 | },
13 | fn: async ({ orgId, memberId }) => {
14 | try {
15 | const response = await MiroClient.getApi().enterpriseGetOrganizationMember(orgId, memberId);
16 |
17 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
18 | } catch (error) {
19 | process.stderr.write(`Error retrieving organization member: ${error}\n`);
20 | return ServerResponse.error(error);
21 | }
22 | }
23 | };
24 |
25 | export default getOrganizationMemberTool;
```
--------------------------------------------------------------------------------
/src/tools/getBoardExportJobResults.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getBoardExportJobResultsTool: ToolSchema = {
7 | name: "get-board-export-job-results",
8 | description: "Retrieves the results of a board export job (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("Unique identifier of the organization"),
11 | jobId: z.string().describe("Unique identifier of the job")
12 | },
13 | fn: async ({ orgId, jobId }) => {
14 | try {
15 | const response = await MiroClient.getApi().enterpriseBoardExportJobResults(orgId, jobId);
16 |
17 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
18 | } catch (error) {
19 | process.stderr.write(`Error retrieving board export job results: ${error}\n`);
20 | return ServerResponse.error(error);
21 | }
22 | }
23 | };
24 |
25 | export default getBoardExportJobResultsTool;
```
--------------------------------------------------------------------------------
/src/tools/getBoardExportJobStatus.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getBoardExportJobStatusTool: ToolSchema = {
7 | name: "get-board-export-job-status",
8 | description: "Retrieves the status of a board export job (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("Unique identifier of the organization"),
11 | jobId: z.string().describe("Unique identifier of the board export job")
12 | },
13 | fn: async ({ orgId, jobId }) => {
14 | try {
15 | const response = await MiroClient.getApi().enterpriseBoardExportJobStatus(orgId, jobId);
16 |
17 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
18 | } catch (error) {
19 | process.stderr.write(`Error retrieving board export job status: ${error}\n`);
20 | return ServerResponse.error(error);
21 | }
22 | }
23 | };
24 |
25 | export default getBoardExportJobStatusTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteMindmapNode.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteMindmapNodeTool: ToolSchema = {
7 | name: "delete-mindmap-node",
8 | description: "Delete a mind map node from a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board from which you want to delete the mind map node"),
11 | itemId: z.string().describe("Unique identifier (ID) of the mind map node that you want to delete")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | const response = await MiroClient.getApi().deleteMindmapNodeExperimental(boardId, itemId);
16 |
17 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
18 | } catch (error) {
19 | process.stderr.write(`Error deleting Miro mind map node: ${error}\n`);
20 | return ServerResponse.error(error);
21 | }
22 | }
23 | };
24 |
25 | export default deleteMindmapNodeTool;
```
--------------------------------------------------------------------------------
/src/tools/getTag.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getTagTool: ToolSchema = {
7 | name: "get-tag",
8 | description: "Retrieve information about a specific tag on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the tag"),
11 | tagId: z.string().describe("Unique identifier (ID) of the tag that you want to retrieve")
12 | },
13 | fn: async ({ boardId, tagId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!tagId) {
20 | return ServerResponse.error("Tag ID is required");
21 | }
22 |
23 | const result = await MiroClient.getApi().getTag(boardId, tagId);
24 | return ServerResponse.text(JSON.stringify(result, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default getTagTool;
```
--------------------------------------------------------------------------------
/src/tools/getMindmapNode.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getMindmapNodeTool: ToolSchema = {
7 | name: "get-mindmap-node",
8 | description: "Retrieve information about a specific mind map node on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board from which you want to retrieve a mind map node"),
11 | itemId: z.string().describe("Unique identifier (ID) of the mind map node that you want to retrieve")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | const response = await MiroClient.getApi().getMindmapNodeExperimental(boardId, itemId);
16 |
17 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
18 | } catch (error) {
19 | process.stderr.write(`Error retrieving Miro mind map node: ${error}\n`);
20 | return ServerResponse.error(error);
21 | }
22 | }
23 | };
24 |
25 | export default getMindmapNodeTool;
```
--------------------------------------------------------------------------------
/src/tools/getBoardClassification.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getBoardClassificationTool: ToolSchema = {
7 | name: "get-board-classification",
8 | description: "Retrieves board classification for a board (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("id of the organization"),
11 | teamId: z.string().describe("id of the team"),
12 | boardId: z.string().describe("Unique identifier of the board that you want to retrieve"),
13 | },
14 | fn: async ({ orgId, teamId, boardId }) => {
15 | try {
16 | const response = await MiroClient.getApi().enterpriseDataclassificationBoardGet(orgId, teamId, boardId);
17 |
18 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
19 | } catch (error) {
20 | process.stderr.write(`Error retrieving board classification: ${error}\n`);
21 | return ServerResponse.error(error);
22 | }
23 | }
24 | };
25 |
26 | export default getBoardClassificationTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteTag.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteTagTool: ToolSchema = {
7 | name: "delete-tag",
8 | description: "Delete a specific tag from a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the tag"),
11 | tagId: z.string().describe("Unique identifier (ID) of the tag that you want to delete")
12 | },
13 | fn: async ({ boardId, tagId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!tagId) {
20 | return ServerResponse.error("Tag ID is required");
21 | }
22 |
23 | await MiroClient.getApi().deleteTag(boardId, tagId);
24 | return ServerResponse.text(JSON.stringify({ success: true, message: "Tag deleted successfully" }, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default deleteTagTool;
```
--------------------------------------------------------------------------------
/src/tools/getEmbedItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getEmbedItemTool: ToolSchema = {
7 | name: "get-embed-item",
8 | description: "Retrieve information about a specific embed item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the embed"),
11 | itemId: z.string().describe("Unique identifier (ID) of the embed that you want to retrieve")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | const result = await MiroClient.getApi().getEmbedItem(boardId, itemId);
24 | return ServerResponse.text(JSON.stringify(result, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default getEmbedItemTool;
```
--------------------------------------------------------------------------------
/src/tools/getShapeItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getShapeItemTool: ToolSchema = {
7 | name: "get-shape-item",
8 | description: "Retrieve information about a specific shape item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the shape"),
11 | itemId: z.string().describe("Unique identifier (ID) of the shape that you want to retrieve")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | const result = await MiroClient.getApi().getShapeItem(boardId, itemId);
24 | return ServerResponse.text(JSON.stringify(result, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default getShapeItemTool;
```
--------------------------------------------------------------------------------
/src/tools/getItemTags.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getItemTagsTool: ToolSchema = {
7 | name: "get-item-tags",
8 | description: "Retrieve all tags attached to a specific item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the item"),
11 | itemId: z.string().describe("Unique identifier (ID) of the item whose tags you want to retrieve"),
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | const result = await MiroClient.getApi().getTagsFromItem(boardId, itemId);
24 | return ServerResponse.text(JSON.stringify(result, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default getItemTagsTool;
```
--------------------------------------------------------------------------------
/src/tools/getCardItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getCardItemTool: ToolSchema = {
7 | name: "get-card-item",
8 | description: "Retrieve information about a specific card item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the card"),
11 | itemId: z.string().describe("Unique identifier (ID) of the card that you want to retrieve")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | const itemData = await MiroClient.getApi().getCardItem(boardId, itemId);
24 |
25 | return ServerResponse.text(JSON.stringify(itemData, null, 2));
26 | } catch (error) {
27 | return ServerResponse.error(error);
28 | }
29 | }
30 | }
31 |
32 | export default getCardItemTool;
```
--------------------------------------------------------------------------------
/src/tools/removeBoardMember.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const removeBoardMemberTool: ToolSchema = {
7 | name: "remove-board-member",
8 | description: "Remove a specific member from a Miro board",
9 | args: {
10 | boardId: z.string().describe("ID of the board"),
11 | memberId: z.string().describe("ID of the board member to remove")
12 | },
13 | fn: async ({ boardId, memberId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!memberId) {
20 | return ServerResponse.error("Member ID is required");
21 | }
22 |
23 | const result = await MiroClient.getApi().removeBoardMember(boardId, memberId);
24 |
25 | return ServerResponse.text(JSON.stringify(result, null, 2));
26 | } catch (error) {
27 | process.stderr.write(`Error removing board member: ${error}\n`);
28 | return ServerResponse.error(error);
29 | }
30 | }
31 | }
32 |
33 | export default removeBoardMemberTool;
34 |
```
--------------------------------------------------------------------------------
/src/tools/deleteBoard.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteBoardTool: ToolSchema = {
7 | name: "delete-board",
8 | description: "Delete a Miro board by its ID. Deleted boards go to Trash (on paid plans) and can be restored via UI within 90 days after deletion.",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that you want to delete")
11 | },
12 | fn: async ({ boardId }) => {
13 | try {
14 | if (!boardId) {
15 | return ServerResponse.error("Board ID is required");
16 | }
17 |
18 | await MiroClient.getApi().deleteBoard(boardId);
19 |
20 | return ServerResponse.text(JSON.stringify({
21 | success: true,
22 | message: `Board ${boardId} has been successfully deleted.`
23 | }, null, 2));
24 | } catch (error) {
25 | process.stderr.write(`Error deleting Miro board: ${error}\n`);
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default deleteBoardTool;
```
--------------------------------------------------------------------------------
/src/tools/getTextItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getTextItemTool: ToolSchema = {
7 | name: "get-text-item",
8 | description: "Retrieve information about a specific text item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the text item"),
11 | itemId: z.string().describe("Unique identifier (ID) of the text item that you want to retrieve")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | const textData = await MiroClient.getApi().getTextItem(boardId, itemId);
24 | return ServerResponse.text(JSON.stringify(textData, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default getTextItemTool;
```
--------------------------------------------------------------------------------
/src/tools/getGroup.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getGroupTool: ToolSchema = {
7 | name: "get-group",
8 | description: "Retrieve information about a specific group on a Miro board",
9 | args: {
10 | boardId: z.string().describe("ID of the board that contains the group"),
11 | groupId: z.string().describe("ID of the group that you want to retrieve")
12 | },
13 | fn: async ({ boardId, groupId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!groupId) {
20 | return ServerResponse.error("Group ID is required");
21 | }
22 |
23 | const result = await MiroClient.getApi().getGroupById(boardId, groupId);
24 |
25 | return ServerResponse.text(JSON.stringify(result, null, 2));
26 | } catch (error) {
27 | process.stderr.write(`Error retrieving group: ${error}\n`);
28 | return ServerResponse.error(error);
29 | }
30 | }
31 | }
32 |
33 | export default getGroupTool;
```
--------------------------------------------------------------------------------
/src/tools/getSpecificItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getSpecificItemTool: ToolSchema = {
7 | name: "get-specific-item",
8 | description: "Retrieve information about a specific item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the item"),
11 | itemId: z.string().describe("Unique identifier (ID) of the item that you want to retrieve")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | const itemData = await MiroClient.getApi().getSpecificItem(boardId, itemId);
24 |
25 | return ServerResponse.text(JSON.stringify(itemData, null, 2));
26 | } catch (error) {
27 | return ServerResponse.error(error);
28 | }
29 | }
30 | }
31 |
32 | export default getSpecificItemTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteEmbedItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteEmbedItemTool: ToolSchema = {
7 | name: "delete-embed-item",
8 | description: "Delete a specific embed item from a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the embed"),
11 | itemId: z.string().describe("Unique identifier (ID) of the embed that you want to delete")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | await MiroClient.getApi().deleteEmbedItem(boardId, itemId);
24 | return ServerResponse.text(JSON.stringify({ success: true, message: "Embed deleted successfully" }, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default deleteEmbedItemTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteShapeItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteShapeItemTool: ToolSchema = {
7 | name: "delete-shape-item",
8 | description: "Delete a specific shape item from a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the shape"),
11 | itemId: z.string().describe("Unique identifier (ID) of the shape that you want to delete")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | await MiroClient.getApi().deleteShapeItem(boardId, itemId);
24 | return ServerResponse.text(JSON.stringify({ success: true, message: "Shape deleted successfully" }, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default deleteShapeItemTool;
```
--------------------------------------------------------------------------------
/src/tools/getAppCardItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getAppCardItemTool: ToolSchema = {
7 | name: "get-app-card-item",
8 | description: "Retrieve information about a specific app card item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the app card"),
11 | itemId: z.string().describe("Unique identifier (ID) of the app card that you want to retrieve")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | const itemData = await MiroClient.getApi().getAppCardItem(boardId, itemId);
24 |
25 | return ServerResponse.text(JSON.stringify(itemData, null, 2));
26 | } catch (error) {
27 | return ServerResponse.error(error);
28 | }
29 | }
30 | }
31 |
32 | export default getAppCardItemTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteTextItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteTextItemTool: ToolSchema = {
7 | name: "delete-text-item",
8 | description: "Delete a specific text item from a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the text item"),
11 | itemId: z.string().describe("Unique identifier (ID) of the text item that you want to delete")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | await MiroClient.getApi().deleteTextItem(boardId, itemId);
24 | return ServerResponse.text(JSON.stringify({ success: true, message: "Text item successfully deleted" }));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default deleteTextItemTool;
```
--------------------------------------------------------------------------------
/src/tools/getDocumentItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getDocumentItemTool: ToolSchema = {
7 | name: "get-document-item",
8 | description: "Retrieve information about a specific document item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the document"),
11 | itemId: z.string().describe("Unique identifier (ID) of the document that you want to retrieve")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | const documentData = await MiroClient.getApi().getDocumentItem(boardId, itemId);
24 | return ServerResponse.text(JSON.stringify(documentData, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default getDocumentItemTool;
```
--------------------------------------------------------------------------------
/src/tools/getImageItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getImageItemTool: ToolSchema = {
7 | name: "get-image-item",
8 | description: "Retrieve information about a specific image item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the image"),
11 | itemId: z.string().describe("Unique identifier (ID) of the image that you want to retrieve")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | // Use generic getItem for image item
24 | const result = await MiroClient.getApi().getImageItem(boardId, itemId);
25 | return ServerResponse.text(JSON.stringify(result, null, 2));
26 | } catch (error) {
27 | return ServerResponse.error(error);
28 | }
29 | }
30 | }
31 |
32 | export default getImageItemTool;
```
--------------------------------------------------------------------------------
/src/tools/getLegalHold.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getLegalHoldTool: ToolSchema = {
7 | name: "get-legal-hold",
8 | description: "Retrieves information about a specific legal hold (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("The ID of the organization for which you want to retrieve the legal hold information"),
11 | caseId: z.string().describe("The ID of the case for which you want to retrieve the legal hold information"),
12 | legalHoldId: z.string().describe("The ID of the legal hold you want to retrieve")
13 | },
14 | fn: async ({ orgId, caseId, legalHoldId }) => {
15 | try {
16 | const response = await MiroClient.getApi().getLegalHold(orgId, caseId, legalHoldId);
17 |
18 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
19 | } catch (error) {
20 | process.stderr.write(`Error retrieving legal hold: ${error}\n`);
21 | return ServerResponse.error(error);
22 | }
23 | }
24 | };
25 |
26 | export default getLegalHoldTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteDocumentItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteDocumentItemTool: ToolSchema = {
7 | name: "delete-document-item",
8 | description: "Delete a specific document item from a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the document"),
11 | itemId: z.string().describe("Unique identifier (ID) of the document that you want to delete")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | await MiroClient.getApi().deleteDocumentItem(boardId, itemId);
24 | return ServerResponse.text(JSON.stringify({ success: true, message: "Document item successfully deleted" }));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default deleteDocumentItemTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteImageItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteImageItemTool: ToolSchema = {
7 | name: "delete-image-item",
8 | description: "Delete a specific image item from a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the image"),
11 | itemId: z.string().describe("Unique identifier (ID) of the image that you want to delete")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | // Use generic deleteItem
24 | await MiroClient.getApi().deleteItem(boardId, itemId);
25 | return ServerResponse.text(JSON.stringify({ success: true, message: "Image deleted successfully" }, null, 2));
26 | } catch (error) {
27 | return ServerResponse.error(error);
28 | }
29 | }
30 | }
31 |
32 | export default deleteImageItemTool;
```
--------------------------------------------------------------------------------
/src/tools/getAllCases.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getAllCasesTool: ToolSchema = {
7 | name: "get-all-cases",
8 | description: "Retrieves the list of eDiscovery cases in an organization (Enterprise only)",
9 | args: {
10 | limit: z.number().describe("The maximum number of items in the result list"),
11 | orgId: z.string().describe("The ID of the organization for which you want to retrieve the list of cases"),
12 | cursor: z.string().optional().nullish().describe("Cursor for pagination")
13 | },
14 | fn: async ({ limit, orgId, cursor }) => {
15 | try {
16 | const query: any = {};
17 | if (cursor) query.cursor = cursor;
18 |
19 | const response = await MiroClient.getApi().getAllCases(limit, orgId, query);
20 |
21 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
22 | } catch (error) {
23 | process.stderr.write(`Error retrieving cases: ${error}\n`);
24 | return ServerResponse.error(error);
25 | }
26 | }
27 | };
28 |
29 | export default getAllCasesTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteItemTool: ToolSchema = {
7 | name: "delete-item",
8 | description: "Delete a specific item from a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the item"),
11 | itemId: z.string().describe("Unique identifier (ID) of the item that you want to delete")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | await MiroClient.getApi().deleteItem(boardId, itemId);
24 |
25 | return ServerResponse.text(JSON.stringify({
26 | success: true,
27 | message: `Item ${itemId} successfully deleted from board ${boardId}`
28 | }, null, 2));
29 | } catch (error) {
30 | return ServerResponse.error(error);
31 | }
32 | }
33 | }
34 |
35 | export default deleteItemTool;
```
--------------------------------------------------------------------------------
/src/tools/getItemsOnBoard.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getItemsOnBoardTool: ToolSchema = {
7 | name: "get-items-on-board",
8 | description: "Retrieve all items on a specific Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board whose items you want to retrieve"),
11 | limit: z.number().optional().nullish().describe("Maximum number of items to return (default: 50)"),
12 | offset: z.number().optional().nullish().describe("Offset for pagination (default: 0)")
13 | },
14 | fn: async ({ boardId, limit = 50, offset = 0 }) => {
15 | try {
16 | if (!boardId) {
17 | return ServerResponse.error("Board ID is required");
18 | }
19 |
20 | const itemsData = await MiroClient.getApi().getItems(boardId, {
21 | limit: limit.toString(),
22 | });
23 |
24 | return ServerResponse.text(JSON.stringify(itemsData, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default getItemsOnBoardTool;
```
--------------------------------------------------------------------------------
/src/tools/getStickyNoteItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getStickyNoteItemTool: ToolSchema = {
7 | name: "get-sticky-note-item",
8 | description: "Retrieve information about a specific sticky note item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the sticky note"),
11 | itemId: z.string().describe("Unique identifier (ID) of the sticky note that you want to retrieve")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | const stickyNoteData = await MiroClient.getApi().getStickyNoteItem(boardId, itemId);
24 | return ServerResponse.text(JSON.stringify(stickyNoteData, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default getStickyNoteItemTool;
```
--------------------------------------------------------------------------------
/src/tools/getSpecificBoardMember.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getSpecificBoardMemberTool: ToolSchema = {
7 | name: "get-specific-board-member",
8 | description: "Retrieve details of a specific member on a Miro board",
9 | args: {
10 | boardId: z.string().describe("ID of the board"),
11 | memberId: z.string().describe("ID of the specific board member to retrieve")
12 | },
13 | fn: async ({ boardId, memberId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!memberId) {
20 | return ServerResponse.error("Member ID is required");
21 | }
22 |
23 | const result = await MiroClient.getApi().getSpecificBoardMember(boardId, memberId);
24 |
25 | return ServerResponse.text(JSON.stringify(result, null, 2));
26 | } catch (error) {
27 | process.stderr.write(`Error retrieving specific board member: ${error}\n`);
28 | return ServerResponse.error(error);
29 | }
30 | }
31 | }
32 |
33 | export default getSpecificBoardMemberTool;
34 |
```
--------------------------------------------------------------------------------
/src/tools/getFrameItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getFrameItemTool: ToolSchema = {
7 | name: "get-frame-item",
8 | description: "Retrieve information for a specific frame on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the frame that you want to retrieve"),
11 | itemId: z.string().describe("Unique identifier (ID) of the frame that you want to retrieve")
12 | },
13 | fn: async ({ boardId, itemId }: {
14 | boardId: string,
15 | itemId: string
16 | }) => {
17 | try {
18 | if (!boardId) {
19 | return ServerResponse.error("Board ID is required");
20 | }
21 |
22 | if (!itemId) {
23 | return ServerResponse.error("Item ID is required");
24 | }
25 |
26 | const result = await MiroClient.getApi().getFrameItem(boardId, itemId);
27 | return ServerResponse.text(JSON.stringify(result, null, 2));
28 | } catch (error) {
29 | return ServerResponse.error(error);
30 | }
31 | }
32 | }
33 |
34 | export default getFrameItemTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteConnector.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteConnectorTool: ToolSchema = {
7 | name: "delete-connector",
8 | description: "Delete a specific connector from a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the connector"),
11 | connectorId: z.string().describe("Unique identifier (ID) of the connector that you want to delete")
12 | },
13 | fn: async ({ boardId, connectorId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!connectorId) {
20 | return ServerResponse.error("Connector ID is required");
21 | }
22 |
23 | await MiroClient.getApi().deleteConnector(boardId, connectorId);
24 | return ServerResponse.text(JSON.stringify({ success: true, message: "Connector deleted successfully" }, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default deleteConnectorTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteFrameItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteFrameItemTool: ToolSchema = {
7 | name: "delete-frame-item",
8 | description: "Delete a frame from a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board from which you want to delete the frame"),
11 | itemId: z.string().describe("Unique identifier (ID) of the frame that you want to delete")
12 | },
13 | fn: async ({ boardId, itemId }: {
14 | boardId: string,
15 | itemId: string
16 | }) => {
17 | try {
18 | if (!boardId) {
19 | return ServerResponse.error("Board ID is required");
20 | }
21 |
22 | if (!itemId) {
23 | return ServerResponse.error("Item ID is required");
24 | }
25 |
26 | await MiroClient.getApi().deleteFrameItem(boardId, itemId);
27 | return ServerResponse.text(JSON.stringify({ success: true, message: "Frame successfully deleted" }, null, 2));
28 | } catch (error) {
29 | return ServerResponse.error(error);
30 | }
31 | }
32 | }
33 |
34 | export default deleteFrameItemTool;
```
--------------------------------------------------------------------------------
/src/tools/getSpecificConnector.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getSpecificConnectorTool: ToolSchema = {
7 | name: "get-specific-connector",
8 | description: "Retrieve information about a specific connector on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the connector"),
11 | connectorId: z.string().describe("Unique identifier (ID) of the connector that you want to retrieve")
12 | },
13 | fn: async ({ boardId, connectorId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!connectorId) {
20 | return ServerResponse.error("Connector ID is required");
21 | }
22 |
23 | const connectorData = await MiroClient.getApi().getConnector(boardId, connectorId);
24 | return ServerResponse.text(JSON.stringify(connectorData, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default getSpecificConnectorTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteStickyNoteItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteStickyNoteItemTool: ToolSchema = {
7 | name: "delete-sticky-note-item",
8 | description: "Delete a specific sticky note item from a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the sticky note"),
11 | itemId: z.string().describe("Unique identifier (ID) of the sticky note that you want to delete")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | await MiroClient.getApi().deleteStickyNoteItem(boardId, itemId);
24 | return ServerResponse.text(JSON.stringify({ success: true, message: "Sticky note deleted successfully" }, null, 2));
25 | } catch (error) {
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | }
30 |
31 | export default deleteStickyNoteItemTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteCardItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteCardItemTool: ToolSchema = {
7 | name: "delete-card-item",
8 | description: "Delete a specific card item from a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the card"),
11 | itemId: z.string().describe("Unique identifier (ID) of the card that you want to delete")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | await MiroClient.getApi().deleteCardItem(boardId, itemId);
24 |
25 | return ServerResponse.text(JSON.stringify({
26 | success: true,
27 | message: `Card Item ${itemId} successfully deleted from board ${boardId}`
28 | }, null, 2));
29 | } catch (error) {
30 | return ServerResponse.error(error);
31 | }
32 | }
33 | }
34 |
35 | export default deleteCardItemTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteAppCardItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteAppCardItemTool: ToolSchema = {
7 | name: "delete-app-card-item",
8 | description: "Delete a specific app card item from a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the app card"),
11 | itemId: z.string().describe("Unique identifier (ID) of the app card that you want to delete")
12 | },
13 | fn: async ({ boardId, itemId }) => {
14 | try {
15 | if (!boardId) {
16 | return ServerResponse.error("Board ID is required");
17 | }
18 |
19 | if (!itemId) {
20 | return ServerResponse.error("Item ID is required");
21 | }
22 |
23 | await MiroClient.getApi().deleteAppCardItem(boardId, itemId);
24 |
25 | return ServerResponse.text(JSON.stringify({
26 | success: true,
27 | message: `App Card Item ${itemId} successfully deleted from board ${boardId}`
28 | }, null, 2));
29 | } catch (error) {
30 | return ServerResponse.error(error);
31 | }
32 | }
33 | }
34 |
35 | export default deleteAppCardItemTool;
```
--------------------------------------------------------------------------------
/src/tools/getAllGroups.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getAllGroupsTool: ToolSchema = {
7 | name: "get-all-groups",
8 | description: "Retrieve all groups on a Miro board",
9 | args: {
10 | boardId: z.string().describe("ID of the board whose groups you want to retrieve"),
11 | limit: z.number().optional().nullish().describe("Maximum number of groups to return (default: 50)"),
12 | cursor: z.string().optional().nullish().describe("Cursor for pagination")
13 | },
14 | fn: async ({ boardId, limit, cursor }) => {
15 | try {
16 | if (!boardId) {
17 | return ServerResponse.error("Board ID is required");
18 | }
19 |
20 | const options: any = {};
21 | if (limit) options.limit = limit;
22 | if (cursor) options.cursor = cursor;
23 |
24 | const result = await MiroClient.getApi().getAllGroups(boardId, options);
25 |
26 | return ServerResponse.text(JSON.stringify(result, null, 2));
27 | } catch (error) {
28 | process.stderr.write(`Error retrieving groups: ${error}\n`);
29 | return ServerResponse.error(error);
30 | }
31 | }
32 | }
33 |
34 | export default getAllGroupsTool;
```
--------------------------------------------------------------------------------
/src/tools/getAllBoardMembers.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getAllBoardMembersTool: ToolSchema = {
7 | name: "get-all-board-members",
8 | description: "Retrieve all members of a specific Miro board",
9 | args: {
10 | boardId: z.string().describe("ID of the board to retrieve members from"),
11 | limit: z.number().optional().nullish().describe("Maximum number of members to retrieve (default: 50)"),
12 | offset: z.number().optional().nullish().describe("Offset for pagination (default: 0)")
13 | },
14 | fn: async ({ boardId, limit = 50, offset = 0 }) => {
15 | try {
16 | if (!boardId) {
17 | return ServerResponse.error("Board ID is required");
18 | }
19 |
20 | const result = await MiroClient.getApi().getBoardMembers(boardId, {
21 | limit: limit.toString(),
22 | offset: offset.toString()
23 | });
24 |
25 | return ServerResponse.text(JSON.stringify(result, null, 2));
26 | } catch (error) {
27 | process.stderr.write(`Error retrieving board members: ${error}\n`);
28 | return ServerResponse.error(error);
29 | }
30 | }
31 | }
32 |
33 | export default getAllBoardMembersTool;
34 |
```
--------------------------------------------------------------------------------
/src/tools/createGroup.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const createGroupTool: ToolSchema = {
7 | name: "create-group",
8 | description: "Create a new group on a Miro board",
9 | args: {
10 | boardId: z.string().describe("ID of the board where the group will be created"),
11 | data: z.object({
12 | items: z.array(z.string()).describe("List of item IDs to include in the group")
13 | }).describe("Group data with item IDs to include in the group")
14 | },
15 | fn: async ({ boardId, data }) => {
16 | try {
17 | if (!boardId) {
18 | return ServerResponse.error("Board ID is required");
19 | }
20 |
21 | if (!data || !data.items || data.items.length === 0) {
22 | return ServerResponse.error("At least one item ID is required in the 'items' array");
23 | }
24 |
25 | const result = await MiroClient.getApi().createGroup(boardId, { data });
26 |
27 | return ServerResponse.text(JSON.stringify(result, null, 2));
28 | } catch (error) {
29 | process.stderr.write(`Error creating group: ${error}\n`);
30 | return ServerResponse.error(error);
31 | }
32 | }
33 | }
34 |
35 | export default createGroupTool;
```
--------------------------------------------------------------------------------
/src/tools/removeProjectMember.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const removeProjectMemberTool: ToolSchema = {
7 | name: "remove-project-member",
8 | description: "Removes a member from a project (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("The ID of the organization to which the project belongs"),
11 | teamId: z.string().describe("The ID of the team to which the project belongs"),
12 | projectId: z.string().describe("The ID of the project from which you want to remove a member"),
13 | memberId: z.string().describe("The ID of the member that you want to remove from a project")
14 | },
15 | fn: async ({ orgId, teamId, projectId, memberId }) => {
16 | try {
17 | const response = await MiroClient.getApi().enterpriseDeleteProjectMember(
18 | orgId,
19 | teamId,
20 | projectId,
21 | memberId
22 | );
23 |
24 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
25 | } catch (error) {
26 | process.stderr.write(`Error removing project member: ${error}\n`);
27 | return ServerResponse.error(error);
28 | }
29 | }
30 | };
31 |
32 | export default removeProjectMemberTool;
```
--------------------------------------------------------------------------------
/src/tools/shareBoard.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const shareBoardTool: ToolSchema = {
7 | name: "share-board",
8 | description: "Share a Miro board with specific access level and optional team assignment",
9 | args: {
10 | boardId: z.string().describe("ID of the board to share"),
11 | accessLevel: z.enum(['private', 'view', 'comment', 'edit']).describe("Access level for shared board"),
12 | teamId: z.string().optional().nullish().describe("Team ID to assign the board to"),
13 | },
14 | fn: async ({ boardId, accessLevel, teamId }) => {
15 | try {
16 | if (!boardId) {
17 | return ServerResponse.error("Board ID is required");
18 | }
19 |
20 | const boardChanges = {
21 | sharingPolicy: {
22 | access: accessLevel
23 | },
24 | teamId
25 | };
26 |
27 | const result = await MiroClient.getApi().updateBoard(boardId, boardChanges);
28 |
29 | return ServerResponse.text(JSON.stringify(result, null, 2));
30 | } catch (error) {
31 | process.stderr.write(`Error sharing Miro board: ${error}\n`);
32 | return ServerResponse.error(error);
33 | }
34 | }
35 | }
36 |
37 | export default shareBoardTool;
```
--------------------------------------------------------------------------------
/src/tools/getMindmapNodes.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getMindmapNodesTool: ToolSchema = {
7 | name: "get-mindmap-nodes",
8 | description: "Retrieve a list of mind map nodes on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board from which you want to retrieve mind map nodes"),
11 | limit: z.number().optional().nullish().describe("Maximum number of results to return (default: 50)"),
12 | cursor: z.string().optional().nullish().describe("Cursor for pagination")
13 | },
14 | fn: async ({ boardId, limit, cursor }) => {
15 | try {
16 | // Prepare query parameters
17 | const query: any = {};
18 | if (limit) query.limit = limit.toString();
19 | if (cursor) query.cursor = cursor;
20 |
21 | const response = await MiroClient.getApi().getMindmapNodesExperimental(boardId, query);
22 |
23 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
24 | } catch (error) {
25 | process.stderr.write(`Error retrieving Miro mind map nodes: ${error}\n`);
26 | return ServerResponse.error(error);
27 | }
28 | }
29 | };
30 |
31 | export default getMindmapNodesTool;
```
--------------------------------------------------------------------------------
/src/tools/getAllTags.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getAllTagsTool: ToolSchema = {
7 | name: "get-all-tags",
8 | description: "Retrieve all tags on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board for which you want to retrieve all tags"),
11 | limit: z.number().optional().nullish().describe("Maximum number of tags to return (default: 50)"),
12 | offset: z.number().optional().nullish().describe("Offset for pagination (default: 0)")
13 | },
14 | fn: async ({ boardId, limit, offset }) => {
15 | try {
16 | if (!boardId) {
17 | return ServerResponse.error("Board ID is required");
18 | }
19 |
20 | const query: Record<string, any> = {};
21 |
22 | if (limit !== undefined) {
23 | query.limit = limit;
24 | }
25 |
26 | if (offset !== undefined) {
27 | query.offset = offset;
28 | }
29 |
30 | const result = await MiroClient.getApi().getTagsFromBoard(boardId, query);
31 | return ServerResponse.text(JSON.stringify(result, null, 2));
32 | } catch (error) {
33 | return ServerResponse.error(error);
34 | }
35 | }
36 | }
37 |
38 | export default getAllTagsTool;
```
--------------------------------------------------------------------------------
/src/tools/getConnectors.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getConnectorsTool: ToolSchema = {
7 | name: "get-connectors",
8 | description: "Retrieve all connectors on a specific Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board whose connectors you want to retrieve"),
11 | limit: z.number().optional().nullish().describe("Maximum number of connectors to return (default: 50)"),
12 | cursor: z.string().optional().nullish().describe("Cursor for pagination")
13 | },
14 | fn: async ({ boardId, limit, cursor }) => {
15 | try {
16 | if (!boardId) {
17 | return ServerResponse.error("Board ID is required");
18 | }
19 |
20 | const queryParams: { limit?: string; cursor?: string } = {};
21 | if (limit) queryParams.limit = limit.toString();
22 | if (cursor) queryParams.cursor = cursor;
23 |
24 | const connectorsData = await MiroClient.getApi().getConnectors(boardId, queryParams);
25 | return ServerResponse.text(JSON.stringify(connectorsData, null, 2));
26 | } catch (error) {
27 | return ServerResponse.error(error);
28 | }
29 | }
30 | }
31 |
32 | export default getConnectorsTool;
```
--------------------------------------------------------------------------------
/src/tools/getAllLegalHolds.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getLegalHoldsTool: ToolSchema = {
7 | name: "get-all-legal-holds",
8 | description: "Retrieves the list of all legal holds within a case (Enterprise only)",
9 | args: {
10 | limit: z.number().describe("The maximum number of items in the result list"),
11 | orgId: z.string().describe("The ID of the organization for which you want to retrieve the list of legal holds"),
12 | caseId: z.string().describe("The ID of the case for which you want to retrieve the list of legal holds"),
13 | cursor: z.string().optional().nullish().describe("Cursor for pagination")
14 | },
15 | fn: async ({ limit, orgId, caseId, cursor }) => {
16 | try {
17 | const query: any = {};
18 | if (cursor) query.cursor = cursor;
19 |
20 | const response = await MiroClient.getApi().getAllLegalHolds(limit, orgId, caseId, query);
21 |
22 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
23 | } catch (error) {
24 | process.stderr.write(`Error retrieving legal holds: ${error}\n`);
25 | return ServerResponse.error(error);
26 | }
27 | }
28 | };
29 |
30 | export default getLegalHoldsTool;
```
--------------------------------------------------------------------------------
/src/tools/attachTag.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const attachTagTool: ToolSchema = {
7 | name: "attach-tag",
8 | description: "Attach a tag to an item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the tag and item"),
11 | tagId: z.string().describe("Unique identifier (ID) of the tag that you want to attach"),
12 | itemId: z.string().describe("Unique identifier (ID) of the item to which you want to attach the tag")
13 | },
14 | fn: async ({ boardId, tagId, itemId }) => {
15 | try {
16 | if (!boardId) {
17 | return ServerResponse.error("Board ID is required");
18 | }
19 |
20 | if (!tagId) {
21 | return ServerResponse.error("Tag ID is required");
22 | }
23 |
24 | if (!itemId) {
25 | return ServerResponse.error("Item ID is required");
26 | }
27 |
28 | await MiroClient.getApi().attachTagToItem(boardId, itemId, tagId);
29 | return ServerResponse.text(JSON.stringify({ success: true, message: "Tag attached successfully" }, null, 2));
30 | } catch (error) {
31 | return ServerResponse.error(error);
32 | }
33 | }
34 | }
35 |
36 | export default attachTagTool;
```
--------------------------------------------------------------------------------
/src/tools/getProjectMember.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getProjectMemberTool: ToolSchema = {
7 | name: "get-project-member",
8 | description: "Retrieves information about a specific project member (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("The ID of the organization to which the project belongs"),
11 | teamId: z.string().describe("The ID of the team to which the project belongs"),
12 | projectId: z.string().describe("The ID of the project from which you want to retrieve specific member information"),
13 | memberId: z.string().describe("The ID of the member for which you want to retrieve information")
14 | },
15 | fn: async ({ orgId, teamId, projectId, memberId }) => {
16 | try {
17 | const response = await MiroClient.getApi().enterpriseGetProjectMember(
18 | orgId,
19 | teamId,
20 | projectId,
21 | memberId
22 | );
23 |
24 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
25 | } catch (error) {
26 | process.stderr.write(`Error retrieving project member: ${error}\n`);
27 | return ServerResponse.error(error);
28 | }
29 | }
30 | };
31 |
32 | export default getProjectMemberTool;
```
--------------------------------------------------------------------------------
/src/tools/deleteGroup.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const deleteGroupTool: ToolSchema = {
7 | name: "delete-group",
8 | description: "Delete a specific group from a Miro board",
9 | args: {
10 | boardId: z.string().describe("ID of the board that contains the group"),
11 | groupId: z.string().describe("ID of the group that you want to delete"),
12 | deleteItems: z.boolean().optional().nullish().describe("Indicates whether the items should be removed. Set to true to delete items in the group, false to keep them")
13 | },
14 | fn: async ({ boardId, groupId, deleteItems }) => {
15 | try {
16 | if (!boardId) {
17 | return ServerResponse.error("Board ID is required");
18 | }
19 |
20 | if (!groupId) {
21 | return ServerResponse.error("Group ID is required");
22 | }
23 |
24 | await MiroClient.getApi().deleteGroup(boardId, groupId, deleteItems ?? false);
25 |
26 | return ServerResponse.text(JSON.stringify({ success: true, message: "Group successfully deleted" }, null, 2));
27 | } catch (error) {
28 | process.stderr.write(`Error deleting group: ${error}\n`);
29 | return ServerResponse.error(error);
30 | }
31 | }
32 | }
33 |
34 | export default deleteGroupTool;
```
--------------------------------------------------------------------------------
/src/tools/updateBoardClassification.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const updateBoardClassificationTool: ToolSchema = {
7 | name: "update-board-classification",
8 | description: "Updates board classification for an existing board (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("id of the organization"),
11 | teamId: z.string().describe("id of the team"),
12 | boardId: z.string().describe("Unique identifier of the board that you want to update"),
13 | labelId: z.string().describe("Unique identifier of the classification label to apply")
14 | },
15 | fn: async ({ orgId, teamId, boardId, labelId }) => {
16 | try {
17 | const dataClassificationLabelId = {
18 | labelId: labelId
19 | };
20 |
21 | const response = await MiroClient.getApi().enterpriseDataclassificationBoardSet(
22 | orgId,
23 | teamId,
24 | boardId,
25 | dataClassificationLabelId
26 | );
27 |
28 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
29 | } catch (error) {
30 | process.stderr.write(`Error updating board classification: ${error}\n`);
31 | return ServerResponse.error(error);
32 | }
33 | }
34 | };
35 |
36 | export default updateBoardClassificationTool;
```
--------------------------------------------------------------------------------
/src/tools/createBoardExportJob.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const createBoardExportJobTool: ToolSchema = {
7 | name: "create-board-export-job",
8 | description: "Creates an export job for one or more boards (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("Unique identifier of the organization"),
11 | requestId: z.string().describe("Unique identifier of the board export job"),
12 | boardIds: z.array(z.string()).describe("Array of board IDs to export"),
13 | format: z.enum(["pdf", "csv"]).optional().nullish().describe("Export format (default: pdf)")
14 | },
15 | fn: async ({ orgId, requestId, boardIds, format }) => {
16 | try {
17 | const createBoardExportRequest = {
18 | boardIds: boardIds,
19 | ...(format && { format: format })
20 | };
21 |
22 | const response = await MiroClient.getApi().enterpriseCreateBoardExport(
23 | orgId,
24 | requestId,
25 | createBoardExportRequest
26 | );
27 |
28 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
29 | } catch (error) {
30 | process.stderr.write(`Error creating board export job: ${error}\n`);
31 | return ServerResponse.error(error);
32 | }
33 | }
34 | };
35 |
36 | export default createBoardExportJobTool;
```
--------------------------------------------------------------------------------
/src/tools/detachTag.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const detachTagTool: ToolSchema = {
7 | name: "detach-tag",
8 | description: "Detach a tag from an item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the tag and item"),
11 | tagId: z.string().describe("Unique identifier (ID) of the tag that you want to detach"),
12 | itemId: z.string().describe("Unique identifier (ID) of the item from which you want to detach the tag")
13 | },
14 | fn: async ({ boardId, tagId, itemId }) => {
15 | try {
16 | if (!boardId) {
17 | return ServerResponse.error("Board ID is required");
18 | }
19 |
20 | if (!tagId) {
21 | return ServerResponse.error("Tag ID is required");
22 | }
23 |
24 | if (!itemId) {
25 | return ServerResponse.error("Item ID is required");
26 | }
27 |
28 | // Use the SDK method to detach a tag from an item
29 | await MiroClient.getApi().removeTagFromItem(boardId, itemId, tagId);
30 | return ServerResponse.text(JSON.stringify({ success: true, message: "Tag detached successfully" }, null, 2));
31 | } catch (error) {
32 | return ServerResponse.error(error);
33 | }
34 | }
35 | }
36 |
37 | export default detachTagTool;
```
--------------------------------------------------------------------------------
/src/tools/ungroupItems.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const ungroupItemsTool: ToolSchema = {
7 | name: "ungroup-items",
8 | description: "Ungroup a specific group on a Miro board",
9 | args: {
10 | boardId: z.string().describe("ID of the board that contains the group"),
11 | groupId: z.string().describe("ID of the group that you want to ungroup"),
12 | deleteItems: z.boolean().optional().nullish().describe("Indicates whether the items should be removed. By default, false.")
13 | },
14 | fn: async ({ boardId, groupId, deleteItems }) => {
15 | try {
16 | if (!boardId) {
17 | return ServerResponse.error("Board ID is required");
18 | }
19 |
20 | if (!groupId) {
21 | return ServerResponse.error("Group ID is required");
22 | }
23 |
24 | const options: any = {};
25 | if (deleteItems !== undefined) options.deleteItems = deleteItems;
26 |
27 | await MiroClient.getApi().unGroup(boardId, groupId, options);
28 |
29 | return ServerResponse.text(JSON.stringify({ success: true, message: "Group successfully ungrouped" }, null, 2));
30 | } catch (error) {
31 | process.stderr.write(`Error ungrouping items: ${error}\n`);
32 | return ServerResponse.error(error);
33 | }
34 | }
35 | }
36 |
37 | export default ungroupItemsTool;
```
--------------------------------------------------------------------------------
/src/tools/createTag.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { TagCreateRequest } from '@mirohq/miro-api/dist/model/tagCreateRequest.js';
7 |
8 | const createTagTool: ToolSchema = {
9 | name: "create-tag",
10 | description: "Create a new tag on a Miro board",
11 | args: {
12 | boardId: z.string().describe("Unique identifier (ID) of the board where the tag will be created"),
13 | data: z.object({
14 | title: z.string().describe("Title of the tag")
15 | }).describe("The content and configuration of the tag"),
16 | fillColor: z.string().optional().nullish().describe("Fill color of the tag (hex format, e.g. #000000)")
17 | },
18 | fn: async ({ boardId, data, fillColor }) => {
19 | try {
20 | if (!boardId) {
21 | return ServerResponse.error("Board ID is required");
22 | }
23 |
24 | const createRequest = new TagCreateRequest();
25 | createRequest.title = data.title;
26 |
27 | if (fillColor) {
28 | createRequest.fillColor = fillColor;
29 | }
30 |
31 | const result = await MiroClient.getApi().createTag(boardId, createRequest);
32 | return ServerResponse.text(JSON.stringify(result, null, 2));
33 | } catch (error) {
34 | return ServerResponse.error(error);
35 | }
36 | }
37 | }
38 |
39 | export default createTagTool;
```
--------------------------------------------------------------------------------
/src/tools/addProjectMember.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const addProjectMemberTool: ToolSchema = {
7 | name: "add-project-member",
8 | description: "Adds a member to a project (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("The ID of the organization to which the project belongs"),
11 | teamId: z.string().describe("The ID of the team to which the project belongs"),
12 | projectId: z.string().describe("The ID of the project to which you want to add a user"),
13 | email: z.string().describe("Email ID of the user to add to the project"),
14 | role: z.enum(["owner", "editor", "commenter", "viewer"]).describe("Role to assign to the user")
15 | },
16 | fn: async ({ orgId, teamId, projectId, email, role }) => {
17 | try {
18 | const addProjectMemberRequest = {
19 | email,
20 | role
21 | };
22 |
23 | const response = await MiroClient.getApi().enterpriseAddProjectMember(
24 | orgId,
25 | teamId,
26 | projectId,
27 | addProjectMemberRequest
28 | );
29 |
30 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
31 | } catch (error) {
32 | process.stderr.write(`Error adding project member: ${error}\n`);
33 | return ServerResponse.error(error);
34 | }
35 | }
36 | };
37 |
38 | export default addProjectMemberTool;
```
--------------------------------------------------------------------------------
/src/tools/createBoard.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const createBoardTool: ToolSchema = {
7 | name: "create-board",
8 | description: "Create a new Miro board with specified name and sharing policies",
9 | args: {
10 | name: z.string().describe("Name of the board to create"),
11 | description: z.string().optional().nullish().describe("Description of the board"),
12 | sharingPolicy: z.enum(['private', 'view', 'comment', 'edit']).optional().nullish().describe("Sharing policy for the board"),
13 | teamId: z.string().optional().nullish().describe("Team ID to assign the board to")
14 | },
15 | fn: async ({ name, description, sharingPolicy, teamId }) => {
16 | try {
17 | if (!name) {
18 | return ServerResponse.error("Board name is required");
19 | }
20 |
21 | const boardChanges = {
22 | name,
23 | description,
24 | sharingPolicy: {
25 | access: sharingPolicy || 'private'
26 | },
27 | teamId
28 | };
29 |
30 | const boardData = await MiroClient.getApi().createBoard(boardChanges);
31 |
32 | return ServerResponse.text(JSON.stringify(boardData, null, 2));
33 | } catch (error) {
34 | process.stderr.write(`Error creating Miro board: ${error}\n`);
35 | return ServerResponse.error(error);
36 | }
37 | }
38 | }
39 |
40 | export default createBoardTool;
```
--------------------------------------------------------------------------------
/src/tools/getGroupItems.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getGroupItemsTool: ToolSchema = {
7 | name: "get-group-items",
8 | description: "Retrieve all items in a specific group on a Miro board",
9 | args: {
10 | boardId: z.string().describe("ID of the board that contains the group"),
11 | groupId: z.string().describe("ID of the group whose items you want to retrieve"),
12 | limit: z.number().optional().nullish().describe("Maximum number of items to return (default: 50)"),
13 | cursor: z.string().optional().nullish().describe("Cursor for pagination")
14 | },
15 | fn: async ({ boardId, groupId, limit, cursor }) => {
16 | try {
17 | if (!boardId) {
18 | return ServerResponse.error("Board ID is required");
19 | }
20 |
21 | if (!groupId) {
22 | return ServerResponse.error("Group ID is required");
23 | }
24 |
25 | const options: any = {};
26 | if (limit) options.limit = limit;
27 | if (cursor) options.cursor = cursor;
28 |
29 | const result = await MiroClient.getApi().getItemsByGroupId(boardId, groupId, options);
30 |
31 | return ServerResponse.text(JSON.stringify(result, null, 2));
32 | } catch (error) {
33 | process.stderr.write(`Error retrieving group items: ${error}\n`);
34 | return ServerResponse.error(error);
35 | }
36 | }
37 | }
38 |
39 | export default getGroupItemsTool;
```
--------------------------------------------------------------------------------
/src/tools/updateGroup.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const updateGroupTool: ToolSchema = {
7 | name: "update-group",
8 | description: "Update a specific group on a Miro board with new items",
9 | args: {
10 | boardId: z.string().describe("ID of the board that contains the group"),
11 | groupId: z.string().describe("ID of the group that you want to update"),
12 | data: z.object({
13 | items: z.array(z.string()).describe("Updated list of item IDs to include in the group")
14 | }).describe("Updated group data with item IDs to include in the group")
15 | },
16 | fn: async ({ boardId, groupId, data }) => {
17 | try {
18 | if (!boardId) {
19 | return ServerResponse.error("Board ID is required");
20 | }
21 |
22 | if (!groupId) {
23 | return ServerResponse.error("Group ID is required");
24 | }
25 |
26 | if (!data || !data.items || data.items.length === 0) {
27 | return ServerResponse.error("At least one item ID is required in the 'items' array");
28 | }
29 |
30 | const result = await MiroClient.getApi().updateGroup(boardId, groupId, { data });
31 |
32 | return ServerResponse.text(JSON.stringify(result, null, 2));
33 | } catch (error) {
34 | process.stderr.write(`Error updating group: ${error}\n`);
35 | return ServerResponse.error(error);
36 | }
37 | }
38 | }
39 |
40 | export default updateGroupTool;
```
--------------------------------------------------------------------------------
/src/tools/getAuditLogs.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getAuditLogsTool: ToolSchema = {
7 | name: "get-audit-logs",
8 | description: "Retrieves a page of audit events from the last 90 days (Enterprise only)",
9 | args: {
10 | createdAfter: z.string().describe("Retrieve audit logs created after this date (ISO 8601 format)"),
11 | createdBefore: z.string().describe("Retrieve audit logs created before this date (ISO 8601 format)"),
12 | cursor: z.string().optional().nullish().describe("Cursor for pagination"),
13 | limit: z.number().optional().nullish().describe("Maximum number of results to return (default: 100)"),
14 | sorting: z.enum(["ASC", "DESC"]).optional().nullish().describe("Sort order for results (default: ASC)")
15 | },
16 | fn: async ({ createdAfter, createdBefore, cursor, limit, sorting }) => {
17 | try {
18 | const query: any = {};
19 | if (cursor) query.cursor = cursor;
20 | if (limit) query.limit = limit;
21 | if (sorting) query.sorting = sorting;
22 |
23 | const response = await MiroClient.getApi().enterpriseGetAuditLogs(
24 | createdAfter,
25 | createdBefore,
26 | query
27 | );
28 |
29 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
30 | } catch (error) {
31 | process.stderr.write(`Error retrieving audit logs: ${error}\n`);
32 | return ServerResponse.error(error);
33 | }
34 | }
35 | };
36 |
37 | export default getAuditLogsTool;
```
--------------------------------------------------------------------------------
/src/tools/getLegalHoldContentItems.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getLegalHoldContentItemsTool: ToolSchema = {
7 | name: "get-legal-hold-content-items",
8 | description: "Retrieves the list of content items under legal hold (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("The ID of the organization for which you want to retrieve the list of content items under hold"),
11 | caseId: z.string().describe("The ID of the case for which you want to retrieve the list of content items under hold"),
12 | legalHoldId: z.string().describe("The ID of the legal hold for which you want to retrieve the list of content items under hold"),
13 | limit: z.number().describe("The maximum number of items in the result list"),
14 | cursor: z.string().optional().nullish().describe("Cursor for pagination")
15 | },
16 | fn: async ({ orgId, caseId, legalHoldId, limit, cursor }) => {
17 | try {
18 | const query: any = {};
19 | if (cursor) query.cursor = cursor;
20 |
21 | const response = await MiroClient.getApi().getLegalHoldContentItems(
22 | orgId,
23 | caseId,
24 | legalHoldId,
25 | limit,
26 | query
27 | );
28 |
29 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
30 | } catch (error) {
31 | process.stderr.write(`Error retrieving legal hold content items: ${error}\n`);
32 | return ServerResponse.error(error);
33 | }
34 | }
35 | };
36 |
37 | export default getLegalHoldContentItemsTool;
```
--------------------------------------------------------------------------------
/src/tools/updateTag.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { TagUpdateRequest } from '@mirohq/miro-api/dist/model/tagUpdateRequest.js';
7 |
8 | const updateTagTool: ToolSchema = {
9 | name: "update-tag",
10 | description: "Update an existing tag on a Miro board",
11 | args: {
12 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the tag"),
13 | tagId: z.string().describe("Unique identifier (ID) of the tag that you want to update"),
14 | title: z.string().optional().nullish().describe("Updated title of the tag"),
15 | fillColor: z.string().optional().nullish().describe("Updated fill color of the tag (hex format, e.g. #000000)")
16 | },
17 | fn: async ({ boardId, tagId, title, fillColor }) => {
18 | try {
19 | if (!boardId) {
20 | return ServerResponse.error("Board ID is required");
21 | }
22 |
23 | if (!tagId) {
24 | return ServerResponse.error("Tag ID is required");
25 | }
26 |
27 | const updateRequest = new TagUpdateRequest();
28 |
29 | if (title !== undefined) {
30 | updateRequest.title = title;
31 | }
32 |
33 | if (fillColor !== undefined) {
34 | updateRequest.fillColor = fillColor;
35 | }
36 |
37 | const result = await MiroClient.getApi().updateTag(boardId, tagId, updateRequest);
38 | return ServerResponse.text(JSON.stringify(result, null, 2));
39 | } catch (error) {
40 | return ServerResponse.error(error);
41 | }
42 | }
43 | }
44 |
45 | export default updateTagTool;
```
--------------------------------------------------------------------------------
/src/tools/updateBoardMember.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const updateBoardMemberTool: ToolSchema = {
7 | name: "update-board-member",
8 | description: "Update a specific member's role or status on a Miro board",
9 | args: {
10 | boardId: z.string().describe("ID of the board"),
11 | memberId: z.string().describe("ID of the board member to update"),
12 | role: z.enum(['member', 'admin', 'owner']).optional().nullish().describe("New role for the board member"),
13 | status: z.enum(['active', 'pending', 'blocked']).optional().nullish().describe("New status for the board member")
14 | },
15 | fn: async ({ boardId, memberId, role, status }) => {
16 | try {
17 | if (!boardId) {
18 | return ServerResponse.error("Board ID is required");
19 | }
20 |
21 | if (!memberId) {
22 | return ServerResponse.error("Member ID is required");
23 | }
24 |
25 | if (!role && !status) {
26 | return ServerResponse.error("At least one of role or status must be provided");
27 | }
28 |
29 | const memberChanges: any = {};
30 | if (role) memberChanges.role = role;
31 | if (status) memberChanges.status = status;
32 |
33 | const result = await MiroClient.getApi().updateBoardMember(boardId, memberId, memberChanges);
34 |
35 | return ServerResponse.text(JSON.stringify(result, null, 2));
36 | } catch (error) {
37 | process.stderr.write(`Error updating board member: ${error}\n`);
38 | return ServerResponse.error(error);
39 | }
40 | }
41 | }
42 |
43 | export default updateBoardMemberTool;
44 |
```
--------------------------------------------------------------------------------
/src/tools/updateBoard.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const updateBoardTool: ToolSchema = {
7 | name: "update-board",
8 | description: "Update an existing Miro board with new settings",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that you want to update"),
11 | name: z.string().optional().nullish().describe("New name for the board"),
12 | description: z.string().optional().nullish().describe("New description for the board"),
13 | sharingPolicy: z.enum(['private', 'view', 'comment', 'edit']).optional().nullish().describe("New sharing policy for the board"),
14 | teamId: z.string().optional().nullish().describe("New team ID to assign the board to")
15 | },
16 | fn: async ({ boardId, name, description, sharingPolicy, teamId }) => {
17 | try {
18 | if (!boardId) {
19 | return ServerResponse.error("Board ID is required");
20 | }
21 |
22 | const boardChanges = {};
23 | if (name) boardChanges['name'] = name;
24 | if (description !== undefined) boardChanges['description'] = description;
25 | if (sharingPolicy) boardChanges['sharingPolicy'] = { access: sharingPolicy };
26 | if (teamId) boardChanges['teamId'] = teamId;
27 |
28 | const boardData = await MiroClient.getApi().updateBoard(boardId, boardChanges);
29 |
30 | return ServerResponse.text(JSON.stringify(boardData, null, 2));
31 | } catch (error) {
32 | process.stderr.write(`Error updating Miro board: ${error}\n`);
33 | return ServerResponse.error(error);
34 | }
35 | }
36 | }
37 |
38 | export default updateBoardTool;
```
--------------------------------------------------------------------------------
/src/tools/copyBoard.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const copyBoardTool: ToolSchema = {
7 | name: "copy-board",
8 | description: "Create a copy of an existing Miro board with optional new settings",
9 | args: {
10 | copyFrom: z.string().describe("Unique identifier (ID) of the board that you want to copy"),
11 | name: z.string().optional().nullish().describe("Name for the new copied board"),
12 | description: z.string().optional().nullish().describe("Description for the new copied board"),
13 | sharingPolicy: z.enum(['private', 'view', 'comment', 'edit']).optional().nullish().describe("Sharing policy for the new copied board"),
14 | teamId: z.string().optional().nullish().describe("Team ID to assign the new copied board to")
15 | },
16 | fn: async ({ copyFrom, name, description, sharingPolicy, teamId }) => {
17 | try {
18 | if (!copyFrom) {
19 | return ServerResponse.error("Source board ID is required");
20 | }
21 |
22 | const copyBoardChanges = {};
23 | if (name) copyBoardChanges['name'] = name;
24 | if (description !== undefined) copyBoardChanges['description'] = description;
25 | if (sharingPolicy) copyBoardChanges['sharingPolicy'] = { access: sharingPolicy };
26 | if (teamId) copyBoardChanges['teamId'] = teamId;
27 |
28 | const boardData = await MiroClient.getApi().copyBoard(copyFrom, copyBoardChanges);
29 |
30 | return ServerResponse.text(JSON.stringify(boardData, null, 2));
31 | } catch (error) {
32 | process.stderr.write(`Error copying Miro board: ${error}\n`);
33 | return ServerResponse.error(error);
34 | }
35 | }
36 | }
37 |
38 | export default copyBoardTool;
```
--------------------------------------------------------------------------------
/src/tools/updateItemPosition.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const updateItemPositionTool: ToolSchema = {
7 | name: "update-item-position",
8 | description: "Update the position or parent of a specific item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the item"),
11 | itemId: z.string().describe("Unique identifier (ID) of the item that you want to update"),
12 | position: z.object({
13 | x: z.number().optional().nullish().describe("X coordinate of the item"),
14 | y: z.number().optional().nullish().describe("Y coordinate of the item")
15 | }).optional().nullish().describe("New position coordinates for the item"),
16 | parentId: z.string().optional().nullish().describe("Unique identifier (ID) of the new parent item")
17 | },
18 | fn: async ({ boardId, itemId, position, parentId }) => {
19 | try {
20 | if (!boardId) {
21 | return ServerResponse.error("Board ID is required");
22 | }
23 |
24 | if (!itemId) {
25 | return ServerResponse.error("Item ID is required");
26 | }
27 |
28 | const updateData = {};
29 |
30 | if (position) {
31 | updateData['position'] = position;
32 | }
33 |
34 | if (parentId) {
35 | updateData['parent'] = { id: parentId };
36 | }
37 |
38 | if (Object.keys(updateData).length === 0) {
39 | return ServerResponse.error("At least one update parameter (position or parentId) is required");
40 | }
41 |
42 | const updatedItem = await MiroClient.getApi().updateItemPositionOrParent(boardId, itemId, updateData);
43 |
44 | return ServerResponse.text(JSON.stringify(updatedItem, null, 2));
45 | } catch (error) {
46 | return ServerResponse.error(error);
47 | }
48 | }
49 | }
50 |
51 | export default updateItemPositionTool;
```
--------------------------------------------------------------------------------
/src/tools/getOrganizationMembers.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getOrganizationMembersTool: ToolSchema = {
7 | name: "get-organization-members",
8 | description: "Retrieves a list of members for an organization (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("id of the organization"),
11 | emails: z.string().optional().nullish().describe("Filter by comma-separated email addresses"),
12 | role: z.enum(['organization_internal_admin', 'organization_internal_user', 'organization_external_user', 'organization_team_guest_user', 'unknown']).optional().nullish().describe("Filter by user role"),
13 | license: z.enum(['full', 'occasional', 'free', 'free_restricted', 'full_trial', 'unknown']).optional().nullish().describe("Filter by license type"),
14 | active: z.boolean().optional().nullish().describe("Filter by active status"),
15 | cursor: z.string().optional().nullish().describe("Cursor for pagination"),
16 | limit: z.number().optional().nullish().describe("Maximum number of results to return")
17 | },
18 | fn: async ({ orgId, emails, role, license, active, cursor, limit }) => {
19 | try {
20 | const query: any = {};
21 | if (emails) query.emails = emails;
22 | if (role) query.role = role;
23 | if (license) query.license = license;
24 | if (active !== undefined) query.active = active;
25 | if (cursor) query.cursor = cursor;
26 | if (limit) query.limit = limit;
27 |
28 | const response = await MiroClient.getApi().enterpriseGetOrganizationMembers(orgId, query);
29 |
30 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
31 | } catch (error) {
32 | process.stderr.write(`Error retrieving organization members: ${error}\n`);
33 | return ServerResponse.error(error);
34 | }
35 | }
36 | };
37 |
38 | export default getOrganizationMembersTool;
```
--------------------------------------------------------------------------------
/src/tools/getBoardContentLogs.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const getBoardContentLogsTool: ToolSchema = {
7 | name: "get-board-content-logs",
8 | description: "Retrieves content change logs of board items (Enterprise only)",
9 | args: {
10 | orgId: z.string().describe("Unique identifier of the organization"),
11 | from: z.string().describe("Start date for filtering (ISO 8601 format)"),
12 | to: z.string().describe("End date for filtering (ISO 8601 format)"),
13 | boardIds: z.array(z.string()).optional().nullish().describe("List of board IDs to filter by"),
14 | emails: z.array(z.string()).optional().nullish().describe("List of user emails to filter by"),
15 | cursor: z.string().optional().nullish().describe("Cursor for pagination"),
16 | limit: z.number().optional().nullish().describe("Maximum number of results to return"),
17 | sorting: z.enum(["asc", "desc"]).optional().nullish().describe("Sort order for results")
18 | },
19 | fn: async ({ orgId, from, to, boardIds, emails, cursor, limit, sorting }) => {
20 | try {
21 | const query: any = {};
22 | if (boardIds) query.boardIds = boardIds;
23 | if (emails) query.emails = emails;
24 | if (cursor) query.cursor = cursor;
25 | if (limit) query.limit = limit;
26 | if (sorting) query.sorting = sorting;
27 |
28 | // Convert string dates to Date objects
29 | const fromDate = new Date(from);
30 | const toDate = new Date(to);
31 |
32 | const response = await MiroClient.getApi().enterpriseBoardContentItemLogsFetch(
33 | orgId,
34 | fromDate,
35 | toDate,
36 | query
37 | );
38 |
39 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
40 | } catch (error) {
41 | process.stderr.write(`Error retrieving board content logs: ${error}\n`);
42 | return ServerResponse.error(error);
43 | }
44 | }
45 | };
46 |
47 | export default getBoardContentLogsTool;
```
--------------------------------------------------------------------------------
/src/tools/createMindmapNode.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const createMindmapNodeTool: ToolSchema = {
7 | name: "create-mindmap-node",
8 | description: "Create a new mind map node on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board where you want to create the node"),
11 | data: z.object({
12 | content: z.string().describe("Text content for the mind map node"),
13 | parentId: z.string().optional().nullish().describe("ID of the parent node (if this is a child node)"),
14 | style: z.object({
15 | fillColor: z.string().optional().nullish().describe("Fill color for the node"),
16 | textColor: z.string().optional().nullish().describe("Text color for the node")
17 | }).optional().nullish()
18 | }).describe("The content and style configuration of the mind map node"),
19 | position: z.object({
20 | x: z.number().describe("X coordinate of the node"),
21 | y: z.number().describe("Y coordinate of the node")
22 | }).describe("Position of the node on the board")
23 | },
24 | fn: async ({ boardId, data, position }) => {
25 | try {
26 | // Prepare the request data
27 | const mindmapCreateRequest = {
28 | data: {
29 | nodeView: {
30 | data: {
31 | type: "text",
32 | content: data.content
33 | }
34 | },
35 | ...(data.parentId && { parentId: data.parentId }),
36 | ...(data.style && { style: data.style })
37 | },
38 | position
39 | };
40 |
41 | // Call the Miro API to create a mind map node
42 | const response = await MiroClient.getApi().createMindmapNodesExperimental(boardId, mindmapCreateRequest);
43 |
44 | return ServerResponse.text(JSON.stringify(response.body, null, 2));
45 | } catch (error) {
46 | process.stderr.write(`Error creating Miro mind map node: ${error}\n`);
47 | return ServerResponse.error(error);
48 | }
49 | }
50 | };
51 |
52 | export default createMindmapNodeTool;
```
--------------------------------------------------------------------------------
/src/tools/createConnector.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { ConnectorCreationData } from '@mirohq/miro-api/dist/model/connectorCreationData.js';
7 |
8 | const createConnectorTool: ToolSchema = {
9 | name: "create-connector",
10 | description: "Create a new connector between items on a Miro board",
11 | args: {
12 | boardId: z.string().describe("Unique identifier (ID) of the board where the connector will be created"),
13 | startItem: z.object({
14 | id: z.string().describe("ID of the item at the start of the connector")
15 | }).describe("Start item of the connector"),
16 | endItem: z.object({
17 | id: z.string().describe("ID of the item at the end of the connector")
18 | }).describe("End item of the connector"),
19 | style: z.object({
20 | strokeColor: z.string().optional().nullish().describe("Color of the connector stroke"),
21 | strokeWidth: z.number().optional().nullish().describe("Width of the connector stroke"),
22 | strokeStyle: z.string().optional().nullish().describe("Style of the connector stroke (normal, dashed, etc.)"),
23 | startStrokeCap: z.string().optional().nullish().describe("Start stroke cap style"),
24 | endStrokeCap: z.string().optional().nullish().describe("End stroke cap style")
25 | }).optional().nullish().describe("Style configuration of the connector")
26 | },
27 | fn: async ({ boardId, startItem, endItem, style }) => {
28 | try {
29 | if (!boardId) {
30 | return ServerResponse.error("Board ID is required");
31 | }
32 |
33 | const connectorData = new ConnectorCreationData();
34 | connectorData.startItem = startItem;
35 | connectorData.endItem = endItem;
36 |
37 | if (style) {
38 | connectorData.style = style;
39 | }
40 |
41 | const result = await MiroClient.getApi().createConnector(boardId, connectorData);
42 | return ServerResponse.text(JSON.stringify(result, null, 2));
43 | } catch (error) {
44 | return ServerResponse.error(error);
45 | }
46 | }
47 | }
48 |
49 | export default createConnectorTool;
```
--------------------------------------------------------------------------------
/src/tools/createDocumentItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { DocumentCreateRequest } from '@mirohq/miro-api/dist/model/documentCreateRequest.js';
7 | import { DocumentUrlData } from '@mirohq/miro-api/dist/model/documentUrlData.js';
8 |
9 | const createDocumentItemTool: ToolSchema = {
10 | name: "create-document-item",
11 | description: "Create a new document item on a Miro board",
12 | args: {
13 | boardId: z.string().describe("Unique identifier (ID) of the board where the document will be created"),
14 | data: z.object({
15 | url: z.string().describe("URL of the document to be added to the board"),
16 | title: z.string().optional().nullish().describe("Title of the document")
17 | }).describe("The content and configuration of the document"),
18 | position: z.object({
19 | x: z.number().describe("X coordinate of the document"),
20 | y: z.number().describe("Y coordinate of the document")
21 | }).describe("Position of the document on the board"),
22 | geometry: z.object({
23 | width: z.number().optional().nullish().describe("Width of the document"),
24 | height: z.number().optional().nullish().describe("Height of the document")
25 | }).optional().nullish().describe("Dimensions of the document")
26 | },
27 | fn: async ({ boardId, data, position, geometry }) => {
28 | try {
29 | if (!boardId) {
30 | return ServerResponse.error("Board ID is required");
31 | }
32 |
33 | const createRequest = new DocumentCreateRequest();
34 |
35 | const documentData = new DocumentUrlData();
36 | documentData.url = data.url;
37 |
38 | if (data.title !== undefined) documentData.title = data.title;
39 |
40 | createRequest.data = documentData;
41 | createRequest.position = position;
42 |
43 | if (geometry) {
44 | createRequest.geometry = geometry;
45 | }
46 |
47 | const result = await MiroClient.getApi().createDocumentItemUsingUrl(boardId, createRequest);
48 | return ServerResponse.text(JSON.stringify(result, null, 2));
49 | } catch (error) {
50 | return ServerResponse.error(error);
51 | }
52 | }
53 | }
54 |
55 | export default createDocumentItemTool;
```
--------------------------------------------------------------------------------
/src/tools/createTextItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { TextCreateRequest } from '@mirohq/miro-api/dist/model/textCreateRequest.js';
7 | import { TextData } from '@mirohq/miro-api/dist/model/textData.js';
8 |
9 | const createTextItemTool: ToolSchema = {
10 | name: "create-text-item",
11 | description: "Create a new text item on a Miro board",
12 | args: {
13 | boardId: z.string().describe("Unique identifier (ID) of the board where the text will be created"),
14 | data: z.object({
15 | content: z.string().describe("Text content of the text item")
16 | }).describe("The content of the text item"),
17 | position: z.object({
18 | x: z.number().describe("X coordinate of the text item"),
19 | y: z.number().describe("Y coordinate of the text item")
20 | }).describe("Position of the text item on the board"),
21 | geometry: z.object({
22 | width: z.number().optional().nullish().describe("Width of the text item")
23 | }).optional().nullish().describe("Dimensions of the text item"),
24 | style: z.object({
25 | color: z.string().optional().nullish().describe("Color of the text"),
26 | fontSize: z.number().optional().nullish().describe("Font size of the text"),
27 | textAlign: z.string().optional().nullish().describe("Alignment of the text (left, center, right)")
28 | }).optional().nullish().describe("Style configuration of the text item")
29 | },
30 | fn: async ({ boardId, data, position, geometry, style }) => {
31 | try {
32 | if (!boardId) {
33 | return ServerResponse.error("Board ID is required");
34 | }
35 |
36 | const createRequest = new TextCreateRequest();
37 |
38 | const textData = new TextData();
39 | textData.content = data.content;
40 |
41 | createRequest.data = textData;
42 | createRequest.position = position;
43 |
44 | if (geometry) {
45 | createRequest.geometry = geometry;
46 | }
47 |
48 | if (style) {
49 | createRequest.style = style;
50 | }
51 |
52 | const result = await MiroClient.getApi().createTextItem(boardId, createRequest);
53 | return ServerResponse.text(JSON.stringify(result, null, 2));
54 | } catch (error) {
55 | return ServerResponse.error(error);
56 | }
57 | }
58 | }
59 |
60 | export default createTextItemTool;
```
--------------------------------------------------------------------------------
/src/tools/updateConnector.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { ConnectorChangesData } from '@mirohq/miro-api/dist/model/connectorChangesData.js';
7 |
8 | const updateConnectorTool: ToolSchema = {
9 | name: "update-connector",
10 | description: "Update an existing connector on a Miro board",
11 | args: {
12 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the connector"),
13 | connectorId: z.string().describe("Unique identifier (ID) of the connector that you want to update"),
14 | startItem: z.object({
15 | id: z.string().describe("ID of the item at the start of the connector")
16 | }).optional().nullish().describe("Start item of the connector"),
17 | endItem: z.object({
18 | id: z.string().describe("ID of the item at the end of the connector")
19 | }).optional().nullish().describe("End item of the connector"),
20 | style: z.object({
21 | strokeColor: z.string().optional().nullish().describe("Updated color of the connector stroke"),
22 | strokeWidth: z.number().optional().nullish().describe("Updated width of the connector stroke"),
23 | strokeStyle: z.string().optional().nullish().describe("Updated style of the connector stroke (normal, dashed, etc.)"),
24 | startStrokeCap: z.string().optional().nullish().describe("Updated start stroke cap style"),
25 | endStrokeCap: z.string().optional().nullish().describe("Updated end stroke cap style")
26 | }).optional().nullish().describe("Updated style configuration of the connector")
27 | },
28 | fn: async ({ boardId, connectorId, startItem, endItem, style }) => {
29 | try {
30 | if (!boardId) {
31 | return ServerResponse.error("Board ID is required");
32 | }
33 |
34 | if (!connectorId) {
35 | return ServerResponse.error("Connector ID is required");
36 | }
37 |
38 | const changes = new ConnectorChangesData();
39 |
40 | if (startItem) {
41 | changes.startItem = startItem;
42 | }
43 |
44 | if (endItem) {
45 | changes.endItem = endItem;
46 | }
47 |
48 | if (style) {
49 | changes.style = style;
50 | }
51 |
52 | const result = await MiroClient.getApi().updateConnector(boardId, connectorId, changes);
53 | return ServerResponse.text(JSON.stringify(result, null, 2));
54 | } catch (error) {
55 | return ServerResponse.error(error);
56 | }
57 | }
58 | }
59 |
60 | export default updateConnectorTool;
```
--------------------------------------------------------------------------------
/src/tools/updateImageItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { ImageUpdateRequest } from '@mirohq/miro-api/dist/model/imageUpdateRequest.js';
7 |
8 | const updateImageItemTool: ToolSchema = {
9 | name: "update-image-item",
10 | description: "Update an existing image item on a Miro board",
11 | args: {
12 | boardId: z.string().describe("Unique identifier (ID) of the board where you want to update the item"),
13 | itemId: z.string().describe("Unique identifier (ID) of the image that you want to update"),
14 | data: z.object({
15 | title: z.string().optional().nullish().describe("Updated title of the image")
16 | }).optional().nullish().describe("The updated content of the image"),
17 | position: z.object({
18 | x: z.number().optional().nullish().describe("Updated X coordinate of the image"),
19 | y: z.number().optional().nullish().describe("Updated Y coordinate of the image"),
20 | origin: z.string().optional().nullish().describe("Updated origin of the image (center, top-left, etc.)"),
21 | relativeTo: z.string().optional().nullish().describe("Updated reference point (canvas_center, etc.)")
22 | }).optional().nullish().describe("Updated position of the image on the board"),
23 | geometry: z.object({
24 | width: z.number().optional().nullish().describe("Updated width of the image"),
25 | height: z.number().optional().nullish().describe("Updated height of the image")
26 | }).optional().nullish().describe("Updated dimensions of the image")
27 | },
28 | fn: async ({ boardId, itemId, data, position, geometry }) => {
29 | try {
30 | if (!boardId) {
31 | return ServerResponse.error("Board ID is required");
32 | }
33 |
34 | if (!itemId) {
35 | return ServerResponse.error("Item ID is required");
36 | }
37 |
38 | const updateRequest = new ImageUpdateRequest();
39 |
40 | if (data) {
41 | updateRequest.data = {};
42 |
43 | if (data.title !== undefined) {
44 | updateRequest.data.title = data.title;
45 | }
46 | }
47 |
48 | if (position) {
49 | updateRequest.position = position;
50 | }
51 |
52 | if (geometry) {
53 | updateRequest.geometry = geometry;
54 | }
55 |
56 | const result = await MiroClient.getApi().updateImageItemUsingUrl(boardId, itemId, updateRequest);
57 | return ServerResponse.text(JSON.stringify(result, null, 2));
58 | } catch (error) {
59 | return ServerResponse.error(error);
60 | }
61 | }
62 | }
63 |
64 | export default updateImageItemTool;
```
--------------------------------------------------------------------------------
/src/tools/createImageItemUsingUrl.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { ImageCreateRequest } from '@mirohq/miro-api/dist/model/imageCreateRequest.js';
7 | import { ImageUrlData } from '@mirohq/miro-api/dist/model/imageUrlData.js';
8 |
9 | const createImageItemUsingUrlTool: ToolSchema = {
10 | name: "create-image-item-using-url",
11 | description: "Create a new image item on a Miro board using a URL",
12 | args: {
13 | boardId: z.string().describe("Unique identifier (ID) of the board where the image will be created"),
14 | data: z.object({
15 | url: z.string().describe("URL of the image to be added to the board"),
16 | title: z.string().optional().nullish().describe("Title of the image")
17 | }).describe("The content and configuration of the image"),
18 | position: z.object({
19 | x: z.number().describe("X coordinate of the image"),
20 | y: z.number().describe("Y coordinate of the image"),
21 | origin: z.string().optional().nullish().describe("Origin of the image (center, top-left, etc.)"),
22 | relativeTo: z.string().optional().nullish().describe("Reference point (canvas_center, etc.)")
23 | }).describe("Position of the image on the board"),
24 | geometry: z.object({
25 | width: z.number().optional().nullish().describe("Width of the image"),
26 | height: z.number().optional().nullish().describe("Height of the image")
27 | }).optional().nullish().describe("Dimensions of the image")
28 | },
29 | fn: async ({ boardId, data, position, geometry }) => {
30 | try {
31 | if (!boardId) {
32 | return ServerResponse.error("Board ID is required");
33 | }
34 |
35 | const createRequest = new ImageCreateRequest();
36 |
37 | const imageData = new ImageUrlData();
38 | imageData.url = data.url;
39 |
40 | if (data.title !== undefined) {
41 | imageData.title = data.title;
42 | }
43 |
44 | createRequest.data = imageData;
45 |
46 | const completePosition = {
47 | ...position,
48 | origin: position.origin || "center",
49 | relativeTo: position.relativeTo || "canvas_center"
50 | };
51 |
52 | createRequest.position = completePosition;
53 |
54 | if (geometry) {
55 | createRequest.geometry = geometry;
56 | }
57 |
58 | const result = await MiroClient.getApi().createImageItemUsingUrl(boardId, createRequest);
59 | return ServerResponse.text(JSON.stringify(result, null, 2));
60 | } catch (error) {
61 | return ServerResponse.error(error);
62 | }
63 | }
64 | }
65 |
66 | export default createImageItemUsingUrlTool;
```
--------------------------------------------------------------------------------
/src/tools/createImageItemUsingFileFromDevice.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 | import { UploadFileFromDeviceData } from '@mirohq/miro-api/dist/model/uploadFileFromDeviceData.js';
6 | import { RequestFile } from '@mirohq/miro-api/dist/model/models.js';
7 |
8 | const createImageItemUsingFileFromDeviceTool: ToolSchema = {
9 | name: "create-image-item-using-file",
10 | description: "Create a new image item on a Miro board using file from device or from chat",
11 | args: {
12 | boardId: z.string().describe("Unique identifier (ID) of the board where the image will be created"),
13 | imageData: z.string().describe("Base64 encoded image data from the chat"),
14 | position: z.object({
15 | x: z.number().describe("X coordinate of the image"),
16 | y: z.number().describe("Y coordinate of the image"),
17 | origin: z.string().optional().nullish().describe("Origin of the image (center, top-left, etc.)"),
18 | relativeTo: z.string().optional().nullish().describe("Reference point (canvas_center, etc.)")
19 | }).describe("Position of the image on the board"),
20 | title: z.string().optional().nullish().describe("Title of the image")
21 | },
22 | fn: async ({ boardId, imageData, position, title }) => {
23 | try {
24 | if (!boardId) {
25 | return ServerResponse.error("Board ID is required");
26 | }
27 |
28 | if (!imageData) {
29 | return ServerResponse.error("Image data is required");
30 | }
31 |
32 | let imageBuffer;
33 | try {
34 | const base64Data = imageData.replace(/^data:image\/\w+;base64,/, '');
35 | imageBuffer = Buffer.from(base64Data, 'base64');
36 | } catch (error) {
37 | return ServerResponse.error(`Error decoding Base64 image data: ${error.message}`);
38 | }
39 |
40 | try {
41 | const metadata = {};
42 |
43 | if (position) {
44 | metadata['position'] = {
45 | ...position,
46 | origin: position.origin || 'center',
47 | relativeTo: position.relativeTo || 'canvas_center'
48 | };
49 | }
50 |
51 | if (title) {
52 | metadata['title'] = title;
53 | }
54 |
55 | const result = await MiroClient.getApi().createImageItemUsingLocalFile(boardId, imageBuffer, metadata);
56 | return ServerResponse.text(JSON.stringify(result, null, 2));
57 | } catch (error) {
58 | return ServerResponse.error(`Error uploading image to Miro: ${error.message}`);
59 | }
60 | } catch (error) {
61 | return ServerResponse.error(error);
62 | }
63 | }
64 | };
65 |
66 | export default createImageItemUsingFileFromDeviceTool;
```
--------------------------------------------------------------------------------
/src/tools/updateEmbedItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const updateEmbedItemTool: ToolSchema = {
7 | name: "update-embed-item",
8 | description: "Update an existing embed item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the embed"),
11 | itemId: z.string().describe("Unique identifier (ID) of the embed that you want to update"),
12 | data: z.object({
13 | mode: z.string().optional().nullish().describe("Updated mode of the embed (normal, inline, etc.)")
14 | }).optional().nullish().describe("The updated configuration of the embed"),
15 | position: z.object({
16 | x: z.number().describe("Updated X coordinate of the embed"),
17 | y: z.number().describe("Updated Y coordinate of the embed"),
18 | origin: z.string().optional().nullish().describe("Origin of the embed (center, top-left, etc.)"),
19 | relativeTo: z.string().optional().nullish().describe("Reference point (canvas_center, etc.)")
20 | }).optional().nullish().describe("Updated position of the embed on the board"),
21 | geometry: z.object({
22 | width: z.number().optional().nullish().describe("Updated width of the embed"),
23 | height: z.number().optional().nullish().describe("Updated height of the embed")
24 | })
25 | .optional().nullish()
26 | .refine(data => !data || data.width !== undefined || data.height !== undefined, {
27 | message: "Either width or height must be provided if geometry is set"
28 | })
29 | .refine(data => !data || !(data.width !== undefined && data.height !== undefined), {
30 | message: "Only one of width or height should be provided for items with fixed aspect ratio"
31 | })
32 | .describe("Updated dimensions of the embed")
33 | },
34 | fn: async ({ boardId, itemId, data, position, geometry }) => {
35 | try {
36 | if (!boardId) {
37 | return ServerResponse.error("Board ID is required");
38 | }
39 |
40 | if (!itemId) {
41 | return ServerResponse.error("Item ID is required");
42 | }
43 |
44 | const updateRequest: Record<string, any> = {};
45 |
46 | if (data) {
47 | updateRequest.data = data;
48 | }
49 |
50 | if (position) {
51 | updateRequest.position = position;
52 | }
53 |
54 | if (geometry) {
55 | updateRequest.geometry = geometry;
56 | }
57 |
58 | const result = await MiroClient.getApi().updateEmbedItem(boardId, itemId, updateRequest);
59 | return ServerResponse.text(JSON.stringify(result, null, 2));
60 | } catch (error) {
61 | return ServerResponse.error(error);
62 | }
63 | }
64 | }
65 |
66 | export default updateEmbedItemTool;
```
--------------------------------------------------------------------------------
/src/tools/createEmbedItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { EmbedCreateRequest } from '@mirohq/miro-api/dist/model/embedCreateRequest.js';
7 | import { EmbedUrlData } from '@mirohq/miro-api/dist/model/embedUrlData.js';
8 |
9 | const createEmbedItemTool: ToolSchema = {
10 | name: "create-embed-item",
11 | description: "Create a new embed item on a Miro board",
12 | args: {
13 | boardId: z.string().describe("Unique identifier (ID) of the board where the embed will be created"),
14 | data: z.object({
15 | url: z.string().describe("URL to be embedded on the board"),
16 | mode: z.string().optional().nullish().describe("Mode of the embed (normal, inline, etc.)")
17 | }).describe("The content and configuration of the embed"),
18 | position: z.object({
19 | x: z.number().describe("X coordinate of the embed"),
20 | y: z.number().describe("Y coordinate of the embed"),
21 | origin: z.string().optional().nullish().describe("Origin of the embed (center, top-left, etc.)"),
22 | relativeTo: z.string().optional().nullish().describe("Reference point (canvas_center, etc.)")
23 | }).describe("Position of the embed on the board"),
24 | geometry: z.object({
25 | width: z.number().optional().nullish().describe("Width of the embed"),
26 | height: z.number().optional().nullish().describe("Height of the embed")
27 | })
28 | .refine(data => data.width !== undefined || data.height !== undefined, {
29 | message: "Either width or height must be provided"
30 | })
31 | .refine(data => !(data.width !== undefined && data.height !== undefined), {
32 | message: "Only one of width or height should be provided for items with fixed aspect ratio"
33 | })
34 | .describe("Dimensions of the embed")
35 | },
36 | fn: async ({ boardId, data, position, geometry }) => {
37 | try {
38 | if (!boardId) {
39 | return ServerResponse.error("Board ID is required");
40 | }
41 |
42 | const createRequest = new EmbedCreateRequest();
43 |
44 | const embedData = new EmbedUrlData();
45 | embedData.url = data.url;
46 |
47 | if (data.mode !== undefined) {
48 | embedData.mode = data.mode;
49 | }
50 |
51 | createRequest.data = embedData;
52 |
53 | const completePosition = {
54 | ...position,
55 | origin: position.origin || "center",
56 | relativeTo: position.relativeTo || "canvas_center"
57 | };
58 |
59 | createRequest.position = completePosition;
60 | createRequest.geometry = geometry;
61 |
62 | const result = await MiroClient.getApi().createEmbedItem(boardId, createRequest);
63 | return ServerResponse.text(JSON.stringify(result, null, 2));
64 | } catch (error) {
65 | return ServerResponse.error(error);
66 | }
67 | }
68 | }
69 |
70 | export default createEmbedItemTool;
```
--------------------------------------------------------------------------------
/src/tools/createCardItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { CardCreateRequest } from '@mirohq/miro-api/dist/model/cardCreateRequest.js';
7 | import { CardData } from '@mirohq/miro-api/dist/model/cardData.js';
8 |
9 | const createCardItemTool: ToolSchema = {
10 | name: "create-card-item",
11 | description: "Create a new card item on a Miro board",
12 | args: {
13 | boardId: z.string().describe("Unique identifier (ID) of the board where the card will be created"),
14 | data: z.object({
15 | title: z.string().describe("Title of the card"),
16 | description: z.string().optional().nullish().describe("Description of the card"),
17 | assigneeId: z.string().optional().nullish().describe("User ID of the assignee"),
18 | dueDate: z.string().optional().nullish().describe("Due date for the card (ISO 8601 format)")
19 | }).describe("The content and configuration of the card"),
20 | position: z.object({
21 | x: z.number().describe("X coordinate of the card"),
22 | y: z.number().describe("Y coordinate of the card")
23 | }).describe("Position of the card on the board"),
24 | geometry: z.object({
25 | width: z.number().optional().nullish().describe("Width of the card"),
26 | height: z.number().optional().nullish().describe("Height of the card"),
27 | rotation: z.number().optional().nullish().describe("Rotation angle of the card")
28 | }).optional().nullish().describe("Dimensions of the card"),
29 | style: z.object({
30 | cardTheme: z.string().optional().nullish().describe("Color of the card")
31 | }).optional().nullish().describe("Style configuration of the card")
32 | },
33 | fn: async ({ boardId, data, position, geometry, style }) => {
34 | try {
35 | if (!boardId) {
36 | return ServerResponse.error("Board ID is required");
37 | }
38 |
39 | const createRequest = new CardCreateRequest();
40 |
41 | const cardData = new CardData();
42 | cardData.title = data.title;
43 |
44 | if (data.description !== undefined) cardData.description = data.description;
45 | if (data.assigneeId !== undefined) cardData.assigneeId = data.assigneeId;
46 |
47 | if (data.dueDate !== undefined) {
48 | cardData.dueDate = new Date(data.dueDate);
49 | }
50 |
51 | createRequest.data = cardData;
52 | createRequest.position = position;
53 |
54 | if (geometry) {
55 | createRequest.geometry = geometry;
56 | }
57 |
58 | if (style) {
59 | createRequest.style = style;
60 | }
61 |
62 | const result = await MiroClient.getApi().createCardItem(boardId, createRequest);
63 | return ServerResponse.text(JSON.stringify(result, null, 2));
64 | } catch (error) {
65 | return ServerResponse.error(error);
66 | }
67 | }
68 | }
69 |
70 | export default createCardItemTool;
```
--------------------------------------------------------------------------------
/src/tools/updateDocumentItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 | import { DocumentUpdateRequest } from '@mirohq/miro-api/dist/model/documentUpdateRequest.js';
6 | import { DocumentUrlData } from '@mirohq/miro-api/dist/model/documentUrlData.js';
7 |
8 | const updateDocumentItemTool: ToolSchema = {
9 | name: "update-document-item",
10 | description: "Update an existing document item on a Miro board",
11 | args: {
12 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the document"),
13 | itemId: z.string().describe("Unique identifier (ID) of the document that you want to update"),
14 | data: z.object({
15 | url: z.string().optional().nullish().describe("Updated URL of the document"),
16 | title: z.string().optional().nullish().describe("Updated title of the document")
17 | }).optional().nullish().describe("The updated content and configuration of the document"),
18 | position: z.object({
19 | x: z.number().optional().nullish().describe("Updated X coordinate of the document"),
20 | y: z.number().optional().nullish().describe("Updated Y coordinate of the document")
21 | }).optional().nullish().describe("Updated position of the document on the board"),
22 | geometry: z.object({
23 | width: z.number().optional().nullish().describe("Updated width of the document"),
24 | height: z.number().optional().nullish().describe("Updated height of the document")
25 | }).optional().nullish().describe("Updated dimensions of the document")
26 | },
27 | fn: async ({ boardId, itemId, data, position, geometry }) => {
28 | try {
29 | if (!boardId) {
30 | return ServerResponse.error("Board ID is required");
31 | }
32 |
33 | if (!itemId) {
34 | return ServerResponse.error("Item ID is required");
35 | }
36 |
37 | const updateRequest = new DocumentUpdateRequest();
38 |
39 | if (data) {
40 | const documentData = new DocumentUrlData();
41 |
42 | if (data.url !== undefined) documentData.url = data.url;
43 | if (data.title !== undefined) documentData.title = data.title;
44 |
45 | if (Object.keys(documentData).length > 0) {
46 | updateRequest.data = documentData;
47 | }
48 | }
49 |
50 | if (position) {
51 | updateRequest.position = position;
52 | }
53 |
54 | if (geometry) {
55 | updateRequest.geometry = geometry;
56 | }
57 |
58 | if (Object.keys(updateRequest).length === 0) {
59 | return ServerResponse.error("No data provided for update");
60 | }
61 |
62 | const result = await MiroClient.getApi().updateDocumentItemUsingUrl(boardId, itemId, updateRequest);
63 | return ServerResponse.text(JSON.stringify(result, null, 2));
64 | } catch (error) {
65 | return ServerResponse.error(error);
66 | }
67 | }
68 | }
69 |
70 | export default updateDocumentItemTool;
```
--------------------------------------------------------------------------------
/src/tools/updateTextItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 | import { TextUpdateRequest } from '@mirohq/miro-api/dist/model/textUpdateRequest.js';
6 | import { TextData } from '@mirohq/miro-api/dist/model/textData.js';
7 |
8 | const updateTextItemTool: ToolSchema = {
9 | name: "update-text-item",
10 | description: "Update an existing text item on a Miro board",
11 | args: {
12 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the text item"),
13 | itemId: z.string().describe("Unique identifier (ID) of the text item that you want to update"),
14 | data: z.object({
15 | content: z.string().optional().nullish().describe("Updated text content of the text item")
16 | }).optional().nullish().describe("The updated content of the text item"),
17 | position: z.object({
18 | x: z.number().optional().nullish().describe("Updated X coordinate of the text item"),
19 | y: z.number().optional().nullish().describe("Updated Y coordinate of the text item")
20 | }).optional().nullish().describe("Updated position of the text item on the board"),
21 | geometry: z.object({
22 | width: z.number().optional().nullish().describe("Updated width of the text item")
23 | }).optional().nullish().describe("Updated dimensions of the text item"),
24 | style: z.object({
25 | color: z.string().optional().nullish().describe("Updated color of the text"),
26 | fontSize: z.number().optional().nullish().describe("Updated font size of the text"),
27 | textAlign: z.string().optional().nullish().describe("Updated alignment of the text (left, center, right)")
28 | }).optional().nullish().describe("Updated style configuration of the text item")
29 | },
30 | fn: async ({ boardId, itemId, data, position, geometry, style }) => {
31 | try {
32 | if (!boardId) {
33 | return ServerResponse.error("Board ID is required");
34 | }
35 |
36 | if (!itemId) {
37 | return ServerResponse.error("Item ID is required");
38 | }
39 |
40 | const updateRequest = new TextUpdateRequest();
41 |
42 | if (data) {
43 | const textData = new TextData();
44 |
45 | if (data.content !== undefined) textData.content = data.content;
46 |
47 | if (Object.keys(textData).length > 0) {
48 | updateRequest.data = textData;
49 | }
50 | }
51 |
52 | if (position) {
53 | updateRequest.position = position;
54 | }
55 |
56 | if (geometry) {
57 | updateRequest.geometry = geometry;
58 | }
59 |
60 | if (style) {
61 | updateRequest.style = style;
62 | }
63 |
64 | if (Object.keys(updateRequest).length === 0) {
65 | return ServerResponse.error("No data provided for update");
66 | }
67 |
68 | const result = await MiroClient.getApi().updateTextItem(boardId, itemId, updateRequest);
69 | return ServerResponse.text(JSON.stringify(result, null, 2));
70 | } catch (error) {
71 | return ServerResponse.error(error);
72 | }
73 | }
74 | }
75 |
76 | export default updateTextItemTool;
```
--------------------------------------------------------------------------------
/src/tools/updateImageItemUsingFileFromDevice.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 | import { UploadFileFromDeviceData } from '@mirohq/miro-api/dist/model/uploadFileFromDeviceData.js';
6 | import { RequestFile } from '@mirohq/miro-api/dist/model/models.js';
7 | import * as fs from 'fs';
8 | import FormData from 'form-data';
9 |
10 | const updateImageItemUsingFileFromDeviceTool: ToolSchema = {
11 | name: "update-image-item-using-file",
12 | description: "Update an existing image item on a Miro board using file from device",
13 | args: {
14 | boardId: z.string().describe("Unique identifier (ID) of the board where you want to update the item"),
15 | itemId: z.string().describe("Unique identifier (ID) of the image that you want to update"),
16 | filePath: z.string().describe("Path to the new image file on the device"),
17 | title: z.string().optional().nullish().describe("Updated title of the image"),
18 | position: z.object({
19 | x: z.number().optional().nullish().describe("Updated X coordinate of the image"),
20 | y: z.number().optional().nullish().describe("Updated Y coordinate of the image"),
21 | origin: z.string().optional().nullish().describe("Updated origin of the image (center, top-left, etc.)"),
22 | relativeTo: z.string().optional().nullish().describe("Updated reference point (canvas_center, etc.)")
23 | }).optional().nullish().describe("Updated position of the image on the board")
24 | },
25 | fn: async ({ boardId, itemId, filePath, title, position }) => {
26 | try {
27 | if (!boardId) {
28 | return ServerResponse.error("Board ID is required");
29 | }
30 |
31 | if (!itemId) {
32 | return ServerResponse.error("Item ID is required");
33 | }
34 |
35 | if (!filePath) {
36 | return ServerResponse.error("File path is required");
37 | }
38 |
39 | // Implementacja aktualizacji obrazu z pliku lokalnego nie jest możliwa bezpośrednio w MCP
40 | // ponieważ wymaga dostępu do systemu plików klienta oraz konstruktora FormData
41 |
42 | const instructionsForUser = {
43 | message: "Aktualizacja obrazu z pliku lokalnego nie jest obecnie obsługiwana bezpośrednio w MCP Miro.",
44 | alternatives: [
45 | "1. Użyj funkcji 'update-image-item' z URL do obrazu.",
46 | "2. Alternatywnie, możesz użyć bezpośrednio API Miro przez SDK lub żądania HTTP:",
47 | " - Utwórz formularz FormData",
48 | " - Dodaj plik do formularza",
49 | " - Wyślij żądanie PATCH do https://api.miro.com/v2/boards/{boardId}/images/{itemId}",
50 | " - Dodaj nagłówek 'Content-Type: multipart/form-data' oraz token autoryzacyjny"
51 | ],
52 | documentation: "Więcej informacji znajdziesz w dokumentacji API Miro: https://developers.miro.com/reference/update-image-item-using-file-from-device"
53 | };
54 |
55 | return ServerResponse.text(JSON.stringify(instructionsForUser, null, 2));
56 | } catch (error) {
57 | return ServerResponse.error(error);
58 | }
59 | }
60 | }
61 |
62 | export default updateImageItemUsingFileFromDeviceTool;
```
--------------------------------------------------------------------------------
/src/tools/createFrameItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { FrameCreateRequest } from '@mirohq/miro-api/dist/model/frameCreateRequest.js';
7 | import { FrameChanges } from '@mirohq/miro-api/dist/model/frameChanges.js';
8 |
9 | const createFrameItemTool: ToolSchema = {
10 | name: "create-frame",
11 | description: "Create a new frame on a Miro board",
12 | args: {
13 | boardId: z.string().describe("Unique identifier (ID) of the board where the frame will be created"),
14 | data: z.object({
15 | title: z.string().optional().nullish().describe("Title of the frame. This title appears at the top of the frame."),
16 | format: z.string().optional().nullish().describe("Format of the frame. Only 'custom' is supported currently."),
17 | type: z.string().optional().nullish().describe("Type of the frame. Only 'freeform' is supported currently."),
18 | showContent: z.boolean().optional().nullish().describe("Hide or reveal the content inside a frame (Enterprise plan only).")
19 | }).describe("The content and configuration of the frame"),
20 | position: z.object({
21 | x: z.number().describe("X coordinate of the frame"),
22 | y: z.number().describe("Y coordinate of the frame")
23 | }).describe("Position of the frame on the board"),
24 | geometry: z.object({
25 | width: z.number().optional().nullish().describe("Width of the frame"),
26 | height: z.number().optional().nullish().describe("Height of the frame")
27 | }).optional().nullish().describe("Dimensions of the frame"),
28 | style: z.object({
29 | fillColor: z.string().optional().nullish().describe("Fill color for the frame. Hex values like #f5f6f8, #d5f692, etc.")
30 | }).optional().nullish().describe("Style configuration of the frame")
31 | },
32 | fn: async ({ boardId, data, position, geometry, style }: {
33 | boardId: string,
34 | data: {
35 | title?: string,
36 | format?: string,
37 | type?: string,
38 | showContent?: boolean
39 | },
40 | position: {
41 | x: number,
42 | y: number
43 | },
44 | geometry?: {
45 | width?: number,
46 | height?: number
47 | },
48 | style?: {
49 | fillColor?: string
50 | }
51 | }) => {
52 | try {
53 | if (!boardId) {
54 | return ServerResponse.error("Board ID is required");
55 | }
56 |
57 | const createRequest = new FrameCreateRequest();
58 |
59 | const frameData = new FrameChanges();
60 |
61 | if (data.title !== undefined) frameData.title = data.title;
62 | if (data.format !== undefined) frameData.format = data.format;
63 | if (data.type !== undefined) frameData.type = data.type;
64 | if (data.showContent !== undefined) frameData.showContent = data.showContent;
65 |
66 | createRequest.data = frameData;
67 | createRequest.position = position;
68 |
69 | if (geometry) {
70 | createRequest.geometry = geometry;
71 | }
72 |
73 | if (style) {
74 | createRequest.style = style;
75 | }
76 |
77 | const result = await MiroClient.getApi().createFrameItem(boardId, createRequest);
78 | return ServerResponse.text(JSON.stringify(result, null, 2));
79 | } catch (error) {
80 | return ServerResponse.error(error);
81 | }
82 | }
83 | }
84 |
85 | export default createFrameItemTool;
```
--------------------------------------------------------------------------------
/src/tools/createAppCardItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { AppCardCreateRequest } from '@mirohq/miro-api/dist/model/appCardCreateRequest.js';
5 | import { AppCardDataChanges } from '@mirohq/miro-api/dist/model/appCardDataChanges.js';
6 | import { CustomField } from '@mirohq/miro-api/dist/model/customField.js';
7 | import { ToolSchema } from '../tool.js';
8 |
9 | const createAppCardItemTool: ToolSchema = {
10 | name: "create-app-card-item",
11 | description: "Create a new app card item on a Miro board",
12 | args: {
13 | boardId: z.string().describe("Unique identifier (ID) of the board where the app card will be created"),
14 | data: z.object({
15 | title: z.string().describe("Title of the app card"),
16 | description: z.string().optional().nullish().describe("Description of the app card"),
17 | status: z.string().optional().nullish().describe("Status text of the app card"),
18 | fields: z.array(z.object({
19 | value: z.string().describe("Value of the field"),
20 | iconShape: z.string().optional().nullish().describe("Shape of the icon"),
21 | fillColor: z.string().optional().nullish().describe("Fill color of the field"),
22 | textColor: z.string().optional().nullish().describe("Color of the text"),
23 | })).optional().nullish().describe("Custom fields to display on the app card")
24 | }).describe("The content and configuration of the app card"),
25 | position: z.object({
26 | x: z.number().describe("X coordinate of the app card"),
27 | y: z.number().describe("Y coordinate of the app card")
28 | }).describe("Position of the app card on the board"),
29 | geometry: z.object({
30 | width: z.number().optional().nullish().describe("Width of the app card"),
31 | height: z.number().optional().nullish().describe("Height of the app card")
32 | }).optional().nullish().describe("Dimensions of the app card")
33 | },
34 | fn: async ({boardId, data, position, geometry}) => {
35 | try {
36 | if (!boardId) {
37 | return ServerResponse.error("Board ID is required");
38 | }
39 |
40 | const createRequest = new AppCardCreateRequest();
41 |
42 | const appCardData = new AppCardDataChanges();
43 | appCardData.title = data.title;
44 |
45 | if (data.description !== undefined) appCardData.description = data.description;
46 | if (data.status !== undefined) appCardData.status = data.status;
47 |
48 | if (data.fields) {
49 | appCardData.fields = data.fields.map(field => {
50 | const customField = new CustomField();
51 | customField.value = field.value;
52 | if (field.iconShape) customField.iconShape = field.iconShape;
53 | if (field.fillColor) customField.fillColor = field.fillColor;
54 | if (field.textColor) customField.textColor = field.textColor;
55 | return customField;
56 | });
57 | }
58 |
59 | createRequest.data = appCardData;
60 | createRequest.position = position;
61 |
62 | if (geometry) {
63 | createRequest.geometry = geometry;
64 | }
65 |
66 | const result = await MiroClient.getApi().createAppCardItem(boardId, createRequest);
67 | return ServerResponse.text(JSON.stringify(result, null, 2));
68 | } catch (error) {
69 | return ServerResponse.error(error);
70 | }
71 | }
72 | }
73 |
74 | export default createAppCardItemTool;
75 |
```
--------------------------------------------------------------------------------
/src/tools/updateCardItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { CardUpdateRequest } from '@mirohq/miro-api/dist/model/cardUpdateRequest.js';
7 | import { CardData } from '@mirohq/miro-api/dist/model/cardData.js';
8 |
9 | const updateCardItemTool: ToolSchema = {
10 | name: "update-card-item",
11 | description: "Update an existing card item on a Miro board",
12 | args: {
13 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the card"),
14 | itemId: z.string().describe("Unique identifier (ID) of the card that you want to update"),
15 | data: z.object({
16 | title: z.string().optional().nullish().describe("Updated title of the card"),
17 | description: z.string().optional().nullish().describe("Updated description of the card"),
18 | assigneeId: z.string().optional().nullish().describe("Updated user ID of the assignee"),
19 | dueDate: z.string().optional().nullish().describe("Updated due date for the card (ISO 8601 format)")
20 | }).optional().nullish().describe("The updated content and configuration of the card"),
21 | position: z.object({
22 | x: z.number().describe("Updated X coordinate of the card"),
23 | y: z.number().describe("Updated Y coordinate of the card")
24 | }).optional().nullish().describe("Updated position of the card on the board"),
25 | geometry: z.object({
26 | width: z.number().optional().nullish().describe("Updated width of the card"),
27 | height: z.number().optional().nullish().describe("Updated height of the card"),
28 | rotation: z.number().optional().nullish().describe("Updated rotation angle of the card")
29 | }).optional().nullish().describe("Updated dimensions of the card"),
30 | style: z.object({
31 | cardTheme: z.string().optional().nullish().describe("Updated color of the card")
32 | }).optional().nullish().describe("Updated style configuration of the card")
33 | },
34 | fn: async ({ boardId, itemId, data, position, geometry, style }) => {
35 | try {
36 | if (!boardId) {
37 | return ServerResponse.error("Board ID is required");
38 | }
39 |
40 | if (!itemId) {
41 | return ServerResponse.error("Item ID is required");
42 | }
43 |
44 | const updateData = new CardUpdateRequest();
45 |
46 | if (data) {
47 | const cardData = new CardData();
48 |
49 | if (data.title !== undefined) cardData.title = data.title;
50 | if (data.description !== undefined) cardData.description = data.description;
51 | if (data.assigneeId !== undefined) cardData.assigneeId = data.assigneeId;
52 |
53 | if (data.dueDate !== undefined) {
54 | cardData.dueDate = new Date(data.dueDate);
55 | }
56 |
57 | updateData.data = cardData;
58 | }
59 |
60 | if (position) {
61 | updateData.position = position;
62 | }
63 |
64 | if (geometry) {
65 | updateData.geometry = geometry;
66 | }
67 |
68 | if (style) {
69 | updateData.style = style;
70 | }
71 |
72 | const result = await MiroClient.getApi().updateCardItem(boardId, itemId, updateData);
73 |
74 | return ServerResponse.text(JSON.stringify(result, null, 2));
75 | } catch (error) {
76 | return ServerResponse.error(error);
77 | }
78 | }
79 | }
80 |
81 | export default updateCardItemTool;
```
--------------------------------------------------------------------------------
/src/tools/updateShapeItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | const updateShapeItemTool: ToolSchema = {
7 | name: "update-shape-item",
8 | description: "Update an existing shape item on a Miro board",
9 | args: {
10 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the shape"),
11 | itemId: z.string().describe("Unique identifier (ID) of the shape that you want to update"),
12 | data: z.object({
13 | shape: z.string().optional().nullish().describe("Updated type of the shape (rectangle, circle, triangle, etc.)"),
14 | content: z.string().optional().nullish().describe("Updated text content to display inside the shape")
15 | }).optional().nullish().describe("The updated content and configuration of the shape"),
16 | position: z.object({
17 | x: z.number().describe("Updated X coordinate of the shape"),
18 | y: z.number().describe("Updated Y coordinate of the shape")
19 | }).optional().nullish().describe("Updated position of the shape on the board"),
20 | geometry: z.object({
21 | width: z.number().optional().nullish().describe("Updated width of the shape"),
22 | height: z.number().optional().nullish().describe("Updated height of the shape"),
23 | rotation: z.number().optional().nullish().describe("Rotation angle of the shape")
24 | }).optional().nullish().describe("Updated dimensions of the shape"),
25 | style: z.object({
26 | borderColor: z.string().optional().nullish().describe("Updated color of the shape border (hex format, e.g. #000000)"),
27 | borderWidth: z.number().optional().nullish().describe("Updated width of the shape border"),
28 | borderStyle: z.string().optional().nullish().describe("Updated style of the shape border (normal, dashed, etc.)"),
29 | borderOpacity: z.number().optional().nullish().describe("Updated opacity of the shape border (0-1)"),
30 | fillColor: z.string().optional().nullish().describe("Updated fill color of the shape (hex format, e.g. #000000)"),
31 | fillOpacity: z.number().optional().nullish().describe("Updated opacity of the shape fill (0-1)"),
32 | color: z.string().optional().nullish().describe("Updated color of the text in the shape (hex format, e.g. #000000)")
33 | }).optional().nullish().describe("Updated style configuration of the shape")
34 | },
35 | fn: async ({ boardId, itemId, data, position, geometry, style }) => {
36 | try {
37 | if (!boardId) {
38 | return ServerResponse.error("Board ID is required");
39 | }
40 |
41 | if (!itemId) {
42 | return ServerResponse.error("Item ID is required");
43 | }
44 |
45 | const updateRequest: Record<string, any> = {};
46 |
47 | if (data) {
48 | updateRequest.data = data;
49 | }
50 |
51 | if (position) {
52 | updateRequest.position = position;
53 | }
54 |
55 | if (geometry) {
56 | updateRequest.geometry = geometry;
57 | }
58 |
59 | if (style) {
60 | updateRequest.style = style;
61 | }
62 |
63 | const result = await MiroClient.getApi().updateShapeItem(boardId, itemId, updateRequest);
64 | return ServerResponse.text(JSON.stringify(result, null, 2));
65 | } catch (error) {
66 | return ServerResponse.error(error);
67 | }
68 | }
69 | }
70 |
71 | export default updateShapeItemTool;
```
--------------------------------------------------------------------------------
/src/tools/updateFrameItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { FrameUpdateRequest } from '@mirohq/miro-api/dist/model/frameUpdateRequest.js';
7 | import { FrameChanges } from '@mirohq/miro-api/dist/model/frameChanges.js';
8 |
9 | const updateFrameItemTool: ToolSchema = {
10 | name: "update-frame-item",
11 | description: "Update a frame on a Miro board based on the data, style, or geometry properties provided in the request body",
12 | args: {
13 | boardId: z.string().describe("Unique identifier (ID) of the board where you want to update the frame"),
14 | itemId: z.string().describe("Unique identifier (ID) of the frame that you want to update"),
15 | data: z.object({
16 | title: z.string().optional().nullish().describe("Title of the frame. This title appears at the top of the frame."),
17 | format: z.string().optional().nullish().describe("Format of the frame. Only 'custom' is supported currently."),
18 | type: z.string().optional().nullish().describe("Type of the frame. Only 'freeform' is supported currently."),
19 | showContent: z.boolean().optional().nullish().describe("Hide or reveal the content inside a frame (Enterprise plan only).")
20 | }).optional().nullish().describe("The updated content and configuration of the frame"),
21 | position: z.object({
22 | x: z.number().describe("X coordinate of the frame"),
23 | y: z.number().describe("Y coordinate of the frame")
24 | }).optional().nullish().describe("Updated position of the frame on the board"),
25 | geometry: z.object({
26 | width: z.number().optional().nullish().describe("Width of the frame"),
27 | height: z.number().optional().nullish().describe("Height of the frame")
28 | }).optional().nullish().describe("Updated dimensions of the frame"),
29 | style: z.object({
30 | fillColor: z.string().optional().nullish().describe("Fill color for the frame. Hex values like #f5f6f8, #d5f692, etc.")
31 | }).optional().nullish().describe("Updated style configuration of the frame")
32 | },
33 | fn: async ({ boardId, itemId, data, position, geometry, style }: {
34 | boardId: string,
35 | itemId: string,
36 | data?: {
37 | title?: string,
38 | format?: string,
39 | type?: string,
40 | showContent?: boolean
41 | },
42 | position?: {
43 | x: number,
44 | y: number
45 | },
46 | geometry?: {
47 | width?: number,
48 | height?: number
49 | },
50 | style?: {
51 | fillColor?: string
52 | }
53 | }) => {
54 | try {
55 | if (!boardId) {
56 | return ServerResponse.error("Board ID is required");
57 | }
58 |
59 | if (!itemId) {
60 | return ServerResponse.error("Item ID is required");
61 | }
62 |
63 | const updateRequest = new FrameUpdateRequest();
64 |
65 | if (data) {
66 | const frameData = new FrameChanges();
67 |
68 | if (data.title !== undefined) frameData.title = data.title;
69 | if (data.format !== undefined) frameData.format = data.format;
70 | if (data.type !== undefined) frameData.type = data.type;
71 | if (data.showContent !== undefined) frameData.showContent = data.showContent;
72 |
73 | updateRequest.data = frameData;
74 | }
75 |
76 | if (position) {
77 | updateRequest.position = position;
78 | }
79 |
80 | if (geometry) {
81 | updateRequest.geometry = geometry;
82 | }
83 |
84 | if (style) {
85 | updateRequest.style = style;
86 | }
87 |
88 | const result = await MiroClient.getApi().updateFrameItem(boardId, itemId, updateRequest);
89 | return ServerResponse.text(JSON.stringify(result, null, 2));
90 | } catch (error) {
91 | return ServerResponse.error(error);
92 | }
93 | }
94 | }
95 |
96 | export default updateFrameItemTool;
```
--------------------------------------------------------------------------------
/src/tools/updateAppCardItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { AppCardUpdateRequest } from '@mirohq/miro-api/dist/model/appCardUpdateRequest.js';
7 | import { AppCardDataChanges } from '@mirohq/miro-api/dist/model/appCardDataChanges.js';
8 | import { CustomField } from '@mirohq/miro-api/dist/model/customField.js';
9 |
10 | const updateAppCardItemTool: ToolSchema = {
11 | name: "update-app-card-item",
12 | description: "Update an existing app card item on a Miro board",
13 | args: {
14 | boardId: z.string().describe("Unique identifier (ID) of the board that contains the app card"),
15 | itemId: z.string().describe("Unique identifier (ID) of the app card that you want to update"),
16 | data: z.object({
17 | title: z.string().optional().nullish().describe("Updated title of the app card"),
18 | description: z.string().optional().nullish().describe("Updated description of the app card"),
19 | status: z.string().optional().nullish().describe("Updated status text of the app card"),
20 | fields: z.array(z.object({
21 | value: z.string().describe("Value of the field"),
22 | iconShape: z.string().optional().nullish().describe("Shape of the icon"),
23 | fillColor: z.string().optional().nullish().describe("Fill color of the field"),
24 | textColor: z.string().optional().nullish().describe("Color of the text"),
25 | })).optional().nullish().describe("Updated custom fields to display on the app card")
26 | }).optional().nullish().describe("The updated content and configuration of the app card"),
27 | position: z.object({
28 | x: z.number().describe("Updated X coordinate of the app card"),
29 | y: z.number().describe("Updated Y coordinate of the app card")
30 | }).optional().nullish().describe("Updated position of the app card on the board"),
31 | geometry: z.object({
32 | width: z.number().optional().nullish().describe("Updated width of the app card"),
33 | height: z.number().optional().nullish().describe("Updated height of the app card")
34 | }).optional().nullish().describe("Updated dimensions of the app card")
35 | },
36 | fn: async ({ boardId, itemId, data, position, geometry }) => {
37 | try {
38 | if (!boardId) {
39 | return ServerResponse.error("Board ID is required");
40 | }
41 |
42 | if (!itemId) {
43 | return ServerResponse.error("Item ID is required");
44 | }
45 |
46 | const updateRequest = new AppCardUpdateRequest();
47 |
48 | if (data) {
49 | const appCardData = new AppCardDataChanges();
50 |
51 | if (data.title !== undefined) appCardData.title = data.title;
52 | if (data.description !== undefined) appCardData.description = data.description;
53 | if (data.status !== undefined) appCardData.status = data.status;
54 |
55 | if (data.fields) {
56 | appCardData.fields = data.fields.map(field => {
57 | const customField = new CustomField();
58 | customField.value = field.value;
59 | if (field.iconShape) customField.iconShape = field.iconShape;
60 | if (field.fillColor) customField.fillColor = field.fillColor;
61 | if (field.textColor) customField.textColor = field.textColor;
62 | return customField;
63 | });
64 | }
65 |
66 | updateRequest.data = appCardData;
67 | }
68 |
69 | if (position) {
70 | updateRequest.position = position;
71 | }
72 |
73 | if (geometry) {
74 | updateRequest.geometry = geometry;
75 | }
76 |
77 | const result = await MiroClient.getApi().updateAppCardItem(boardId, itemId, updateRequest);
78 |
79 | return ServerResponse.text(JSON.stringify(result, null, 2));
80 | } catch (error) {
81 | return ServerResponse.error(error);
82 | }
83 | }
84 | }
85 |
86 | export default updateAppCardItemTool;
```
--------------------------------------------------------------------------------
/src/tools/createShapeItem.ts:
--------------------------------------------------------------------------------
```typescript
1 | import MiroClient from '../client.js';
2 | import { z } from 'zod';
3 | import { ServerResponse } from '../server-response.js';
4 | import { ToolSchema } from '../tool.js';
5 |
6 | import { ShapeCreateRequest } from '@mirohq/miro-api/dist/model/shapeCreateRequest.js';
7 | import { ShapeData } from '@mirohq/miro-api/dist/model/shapeData.js';
8 |
9 | const validShapeTypes = ['rectangle', 'round_rectangle', 'circle', 'triangle', 'rhombus', 'parallelogram', 'trapezoid', 'pentagon', 'hexagon', 'octagon', 'wedge_round_rectangle_callout', 'star', 'flow_chart_predefined_process', 'cloud', 'cross', 'can', 'right_arrow', 'left_arrow', 'left_right_arrow', 'left_brace', 'right_brace'];
10 |
11 | const createShapeItemTool: ToolSchema = {
12 | name: "create-shape-item",
13 | description: "Create a new shape item on a Miro board",
14 | args: {
15 | boardId: z.string().describe("Unique identifier (ID) of the board where the shape will be created"),
16 | data: z.object({
17 | shape: z.string().describe("Type of the shape (rectangle, circle, triangle, etc.)"),
18 | content: z.string().optional().nullish().describe("Text content to display inside the shape")
19 | }).describe("The content and configuration of the shape"),
20 | position: z.object({
21 | x: z.number().describe("X coordinate of the shape"),
22 | y: z.number().describe("Y coordinate of the shape")
23 | }).describe("Position of the shape on the board"),
24 | geometry: z.object({
25 | width: z.number().describe("Width of the shape"),
26 | height: z.number().describe("Height of the shape"),
27 | rotation: z.number().optional().nullish().describe("Rotation angle of the shape")
28 | }).describe("Dimensions of the shape"),
29 | style: z.object({
30 | borderColor: z.string().optional().nullish().describe("Color of the shape border (hex format, e.g. #000000)"),
31 | borderWidth: z.number().optional().nullish().describe("Width of the shape border"),
32 | borderStyle: z.string().optional().nullish().describe("Style of the shape border (normal, dashed, etc.)"),
33 | borderOpacity: z.number().optional().nullish().describe("Opacity of the shape border (0-1)"),
34 | fillColor: z.string().optional().nullish().describe("Fill color of the shape (hex format, e.g. #000000)"),
35 | fillOpacity: z.number().optional().nullish().describe("Opacity of the shape fill (0-1)"),
36 | color: z.string().optional().nullish().describe("Color of the text in the shape (hex format, e.g. #000000)")
37 | }).optional().nullish().describe("Style configuration of the shape")
38 | },
39 | fn: async ({ boardId, data, position, geometry, style }) => {
40 | try {
41 | if (!boardId) {
42 | return ServerResponse.error("Board ID is required");
43 | }
44 |
45 | if (!validShapeTypes.includes(data.type)) {
46 | return ServerResponse.error("Invalid shape type. Valid types are: " + validShapeTypes.join(", "));
47 | }
48 |
49 | const createRequest = new ShapeCreateRequest();
50 |
51 | const shapeData = new ShapeData();
52 | // Set shape type via property assignment
53 | (shapeData as any).type = data.type;
54 |
55 | if (data.content !== undefined) {
56 | shapeData.content = data.content;
57 | }
58 |
59 | createRequest.data = shapeData;
60 |
61 | const completePosition = {
62 | ...position,
63 | origin: position.origin || "center",
64 | relativeTo: position.relativeTo || "canvas_center"
65 | };
66 |
67 | createRequest.position = completePosition;
68 | createRequest.geometry = geometry;
69 |
70 | if (style) {
71 | createRequest.style = style as Record<string, any>;
72 | }
73 |
74 | const result = await MiroClient.getApi().createShapeItem(boardId, createRequest);
75 | return ServerResponse.text(JSON.stringify(result, null, 2));
76 | } catch (error) {
77 | return ServerResponse.error(error);
78 | }
79 | }
80 | }
81 |
82 | export default createShapeItemTool;
```