# FrontMCP vs ViteMCP

> How FrontMCP and ViteMCP, the stateless successor to punkpeye's FastMCP, differ in protocol support, sessions, auth, testing and deployment, and when to choose each.

Source: https://frontmcp.dev/compare/vitemcp

ViteMCP is a TypeScript framework for stateless MCP servers, written for MCP 2026-07-28 by the author of [FastMCP for TypeScript](https://frontmcp.dev/compare/fastmcp-typescript), whose API and history it continues: one `ViteMCP` object holds the whole server, with `addTool()`, `addResource()`, `addPrompt()`, then `start()`. FrontMCP declares the same things with decorators and adds a container for shared services, sessions for older clients, agents and jobs, widgets, a test library and builds for several platforms. This page shows the same tool in both and compares them on the criteria of the [comparison overview](https://frontmcp.dev/compare).

This site documents FrontMCP, so read it knowing who wrote it. Every ViteMCP fact below comes from ViteMCP's own README, source and npm entry at **1.9.5**, checked on **2026-10-20**, and links to them. Every FrontMCP fact links to the page on this site that shows FrontMCP 1.10.5 doing it, or to [how this was checked](#how-this-was-checked).

## Quick answer

Choose ViteMCP when you want the one-object API of punkpeye's FastMCP on MCP 2026-07-28: one file, no build step, any Standard Schema library, and stateless servers on Node, Cloudflare Workers or Deno Deploy. Choose FrontMCP over ViteMCP when your clients on MCP 2025-11-25 or earlier need sessions, or when you want shared services, agents, jobs, widgets and a test library in the same framework.

---

## What ViteMCP is

[ViteMCP](https://github.com/vitemcp/server) is published on npm as [`@vitemcp/server`](https://www.npmjs.com/package/@vitemcp/server), which names Frank Fiegel as its author and, like `fastmcp`, has `punkpeye` as its maintainer. It's MIT-licensed ([LICENSE](https://github.com/vitemcp/server/blob/v1.9.5/LICENSE)). Its first release was 1.0.0 on 2026-08-06; 1.9.5, the version checked here, came out on 2026-10-17, after 33 versions ([npm](https://www.npmjs.com/package/@vitemcp/server?activeTab=versions)). Its documentation is the [README](https://github.com/vitemcp/server/blob/v1.9.5/README.md) and two guides in [`docs/`](https://github.com/vitemcp/server/tree/v1.9.5/docs), for OAuth and OpenAPI.

Its README calls it "a TypeScript framework for building stateless MCP servers", and says it "targets MCP revision **2026-07-28**, which made the protocol stateless" ([README](https://github.com/vitemcp/server/blob/v1.9.5/README.md?plain=1#L3-L13)). It "continues [FastMCP](https://github.com/punkpeye/fastmcp), whose commit history this repository carries" ([Acknowledgements](https://github.com/vitemcp/server/blob/v1.9.5/README.md#acknowledgements)): FastMCP's commits from December 2024 are in both repositories, and FastMCP's own README points to ViteMCP for 2026-07-28 ([FastMCP README](https://github.com/punkpeye/fastmcp/blob/v4.23.4/README.md?plain=1#L5-L7)). The API is FastMCP's, without what 2026-07-28 removed: sessions, `ping`, roots, sampling, `streamContent`, and an `elicit()` that waits for the answer ([Migrating from the session-based API](https://github.com/vitemcp/server/blob/v1.9.5/README.md#migrating-from-the-session-based-api)).

ViteMCP is [built on the official SDK](https://github.com/vitemcp/server/blob/v1.9.5/README.md#when-to-use-vitemcp-over-the-official-sdk), v2: its `package.json` asks for `@modelcontextprotocol/server` `^2.0.0`, which installed 2.3.1 on 2026-10-20, and for Node 24 or later ([`package.json`](https://github.com/vitemcp/server/blob/v1.9.5/package.json)). Its HTTP server is Hono ([Custom HTTP Routes](https://github.com/vitemcp/server/blob/v1.9.5/README.md#custom-http-routes)).

On 2026-10-20, ViteMCP had 16 GitHub stars ([GitHub API](https://api.github.com/repos/vitemcp/server)) and 509 npm downloads in the week of 2026-10-12 to 2026-10-18 ([npm API](https://api.npmjs.org/downloads/point/last-week/@vitemcp/server)). FrontMCP had 146 stars and 15,574 downloads of `@frontmcp/sdk` in the same week. ViteMCP is under three months old as a package, though the code it continues has been released since December 2024.

## The same tool in both

One tool, `add`, that takes two numbers and returns their sum, called with `{ "a": 2, "b": 3 }`.

### In ViteMCP

This is ViteMCP's [Quickstart](https://github.com/vitemcp/server/blob/v1.9.5/README.md#quickstart), as we ran it with `@vitemcp/server` 1.9.5, `zod` 4.6.7 and `tsx`, in a project with `"type": "module"`. It's FastMCP's Quickstart with `FastMCP` renamed:

```ts server.ts
import { ViteMCP } from "@vitemcp/server";
import { z } from "zod"; // Or any validation library that supports Standard Schema

const server = new ViteMCP({
  name: "My Server",
  version: "1.0.0",
});

server.addTool({
  name: "add",
  description: "Add two numbers",
  parameters: z.object({
    a: z.number(),
    b: z.number(),
  }),
  execute: async (args) => {
    return String(args.a + args.b);
  },
});

server.start({
  transportType: "stdio",
});
```

`npx @vitemcp/server dev server.ts --tool add --args '{"a":2,"b":3}'` ([Test with `mcp-cli`](https://github.com/vitemcp/server/blob/v1.9.5/README.md#test-with-mcp-cli)) ran it and called the tool:

```json
{
  "content": [
    {
      "type": "text",
      "text": "5"
    }
  ]
}
```

With `start({ transportType: "httpStream", httpStream: { port: 3206 } })` instead, the same server answered at `http://127.0.0.1:3206/mcp`. A client from `@modelcontextprotocol/client` 2.3.1 called `add` twice: with its default, which opens a 2025-era connection with `initialize`, and with `versionNegotiation: { mode: "auto" }`, which asks for 2026-07-28 first:

```text
legacy 2025-11-25 {"content":[{"type":"text","text":"5"}]}
modern 2026-07-28 {"_meta":{"io.modelcontextprotocol/serverInfo":{"name":"My Server","version":"1.0.0"}},"content":[{"type":"text","text":"5"}]}
```

The 2025-era call worked although the README says that the server "serves only 2026-07-28" and that clients which don't opt in "will be rejected", unless you pass `httpStream: { legacy: "stateless" }` ([README](https://github.com/vitemcp/server/blob/v1.9.5/README.md?plain=1#L1499-L1504)). In the source, `"stateless"` is the default when `legacy` isn't set ([`ViteMCP.ts`](https://github.com/vitemcp/server/blob/v1.9.5/src/ViteMCP.ts#L1524)), and the server answered `initialize` for every 2025-era revision without issuing an `Mcp-Session-Id`. With `legacy: "reject"`, those requests got `400` and `-32022` `Unsupported protocol version`.

### In FrontMCP

The same tool, in a one-app FrontMCP server. The Playground runs it and calls `add`; the **Tests** tab runs the checks below it.

```ts main.ts active
import { App, FrontMcp, Tool, ToolContext, z } from "@frontmcp/sdk";

@Tool({
  name: "add",
  description: "Add two numbers",
  inputSchema: { a: z.number(), b: z.number() },
})
export class Add extends ToolContext {
  async execute({ a, b }: { a: number; b: number }) {
    return { sum: a + b };
  }
}

@App({ id: "calc", name: "Calculator", tools: [Add] })
export class CalcApp {}

@FrontMcp({ info: { name: "calc", version: "1.0.0" }, apps: [CalcApp] })
export default class Server {}
```

```ts add.test.ts
import { test, expect } from "@frontmcp/testing";

test("adds two numbers", async ({ mcp }) => {
  const result = await mcp.tools.call("add", { a: 2, b: 3 });
  expect(result).toBeSuccessful();
  expect(result.json()).toEqual({ sum: 5 });
});

test("rejects a string where a number belongs", async ({ mcp }) => {
  const result = await mcp.tools.call("add", { a: "2", b: 3 });
  expect(result).toBeError("INVALID_INPUT");
});
```

The FrontMCP version is longer: a tool class, an app that lists it, and a server that lists the app. It returns an object, which arrives as `structuredContent` with a text copy ([Your First Tool](https://frontmcp.dev/learn/your-first-tool#returning-results-and-errors)). Both need Node 24 or later; FrontMCP also needs TypeScript's decorator settings ([Installation](https://frontmcp.dev/learn/installation)), and [`frontmcp dev`](https://frontmcp.dev/reference/cli#frontmcp-dev) runs it. `npm install @vitemcp/server` installed 57 packages on 2026-10-20, and `npm install @frontmcp/sdk` 126.

## Side by side

| | ViteMCP 1.9.5 | FrontMCP 1.10.5 |
| --- | --- | --- |
| MCP revisions served | 2024-11-05 to 2026-07-28 over HTTP and stdio in our run, with no session for the older four over HTTP; the README says it serves only 2026-07-28 ([README](https://github.com/vitemcp/server/blob/v1.9.5/README.md?plain=1#L1499-L1504)). `legacy: "reject"` serves 2026-07-28 only | 2024-11-05 to 2026-07-28 over Streamable HTTP and stdio, with a session for the older four ([Protocol versions](https://frontmcp.dev/reference/server/protocol-versions#revisions-over-stdio)) |
| Declaring a tool | `server.addTool({ name, parameters, execute })` ([Tools](https://github.com/vitemcp/server/blob/v1.9.5/README.md#tools)) | A [`@Tool`](https://frontmcp.dev/reference/sdk/tool) class, or the `tool()` function |
| Schemas | Standard Schema: Zod, ArkType, Valibot, or JSON Schema through `jsonSchemaAdapter`; `outputSchema`, checked before the result is sent ([Tools](https://github.com/vitemcp/server/blob/v1.9.5/README.md#tools), [Structured Tool Output](https://github.com/vitemcp/server/blob/v1.9.5/README.md#structured-tool-output)) | Zod 4; `outputSchema` checks every result ([Schemas Are Contracts](https://frontmcp.dev/learn/schemas-are-contracts), [Shaping Tool Results](https://frontmcp.dev/learn/shaping-tool-results)) |
| Shared services | No container documented. Tools get a per-request `context` with `auth`, logging and progress ([Migrating from the session-based API](https://github.com/vitemcp/server/blob/v1.9.5/README.md#migrating-from-the-session-based-api)) | [`@Provider`](https://frontmcp.dev/reference/sdk/provider) services, read with `this.get()`; [hooks](https://frontmcp.dev/reference/sdk/hooks) and [plugins](https://frontmcp.dev/reference/sdk/plugin) |
| Auth | An `authenticate(request)` hook for keys or tokens; an OAuth proxy with Google, GitHub, Azure and generic providers, client ID metadata documents and discovery endpoints; per-tool `canAccess` with `requireScopes` and `requireRole` ([Authentication](https://github.com/vitemcp/server/blob/v1.9.5/README.md#authentication), [OAuth guide](https://github.com/vitemcp/server/blob/v1.9.5/docs/oauth.md)) | Five modes: public, static keys, JWTs from your identity provider, and FrontMCP as the OAuth server, with its own sign-in page or an upstream provider's ([Auth modes](https://frontmcp.dev/reference/auth/modes)); per-entry rules ([Authorities](https://frontmcp.dev/reference/auth/authorities)); [client ID metadata documents](https://frontmcp.dev/reference/auth/cimd) |
| Asking the client for input | A tool returns `ctx.inputRequired()`, and the client sends the call again with the answers; sampling and roots were removed ([Multi round-trip requests](https://github.com/vitemcp/server/blob/v1.9.5/README.md#multi-round-trip-requests)) | [`this.elicit()`](https://frontmcp.dev/reference/sdk/elicit), which becomes `input_required` for 2026-07-28 clients; [`this.sample()` and `this.listRoots()`](https://frontmcp.dev/reference/sdk/contexts#thissample-and-thislistroots) for clients that offer them |
| Testing | `server.connect()` with the SDK's `InMemoryTransport`, `vitemcp dev`, `vitemcp inspect` ([Unit testing](https://github.com/vitemcp/server/blob/v1.9.5/README.md#unit-testing-with-an-in-memory-transport)) | `@frontmcp/testing` with MCP matchers, run by `frontmcp test` ([Testing](https://frontmcp.dev/reference/testing)) |
| Resources, prompts, completions | Resources and templates, prompts, completion of prompt arguments and template parameters ([Resources](https://github.com/vitemcp/server/blob/v1.9.5/README.md#resources), [Prompts](https://github.com/vitemcp/server/blob/v1.9.5/README.md#prompts), [completion](https://github.com/vitemcp/server/blob/v1.9.5/README.md#prompt-argument-auto-completion)) | Resources and templates, prompts, completion of template parameters ([`@Resource`](https://frontmcp.dev/reference/sdk/resource), [`@Prompt`](https://frontmcp.dev/reference/sdk/prompt), [completers](https://frontmcp.dev/reference/sdk/resource-template#completing-parameters)) |
| Agents, jobs, workflows, tasks | Not documented | [`@Agent`](https://frontmcp.dev/reference/sdk/agent), [`@Job`](https://frontmcp.dev/reference/sdk/job), [`@Workflow`](https://frontmcp.dev/reference/sdk/workflow); [background tasks](https://frontmcp.dev/reference/server/tasks) |
| Widgets (MCP Apps) | Not documented | A tool's `ui` option, for MCP Apps hosts and the OpenAI Apps SDK ([Tool UI](https://frontmcp.dev/reference/ui), [Hosts](https://frontmcp.dev/reference/ui/hosts)) |
| Transports | stdio; Streamable HTTP, stateless; in-memory ([HTTP Streaming](https://github.com/vitemcp/server/blob/v1.9.5/README.md#http-streaming)) | Streamable HTTP with or without sessions, the older HTTP+SSE, stdio, a Unix socket, in-memory ([`FrontMcpInstance`](https://frontmcp.dev/reference/sdk/frontmcp-instance), [`transport`](https://frontmcp.dev/reference/sdk/frontmcp#transport)) |
| Runtimes and deployment | Node 24+; `EdgeViteMCP` for Cloudflare Workers and Deno Deploy, over HTTP only and without built-in auth ([Edge Runtime Support](https://github.com/vitemcp/server/blob/v1.9.5/README.md#edge-runtime-support)) | Node 24+; `frontmcp build` targets for Node, Vercel, AWS Lambda, Cloudflare Workers and a browser module ([Production build](https://frontmcp.dev/reference/deployment/production-build)); a fetch handler for other runtimes ([`createFetchHandler()`](https://frontmcp.dev/reference/sdk/create-fetch-handler)) |
| CLI | `vitemcp dev` and `vitemcp inspect` ([Testing and Debugging](https://github.com/vitemcp/server/blob/v1.9.5/README.md#testing-and-debugging)), and `vitemcp validate` in `vitemcp --help`; no project generator | `frontmcp create`, `dev`, `build`, `test`, `inspector` ([CLI](https://frontmcp.dev/reference/cli)); an [Nx plugin](https://frontmcp.dev/reference/nx) |
| License | [MIT](https://github.com/vitemcp/server/blob/v1.9.5/LICENSE) | [Apache-2.0](https://github.com/agentfront/frontmcp/blob/main/LICENSE) |

## What each does that the other doesn't

What ViteMCP documents, or did in our run, and this site doesn't show for FrontMCP:

- **A choice of schema library.** Any [Standard Schema](https://github.com/vitemcp/server/blob/v1.9.5/README.md#tools) library works, ArkType and Valibot included, and so does plain JSON Schema. FrontMCP's pages use Zod 4 only.
- **Ready-made OAuth providers.** `GoogleProvider`, `GitHubProvider` and `AzureProvider` set up the [OAuth proxy](https://github.com/vitemcp/server/blob/v1.9.5/README.md#oauth-with-pre-configured-providers) for those sign-ins. FrontMCP's [`remote` mode](https://frontmcp.dev/reference/auth/remote) takes an OpenID Connect provider you configure; a plain OAuth provider such as GitHub, whose users have no `sub`, [can't be used](https://frontmcp.dev/reference/auth/remote#pointing-frontmcp-at-your-providers-endpoints).
- **Completion of prompt arguments**, including from an `enum` ([Prompt argument auto-completion](https://github.com/vitemcp/server/blob/v1.9.5/README.md#prompt-argument-auto-completion)). This site shows FrontMCP completing resource template parameters only.
- **HTTPS and mutual TLS** on the built-in server, from certificate files ([HTTPS Support](https://github.com/vitemcp/server/blob/v1.9.5/README.md#https-support)).
- **Deno Deploy** is named as a runtime. This site shows a [fetch handler](https://frontmcp.dev/reference/sdk/create-fetch-handler) for such runtimes but no deployment guide for it.
- **A smaller install**: 57 packages against FrontMCP's 126, on 2026-10-20.

What FrontMCP does that ViteMCP's README doesn't document:

- **Sessions for clients on 2025-11-25 and earlier**, which [Redis](https://frontmcp.dev/reference/deployment/redis) can share between instances. ViteMCP answers those clients without a session.
- **Requests from the server to the client**: [`this.sample()` and `this.listRoots()`](https://frontmcp.dev/reference/sdk/contexts#thissample-and-thislistroots) for clients that offer them. ViteMCP's migration table says to "call your LLM provider directly" instead of sampling, and replaces roots with nothing ([Migrating from the session-based API](https://github.com/vitemcp/server/blob/v1.9.5/README.md#migrating-from-the-session-based-api)).
- **A dependency container**: [providers](https://frontmcp.dev/learn/sharing-state-with-providers) with scopes, which tools, resources and prompts get with `this.get()`.
- **Agents, jobs, workflows and tasks**: [agents](https://frontmcp.dev/learn/your-first-agent) that run a model loop on the server, [jobs](https://frontmcp.dev/learn/your-first-job) that run in the background, [workflows](https://frontmcp.dev/learn/chaining-jobs-into-workflows) that chain them, and tools that run as [MCP tasks](https://frontmcp.dev/reference/server/tasks).
- **Widgets.** A tool's `ui` option renders an HTML or React widget for MCP Apps hosts and the OpenAI Apps SDK ([Your First Widget](https://frontmcp.dev/learn/your-first-widget)).
- **Plugins** for caching, memory, approval, feature flags and CodeCall ([Plugins and adapters](https://frontmcp.dev/reference/plugins)).
- **Sign-in without an upstream provider**: in `local` mode FrontMCP is the OAuth server and serves the sign-in page, and you check the user in `authenticate` ([Local auth](https://frontmcp.dev/reference/auth/local#checking-users-yourself)). ViteMCP's OAuth proxy signs users in through a provider.
- **Project scaffolding and platform builds**: `frontmcp create`, and `frontmcp build` for Vercel, AWS Lambda and Cloudflare Workers ([Deploying Your Server](https://frontmcp.dev/learn/deploying-your-server)).
- **A test library** with MCP matchers and fixtures ([Testing Your Server](https://frontmcp.dev/learn/testing-your-server)).

Both import tools from an OpenAPI spec: ViteMCP's [`fromOpenAPI()`](https://github.com/vitemcp/server/blob/v1.9.5/README.md#generating-a-server-from-openapi) and FrontMCP's [OpenAPI adapter](https://frontmcp.dev/reference/adapters/openapi). Both accept clients that identify themselves with a [client ID metadata document](https://github.com/vitemcp/server/blob/v1.9.5/README.md#client-id-metadata-documents) ([FrontMCP](https://frontmcp.dev/reference/auth/cimd)).

## When to choose ViteMCP

- You use FastMCP for TypeScript and want MCP 2026-07-28: the API is the same, and the README has a [migration table](https://github.com/vitemcp/server/blob/v1.9.5/README.md#migrating-from-the-session-based-api) for what changed.
- You want the smallest setup that works: one file, no decorators, no build, run with `tsx`, and 57 packages installed.
- Every request can stand on its own, and you deploy where that matters: serverless platforms, Cloudflare Workers or Deno Deploy.
- You want ArkType, Valibot or plain JSON Schema rather than Zod, or you sign users in with Google, GitHub or Azure and want the provider preset.

## When to choose FrontMCP

- Your clients use MCP 2025-11-25 or earlier and need a session: a server that asks them for sampling or roots, or several instances that share sessions.
- The server is growing past a handful of tools, and you want shared services, several apps, plugins and hooks to organise it ([Structuring a Server](https://frontmcp.dev/learn/structuring-a-server)).
- You want agents, background jobs, workflows, tasks or widgets from the same framework.
- You want tests written against your server with a dedicated library, or a build for Vercel, AWS Lambda or Cloudflare Workers.
- You want the more widely used of the two today: in the week of 2026-10-12 to 2026-10-18, npm counted 15,574 downloads of `@frontmcp/sdk` and 509 of `@vitemcp/server`.

## How this was checked

On 2026-10-20 we installed `@vitemcp/server` 1.9.5, with Node 24.18.1 and npm 11.16.0, ran the Quickstart above over stdio and Streamable HTTP, and called `add`. We then sent each server an `initialize` request for every MCP revision from 2024-11-05 to 2025-11-25, and the 2026-07-28 `server/discover` and `tools/call` requests, with the `MCP-Protocol-Version: 2026-07-28` header and the revision in `_meta`. Over stdio and over HTTP, all five answered and returned `5`; over HTTP the 2025-era `initialize` answers carried no `Mcp-Session-Id`, and `server/discover` listed only `2026-07-28` in `supportedVersions`. With `legacy: "reject"`, the four older revisions got `400` and `-32022`. We didn't deploy `EdgeViteMCP` to Cloudflare Workers or Deno Deploy.

FrontMCP serves all five revisions over Streamable HTTP and stdio. Its stdio router returns discovery and `resultType` results for 2026-07-28, and keeps `initialize` sessions for older clients. Changed in 1.10.5: before, `server/discover` over stdio returned `-32601` and a 2026-07-28 call received an older-revision result. The [overview](https://frontmcp.dev/compare#how-this-was-checked) describes the method for every library.
