@@ -48,7 +48,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
48
48
49
49
<Steps >
50
50
<Step title = " Define types" >
51
- Create a file ` types.ts ` , and add the following:
51
+ Create a file ` src/ types.ts` , and add the following:
52
52
53
53
``` typescript
54
54
export interface OpenWeatherResponse {
@@ -85,7 +85,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
85
85
}
86
86
87
87
// Type guard for forecast arguments
88
- export function isValidForecastArgs(args : unknown ): args is GetForecastArgs {
88
+ export function isValidForecastArgs(args : any ): args is GetForecastArgs {
89
89
return (
90
90
typeof args === " object" &&
91
91
args !== null &&
@@ -98,9 +98,10 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
98
98
</Step >
99
99
100
100
<Step title = " Add the base code" >
101
- Replace ` index.ts ` with the following:
101
+ Replace ` src/ index.ts` with the following:
102
102
103
103
``` typescript
104
+ #! / usr / bin / env node
104
105
import { Server } from " @modelcontextprotocol/sdk/server/index.js" ;
105
106
import { StdioServerTransport } from " @modelcontextprotocol/sdk/server/stdio.js" ;
106
107
import {
@@ -116,7 +117,6 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
116
117
import {
117
118
WeatherData ,
118
119
ForecastDay ,
119
- GetForecastArgs ,
120
120
OpenWeatherResponse ,
121
121
isValidForecastArgs
122
122
} from " ./types.js" ;
@@ -145,6 +145,11 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
145
145
this .server = new Server ({
146
146
name: " example-weather-server" ,
147
147
version: " 0.1.0"
148
+ }, {
149
+ capabilities: {
150
+ resources: {},
151
+ tools: {}
152
+ }
148
153
});
149
154
150
155
// Configure axios with defaults
@@ -197,7 +202,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
197
202
</Step >
198
203
199
204
<Step title = " Add resource handlers" >
200
- Add this to the ` setupHandlers ` method:
205
+ Add this to the ` setupResourceHandlers ` method:
201
206
202
207
``` typescript
203
208
private setupResourceHandlers (): void {
@@ -263,7 +268,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
263
268
</Step >
264
269
265
270
<Step title = " Add tool handlers" >
266
- Add these handlers to the ` setupHandlers ` method:
271
+ Add these handlers to the ` setupToolHandlers ` method:
267
272
268
273
``` typescript
269
274
private setupToolHandlers (): void {
@@ -333,13 +338,21 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
333
338
});
334
339
}
335
340
336
- return { toolResult: forecasts };
341
+ return {
342
+ content: {
343
+ mimeType: " application/json" ,
344
+ text: JSON .stringify (forecasts , null , 2 )
345
+ }
346
+ };
337
347
} catch (error ) {
338
348
if (axios .isAxiosError (error )) {
339
- throw new McpError (
340
- ErrorCode .InternalError ,
341
- ` Weather API error: ${error .response ?.data .message ?? error .message } `
342
- );
349
+ return {
350
+ content: {
351
+ mimeType: " text/plain" ,
352
+ text: ` Weather API error: ${error .response ?.data .message ?? error .message } `
353
+ },
354
+ isError: true ,
355
+ }
343
356
}
344
357
throw error ;
345
358
}
@@ -361,7 +374,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
361
374
362
375
<Steps >
363
376
<Step title = " Update Claude config" >
364
- Add to ` claude_desktop_config.json ` :
377
+ If you didn't already connect to Claude Desktop during project setup, add to ` claude_desktop_config.json ` :
365
378
366
379
``` json
367
380
{
@@ -466,14 +479,35 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
466
479
title = " Error Handling"
467
480
icon = " shield"
468
481
>
482
+ When a tool encounters an error, return the error message with ` isError: true ` , so the model can self-correct:
483
+
484
+ ``` typescript
485
+ try {
486
+ const response = await axiosInstance .get (... );
487
+ } catch (error ) {
488
+ if (axios .isAxiosError (error )) {
489
+ return {
490
+ content: {
491
+ mimeType: " text/plain" ,
492
+ text: ` Weather API error: ${error .response ?.data .message ?? error .message } `
493
+ },
494
+ isError: true ,
495
+ }
496
+ }
497
+ throw error ;
498
+ }
499
+ ```
500
+
501
+ For other handlers, throw an error, so the application can notify the user:
502
+
469
503
``` typescript
470
504
try {
471
505
const response = await this .axiosInstance .get (... );
472
506
} catch (error ) {
473
507
if (axios .isAxiosError (error )) {
474
508
throw new McpError (
475
509
ErrorCode .InternalError ,
476
- ` API error: ${error .response ?.data .message } `
510
+ ` Weather API error: ${error .response ?.data .message }`
477
511
);
478
512
}
479
513
throw error ;
@@ -482,11 +516,11 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
482
516
</Card >
483
517
484
518
<Card
485
- title = " Type Guards "
519
+ title = " Type Validation "
486
520
icon = " check"
487
521
>
488
522
``` typescript
489
- function isValidForecastArgs(args : unknown ): args is GetForecastArgs {
523
+ function isValidForecastArgs(args : any ): args is GetForecastArgs {
490
524
return (
491
525
typeof args === " object" &&
492
526
args !== null &&
@@ -495,71 +529,36 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
495
529
);
496
530
}
497
531
```
498
- </Card >
499
532
500
- <Card
501
- title = " Environment Variables"
502
- icon = " gear"
503
- >
504
- ``` typescript
505
- if (! process .env .OPENWEATHER_API_KEY ) {
506
- throw new Error (" OPENWEATHER_API_KEY is required" );
507
- }
508
- ```
509
- </Card >
510
-
511
- <Card
512
- title = " Constants"
513
- icon = " box"
514
- >
515
- ``` typescript
516
- const API_CONFIG = {
517
- BASE_URL: ' ...' ,
518
- ENDPOINTS: {
519
- CURRENT: ' weather' ,
520
- FORECAST: ' forecast'
521
- }
522
- } as const ;
523
- ```
533
+ <Tip >You can also use libraries like [ Zod] ( https://zod.dev/ ) to perform this validation automatically.</Tip >
524
534
</Card >
525
535
</CardGroup >
526
536
527
537
## Available transports
528
538
529
- While this guide uses stdio transport, MCP supports multiple transport options:
530
-
531
- ### WebSocket
532
- ``` typescript
533
- import { WebSocketServerTransport } from " @modelcontextprotocol/sdk/server/websocket.js" ;
534
- const transport = new WebSocketServerTransport ();
535
- ```
536
-
537
- ### SSE (Server-Sent Events)
538
- ``` typescript
539
- import { SSEServerTransport } from " @modelcontextprotocol/sdk/server/sse.js" ;
540
- const transport = new SSEServerTransport (" /events" , response );
541
- ```
539
+ While this guide uses stdio to run the MCP server as a local process, MCP supports other [ transports] ( /docs/concepts/transports ) as well.
542
540
543
541
## Troubleshooting
544
542
543
+ <Info >
544
+ The following troubleshooting tips are for macOS. Guides for other platforms are coming soon.
545
+ </Info >
546
+
545
547
### Build errors
546
548
``` bash
547
549
# Check TypeScript version
548
550
npx tsc --version
549
551
550
552
# Clean and rebuild
551
- rm -rf dist /
553
+ rm -rf build /
552
554
npm run build
553
555
```
554
556
555
557
### Runtime errors
556
- Look for detailed error messages in the Claude app logs:
558
+ Look for detailed error messages in the Claude Desktop logs:
557
559
``` bash
558
- # Launch Claude with logging
559
- open /Applications/Claude.app --stdout ~ /Claude.log --stderr ~ /Claude.log
560
-
561
560
# Monitor logs
562
- tail -f ~ /Claude.log
561
+ tail -n 20 - f ~ /Library/Application \ Support/ Claude/mcp * .log
563
562
```
564
563
565
564
### Type errors
0 commit comments