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.

You can build the MCP server a chat host connects to with Node.js, the v2 TypeScript SDK package @modelcontextprotocol/server, and the stdio transport. The server exposes capabilities—such as tools—that a compatible AI host can call; MCP does not, by itself, provide a chat interface, a model, or a complete conversation manager. The example below registers a small tool, runs the server locally, and shows how to verify it. It targets the SDK v2 documentation’s 2026-07-28 specification revision and Node.js 20 or later.

What you are building

The Model Context Protocol (MCP) connects AI applications to systems that provide data and tools. In this pattern, the chat host is the MCP client: it starts or connects to your server, discovers its capabilities, and makes them available to the model. Your server implements those capabilities and returns results. The host remains responsible for the chat UI and the model interaction.

This tutorial builds a local stdio server with one callable tool. The tool accepts a place name and returns a short message. It is deliberately a simple example of the request-and-response shape, not a live weather or geocoding integration. Add a real data source only when you can define its coverage, credentials, error handling, and user-facing limitations.

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

The current official TypeScript SDK documentation identifies v2 as its stable release line for the 2026-07-28 MCP specification. For new examples, use the v2 package, @modelcontextprotocol/server; do not mix its imports with the older v1 monolithic package, @modelcontextprotocol/sdk. The SDK supports Node.js, Bun, and Deno, but the steps here use Node.js.

Choose local stdio or a remote endpoint

Integration When it fits What changes
Local process with stdio A desktop or development host launches your server as a local process. The host starts the command; MCP requests arrive on standard input and responses leave on standard output.
Hosted HTTP endpoint You want to host an endpoint that multiple clients can connect to. You must use the current v2 HTTP serving approach and account for deployment and access control.

For a first implementation, stdio avoids the extra work of exposing and deploying a network service. If you need remote access, follow the SDK’s current v2 serving and migration documentation rather than copying v1 transport examples. The v2 migration guide identifies createMcpHandler as an HTTP entry point; the v2 API also documents a Node-compatible Streamable HTTP transport.

Set up the Node.js project

  1. Install Node.js 20 or later, then create a project directory and initialize npm:

    mkdir mcp-node-chat-server
    cd mcp-node-chat-server
    npm init -y
  2. Set the project to use ES modules. Add "type": "module" to the top level of package.json, preserving the other fields. For example:

    Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
    {
      "name": "mcp-node-chat-server",
      "version": "1.0.0",
      "type": "module",
      "scripts": {
        "start": "tsx src/index.ts"
      }
    }
  3. Install the v2 server package and the packages used by the example:

    npm install @modelcontextprotocol/server zod
    npm install --save-dev tsx
  4. Create the source file:

    mkdir src

    Save the server code in src/index.ts.

The SDK package ships as ES modules only, which is why the project’s module setting matters. In TypeScript 6 projects, the package reference notes that @types/* packages are no longer auto-included; depending on your configuration, you may need "types": ["node"] in tsconfig.json because declarations refer to Buffer. This is a TypeScript setup consideration, not a requirement to add that setting to every Node.js project.

Register a tool and serve it over stdio

A tool is a callable action the host can expose to a model. The SDK’s registerTool(name, config, handler) pattern associates a name and input schema with a handler; the SDK validates the call against the schema before the handler runs. The following example uses the v2 server package and keeps its output intentionally simple:

import { McpServer, serveStdio } from "@modelcontextprotocol/server";
import { z } from "zod";

function createServer() {
  const server = new McpServer({
    name: "place-message-server",
    version: "1.0.0",
  });

  server.registerTool(
    "place_message",
    {
      title: "Create a place message",
      description: "Return a short message about a place name.",
      inputSchema: {
        place: z.string().min(1).describe("A place name"),
      },
    },
    async ({ place }) => ({
      content: [
        {
          type: "text",
          text: `You asked about ${place.trim()}. Connect this tool to a trusted data source to return live information.`,
        },
      ],
    }),
  );

  return server;
}

await serveStdio(createServer);

The server factory creates the server and registers one capability; serveStdio owns the local protocol connection. Replace the example handler’s message with your application logic, but keep validation at the boundary and return a useful result the host can pass back to the model. A tool description should say what the action actually does so a host can present it accurately.

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

Keep standard output clean. Stdio uses stdout as the JSON-RPC protocol channel. The official SDK guide warns: “stdout is the protocol channel. Log with console.error — one console.log corrupts the JSON-RPC stream.” Send diagnostics to console.error, a logger configured for stderr, or another appropriate diagnostic channel. Do not print banners, debug lines, or startup messages with console.log.

Run and verify the server

  1. Start the process from the project directory:

    npx tsx src/index.ts

    With stdio transport, this process is intended to wait for requests from a client. Seeing no human-readable chat window is expected: the server is not the chat application.

  2. In a second terminal, launch the MCP Inspector using the server command:

    npx @modelcontextprotocol/inspector npx tsx src/index.ts
  3. Connect in the Inspector UI, open Tools, select place_message, provide a non-empty place value such as Reykjavik, and run it. You should see the text returned by the handler.

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

This is the verification flow shown in the official getting-started guide; it is a way to inspect tool discovery and invocation, not a claim that the example connects to a real weather or place database. If you add a live integration, test successful results, invalid input, upstream errors, and timeouts with the same client.

Expand the server without blurring its job

MCP servers can expose tools, resources, and prompts. Tools represent actions a host can ask the server to perform. Resources and prompts are other capability types; implement them only when your use case needs them, and use the current v2 server documentation for their exact APIs. Older v1 pages may show signatures that should not be assumed to work unchanged with v2.

Design tools around bounded actions

  • Use a narrow input schema. Require the fields your handler needs, constrain formats and ranges where appropriate, and reject empty or malformed input before calling an external service.
  • Describe effects honestly. State whether a tool reads data, changes state, or may trigger an external action. Do not imply that a demo response is live data.
  • Return useful failures. Handle expected upstream failures in the handler so the host receives an understandable result rather than an opaque process crash.
  • Keep secrets out of the schema and logs. Supply credentials through your runtime’s configuration and avoid returning them in tool content or diagnostics.

Keep the host-server boundary clear

A chat host decides which tools to make available and how its model uses their results. Your server should implement and document capabilities, not assume a particular host’s setup screen or conversation behavior. Configuration and launch instructions vary by host; check that host’s current MCP client documentation before distributing a connection recipe.

Move from local to remote serving carefully

A local stdio process and a hosted HTTP server solve different connection problems; neither is inherently faster, cheaper, or more secure in every deployment. For remote use, select the current v2 HTTP serving pattern and verify that your chosen client supports it. Older v1 documentation describes Streamable HTTP as the modern remote transport for that SDK version and HTTP+SSE as a backwards-compatibility option. Treat that guidance as version-specific, not as a substitute for v2 compatibility requirements.

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

Network exposure changes the threat model. Older v1 server guidance discusses DNS rebinding risks for localhost servers, host-header validation, and a protected Express helper; it also notes that automatic protection is not enabled when binding to all interfaces. Those are useful reasons to review local and remote exposure, but do not assume a v1 helper is the v2 solution. Check the current v2 deployment and serving guidance for the implementation you use.

  • Expose only the endpoint and capabilities your integration needs.
  • Decide how clients are authorized before making a server reachable beyond the local machine.
  • Review host/origin validation, network binding, secrets handling, and logging for the selected transport.
  • Test behavior from the client’s point of view, including disconnects and failed requests.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting common problems

Symptom Likely cause What to check
The host reports that it cannot start or parse the server. A runtime or module mismatch, an incorrect launch path, or startup output contaminating stdio. Confirm Node.js 20 or later, use the v2 package in an ES module project, check the command’s working directory, and remove stdout logging.
The process starts but no tools appear. The client may not have connected to the intended process, or the server did not register the expected tool. Use Inspector with the same launch command and confirm the tool name and schema appear under Tools.
A tool call is rejected before the handler runs. The supplied input does not match the schema. Check required fields, value types, and constraints such as the non-empty string requirement in this example.
TypeScript reports a missing Node type such as Buffer. The project’s TypeScript 6 type configuration may not include Node declarations. Install the appropriate Node type package if needed and review whether types: ["node"] belongs in your tsconfig.json.
A remote client cannot connect. The server may still be configured for stdio, or the selected HTTP transport may not match the client or current SDK setup. Use the v2 HTTP serving documentation, confirm the endpoint is reachable, and check client transport compatibility.

Or skip the browser setup

If the MCP tool you want is a website screenshot, you can call ScreenshotNeo’s API instead of building and maintaining a browser-capture workflow. It returns a PNG, JPEG, WebP, or PDF from one GET request. Here is a runnable cURL example; create an API key and follow the ScreenshotNeo API documentation for available parameters.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

ScreenshotNeo accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents using Claude, Cursor, or another MCP client. The free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots.

Sign up for 1,000 free screenshots a month with no card.

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

Practical next steps

Start with one bounded capability, test it through Inspector, and connect it to a host only after its inputs, results, and failure behavior are clear. Keep the version boundary explicit: this example targets the v2 package and local stdio flow, while a shared remote endpoint requires the corresponding current v2 HTTP serving design.

Frequently Asked Questions

Does an MCP server include a chat UI or AI model?

No. The MCP server provides capabilities to a compatible host; the host supplies the model and chat experience.

Can this stdio example be used directly as a hosted endpoint?

No. It serves a local stdio connection. Remote clients require an HTTP serving implementation.

Which package should a new TypeScript server use?

The current v2 package is @modelcontextprotocol/server; the older v1 monolithic package is @modelcontextprotocol/sdk.

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

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.