An MCP server is a program that exposes capabilities to an MCP client through a standard protocol. The fastest safe starting point is a narrowly scoped tool: define an input schema, register a handler, run the server over stdio, and verify the tool with MCP Inspector. Use Streamable HTTP when the server is hosted remotely. This guide builds that first server, explains resources and prompts, shows the Python SDK path, and covers the checks that prevent version, transport, and protocol errors.
What an MCP server provides
Model Context Protocol (MCP) servers publish capabilities that a client can discover and use:
- Tools are actions. A client supplies validated arguments and the server performs work, such as querying a service or transforming data.
- Resources are readable data identified by resource URIs. They are suitable for documents, records, or other context a client needs to read.
- Prompts are reusable prompt templates that standardize how a client asks for work.
Start with one useful tool. Add resources or prompts only when your use case needs shared data or repeatable instructions. Keep handlers narrow, validate every argument, and return a clear result that the client can display.
Choose the SDK generation and runtime first
The official TypeScript SDK documentation describes v2 as the stable release line implementing the 2026-07-28 MCP specification. It replaces the v1 monolithic package, so do not mix v1 imports with v2 examples. The Python documentation likewise has a stable v2 line and a separately maintained v1 line. Check the SDK version and migration notes before copying code.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstall#1 Best Overall
| Path | Prerequisite | Installation | Best fit |
|---|---|---|---|
| TypeScript SDK v2 | Node.js 20 or later | npm install @modelcontextprotocol/server zodnpm install -D tsx |
A local server launched as a child process |
| Python SDK v2 | Python 3.10 or later | uv add "mcp[cli]" or pip install "mcp[cli]" |
Python services using stdio, Streamable HTTP, or SSE |
The TypeScript v2 package layout and the Python v2 APIs can change, so compare the installed package’s documentation with the example below if your version reports an import or method error.
Build a minimal TypeScript MCP server
1. Create the project
- Install Node.js 20 or later.
- Create a directory and initialize it with
npm init -y. - Install the server SDK, Zod, and the
tsxrunner:
npm install @modelcontextprotocol/server zod
npm install -D tsx
Mark the project as an ES module by adding "type": "module" to package.json. Create server.ts.
2. Register one validated tool
This example exposes a small deterministic tool that returns a deployment checklist. It demonstrates the important pieces without requiring a third-party API.
import { z } from "zod";
import { createServer, serveStdio } from "@modelcontextprotocol/server";
const server = createServer({
name: "deployment-checklist",
version: "1.0.0",
});
server.tool(
"deployment_checklist",
"Create a short checklist for a deployment environment.",
{
environment: z.enum(["development", "staging", "production"]),
owner: z.string().min(1).max(80),
},
async ({ environment, owner }) => ({
content: [{
type: "text",
text: [
`Environment: ${environment}`,
`Owner: ${owner}`,
"Verify configuration, run the smoke test, and confirm rollback steps.",
].join("\n"),
}],
}),
);
await serveStdio(server);
The declared schema is checked before the handler runs. An invalid environment or an empty owner therefore fails as an input-validation error instead of reaching your business logic. Replace the handler with your real operation, but keep the same discipline: bounded strings, explicit enums, and no implicit credentials supplied by the caller.
Free tools Windows power users keep installed
One-click scans. No signup required.
3. Keep stdout exclusively for MCP traffic
serveStdio reads requests from standard input and writes protocol responses to standard output. A stray console.log can corrupt the JSON-RPC stream and make a client report malformed messages or disconnect. Send diagnostics to standard error instead:
Rank #2
console.error("starting deployment-checklist server");
Run the file with:
npx tsx server.ts
A terminal may appear to do nothing because the process is waiting for protocol messages. That is normal for a stdio server; use an MCP client or Inspector to interact with it.
Verify the server with MCP Inspector
Testing only that the process starts is insufficient. Connect MCP Inspector to the server over stdio, confirm that deployment_checklist appears in the tool list, and invoke it with an object such as {"environment":"staging","owner":"Alex"}. The successful response should contain the three text lines produced by the handler.
- If the tool is absent, inspect the startup output on stderr and confirm that the client launched the intended file.
- If invocation is rejected, compare every property name and value with the Zod schema.
- If the connection closes immediately, remove all ordinary stdout logging and check the Node.js and package versions.
The official tutorials use MCP Inspector for this discovery-and-call workflow. Treat it as a protocol test: list capabilities, call each tool with valid input, then exercise invalid input to confirm that validation behaves as expected.
Choose the transport for your deployment
| Deployment | Transport | How communication works | Critical concern |
|---|---|---|---|
| Local integration | stdio | The host launches your process and exchanges messages through stdin/stdout. | Keep stdout clean; write logs to stderr. |
| Remote service | Streamable HTTP | The client connects to an HTTP endpoint hosted by your service. | Apply the SDK’s HTTP deployment and security guidance. |
Streamable HTTP is the documented choice for a remotely hosted server. TypeScript v1 documentation also describes HTTP+SSE as a backward-compatibility option. That legacy transport guidance should not be mistaken for current v2 server code; use the current SDK documentation and migration instructions when deploying it.
Python SDK route
Use Python SDK v2 with Python 3.10 or later. Install it with uv add "mcp[cli]" or pip install "mcp[cli]". The v2 documentation covers tools, resources, prompts, stdio, Streamable HTTP, and SSE.
The maintained v1 documentation contains a compact FastMCP example with an add tool, a greeting://{name} resource, and a greet_user prompt. It is explicitly a v1 example, so do not paste its imports into a v2 project without checking the migration guidance.
Python v2 also demonstrates an in-memory client test: connect a client directly to the server object, call a tool, and assert the structured content. This test path needs no subprocess, listening port, or network transport and is useful for unit tests before you verify the deployed transport.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Add resources and prompts deliberately
Resources
Add a resource when clients need to read stable or addressable data, such as a document or record. Give it a predictable URI and enforce authorization before returning content. Do not turn every internal database query into a resource; expose only data the client is allowed to see.
Prompts
Add a prompt when users repeatedly need the same structured request. Keep variable names explicit and document what the resulting prompt is intended to accomplish. Prompts guide a client; they do not replace authorization or input validation in tools.
Capability growth
After the first tool works, add one capability at a time. Re-run discovery and valid/invalid invocation tests after each change so a new resource or prompt cannot silently break the existing interface.
Production checks and failure recovery
Version and package mismatch
Symptom: an import, factory, or transport method is undefined. Fix: inspect the installed SDK version, select one generation, and follow that generation’s documentation. TypeScript v2 and Python v2 should not be combined with v1 snippets.
Recommended Free Tools
Transport mismatch
Symptom: a remote client attempts stdio, or a local host expects an HTTP endpoint. Fix: use stdio for a host-launched local process and Streamable HTTP for a hosted endpoint. Ensure both client and server select the same transport.
Dirty stdout
Symptom: JSON-RPC parse errors or an immediate disconnect over stdio. Fix: remove console.log, print diagnostics to stderr, and ensure dependencies do not write banners to stdout.
Schema and argument errors
Symptom: the client discovers the tool but every call is rejected. Fix: send the exact property names and types declared by the schema; test boundary values and deliberately invalid values in Inspector.
Slow or unreliable handlers
- Set timeouts around outbound services and return actionable errors rather than hanging.
- Keep tool results bounded; paginate or provide a resource for large data.
- Log request identifiers and failures to stderr or your service logger, never into stdio protocol output.
- Test startup, capability discovery, successful calls, invalid calls, cancellation behavior supported by your SDK, and clean shutdown.
Or skip the browser setup
If your MCP server needs website screenshots, ScreenshotNeo provides an MCP server for AI agents as well as a one-request screenshot API. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed; each response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers.
For a direct call, see the ScreenshotNeo documentation:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same endpoint supports PNG, JPEG, WebP, and PDF output plus options such as full-page capture, CSS selectors, device presets, custom JavaScript, waiting rules, request blocking, cookies, headers, geolocation, caching, signed links, async webhooks, bulk capture, and an OpenAPI specification. Its MCP tools are take_screenshot, get_page_info, and capture_pdf, so an MCP client can use those capabilities without you maintaining a browser process.
Best Value
There is a free allowance of 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots, and every feature is on every plan. Create a free ScreenshotNeo account.
Operational checklist
- Confirm the SDK generation and runtime requirement.
- Register a narrowly scoped tool with a strict input schema.
- Keep stdio stdout free of logs.
- Choose stdio locally or Streamable HTTP remotely.
- Use Inspector to list capabilities and call valid and invalid inputs.
- Add resources and prompts only when they solve a demonstrated need.
- Test the in-memory client path for Python logic where practical.
- Secure remote endpoints and outbound credentials according to the selected SDK’s guidance.
Frequently Asked Questions
Can one MCP server expose tools, resources, and prompts?
Yes. They are separate capability types, and you can add each independently as the use case requires.
Is HTTP+SSE the default transport for a new server?
No. Current guidance favors Streamable HTTP for remote servers; HTTP+SSE appears as backward-compatibility guidance in TypeScript v1 material.
Why does a stdio server look idle after launch?
It is waiting for protocol messages on stdin. Connect an MCP client or Inspector rather than typing ordinary text into the terminal.
Quick Recap
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.

