#
tokens: 6286/50000 14/14 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── .env.example
├── .gitignore
├── Dockerfile
├── LICENSE
├── package.json
├── README.md
├── smithery.yaml
├── src
│   ├── api
│   │   └── LottieApiClient.ts
│   ├── error
│   │   └── ErrorHandler.ts
│   ├── handlers
│   │   ├── PromptHandler.ts
│   │   ├── ResourceHandler.ts
│   │   └── ToolHandler.ts
│   ├── index.ts
│   └── types.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------

```
1 | LOTTIEFILES_API_URL=https://lottiefiles.com/api
```

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
 1 | # Dependencies
 2 | node_modules/
 3 | package-lock.json
 4 | 
 5 | # Build output
 6 | dist/
 7 | 
 8 | # Environment variables
 9 | .env
10 | 
11 | # IDE files
12 | .vscode/
13 | .idea/
14 | 
15 | # Logs
16 | *.log
17 | npm-debug.log*
18 | 
19 | # OS files
20 | .DS_Store
21 | Thumbs.db 
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
 1 | # LottieFiles MCP Server
 2 | [![smithery badge](https://smithery.ai/badge/mcp-server-lottiefiles)](https://smithery.ai/server/mcp-server-lottiefiles)
 3 | 
 4 | A Model Context Protocol (MCP) server for searching and retrieving Lottie animations from LottieFiles.
 5 | 
 6 | ## Features
 7 | 
 8 | - Search Lottie animations
 9 | - Get animation details
10 | - Get popular animations list
11 | 
12 | ## Installation
13 | 
14 | ### Installing via Smithery
15 | 
16 | To install LottieFiles Server for Claude Desktop automatically via [Smithery](https://smithery.ai/server/mcp-server-lottiefiles):
17 | 
18 | ```bash
19 | npx -y smithery install mcp-server-lottiefiles --client claude
20 | ```
21 | 
22 | ### Manual Installation
23 | ```bash
24 | npm install
25 | ```
26 | 
27 | ## Usage
28 | 
29 | 1. Start the server:
30 | 
31 | ```bash
32 | npm start
33 | ```
34 | 
35 | 2. Connect using an MCP client
36 | 
37 | ## API Tools
38 | 
39 | ### Search Animations
40 | 
41 | Search for Lottie animations by keywords.
42 | 
43 | Parameters:
44 | - `query`: Search keywords
45 | - `page`: Page number (optional, default: 1)
46 | - `limit`: Items per page (optional, default: 20)
47 | 
48 | ### Get Animation Details
49 | 
50 | Get detailed information about a specific Lottie animation.
51 | 
52 | Parameters:
53 | - `id`: Unique identifier of the animation
54 | 
55 | ### Get Popular Animations
56 | 
57 | Get a list of currently popular Lottie animations.
58 | 
59 | Parameters:
60 | - `page`: Page number (optional, default: 1)
61 | - `limit`: Items per page (optional, default: 20)
62 | 
63 | ## Development
64 | 
65 | ```bash
66 | # Build
67 | npm run build
68 | ```
69 | 
70 | ## License
71 | 
72 | MIT
73 | 
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2020",
 4 |     "module": "ESNext",
 5 |     "moduleResolution": "node",
 6 |     "esModuleInterop": true,
 7 |     "strict": true,
 8 |     "skipLibCheck": true,
 9 |     "forceConsistentCasingInFileNames": true,
10 |     "outDir": "./dist",
11 |     "rootDir": "./src",
12 |     "declaration": true
13 |   },
14 |   "include": ["src/**/*"],
15 |   "exclude": ["node_modules", "dist"]
16 | } 
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "mcp-server-lottiefiles",
 3 |   "version": "1.0.3",
 4 |   "type": "module",
 5 |   "main": "dist/index.js",
 6 |   "bin": {
 7 |     "mcp-server-lottiefiles": "dist/index.js"
 8 |   },
 9 |   "scripts": {
10 |     "build": "tsc",
11 |     "start": "node dist/index.js"
12 |   },
13 |   "dependencies": {
14 |     "@modelcontextprotocol/sdk": "^1.7.0",
15 |     "axios": "^1.7.9",
16 |     "dotenv": "^16.4.7"
17 |   },
18 |   "devDependencies": {
19 |     "@types/dotenv": "^8.2.3",
20 |     "@types/node": "^18.19.80",
21 |     "typescript": "^5.0.0"
22 |   }
23 | }
24 | 
```

--------------------------------------------------------------------------------
/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 |     properties: {}
 9 |     default: {}
10 |     description: No configuration needed for the LottieFiles MCP server
11 |   commandFunction:
12 |     # A JS function that produces the CLI command based on the given config to start the MCP on stdio.
13 |     |-
14 |     (config) => ({ command: 'node', args: ['dist/index.js'], env: {} })
15 |   exampleConfig: {}
16 | 
```

--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
 1 | # Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
 2 | # Dockerfile for LottieFiles MCP Server
 3 | FROM node:lts-alpine AS builder
 4 | WORKDIR /app
 5 | 
 6 | # Copy package files and typescript config
 7 | COPY package.json package-lock.json* tsconfig.json ./
 8 | 
 9 | # Copy source
10 | COPY src ./src
11 | 
12 | # Install dependencies and build
13 | RUN npm install --ignore-scripts && npm run build
14 | 
15 | # Runtime image
16 | FROM node:lts-alpine AS runtime
17 | WORKDIR /app
18 | 
19 | # Copy only built files and dependencies
20 | COPY --from=builder /app/dist ./dist
21 | COPY --from=builder /app/node_modules ./node_modules
22 | 
23 | # Copy package.json for completeness
24 | COPY package.json ./
25 | 
26 | # Default command
27 | CMD ["node", "dist/index.js"]
28 | 
```

--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------

```typescript
 1 | export interface LottieAnimation {
 2 |   id: string;
 3 |   name: string;
 4 |   description: string;
 5 |   previewUrl: string;
 6 |   downloadUrl: string;
 7 |   tags: string[];
 8 |   createdAt: string;
 9 |   updatedAt: string;
10 | }
11 | 
12 | export interface SearchAnimationsParams {
13 |   query: string;
14 |   page?: number;
15 |   limit?: number;
16 | }
17 | 
18 | export interface GetAnimationParams {
19 |   id: string;
20 | }
21 | 
22 | export interface GetPopularAnimationsParams {
23 |   page?: number;
24 |   limit?: number;
25 | }
26 | 
27 | export interface SearchAnimationsResponse {
28 |   animations: LottieAnimation[];
29 |   total: number;
30 |   page: number;
31 |   limit: number;
32 | }
33 | 
34 | export interface GetPopularAnimationsResponse {
35 |   animations: LottieAnimation[];
36 |   total: number;
37 |   page: number;
38 |   limit: number;
39 | }
40 | 
41 | export interface Prompt {
42 |   name: string;
43 |   description: string;
44 |   arguments: Array<{
45 |     name: string;
46 |     description: string;
47 |     required: boolean;
48 |   }>;
49 | } 
```

--------------------------------------------------------------------------------
/src/error/ErrorHandler.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
 2 | import axios from "axios";
 3 | 
 4 | export class ErrorHandler {
 5 |   static handleError(error: unknown): never {
 6 |     if (axios.isAxiosError(error)) {
 7 |       throw new McpError(
 8 |         ErrorCode.InternalError,
 9 |         `LottieFiles API error: ${error.response?.data?.message || error.message}`
10 |       );
11 |     }
12 | 
13 |     if (error instanceof McpError) {
14 |       throw error;
15 |     }
16 | 
17 |     if (error instanceof Error) {
18 |       throw new McpError(
19 |         ErrorCode.InternalError,
20 |         error.message
21 |       );
22 |     }
23 | 
24 |     throw new McpError(
25 |       ErrorCode.InternalError,
26 |       'An unknown error occurred'
27 |     );
28 |   }
29 | 
30 |   static validateRequiredParam(param: unknown, paramName: string): void {
31 |     if (param === undefined || param === null) {
32 |       throw new McpError(
33 |         ErrorCode.InvalidRequest,
34 |         `Missing required parameter: ${paramName}`
35 |       );
36 |     }
37 |   }
38 | } 
```

--------------------------------------------------------------------------------
/src/handlers/ResourceHandler.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { LottieApiClient } from '../api/LottieApiClient.js';
 2 | import { ListResourcesRequest, ReadResourceRequest } from '@modelcontextprotocol/sdk/types.js';
 3 | 
 4 | export class ResourceHandler {
 5 |   constructor(private apiClient: LottieApiClient) {
 6 |     this.apiClient = apiClient;
 7 |   }
 8 | 
 9 |   async listResources(request: ListResourcesRequest) {
10 |     return {
11 |       resources: [{
12 |         uri: "lottiefiles://resources/popular",
13 |         name: "popular",
14 |         mimeType: "application/json",
15 |         description: "Popular Lottie animations"
16 |       }]
17 |     };
18 |   }
19 | 
20 |   async readResource(request: ReadResourceRequest) {
21 |     const { name, uri } = request.params;
22 | 
23 |     switch (name) {
24 |       case "popular": {
25 |         const popularList = await this.apiClient.getPopularAnimations(
26 |           request.params.page as number,
27 |           request.params.limit as number
28 |         );
29 |         return {
30 |           contents: [{
31 |             uri,
32 |             mimeType: "application/json",
33 |             text: JSON.stringify(popularList, null, 2)
34 |           }]
35 |         };
36 |       }
37 | 
38 |       default:
39 |         throw new Error(`Unknown resource: ${name}`);
40 |     }
41 |   }
42 | } 
```

--------------------------------------------------------------------------------
/src/handlers/PromptHandler.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpError, ErrorCode, ListPromptsRequest, GetPromptRequest } from "@modelcontextprotocol/sdk/types.js";
 2 | import { Prompt } from "../types.js";
 3 | 
 4 | export class PromptHandler {
 5 | 
 6 |   async listPrompts(request: ListPromptsRequest) {
 7 |     return {
 8 |       prompts: [
 9 |         {
10 |           name: "search_animations",
11 |           description: "Search for Lottie animations",
12 |           inputSchema: {
13 |             type: "object",
14 |             properties: {
15 |               query: {
16 |                 type: "string",
17 |                 description: "Search keywords"
18 |               }
19 |             }
20 |           }
21 |         },
22 |         {
23 |           name: "get_popular_animations",
24 |           description: "Get popular Lottie animations",
25 |           inputSchema: {
26 |             type: "object",
27 |             properties: {}
28 |           }
29 |         }
30 |       ]
31 |     };
32 |   }
33 | 
34 |   async getPrompt(request: GetPromptRequest) {
35 |     const { name, arguments: args } = request.params;
36 | 
37 |     switch (name) {
38 |       case "search_animations":
39 |         return {
40 |           prompt: `Please help me search for Lottie animations related to "${args?.query}".`,
41 |           tools: ["search_animations"]
42 |         };
43 | 
44 |       case "get_popular_animations":
45 |         return {
46 |           prompt: "Please help me get the most popular Lottie animations.",
47 |           tools: ["get_popular_animations"]
48 |         };
49 | 
50 |       default:
51 |         throw new Error(`Unknown prompt: ${name}`);
52 |     }
53 |   }
54 | 
55 | } 
```

--------------------------------------------------------------------------------
/src/api/LottieApiClient.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import axios from "axios";
  2 | export class LottieApiClient {
  3 |   private baseUrl: string;
  4 |   private axiosInstance: any;
  5 | 
  6 |   constructor() {
  7 |     this.baseUrl =
  8 |       process.env.LOTTIEFILES_API_URL || "https://lottiefiles.com/api";
  9 |     this.axiosInstance = axios.create({
 10 |       baseURL: this.baseUrl,
 11 |       params: {
 12 |         format: "json",
 13 |       },
 14 |     });
 15 |   }
 16 | 
 17 |   async searchAnimations(query: string, page: number = 1, limit: number = 20) {
 18 |     try {
 19 |       const response = await this.axiosInstance.get(
 20 |         `${this.baseUrl}/search/get-animations`,
 21 |         {
 22 |           params: {
 23 |             query,
 24 |             page,
 25 |             limit,
 26 |           },
 27 |         }
 28 |       );
 29 |       return response.data.data.data;
 30 |     } catch (error) {
 31 |       if (error instanceof Error) {
 32 |         throw new Error(`Failed to search animations: ${error.message}`);
 33 |       }
 34 |       throw new Error("Failed to search animations: Unknown error");
 35 |     }
 36 |   }
 37 | 
 38 |   async getAnimationById(id: string) {
 39 |     try {
 40 |       const response = await this.axiosInstance.get(
 41 |         `${this.baseUrl}/animations/get-animation-data`,
 42 |         {
 43 |           params: {
 44 |             fileId: id,
 45 |           },
 46 |         }
 47 |       );
 48 | 
 49 |       return response.data;
 50 |     } catch (error) {
 51 |       if (error instanceof Error) {
 52 |         throw new Error(`Failed to get animation: ${error.message}`);
 53 |       }
 54 |       throw new Error("Failed to get animation: Unknown error");
 55 |     }
 56 |   }
 57 | 
 58 |   async getAnimationByUser(user: string, page: number = 1, limit: number = 20) {
 59 |     try {
 60 |       const response = await this.axiosInstance.get(
 61 |         `${this.baseUrl}/search/get-users`,
 62 |         {
 63 |           params: {
 64 |             query: user,
 65 |             page,
 66 |             limit,
 67 |           },
 68 |         }
 69 |       );
 70 |       return response.data;
 71 |     } catch (error) {
 72 |       if (error instanceof Error) {
 73 |         throw new Error(`Failed to get animation: ${error.message}`);
 74 |       }
 75 |       throw new Error("Failed to get animation: Unknown error");
 76 |     }
 77 |   }
 78 | 
 79 |   async getPopularAnimations(page: number = 1, limit: number = 20) {
 80 |     try {
 81 |       const response = await this.axiosInstance.get(
 82 |         `${this.baseUrl}/iconscout/popular-animations-weekly?api=%26sort%3Dpopular`,
 83 |         {
 84 |           params: {
 85 |             page,
 86 |             limit,
 87 |           },
 88 |         }
 89 |       );
 90 | 
 91 |       return response.data.popularWeeklyData.data;
 92 |     } catch (error) {
 93 |       if (error instanceof Error) {
 94 |         throw new Error(`Failed to get popular animations: ${error.message}`);
 95 |       }
 96 |       throw new Error("Failed to get popular animations: Unknown error");
 97 |     }
 98 |   }
 99 | }
100 | 
```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | #!/usr/bin/env node
  2 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
  3 | import {
  4 |   ListToolsRequestSchema,
  5 |   CallToolRequestSchema,
  6 |   ListResourcesRequestSchema,
  7 |   ReadResourceRequestSchema,
  8 |   ListPromptsRequestSchema,
  9 |   GetPromptRequestSchema,
 10 | } from "@modelcontextprotocol/sdk/types.js";
 11 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
 12 | import dotenv from "dotenv";
 13 | 
 14 | import { LottieApiClient } from "./api/LottieApiClient.js";
 15 | import { ToolHandler } from "./handlers/ToolHandler.js";
 16 | import { ResourceHandler } from "./handlers/ResourceHandler.js";
 17 | import { PromptHandler } from "./handlers/PromptHandler.js";
 18 | import { ErrorHandler } from "./error/ErrorHandler.js";
 19 | class LottieServer {
 20 |   private readonly server: Server;
 21 |   private readonly apiClient: LottieApiClient;
 22 |   private readonly toolHandler: ToolHandler;
 23 |   private readonly resourceHandler: ResourceHandler;
 24 |   private readonly promptHandler: PromptHandler;
 25 | 
 26 |   constructor() {
 27 |     // Load environment variables
 28 |     dotenv.config();
 29 | 
 30 |     // Initialize API client
 31 |     this.apiClient = new LottieApiClient();
 32 | 
 33 |     // Initialize handlers
 34 |     this.toolHandler = new ToolHandler(this.apiClient);
 35 |     this.resourceHandler = new ResourceHandler(this.apiClient);
 36 |     this.promptHandler = new PromptHandler();
 37 | 
 38 |     // Initialize server with configuration
 39 |     this.server = this.initializeServer();
 40 | 
 41 |     // Setup handlers and error handling
 42 |     this.setupHandlers();
 43 |     this.setupErrorHandling();
 44 |   }
 45 | 
 46 |   private initializeServer(): Server {
 47 |     return new Server(
 48 |       {
 49 |         name: "lottiefiles-server",
 50 |         version: "1.0.0",
 51 |       },
 52 |       {
 53 |         capabilities: {
 54 |           tools: {},
 55 |           resources: {
 56 |             list: true,
 57 |             read: true,
 58 |             subscribe: false,
 59 |           },
 60 |           prompts: {
 61 |             list: true,
 62 |             get: true,
 63 |           },
 64 |         },
 65 |       }
 66 |     );
 67 |   }
 68 | 
 69 |   private setupErrorHandling(): void {
 70 |     this.server.onerror = (error) => {
 71 |       console.error("[MCP Error]", error);
 72 |     };
 73 |     process.on("SIGINT", async () => {
 74 |       await this.server.close();
 75 |       process.exit(0);
 76 |     });
 77 |   }
 78 | 
 79 |   private setupHandlers(): void {
 80 |     // Tool handlers
 81 |     this.server.setRequestHandler(ListToolsRequestSchema, async (request) => {
 82 |       return await this.toolHandler.listTools(request);
 83 |     });
 84 | 
 85 |     this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
 86 |       return await this.toolHandler.callTool(request);
 87 |     });
 88 | 
 89 |     // Resource handlers
 90 |     this.server.setRequestHandler(
 91 |       ListResourcesRequestSchema,
 92 |       async (request) => {
 93 |         return await this.resourceHandler.listResources(request);
 94 |       }
 95 |     );
 96 | 
 97 |     this.server.setRequestHandler(
 98 |       ReadResourceRequestSchema,
 99 |       async (request) => {
100 |         return await this.resourceHandler.readResource(request);
101 |       }
102 |     );
103 | 
104 |     // Prompt handlers
105 |     this.server.setRequestHandler(ListPromptsRequestSchema, async (request) => {
106 |       return await this.promptHandler.listPrompts(request);
107 |     });
108 | 
109 |     this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
110 |       return await this.promptHandler.getPrompt(request);
111 |     });
112 |   }
113 | 
114 |   async run(): Promise<void> {
115 |     const transport = new StdioServerTransport();
116 |     await this.server.connect(transport);
117 |   }
118 | }
119 | 
120 | // Start the server
121 | const server = new LottieServer();
122 | server.run().catch((error) => {
123 |   ErrorHandler.handleError(error);
124 | });
125 | 
```

--------------------------------------------------------------------------------
/src/handlers/ToolHandler.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import {
  2 |   CallToolRequest,
  3 |   ListToolsRequest,
  4 | } from "@modelcontextprotocol/sdk/types.js";
  5 | import { LottieApiClient } from "../api/LottieApiClient.js";
  6 | export class ToolHandler {
  7 |   constructor(private apiClient: LottieApiClient) {
  8 |     this.apiClient = apiClient;
  9 |   }
 10 | 
 11 |   async listTools(request: ListToolsRequest) {
 12 |     return {
 13 |       tools: [
 14 |         {
 15 |           name: "search_animations",
 16 |           description:
 17 |             "Search for Lottie animations by keywords, tags, and other criteria. Supports pagination.",
 18 |           inputSchema: {
 19 |             type: "object",
 20 |             properties: {
 21 |               query: {
 22 |                 type: "string",
 23 |                 description:
 24 |                   "Search keywords that match animation names, descriptions, tags, etc.",
 25 |               },
 26 |               page: {
 27 |                 type: "integer",
 28 |                 description: "Page number, starting from 1",
 29 |                 minimum: 1,
 30 |                 default: 1,
 31 |               },
 32 |               limit: {
 33 |                 type: "integer",
 34 |                 description: "Number of items per page",
 35 |                 minimum: 1,
 36 |                 maximum: 100,
 37 |                 default: 20,
 38 |               },
 39 |             },
 40 |           },
 41 |         },
 42 |         {
 43 |           name: "get_animation_details",
 44 |           description:
 45 |             "Get detailed information about a specific Lottie animation, including animation data, preview images, and tags.",
 46 |           inputSchema: {
 47 |             type: "object",
 48 |             properties: {
 49 |               id: {
 50 |                 type: "string",
 51 |                 description: "Unique identifier of the animation",
 52 |               },
 53 |             },
 54 |             required: ["id"],
 55 |           },
 56 |         },
 57 |         {
 58 |           name: "get_popular_animations",
 59 |           description: "Get a list of currently popular Lottie animations.",
 60 |           inputSchema: {
 61 |             type: "object",
 62 |             properties: {
 63 |               page: {
 64 |                 type: "integer",
 65 |                 description: "Page number, starting from 1",
 66 |                 minimum: 1,
 67 |                 default: 1,
 68 |               },
 69 |               limit: {
 70 |                 type: "integer",
 71 |                 description: "Number of items per page",
 72 |                 minimum: 1,
 73 |                 maximum: 100,
 74 |                 default: 20,
 75 |               },
 76 |             },
 77 |           },
 78 |         },
 79 |       ],
 80 |     };
 81 |   }
 82 | 
 83 |   async callTool(request: CallToolRequest) {
 84 |     const { name, arguments: args } = request.params;
 85 | 
 86 |     switch (name) {
 87 |       case "search_animations":
 88 |         const list = await this.apiClient.searchAnimations(
 89 |           args?.query as string,
 90 |           args?.page as number,
 91 |           args?.limit as number
 92 |         );
 93 | 
 94 |         return {
 95 |           content: [
 96 |             {
 97 |               type: "text",
 98 |               text: JSON.stringify(
 99 |                 {
100 |                   count: list.length,
101 |                   animations: list,
102 |                 },
103 |                 null,
104 |                 2
105 |               ),
106 |             },
107 |           ],
108 |         };
109 | 
110 |       case "get_animation_details":
111 |         const details = await this.apiClient.getAnimationById(
112 |           args?.id as string
113 |         );
114 | 
115 |         return {
116 |           content: [
117 |             {
118 |               type: "text",
119 |               text: JSON.stringify(details, null, 2),
120 |             },
121 |           ],
122 |         };
123 | 
124 |       case "get_popular_animations":
125 |         const popular = await this.apiClient.getPopularAnimations(
126 |           args?.page as number,
127 |           args?.limit as number
128 |         );
129 |         return {
130 |           content: [
131 |             {
132 |               type: "text",
133 |               text: JSON.stringify(
134 |                 {
135 |                   count: popular.length,
136 |                   popular: popular,
137 |                 },
138 |                 null,
139 |                 2
140 |               ),
141 |             },
142 |           ],
143 |         };
144 | 
145 |       default:
146 |         throw new Error(`Unknown tool: ${name}`);
147 |     }
148 |   }
149 | }
150 | 
```