# Packages and subpath exports

The SDK is published as nine npm packages. Most projects install exactly one of them.

## Start from one package

Everything in [Build your first server](https://ts.sdk.modelcontextprotocol.io/v2/get-started/first-server.md) came from a single install, `@modelcontextprotocol/server` — through two import paths.

```ts
import { McpServer } from '@modelcontextprotocol/server';
import { serveStdio } from '@modelcontextprotocol/server/stdio';
```

The first path is the package's root entry. The second is a **subpath export** — a separate entry point inside the same package, declared in its `exports` map.

## Pick the package for your side of the protocol

Install the package for the side of the protocol you are building.

```sh
npm install @modelcontextprotocol/server   # expose tools, resources, prompts
npm install @modelcontextprotocol/client   # connect to servers and call them
```

Those two are the starting point for almost everything; a process that plays both roles installs both. The full published set is nine packages:

- `@modelcontextprotocol/server` and `@modelcontextprotocol/client` — the two starting points, one per side.
- `@modelcontextprotocol/node`, `@modelcontextprotocol/express`, `@modelcontextprotocol/hono`, `@modelcontextprotocol/fastify` — optional adapters for serving over HTTP.
- `@modelcontextprotocol/core` — the raw Zod wire schemas.
- `@modelcontextprotocol/server-legacy` and `@modelcontextprotocol/codemod` — migration surfaces for v1 code.

A tenth package in the repository, `@modelcontextprotocol/core-internal`, is private: `server` and `client` bundle it at build time, so it never appears in your dependency tree.

## Keep Node-only code behind the `./stdio` subpath

`StdioClientTransport` spawns the server as a child process, so it is exported from `./stdio`, never from the root entry.

```ts
// Runs anywhere: browsers, Workers, Node.
import { Client } from '@modelcontextprotocol/client';
// Spawns a child process — Node-only, so it lives behind the subpath.
import { StdioClientTransport } from '@modelcontextprotocol/client/stdio';
```

The root entry of every package is **runtime-neutral**: its module graph never reaches `node:child_process` or any other Node builtin a browser or Cloudflare Workers bundler cannot resolve. Importing `./stdio` is the explicit opt-in to a process runtime. `@modelcontextprotocol/server/stdio` is the server-side counterpart and exports `serveStdio` and `StdioServerTransport`.

::: info Coming from v1?
v1's single `@modelcontextprotocol/sdk` package exposed deep file paths such as `@modelcontextprotocol/sdk/server/mcp.js`. The v2 packages declare an `exports` map, so only the subpaths each package names resolve — the codemod rewrites the imports for you.
:::

## Add a framework adapter when you serve over HTTP

`createMcpHandler` from `@modelcontextprotocol/server` already serves MCP over web-standard `Request` and `Response` objects. An adapter package wires that handler into a specific runtime or framework; install the adapter next to the framework it adapts.

```sh
npm install @modelcontextprotocol/express express
```

Four adapters exist: `@modelcontextprotocol/node` for Node's built-in `http` server, and one each for Express, Hono, and Fastify. They are thin layers over `createMcpHandler` and add no MCP behavior of their own.

[Serve over HTTP](https://ts.sdk.modelcontextprotocol.io/v2/serving/http.md) covers the handler itself; [Express](https://ts.sdk.modelcontextprotocol.io/v2/serving/express.md), [Hono](https://ts.sdk.modelcontextprotocol.io/v2/serving/hono.md), and [Fastify](https://ts.sdk.modelcontextprotocol.io/v2/serving/fastify.md) each have a recipe.

## Reach for `core` only to validate raw wire JSON

`@modelcontextprotocol/core` exports the Zod schema constants the SDK validates protocol payloads against, for code that handles raw JSON-RPC payloads itself — gateways, proxies, log pipelines. Neither `server` nor `client` exports a Zod schema, and the matching TypeScript types ship with both, so if you only call `registerTool` and `callTool` you never import it directly — it arrives transitively, since `server` and `client` resolve their shared schema graph from it at runtime. [Wire schemas](https://ts.sdk.modelcontextprotocol.io/v2/advanced/wire-schemas.md) is the how-to.

## Leave `server-legacy` and `codemod` to the migration guide

`@modelcontextprotocol/server-legacy` is a frozen copy of v1's server-side SSE transport and OAuth Authorization Server helpers, published so a v1 deployment can move to v2 without replacing everything at once. `@modelcontextprotocol/codemod` is the command-line tool that rewrites v1 imports and call sites to their v2 forms. Neither belongs in a new project — the [upgrade guide](https://ts.sdk.modelcontextprotocol.io/v2/migration/upgrade-to-v2.md) covers both.

## Recap

- `@modelcontextprotocol/server` and `@modelcontextprotocol/client` are the two packages you install, one per side of the protocol.
- Package root entries are runtime-neutral; code that spawns processes lives at the `./stdio` subpath and only enters your bundle when you import it.
- The HTTP adapters — `node`, `express`, `hono`, `fastify` — are optional thin layers over `createMcpHandler`; install at most one.
- `@modelcontextprotocol/core` exports only Zod schema constants, for code that validates raw wire JSON itself.
- `@modelcontextprotocol/server-legacy` and `@modelcontextprotocol/codemod` exist for migration from v1, not for new projects.
