MCP Servers: How to Build and Sell Model Context Protocol Tools in 2026
The New Developer Gold Rush
In 2026, the hottest item in every developer's toolkit isn't a new framework or cloud service — it's an MCP server.
Model Context Protocol (MCP) is Anthropic's open standard that lets AI assistants like Claude connect to external tools, APIs, databases, and services. Instead of copy-pasting data into a chat window, you plug your tools directly into the AI. Claude runs in your terminal, and it can query your database, browse your docs, call your APIs — all through MCP.
Thousands of developers are now building and selling MCP servers. This is your guide to joining them.
MCP architecture diagram
What Is MCP? (The 2-Minute Explanation)
MCP is a JSON-RPC protocol. An MCP server exposes tools and resources that an AI client can call. The client (Claude Code, Claude Desktop, Cursor) discovers what tools are available, then calls them during a conversation.
Think of it like a REST API — but instead of a human reading the docs and writing fetch calls, the AI reads the schema and calls the tools autonomously.
Tools = actions the AI can take (run a query, send a message, create a file)
Resources = data the AI can read (database records, file contents, API responses)
Prompts = reusable templates the AI can invoke
Real-World Example
Without MCP:
User: "What were our top 5 revenue-generating users last month?"
→ You open Postgres, run the query, copy results, paste into ClaudeWith MCP:
User: "What were our top 5 revenue-generating users last month?"
→ Claude calls your database MCP server's query_users tool directly
→ Answer appears in secondsWhy MCP Servers Are a Business Opportunity
The MCP ecosystem is exploding but the supply of quality servers is still thin. Most existing servers are:
Buyers on code marketplaces are actively looking for:
A well-built MCP server for a popular SaaS tool can sell for $29–$149 and generate hundreds of sales.
Building Your First MCP Server
Here's a complete, production-ready MCP server that connects Claude to a PostgreSQL database. This is the kind of thing that sells.
Prerequisites
node -v # 18+
npm install @modelcontextprotocol/sdk pg zodProject Structure
postgres-mcp/
├── src/
│ ├── index.ts # Entry point
│ ├── tools/
│ │ ├── query.ts # Read queries
│ │ └── schema.ts # Schema inspection
│ └── connection.ts # DB connection pool
├── package.json
└── tsconfig.jsonThe Connection Pool
// src/connection.ts
import { Pool } from "pg";
let pool: Pool | null = null;
export function getPool(): Pool {
if (!pool) {
pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 10,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
}
return pool;
}
export async function closePool(): Promise<void> {
if (pool) {
await pool.end();
pool = null;
}
}The Query Tool
// src/tools/query.ts
import { z } from "zod";
import { getPool } from "../connection";
export const QueryInput = z.object({
sql: z.string().describe("SQL SELECT query to execute"),
limit: z
.number()
.int()
.min(1)
.max(1000)
.default(100)
.describe("Max rows to return"),
});
export async function executeQuery(
input: z.infer<typeof QueryInput>
): Promise<string> {
// Security: only allow SELECT statements
const normalized = input.sql.trim().toUpperCase();
if (!normalized.startsWith("SELECT") && !normalized.startsWith("WITH")) {
throw new Error("Only SELECT queries are allowed");
}
const pool = getPool();
const limitedSql = `${input.sql.trim().replace(/;\s*$/, "")} LIMIT ${input.limit}`;
const result = await pool.query(limitedSql);
if (result.rows.length === 0) {
return "Query returned no results.";
}
// Format as a readable table
const headers = Object.keys(result.rows[0]);
const rows = result.rows.map((row) =>
headers.map((h) => String(row[h] ?? "NULL")).join(" | ")
);
return [
`Rows: ${result.rows.length}`,
headers.join(" | "),
headers.map(() => "---").join(" | "),
...rows,
].join("\n");
}The Main Server
// src/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { executeQuery, QueryInput } from "./tools/query";
import { closePool } from "./connection";
const server = new Server(
{ name: "postgres-mcp", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "query_database",
description:
"Execute a read-only SQL SELECT query against the PostgreSQL database. " +
"Returns results as a formatted table. Use this to look up user data, " +
"analyze metrics, check order history, or explore any data in the database.",
inputSchema: {
type: "object",
properties: {
sql: {
type: "string",
description: "SQL SELECT query to execute",
},
limit: {
type: "number",
description: "Maximum rows to return (1–1000, default 100)",
},
},
required: ["sql"],
},
},
],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "query_database") {
try {
const input = QueryInput.parse(request.params.arguments);
const result = await executeQuery(input);
return { content: [{ type: "text", text: result }] };
} catch (err) {
const message = err instanceof Error ? err.message : "Unknown error";
return {
content: [{ type: "text", text: `Error: ${message}` }],
isError: true,
};
}
}
return {
content: [{ type: "text", text: `Unknown tool: ${request.params.name}` }],
isError: true,
};
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Postgres MCP server running");
}
main().catch((err) => {
console.error("Fatal error:", err);
closePool();
process.exit(1);
});Configuring Claude to Use It
Add to claude_desktop_config.json (or .claude/settings.json for Claude Code):
{
"mcpServers": {
"postgres": {
"command": "node",
"args": ["/path/to/postgres-mcp/dist/index.js"],
"env": {
"DATABASE_URL": "postgresql://user:password@localhost:5432/mydb"
}
}
}
}Now when you open Claude Code and type:
> "How many users signed up this week, broken down by day?"
Claude calls query_database automatically and returns the answer.
What Makes an MCP Server Sell
After analyzing dozens of successful listings on code marketplaces, the pattern is clear:
1. Solve a specific pain point
Generic "connect to any API" servers don't sell. Specific ones do:
2. Include production-ready auth
OAuth 2.0, API key rotation, environment variable validation with Zod. Buyers are deploying this in their companies — they need it secure.
3. Write exceptional tool descriptions
The description field in your tool schema is what the AI reads to decide when to use the tool. Bad descriptions = Claude won't use it correctly. Good descriptions = magic.
// Bad
description: "Gets user data"
// Good
description:
"Retrieve detailed information about a specific user including their " +
"account status, subscription plan, payment history, and last login. " +
"Use when you need to investigate a specific customer or verify their current state."4. Package it properly
{
"name": "postgres-mcp",
"version": "1.0.0",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "ts-node src/index.ts"
},
"files": ["dist/", "README.md", "claude_desktop_config.example.json"]
}Include a claude_desktop_config.example.json — buyers who can copy-paste the config are buyers who leave 5-star reviews.
Pricing Your MCP Server
| Category | Price Range | Notes |
|---|---|---|
| Simple single-tool server | $9–$19 | Database query, file ops |
| Multi-tool SaaS integration | $29–$59 | Stripe, Linear, Notion |
| Full-stack MCP with UI | $79–$149 | Admin panel + server |
| Enterprise bundle | $199–$499 | Multiple integrations |
The key insight: buyers aren't paying for code, they're paying for hours saved. A Stripe MCP server that lets a founder answer revenue questions in seconds instead of writing SQL queries is easily worth $49.
The MCP Servers Selling Right Now
Based on marketplace demand in early 2026:
Highest demand:
Underserved niches:
The MCP + Vibe Coding Stack
The most efficient setup for building sellable MCP servers in 2026:
# 1. Scaffold with Claude Code
mkdir stripe-mcp && cd stripe-mcp
claude
# Prompt:
# "Build a TypeScript MCP server for Stripe. Include tools for:
# - Querying recent charges and revenue
# - Looking up customer subscriptions
# - Creating payment links
# - Retrieving invoice history
# Use the @modelcontextprotocol/sdk and stripe npm packages.
# Add proper error handling and Zod validation."Claude Code scaffolds the entire server. You review the output, test it against your own Stripe account, clean up edge cases in Cursor, and you have a sellable product in an afternoon.
Publishing to CodeCudos
When your MCP server is ready:
The buyers for MCP servers are developers and technical founders who understand the value immediately. You don't need to explain what MCP is — just show the output.
---
Summary
MCP servers are the fastest-growing category in developer tools right now. The protocol is simple, TypeScript support is first-class, and the buyers are there.
The formula:
One good MCP server, sold 50 times, is $1,500–$2,500 in passive income — from a day's work.