Use @usefractal/frac/server
Use @usefractal/frac/server
Section titled “Use @usefractal/frac/server”This guide shows you how to add @usefractal/frac/server to an existing MCP server to enable view support with full TypeScript type inference.
Prerequisites
Section titled “Prerequisites”You should already have:
- A working MCP server using the official TypeScript MCP SDK
- Node.js 24+
Install frac
Section titled “Install frac”pnpm add @usefractal/fracUpdate your server
Section titled “Update your server”Replace your McpServer import with frac’s enhanced version:
// Beforeimport { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
// Afterimport { McpServer } from "@usefractal/frac/server";Keep your existing dependency to @modelcontextprotocol/sdk in your project, frac does not replaces it, but depends on it.
Your existing tools, resources, and prompts will continue to work as before. With @usefractal/frac/server, registerTool provides an optional view field so you can bind a tool to a React view in a single call.
Project structure
Section titled “Project structure”your-project/├── src/│ ├── server.ts # MCP server entry│ └── views/│ └── my-view.tsx # View component├── vite.config.ts # Vite + frac plugin├── tsconfig.json└── package.jsonBy default views are located in src/views/. This is configurable via the viewsDir option in the provided Vite plugin.
View naming convention
Section titled “View naming convention”A view’s file name must match view.component in registerTool. See registerTool.
Set up Vite
Section titled “Set up Vite”Install the web dependencies and create vite.config.ts at the project root:
pnpm add react react-dompnpm add -D vite typescript @types/react @types/react-domimport { defineConfig } from "vite";import { frac } from "@usefractal/frac/vite";
export default defineConfig({ plugins: [frac()],});Make sure tsconfig.json includes the generated types:
{ "include": ["src", ".frac/**/*.d.ts"]}Create your first view
Section titled “Create your first view”Create src/views/my-view.tsx and export default a React component:
export default function MyView() { return ( <div> <h2>Hello from frac!</h2> <p>Your view is working!</p> </div> );}Register the view
Section titled “Register the view”In your server code, register the view with registerTool and view:
import { McpServer } from "@usefractal/frac/server";import { z } from "zod";
const server = new McpServer({ name: "my-app", version: "1.0" }, {}) .registerTool( { name: "my-view", description: "My first view", inputSchema: { message: z.string() }, view: { component: "my-view" }, // must match src/views/my-view.tsx }, async ({ message }) => { return { content: message || "Hello World" }; }, );Configure your dev server
Section titled “Configure your dev server”Update your server startup to serve the MCP endpoint. If you’re using Express:
import { McpServer } from "@usefractal/frac/server";import { z } from "zod";import express from "express";
const app = express();const server = new McpServer({ name: "my-app", version: "1.0" }, {}) .registerTool( { name: "my-view", inputSchema: { message: z.string() }, view: { component: "my-view" }, }, async ({ message }) => { return { content: message }; }, );
// Serve the MCP endpointapp.use("/mcp", server.handler());
// Start the serverapp.listen(3000, () => { console.log("Server running on http://localhost:3000");});Type Safety
Section titled “Type Safety”For full type inference and autocomplete, use method chaining and generateHelpers. See Type Safety for the complete setup.
Quick summary:
- Use method chaining when registering tools
- Export
type AppType = typeof server - Create a
helpers.tsfile withgenerateHelpers<AppType>() - Import typed hooks from your helper file