DEV Community

Cover image for Model Context Protocol (MCP): Explained & Built from Scratch.
Naman Raj
Naman Raj

Posted on

Model Context Protocol (MCP): Explained & Built from Scratch.

Hi, I’m Naman a full stack developer.
In this blog, I’m diving into the Model Context Protocol (MCP): what it is, why it matters, and how I went about building my own MCP server from the ground up.
This will be a detailed breakdown: first, we’ll explore all the core concepts of MCP, and then we’ll put that knowledge to work by building a functional MCP server from scratch.
Whether you're just hearing about MCP or looking to implement it yourself, this post breaks it down both conceptually and practically

🧩 What is the Model Context Protocol (MCP)?

The Model Context Protocol (MCP) is basically a way for different parts of a system to talk to each other but with context.

It’s not just about asking the system to do something, it’s about helping it understand the situation around that action. So instead of just saying “do X,” you're saying “do X, knowing that Y and Z are also true right now.”

dimage ke upar se gya(sounds a bit vague), here’s a simple example:

Let’s say you walk into a coffee shop and say, “I’ll have a latte.”
A regular system gives you a latte, no questions asked.
But a system using context? That’s the barista who notices it’s raining, sees you’re soaked, and decides to make your latte extra hot and finds you a warm seat inside.
That’s what context does. And that’s the idea behind MCP, it helps systems make better decisions based on what’s going on around them
.

🧭 Where Did MCP Come From?

MCP actually started off in the Minecraft modding scene yeah, really. Developers used it to understand and tweak how the game behaved internally.

Over time, the concept became more general. Now, it's useful in things like AI systems, backend workflows, and apps where understanding the bigger picture matters

🔍 Why MCP?

Most systems work in a straightforward way. You send a request, they do something.

For example:
“Give me the user data”
“Update this post”
“Delete that file”

That works fine when everything is simple. But when your system needs to make decisions based on what’s happening, those basic calls fall short.

That’s where MCP comes in. It asks questions like:
What’s the current state of the system?
What just happened before this command?
Should we respond differently depending on the situation?

System ko thoda samajhdaar banane jaisa hai, jaise backend ko bol diya ho, "bhai, thoda dimaag laga."
(It’s like giving your backend a bit more awareness as if you’ve told it, “bro, use your brain a little.”)
Aur jab system fast changing ho, jaise AI tools ya complex workflows fir to bhai waha yeh samajh bohot kaam aata hai.
(And when your system is fast changing like AI tools or workflow engines that extra awareness really helps.)

🛠 Real Life Example: Your Desi Smart Assistant

Imagine you’ve got a smart assistant at home let’s call it “Marco AI.”
Now you say:

“Marco, light band kar de.”
(“Marco, turn off the lights.”)

If it’s a basic assistant, it'll just go:
Poof. Lights off. Kaam khatam.

But if it's context-aware using something like MCP, here’s how it might think:

  • Time check: Oh, it’s 11:30 PM.
  • Motion detection: There’s still someone moving in the kitchen.
  • Recent command: You just said “Good night” 2 minutes ago in the bedroom.

So now instead of killing all the lights like a power cut:

  • It only turns off the bedroom light, not the kitchen one (because someone's still grabbing water).
  • It starts your night routine: turns on DND on your phone, lowers fan speed, and maybe even plays that lo-fi playlist you always fall asleep to.
  • And yeah, it doesn’t turn off the bathroom light because you left it on and MCP knows you always forget.

Yeh wahi baat hai — ek normal banda bolta hai “light band kar,” aur doosra poochta hai, “kaunsi? sab ki?
(It’s the difference between someone who follows orders and someone who thinks before acting.)

🔧 2. Core Concepts of MCP

The beauty of MCP lies in how it structures communication between models, making them aware of the environment they’re operating in. Think of it as building systems that “know what’s going on” instead of blindly executing commands.

🧠 2.1 Model-Context Design
In MCP, a “context” is a set of facts or environmental data that helps a model understand what’s happening right now. This includes things like:

  • The current state of the system
  • Recent events or actions
  • Inputs from other models
  • External data like time, user info, etc

Why it matters:
Instead of just saying "do task X", you're saying:

Do task X, but keep in mind we’re in state Y, action Z just happened, and model A is waiting on your output.

Example: If a user says “cancel my subscription” in an app, the model doesn’t just delete the plan it checks:

  • Did the user already initiate a refund request?
  • Are there any active services running?
  • Is there a promotion that could retain them?

🧾 2.2 Command-based Architecture
MCP systems rely on a command driven flow like a structured conversation where each action is a clearly defined message.

A command is not just an API call or function; it’s a semantic instruction:

CreateOrder
UpdateInventory
NotifyUser
EvaluateResponse

Each command carries:

  • Intent: What action is requested
  • Context: What the system knows right now
  • Payload: Any required data (e.g., user ID, product ID)

This makes it easy to track, test, and extend behavior. Think of it like building with Lego blocks each command has a clear shape and job and can plug into other parts cleanly.

📦 2.3 State Handling
MCP treats state as a first-class citizen. That means each model doesn’t just operate in isolation, it shares and consumes state via a central context manager or store.

Key aspects of state handling:

  • Models read from shared context
  • They update the context with new outcomes
  • The context flows with the execution kind of like a memory that travels

Let’s say you’re using GitHub Copilot in Agent mode, and you switch between different models during the session say from GPT-4 to Claude 3 Sonnet, or Gemini 2.5.

Despite switching models, your session context stays intact:

  • Your previous code
  • The task you're working on
  • The error you just ran into
  • Even the last thing you asked the assistant

“Model badal gaya, par yaadein wahi rahi. 😂”
(The model changed, but the memories stayed the same.)

That’s basically how MCP handles state like a central memory bank all models read from and write to. So whether it’s one model or many, they all operate with a shared understanding of ‘what’s going on’

This is what allows things like:

  • Chaining responses across models
  • Smarter multi-agent reasoning
  • Being able to "pause and resume" with full context

🧩 2.4 Decoupling Logic
This is where MCP really shines. By using commands + shared context, MCP naturally leads to modular and decoupled system design.

What this means in practice:

  • Each model (or agent) focuses on its specific job
  • No model needs to know how others work internally
  • Communication happens only via commands and context not direct calls or dependencies

This makes systems:

  • Easier to scale
  • Easier to test (you can unit-test models independently)
  • Easier to swap in new models (AI version A to version B, for example)
  • Less fragile one model crashing doesn't break the others

🧠 MCP Server Architecture Explained

The Model Context Protocol (MCP) Server is a modular system designed to handle model driven command execution with a focus on tools, resources, and prompt management. This architecture is scalable, extensible, and supports multiple transport protocols and storage backends.

Here is the architecture diagram (Zoom in) ⬇️

architecture diagram

📦 Components Breakdown

1. Transport Layer
The Transport Layer handles the actual communication between the AI client and your MCP server. Think of it as the "delivery method" for messages.

STDIO Transport:

const transport = new StdioServerTransport();
Enter fullscreen mode Exit fullscreen mode
  • Uses standard input/output streams
  • Most common for local MCP servers
  • No network configuration required
  • Direct process-to-process communication

HTTP Transport:

const transport = new HTTPServerTransport();
Enter fullscreen mode Exit fullscreen mode
  • Uses HTTP protocol over network
  • Useful for remote MCP servers
  • Requires port and URL configuration
  • Can handle multiple concurrent clients

WebSocket Transport:

const transport = new WebSocketTransport();
Enter fullscreen mode Exit fullscreen mode
  • Real-time bidirectional communication
  • Good for streaming data
  • Maintains persistent connections
  • Lower latency than HTTP

Custom Transport:

  • You can implement your own transport method
  • Must follow MCP protocol specifications
  • Useful for specialized communication needs

2. Command Dispatcher
The Command Dispatcher is the "traffic controller" of your MCP server. It receives all incoming requests and decides where to send them.

  • Request Analysis: Examines the incoming JSON-RPC message
  • Route Determination: Decides which handler should process the request
  • Schema Validation: Ensures request format is correct

Example Request Routing:

// Incoming request
{
  "method": "tools/call",
  "params": { "name": "get_completed_payments" }
}

// Router logic
if (method === "tools/call") {
  route_to_tools_handler();
} else if (method === "resources/read") {
  route_to_resources_handler();
}
Enter fullscreen mode Exit fullscreen mode

This code is like a traffic cop 🚦:

If the request says "tools/call" → send it to the Tools Handler
If it says "resources/read" → send it to the Resources Handler

3. Handler Components
The server has three main types of handlers, each responsible for different MCP capabilities:

3.1 Tools Handler
Processes executable functions that perform actions.

Handles Two Request Types:
tools/list: Returns available tools
tools/call: Executes a specific tool

Example Implementation:

// tools/list response
{
  "tools": [
    {
      "name": "weather_forecast",
      "description": "Get weather forecast for a location",
      "inputSchema": {
        "type": "object",
        "properties": {
          "location": {
            "type": "string",
            "description": "City name"
          }
        },
        "required": ["location"]
      }
    },
    {
      "name": "calculator",
      "description": "Perform basic math calculations",
      "inputSchema": {
        "type": "object",
        "properties": {
          "operation": {
            "type": "string",
            "enum": ["add", "subtract", "multiply", "divide"]
          },
          "num1": { "type": "number" },
          "num2": { "type": "number" }
        },
        "required": ["operation", "num1", "num2"]
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode
// tools/call execution
// Example 1: Weather forecast tool
async function executeWeatherForecast(params) {
  const { location } = params;

  // Get weather data (simplified)
  const weather = {
    location: location,
    temperature: "72°F",
    condition: "Sunny",
    forecast: "Clear skies all day"
  };

  return { 
    content: [
      { 
        type: "text", 
        text: `Weather for ${location}: ${weather.temperature}, ${weather.condition}. 
               Forecast: ${weather.forecast}`
      }
    ] 
  };
}

// Example 2: Calculator tool
async function executeCalculator(params) {
  const { operation, num1, num2 } = params;
  let result;

  // Perform calculation
  switch(operation) {
    case "add": 
      result = num1 + num2;
      break;
    case "subtract":
      result = num1 - num2;
      break;
    case "multiply":
      result = num1 * num2;
      break;
    case "divide":
      result = num1 / num2;
      break;
  }

  return { 
    content: [
      { 
        type: "text", 
        text: `${num1} ${operation} ${num2} = ${result}`
      }
    ] 
  };
}
Enter fullscreen mode Exit fullscreen mode

3.2 Resources Handler
Manages static data and content that can be read.

Handles Two Request Types:
resources/list: Returns available resources
resources/read: Retrieves resource content

Example Implementation:

resources/list Response:

{
  "resources": [
    {
      "uri": "recipes://breakfast",
      "name": "Breakfast Recipes",
      "description": "Collection of breakfast recipes",
      "mimeType": "application/json"
    },
    {
      "uri": "notes://shopping-list",
      "name": "Shopping List",
      "description": "Current shopping list items",
      "mimeType": "text/plain"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

resources/read Execution:

// Example resource handler
async function readResource(uri) {
  // Breakfast recipes resource
  if (uri === "recipes://breakfast") {
    const breakfastRecipes = [
      { name: "Scrambled Eggs", ingredients: ["eggs", "butter", "salt"] },
      { name: "Pancakes", ingredients: ["flour", "milk", "eggs", "sugar"] }
    ];

    return { 
      contents: [
        { 
          uri: uri,
          text: JSON.stringify(breakfastRecipes, null, 2),
          mimeType: "application/json" 
        }
      ] 
    };
  } 
  // Shopping list resource
  else if (uri === "notes://shopping-list") {
    const shoppingList = 
      "1. Milk\n" +
      "2. Bread\n" +
      "3. Eggs\n" +
      "4. Apples\n" +
      "5. Coffee";

    return { 
      contents: [
        { 
          uri: uri,
          text: shoppingList,
          mimeType: "text/plain" 
        }
      ] 
    };
  }
}
Enter fullscreen mode Exit fullscreen mode

3.3 Prompts Handler
Manages pre-defined prompts that can be used by the AI client.

In your architecture, the Prompt Handler is the part of the server that deals with prompts aka the messages or instructions that you send to the AI to make it do something.

Think of prompts like the script you give an actor. The AI is the actor, and your prompt tells it what to say or do.

The Prompt Handler helps:

  • List all available prompts
  • Fetch a specific prompt
  • Inject variables into prompts (dynamic prompts)
  • Send these prompts to the AI client (like Claude, GPT, etc.)

prompts/list: Returns a list of all available prompts.
Example response:

["generate_invoice", "summarize_text", "write_lawyer_reply"]

Enter fullscreen mode Exit fullscreen mode

prompts/get: Fetches the full prompt template for a given name.
Example request:

{
  "method": "prompts/get",
  "params": { "name": "summarize_text" }
}
Enter fullscreen mode Exit fullscreen mode

Example response:

{
  "template": "Summarize the following text:\n\n{{input_text}}"
}
Enter fullscreen mode Exit fullscreen mode

You can then plug in dynamic input like:

"input_text": "The Supreme Court ruled in favor of the plaintiff in a landmark decision..."
Enter fullscreen mode Exit fullscreen mode

And the final prompt becomes:

Summarize the following text:

The Supreme Court ruled in favor of the plaintiff in a landmark decision...
Enter fullscreen mode Exit fullscreen mode

4. Model Registry
The Model Registry is the "rulebook" for your MCP server. It stores schemas, validation rules, and metadata.

Three Main Components:
Tool Schemas:

{
  "name": "convert_temperature",
  "description": "Convert between Fahrenheit and Celsius",
  "inputSchema": {
    "type": "object",
    "properties": {
      "value": { 
        "type": "number",
        "description": "Temperature value to convert" 
      },
      "from": { 
        "type": "string",
        "enum": ["celsius", "fahrenheit"],
        "description": "Source temperature unit" 
      }
    },
    "required": ["value", "from"]
  }
}
Enter fullscreen mode Exit fullscreen mode
  • Defines input/output validation
  • Stores tool metadata and descriptions
  • Ensures type safety

Resource Schemas:

{
  "uri": "payments://done",
  "mimeType": "application/json",
  "description": "All completed payments"
}
Enter fullscreen mode Exit fullscreen mode
  • Defines URI patterns
  • Specifies content types
  • Provides resource descriptions

Prompt Templates:

{
  "name": "payment_summary",
  "template": "Summarize {count} payments totaling ${amount}",
  "arguments": ["count", "amount"]
}
Enter fullscreen mode Exit fullscreen mode
  • Stores reusable prompt templates
  • Manages dynamic prompt generation
  • Defines prompt arguments

6. Context Storage
The Context Storage layer manages data persistence and retrieval. Your MCP server can use multiple storage backends.

Storage Types:

In-Memory Storage:

const sessionData = new Map();
const cache = new Map();
Enter fullscreen mode Exit fullscreen mode
  • Fast access for temporary data
  • Session management
  • Caching frequently accessed data
  • Lost when server restarts

Database Storage:

// MongoDB example
const payments = await db.collection('payments').find({}).toArray();

// PostgreSQL example
const result = await client.query('SELECT * FROM payments WHERE done = true');
Enter fullscreen mode Exit fullscreen mode
  • Persistent data storage
  • Complex queries and relationships
  • ACID compliance (for SQL databases)
  • Scalable for large datasets

File System Storage:

const fs = require('fs');
const data = fs.readFileSync('/path/to/data.json');
Enter fullscreen mode Exit fullscreen mode
  • Local file operations
  • Log storage
  • Configuration files
  • Simple data persistence

External APIs:

// REST API call
const response = await fetch('https://api.example.com/payments');

// GraphQL query
const result = await graphql(schema, query);
Enter fullscreen mode Exit fullscreen mode
  • Integration with external services
  • Real-time data from third parties
  • Webhook processing
  • Microservices communication

ALRIGHT DEVS! I'M GLAD WE MAKE IT TILL HERE, BECAUSE IT'S TIME WE BUILD ONE 🔥


🧠Building Our Own MCP Server: A Step-by-Step Guide

In this guide, I'll walk you through creating a Model Context Protocol (MCP) server that exposes my MongoDB data to Large Language Models (LLMs) like Claude. We'll build a server that manages payment data and makes it accessible through both MCP Resources and Tools.

Prerequisites

Before we begin, make sure we have:

  • Node.js installed (v14 or higher)
  • MongoDB Atlas account (or a local MongoDB instance)
  • Basic understanding of JavaScript/Node.js
  • Claude Desktop installed (for testing with LLM)
  • MCP Inspector (for debugging and testing)

Step 1: Project Setup

mkdir mcp_server
cd mcp_server
npm init -y
Enter fullscreen mode Exit fullscreen mode

Install the required dependencies:
npm install @modelcontextprotocol/sdk mongodb

Step 2: Server Implementation
Let's create our index.js file and break down each component in detail:

1. Basic Server Setup and Imports

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  ListResourcesRequestSchema,
  ReadResourceRequestSchema,
  ListToolsRequestSchema,
  CallToolRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { MongoClient } from "mongodb";

// Initialize the MCP server
const server = new Server(
  {
    name: "NextApp Payments Resource",
    version: "1.0.0",
  },
  {
    capabilities: {
      resources: {}, // We'll expose payment resources
      tools: {}, // We'll expose payment-related tools
    },
  }
);
Enter fullscreen mode Exit fullscreen mode

This setup:

  • Imports necessary MCP SDK components
  • Imports MongoDB client
  • Creates a new MCP server instance with metadata
  • Defines server capabilities (resources and tools)

2. MongoDB Connection Setup

// MongoDB connection setup with error handling
const uri = process.env.MONGODB_URI;
if (!uri) {
  console.error(
    JSON.stringify({
      type: "error",
      message: "MONGODB_URI environment variable is required",
    })
  );
  process.exit(1);
}

// Helper function for MongoDB operations
async function withMongoDB(operation) {
  let client;
  try {
    client = new MongoClient(uri);
    await client.connect();
    const db = client.db("test");
    return await operation(db);
  } catch (error) {
    console.error(
      JSON.stringify({
        type: "error",
        message: "MongoDB Error",
        error: error.message,
      })
    );
    throw error;
  } finally {
    if (client) {
      await client.close();
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

This section:

  • Validates MongoDB connection string
  • Creates a reusable helper function for database operations
  • Implements proper connection handling and cleanup

3. Implementing MCP Tools

// Define and implement tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "get_completed_payments",
        description: "\"Get all payments where done is true\","
        inputSchema: {
          type: "object",
          properties: {},
          required: [],
        },
      },
      {
        name: "get_all_payments",
        description: "\"Get all payments from the database\","
        inputSchema: {
          type: "object",
          properties: {},
          required: [],
        },
      },
    ],
  };
});

// Handle tool execution
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name } = request.params;

  const handlePayments = async (query = {}) => {
    return await withMongoDB(async (db) => {
      const payments = await db.collection("payments").find(query).toArray();
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify(payments, null, 2),
          },
        ],
      };
    });
  };

  switch (name) {
    case "get_completed_payments":
      return handlePayments({ done: true });
    case "get_all_payments":
      return handlePayments();
    default:
      throw new Error(`Unknown tool: ${name}`);
  }
});
Enter fullscreen mode Exit fullscreen mode

This implements:

  • Tool registration with clear descriptions
  • Input schema definitions (empty in this case)
  • Reusable payment handling logic
  • Specific tool implementations

get_completed_payments

  • Description: Retrieves all payments where done is true
  • Input: No parameters required
  • Output: JSON array of completed payments

get_all_payments

  • Description: Retrieves all payments from the database
  • Input: No parameters required
  • Output: JSON array of all payments

4. Implementing MCP Resources

// Define available resources
server.setRequestHandler(ListResourcesRequestSchema, async () => {
  return {
    resources: [
      {
        uri: "payments://done",
        name: "Completed Payments",
        description: "\"All payments where done is true\","
        mimeType: "application/json",
      },
    ],
  };
});

// Handle resource reading
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
  const { uri } = request.params;

  if (uri === "payments://done") {
    return await withMongoDB(async (db) => {
      const payments = await db
        .collection("payments")
        .find({ done: true })
        .toArray();

      return {
        contents: [
          {
            uri: uri,
            text: JSON.stringify(payments, null, 2),
            mimeType: "application/json",
          },
        ],
      };
    });
  }

  throw new Error(`Unknown resource: ${uri}`);
});
Enter fullscreen mode Exit fullscreen mode

This section:

  • Defines a resource for completed payments
  • Implements resource reading logic
  • Uses our MongoDB helper function
  • Returns properly formatted JSON responses

5. Server Startup

// Main function to start the server
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);

  console.error(
    JSON.stringify({
      type: "info",
      message: "MCP server started with tools and resources",
    })
  );
}

main().catch((error) =>
  console.error(
    JSON.stringify({
      type: "error",
      message: "Server startup error",
      error: error.message,
    })
  )
);
Enter fullscreen mode Exit fullscreen mode

Step 3: Configuration Setup

MCP Inspector Configuration

MCP Inspector is a development tool that helps you test and debug your MCP server. Here's how to set it up:

Start your server:
node index.js

Access MCP Inspector:

Open your browser and navigate to http://localhost:6274/#resources
The Inspector will automatically connect to your running server
You can test resources and tools directly from the interface

mcp inspector

The image above shows the MCP Inspector interface displaying the payment records retrieved from MongoDB Atlas through the MCP server.

Claude Desktop Configuration
Let's walk through the process of configuring your MCP server in Claude Desktop:

Step 1: Access Settings

  1. Open Claude Desktop application
  2. Click on the hamburger menu (three lines) in the top-left corner
  3. Select "File" → "Settings"

claude setup

Step 2: Configure MCP Server

  • In the Settings window, select the "Developer" tab
  • Click on "Edit Config" button

claude settings

  • This will open your Claude configuration file in your default text editor

Windows: C:\Users\<username>\AppData\Roaming\claude\claude_desktop_config.json

macOS: ~/Library/Application Support/claude/claude_desktop_config.json

Linux: ~/.config/claude/claude_desktop_config.json

claude config file

  • Add your server configuration to the file:
{
  "mcpServers": {
    "PaymentsResource": {
      "command": "node",
      "args": ["C:/path/to/your/index.js"],
      "env": {
        "MONGODB_URI": "mongodb+srv://your-connection-string"
      }
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

Step 3: Apply Changes

  1. Save the configuration file
  2. Close the text editor
  3. Close Claude Desktop completely
  4. Important: Sometimes just closing the application isn't enough
    • Windows: Open Task Manager (Ctrl + Shift + Esc)
    • Find "Claude" in the processes
    • Right-click and select "End Task"
  5. Restart Claude Desktop

Step 4: Verify Server Connection

  1. Open Claude Desktop
  2. Go to Settings → Developer tab
  3. You should see your MCP server listed as "running"

mcp server running

Step 5: Using Your MCP Server

  1. Go to the main Claude chat interface
  2. Look for the search and tools options at the top
  3. You'll find your configured MCP server in the tools list

[NOTE: You will be asked to give the permission, to use those tools.]

claude permission

mcp configured in claude

mcp tools in claude

To use resources:

  • Click the upload button (+) on the left sidebar
  • Select from your available resources
  • Query the resource as needed

payment resource

Once you click on that "Add from Payment Resource"
You will be able to upload your Completed Payments resource

payment resource 1

payment resource 2

Step 4: Testing Your Implementation

  1. Start your server:
    node index.js

  2. In Claude Desktop:

  • Verify server status in Settings → Developer
  • Your server should show as "running"

Test commands:

# Test resource access
Use the MCP resource payments://done and show me all completed payments

# Test tools
Use the MCP tool get_completed_payments to show me successful transactions
Use the MCP tool get_all_payments to display all payment records
Enter fullscreen mode Exit fullscreen mode

USING TOOL
final result

USING RESOURCE
final result 2

Troubleshooting Guide

Common Issues and Solutions

Server Won't Start

  • Check Node.js version
  • Verify file paths in config
  • Check for syntax errors
  • Verify MongoDB URI

Claude Can't Connect

  • Check config file location
  • Verify absolute paths
  • Check environment variables
  • Restart Claude Desktop

MCP Inspector Issues

  • Verify server is running
  • Check port 6274 is available
  • Look for console errors
  • Check browser console

MongoDB Connection Failed

  • Verify connection string
  • Check network connectivity
  • Verify database permissions
  • Check IP whitelist

"SHEEESHHH!! NOW WE HAVE OUR OWN MCP SERVER"

Working on this project was honestly a fun deep dive into how we can make large language models a lot smarter with real world, live data. We built a custom MCP server that connects directly to MongoDB, giving Claude access to actual payment data using tools and resources and We designed from scratch. This whole thing isn’t just a tech demo; it’s a glimpse into how we can build AI apps that are actually aware of context and data that matters in the moment.

Conclusion

  • We've now built a fully functional MCP server that:
  • Exposes MongoDB data through MCP resources
  • Provides tools for querying payments
  • Integrates with Claude Desktop

That’s it from my end for now!
If you’ve made it this far thanks for checking it out. If you’re building something similar, playing around with MCP, or just wanna collaborate on AI ideas, feel free to fork the repo, drop a star, or hit me up on GitHub: @Denyme24 or LinkedIn: in/namanraj24.

🔗 Repo for reference: my-mcp-server

Catch ya in the next project.
Stay curious & keep building 🚀🧠

Top comments (0)