Tools: Understanding MCP Through a Simple Example: A Practical Introduction

Tools: Understanding MCP Through a Simple Example: A Practical Introduction

Source: Dev.to

A Personal Take First ## The Learning Goal ## What MCP Actually Does ## The Example Architecture ## Look at the MCP tool definition: ## Why This Simple Example Matters ## See It Working ## Setting It Up (For Learning Purposes) ## The Real Takeaway ## Potential Use Cases (Beyond This Simple Example) ## Check Out The Code I’ve been working with MCP fairly often and like most of us, I learn best by actually building something. Not something production-ready or revolutionary — just something simple enough to understand what MCP actually does. That’s why I built a basic currency converter using MCP. It’s intentionally simple, but that’s the point. Let me walk you through what can be learned from this example. When new protocols and frameworks come out, I want to answer one question: “What problem does this actually solve?” This currency converter teaches exactly how MCP works, and that’s worth sharing. Before writing any code, I want you to understand one specific thing: How does AI actually communicate with external tools through MCP? Here’s what I learned by building this: My simple implementation looks like this: This tool just returns exchange rates. That’s it. The AI takes care of everything else. Now Let’s take a closer look at the implementation steps together. 1- User sends natural language prompt 3- API gets list of provided MCP server tools (get_exchange_rate) 5- Claude AI interprets When user wants an action that provided in tools get_exchange_rate 6- In the interception step API calls MCP tool, getting the actual rate 7- API sends another request to Claude AI including actual rate + prompt 8- User gets their answer Here’s what this simple example demonstrates: 1.** Tool Discovery** The AI can see what tools are available and understand when to use them based on the description. I recorded a quick demo showing different types of queries being handled: Press enter or click to view image in full size Nothing fancy, just the basic flow working as expected. If you want to try this yourself to understand MCP: Then just send POST requests with natural language prompts: After building this simple example, We now understand: MCP is not about building smarter APIs. It’s about building simple, focused tools and letting AI be the smart layer that connects them to human intent. Your tool can be dumb. It should be dumb. Just do one thing well, and let AI the rest. While the currency converter is basic, the pattern scales to more interesting problems, have a look to these examples. The complexity isn’t in MCP itself — it’s in the tools you build and connect. The full repository includes: Feel free to clone it, modify it, or use it as a reference while learning MCP yourself. Are you learning MCP too? Have you built simple examples to understand new tech? I’d love to hear about it — drop a comment! P.S. — If this helped you understand MCP a bit better, give it a like! And remember: simple examples are valid examples. Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse CODE_BLOCK: You: "Is ¥10,000 enough to buy a $60 game?" AI: "I don't have access to current exchange rates, but you can check [some website]." Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: You: "Is ¥10,000 enough to buy a $60 game?" AI: "I don't have access to current exchange rates, but you can check [some website]." CODE_BLOCK: You: "Is ¥10,000 enough to buy a $60 game?" AI: "I don't have access to current exchange rates, but you can check [some website]." CODE_BLOCK: You: "Is ¥10,000 enough to buy a $60 game?" AI: 1. Realizes it needs an exchange rate 2. Sees there's a get_exchange_rate tool available 3. Calls: get_exchange_rate(from="JPY", to="USD", amount=10000) 4. Gets: 10000 JPY = 65.83 USD 5. Responds: "Yes, ¥10,000 is approximately $65.83 USD, so you'd have $5.83 left after buying the game." The key insight: MCP is just a standardized way for AI to discover and use your tools. Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: You: "Is ¥10,000 enough to buy a $60 game?" AI: 1. Realizes it needs an exchange rate 2. Sees there's a get_exchange_rate tool available 3. Calls: get_exchange_rate(from="JPY", to="USD", amount=10000) 4. Gets: 10000 JPY = 65.83 USD 5. Responds: "Yes, ¥10,000 is approximately $65.83 USD, so you'd have $5.83 left after buying the game." The key insight: MCP is just a standardized way for AI to discover and use your tools. CODE_BLOCK: You: "Is ¥10,000 enough to buy a $60 game?" AI: 1. Realizes it needs an exchange rate 2. Sees there's a get_exchange_rate tool available 3. Calls: get_exchange_rate(from="JPY", to="USD", amount=10000) 4. Gets: 10000 JPY = 65.83 USD 5. Responds: "Yes, ¥10,000 is approximately $65.83 USD, so you'd have $5.83 left after buying the game." The key insight: MCP is just a standardized way for AI to discover and use your tools. CODE_BLOCK: { name: "get_exchange_rate", description: "Get exchange rate between currencies", inputSchema: { type: "object", properties: { from_currency: { type: "string" }, to_currency: { type: "string" }, amount: { type: "number", optional: true } } } } Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: { name: "get_exchange_rate", description: "Get exchange rate between currencies", inputSchema: { type: "object", properties: { from_currency: { type: "string" }, to_currency: { type: "string" }, amount: { type: "number", optional: true } } } } CODE_BLOCK: { name: "get_exchange_rate", description: "Get exchange rate between currencies", inputSchema: { type: "object", properties: { from_currency: { type: "string" }, to_currency: { type: "string" }, amount: { type: "number", optional: true } } } } CODE_BLOCK: "Is ¥10,000 enough to buy a $60 game?" Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: "Is ¥10,000 enough to buy a $60 game?" CODE_BLOCK: "Is ¥10,000 enough to buy a $60 game?" CODE_BLOCK: app.post('/api/chat') const { prompt } = await c.req.json(); Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: app.post('/api/chat') const { prompt } = await c.req.json(); CODE_BLOCK: app.post('/api/chat') const { prompt } = await c.req.json(); CODE_BLOCK: const tools = await mcpClient.listTools(); 4- API Sends prompt + tools to Claude AI const response = await anthropic.messages.create({ tools: tools, messages: [{ role: 'user', content: prompt }] }); Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: const tools = await mcpClient.listTools(); 4- API Sends prompt + tools to Claude AI const response = await anthropic.messages.create({ tools: tools, messages: [{ role: 'user', content: prompt }] }); CODE_BLOCK: const tools = await mcpClient.listTools(); 4- API Sends prompt + tools to Claude AI const response = await anthropic.messages.create({ tools: tools, messages: [{ role: 'user', content: prompt }] }); COMMAND_BLOCK: while (response.stop_reason === 'tool_use') const toolUse = response.content.find(block => block.type === 'tool_use'); Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: while (response.stop_reason === 'tool_use') const toolUse = response.content.find(block => block.type === 'tool_use'); COMMAND_BLOCK: while (response.stop_reason === 'tool_use') const toolUse = response.content.find(block => block.type === 'tool_use'); CODE_BLOCK: const toolResult = await mcpClient.callTool({ name: toolUse.name, arguments: toolUse.input, }); Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: const toolResult = await mcpClient.callTool({ name: toolUse.name, arguments: toolUse.input, }); CODE_BLOCK: const toolResult = await mcpClient.callTool({ name: toolUse.name, arguments: toolUse.input, }); CODE_BLOCK: response = await anthropic.messages.create({ tools: tools, messages: [ { role: 'user', content: prompt }, // original prompt { role: 'user', content: [{ type: 'tool_result', tool_use_id: toolUse.id, content: JSON.stringify(toolResult.content) // rate info }] } ] }); Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: response = await anthropic.messages.create({ tools: tools, messages: [ { role: 'user', content: prompt }, // original prompt { role: 'user', content: [{ type: 'tool_result', tool_use_id: toolUse.id, content: JSON.stringify(toolResult.content) // rate info }] } ] }); CODE_BLOCK: response = await anthropic.messages.create({ tools: tools, messages: [ { role: 'user', content: prompt }, // original prompt { role: 'user', content: [{ type: 'tool_result', tool_use_id: toolUse.id, content: JSON.stringify(toolResult.content) // rate info }] } ] }); CODE_BLOCK: const finalText = response.content return finalText // Yes, ¥10,000 is approximately $65.83 USD, // so you'd have $5.83 left after buying the game Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: const finalText = response.content return finalText // Yes, ¥10,000 is approximately $65.83 USD, // so you'd have $5.83 left after buying the game CODE_BLOCK: const finalText = response.content return finalText // Yes, ¥10,000 is approximately $65.83 USD, // so you'd have $5.83 left after buying the game CODE_BLOCK: “Is ¥10,000 enough for $60?” → from="JPY", to="USD", amount=10000 “How many dollars is 50 euros?” → from="EUR", to="USD", amount=50 Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: “Is ¥10,000 enough for $60?” → from="JPY", to="USD", amount=10000 “How many dollars is 50 euros?” → from="EUR", to="USD", amount=50 CODE_BLOCK: “Is ¥10,000 enough for $60?” → from="JPY", to="USD", amount=10000 “How many dollars is 50 euros?” → from="EUR", to="USD", amount=50 CODE_BLOCK: “I have 5 euros in cash and 20 in my bank, total in USD?” AI does: 5 + 20 = 25, then calls the tool with 25 EUR Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: “I have 5 euros in cash and 20 in my bank, total in USD?” AI does: 5 + 20 = 25, then calls the tool with 25 EUR CODE_BLOCK: “I have 5 euros in cash and 20 in my bank, total in USD?” AI does: 5 + 20 = 25, then calls the tool with 25 EUR COMMAND_BLOCK: git clone https://github.com/hshoja/Currency-Exchange-MCP-Service npm install cp env.example .env # Add your API keys to .env npm run dev Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: git clone https://github.com/hshoja/Currency-Exchange-MCP-Service npm install cp env.example .env # Add your API keys to .env npm run dev COMMAND_BLOCK: git clone https://github.com/hshoja/Currency-Exchange-MCP-Service npm install cp env.example .env # Add your API keys to .env npm run dev CODE_BLOCK: { "prompt": "What is 100 USD in EUR?" } Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: { "prompt": "What is 100 USD in EUR?" } CODE_BLOCK: { "prompt": "What is 100 USD in EUR?" } - User sends natural language prompt - Hono API receives it - API gets list of provided MCP server tools (get_exchange_rate) - API Sends prompt + tools to Claude AI - Claude AI interprets when user wants a tool - In the interception step API calls MCP tool, getting the actual rate - API sends another request to Claude AI including actual rate + prompt - User gets their answer It’s basic. And that’s exactly why it’s useful for learning. - Parameter Extraction The AI automatically extracts structured parameters from messy natural language: - Context Awareness The AI can handle complex queries: - Natural Responses The AI formats the tool’s response naturally instead of just dumping JSON. - Anthropic API key (for Claude AI) - Freecurrencyapi key (for exchange rates) - AI Agent Crypto MCP Trading : an example which shows how create an mcp that opens or closes positions in a crypto platform by natural language - Kali Linux HACKING MCP : running kali commands for hacking by natural language - Natural language to SQL: connect and query the database by natural language - Building an agentic appointment scheduling app