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

```
├── .gitignore
├── package-lock.json
├── package.json
├── readme.md
├── src
│   └── index.ts
└── tsconfig.json
```

# Files

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

```
1 | /node_modules
2 | /build
```

--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Swagger/OpenAPI MCP Server
  2 | 
  3 | A Model Context Protocol (MCP) server that allows LLMs to explore and interact with Swagger/OpenAPI specifications. This server provides tools and resources for loading API specifications, browsing endpoints, and getting detailed information about API operations.
  4 | 
  5 | ## Installation
  6 | 
  7 | 1. Clone or create the project directory
  8 | 2. Install dependencies:
  9 | 
 10 | ```bash
 11 | npm install
 12 | ```
 13 | 
 14 | 3. Build the TypeScript code:
 15 | 
 16 | ```bash
 17 | npm run build
 18 | ```
 19 | 
 20 | ## Usage
 21 | 
 22 | 
 23 | ### Available Tools
 24 | 
 25 | #### `load_api`
 26 | Load an OpenAPI/Swagger specification into the server.
 27 | 
 28 | **Parameters:**
 29 | - `apiId` (string): Unique identifier for this API
 30 | - `source` (string): URL or file path to the OpenAPI/Swagger specification
 31 | 
 32 | **Example:**
 33 | ```json
 34 | {
 35 |   "name": "load_api",
 36 |   "arguments": {
 37 |     "apiId": "petstore",
 38 |     "source": "https://petstore.swagger.io/v2/swagger.json"
 39 |   }
 40 | }
 41 | ```
 42 | 
 43 | #### `get_endpoint_details`
 44 | Get detailed information about a specific API endpoint.
 45 | 
 46 | **Parameters:**
 47 | - `apiId` (string): ID of the loaded API
 48 | - `method` (string): HTTP method (GET, POST, etc.)
 49 | - `path` (string): API endpoint path
 50 | - `natural` (boolean, optional): If true, returns a human-readable summary
 51 | 
 52 | **Example:**
 53 | ```json
 54 | {
 55 |   "name": "get_endpoint_details",
 56 |   "arguments": {
 57 |     "apiId": "petstore",
 58 |     "method": "GET",
 59 |     "path": "/pet/{petId}",
 60 |     "natural": true
 61 |   }
 62 | }
 63 | ```
 64 | 
 65 | #### `list_apis`
 66 | List all currently loaded API specifications.
 67 | 
 68 | **Parameters:** None
 69 | 
 70 | #### `search_endpoints`
 71 | Search for endpoints matching a specific pattern.
 72 | 
 73 | **Parameters:**
 74 | - `apiId` (string): ID of the loaded API
 75 | - `pattern` (string): Search pattern for endpoint paths or descriptions
 76 | 
 77 | **Example:**
 78 | ```json
 79 | {
 80 |   "name": "search_endpoints",
 81 |   "arguments": {
 82 |     "apiId": "petstore",
 83 |     "pattern": "pet"
 84 |   }
 85 | }
 86 | ```
 87 | 
 88 | ### Available Resources
 89 | 
 90 | #### `swagger://{apiId}/load`
 91 | Get overview information about a loaded API specification.
 92 | 
 93 | #### `swagger://{apiId}/endpoints`
 94 | Get a list of all available endpoints for an API.
 95 | 
 96 | #### `swagger://{apiId}/endpoint/{method}/{path}`
 97 | Get detailed information about a specific endpoint.
 98 | 
 99 | ## Configuration with Claude Desktop
100 | 
101 | To use this server with Claude Desktop, add the following to your `claude_desktop_config.json`:
102 | 
103 | ```json
104 | {
105 |   "mcpServers": {
106 |     "swagger-explorer": {
107 |       "command": "node",
108 |       "args": ["/path/to/your/swagger-mcp-server/build/index.js"]
109 |     }
110 |   }
111 | }
112 | ```
113 | 
114 | Replace `/path/to/your/swagger-mcp-server` with the actual path to your project directory.
115 | 
116 | 
117 | ## License
118 | 
119 | MIT License
120 | 
```

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

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2022",
 4 |     "module": "Node16",
 5 |     "moduleResolution": "Node16",
 6 |     "outDir": "./build",
 7 |     "rootDir": "./src",
 8 |     "strict": true,
 9 |     "esModuleInterop": true,
10 |     "skipLibCheck": true,
11 |     "forceConsistentCasingInFileNames": true,
12 |     "allowSyntheticDefaultImports": true,
13 |     "resolveJsonModule": true,
14 |     "declaration": true,
15 |     "declarationMap": true,
16 |     "sourceMap": true
17 |   },
18 |   "include": [
19 |     "src/**/*"
20 |   ],
21 |   "exclude": [
22 |     "node_modules",
23 |     "build"
24 |   ]
25 | }
```

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

```json
 1 | {
 2 |   "name": "swagger-mcp-server",
 3 |   "version": "1.0.0",
 4 |   "description": "MCP Server for exploring Swagger/OpenAPI specifications",
 5 |   "main": "build/index.js",
 6 |   "bin": {
 7 |     "swagger-mcp-server": "./build/index.js"
 8 |   },
 9 |   "scripts": {
10 |     "build": "tsc && chmod 755 build/index.js",
11 |     "dev": "tsc && node build/index.js",
12 |     "start": "node build/index.js",
13 |     "watch": "tsc --watch"
14 |   },
15 |   "dependencies": {
16 |     "@modelcontextprotocol/sdk": "^1.0.0",
17 |     "@apidevtools/swagger-parser": "^10.1.0",
18 |     "openapi-types": "^12.1.3",
19 |     "zod": "^3.23.8"
20 |   },
21 |   "devDependencies": {
22 |     "@types/node": "^20.10.0",
23 |     "typescript": "^5.3.0"
24 |   },
25 |   "keywords": [
26 |     "mcp",
27 |     "model-context-protocol",
28 |     "swagger",
29 |     "openapi",
30 |     "api",
31 |     "documentation"
32 |   ],
33 |   "author": "Your Name",
34 |   "license": "MIT",
35 |   "files": [
36 |     "build/"
37 |   ],
38 |   "engines": {
39 |     "node": ">=18.0.0"
40 |   }
41 | }
```

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

```typescript
  1 | import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | import SwaggerParser from "@apidevtools/swagger-parser";
  5 | import { OpenAPIV3 } from "openapi-types";
  6 | 
  7 | interface ParsedAPI {
  8 |   spec: OpenAPIV3.Document;
  9 |   parser: SwaggerParser;
 10 | }
 11 | 
 12 | class SwaggerMCPServer {
 13 |   private server: McpServer;
 14 |   private apis: Map<string, ParsedAPI> = new Map();
 15 | 
 16 |   constructor() {
 17 |     this.server = new McpServer({
 18 |       name: "swagger-api-explorer",
 19 |       version: "1.0.0"
 20 |     });
 21 | 
 22 |     this.setupResources();
 23 |     this.setupTools();
 24 |   }
 25 | 
 26 |   private setupResources() {
 27 |     // Resource for loading and caching API specifications
 28 |     this.server.resource(
 29 |       "load-api",
 30 |       new ResourceTemplate("swagger://{apiId}/load", { list: undefined }),
 31 |       async (uri, params) => {
 32 |         try {
 33 |           // Handle both string and string[] cases
 34 |           const apiId = Array.isArray(params.apiId) ? params.apiId[0] : params.apiId;
 35 |           
 36 |           if (!this.apis.has(apiId)) {
 37 |             return {
 38 |               contents: [{
 39 |                 uri: uri.href,
 40 |                 text: `API with ID '${apiId}' not loaded. Use the load_api tool first.`,
 41 |                 mimeType: "text/plain"
 42 |               }]
 43 |             };
 44 |           }
 45 | 
 46 |           const api = this.apis.get(apiId)!;
 47 |           return {
 48 |             contents: [{
 49 |               uri: uri.href,
 50 |               text: JSON.stringify({
 51 |                 info: api.spec.info,
 52 |                 servers: api.spec.servers,
 53 |                 paths: Object.keys(api.spec.paths || {}),
 54 |                 components: Object.keys(api.spec.components?.schemas || {})
 55 |               }, null, 2),
 56 |               mimeType: "application/json"
 57 |             }]
 58 |           };
 59 |         } catch (error) {
 60 |           return {
 61 |             contents: [{
 62 |               uri: uri.href,
 63 |               text: `Error accessing API: ${error instanceof Error ? error.message : String(error)}`,
 64 |               mimeType: "text/plain"
 65 |             }]
 66 |           };
 67 |         }
 68 |       }
 69 |     );
 70 | 
 71 |     // Resource for getting all available endpoints
 72 |     this.server.resource(
 73 |       "endpoints",
 74 |       new ResourceTemplate("swagger://{apiId}/endpoints", { list: undefined }),
 75 |       async (uri, params) => {
 76 |         try {
 77 |           const apiId = Array.isArray(params.apiId) ? params.apiId[0] : params.apiId;
 78 |           const api = this.apis.get(apiId);
 79 |           if (!api) {
 80 |             return {
 81 |               contents: [{
 82 |                 uri: uri.href,
 83 |                 text: `API with ID '${apiId}' not found`,
 84 |                 mimeType: "text/plain"
 85 |               }]
 86 |             };
 87 |           }
 88 | 
 89 |           const endpoints: Array<{method: string, path: string, summary?: string}> = [];
 90 |           
 91 |           Object.entries(api.spec.paths || {}).forEach(([path, pathItem]) => {
 92 |             if (!pathItem) return;
 93 |             
 94 |             ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'].forEach(method => {
 95 |               const operation = (pathItem as any)[method] as OpenAPIV3.OperationObject;
 96 |               if (operation) {
 97 |                 endpoints.push({
 98 |                   method: method.toUpperCase(),
 99 |                   path,
100 |                   summary: operation.summary
101 |                 });
102 |               }
103 |             });
104 |           });
105 | 
106 |           return {
107 |             contents: [{
108 |               uri: uri.href,
109 |               text: JSON.stringify(endpoints, null, 2),
110 |               mimeType: "application/json"
111 |             }]
112 |           };
113 |         } catch (error) {
114 |           return {
115 |             contents: [{
116 |               uri: uri.href,
117 |               text: `Error getting endpoints: ${error instanceof Error ? error.message : String(error)}`,
118 |               mimeType: "text/plain"
119 |             }]
120 |           };
121 |         }
122 |       }
123 |     );
124 | 
125 |     // Resource for getting specific endpoint details
126 |     this.server.resource(
127 |       "endpoint-detail",
128 |       new ResourceTemplate("swagger://{apiId}/endpoint/{method}/{path}", { list: undefined }),
129 |       async (uri, params) => {
130 |         try {
131 |           const apiId = Array.isArray(params.apiId) ? params.apiId[0] : params.apiId;
132 |           const method = Array.isArray(params.method) ? params.method[0] : params.method;
133 |           const path = Array.isArray(params.path) ? params.path[0] : params.path;
134 |           
135 |           const api = this.apis.get(apiId);
136 |           if (!api) {
137 |             return {
138 |               contents: [{
139 |                 uri: uri.href,
140 |                 text: `API with ID '${apiId}' not found`,
141 |                 mimeType: "text/plain"
142 |               }]
143 |             };
144 |           }
145 | 
146 |           const decodedPath = decodeURIComponent(path);
147 |           const pathItem = api.spec.paths?.[decodedPath];
148 |           if (!pathItem) {
149 |             return {
150 |               contents: [{
151 |                 uri: uri.href,
152 |                 text: `Path '${decodedPath}' not found in API`,
153 |                 mimeType: "text/plain"
154 |               }]
155 |             };
156 |           }
157 | 
158 |           const operation = (pathItem as any)[method.toLowerCase()] as OpenAPIV3.OperationObject;
159 |           if (!operation) {
160 |             return {
161 |               contents: [{
162 |                 uri: uri.href,
163 |                 text: `Method '${method}' not found for path '${decodedPath}'`,
164 |                 mimeType: "text/plain"
165 |               }]
166 |             };
167 |           }
168 | 
169 |           const endpointDetails = this.formatEndpointDetails(operation, decodedPath, method.toUpperCase());
170 | 
171 |           return {
172 |             contents: [{
173 |               uri: uri.href,
174 |               text: JSON.stringify(endpointDetails, null, 2),
175 |               mimeType: "application/json"
176 |             }]
177 |           };
178 |         } catch (error) {
179 |           return {
180 |             contents: [{
181 |               uri: uri.href,
182 |               text: `Error getting endpoint details: ${error instanceof Error ? error.message : String(error)}`,
183 |               mimeType: "text/plain"
184 |             }]
185 |           };
186 |         }
187 |       }
188 |     );
189 |   }
190 | 
191 |   private setupTools() {
192 |     // Tool to load an API specification
193 |     this.server.tool(
194 |       "load_api",
195 |       {
196 |         apiId: z.string().describe("Unique identifier for this API"),
197 |         source: z.string().describe("URL or file path to the OpenAPI/Swagger specification")
198 |       },
199 |       async ({ apiId, source }) => {
200 |         try {
201 |           console.error(`Loading API from: ${source}`);
202 |           
203 |           const parser = new SwaggerParser();
204 |           const spec = await parser.dereference(source) as OpenAPIV3.Document;
205 |           
206 |           this.apis.set(apiId, { spec, parser });
207 |           
208 |           const pathCount = Object.keys(spec.paths || {}).length;
209 |           const endpointCount = Object.values(spec.paths || {}).reduce((count, pathItem) => {
210 |             if (!pathItem) return count;
211 |             return count + ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace']
212 |               .filter(method => (pathItem as any)[method]).length;
213 |           }, 0);
214 | 
215 |           return {
216 |             content: [{
217 |               type: "text",
218 |               text: `Successfully loaded API '${spec.info?.title || apiId}' (v${spec.info?.version || 'unknown'}) with ${pathCount} paths and ${endpointCount} endpoints.`
219 |             }]
220 |           };
221 |         } catch (error) {
222 |           return {
223 |             content: [{
224 |               type: "text",
225 |               text: `Failed to load API: ${error instanceof Error ? error.message : String(error)}`
226 |             }],
227 |             isError: true
228 |           };
229 |         }
230 |       }
231 |     );
232 | 
233 |     // Tool to get endpoint details with optional natural language summary
234 |     this.server.tool(
235 |       "get_endpoint_details",
236 |       {
237 |         apiId: z.string().describe("ID of the loaded API"),
238 |         method: z.string().describe("HTTP method (GET, POST, etc.)"),
239 |         path: z.string().describe("API endpoint path"),
240 |         natural: z.boolean().optional().describe("If true, returns a human-readable summary")
241 |       },
242 |       async ({ apiId, method, path, natural = false }) => {
243 |         try {
244 |           const api = this.apis.get(apiId);
245 |           if (!api) {
246 |             return {
247 |               content: [{
248 |                 type: "text",
249 |                 text: `API with ID '${apiId}' not found. Use load_api tool first.`
250 |               }],
251 |               isError: true
252 |             };
253 |           }
254 | 
255 |           const pathItem = api.spec.paths?.[path];
256 |           if (!pathItem) {
257 |             return {
258 |               content: [{
259 |                 type: "text",
260 |                 text: `Path '${path}' not found in API`
261 |               }],
262 |               isError: true
263 |             };
264 |           }
265 | 
266 |           const operation = (pathItem as any)[method.toLowerCase()] as OpenAPIV3.OperationObject;
267 |           if (!operation) {
268 |             return {
269 |               content: [{
270 |                 type: "text",
271 |                 text: `Method '${method}' not found for path '${path}'`
272 |               }],
273 |               isError: true
274 |             };
275 |           }
276 | 
277 |           const endpointDetails = this.formatEndpointDetails(operation, path, method.toUpperCase());
278 | 
279 |           if (natural) {
280 |             const summary = this.generateNaturalSummary(endpointDetails, path, method);
281 |             return {
282 |               content: [{
283 |                 type: "text",
284 |                 text: summary
285 |               }]
286 |             };
287 |           }
288 | 
289 |           return {
290 |             content: [{
291 |               type: "text",
292 |               text: JSON.stringify(endpointDetails, null, 2)
293 |             }]
294 |           };
295 |         } catch (error) {
296 |           return {
297 |             content: [{
298 |               type: "text",
299 |               text: `Error getting endpoint details: ${error instanceof Error ? error.message : String(error)}`
300 |             }],
301 |             isError: true
302 |           };
303 |         }
304 |       }
305 |     );
306 | 
307 |     // Tool to list all available APIs
308 |     this.server.tool(
309 |       "list_apis",
310 |       {},
311 |       async () => {
312 |         const apiList = Array.from(this.apis.entries()).map(([id, api]) => ({
313 |           id,
314 |           title: api.spec.info?.title || id,
315 |           version: api.spec.info?.version,
316 |           description: api.spec.info?.description,
317 |           pathCount: Object.keys(api.spec.paths || {}).length
318 |         }));
319 | 
320 |         return {
321 |           content: [{
322 |             type: "text",
323 |             text: apiList.length > 0 
324 |               ? JSON.stringify(apiList, null, 2)
325 |               : "No APIs loaded. Use the load_api tool to load an API specification."
326 |           }]
327 |         };
328 |       }
329 |     );
330 | 
331 |     // Tool to search endpoints by pattern
332 |     this.server.tool(
333 |       "search_endpoints",
334 |       {
335 |         apiId: z.string().describe("ID of the loaded API"),
336 |         pattern: z.string().describe("Search pattern for endpoint paths or descriptions")
337 |       },
338 |       async ({ apiId, pattern }) => {
339 |         try {
340 |           const api = this.apis.get(apiId);
341 |           if (!api) {
342 |             return {
343 |               content: [{
344 |                 type: "text",
345 |                 text: `API with ID '${apiId}' not found`
346 |               }],
347 |               isError: true
348 |             };
349 |           }
350 | 
351 |           const matchingEndpoints: Array<{method: string, path: string, summary?: string, description?: string}> = [];
352 |           const searchPattern = pattern.toLowerCase();
353 | 
354 |           Object.entries(api.spec.paths || {}).forEach(([path, pathItem]) => {
355 |             if (!pathItem) return;
356 |             
357 |             ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'].forEach(method => {
358 |               const operation = (pathItem as any)[method] as OpenAPIV3.OperationObject;
359 |               if (operation) {
360 |                 const matchesPath = path.toLowerCase().includes(searchPattern);
361 |                 const matchesSummary = operation.summary?.toLowerCase().includes(searchPattern);
362 |                 const matchesDescription = operation.description?.toLowerCase().includes(searchPattern);
363 |                 
364 |                 if (matchesPath || matchesSummary || matchesDescription) {
365 |                   matchingEndpoints.push({
366 |                     method: method.toUpperCase(),
367 |                     path,
368 |                     summary: operation.summary,
369 |                     description: operation.description
370 |                   });
371 |                 }
372 |               }
373 |             });
374 |           });
375 | 
376 |           return {
377 |             content: [{
378 |               type: "text",
379 |               text: matchingEndpoints.length > 0
380 |                 ? JSON.stringify(matchingEndpoints, null, 2)
381 |                 : `No endpoints found matching pattern: ${pattern}`
382 |             }]
383 |           };
384 |         } catch (error) {
385 |           return {
386 |             content: [{
387 |               type: "text",
388 |               text: `Error searching endpoints: ${error instanceof Error ? error.message : String(error)}`
389 |             }],
390 |             isError: true
391 |           };
392 |         }
393 |       }
394 |     );
395 |   }
396 | 
397 |   private formatEndpointDetails(operation: OpenAPIV3.OperationObject, path: string, method: string) {
398 |     const details: any = {
399 |       method,
400 |       path,
401 |       summary: operation.summary,
402 |       description: operation.description,
403 |       operationId: operation.operationId,
404 |       tags: operation.tags,
405 |       parameters: [],
406 |       requestBody: null,
407 |       responses: {}
408 |     };
409 | 
410 |     // Process parameters
411 |     if (operation.parameters) {
412 |       details.parameters = operation.parameters.map((param: any) => ({
413 |         name: param.name,
414 |         in: param.in,
415 |         required: param.required || false,
416 |         description: param.description,
417 |         schema: param.schema,
418 |         example: param.example
419 |       }));
420 |     }
421 | 
422 |     // Process request body
423 |     if (operation.requestBody) {
424 |       const requestBody = operation.requestBody as OpenAPIV3.RequestBodyObject;
425 |       details.requestBody = {
426 |         description: requestBody.description,
427 |         required: requestBody.required || false,
428 |         content: requestBody.content
429 |       };
430 |     }
431 | 
432 |     // Process responses
433 |     if (operation.responses) {
434 |       Object.entries(operation.responses).forEach(([code, response]) => {
435 |         if (response && typeof response === 'object' && 'description' in response) {
436 |           details.responses[code] = {
437 |             description: response.description,
438 |             content: (response as OpenAPIV3.ResponseObject).content,
439 |             headers: (response as OpenAPIV3.ResponseObject).headers
440 |           };
441 |         }
442 |       });
443 |     }
444 | 
445 |     return details;
446 |   }
447 | 
448 |   private generateNaturalSummary(endpointDetails: any, path: string, method: string): string {
449 |     const { summary, description, parameters, requestBody, responses } = endpointDetails;
450 |     
451 |     let naturalSummary = `The ${method} ${path} endpoint`;
452 |     
453 |     if (summary) {
454 |       naturalSummary += ` ${summary.toLowerCase()}`;
455 |     } else if (description) {
456 |       naturalSummary += ` ${description.toLowerCase()}`;
457 |     }
458 |     
459 |     // Add parameter information
460 |     if (parameters && parameters.length > 0) {
461 |       const requiredParams = parameters.filter((p: any) => p.required);
462 |       const optionalParams = parameters.filter((p: any) => !p.required);
463 |       
464 |       if (requiredParams.length > 0) {
465 |         naturalSummary += `. It requires ${requiredParams.map((p: any) => `${p.name} (${p.in})`).join(', ')}`;
466 |       }
467 |       
468 |       if (optionalParams.length > 0) {
469 |         naturalSummary += `. Optional parameters include ${optionalParams.map((p: any) => `${p.name} (${p.in})`).join(', ')}`;
470 |       }
471 |     }
472 |     
473 |     // Add request body information
474 |     if (requestBody) {
475 |       naturalSummary += `. It accepts a request body`;
476 |       if (requestBody.required) {
477 |         naturalSummary += ' (required)';
478 |       }
479 |     }
480 |     
481 |     // Add response information
482 |     const responseKeys = Object.keys(responses || {});
483 |     if (responseKeys.length > 0) {
484 |       const successCodes = responseKeys.filter(code => code.startsWith('2'));
485 |       if (successCodes.length > 0) {
486 |         naturalSummary += `. Success responses include ${successCodes.join(', ')}`;
487 |       }
488 |     }
489 |     
490 |     naturalSummary += '.';
491 |     
492 |     return naturalSummary;
493 |   }
494 | 
495 |   async connect(transport: StdioServerTransport) {
496 |     await this.server.connect(transport);
497 |   }
498 | }
499 | 
500 | // Main execution
501 | async function main() {
502 |   const server = new SwaggerMCPServer();
503 |   const transport = new StdioServerTransport();
504 |   
505 |   console.error("Starting Swagger MCP Server...");
506 |   await server.connect(transport);
507 |   console.error("Swagger MCP Server running on stdio");
508 | }
509 | 
510 | // Handle graceful shutdown
511 | process.on('SIGINT', () => {
512 |   console.error('Received SIGINT, shutting down gracefully...');
513 |   process.exit(0);
514 | });
515 | 
516 | process.on('SIGTERM', () => {
517 |   console.error('Received SIGTERM, shutting down gracefully...');
518 |   process.exit(0);
519 | });
520 | 
521 | if (require.main === module) {
522 |   main().catch((error) => {
523 |     console.error('Fatal error:', error);
524 |     process.exit(1);
525 |   });
526 | }
```