How to Set Up an MCP Server -- The Complete Guide for Developers
How to Set Up an MCP Server -- The Complete Guide for Developers
The Model Context Protocol (MCP) is an open standard that lets AI assistants like Claude connect to external tools, databases, APIs, and file systems. Instead of copy-pasting data into chat windows, MCP lets the AI reach out and interact with your systems directly.
This guide walks you through setting up your first MCP server, connecting it to Claude, and building custom tools that actually solve real problems.
What Is MCP and Why Should You Care?
Think of MCP as a USB port for AI. Before USB, every device needed its own proprietary connector. MCP does the same thing for AI integrations -- it provides one standard protocol that any AI client can use to talk to any tool.
Without MCP, if you want Claude to query your database, you have to:
- 1Run the query yourself
- 2Copy the results
- 3Paste them into the chat
- 4Wait for analysis
- 5Repeat for every follow-up question
With MCP, Claude can query your database directly, read your files, call your APIs, and perform actions -- all within the conversation.
Key Concepts
- •MCP Host: The AI application (like Claude Desktop or Claude Code) that connects to servers
- •MCP Server: A lightweight program that exposes specific capabilities through the standard protocol
- •Tools: Functions the AI can call (like "query_database" or "create_ticket")
- •Resources: Data the AI can read (like files, database schemas, or documentation)
- •Prompts: Reusable prompt templates the server can provide
Prerequisites
Before you start, make sure you have:
- •Node.js 18+ or Python 3.10+ (depending on which SDK you use)
- •Claude Desktop or Claude Code installed
- •A text editor (VS Code recommended)
- •Basic familiarity with TypeScript or Python
Option 1: Building an MCP Server with TypeScript
Step 1: Initialize the Project
Create a new directory and set up a TypeScript project:
> mkdir my-mcp-server && cd my-mcp-server
> npm init -y
> npm install @modelcontextprotocol/sdk zod
> npm install -D typescript @types/node
> npx tsc --init
Step 2: Create the Server
Create a file called server.ts with the basic structure:
> import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
> import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
> import { z } from "zod";
>
> const server = new McpServer({
> name: "my-first-server",
> version: "1.0.0",
> });
>
> // Define a tool
> server.tool(
> "greet",
> "Greet a user by name",
> { name: z.string().describe("The name to greet") },
> async ({ name }) => ({
> content: [{ type: "text", text: "Hello, " + name + "! Welcome." }],
> })
> );
>
> // Start the server
> const transport = new StdioServerTransport();
> await server.connect(transport);
Step 3: Build and Test
Add a build script to your package.json:
> "scripts": {
> "build": "tsc",
> "start": "node dist/server.js"
> }
Make sure your tsconfig.json has these settings:
> "module": "Node16",
> "moduleResolution": "Node16",
> "outDir": "./dist"
Build the project:
> npm run build
Step 4: Connect to Claude Desktop
Open your Claude Desktop config file:
- •macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
- •Windows: %APPDATA%/Claude/claude_desktop_config.json
Add your server:
> {
> "mcpServers": {
> "my-first-server": {
> "command": "node",
> "args": ["/absolute/path/to/my-mcp-server/dist/server.js"]
> }
> }
> }
Restart Claude Desktop. You should see your server listed in the MCP tools menu.
Option 2: Building an MCP Server with Python
Step 1: Set Up the Project
> mkdir my-mcp-server && cd my-mcp-server
> python -m venv venv
> source venv/bin/activate
> pip install mcp
Step 2: Create the Server
Create server.py:
> from mcp.server.fastmcp import FastMCP
>
> mcp = FastMCP("my-first-server")
>
> @mcp.tool()
> def greet(name: str) -> str:
> """Greet a user by name."""
> return f"Hello, {name}! Welcome."
>
> if __name__ == "__main__":
> mcp.run()
Step 3: Connect to Claude Desktop
Add to your Claude Desktop config:
> {
> "mcpServers": {
> "my-first-server": {
> "command": "python",
> "args": ["/absolute/path/to/my-mcp-server/server.py"]
> }
> }
> }
Building Real-World Tools
A greeting tool is a good test, but here are examples of tools that solve real problems.
Database Query Tool
> server.tool(
> "query_db",
> "Run a read-only SQL query against the database",
> {
> query: z.string().describe("SQL SELECT query to run"),
> },
> async ({ query }) => {
> if (!query.trim().toUpperCase().startsWith("SELECT")) {
> return { content: [{ type: "text", text: "Error: Only SELECT queries are allowed." }] };
> }
> const results = await db.query(query);
> return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
> }
> );
File Search Tool
> server.tool(
> "search_files",
> "Search for files matching a pattern in the project",
> {
> pattern: z.string().describe("Glob pattern like */.ts"),
> directory: z.string().optional().describe("Directory to search in"),
> },
> async ({ pattern, directory }) => {
> const glob = await import("glob");
> const files = await glob.glob(pattern, { cwd: directory || "." });
> return { content: [{ type: "text", text: files.join("\n") }] };
> }
> );
API Caller Tool
> server.tool(
> "call_api",
> "Make a GET request to an API endpoint",
> {
> url: z.string().url().describe("The URL to fetch"),
> },
> async ({ url }) => {
> const response = await fetch(url);
> const data = await response.json();
> return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
> }
> );
Adding Resources
Resources let the AI read data without calling a tool. They are great for documentation, schemas, or configuration files.
server.resource(
"project-readme",
"file:///project/README.md",
async (uri) => {
const content = await fs.readFile("./README.md", "utf-8");
return { contents: [{ uri: uri.href, text: content, mimeType: "text/markdown" }] };
}
);
Security Best Practices
MCP servers run on your machine with your permissions. Take security seriously:
- 1Validate all inputs -- never pass user input directly to shell commands or SQL without sanitization
- 2Use read-only database connections when the AI only needs to read data
- 3Limit file system access -- do not give the server access to your entire home directory
- 4Log tool calls -- keep a record of what the AI is doing through your server
- 5Use environment variables for secrets -- never hardcode API keys or passwords in the server code
Debugging Tips
- •Check the logs: Claude Desktop logs MCP communication. On macOS, check ~/Library/Logs/Claude/
- •Test standalone: Run your server directly with a test client before connecting to Claude
- •Use the MCP Inspector: The official MCP Inspector tool lets you interact with your server in a browser
- •Start simple: Get one tool working before adding complexity
Common Mistakes
- •Forgetting to rebuild: TypeScript servers need to be recompiled after changes. Run npm run build before restarting Claude
- •Relative paths: Always use absolute paths in the Claude Desktop config
- •Wrong Node version: MCP SDK requires Node.js 18 or higher
- •Not restarting Claude: After changing the config, you need to fully restart Claude Desktop
What to Build Next
Once you have the basics down, consider building servers for:
- •Your project's database -- let Claude query and analyze your data
- •Your CI/CD pipeline -- check build status, trigger deployments
- •Your issue tracker -- create, update, and search tickets from the conversation
- •Your monitoring tools -- pull metrics and logs into Claude for analysis
- •Your documentation -- give Claude access to internal docs and wikis
MCP is still evolving rapidly, and the ecosystem of pre-built servers is growing. Check the official MCP repository for community-built servers you can use directly.
For more developer guides and free tools, check out our blog and explore our developer tools.