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

```
├── .gitignore
├── package.json
├── readme.md
├── showSettings.js
├── src
│   └── index.ts
└── tsconfig.json
```

# Files

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

```
1 | node_modules
2 | build
3 | package-lock.json
4 | yarn.lock
```

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

```markdown
 1 | # MCP Server Guide
 2 | 
 3 | To build the MCP server, run:
 4 | 
 5 | ```
 6 | npm install && npm run build
 7 | ```
 8 | 
 9 | This will compile the typescript files and produce a build directory plus it will output the json you can copy/paste into your MCP client (Claude Desktop, Windsurf, Cursor, etc.)
10 | 
11 | If all things go well, this will produce an output similar to this:
12 | 
13 | ```json
14 | {
15 |   "mcpServers": {
16 |     "doordash": {
17 |       "command": "node",
18 |       "args": [
19 |         "<thePathToYour>/build/index.js"
20 |       ],
21 |       "env": [
22 |         {
23 |           "DOORDASH_API_KEY": "<REPLACE>"
24 |         }
25 |       ]
26 |     }
27 |   }
28 | }
29 | ```
30 | 
31 | ## Support & Feedback
32 | If things do not compile, or you have more advanced needs, please reach out to me at, [email protected].
33 | 
34 | ## Sharing
35 | 
36 | If you have found value in this service please share it on social media. You can tag me [@jordandalton](https://x.com/jordankdalton) on X, or [jdcarnivore](https://www.reddit.com/user/jdcarnivore) on Reddit.
```

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

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2022",
 4 |     "module": "NodeNext",
 5 |     "moduleResolution": "NodeNext",
 6 |     "outDir": "./build",
 7 |     "rootDir": "./src",
 8 |     "strict": true,
 9 |     "esModuleInterop": true,
10 |     "skipLibCheck": true,
11 |     "forceConsistentCasingInFileNames": true,
12 |     "allowSyntheticDefaultImports": true,
13 |     "moduleDetection": "force",
14 |     "allowJs": true
15 |   },
16 |   "include": ["src/**/*"],
17 |   "exclude": ["node_modules"]
18 | }
```

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

```json
 1 | {
 2 |   "name": "doordash-mcp-server",
 3 |   "version": "1.0.0",
 4 |   "main": "index.js",
 5 |   "type": "module",
 6 |   "scripts": {
 7 |     "build": "tsc && chmod 755 build/index.js && node showSettings"
 8 |   },
 9 |   "keywords": [],
10 |   "author": "",
11 |   "license": "ISC",
12 |   "description": "",
13 |   "dependencies": {
14 |     "@modelcontextprotocol/sdk": "^1.8.0",
15 |     "axios": "^1.8.4",
16 |     "jsonwebtoken": "^9.0.2",
17 |     "zod": "^3.24.2"
18 |   },
19 |   "devDependencies": {
20 |     "@types/node": "^22.14.0",
21 |     "typescript": "^5.8.3"
22 |   }
23 | }
24 | 
```

--------------------------------------------------------------------------------
/showSettings.js:
--------------------------------------------------------------------------------

```javascript
 1 | import path from 'path';
 2 | import fs from 'fs';
 3 | 
 4 | const filePath = path.join(process.cwd(), 'build', 'index.js');
 5 | 
 6 | // look for any env variables inside the file
 7 | const env = {};
 8 | 
 9 | // Read the file
10 | const fileContent = fs.readFileSync(filePath, 'utf-8');
11 | 
12 | // Find all env variables
13 | const envRegex = /process\.env\.(\w+)/g;
14 | let match;
15 | while ((match = envRegex.exec(fileContent)) !== null) {
16 |     const row = { [match[1]]: '<REPLACE>' };
17 |     Object.assign(env, row);
18 | }
19 | 
20 | const structure = {
21 |     mcpServers : {
22 |         "doordash" : {
23 |             command : "node",
24 |             args : [filePath],
25 |             env : env
26 |         }
27 |     }
28 | }
29 | 
30 | console.log('Copy/Paste into your MCP client:');
31 | console.log(
32 |     JSON.stringify(structure, null, 2)
33 | );
34 | 
```

--------------------------------------------------------------------------------
/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 axios from 'axios';
  5 | import jwt from "jsonwebtoken";
  6 | 
  7 | const developer_id = process.env.DOORDASH_DEVELOPER_ID;
  8 | const key_id = process.env.DOORDASH_KEY_ID;
  9 | const signing_secret = process.env.DOORDASH_SIGNING_SECRET;
 10 | 
 11 | // Create an MCP server
 12 | const server = new McpServer({
 13 |   name: "DoorDashDriveAPI",
 14 |   version: "1.0.0"
 15 | });
 16 | 
 17 | const issuedAt = Math.floor(Date.now() / 1000);
 18 |   const expirationDuration = 300;
 19 | 
 20 |   const jwtData = {
 21 |     aud: 'doordash',
 22 |     iss: developer_id,
 23 |     kid: key_id,
 24 |     exp: issuedAt + expirationDuration,
 25 |     iat: issuedAt,
 26 |   }
 27 |   
 28 |   const token = jwt.sign(
 29 |     jwtData,
 30 |     Buffer.from(signing_secret, 'base64'),
 31 |     {
 32 |       algorithm: "HS256",
 33 |       header: {
 34 |         alg: "HS256",
 35 |         'dd-ver': 'DD-JWT-V1'
 36 |       }
 37 |     } as unknown as jwt.SignOptions
 38 |   );
 39 | 
 40 | // Helper function to make API requests with authentication
 41 | async function makeApiRequest(url: string, method: string, data?: any) {
 42 |   const headers = {
 43 |     Authorization: `Bearer ${token}`,
 44 |     'Content-Type': 'application/json',
 45 |   };
 46 |   try {
 47 |     const response = await axios({
 48 |       url: url,
 49 |       method: method,
 50 |       data: data,
 51 |       headers
 52 |     });
 53 |     return response.data;
 54 |   } catch (error) {
 55 |     console.error("API request failed:", error);
 56 |     throw error; // Re-throw the error for the tool to handle
 57 |   }
 58 | }
 59 | 
 60 | // Tool: Create Quote
 61 | server.tool("create_quote",
 62 |   {
 63 |     external_delivery_id: z.string(),
 64 |     locale: z.string().optional(),
 65 |     order_fulfillment_method: z.string().optional(),
 66 |     origin_facility_id: z.string().optional(),
 67 |     pickup_address: z.string().optional(),
 68 |     pickup_business_name: z.string().optional(),
 69 |     pickup_phone_number: z.string().optional(),
 70 |     pickup_instructions: z.string().optional(),
 71 |     pickup_reference_tag: z.string().optional(),
 72 |     pickup_external_business_id: z.string().optional(),
 73 |     pickup_external_store_id: z.string().optional(),
 74 |     pickup_verification_metadata: z.record(z.any()).optional(),
 75 |     dropoff_address: z.string(),
 76 |     dropoff_business_name: z.string().optional(),
 77 |     dropoff_location: z.record(z.any()).optional(),
 78 |     dropoff_phone_number: z.string(),
 79 |     dropoff_instructions: z.string().optional(),
 80 |     dropoff_contact_given_name: z.string().optional(),
 81 |     dropoff_contact_family_name: z.string().optional(),
 82 |     dropoff_contact_send_notifications: z.boolean().optional(),
 83 |     dropoff_options: z.record(z.any()).optional(),
 84 |     dropoff_address_components: z.record(z.any()).optional(),
 85 |     dropoff_pin_code_verification_metadata: z.record(z.any()).optional(),
 86 |     shopping_options: z.record(z.any()).optional(),
 87 |     order_value: z.number().optional(),
 88 |     items: z.array(z.record(z.any())).optional(),
 89 |     pickup_time: z.string().optional(),
 90 |     dropoff_time: z.string().optional(),
 91 |     pickup_window: z.record(z.any()).optional(),
 92 |     dropoff_window: z.record(z.any()).optional(),
 93 |     customer_expected_sla: z.any().optional(),
 94 |     expires_by: z.any().optional(),
 95 |     shipping_label_metadata: z.record(z.any()).optional(),
 96 |     contactless_dropoff: z.boolean().optional(),
 97 |     action_if_undeliverable: z.string().optional(),
 98 |     tip: z.number().optional(),
 99 |     order_contains: z.record(z.any()).optional(),
100 |     dasher_allowed_vehicles: z.array(z.string()).optional(),
101 |     dropoff_requires_signature: z.boolean().optional(),
102 |     promotion_id: z.string().optional(),
103 |     dropoff_cash_on_delivery: z.number().optional(),
104 |     order_route_type: z.string().optional(),
105 |     order_route_items: z.array(z.string()).optional()
106 |   },
107 |   async (params) => {
108 |     try {
109 |       const response = await makeApiRequest(
110 |         'https://openapi.doordash.com/drive/v2/quotes',
111 |         'POST',
112 |         params
113 |       );
114 |       return {
115 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
116 |       };
117 |     } catch (error: any) {
118 |       return {
119 |         content: [{ type: "text", text: `Error: ${error.message}` }]
120 |       };
121 |     }
122 |   }
123 | );
124 | 
125 | // Tool: Accept Quote
126 | server.tool("accept_quote",
127 |   {
128 |     external_delivery_id: z.string(),
129 |     tip: z.number().optional(),
130 |     dropoff_phone_number: z.string().optional()
131 |   },
132 |   async ({ external_delivery_id, tip, dropoff_phone_number }) => {
133 |     try {
134 |       const response = await makeApiRequest(
135 |         `https://openapi.doordash.com/drive/v2/quotes/${external_delivery_id}/accept`,
136 |         'POST',
137 |         { tip: tip, dropoff_phone_number: dropoff_phone_number }
138 |       );
139 |       return {
140 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
141 |       };
142 |     } catch (error: any) {
143 |       return {
144 |         content: [{ type: "text", text: `Error: ${error.message}` }]
145 |       };
146 |     }
147 |   }
148 | );
149 | 
150 | // Tool: Create Delivery
151 | server.tool("create_delivery",
152 |   {
153 |     external_delivery_id: z.string(),
154 |     locale: z.string().optional(),
155 |     order_fulfillment_method: z.string().optional(),
156 |     origin_facility_id: z.string().optional(),
157 |     pickup_address: z.string().optional(),
158 |     pickup_business_name: z.string().optional(),
159 |     pickup_phone_number: z.string().optional(),
160 |     pickup_instructions: z.string().optional(),
161 |     pickup_reference_tag: z.string().optional(),
162 |     pickup_external_business_id: z.string().optional(),
163 |     pickup_external_store_id: z.string().optional(),
164 |     pickup_verification_metadata: z.record(z.any()).optional(),
165 |     dropoff_address: z.string(),
166 |     dropoff_business_name: z.string().optional(),
167 |     dropoff_location: z.record(z.any()).optional(),
168 |     dropoff_phone_number: z.string(),
169 |     dropoff_instructions: z.string().optional(),
170 |     dropoff_contact_given_name: z.string().optional(),
171 |     dropoff_contact_family_name: z.string().optional(),
172 |     dropoff_contact_send_notifications: z.boolean().optional(),
173 |     dropoff_options: z.record(z.any()).optional(),
174 |     dropoff_address_components: z.record(z.any()).optional(),
175 |     dropoff_pin_code_verification_metadata: z.record(z.any()).optional(),
176 |     shopping_options: z.record(z.any()).optional(),
177 |     order_value: z.number().optional(),
178 |     items: z.array(z.record(z.any())).optional(),
179 |     pickup_time: z.string().optional(),
180 |     dropoff_time: z.string().optional(),
181 |     pickup_window: z.record(z.any()).optional(),
182 |     dropoff_window: z.record(z.any()).optional(),
183 |     customer_expected_sla: z.any().optional(),
184 |     expires_by: z.any().optional(),
185 |     shipping_label_metadata: z.record(z.any()).optional(),
186 |     contactless_dropoff: z.boolean().optional(),
187 |     action_if_undeliverable: z.string().optional(),
188 |     tip: z.number().optional(),
189 |     order_contains: z.record(z.any()).optional(),
190 |     dasher_allowed_vehicles: z.array(z.string()).optional(),
191 |     dropoff_requires_signature: z.boolean().optional(),
192 |     promotion_id: z.string().optional(),
193 |     dropoff_cash_on_delivery: z.number().optional(),
194 |     order_route_type: z.string().optional(),
195 |     order_route_items: z.array(z.string()).optional()
196 |   },
197 |   async (params) => {
198 |     try {
199 |       const response = await makeApiRequest(
200 |         'https://openapi.doordash.com/drive/v2/deliveries',
201 |         'POST',
202 |         params
203 |       );
204 |       return {
205 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
206 |       };
207 |     } catch (error: any) {
208 |       return {
209 |         content: [{ type: "text", text: `Error: ${error.message}` }]
210 |       };
211 |     }
212 |   }
213 | );
214 | 
215 | // Tool: Get Delivery
216 | server.tool("get_delivery",
217 |   {
218 |     external_delivery_id: z.string()
219 |   },
220 |   async ({ external_delivery_id }) => {
221 |     try {
222 |       const response = await makeApiRequest(
223 |         `https://openapi.doordash.com/drive/v2/deliveries/${external_delivery_id}`,
224 |         'GET'
225 |       );
226 |       return {
227 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
228 |       };
229 |     } catch (error: any) {
230 |       return {
231 |         content: [{ type: "text", text: `Error: ${error.message}` }]
232 |       };
233 |     }
234 |   }
235 | );
236 | 
237 | // Tool: Update Delivery
238 | server.tool("update_delivery",
239 |   {
240 |     external_delivery_id: z.string(),
241 |     pickup_address: z.string().optional(),
242 |     pickup_business_name: z.string().optional(),
243 |     pickup_phone_number: z.string().optional(),
244 |     pickup_instructions: z.string().optional(),
245 |     pickup_reference_tag: z.string().optional(),
246 |     pickup_external_business_id: z.string().optional(),
247 |     pickup_external_store_id: z.string().optional(),
248 |     pickup_verification_metadata: z.record(z.any()).optional(),
249 |     dropoff_address: z.string().optional(),
250 |     dropoff_business_name: z.string().optional(),
251 |     dropoff_location: z.record(z.any()).optional(),
252 |     dropoff_phone_number: z.string().optional(),
253 |     dropoff_instructions: z.string().optional(),
254 |     dropoff_contact_given_name: z.string().optional(),
255 |     dropoff_contact_family_name: z.string().optional(),
256 |     dropoff_contact_send_notifications: z.boolean().optional(),
257 |     dropoff_options: z.record(z.any()).optional(),
258 |     dropoff_address_components: z.record(z.any()).optional(),
259 |     dropoff_pin_code_verification_metadata: z.record(z.any()).optional(),
260 |     contactless_dropoff: z.boolean().optional(),
261 |     action_if_undeliverable: z.string().optional(),
262 |     tip: z.number().optional(),
263 |     order_contains: z.record(z.any()).optional(),
264 |     dasher_allowed_vehicles: z.array(z.string()).optional(),
265 |     dropoff_requires_signature: z.boolean().optional(),
266 |     promotion_id: z.string().optional(),
267 |     dropoff_cash_on_delivery: z.number().optional(),
268 |     order_route_type: z.string().optional(),
269 |     order_route_items: z.array(z.string()).optional(),
270 |     order_value: z.number().optional(),
271 |     items: z.array(z.record(z.any())).optional(),
272 |     pickup_time: z.string().optional(),
273 |     dropoff_time: z.string().optional(),
274 |     pickup_window: z.record(z.any()).optional(),
275 |     dropoff_window: z.record(z.any()).optional(),
276 |     customer_expected_sla: z.any().optional(),
277 |     expires_by: z.any().optional(),
278 |     shipping_label_metadata: z.record(z.any()).optional(),
279 |   },
280 |   async ({ external_delivery_id, ...params }) => {
281 |     try {
282 |       const response = await makeApiRequest(
283 |         `https://openapi.doordash.com/drive/v2/deliveries/${external_delivery_id}`,
284 |         'PATCH',
285 |         params
286 |       );
287 |       return {
288 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
289 |       };
290 |     } catch (error: any) {
291 |       return {
292 |         content: [{ type: "text", text: `Error: ${error.message}` }]
293 |       };
294 |     }
295 |   }
296 | );
297 | 
298 | // Tool: Cancel Delivery
299 | server.tool("cancel_delivery",
300 |   {
301 |     external_delivery_id: z.string()
302 |   },
303 |   async ({ external_delivery_id }) => {
304 |     try {
305 |       const response = await makeApiRequest(
306 |         `https://openapi.doordash.com/drive/v2/deliveries/${external_delivery_id}/cancel`,
307 |         'PUT'
308 |       );
309 |       return {
310 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
311 |       };
312 |     } catch (error: any) {
313 |       return {
314 |         content: [{ type: "text", text: `Error: ${error.message}` }]
315 |       };
316 |     }
317 |   }
318 | );
319 | 
320 | // Tool: Get Items Substitution Recommendation
321 | server.tool("get_items_substitution_recommendation",
322 |   {
323 |     pickup_external_business_id: z.string(),
324 |     pickup_external_store_id: z.string(),
325 |     items: z.array(z.record(z.any())),
326 |     customer: z.record(z.any()).optional()
327 |   },
328 |   async (params) => {
329 |     try {
330 |       const response = await makeApiRequest(
331 |         'https://openapi.doordash.com/drive/v2/items_substitution_recommendation',
332 |         'POST',
333 |         params
334 |       );
335 |       return {
336 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
337 |       };
338 |     } catch (error: any) {
339 |       return {
340 |         content: [{ type: "text", text: `Error: ${error.message}` }]
341 |       };
342 |     }
343 |   }
344 | );
345 | 
346 | // Tool: Create Checkout Audit Signal
347 | server.tool("create_checkout_audit_signal",
348 |   {
349 |     external_delivery_id: z.string(),
350 |     is_audit_successful: z.boolean(),
351 |     audit_period: z.record(z.any()).optional(),
352 |     requested_audit_item_count: z.number().optional(),
353 |     audited_item_count: z.number().optional(),
354 |     successful_audit_items: z.array(z.record(z.any())).optional(),
355 |     failed_audit_items: z.array(z.record(z.any())).optional(),
356 |     checkout_audit_status: z.string().optional()
357 |   },
358 |   async (params) => {
359 |     try {
360 |       const response = await makeApiRequest(
361 |         'https://openapi.doordash.com/drive/v2/checkout_audit_signal',
362 |         'POST',
363 |         params
364 |       );
365 |       return {
366 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
367 |       };
368 |     } catch (error: any) {
369 |       return {
370 |         content: [{ type: "text", text: `Error: ${error.message}` }]
371 |       };
372 |     }
373 |   }
374 | );
375 | 
376 | // Tool: Get Business
377 | server.tool("get_business",
378 |   {
379 |     external_business_id: z.string()
380 |   },
381 |   async ({ external_business_id }) => {
382 |     try {
383 |       const response = await makeApiRequest(
384 |         `https://openapi.doordash.com/developer/v1/businesses/${external_business_id}`,
385 |         'GET'
386 |       );
387 |       return {
388 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
389 |       };
390 |     } catch (error: any) {
391 |       return {
392 |         content: [{ type: "text", text: `Error: ${error.message}` }]
393 |       };
394 |     }
395 |   }
396 | );
397 | 
398 | // Tool: Update Business
399 | server.tool("update_business",
400 |   {
401 |     external_business_id: z.string(),
402 |     name: z.string().optional(),
403 |     description: z.string().optional(),
404 |     activation_status: z.string().optional()
405 |   },
406 |   async ({ external_business_id, name, description, activation_status }) => {
407 |     try {
408 |       const response = await makeApiRequest(
409 |         `https://openapi.doordash.com/developer/v1/businesses/${external_business_id}`,
410 |         'PATCH',
411 |         { name: name, description: description, activation_status: activation_status }
412 |       );
413 |       return {
414 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
415 |       };
416 |     } catch (error: any) {
417 |       return {
418 |         content: [{ type: "text", text: `Error: ${error.message}` }]
419 |       };
420 |     }
421 |   }
422 | );
423 | 
424 | // Tool: List Businesses
425 | server.tool("list_businesses",
426 |   {
427 |     activationStatus: z.string().optional(),
428 |     continuationToken: z.string().optional()
429 |   },
430 |   async ({ activationStatus, continuationToken }) => {
431 |     try {
432 |       let url = 'https://openapi.doordash.com/developer/v1/businesses';
433 |       const params = new URLSearchParams();
434 |       if (activationStatus) {
435 |         params.append('activationStatus', activationStatus);
436 |       }
437 |       if (continuationToken) {
438 |         params.append('continuationToken', continuationToken);
439 |       }
440 |       if (params.toString()) {
441 |         url += `?${params.toString()}`;
442 |       }
443 |       const response = await makeApiRequest(url, 'GET');
444 |       return {
445 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
446 |       };
447 |     } catch (error: any) {
448 |       return {
449 |         content: [{ type: "text", text: `Error: ${error.message}` }]
450 |       };
451 |     }
452 |   }
453 | );
454 | 
455 | // Tool: Get Store
456 | server.tool("get_store",
457 |   {
458 |     external_business_id: z.string(),
459 |     external_store_id: z.string()
460 |   },
461 |   async ({ external_business_id, external_store_id }) => {
462 |     try {
463 |       const response = await makeApiRequest(
464 |         `https://openapi.doordash.com/developer/v1/businesses/${external_business_id}/stores/${external_store_id}`,
465 |         'GET'
466 |       );
467 |       return {
468 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
469 |       };
470 |     } catch (error: any) {
471 |       return {
472 |         content: [{ type: "text", text: `Error: ${error.message}` }]
473 |       };
474 |     }
475 |   }
476 | );
477 | 
478 | // Tool: Update Store
479 | server.tool("update_store",
480 |   {
481 |     external_business_id: z.string(),
482 |     external_store_id: z.string(),
483 |     name: z.string().optional(),
484 |     phone_number: z.string().optional(),
485 |     address: z.string().optional()
486 |   },
487 |   async ({ external_business_id, external_store_id, name, phone_number, address }) => {
488 |     try {
489 |       const response = await makeApiRequest(
490 |         `https://openapi.doordash.com/developer/v1/businesses/${external_business_id}/stores/${external_store_id}`,
491 |         'PATCH',
492 |         { name: name, phone_number: phone_number, address: address }
493 |       );
494 |       return {
495 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
496 |       };
497 |     } catch (error: any) {
498 |       return {
499 |         content: [{ type: "text", text: `Error: ${error.message}` }]
500 |       };
501 |     }
502 |   }
503 | );
504 | 
505 | // Tool: Create Store
506 | server.tool("create_store",
507 |   {
508 |     external_business_id: z.string(),
509 |     external_store_id: z.string(),
510 |     name: z.string(),
511 |     phone_number: z.string(),
512 |     address: z.string()
513 |   },
514 |   async ({ external_business_id, external_store_id, name, phone_number, address }) => {
515 |     try {
516 |       const response = await makeApiRequest(
517 |         `https://openapi.doordash.com/developer/v1/businesses/${external_business_id}/stores`,
518 |         'POST',
519 |         { external_store_id: external_store_id, name: name, phone_number: phone_number, address: address }
520 |       );
521 |       return {
522 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
523 |       };
524 |     } catch (error: any) {
525 |       return {
526 |         content: [{ type: "text", text: `Error: ${error.message}` }]
527 |       };
528 |     }
529 |   }
530 | );
531 | 
532 | // Tool: List Stores
533 | server.tool("list_stores",
534 |   {
535 |     external_business_id: z.string(),
536 |     activationStatus: z.string().optional(),
537 |     continuationToken: z.string().optional()
538 |   },
539 |   async ({ external_business_id, activationStatus, continuationToken }) => {
540 |     try {
541 |       let url = `https://openapi.doordash.com/developer/v1/businesses/${external_business_id}/stores`;
542 |       const params = new URLSearchParams();
543 |       if (activationStatus) {
544 |         params.append('activationStatus', activationStatus);
545 |       }
546 |       if (continuationToken) {
547 |         params.append('continuationToken', continuationToken);
548 |       }
549 |       if (params.toString()) {
550 |         url += `?${params.toString()}`;
551 |       }
552 |       const response = await makeApiRequest(url, 'GET');
553 |       return {
554 |         content: [{ type: "text", text: String(JSON.stringify(response)) }]
555 |       };
556 |     } catch (error: any) {
557 |       return {
558 |         content: [{ type: "text", text: `Error: ${error.message}` }]
559 |       };
560 |     }
561 |   }
562 | );
563 | 
564 | // Start receiving messages on stdin and sending messages on stdout
565 | const transport = new StdioServerTransport();
566 | await server.connect(transport);
```