What Are MCP Tools? A Practical Guide
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.
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
- Introduction
- Top Public MCP Servers and Their Tools
- How MCP Tools Work: Agent-Server Interaction
- Anatomy of a Tool Descriptor
- Spinning Up a Minimal MCP Server
- Run and Test Your MCP Server
- Real-World Use
- 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. |
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 aslist-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:
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
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
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
.
-
Open Terminal 1 and start your MCP server manually:
node dist/index.js
-
In Terminal 2, launch the MCP Inspector:
npx @modelcontextprotocol/inspector
-
Navigate to the MCP Inspector UI at: http://localhost:6274
-
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.
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.