DevInterviewMasterStart free →
AI & AutomationFree to read

Building Custom MCP Servers & Tools

Create Your Own AI-Accessible Integrations

Learn to build production-grade MCP servers from scratch. Design tools that LLMs can understand and use effectively, handle errors gracefully, implement security, and deploy servers that your entire team can use.

Why Build Custom MCP Servers?

When Pre-Built Servers Are Not Enough

The Need for Custom Servers:

Pre-built MCP servers cover popular services like GitHub, Slack, and databases. But every company has unique internal systems that no generic server covers. Your internal CRM, custom deployment pipeline, proprietary data warehouse, internal ticketing system - these need custom MCP servers.

Building a custom MCP server means your AI can interact with systems that are completely unique to your organization. It is like building a custom app for your business instead of using off-the-shelf software.

Real-World Analogy - Flipkart Seller Dashboard:

Flipkart provides standard tools for all sellers (listing, orders, payments). But a large seller like a clothing brand might build a custom integration that connects Flipkart to their internal inventory system, automatically updates stock levels, and generates custom reports. That custom integration is like a custom MCP server - purpose-built for their specific workflow.

When to Build vs. Use Pre-Built:

Build CustomUse Pre-Built
Internal APIs and databasesGitHub, Slack, Google Drive
Proprietary business logicStandard file operations
Custom data transformationsWeb search, standard DB queries
Company-specific workflowsStandard code management

Note: Building MCP servers is straightforward with official SDKs (TypeScript, Python, Kotlin, C#). Most developers can build a simple server in under an hour.

MCP Server Architecture & SDK Setup

Understanding What Goes Into an MCP Server

Server Components:

Every MCP server has four main parts:

  • Transport Handler: Manages how messages flow (stdio or HTTP). The SDK handles this for you.
  • Tool Definitions: Describe what tools are available, their parameters (JSON Schema), and what they do.
  • Tool Handlers: The actual code that runs when a tool is called. Your business logic lives here.
  • Error Handling: How the server responds when things go wrong. Critical for good LLM experience.

Available SDKs:

  • TypeScript SDK (@modelcontextprotocol/sdk): Most popular, great for Node.js developers. Full support for all MCP features.
  • Python SDK (mcp): Excellent for data science and ML teams. Async-first design.
  • Kotlin SDK: For JVM-based applications and Android.
  • C# SDK: For .NET applications and enterprise systems.

Project Structure (TypeScript):

my-mcp-server/
  package.json          // Dependencies: @modelcontextprotocol/sdk
  src/
    index.ts            // Server setup and transport
    tools/
      search-users.ts   // Tool: search users in CRM
      create-ticket.ts  // Tool: create support ticket
      get-metrics.ts    // Tool: fetch dashboard metrics
    utils/
      api-client.ts     // Internal API connection
      validators.ts     // Input validation helpers

Note: Start with the TypeScript or Python SDK - they have the best documentation and community support. You can always port to other languages later.

Designing Great Tool Definitions

The Art of Writing Tools That LLMs Actually Use Well

Tool Descriptions Are Everything:

The LLM reads your tool descriptions to decide when to use each tool and what parameters to pass. A bad description means the LLM will misuse or ignore your tool. Think of it like writing documentation for a very smart but very literal intern.

Good vs Bad Tool Definitions:

Bad Definition:

Name: "get_data"
Description: "Gets data from the system"
Params: { id: string }

Too vague. What data? Which system? What kind of ID?

Good Definition:

Name: "search_customers"
Description: "Search customers in the CRM by name, email,
  or phone number. Returns up to 10 matching customers
  with their name, email, subscription plan, and
  last active date. Use this when the user asks about
  a specific customer or wants to look someone up."
Params: {
  query: string (required) - "Search term: name, email, or phone"
  status: enum ["active", "inactive", "all"] - "Filter by status. Default: all"
}

Tool Design Principles:

  • One Tool, One Job: search_customers, get_customer_details, update_customer - NOT manage_customers. Granular tools are easier for the LLM to use correctly.
  • Descriptive Names: Use verb_noun format. search_logs, create_ticket, get_report. The name alone should hint at what it does.
  • Typed Parameters: Use JSON Schema with types, enums, required fields, and descriptions for every parameter.
  • Return Format: Return structured data, not raw dumps. Include only relevant fields. The LLM will present it to the user.
  • Usage Hints: Tell the LLM WHEN to use this tool. "Use this when the user asks about order status" helps the LLM pick the right tool.

Note: Spend 80% of your design time on tool descriptions and 20% on implementation. Great descriptions make the difference between a tool the LLM uses perfectly vs. one it constantly misuses.

Error Handling, Validation & Security

Making Your Server Production-Ready

Input Validation - Trust Nothing:

The LLM generates the tool inputs. It can pass wrong types, missing fields, injection attempts, or completely unexpected values. Validate every single input as if it came from an untrusted user on the internet.

  • Check required fields exist
  • Validate types (string, number, enum values)
  • Sanitize strings to prevent injection
  • Enforce reasonable limits (max length, ranges)

Error Response Best Practices:

When something goes wrong, return errors that help the LLM recover:

// BAD: Cryptic error
{ "error": "404" }

// GOOD: Helpful error that guides the LLM
{
  "error": "Customer with ID cust_123 was not found.
  The customer may have been deleted.
  Try searching by email or name instead
  using the search_customers tool."
}

Security Checklist:

  • Authentication: Verify the caller is authorized. For stdio, the OS process model handles this. For HTTP, implement proper auth (API keys, OAuth).
  • Rate Limiting: Prevent the AI from making 1000 API calls in a loop. Set reasonable per-minute limits.
  • Audit Logging: Log every tool call with timestamp, caller, parameters, and result. Essential for debugging and compliance.
  • Timeouts: Set timeouts for external API calls. A hanging request should fail after a reasonable time, not block forever.
  • Data Filtering: Never return sensitive data (passwords, API keys, PII) in tool results. Filter it out server-side.

Note: LLM-generated inputs are untrusted. A prompt injection attack could make the LLM pass malicious parameters to your tools. Always validate and sanitize.

Building a Complete MCP Server - Step by Step

Walkthrough: Employee Directory MCP Server

Scenario:

Your company has an internal employee directory API. You want AI to help managers look up team members, check org charts, and find experts. Let us build an MCP server for this.

Step 1: Define Your Tools

Tool 1: search_employees
  Description: Search for employees by name, department,
    or skill. Returns matching employees with name, title,
    department, and email. Max 20 results.
  Params: { query: string, department?: string }

Tool 2: get_employee_profile
  Description: Get detailed profile of a specific employee
    including their team, manager, skills, location,
    and recent projects.
  Params: { employee_id: string }

Tool 3: get_org_chart
  Description: Get the organizational chart showing
    direct reports for a given manager.
  Params: { manager_id: string }

Tool 4: find_experts
  Description: Find employees with expertise in a
    specific technology or domain. Useful when user
    needs help finding the right person for a task.
  Params: { skill: string, location?: string }

Step 2: Implement Handlers

// Pseudocode for search_employees handler
function handle_search_employees(params):
  // 1. Validate inputs
  if params.query is empty: return error("Query is required")
  if params.query.length > 100: return error("Query too long")

  // 2. Call internal API
  results = call_employee_api("/search", params)

  // 3. Filter sensitive data
  remove salary, SSN, personal phone from results

  // 4. Format response
  return formatted_results with name, title, dept, email

Step 3: Configure and Test

// Add to Claude Desktop config
{
  "mcpServers": {
    "employee-directory": {
      "command": "node",
      "args": ["/path/to/your/server/dist/index.js"],
      "env": {
        "EMPLOYEE_API_URL": "https://internal-api.company.com",
        "API_KEY": "your-secret-key"
      }
    }
  }
}

// Test conversation:
User: "Who are the React experts in Bangalore?"
AI calls: find_experts({skill: "React", location: "Bangalore"})
AI: "Found 5 React experts in Bangalore: Priya (Staff Eng),
     Rahul (Senior Eng), ..."

Note: Always test your MCP server with a variety of queries, including edge cases and unusual inputs, before deploying. LLMs will find every edge case you missed.

Interview Questions

Q: When should you build a custom MCP server vs using a pre-built one?

Build custom when you have internal systems unique to your organization - internal CRMs, proprietary databases, custom deployment pipelines, internal APIs. Use pre-built for standard services like GitHub, Slack, file systems, and popular databases. The rule: if a public server exists and meets your needs, use it. If your use case involves company-specific logic or data, build custom.

Q: What makes a good MCP tool description?

A good description is specific, complete, and includes usage hints. It should explain: what the tool does, what parameters it accepts (with types and examples), what it returns, and when to use it. Avoid vague descriptions like "gets data". Instead: "Search customers by name or email. Returns up to 10 results with name, plan, and status. Use when user asks about a specific customer." The LLM uses descriptions to decide when and how to use tools.

Q: Why should LLM-generated tool inputs be treated as untrusted?

LLMs can generate unexpected, malformed, or malicious inputs. A prompt injection could trick the LLM into passing SQL injection strings, path traversal attempts, or excessively large values. Treat all inputs like untrusted user input: validate types, check required fields, sanitize strings, enforce limits. Never directly pass LLM-generated strings to database queries or shell commands.

Q: What is the recommended approach for MCP tool granularity?

Follow the one tool, one job principle. Instead of a single "manage_users" tool that does search/create/update/delete, create four separate tools: search_users, create_user, update_user, delete_user. Granular tools are easier for the LLM to understand and use correctly. The LLM can precisely pick the right tool for each step. Complex multi-purpose tools lead to confusion and misuse.

Q: How should MCP server errors be structured?

Error messages should help the LLM recover, not just report failure. Include: what went wrong, why it might have happened, and what the LLM can try instead. Example: "Customer ID cust_123 not found. The customer may have been deleted. Try using search_customers to find them by name or email." This is much better than a generic "Error 404" because the LLM can take corrective action.

Frequently Asked Questions

What is Building Custom MCP Servers & Tools?

Learn to build production-grade MCP servers from scratch. Design tools that LLMs can understand and use effectively, handle errors gracefully, implement security, and deploy servers that your entire team can use.

How does Building Custom MCP Servers & Tools work?

When Pre-Built Servers Are Not Enough The Need for Custom Servers: Pre-built MCP servers cover popular services like GitHub, Slack, and databases. But every company has unique internal systems that no generic server covers.

Browse all AI & Automation topics →

Practice this on DevInterviewMaster

Read the full Building Custom MCP Servers & Tools breakdown with interactive demos, quizzes, and Hinglish notes.

Open the interactive topic →

800+ system-design, LLD, coding, and design-pattern topics. Unlock everything with Pro (₹499, one-time) or Ultimate (₹999, one-time) — lifetime access, no subscription.