#
tokens: 49096/50000 105/110 files (page 1/2)
lines: on (toggle) GitHub
raw markdown copy reset
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 | [![Trust Score](https://archestra.ai/mcp-catalog/api/badge/quality/k-jarzyna/mcp-miro)](https://archestra.ai/mcp-catalog/k-jarzyna__mcp-miro)
  4 | [![smithery badge](https://smithery.ai/badge/@k-jarzyna/mcp-miro)](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;
```
Page 1/2FirstPrevNextLast