Back to Blog

What Are MCP Tools? A Practical Guide

Zaheer Ahmad
MCPToolsAgentLLMAutomationJSON-RPCFrameworksDeveloper Guidemcpevals

Introduction

The history of software has seen the rise of universal connectors that allow different systems to communicate effectively. Protocols like TCP/IP made networking possible, HTTP brought the web to life, and USB‑C standardized device connectivity. These technologies simplified complex integrations and unlocked new possibilities by providing a clear, consistent way for systems to work together.

Today, as intelligent tools like large language models (LLMs) begin to interact more directly with the real world—beyond just answering questions—there’s a growing need for a similar unifying layer. This is where the Model Context Protocol (MCP) steps in. It aims to serve as a universal connector for smart software, enabling AI agents to discover, access, and operate tools through a shared, standardized framework.

Instead of writing custom integrations for each new tool or API, developers can now expose tools via MCP, allowing agents to interact with them dynamically. A language model can generate Python scripts or SQL queries—and also create GitHub issues, perform web searches using BraveSearch, capture website snapshots via Puppeteer, or send messages in Slack—all through a single, unified protocol.

By focusing on what tools are available rather than how to call each API, MCP reduces redundant effort, minimizes integration overhead, and empowers AI systems to reason, act, and automate with greater efficiency.

architecture

Main idea: Instead of teaching every agent how to call every API, we just teach it to speak MCP and point it to a list of tools.

Table of Contents

  1. Introduction
  2. Top Public MCP Servers and Their Tools
  3. How MCP Tools Work: Agent-Server Interaction
  4. Anatomy of a Tool Descriptor
  5. Spinning Up a Minimal MCP Server
  6. Run and Test Your MCP Server
  7. Real-World Use
  8. Conclusion

Top Public MCP Servers and Their Tools

Server Tool Name(s) GitHub Repo / Docs
BraveSearch search_web, image_search, news_search arben-adm/brave-mcp-search
GitHub create_or_update_file, create_issue github/github-mcp-server
Slack post_message, list_channels, search_messages ubie-oss/slack-mcp-server
Browser Automation goto, click, screenshot, extract_text merajmehrabi/puppeteer-mcp-server
AWS S3 list_objects, get_object, put_object aws-samples/sample-mcp-server-s3
Postgres / Supabase exec_sql, list_tables supabase-community/supabase-mcp
SendGrid send_email, list_contacts Garoth/sendgrid-mcp
Twilio send_sms, call_number YiyangLi/sms-mcp-server
OpenAI Whisper transcribe_audio Apify Whisper Actor MCP
Replicate generate_image, transform_video deepfates/mcp-replicate

How MCP Tools Work: Agent-Server Interaction

MCP tools run on a set of straightforward principles that help AI agents find, use, and manage outside capabilities easily. These principles show up in every MCP Server interaction — from starting up to running a tool — and they create a clear and reusable way to automate things.

Every MCP Server interaction includes:

  • A simple handshake between the agent and the server
  • Tool discovery to find what capabilities are available
  • Using structured arguments to invoke tools
  • Receiving real-time feedback during execution

All of this follows clear guidelines and formats. They stick to a standard called JSON-RPC, which helps both sides communicate their abilities and keeps things clear during exchanges.

To see this in action, we'll look at the basic parts of MCP, backed by actual logs and examples. This will show how AI agents use MCP tools to think, act, and manage complex tasks easily and securely.

Pillar Purpose Example Log Explanation from Logs
Handshake Establish compatibility and initialize client-server context json{"method": "initialize", "params": {"protocolVersion": "2024-11-05", "clientInfo": {"name": "claude-ai"}}} Claude initializes communication with the MCP server, verifying supported protocol version and client metadata.
Discovery Agents need a catalog of available capabilities json{"method": "tools/list", "params": {}, "id": 1}{"result": {"tools": [{"name": "list-public-s3-buckets", ...}]}} Claude sends a tools/list request. The server responds with tool definitions including name, description, and schema.
Invocation Agents must be able to call tools with arguments json{"method": "tools/call", "params": {"name": "list-public-s3-buckets", "arguments": {}}} Claude invokes the tool using tools/call. The server executes and returns the result.
Context Maintain state or stream events from the server json{"method": "notifications/message", "params": {"data": "Found public bucket: test-bucket"}} The server streams live progress or insights via notifications/message to inform the agent of runtime context.
Error Handling Indicate unsupported or unknown features json{"id":3,"error":{"code":-32601,"message":"Method not found"}} When Claude attempts to call unsupported methods like resources/list, the server returns a method-not-found error.

architecture

These interactions allow AI agents to behave like software clients that negotiate with MCP servers in a structured, JSON-RPC–based protocol. For instance, in the MCP S3 Tool Logs, we observe:

  • An initial initialize handshake, where the client (e.g., Claude) and the MCP server agree on protocol versions and capabilities.
  • A tools/list call, which returns the catalog of available tools — such as list-public-s3-buckets.
  • A tools/call execution, where the agent invokes a selected tool. The server processes the request, executes the action, logs output, and streams the result back to the agent.

This clear flow — from initialization to discovery and invocation with well-defined input/output schemas — is what makes MCP tools both powerful and composable.

In the next sections, we’ll explore what a tool descriptor looks like, and how you can run your own MCP server with just a few lines of code.

Anatomy of a Tool Descriptor

Every MCP server has a bunch of tools that agents can find and use. Each tool comes with a descriptor, which is basically a JSON object that outlines what the tool does, what inputs it needs, and how it works.

Tool Descriptor Structure

{
  name: string;          // Unique identifier for the tool
  description?: string;  // Human-readable description
  inputSchema: {         // JSON Schema for the tool's parameters
    type: "object",
    properties: { ... }  // Tool-specific parameters
  },
  annotations?: {        // Optional hints about tool behavior
    title?: string;             // Friendly label for UI use
    readOnlyHint?: boolean;     // True if the tool does not modify state
    destructiveHint?: boolean;  // True if the tool performs deletions or mutations
    idempotentHint?: boolean;   // True if repeated calls return same result
    openWorldHint?: boolean;    // True if tool touches external systems
  }
}

Example: calculate_sum Tool

Here’s how you might expose a simple MCP tool called calculate_sum, which adds two numbers:

const server = new Server({
  name: "example-server",
  version: "1.0.0"
}, {
  capabilities: {
    tools: {}
  }
});

// Define the tool metadata
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [{
      name: "calculate_sum",
      description: "Add two numbers together",
      inputSchema: {
        type: "object",
        properties: {
          a: { type: "number" },
          b: { type: "number" }
        },
        required: ["a", "b"]
      }
    }]
  };
});

Tool Execution Logic

The server can handle execution by implementing the logic for tools/call:

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name === "calculate_sum") {
    const { a, b } = request.params.arguments;
    return {
      content: [
        {
          type: "text",
          text: String(a + b)
        }
      ]
    };
  }
  throw new Error("Tool not found");
});

Spinning Up a Minimal MCP Server

In this section, we'll create a basic MCP server using the mcp-framework in TypeScript. We'll register a simple tool named sum that adds two numbers.

Start by setting up your project:

# Install the framework globally
npm install -g mcp-framework

# Create a new MCP server project
mcp create my-mcp-server

cd my-mcp-server

# Add a new tool
mcp add tool sum

✅ Your server is now scaffolded and ready to customize.

Project structure after generation:

mcp_framework

sumtool_tools

Now, define the sum tool logic in src/tools/SumTool.ts:

// src/tools/SumTool.ts
import { MCPTool } from "mcp-framework";
import { z } from "zod";

interface SumInput {
  a: number;
  b: number;
}

class SumTool extends MCPTool<SumInput> {
  name = "sum";
  description = "Adds two numbers together";

  schema = {
    a: { type: z.number(), description: "First number" },
    b: { type: z.number(), description: "Second number" }
  };

  async execute({ a, b }: SumInput) {
    return a + b;
  }
}

export default SumTool;

Then build the server:

npm run build

build_tools build_folder

Your MCP server is now ready to expose the sum tool!

Run and Test Your MCP Server

Once your server is built, you can test your MCP tool over stdio using two methods.

🔧 Method 1: Manual Test via CLI

Navigate to your project root directory (where dist/index.js is located) and run the following command:

echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"sum","arguments":{"a":5,"b":7}}}' | node dist/index.js

run_test

Expected Output:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "12"
      }
    ]
  }
}

This confirms the tool is working correctly via stdio.

🔍 Method 2: Test with mcp-inspector

You can also use the mcp-inspector tool to validate your MCP server using stdio.

  1. Open Terminal 1 and start your MCP server manually:

    node dist/index.js
    
  2. In Terminal 2, launch the MCP Inspector:

    npx @modelcontextprotocol/inspector
    

    mcp_inspector

  3. Navigate to the MCP Inspector UI at: http://localhost:6274

  4. In the UI:

    • Set the Transport Type to STDIO

    • Command: node

    • Argument: Provide the absolute path to your built file, e.g.:

      /home/zaheer/my-mcp-server/dist/index.js
      

This method gives you a visual interface to test your tool behavior, inspect logs, and validate schema compliance.

inspector_ui_tools

Real-World Use

  • Anthropic Claude Desktop comes with an MCP client, letting local models work with Git repos.
  • Replit Ghostwriter uses MCP to run tests and set up previews.
  • Sourcegraph Cody creates pull requests through MCP calls.
  • Community servers are already set up for BraveSearch, Slack, Browser Automation, OpenAI Whisper, Twilio, Supabase, and AWS S3.

Conclusion

The Model Context Protocol (MCP) changes how AI agents work with software by creating a common interface for accessing tools. It simplifies things by removing extra code and making automation easier, all while keeping things manageable.

If you're setting up internal tasks or working with external tools, MCP provides a solid base to integrate everything smoothly into your AI setup.

What to do next? Pick one tool, set it up with MCP, and watch your agents take over from there.