DEV Community

kie sp
kie sp

Posted on

I Built an MCP Server So I'd Never Have to Manually Import Excel Data Again

Or: How I spent a Saturday building MindfulMapper instead of doing literally anything else

The Problem That Started It All

Picture this: You're running a small cafe. You've got your menu in an Excel spreadsheet (because that's what everyone uses, right?). Now you need to get that data into MongoDB for your new web app.

Your options:

  1. Copy-paste each item manually (soul-crushing)
  2. Write a one-off Node.js script (works once, breaks next time)
  3. Ask ChatGPT to write the script (gets you 80% there, then you're on your own)

I wanted option 4: Talk to Claude like a human and have it just... work.

That's where MCP (Model Context Protocol) comes in.


What Even is MCP?

MCP is basically a way to give Claude (or any AI) superpowers. Instead of Claude just answering questions, it can actually do things - like reading files, calling APIs, or in my case, importing Excel data into databases.

Think of it like this:

  • Without MCP: Claude is a really smart friend who can only give advice
  • With MCP: Claude is a really smart friend who can actually SSH into your server and fix things

The catch? You have to build the "server" that does the actual work.


Building MindfulMapper

The Vision

I wanted to be able to say:

"Hey Claude, import menu.xlsx into my products collection. Map 'Name (EN)' to name.en and 'Name (TH)' to name.th. Oh, and auto-generate IDs with prefix 'spb'."

And have it... just work.

The Reality (aka Pain Points)

Pain Point #1: The Dotenv Disaster

My first version used dotenv to load environment variables. Seemed innocent enough:

import dotenv from 'dotenv';
dotenv.config();
Enter fullscreen mode Exit fullscreen mode

Turns out, dotenv prints a helpful message to stdout:

[dotenv@17.2.4] injecting env (4) from .env
Enter fullscreen mode Exit fullscreen mode

Claude Desktop saw this message, tried to parse it as JSON (because MCP uses JSON-RPC), and promptly died. Took me WAY too long to figure this out.

Solution: Either suppress the message or just hardcode the env vars in the Claude Desktop config. I went with option 2.

Pain Point #2: SDK Version Hell

The MCP SDK is evolving fast. Like, really fast. Version 1.26.0 uses completely different syntax than what's in the examples online.

What the examples showed:

server.addTool({
  name: "my_tool",
  description: "Does a thing",
  parameters: z.object({...}),
  execute: async ({...}) => {...}
});
Enter fullscreen mode Exit fullscreen mode

What actually works (v1.26.0):

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

server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [...]
}));

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  // Handle tool calls
});
Enter fullscreen mode Exit fullscreen mode

Yeah. Completely different. Spent hours on this one.

Pain Point #3: Auto-Generating IDs

I wanted IDs like spb-0001, spb-0002, etc. Seems simple, right?

The trick is maintaining a counter in MongoDB:

async function getNextId(prefix = 'spb') {
  const counterCollection = db.collection('counters');
  const result = await counterCollection.findOneAndUpdate(
    { _id: 'item_id' },
    { $inc: { seq: 1 } },
    { upsert: true, returnDocument: 'after' }
  );
  const num = result.seq || 1;
  return `${prefix}-${String(num).padStart(4, '0')}`;
}
Enter fullscreen mode Exit fullscreen mode

This ensures:

  • No duplicate IDs (even if you import the same file multiple times)
  • Sequential numbering
  • Custom prefixes for different item types

The Cool Parts

1. Flexible Column Mapping

Want to map Excel columns to nested MongoDB objects? Easy:

// Excel columns: "Name (EN)", "Name (TH)"
// Mapping: { "name.en": "Name (EN)", "name.th": "Name (TH)" }

// Result in MongoDB:
{
  id: "spb-0001",
  name: {
    en: "Americano",
    th: "อเมริกาโน่"
  }
}
Enter fullscreen mode Exit fullscreen mode

The mapper handles the dot notation automatically.

2. Natural Language Interface

This is the magic part. Instead of writing code every time, I just tell Claude:

"Import menu.xlsx into products collection. Use prefix 'spb'. Clear existing data."

Claude translates that into the right MCP tool call with the right parameters. It's like having a very patient assistant who never gets tired of your data imports.

3. It Actually Works in Production

I'm using this with MongoDB Atlas (cloud) for a real cafe menu system. The fact that it works reliably enough for production use still surprises me.


How to Use It

If you want to try it yourself:

1. Install

git clone https://github.com/kie-sp/mindful-mapper.git
cd mindful-mapper
npm install
Enter fullscreen mode Exit fullscreen mode

2. Configure Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "mindful-mapper": {
      "command": "node",
      "args": ["/full/path/to/mindful-mapper/upload-excel.js"],
      "env": {
        "MONGODB_URI": "your-mongodb-connection-string",
        "MONGODB_DB_NAME": "your_db",
        "ID_PREFIX": "spb"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Use It

Restart Claude Desktop, then:

"Import /path/to/menu.xlsx into products collection. Use prefix 'spb'."

That's it.

Lessons Learned

1. MCP is Still Early Days

The SDK is changing fast. Code from 2 months ago might not work today. Always check the version you're using.

2. Debugging MCP Servers is... Interesting

Your server crashes silently. No stack traces in Claude. Your only friend is:

node your-server.js 2>&1
Enter fullscreen mode Exit fullscreen mode

And the logs at:

~/Library/Logs/Claude/mcp*.log
Enter fullscreen mode Exit fullscreen mode

3. The Payoff is Worth It

Once it works, it's magic. I went from dreading data imports to actually enjoying them (well, not dreading them at least).


What's Next?

Current limitations I want to fix:

  1. No schema validation - It'll happily import garbage data
  2. No update/upsert mode - Only insert or clear-and-insert
  3. MongoDB only - PostgreSQL support exists but needs love
  4. No multi-sheet support - First sheet only

But honestly? For 90% of my use cases, it works perfectly as-is.


Try It Yourself

If you build something cool with it, let me know! Or if you hit the same pain points I did, at least now you know you're not alone.


Final Thoughts

Building MCP servers is weird. It's not quite backend development, not quite AI engineering. It's this new thing where you're building tools for an AI to use on your behalf.

But when it works? When you can just casually tell Claude to handle your data imports while you go make coffee? That's pretty cool.

If you end up using this or building something similar, I'd love to hear about it! Feel free to open an issue on GitHub or reach out.

Happy importing! 🎉


Built with: Node.js, MongoDB, MCP SDK, and an unreasonable amount of trial and error

Top comments (1)

Collapse
 
taositkroopad profile image
taositkroopad

Cool