An MCP (Model Context Protocol) server is a small program you run that exposes a set of tools for AI assistants to call — and building your first one is the single highest-leverage skill a non-engineer founder can pick up in 2026 once Claude Code or Cursor is in their daily workflow. Yesterday I built an MCP server that exposes 7 tools for managing my Notion content briefs database. From “I should automate this” to “Claude is running it autonomously” — total time: 84 minutes. Now Claude reads, updates, and creates content briefs directly without me opening Notion.

If you’ve read Claude Code first 30 days and Claude Code Plan Mode tutorial, MCP servers are the day-30+ unlock. They’re how Claude (or any MCP-compatible AI) stops being a chatbot and starts being a true team member with hands on your tools.

This article is the 90-minute tutorial I wish I’d had when I built my first server.

What MCP actually is

The Model Context Protocol is Anthropic’s open standard for connecting AI assistants to external tools and data. Released November 2024, widely adopted by Q2 2025, mature by Q1 2026. The official MCP specification lists 800+ public servers as of May 2026.

The structure:

[Your AI assistant: Claude Desktop, Claude Code, Cursor]
                ↓ (MCP protocol)
[MCP Client built into the AI assistant]

[MCP Server: a small program you run]

[The actual thing: Notion API, your database, your custom logic, etc.]

The MCP server is the translator. It tells the AI assistant: “Here are 7 tools I expose. Here’s what each one does. Here’s what arguments each takes. Call any of them and I’ll respond.”

The AI assistant doesn’t need custom integration code for each tool. It speaks MCP; the server speaks MCP; the underlying service speaks whatever it speaks. The protocol is the contract.

What you’ll build (the example)

To make this concrete, I’ll walk through the actual server I built for 500k.io: a Notion content briefs MCP server. The 7 tools:

ToolWhat it does
list_briefsList all content briefs in the Notion database
get_briefFetch a specific brief by ID
create_briefCreate a new brief with title, keyword, format
update_brief_statusChange a brief’s status (queued/in-progress/published/killed)
add_brief_noteAppend a note to a brief’s notes field
find_briefs_by_statusFilter briefs by status
find_briefs_by_keywordSearch briefs by keyword

That’s 7 tools. Focused. Scoped to one job (managing content briefs). I built it in 84 minutes. By the time you finish this tutorial, you should be able to build something similar in 90-120 minutes.

Prerequisites (5 minutes)

Before starting, you need:

  1. Node.js installed (version 18+) — check with node --version
  2. Claude Code or Cursor — for writing the code with you (see Cursor for non-engineers)
  3. The service’s API key — for our example, a Notion integration token (15 min to set up)
  4. A target service to wrap — Notion, Airtable, your own database, whatever

For the Notion integration token:

  1. Visit https://www.notion.so/my-integrations
  2. Click “New integration”
  3. Name it “MCP Server” or similar
  4. Pick the workspace, save
  5. Copy the “Internal Integration Token” (starts with secret_...)
  6. Open your Notion database, click ”…” → “Add connections” → select your integration

That’s the prerequisite work. Total time: 15 minutes if it’s your first time, 3 minutes if you’ve done it before.

Step 1 — Create the project (10 minutes)

Open your terminal, create a new project directory:

mkdir notion-briefs-mcp
cd notion-briefs-mcp
npm init -y
npm install @modelcontextprotocol/sdk @notionhq/client

That installs the MCP SDK (the official tool for building MCP servers in TypeScript/JavaScript) and the Notion client library.

Create a .env file with your secrets:

NOTION_TOKEN=secret_xxxxxxxxxxxx
NOTION_DATABASE_ID=xxxxxxxxxxxx

Open the project in Claude Code or Cursor.

Step 2 — Write the server skeleton with Claude Code (20 minutes)

This is where the AI does the heavy lifting. Open a fresh Claude Code session and use this prompt:

“I’m building an MCP server in TypeScript that wraps the Notion API. The server should expose 7 tools for managing a content briefs database:

  1. list_briefs — returns all briefs with title, status, ID
  2. get_brief — returns a single brief by ID with all properties
  3. create_brief — creates a new brief; args: title (string), keyword (string), format (string)
  4. update_brief_status — updates status; args: brief_id (string), status (one of ‘queued’, ‘in-progress’, ‘published’, ‘killed’)
  5. add_brief_note — appends a note; args: brief_id (string), note (string)
  6. find_briefs_by_status — filters briefs; args: status (string)
  7. find_briefs_by_keyword — searches briefs; args: keyword (string)

Use the @modelcontextprotocol/sdk and @notionhq/client packages. Load the Notion token and database ID from .env. The Notion database has these properties: Title (title), Status (select), Keyword (rich_text), Format (select), Notes (rich_text). Use stdio transport for local development.

Generate the full server in src/server.ts. Use Plan Mode.”

Claude Code with Plan Mode will produce a 5-7 step plan. Review it, approve it, watch the server get built.

The output is typically:

src/
  server.ts        (the MCP server)
  notion-client.ts (Notion wrapper functions)
.env
package.json       (updated with scripts)
tsconfig.json      (TypeScript config)

Step 3 — Test the server locally (15 minutes)

Add a script to package.json:

{
  "scripts": {
    "dev": "tsx src/server.ts",
    "build": "tsc"
  }
}

Test the server runs:

npm run dev

If it runs without errors, the server is listening on stdio. You’ll see something like:

[MCP] Server started. Listening on stdio.

Press Ctrl+C to stop.

To test the tools actually work, ask Claude Code (in the same project directory):

“Connect to the MCP server in this project using stdio transport. List the available tools and call list_briefs to verify it works.”

Claude Code will spawn the server, connect, list the tools, call list_briefs, and report what it found.

If the call works and returns real data from your Notion database, the server is functional. If anything fails, the error message tells you what to fix. Common fixes: missing .env values, wrong database property names, integration not connected to the database.

Step 4 — Wire the server into Claude Desktop or Claude Code (15 minutes)

The server runs. Now connect it to your AI assistant.

For Claude Desktop

Open Claude Desktop → Settings → Developer → Edit Config. The file is at ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or equivalent on Windows/Linux.

Add your server:

{
  "mcpServers": {
    "notion-briefs": {
      "command": "node",
      "args": ["/full/path/to/notion-briefs-mcp/dist/server.js"],
      "env": {
        "NOTION_TOKEN": "secret_xxx",
        "NOTION_DATABASE_ID": "xxx"
      }
    }
  }
}

Note: you’ll need to npm run build first to generate the compiled dist/server.js.

Restart Claude Desktop. Your server should now be listed in the available MCP tools (small icon at the bottom of the chat input).

For Claude Code

Add to ~/.config/claude-code/mcp_servers.json (or .claude/mcp.json in your project for project-scoped):

{
  "mcpServers": {
    "notion-briefs": {
      "command": "node",
      "args": ["/full/path/to/notion-briefs-mcp/dist/server.js"]
    }
  }
}

Restart Claude Code. Run /mcp to confirm the server shows green.

Smoke test

In Claude Desktop or Claude Code, prompt:

“Use the notion-briefs MCP to list all my content briefs. Then create a new brief with title ‘Test brief from MCP’, keyword ‘mcp-test’, format ‘tutorial’.”

If the server returns the list and creates the brief (verify in Notion), your server is production-ready for personal use.

Step 5 — Add the rules file (10 minutes)

If you’re using Claude Code, add a note to your CLAUDE.md:

## MCP Servers wired

- notion-briefs (local): manages content briefs in the Notion database
  - Tools: list_briefs, get_brief, create_brief, update_brief_status, add_brief_note, find_briefs_by_status, find_briefs_by_keyword
  - Use when: I ask about briefs, content planning, or editorial calendar
  - Do NOT use when: I'm asking about already-published articles or general Notion docs

This tells Claude Code when to use the new tools. Without this note, the agent may not pick the right tool for the right task.

The 5 mistakes I made building my first 3 servers

Mistake 1 — Too many tools

My first server exposed 22 tools. Claude Code got confused about which tool to use for what, and the response quality dropped. I rebuilt the server with 7 tools. Quality jumped back up.

Rule: 5-10 tools per server. If you need more, split into multiple servers (one for “read operations,” one for “write operations,” etc.).

Mistake 2 — Vague tool descriptions

The MCP protocol uses tool descriptions (the description field) to help AI assistants decide when to call each tool. My first server had descriptions like “lists briefs” — too vague.

Better: “Lists all content briefs in the 500k.io editorial calendar, returning title, status, ID, and creation date. Use when the user asks about the current state of the content pipeline or wants to see what’s queued.”

The longer, more specific description helps the agent pick the right tool.

Mistake 3 — No error handling on Notion side

The Notion API sometimes returns rate-limit errors or malformed responses. My first server passed these errors through raw, which broke the AI assistant’s flow.

Fix: wrap each Notion call in try/catch, return a structured error object with a clear message. Claude can then handle the error gracefully (“Notion is rate-limited, I’ll wait 30 seconds and retry”).

Mistake 4 — Storing secrets in code

I once committed a Notion token to a git repo (caught it before push). The standard practice: secrets in .env, .env in .gitignore, never in code. Sounds obvious; it’s the #1 mistake in tutorials.

Mistake 5 — Building before checking for existing servers

For Notion specifically, there are already 3-4 public Notion MCP servers on GitHub. Some are good enough. I should have evaluated those first before building. The general rule: search the MCP servers registry before building from scratch.

When to build your own vs use existing

SituationBuild or use?
Common service (Notion, Airtable, Slack, GitHub)Try existing first
Your own database or internal APIBuild (no existing option)
Custom workflow that wraps multiple servicesBuild
Standard SaaS with public APISearch registry first; build if no good fit
Something Anthropic or OpenAI has officially builtUse official (see Meta Ads MCP — Meta’s official server saved me 25+ minutes of setup)

The MCP ecosystem grew from ~50 servers in early 2025 to 800+ by May 2026. Most common SaaS tools have a community or official MCP server. Search first.

Hosting: local vs cloud

For personal tools, local is fine. The server runs alongside Claude Code on your machine. Zero hosting cost. The only “cost” is starting the server when needed (or wiring it to start automatically).

Cloud hosting matters when:

  • You need the server to run when your laptop is off (e.g., for scheduled tasks)
  • Multiple team members need access
  • The server needs to handle high throughput
  • You need 24/7 availability

For 500k.io, my notion-briefs MCP runs locally because I only use it during active work sessions. The citation tracker MCP (which fires daily on cron) runs on a $5/mo Hetzner VPS.

If you go cloud, the simplest path is Cloudflare Workers or Vercel for HTTP-transport MCP servers. ~$0-5/mo for typical solo founder volume.

A 90-minute total time breakdown

For your first MCP server:

StepTime
Prerequisites (API key, database setup)15 min
Project init + dependencies10 min
Server skeleton with Claude Code + Plan Mode20 min
Local testing15 min
Wire to Claude Desktop / Claude Code15 min
Rules file note10 min
First real use + minor fixes5 min
Total~90 min

By your third server, this drops to 30-45 minutes. The first one is the hardest because you’re learning the MCP protocol and the SDK conventions. After that, it’s mostly copy-pasting your pattern.

What to build next

Once your first MCP server is working, ideas in increasing complexity:

  1. A second wrapper around a different service (Airtable, Linear, Stripe, GitHub)
  2. A custom workflow MCP that chains 2-3 actions together (e.g., “publish article: read from Notion → write to MDX file → commit to git → trigger deploy”)
  3. A read-only data server that exposes your own database (Supabase, Postgres) as MCP tools
  4. A team-shared MCP server hosted on the cloud, accessible to multiple people

The pattern that compounds: each MCP server you build exposes one more part of your operation to your AI assistant. By 5-10 servers, the assistant has hands on most of your tools and the work-handoff-friction drops dramatically.

The single-paragraph MCP server verdict

MCP servers are the bridge between AI assistants and your actual tools. Building your first one takes ~90 minutes with Claude Code or Cursor doing the heavy lifting. Use cases: Notion, Airtable, custom databases, internal APIs, multi-step workflows. Start local; move to cloud when proven. Keep each server focused (5-10 tools). Search the registry before building from scratch. The skill compounds — by your fifth server, you’ll be wiring AI to your entire ops layer.

For the wider context, see Meta Ads funnel + MCP playbook, Claude Code first 30 days, Plan Mode tutorial, and n8n + AI workflows.

FAQ

What's an MCP server in plain English?

It's a small program you run on your computer (or a server) that exposes 'tools' (functions) for an AI to call. Think of it as a translator between your AI assistant and a specific service. Claude wants to read your Notion docs? You build a Notion MCP server. Claude wants to manage your Meta Ads? You use Meta's official MCP server. The protocol is the standard interface.

Do I need to know how to code to build one?

You need to be comfortable letting Claude Code or Cursor write the code, then running it and debugging when it breaks. The first MCP server you build will take ~90 minutes. By the third, you'll be down to 30 minutes. The skill that matters is reading the docs of the service you're wrapping, not writing the MCP code itself.

What's the difference between an MCP server and an API?

An MCP server wraps an API in the MCP protocol, so the AI can discover the available tools, call them, and handle responses in a structured way. The API exists either way. The MCP server is the thin layer that makes it usable by AI assistants without custom integration work.

Should I host my MCP server in the cloud or locally?

Local for personal tools (it runs alongside Claude Code on your machine). Cloud for tools that need to run when you're not at your computer or that need to scale. Start with local. Move to cloud when the local version is proven and you need 24/7 availability.

What's the most common MCP server mistake?

Building a server with too many tools. The temptation is to expose every function of the underlying API as an MCP tool. Don't. Expose 5-10 carefully scoped tools. AI assistants get confused with 30+ tools in one server. Focused servers compose better.