technical
Featured

MCP Server Examples: 25+ Code Samples by Category

Explore 25+ MCP server examples with full code. Organized by category: database, filesystem, API. Python & TypeScript. Plus paid server options on MCPize.

MCPize Team
MCPize TeamCore Team
October 26, 202521 min read
MCP Server Examples gallery showing code samples for databases, filesystems, and APIs

MCP Server Examples: Complete Code Reference

TL;DR: 25+ MCP server code samples organized by category (database, filesystem, API, productivity). Python + FastMCP for speed, TypeScript for production. Complete code reference with copy-paste examples. Yes, paid MCP servers are a thing.

Look, I get it. Reading MCP documentation is boring. You want to see actual code. You want to copy something that works and tweak it for your use case. That's exactly what I would do too.

So here's the deal. I've put together 25+ MCP server examples organized by what they actually do. Database stuff, filesystem operations, API wrappers, productivity tools. Each one has working code you can steal and modify. Python and TypeScript because those are the languages people actually use for MCP servers.

And here's something nobody else talks about: paid MCP servers exist. You can build them. You can sell them. We'll get into that.

What you'll find in this MCP code reference:

  • MCP server examples organized by category (so you can find what you need fast)
  • Working code samples in both Python and TypeScript
  • MCP implementation examples with real usage patterns
  • How to sell your own paid MCP server (yeah, that's a thing now)
  • Templates to get you started in minutes, not hours
Browse all MCP Servers

Quick Start: Your First MCP Server#

Before we dive into the categories, let me show you the absolute minimum you need. This is the "hello world" of MCP servers.

I'm talking like 10 lines of code. That's it. If you can't get this running, something's wrong with your setup, not your code.

Python with FastMCP:

FastMCP is the way to go for Python. It handles all the boilerplate so you can focus on what your server actually does.

from fastmcp import FastMCP

mcp = FastMCP("hello-world")

@mcp.tool
def greet(name: str) -> str:
    """Say hello to someone."""
    return f"Hello, {name}!"

if __name__ == "__main__":
    mcp.run()

That's a working MCP server. Seven lines. The decorator pattern is clean and you can add more tools just by adding more functions.

TypeScript with the Official SDK:

TypeScript takes a bit more setup, but you get type safety in return. Worth it for production servers.

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

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

server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [{
    name: "greet",
    description: "Say hello to someone",
    inputSchema: { type: "object", properties: { name: { type: "string" } } }
  }]
}));

const transport = new StdioServerTransport();
await server.connect(transport);

A bit more verbose, sure. But you get autocomplete, type checking, and your IDE actually helps you. I use TypeScript for anything that's going to production.

The pattern is the same for both languages: define your server, declare your tools, run it. Everything else we cover builds on this foundation.

MCP Server List: Reference Implementations#

Before diving into code samples, here's a quick reference of MCP servers worth studying. These are the servers developers use as code reference points, based on Smithery.ai usage counts.

MCP Servers by Usage Count (Dec 2025)

Let me break down why each of these MCP server examples matters:

RankServerCategoryWhy Developers Love It
1GitHub MCPVersion ControlLets AI manage repos, issues, and PRs. Huge time saver for code review workflows.
2FilesystemFile SystemThe most basic and most useful. Read and write local files. Every developer needs this.
3MemoryData StoreGives AI persistent memory across conversations. Game changer for context.
4SupabaseDatabaseFull Postgres plus auth plus storage. Backend in a box.
5SlackCommunicationTeam messaging automation. Great for notifications and bot workflows.
6NotionProductivityPage and database management. Knowledge base integration.

The popularity isn't random. These MCP servers solve real problems that developers hit every day. If you're building something new, studying these examples is smart. See what patterns they use, how they structure their tools, what makes them usable.

MCP Server Examples by Category#

Alright, let's get into the actual code. I've organized these MCP examples by what problem they solve. Find your category, grab the code, modify it.

Database Servers#

Database MCP servers are probably the most useful category. Being able to have AI query your data directly is incredibly powerful. Here are working examples.

PostgreSQL MCP Server (Python):

This is the pattern I use for any Postgres integration. Simple, async, handles connections properly.

from fastmcp import FastMCP
import asyncpg

mcp = FastMCP("postgres-mcp")
DATABASE_URL = "postgresql://user:pass@localhost/mydb"

@mcp.tool
async def query(sql: str) -> list[dict]:
    """Execute a read-only SQL query on PostgreSQL."""
    conn = await asyncpg.connect(DATABASE_URL)
    try:
        rows = await conn.fetch(sql)
        return [dict(row) for row in rows]
    finally:
        await conn.close()

@mcp.tool
async def list_tables() -> list[str]:
    """List all tables in the database."""
    sql = """
    SELECT table_name FROM information_schema.tables
    WHERE table_schema = 'public'
    """
    result = await query(sql)
    return [row['table_name'] for row in result]

@mcp.tool
async def describe_table(table_name: str) -> list[dict]:
    """Get column info for a specific table."""
    sql = f"""
    SELECT column_name, data_type, is_nullable
    FROM information_schema.columns
    WHERE table_name = '{table_name}'
    """
    return await query(sql)

Pro tip: always include list_tables and describe_table tools. AI needs to understand your schema before it can write good queries.

SQLite MCP Server (TypeScript):

SQLite is perfect for local development and embedded databases. Here's a TypeScript implementation.

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import Database from "better-sqlite3";

const db = new Database("./data.sqlite");

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

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  if (name === "query") {
    const { sql } = args as { sql: string };
    const result = db.prepare(sql).all();
    return {
      content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
    };
  }

  if (name === "execute") {
    const { sql } = args as { sql: string };
    const result = db.prepare(sql).run();
    return {
      content: [{ type: "text", text: `Affected rows: ${result.changes}` }]
    };
  }
});

Database MCP Server Comparison:

ServerDatabaseKey FeaturesBest For
PostgreSQL MCPPostgreSQLFull SQL, async, connection poolingProduction apps
SQLite MCPSQLiteZero setup, embedded, fastLocal dev, prototypes
MongoDB MCPMongoDBDocument queries, aggregation pipelineUnstructured data
Supabase MCPSupabasePostgres + auth + realtime + storageFull stack apps
MySQL MCPMySQLEnterprise features, replicationLegacy systems

Each of these MCP server examples follows the same pattern: connect, expose query tools, handle cleanup. The database client changes, the structure stays the same.

Filesystem Servers#

Filesystem MCP servers let AI read and write files on your machine. Scary? A little. Useful? Incredibly.

Basic File Operations (Python):

from fastmcp import FastMCP
from pathlib import Path
import os

mcp = FastMCP("filesystem-mcp")

@mcp.tool
def read_file(path: str) -> str:
    """Read the contents of a file."""
    file_path = Path(path).expanduser()
    if not file_path.exists():
        raise FileNotFoundError(f"File not found: {path}")
    return file_path.read_text()

@mcp.tool
def write_file(path: str, content: str) -> str:
    """Write content to a file. Creates directories if needed."""
    file_path = Path(path).expanduser()
    file_path.parent.mkdir(parents=True, exist_ok=True)
    file_path.write_text(content)
    return f"Written {len(content)} bytes to {path}"

@mcp.tool
def list_directory(path: str = ".") -> list[dict]:
    """List files and directories at a path."""
    dir_path = Path(path).expanduser()
    items = []
    for item in dir_path.iterdir():
        items.append({
            "name": item.name,
            "type": "directory" if item.is_dir() else "file",
            "size": item.stat().st_size if item.is_file() else None
        })
    return sorted(items, key=lambda x: (x["type"] == "file", x["name"]))

@mcp.tool
def search_files(pattern: str, directory: str = ".") -> list[str]:
    """Search for files matching a glob pattern."""
    dir_path = Path(directory).expanduser()
    return [str(p) for p in dir_path.rglob(pattern)]

I always add search_files to my filesystem MCP servers. AI asking you "where is that config file?" gets old fast.

File Watcher (TypeScript):

This MCP server example monitors directories for changes. Great for development workflows.

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { watch, FSWatcher } from "fs";
import { readdir, stat } from "fs/promises";
import { join } from "path";

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

let watchers: Map<string, FSWatcher> = new Map();

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  if (name === "watch_directory") {
    const { path } = args as { path: string };

    if (watchers.has(path)) {
      return { content: [{ type: "text", text: `Already watching ${path}` }] };
    }

    const watcher = watch(path, { recursive: true }, (event, filename) => {
      console.error(`[${event}] ${filename}`);
    });

    watchers.set(path, watcher);
    return { content: [{ type: "text", text: `Now watching ${path}` }] };
  }

  if (name === "stop_watching") {
    const { path } = args as { path: string };
    const watcher = watchers.get(path);
    if (watcher) {
      watcher.close();
      watchers.delete(path);
    }
    return { content: [{ type: "text", text: `Stopped watching ${path}` }] };
  }
});

Filesystem MCP Examples:

ServerFeaturesUse Case
@mcp/server-filesystemOfficial, read/write/list/searchGeneral file access
File Watcher MCPReal-time change detectionDevelopment, build systems
S3 MCPAWS S3 bucket operationsCloud storage
GCS MCPGoogle Cloud StorageCloud storage
FTP MCPFTP/SFTP operationsLegacy file transfers

API Integration Servers#

These MCP server examples wrap external APIs so AI can interact with them. This is where things get really interesting.

REST API Wrapper (Python):

Generic pattern that works for any REST API. I use this as a starting point constantly.

from fastmcp import FastMCP
import httpx
from typing import Optional

mcp = FastMCP("rest-api-mcp")

BASE_URL = "https://api.example.com/v1"
API_KEY = os.environ.get("API_KEY")

@mcp.tool
async def api_get(endpoint: str, params: Optional[dict] = None) -> dict:
    """Make a GET request to the API."""
    async with httpx.AsyncClient() as client:
        response = await client.get(
            f"{BASE_URL}{endpoint}",
            params=params,
            headers={"Authorization": f"Bearer {API_KEY}"}
        )
        response.raise_for_status()
        return response.json()

@mcp.tool
async def api_post(endpoint: str, data: dict) -> dict:
    """Make a POST request to the API."""
    async with httpx.AsyncClient() as client:
        response = await client.post(
            f"{BASE_URL}{endpoint}",
            json=data,
            headers={"Authorization": f"Bearer {API_KEY}"}
        )
        response.raise_for_status()
        return response.json()

@mcp.tool
async def api_list_endpoints() -> list[str]:
    """List available API endpoints."""
    return [
        "/users - User management",
        "/products - Product catalog",
        "/orders - Order processing",
        "/analytics - Usage statistics"
    ]

OAuth-Protected API (TypeScript):

When you need proper OAuth flow. More complex but necessary for Google, GitHub, etc.

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { OAuth2Client } from "google-auth-library";

const oauth2Client = new OAuth2Client({
  clientId: process.env.GOOGLE_CLIENT_ID,
  clientSecret: process.env.GOOGLE_CLIENT_SECRET,
  redirectUri: "http://localhost:3000/callback"
});

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

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  if (name === "get_auth_url") {
    const url = oauth2Client.generateAuthUrl({
      access_type: "offline",
      scope: ["https://www.googleapis.com/auth/calendar.readonly"]
    });
    return { content: [{ type: "text", text: url }] };
  }

  if (name === "exchange_code") {
    const { code } = args as { code: string };
    const { tokens } = await oauth2Client.getToken(code);
    oauth2Client.setCredentials(tokens);
    return { content: [{ type: "text", text: "Authenticated successfully" }] };
  }

  if (name === "calendar_events") {
    const response = await oauth2Client.request({
      url: "https://www.googleapis.com/calendar/v3/calendars/primary/events"
    });
    return { content: [{ type: "text", text: JSON.stringify(response.data) }] };
  }
});

API Integration Patterns:

PatternComplexityWhen to Use
Simple Bearer TokenLowMost SaaS APIs
OAuth 2.0MediumGoogle, GitHub, etc.
API Key + SecretLowAWS-style services
Webhook ReceiverMediumEvent-driven integrations
GraphQL ClientMediumModern APIs like GitHub's

Developer Tools#

MCP servers for developer workflows. These examples automate the boring stuff.

Git Operations (Python):

from fastmcp import FastMCP
import subprocess
from typing import Optional

mcp = FastMCP("git-mcp")

def run_git(args: list[str], cwd: Optional[str] = None) -> str:
    """Run a git command and return output."""
    result = subprocess.run(
        ["git"] + args,
        capture_output=True,
        text=True,
        cwd=cwd
    )
    if result.returncode != 0:
        raise Exception(f"Git error: {result.stderr}")
    return result.stdout

@mcp.tool
def git_status(repo_path: str = ".") -> str:
    """Get current git status."""
    return run_git(["status", "--porcelain"], repo_path)

@mcp.tool
def git_diff(file: Optional[str] = None, repo_path: str = ".") -> str:
    """Show git diff for a file or all changes."""
    args = ["diff"]
    if file:
        args.append(file)
    return run_git(args, repo_path)

@mcp.tool
def git_log(count: int = 10, repo_path: str = ".") -> str:
    """Show recent commit history."""
    return run_git(
        ["log", f"-{count}", "--oneline", "--decorate"],
        repo_path
    )

@mcp.tool
def git_branch_list(repo_path: str = ".") -> str:
    """List all branches."""
    return run_git(["branch", "-a"], repo_path)

@mcp.tool
def git_stash_changes(message: str, repo_path: str = ".") -> str:
    """Stash current changes with a message."""
    return run_git(["stash", "push", "-m", message], repo_path)

Docker Management (TypeScript):

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { exec } from "child_process";
import { promisify } from "util";

const execAsync = promisify(exec);

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

async function docker(args: string): Promise<string> {
  const { stdout, stderr } = await execAsync(`docker ${args}`);
  if (stderr && !stdout) throw new Error(stderr);
  return stdout;
}

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  switch (name) {
    case "list_containers":
      const containers = await docker("ps --format '{{.Names}}\t{{.Status}}'");
      return { content: [{ type: "text", text: containers }] };

    case "container_logs":
      const { container, lines = 50 } = args as { container: string; lines?: number };
      const logs = await docker(`logs --tail ${lines} ${container}`);
      return { content: [{ type: "text", text: logs }] };

    case "restart_container":
      const { name: containerName } = args as { name: string };
      await docker(`restart ${containerName}`);
      return { content: [{ type: "text", text: `Restarted ${containerName}` }] };
  }
});

Developer Tool MCP Examples:

ServerWhat It DoesBest For
GitHub MCPIssues, PRs, repo managementCode review, project management
Git MCPLocal git operationsDay-to-day development
Docker MCPContainer managementDevOps, local dev
Kubernetes MCPCluster operationsProduction infrastructure
CI/CD MCPPipeline triggersAutomation

Productivity and Communication#

These MCP server examples integrate with the tools teams actually use every day.

Slack Integration (Python):

from fastmcp import FastMCP
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
import os

mcp = FastMCP("slack-mcp")
client = WebClient(token=os.environ["SLACK_BOT_TOKEN"])

@mcp.tool
def send_message(channel: str, text: str) -> dict:
    """Send a message to a Slack channel."""
    try:
        response = client.chat_postMessage(channel=channel, text=text)
        return {
            "success": True,
            "timestamp": response["ts"],
            "channel": response["channel"]
        }
    except SlackApiError as e:
        return {"success": False, "error": str(e)}

@mcp.tool
def list_channels() -> list[dict]:
    """List all accessible Slack channels."""
    response = client.conversations_list(types="public_channel,private_channel")
    return [
        {"id": c["id"], "name": c["name"], "is_private": c["is_private"]}
        for c in response["channels"]
    ]

@mcp.tool
def get_channel_history(channel: str, limit: int = 20) -> list[dict]:
    """Get recent messages from a channel."""
    response = client.conversations_history(channel=channel, limit=limit)
    return [
        {"user": m.get("user"), "text": m.get("text"), "ts": m["ts"]}
        for m in response["messages"]
    ]

@mcp.tool
def add_reaction(channel: str, timestamp: str, emoji: str) -> dict:
    """Add a reaction to a message."""
    try:
        client.reactions_add(channel=channel, timestamp=timestamp, name=emoji)
        return {"success": True}
    except SlackApiError as e:
        return {"success": False, "error": str(e)}

Notion Integration (TypeScript):

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { Client } from "@notionhq/client";

const notion = new Client({ auth: process.env.NOTION_TOKEN });

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

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  if (name === "search") {
    const { query } = args as { query: string };
    const response = await notion.search({
      query,
      filter: { property: "object", value: "page" }
    });
    return {
      content: [{
        type: "text",
        text: JSON.stringify(response.results.map(page => ({
          id: page.id,
          title: page.properties?.title?.title?.[0]?.plain_text || "Untitled"
        })))
      }]
    };
  }

  if (name === "get_page") {
    const { page_id } = args as { page_id: string };
    const page = await notion.pages.retrieve({ page_id });
    const blocks = await notion.blocks.children.list({ block_id: page_id });
    return {
      content: [{
        type: "text",
        text: JSON.stringify({ page, blocks: blocks.results })
      }]
    };
  }

  if (name === "create_page") {
    const { parent_id, title, content } = args as {
      parent_id: string;
      title: string;
      content: string;
    };
    const page = await notion.pages.create({
      parent: { page_id: parent_id },
      properties: {
        title: { title: [{ text: { content: title } }] }
      },
      children: [{
        object: "block",
        type: "paragraph",
        paragraph: { rich_text: [{ text: { content } }] }
      }]
    });
    return { content: [{ type: "text", text: `Created page: ${page.id}` }] };
  }
});

Productivity MCP Examples:

ServerPlatformKey Features
Slack MCPSlackMessages, channels, reactions, threads
Notion MCPNotionPages, databases, blocks, search
Linear MCPLinearIssues, projects, cycles, roadmaps
Jira MCPJiraTickets, sprints, boards, workflows
Calendar MCPGoogle CalendarEvents, scheduling, availability
Email MCPGmail/IMAPRead, send, search, organize

AI and Memory Servers#

These MCP server examples give AI persistent memory. Without them, every conversation starts from zero.

Vector Memory with ChromaDB (Python):

This is how you give AI semantic search over its memories. Game changer for long-running projects.

from fastmcp import FastMCP
import chromadb
from chromadb.config import Settings
import uuid

mcp = FastMCP("memory-mcp")

client = chromadb.Client(Settings(
    chroma_db_impl="duckdb+parquet",
    persist_directory="./memory_store"
))

collection = client.get_or_create_collection(
    name="memories",
    metadata={"hnsw:space": "cosine"}
)

@mcp.tool
def remember(content: str, tags: list[str] = None) -> dict:
    """Store a memory for later retrieval."""
    memory_id = str(uuid.uuid4())
    metadata = {"tags": ",".join(tags)} if tags else {}

    collection.add(
        documents=[content],
        ids=[memory_id],
        metadatas=[metadata]
    )

    return {"id": memory_id, "status": "remembered"}

@mcp.tool
def recall(query: str, limit: int = 5) -> list[dict]:
    """Search memories by semantic similarity."""
    results = collection.query(
        query_texts=[query],
        n_results=limit
    )

    memories = []
    for i, doc in enumerate(results["documents"][0]):
        memories.append({
            "content": doc,
            "id": results["ids"][0][i],
            "distance": results["distances"][0][i] if results.get("distances") else None
        })

    return memories

@mcp.tool
def forget(memory_id: str) -> dict:
    """Delete a specific memory."""
    collection.delete(ids=[memory_id])
    return {"status": "forgotten", "id": memory_id}

@mcp.tool
def list_memories(limit: int = 20) -> list[dict]:
    """List recent memories."""
    results = collection.peek(limit=limit)
    return [
        {"id": id, "content": doc[:100] + "..."}
        for id, doc in zip(results["ids"], results["documents"])
    ]

Memory Server Comparison:

ServerTypeBest For
Memory MCPKey-valueSimple persistent context
ChromaDB MCPVector DBSemantic search, embeddings
Qdrant MCPVector DBLarge-scale, production
Pinecone MCPVector DBManaged, serverless
Vectara MCPRAGRetrieval-augmented generation
Redis MCPKey-valueFast, ephemeral memory

MCP Server Examples by Language#

Same examples, organized by language. Pick your stack and go.

Python Examples#

Python dominates MCP server development. FastMCP makes it stupid simple.

Full-Featured Server Pattern:

Here's the pattern I use for production Python MCP servers. Multiple tools, resources, proper error handling.

from fastmcp import FastMCP
from typing import Optional
import logging

# Setup
mcp = FastMCP("production-server")
logger = logging.getLogger(__name__)

# Tools for actions
@mcp.tool
def create_item(name: str, data: dict) -> dict:
    """Create a new item with the given data."""
    try:
        # Your creation logic here
        item_id = save_to_database(name, data)
        return {"success": True, "id": item_id}
    except Exception as e:
        logger.error(f"Failed to create item: {e}")
        return {"success": False, "error": str(e)}

@mcp.tool
def get_item(item_id: str) -> Optional[dict]:
    """Retrieve an item by ID."""
    return fetch_from_database(item_id)

@mcp.tool
def update_item(item_id: str, updates: dict) -> dict:
    """Update an existing item."""
    try:
        update_in_database(item_id, updates)
        return {"success": True}
    except Exception as e:
        return {"success": False, "error": str(e)}

@mcp.tool
def delete_item(item_id: str) -> dict:
    """Delete an item by ID."""
    try:
        delete_from_database(item_id)
        return {"success": True}
    except Exception as e:
        return {"success": False, "error": str(e)}

# Resources for data access
@mcp.resource("items://{item_id}")
def item_resource(item_id: str) -> dict:
    """Resource for accessing item data directly."""
    return fetch_from_database(item_id)

@mcp.resource("items://list")
def items_list_resource() -> list[dict]:
    """Resource for listing all items."""
    return list_all_items()

# Prompts for common workflows
@mcp.prompt
def create_workflow() -> str:
    """Prompt for creating new items."""
    return """
    To create a new item, I need:
    1. A name for the item
    2. The data to store (as a dictionary)

    Example: create_item(name="test", data={"key": "value"})
    """

Python Ecosystem Summary:

LibraryPurposeWhen to Use
FastMCPRapid development90% of servers
mcp-serverLow-level controlCustom transports
asyncioAsync patternsI/O heavy servers
PydanticValidationComplex data models

TypeScript Examples#

TypeScript is my choice for production MCP servers. The type safety is worth the extra ceremony.

Full-Featured Server Pattern:

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

// Schema definitions
const CreateItemSchema = z.object({
  name: z.string().min(1),
  data: z.record(z.unknown())
});

const UpdateItemSchema = z.object({
  id: z.string().uuid(),
  updates: z.record(z.unknown())
});

// Server setup
const server = new Server(
  { name: "production-server", version: "1.0.0" },
  { capabilities: { tools: {}, resources: {} } }
);

// Tool definitions
server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    {
      name: "create_item",
      description: "Create a new item",
      inputSchema: {
        type: "object",
        properties: {
          name: { type: "string" },
          data: { type: "object" }
        },
        required: ["name", "data"]
      }
    },
    {
      name: "get_item",
      description: "Get an item by ID",
      inputSchema: {
        type: "object",
        properties: {
          id: { type: "string" }
        },
        required: ["id"]
      }
    },
    {
      name: "update_item",
      description: "Update an existing item",
      inputSchema: {
        type: "object",
        properties: {
          id: { type: "string" },
          updates: { type: "object" }
        },
        required: ["id", "updates"]
      }
    },
    {
      name: "delete_item",
      description: "Delete an item",
      inputSchema: {
        type: "object",
        properties: {
          id: { type: "string" }
        },
        required: ["id"]
      }
    }
  ]
}));

// Tool handlers
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  try {
    switch (name) {
      case "create_item": {
        const { name, data } = CreateItemSchema.parse(args);
        const id = await saveToDatabase(name, data);
        return { content: [{ type: "text", text: JSON.stringify({ success: true, id }) }] };
      }

      case "get_item": {
        const { id } = args as { id: string };
        const item = await fetchFromDatabase(id);
        return { content: [{ type: "text", text: JSON.stringify(item) }] };
      }

      case "update_item": {
        const { id, updates } = UpdateItemSchema.parse(args);
        await updateInDatabase(id, updates);
        return { content: [{ type: "text", text: JSON.stringify({ success: true }) }] };
      }

      case "delete_item": {
        const { id } = args as { id: string };
        await deleteFromDatabase(id);
        return { content: [{ type: "text", text: JSON.stringify({ success: true }) }] };
      }

      default:
        throw new Error(`Unknown tool: ${name}`);
    }
  } catch (error) {
    return {
      content: [{
        type: "text",
        text: JSON.stringify({ success: false, error: String(error) })
      }]
    };
  }
});

// Start server
const transport = new StdioServerTransport();
await server.connect(transport);

TypeScript Ecosystem:

PackagePurposeWhen to Use
@modelcontextprotocol/sdkOfficial SDKAlways
zodRuntime validationInput validation
tsxTypeScript executionDevelopment
tsupBundlingProduction builds

Other Languages#

MCP supports any language that can handle JSON-RPC over stdio. Here's the current state.

LanguageSDK/LibraryStatusMaturity
Gomcp-goCommunityGrowing
Rustmcp-rustCommunityEarly
C#MCP.NETOfficialStable
Javamcp-javaCommunityStable
Rubymcp-rubyCommunityEarly
PHPmcp-phpCommunityEarly

The protocol is simple enough that writing your own implementation isn't crazy. JSON-RPC is well documented. But for production use, I'd stick with Python or TypeScript where the tooling is mature.

Are There Paid MCP Servers?#

Yes. And this is the part nobody talks about.

Here's the thing. Most MCP server examples you see online are open source. Cool for learning. But what about developers who want to build businesses around their MCP servers?

That's where MCPize comes in. It's a marketplace where developers sell MCP servers as products.

MCP Server Pricing Models (Dec 2025)

The ecosystem is mostly free right now. But that's changing fast.

Why developers charge for MCP servers:

  • Premium API access isn't cheap. If your server wraps a paid API, you need to cover costs.
  • Enterprise features require support. Companies pay for reliability and SLAs.
  • Specialized tools save time. Time savings have real value.
  • Continuous maintenance. Good servers need updates, bug fixes, security patches.

Pricing models that actually work:

ModelPrice RangeBest For
Subscription$5-20/monthOngoing access, regular updates
Usage-based$0.01-0.10/callAPI wrappers, high-volume tools
One-time$10-50Simple tools, lifetime access
FreemiumFree + paid tierBuilding audience, upselling power users

The revenue opportunity:

MCPize offers 85% revenue share. You build the MCP server, set your price. MCPize handles hosting, billing, distribution, and payments.

I've seen developers make $500-2000/month from a single well-positioned MCP server. The ones that solve real pain points, not the toy examples.

What sells:

  • Integrations with expensive enterprise APIs (cheaper than direct API access)
  • Workflow automations that save hours per week
  • Data processing that requires specialized knowledge
  • Compliance and security focused tools
Browse Paid Servers Sell Your Server

Templates and Starters#

Nobody should build from scratch anymore. These templates give you a head start.

TemplateLanguageWhat's IncludedGet Started
MCPize PythonPythonFastMCP, tests, CI/CD, lintingmcpize init --template python
MCPize TypeScriptTypeScriptZod, ESLint, tests, buildsmcpize init --template typescript
Minimal PythonPythonBare minimum, 10 linesGitHub
Minimal TypeScriptTypeScriptBare minimum, 20 linesGitHub
FastMCP AdvancedPythonMulti-tool, resources, promptsGitHub

The MCPize templates are production-ready. Tests, linting, CI/CD config, everything. Run mcpize init and you're building features in minutes.

Example Servers on MCPize Marketplace#

These are real MCP servers you can install right now. Study them for inspiration.

Top Examples by Category:

ServerCategoryWhat Makes It Good
GitHub MCPDev ToolsClean API, handles auth properly
Supabase MCPDatabaseFull stack integration, real-time
Memory MCPAI/MemorySemantic search, persistence
Notion MCPProductivityDeep integration, block support
Slack MCPCommunicationThreading, reactions, search

Each of these servers follows best practices:

  • Clear tool descriptions (AI needs to understand what each tool does)
  • Proper error handling (don't crash on bad input)
  • Reasonable defaults (sensible behavior without configuration)
  • Good documentation (users need to know how to set up)
Browse All Servers

FAQ#

What are MCP servers and clients?#

Simple breakdown. Servers expose capabilities: tools (actions), resources (data), and prompts (templates). Clients consume them. Claude Desktop, Cursor, VS Code with Copilot, these are clients. When you build an MCP server, you're building something these clients can use.

The protocol is just JSON-RPC over stdio. Servers wait for requests, process them, return results. That's it.

GitHub MCP and Filesystem lead in usage. GitHub has around 2,890 uses tracked on Smithery. Filesystem is essential for any local development workflow.

But "popular" depends on your use case. For database work, PostgreSQL MCP and Supabase MCP dominate. For productivity, Notion and Slack are the top choices.

Can I sell my MCP server?#

Yes. Publish on MCPize, set your price, earn 85% of revenue. MCPize handles hosting, billing, and distribution.

The marketplace is still early. Good opportunity to establish yourself in a niche before it gets crowded.

What language should I use for MCP servers?#

Python with FastMCP for rapid development. The decorator syntax is clean and you can prototype fast. Great for data science integrations too.

TypeScript for production applications. Type safety catches bugs before users hit them. Better tooling for large codebases.

If you're just learning, start with Python. You can always rewrite in TypeScript later.

Do I need to build from scratch?#

No. Use templates: mcpize init --template python or mcpize init --template typescript.

Or fork an existing server from GitHub that's close to what you need. The MCP protocol is standardized, so the structure is always the same.

How do I test my MCP server?#

MCP Inspector is the official testing tool. It connects to your server over stdio and lets you call tools interactively.

npx @modelcontextprotocol/inspector your-server-command

For automated testing, mock the stdio transport and write unit tests for your tool handlers.

Next Steps#

You've seen the MCP server examples. Now build something.

Here's my recommended path:

  1. Pick a category that matches your idea
  2. Copy the relevant example as your starting point
  3. Modify for your use case (add tools, change logic)
  4. Test with MCP Inspector (make sure it actually works)
  5. Deploy and share (or sell on MCPize)

The hardest part is starting. These examples remove that barrier. Now it's just implementation.

Complete Build Guide Python Tutorial TypeScript Tutorial

Related guides:

Building something interesting? Share it in the MCPize Discord or publish to the marketplace.

Enjoyed this article?

Share it with your network

MCPize Team

MCPize Team

Core Team

The team behind MCPize - building the future of MCP server monetization.

Stay Updated

Get the latest MCP tutorials, product updates, and developer tips delivered to your inbox.

No spam, ever. Unsubscribe anytime.

Related Articles

Continue exploring similar topics

View all articles