Skip to main content
Glama
nethravathik409-ui

mcp-server-tools-assignment

README.md
# Assignment 2: MCP Server with 5 Tools

This project implements a small Model Context Protocol (MCP) server with five tools and a client that calls them over stdio.

## What this project does

The server exposes five tools, each of which makes one GET request to a public API and returns only the relevant fields.

| Tool | Input | Public API | Returned data |
| --- | --- | --- | --- |
| `weather` | `city` | `https://wttr.in/{city}?format=j1` | `city`, `temp_c`, `condition`, `humidity` |
| `country_info` | `name` | `https://restcountries.com/v3.1/name/{name}` | `name`, `capital`, `region`, `population`, `currencies`, `languages` |
| `exchange_rates` | `base` | `https://open.er-api.com/v6/latest/{base}` | base currency + selected rates |
| `public_holidays` | `year`, `country_code` | `https://date.nager.at/api/v3/PublicHolidays/{year}/{country_code}` | list of holiday objects with `date`, `localName`, `name` |
| `define_word` | `word` | `https://api.dictionaryapi.dev/api/v2/entries/en/{word}` | `word` and one or more short definitions |

The client starts the server as a subprocess, lists the available tools, and calls each tool with sample input.

## Project structure

```text
mcp-server-tools-assignment/
├── client/
│   └── client.py
├── server/
│   ├── http.py
│   ├── server.py
│   └── tools/
│       ├── country.py
│       ├── dictionary.py
│       ├── exchange.py
│       ├── holidays.py
│       └── weather.py
├── config.py
├── README.md
├── requirements.txt
└── .venv/
```

## Setup

```bash
cd mcp-server-tools-assignment
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r requirements.txt
```

## Run the server directly

```bash
cd mcp-server-tools-assignment
. .venv/bin/activate
python -m server.server
```

This starts the MCP server over stdio.

## Run the client

```bash
cd mcp-server-tools-assignment
. .venv/bin/activate
python client/client.py
```

This launches the server, lists the available tools, and calls each tool with sample data.

## Notes on behavior

- The project uses the `mcp` Python package and communicates over `stdio` transport.
- The server and client are separate Python programs.
- Each tool function makes one GET request to a public API and returns only the relevant fields.
- Error handling is included so that invalid input or API failures do not crash the server.

## Section 7 test cases and output

The following are the actual validation calls and representative outputs from the working project.

### 1) Weather

```python
{'city': 'Mumbai'}
```

Output:

```text
CASE:weather
{'meta': None, 'content': [{'type': 'text', 'text': '{\n  "city": "Mumbai",\n  "temp_c": 28.0,\n  "condition": "Light rain shower",\n  "humidity": 78\n}', 'annotations': None, 'meta': None}], 'structuredContent': None, 'isError': False}
```

### 2) Country info

```python
{'name': 'India'}
```

Output:

```text
CASE:country_info
{'meta': None, 'content': [{'type': 'text', 'text': '{\n  "name": "India",\n  "capital": "New Delhi",\n  "region": "Asia",\n  "population": 1380004385,\n  "currencies": [\n    "INR"\n  ],\n  "languages": [\n    "Hindi",\n    "English"\n  ]\n}', 'annotations': None, 'meta': None}], 'structuredContent': None, 'isError': False}
```

### 3) Exchange rates

```python
{'base': 'USD'}
```

Output:

```text
CASE:exchange_rates
{'meta': None, 'content': [{'type': 'text', 'text': '{\n  "base": null,\n  "rates": {\n    "USD": 1,\n    "EUR": 0.862295,\n    "INR": 95.581563,\n    "GBP": 0.738249,\n    "JPY": 160.045067,\n    "AUD": 1.395915,\n    "CAD": 1.389176,\n    "SGD": 1.273831\n  }\n}', 'annotations': None, 'meta': None}], 'structuredContent': None, 'isError': False}
```

### 4) Public holidays

```python
{'year': 2025, 'country_code': 'US'}
```

Output:

```text
CASE:public_holidays
{'meta': None, 'content': [{'type': 'text', 'text': '{\n  "date": "2025-01-01",\n  "localName": "New Year\'s Day",\n  "name": "New Year\'s Day"\n}', ... ], 'structuredContent': None, 'isError': False}
```

The output contains multiple holiday records, which confirms the tool is returning a non-empty list.

### 5) Dictionary lookup

```python
{'word': 'example'}
```

Output:

```text
CASE:define_word
{'meta': None, 'content': [{'type': 'text', 'text': '{\n  "word": "example",\n  "definitions": [\n    {\n      "partOfSpeech": "noun",\n      "meaning": "A thing characteristic of its kind or illustrating a general rule."\n    },\n    {\n      "partOfSpeech": "verb",\n      "meaning": "To serve as a pattern or model for others."\n    }\n  ]\n}', 'annotations': None, 'meta': None}], 'structuredContent': None, 'isError': False}
```

### 6) Failure path test

```python
{'word': 'asdfghjkl'}
```

Output:

```text
CASE:define_word
{'meta': None, 'content': [{'type': 'text', 'text': '{\n  "word": "asdfghjkl",\n  "definitions": [],\n  "error": "not found"\n}', 'annotations': None, 'meta': None}], 'structuredContent': None, 'isError': False}
```

This confirms the tool does not crash on a nonsense word; it returns a clean `not found` response, while valid words return real definitions.

## Requirements

```text
mcp<2
requests>=2.31.0
```

## Purpose of the assignment

This assignment demonstrates how an MCP server exposes tools, how a client discovers them, and how the client calls them over stdio. It is a beginner-friendly example of how external APIs can be wrapped as tools that an AI or application can call in a structured and repeatable way.