Ever since the AI boom, it feels like everyone wants to integrate AI into their applications to supercharge the user experience.
Here is what I've learned: standard AI models and search engines are fantastic at fetching publicly available information. However, our custom applications rely on private data securely tucked away in our own databases. An out-of-the-box LLM can't just magically see what's inside our private DB!
So, how do we bridge the gap?
I discovered that major AI providers—like OpenAI, Anthropic, and Gemini actually give us a way to let their models interact directly with our applications.
To make this magic happen, we write a specific piece of code called a tool (or function calling).
This tool acts as a smart middleman that tells the AI exactly how to fetch the right information from our app.
The workflow is so cool and looks exactly like this:
User Query --> LLM --> Tool --> Your Server --> Your DB
But here is the current puzzle I’m trying to solve: the setup isn't universal!
Every LLM provider gives a each unique way to interact.
For example, Lets setup a simple server with node and express.
const express = require("express");
const app = express();
const PORT = 3000;
app.use(express.json());
let employees = [
{
id: 1,
name: "John Doe",
salary: 50000,
location: "Bangalore"
},
{
id: 2,
name: "Jane Smith",
salary: 70000,
location: "Chennai"
}
];
app.get("/employees", (req, res) => {
res.status(200).json({
success: true,
data: employees
});
});
app.get("/employees/:id", (req, res) => {
const id = Number(req.params.id);
const employee = employees.find(emp => emp.id === id);
if (!employee) {
return res.status(404).json({
success: false,
message: "Employee not found"
});
}
res.status(200).json({
success: true,
data: employee
});
});
app.post("/employees", (req, res) => {
const { name, salary, location } = req.body;
if (!name || !salary || !location) {
return res.status(400).json({
success: false,
message: "name, salary and location are required"
});
}
const newEmployee = {
id: employees.length
? Math.max(...employees.map(emp => emp.id)) + 1
: 1,
name,
salary,
location
};
employees.push(newEmployee);
res.status(201).json({
success: true,
message: "Employee created successfully",
data: newEmployee
});
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
I've exposed 3 endpoints
GET/employees -> gives all the list of employees
GET/employees/:id -> gives an employee detail
POST/employees -> creates a new employee
I didn't used any db here. Since its only for demo purpose.
I'd like to focus on only one endpoint now. For more endpoints you can refer my github
Now I want my server to interact with claude.
I need to setup my tool, This is the information about your endpoint.
tools: [
{
name: "getEmployees",
description: "Get all employees",
input_schema: {
type: "object",
properties: {}
}
}
]
if I wish my server to interact with gemini, i have to write my tool like this.
const tools = [
{
functionDeclarations: [
{
name: "getEmployees",
description: "Get all employees",
parameters: {
type: "OBJECT",
properties: {}
}
}
]
}
];
if I wish to use open ai. My tool would be,
const tools = [
{
type: "function",
function: {
name: "getEmployees",
description: "Get all employees",
parameters: {
type: "object",
properties: {}
}
}
}
];
There is a next step in which we have to initiate the respective model and handle the tool call. But the core relies on this tool.
Now here comes the MCP to make it universal like an USB-c port for all phones.
MCP provides a way to declare the tools in one config and make use of it in all LLM's.
mcp-server.js file would be like
const { McpServer } = require("@modelcontextprotocol/sdk/server/mcp.js");
const { StdioServerTransport } = require("@modelcontextprotocol/sdk/server/stdio.js");
const server = new McpServer({
name: "employee-server",
version: "1.0.0",
});
server.tool(
"getEmployees",
"Get all employees",
{},
async () => {
return {
content: [
{
type: "text",
text: JSON.stringify(employees, null, 2),
},
],
};
}
);
Now I jus need to run this server when my custom server runs. Thats all. Now I can access this server in my claude desktop.
Although you need to provide the config detail in the claude_desktop_config.json
So that my claude desktop would know about this mcp-server.
{
"mcpServers": {
"employee-server": {
"command": "node",
"args": [
"your-project-folder/mcp-server.js"
]
}
}
}
I'm attaching the screenshots from my claude-desktop for your reference.
I hope this would clarify why we need mcp in our application.


Top comments (0)