Skip to main content
In a few minutes you’ll have an MCP server with a tool, a resource, and a prompt — running locally and answering calls from a client.

Install

npm install @prefecthq/fastmcp-ts
npm install zod

Create a server

A FastMCP server turns plain TypeScript functions into MCP components. Input schemas are inferred from any Standard Schema-compatible library (Zod, Valibot, ArkType, …) and your handler’s argument types follow automatically. Create server.ts:
server.ts
import { FastMCP } from '@prefecthq/fastmcp-ts/server'
import { z } from 'zod'

const server = new FastMCP({ name: 'my-server', version: '1.0.0' })

// A tool: callable by the LLM, arguments validated against the schema
server.tool(
  {
    name: 'add',
    description: 'Add two numbers',
    input: z.object({ a: z.number(), b: z.number() }),
  },
  ({ a, b }) => a + b
)

// A static resource: data the client can read by URI
server.resource(
  { uri: 'config://settings', description: 'App configuration' },
  () => JSON.stringify({ theme: 'dark', lang: 'en' })
)

// A templated resource: `{id}` is extracted and passed to the handler
server.resource(
  { uri: 'user://{id}', description: 'User by ID' },
  ({ id }) => `User #${id}`
)

// A prompt: a reusable message template with arguments
server.prompt(
  {
    name: 'review_code',
    description: 'Review code for quality and correctness',
    arguments: [
      { name: 'code', required: true },
      { name: 'language', required: false },
    ],
  },
  ({ code, language }) =>
    `Review this ${language ?? 'code'} for quality and correctness:\n\n${code}`
)

await server.run()                              // stdio (default)
// await server.run({ transport: 'http', port: 3000 })

Run it

Use the bundled CLI to start the server. It runs TypeScript directly — no build step:
# stdio transport (what editors and desktop clients use)
npx fastmcp run server.ts

# or HTTP, for network access
npx fastmcp run server.ts --transport http --port 3000
To poke at it interactively, open the MCP Inspector UI with file-watch reload:
npx fastmcp dev inspector server.ts
Or inspect its components straight from the terminal:
npx fastmcp inspect --file server.ts
npx fastmcp call add --file server.ts a=1 b=2

Call it from a client

With the server running over HTTP, connect with the Client class:
client.ts
import { Client } from '@prefecthq/fastmcp-ts/client'

await using client = await Client.connect('http://localhost:3000')

const tools = await client.listTools()
const result = await client.callTool('add', { a: 1, b: 2 })
const config = await client.readResource('config://settings')
const review = await client.getPrompt('review_code', { code: 'const x = 1' })

// client closed automatically on scope exit (`await using`)

Where to next

Tools

Schemas, return-value conversion, and the full tool config surface.

Resources

Static resources, URI templates, and subscriptions.

Clients

Lifecycle, error handling, and multi-server connections.

CLI

Every fastmcp command, including editor installs.