Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

The shortest path to a working MCP server is a typed Python tool, tested locally with the MCP Inspector. For a local application that starts your server as a child process, use stdio. For a network service, use Streamable HTTP. The official SDKs support tools, resources, prompts, clients, and both local and remote transports; TypeScript and Python are the clearest starting points.

What an MCP server actually exposes

Model Context Protocol (MCP) standardizes how an AI host discovers and calls capabilities supplied by another process or service. A server can expose three primitives:

  • Tools are callable operations, such as adding numbers, querying a database, or creating a ticket.
  • Resources are addressable data, identified by URIs such as greeting://Ada.
  • Prompts are reusable prompt templates that a host can present to a user or model.

The official SDK map labels TypeScript, Python, C#, and Go as Tier 1; Java, Rust, and Ruby as Tier 2; and Swift, PHP, and Kotlin as Tier 3. Each SDK is intended to support servers and clients, local and remote transports, protocol compliance, and type safety.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Minimal Python MCP server

The Python SDK v2 is the current stable release line, supports the 2026-07-28 MCP specification and earlier revisions, and requires Python 3.10 or newer. Type annotations become the tool schema, while the SDK handles request parsing, validation, and protocol framing.

1. Create the project

mkdir mcp-demo
cd mcp-demo
uv init
uv add "mcp[cli]"

If you use pip instead, install the same extra with pip install "mcp[cli]".

2. Add a server with a tool and resource

from mcp.server import MCPServer

mcp = MCPServer("Demo")

@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers."""
    return a + b

@mcp.resource("greeting://{name}")
def greeting(name: str) -> str:
    """Greet someone by name."""
    return f"Hello, {name}!"

Save this as server.py. The decorators register the capabilities; the annotations tell clients that a and b are integers and that the result is an integer. Keep tool functions deterministic and validate authorization inside the function before touching private data.

3. Open it in MCP Inspector

uv run mcp dev server.py

The command starts the development flow and opens the MCP Inspector. Select the add tool, provide two integers, and verify the returned value. Then open the greeting://{name} resource with a concrete name. Inspector testing catches malformed schemas and transport problems before you involve an AI host.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Minimal TypeScript server

The TypeScript v2 line implements the 2026-07-28 specification. Its packages are split into @modelcontextprotocol/server and @modelcontextprotocol/client; install the server package with:

npm install @modelcontextprotocol/server zod

The implementation sequence is always the same: create an McpServer, register tools, resources, and prompts, choose a transport, then call server.connect(transport).

Local stdio example

import { McpServer } from "@modelcontextprotocol/server";
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { z } from "zod";

const server = new McpServer({ name: "demo", version: "1.0.0" });

server.tool(
  "add",
  "Add two numbers",
  { a: z.number(), b: z.number() },
  async ({ a, b }) => ({ content: [{ type: "text", text: String(a + b) }] })
);

server.resource("greeting", "greeting://{name}", async (uri) => ({
  contents: [{ uri: uri.href, text: `Hello, ${uri.pathname.slice(1)}!` }]
}));

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

Run the compiled file from your host configuration or an MCP client. The v2 documentation also provides a one-file pattern using serveStdio and Standard Schema/Zod validation. The exact helper names can differ between minor releases, so keep the package version pinned and follow the API exported by that version.

Choosing stdio or Streamable HTTP

Use case Transport Session choice Trade-off
A desktop app or editor launches your server stdio Process lifetime Simple, private, and no listening port; the host must be able to spawn the process.
A shared service on a network Streamable HTTP Stateful or stateless Reachable remotely; you must operate an HTTP endpoint and enforce authentication.

Stateful Streamable HTTP

Use NodeStreamableHTTPServerTransport with a session-ID generator when clients need resumability. Retain session state in a durable store if requests can land on different instances, and expire abandoned sessions.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Stateless Streamable HTTP

Pass undefined for the session-ID generator to select stateless mode. It is simpler to scale and deploy, but it does not support resumability. Put all required context in each request or in an external data store.

Registering resources and prompts

Tools perform actions; resources provide read-oriented context; prompts package repeatable instructions. A useful server often combines all three: a tool to query an issue tracker, a resource for the current project policy, and a prompt that asks the model to summarize an issue using that policy. Give every capability a stable name and description because hosts use those fields to decide what to show a model.

Testing and production boundaries

Use runnable pairs, not copied fragments

The official TypeScript repository includes runnable, self-verifying client/server pairs in its examples collection, with support for Node.js, Bun, and Deno. Start there when you need to see initialization, capability discovery, and error handling together.

Do not treat example servers as hardened services

The official modelcontextprotocol/servers repository states: “They are meant to serve as educational examples for developers building their own MCP servers, not as production-ready solutions.” Before deployment, add authentication, authorization, input limits, secret management, structured logs, timeouts, cancellation, dependency pinning, and tests for every tool’s side effects.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Connecting a host such as GitHub Copilot

A host normally launches a local server from configuration, supplying the command and arguments, then speaks MCP over the configured transport. GitHub’s Copilot SDK documentation demonstrates this pattern for both Node.js/TypeScript and Python. Your configuration should use an absolute interpreter or executable path where possible, pass a virtual-environment or project path explicitly, and keep secrets in environment variables rather than command-line arguments.

Typical launch checklist

  1. Install dependencies in the same environment the host will use.
  2. Run the server directly from a terminal and exercise every tool in Inspector.
  3. Configure the host with the command, arguments, and working directory.
  4. Restart the host after changing the configuration; many clients read it only at startup.
  5. Confirm that server logs go to stderr. Writing diagnostic text to stdout corrupts stdio protocol messages.

Reliability, security, and performance checklist

  • Bound work: impose request, result-size, database, and network timeouts.
  • Validate inputs: schemas reject wrong types, but business rules still belong in your code.
  • Minimize authority: expose narrow tools instead of a general shell or unrestricted database connection.
  • Protect secrets: never return API keys in resource text or error messages.
  • Make retries safe: use idempotency keys for tools that create or charge something.
  • Control concurrency: cap parallel calls and queue expensive jobs.
  • Observe without leaking: log request IDs, duration, and outcome while redacting prompts and credentials.
  • Handle cancellation: stop downstream work when the client disconnects.

Troubleshooting common failures

Inspector cannot start the server

Check that Python is 3.10 or newer, the mcp[cli] extra is installed in the active environment, and the file path is correct. With Node, compile or run the file using the same Node version and package manager that installed the SDK.

The host reports invalid JSON or an unexpected message

For stdio, stdout is reserved for MCP protocol traffic. Move prints and debug logs to stderr. Also remove shell banners or wrappers that emit text before the server starts.

A tool is missing from the host

Restart the host, verify that the server reached connect, and inspect the advertised tool name and schema. A syntax error during startup can leave a stale configuration that looks connected but exposes no capabilities.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

HTTP clients lose context between calls

You likely selected stateless Streamable HTTP or deployed stateful sessions without shared storage. Use a session-ID generator and shared session persistence when resumability is required; otherwise include all context in each request.

Calls time out

Instrument each downstream operation, set explicit timeouts, and return a concise error that identifies the failed dependency. Do not let a tool wait indefinitely on a browser, database, or third-party API.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your MCP project needs website screenshots as a tool, ScreenshotNeo provides an MCP server for AI agents plus a one-request screenshot API. It accepts consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result.

Use the API directly (the complete option reference is in the ScreenshotNeo documentation):

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also supports tools such as take_screenshot, get_page_info, and capture_pdf through MCP, so an AI host can request captures without you maintaining browser-launch code. Free accounts include 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

FAQ

Which language should I choose first?

Choose Python for the smallest typed example and fastest Inspector experiment; choose TypeScript when your host, deployment, or existing codebase is Node-oriented.

Can one server expose all three MCP primitives?

Yes. Register tools, resources, and prompts on the same server, then expose it over the transport your host requires.

Is Streamable HTTP always better for teams?

No. It is appropriate for a remotely reachable service. A local, host-spawned integration is usually simpler and safer over stdio.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Frequently Asked Questions

Does MCP replace an API gateway?

No. MCP defines capability discovery and invocation between hosts, clients, and servers; authentication, rate limiting, routing, and deployment remain your responsibility.

How should I version an MCP server?

Pin the SDK and runtime, publish a server version, and treat tool names and input schemas as compatibility-sensitive interfaces.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.