← Back to Guides

AI & Automation · Toolcalling / MCP

MCP Server Overview and Setup Guide (03/28/26)

This guide gives you one practical path: understand what MCP is, build a minimal MCP server, connect it to a client, and harden it for real use. Audience: technical users already running local models, automation workflows, and tool-calling stacks.

1

What an MCP server is (and where it fits)

Model Context Protocol (MCP) is an open protocol for connecting AI clients to external context and actions in a consistent, tool-like way. An MCP server is the program that exposes capabilities (tools, resources, prompts) over MCP.

Core roles

  • MCP Host: the AI app runtime (Claude Desktop, IDE assistants, OpenClaw-style orchestrators).
  • MCP Client: the connection layer inside that host, one per server connection.
  • MCP Server: your integration endpoint exposing capabilities.

What servers expose

  • Tools: callable functions (usually highest value).
  • Resources: structured/readable context (files, docs, records).
  • Prompts: reusable prompt templates.
Architecture shorthand:
Host app → MCP client connection → MCP server → your local/remote systems.

MCP supports both local servers (commonly stdio) and remote servers (commonly Streamable HTTP). Same protocol semantics, different transport and auth posture.

2

Prerequisites and assumptions

Required

  • Comfort with JSON config and terminal workflows.
  • Node.js 20+ or Python 3.10+.
  • An MCP-capable client (e.g., Claude Desktop or another MCP host).
  • A target system to expose (API, DB, filesystem, internal service).

Scope in this guide

  • Recommended path: local dev server first, then harden.
  • Examples for both Node and Python.
  • Client config example in Claude Desktop format.
  • Best-practice checklist for production readiness.
3

Build a simple MCP server and connect a client

Step 1) Pick your server SDK

  • TypeScript: @modelcontextprotocol/server (+ zod).
  • Python: mcp[cli] with FastMCP.

Step 2) Create a minimal tool (Node/TypeScript skeleton)

# package install (example)
npm install @modelcontextprotocol/server zod

# then implement a simple MCP server with one tool, e.g. "ping" or "search_docs"
# expose strict input schema and deterministic output structure

Step 3) Create a minimal tool (Python / FastMCP skeleton)

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("demo-server")

@mcp.tool()
def ping(message: str) -> str:
    """Return a deterministic echo for connectivity checks."""
    return f"pong: {message}"

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

Step 4) Configure a client to launch your local server

Example Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "demo-server": {
      "command": "python",
      "args": ["/ABSOLUTE/PATH/to/server.py"]
    }
  }
}
Important: use absolute paths in config. For stdio servers, never print normal logs to stdout; use stderr or a logger.

Step 5) Restart client and confirm tool discovery

  1. Restart your MCP client app completely.
  2. Open tool selector / MCP indicator.
  3. Run a known-safe test prompt that triggers your demo tool.
  4. Confirm request/response payload shape matches your schema.

Step 6) Move from local to remote (when needed)

Switch to Streamable HTTP only when you need multi-user access, shared infrastructure, or centralized auth/rate control.

4

Best practices (the part people skip and regret)

Security

  • Principle of least privilege (scoped directories, scoped tokens).
  • Require explicit user approval for state-changing tools.
  • Use OAuth/token rotation for remote servers.
  • Treat tool inputs as untrusted: validate + sanitize.

Schema design

  • Use narrow, explicit schemas with enums where possible.
  • Avoid free-form "do anything" tools.
  • Return consistent JSON-shaped outputs for downstream automation.
  • Version breaking schema changes.

Logging + observability

  • Add request IDs and tool-call timing.
  • Log tool name, args hash, result status, and error class.
  • For stdio transport, log to stderr/file only.
  • Keep sensitive payloads redacted by default.

Reliability

  • Set timeouts for all external calls.
  • Implement retries with jitter for transient errors.
  • Rate-limit expensive tools and respect upstream quotas.
  • Return graceful errors that help the model recover.
Versioning strategy: lock SDK major versions in production, track MCP spec updates, and test clients against your server before rolling changes.
5

Success checks

  • Client loads server without startup errors.
  • Your tool appears in the available MCP tools list.
  • One test call succeeds with predictable output.
  • Error cases return structured failures (not stack traces).
  • Logs show timing + request IDs without leaking secrets.
6

Troubleshooting

  • Tool never appears: bad command/path in client config; verify absolute path and executable.
  • Server crashes on first call: schema mismatch or missing dependency; run server directly first.
  • Random JSON parse failures: stdout pollution in stdio mode; move all logs to stderr.
  • Slow/timeout behavior: add per-tool timeout and cache stable reads.
  • Permission errors: reduce scope, then re-grant only required paths/tokens.
7

References and official docs