Download Beam

Build Your Own MCP Server: The 2026 Developer Guide

March 2026 • 16 min read

The Model Context Protocol (MCP) is the standard interface between AI coding agents and external tools. When Claude Code queries your database, reads a Notion page, or searches your internal documentation, it does so through MCP servers. While hundreds of pre-built MCP servers exist, the real power comes from building your own -- connecting Claude Code to your specific APIs, databases, and internal systems.

This guide walks through building a custom MCP server from scratch, using a database query server as the running example. By the end, you will have a working MCP server that gives Claude Code the ability to query your PostgreSQL database with natural language.

What Is MCP?

MCP (Model Context Protocol) is an open standard created by Anthropic that defines how AI agents communicate with external tools and data sources. Think of it as a USB port for AI: any agent that speaks MCP can connect to any tool that implements the MCP server interface, without custom integration code on either side.

MCP Architecture: Client-Server Communication AI Agent (Client) Claude Code Gemini CLI Any MCP Client Tool Call Response MCP JSON-RPC stdio / SSE HTTP MCP Server (Your Code) Tools: query_db, search Resources: schemas Prompts: templates PostgreSQL Your Database REST API Internal Service MCP Server Capabilities Tools Functions the agent can call (query, search, create) Resources Data the agent can read (schemas, docs, configs) Prompts Pre-built prompt templates for common workflows

Why Build a Custom MCP Server?

Pre-built MCP servers cover common use cases: filesystem access, GitHub, Slack, web search. But every engineering team has internal systems that no public MCP server covers. Your internal API, your specific database schema, your custom deployment pipeline -- these require custom MCP servers.

Common Custom MCP Server Use Cases

  • Database queries: Let Claude Code query your production or staging database directly. Ask "how many users signed up this week?" and get the answer without writing SQL yourself
  • Internal API access: Expose your internal microservices to Claude Code. "Deploy the staging build" or "Get the latest error logs from the payment service"
  • Documentation search: Connect Claude Code to your Confluence, Notion, or internal wiki. The agent can reference your team's documentation while writing code
  • CI/CD integration: Trigger builds, check pipeline status, and review deployment logs through Claude Code
  • Monitoring and alerting: Query Datadog, Grafana, or your custom monitoring system. "What's the p99 latency for the checkout endpoint?"

Step 1: Project Setup

We will build the MCP server in TypeScript using the official @modelcontextprotocol/sdk package. This is the reference implementation maintained by Anthropic.

# Create project directory
mkdir mcp-database-server
cd mcp-database-server

# Initialize project
npm init -y
npm install @modelcontextprotocol/sdk pg zod
npm install -D typescript @types/node @types/pg tsx

# Create tsconfig
npx tsc --init --target es2022 --module nodenext \
  --moduleResolution nodenext --outDir dist

Step 2: Define Your Tools

MCP tools are the functions your server exposes to AI agents. Each tool has a name, description, and input schema (defined using JSON Schema). The agent reads the description to understand when and how to use the tool.

// src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import { Pool } from "pg";

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
});

const server = new McpServer({
  name: "database-query",
  version: "1.0.0",
});

// Tool 1: Execute a read-only SQL query
server.tool(
  "query_database",
  "Execute a read-only SQL query against the PostgreSQL database. " +
  "Returns results as JSON. Only SELECT queries are allowed.",
  {
    sql: z.string().describe("The SQL SELECT query to execute"),
    params: z.array(z.string()).optional()
      .describe("Optional parameterized query values"),
  },
  async ({ sql, params }) => {
    // Security: only allow SELECT queries
    const trimmed = sql.trim().toUpperCase();
    if (!trimmed.startsWith("SELECT")) {
      return {
        content: [{
          type: "text",
          text: "Error: Only SELECT queries are allowed.",
        }],
      };
    }

    try {
      const result = await pool.query(sql, params || []);
      return {
        content: [{
          type: "text",
          text: JSON.stringify(result.rows, null, 2),
        }],
      };
    } catch (error) {
      return {
        content: [{
          type: "text",
          text: `Query error: ${(error as Error).message}`,
        }],
      };
    }
  }
);

// Tool 2: List all tables and their columns
server.tool(
  "list_tables",
  "List all tables in the database with their column names and types.",
  {},
  async () => {
    const result = await pool.query(`
      SELECT table_name, column_name, data_type
      FROM information_schema.columns
      WHERE table_schema = 'public'
      ORDER BY table_name, ordinal_position
    `);
    return {
      content: [{
        type: "text",
        text: JSON.stringify(result.rows, null, 2),
      }],
    };
  }
);

Step 3: Implement the Transport

MCP servers communicate over a transport layer. The most common is stdio (standard input/output), where the AI agent spawns your server as a child process and communicates via stdin/stdout. This is what Claude Code uses by default.

// Add to src/index.ts
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("Database MCP server running on stdio");
}

main().catch(console.error);

Step 4: Configure Claude Code

To use your MCP server with Claude Code, add it to your project's .claude/mcp.json configuration file.

// .claude/mcp.json
{
  "mcpServers": {
    "database": {
      "command": "npx",
      "args": ["tsx", "/path/to/mcp-database-server/src/index.ts"],
      "env": {
        "DATABASE_URL": "postgresql://user:pass@localhost:5432/mydb"
      }
    }
  }
}

After adding this configuration, restart Claude Code. It will discover your MCP server and its tools automatically. You can then ask Claude Code to query your database in natural language.

Example Interactions After Setup

  • "How many users signed up in the last 7 days?" -- Claude Code calls query_database with the appropriate SQL
  • "What tables exist in the database?" -- Claude Code calls list_tables
  • "Show me the top 10 orders by revenue this month" -- Claude Code generates a SQL query, executes it, and presents the results

Step 5: Add Resources

Resources are read-only data that the agent can reference. For a database server, exposing the schema as a resource helps the agent write better queries.

// Add to src/index.ts
server.resource(
  "schema",
  "database://schema",
  async (uri) => {
    const result = await pool.query(`
      SELECT table_name, column_name, data_type, is_nullable
      FROM information_schema.columns
      WHERE table_schema = 'public'
      ORDER BY table_name, ordinal_position
    `);

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

Security Considerations

MCP servers execute code on your machine with access to your systems. Security is not optional.

Critical security practices for MCP servers:
  • Input validation: Never pass user input directly to SQL, shell commands, or API calls. Use parameterized queries and validate all inputs against expected schemas
  • Read-only by default: Start with read-only access. Only add write capabilities when you have a specific use case and understand the risks
  • Rate limiting: AI agents can make many rapid tool calls. Implement rate limiting to prevent accidental resource exhaustion
  • Authentication: Use environment variables for credentials. Never hardcode secrets in your MCP server code
  • Principle of least privilege: Create a dedicated database user with minimal permissions for your MCP server. It should not use your admin credentials
  • Logging: Log every tool call for audit purposes. You need to know what the agent did with the access you gave it
// Rate limiting example
const rateLimiter = new Map<string, number[]>();
const RATE_LIMIT = 30; // max calls per minute

function checkRateLimit(toolName: string): boolean {
  const now = Date.now();
  const calls = rateLimiter.get(toolName) || [];
  const recentCalls = calls.filter(t => now - t < 60000);
  if (recentCalls.length >= RATE_LIMIT) return false;
  recentCalls.push(now);
  rateLimiter.set(toolName, recentCalls);
  return true;
}

Testing Your MCP Server

Test your MCP server before connecting it to Claude Code. The MCP SDK includes an inspector tool for interactive testing.

# Run the MCP inspector
npx @modelcontextprotocol/inspector npx tsx src/index.ts

# This opens a web UI where you can:
# - See all registered tools and their schemas
# - Call tools with test inputs
# - Inspect responses
# - Debug issues before connecting to Claude Code
Development workflow: Run your MCP server in one Beam split pane, the MCP inspector in another, and Claude Code in a third. This gives you full visibility into tool calls, server logs, and agent behavior simultaneously.

Publishing and Sharing

Once your MCP server works, you can share it with your team or the community.

Beyond Database Queries

The database query server is a starting point. The same pattern applies to any system you want to expose to AI agents. Replace the PostgreSQL calls with API requests to your internal services, file operations on your document store, or commands to your deployment pipeline. The MCP interface remains the same -- define tools, validate inputs, return results.

The most impactful custom MCP servers are the ones that eliminate context switching. Every time a developer would normally open a browser tab, log into a dashboard, or SSH into a server to check something, that is a candidate for an MCP tool. Build the server once, and every AI agent session from that point forward can access that information directly.

Build and Test MCP Servers with Beam

Use Beam's split panes to run your MCP server, inspector, and Claude Code side by side during development.

Download Beam Free