Getting started

JavaScript (Node)

Let's Build a Weather Tool with MCP and an AI Client

Want to teach an AI how to check the weather? You're in the right place. This guide walks you through building a simple tool using the Model Context Protocol (MCP), which lets your code talk directly to AI assistants.

We'll use Claude Desktop as an example AI client in this guide because it has built-in support for MCP — but the tool you build can work with any AI that understands MCP, like ChatGPT Desktop or Raycast AI, for example.


Setup Hackatime

You'll need to use Hackatime to track your coding time. Hackatime works on all major code editors.

Set it up with the instructions here: https://hackatime.hackclub.com


What is MCP?

In short, MCP (Model Context Protocol) servers allow AI to connect to real tools. Think of it as USB ports for AI apps.

Here's how it works:

  • You define what inputs your tool needs
  • You write a function that does something useful with those inputs
  • MCP acts as the bridge so the AI can understand how to use it

Setting Up Your Project

We'll be writing this in JavaScript with NodeJS. You can install NodeJS from https://nodejs.org/

I'm going to call my project mcp-weather-server.

In a new folder called your project name, let's initialize a project.

npm init -y

Install the MCP SDK:

npm install @modelcontextprotocol/sdk

If you're on an older Node version (<18.0.0), run npm install node-fetch as well.


Writing Your Tool

Create a file called index.js. We'll build this step-by-step.

1. Add the shebang

At the very top of your index.js file, add this line:

#!/usr/bin/env node

This tells the system how to run your script and makes it executable on all platforms.

2. Import the libraries

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

3. Create the MCP server

const server = new McpServer({
  name: "mcp-weather-server",
  version: "1.0.0"
});

4. Define what input the tool expects

The input schema defines what the AI should input to your tool.

In this case: a city name.

const inputSchema = {
  city: z.string().describe("The city to get the weather for. Needs to be a big city.")
};

Side note: You can make fields optional in the schema by using .optional() in Zod. For example: z.string().optional() would make that input not required. This can be useful if your tool supports multiple input paths or you want to provide fallback behavior.

5. Write the function that does the work

async function getWeather({ city }) {
  const response = await fetch(`https://goweather.xyz/weather/${city.toLowerCase()}`);
  if (!response.ok) {
    throw new Error(`Couldn't get weather for ${city}`);
  }

  const data = await response.json();

  return {
    content: [{ type: "text", text: JSON.stringify(data) }]
  };
}

If you need to add additional fields, just expand the parameters of the function. For example: getWeather({ city, isMetric }).

6. Register the tool

Now connect the schema and the function together and register it to our server so it can be accessed.

server.registerTool("weather", {
  title: "Weather Tool",
  description: "Get the weather for a city",
  inputSchema,
}, getWeather);

7. Start the MCP server

There are multiple transport methods for MCP servers (how your AI connects to the MCP server).

We'll be using StdioServerTransport, which works great locally.

const transport = new StdioServerTransport();
await server.connect(transport);

Testing it locally

MCP comes with a really cool inspector. To run it, simply enter the following command:

npx @modelcontextprotocol/inspector node index.js

You'll get a URL in the console that you can open. Simply click the connect button on the bottom left!


Testing It in Claude Desktop (or another AI Client)

For local development testing, if you're using Claude Desktop:

  1. Open settings found in the top left (not by clicking your user name)
  2. In the Developer tab, click "Edit Config" — a file should pop up!
  3. Open the config file in VS Code or the editor of your choice
  4. We need to build a config file that tells Claude how to access our MCP server for local testing
    {
      "mcpServers": {
        "weather": {
          "command": "node",
          "args": [
            "/full/path/to/mcp-weather-server/index.js"
          ]
        }
      }
    }

    Replace /full/path/to/mcp-weather-server/ with the actual path to your project folder

If you need environment variables (for API keys, configs, etc.), you can define them in the config like this

  1. Quit and re-open Claude Desktop
  2. If you go back to the Developer tab, your MCP server should show up
  3. Try it out! Ask Claude something like: "What's the weather in Berlin?"

If all goes well, Claude should show the result returned by your tool. Other AI clients that support MCP may offer similar functionality.


Packaging and Publishing Your Tool

We need to package and publish our MCP server to make it easy for others to use.

1. Create a bin entry point

In your package.json, add this line:

"bin": {
  "mcp-weather-server": "index.js"
},

This tells npm to treat index.js as a command-line app called mcp-weather-server.

Note: We already added the shebang #!/usr/bin/env node at the beginning of our file in step 1, so our script is ready to run on all systems!

2. Publish to npm

This is just a tutorial — don't actually run the publish command unless you're shipping your own version. But if you were building your own app, you would run these to publish to npm.

First, make sure you're logged in:

npm login

And then publish it:

npm publish

Anyone can now run your server with your config file!

3. Config for Published Package

Once your package is published to npm, others (and you) can use it with a simpler config:

{
  "mcpServers": {
    "weather": {
      "command": "npx",
      "args": [
        "mcp-weather-server"
      ]
    }
  }
}

This approach uses npx to automatically download and run your published package, making it much easier for others to use your tool!


What's Next?

Now that you've got the basics, try branching out. Your AI client can use any tool — as long as you define inputs and return something usable.

Here are some inspiration, but you should come up with something else!

  • Pull info from other APIs (Wikipedia, Crypto prices, NASA, anything)
  • Automate stuff locally (play a sound, take a screenshot, launch apps)
  • Build utilities (unit converter, joke fetcher, motivational quote machine)
  • Fetch a random XKCD comic
  • Turn on your smart lights
  • Log thoughts to a text file
  • Update you on the most recent news stories

Submission requirements

To submit you must:

  • Have all your code in a public GitHub repo
  • Publish your server to npm
  • Have a README in your GitHub repo with a description and installation instructions (including the config file)

If you need any help, reach out in the #toolsmith Slack channel!

Ready to Submit?

Once you've built your MCP tool and tested it, you can submit it to earn your $10 in AI credits!

Submit Your Tool