DEV Community

Cover image for How to Build an MCP Server in TypeScript
Shayan
Shayan

Posted on

How to Build an MCP Server in TypeScript

I've been working on UserJot, my SaaS for user feedback and roadmaps, and the next item on my sprint is adding MCP (Model Context Protocol) server support. I want to let users connect their UserJot data directly to Claude Desktop and other AI assistants.

UserJot Dashboard

My backend is built with Node.js and TypeScript, so I needed a TypeScript friendly way to create MCP servers. After exploring various options, I discovered FastMCP and it's exactly what I was looking for.

What is MCP

MCP (Model Context Protocol) is an open protocol that enables AI assistants like Claude to interact with external tools and data sources. It's basically a standardized way for AI to use your APIs. You can read more in the official docs.

Getting Started with FastMCP

The setup is simple. First, install the package:

npm install fastmcp 
Enter fullscreen mode Exit fullscreen mode

Then create your server with just a few lines of code:

import { FastMCP } from "fastmcp"; import { z } from "zod"; const server = new FastMCP({ 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", }); 
Enter fullscreen mode Exit fullscreen mode

That's it. You now have a working MCP server that Claude can use to add numbers.

Building a Real Tool

Here's a more practical example, a text search tool using Prisma. (Note: This is just an example. In production, you'd want to be extremely careful about what database access you expose through MCP. Consider read-only access, query whitelisting, or sandboxed environments.)

import { FastMCP } from "fastmcp"; import { z } from "zod"; import { PrismaClient } from "@prisma/client"; const prisma = new PrismaClient(); const server = new FastMCP({ name: "database-search-mcp", version: "1.0.0", }); server.addTool({ name: "searchPosts", description: "Search posts by title or content", parameters: z.object({ query: z.string().describe("Search term to look for"), limit: z.number().min(1).max(20).default(5), }), execute: async (args) => { const posts = await prisma.post.findMany({ where: { OR: [ { title: { contains: args.query, mode: 'insensitive' } }, { content: { contains: args.query, mode: 'insensitive' } } ] }, take: args.limit, orderBy: { updatedAt: 'desc' }, }); return JSON.stringify(posts, null, 2); }, }); server.start({ transportType: "stdio" }); 
Enter fullscreen mode Exit fullscreen mode

Testing Your Server

FastMCP includes a CLI for testing:

npx fastmcp dev your-server.ts 
Enter fullscreen mode Exit fullscreen mode

This launches an interactive terminal where you can test your tools before connecting them to Claude.

Connecting to Claude Desktop

Once your server is working, add it to Claude Desktop by editing your configuration file:

On macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

On Windows: %APPDATA%\Claude\claude_desktop_config.json

Add your server configuration:

{ "mcpServers": { "database-search": { "command": "node", "args": ["/path/to/your/server.js"], "env": { "DATABASE_URL": "postgresql://user:password@localhost:5432/mydb" } } } } 
Enter fullscreen mode Exit fullscreen mode

Restart Claude Desktop, and your tools will be available.

What I Love About FastMCP

After working with it, here's what stands out:

  • TypeScript-first: Proper types throughout
  • Flexible validation: Works with Zod, ArkType, Valibot, or any Standard Schema validator
  • Built-in features: Sessions, authentication, streaming, progress reporting
  • Great developer experience: Simple API, good docs, easy testing

The authentication support is particularly nice for SaaS products:

const server = new FastMCP({ name: "My Server", version: "1.0.0", authenticate: (request) => { const apiKey = request.headers["x-api-key"]; if (!isValidApiKey(apiKey)) { throw new Response(null, { status: 401 }); } return { userId: getUserIdFromApiKey(apiKey) }; }, }); 
Enter fullscreen mode Exit fullscreen mode

Next Steps

This is exactly what I needed for UserJot. My plan is to build MCP tools that let users:

  • Query their feedback database
  • Create and update roadmap items
  • Generate changelog entries
  • Analyze user sentiment and trends

The beauty of MCP is that once these tools exist, users can interact with their UserJot data naturally through Claude, creating powerful workflows I never imagined.

If you're building a TypeScript backend and need MCP support, FastMCP is the way to go. It takes the complexity out of the protocol and lets you focus on building useful tools.

Now, back to building. I've got some MCP servers to ship!


P.S. If you're building something and looking for a feedback platform, I'd love for you to give UserJot a try and let me know what you think!

Top comments (6)

Collapse
 
code42cate profile image
Jonas Scholz

Are you also going to offer a hosted mcp server? Kinda feels necessary for non technical users

Collapse
 
shayy profile image
Shayan

yeah for sure! this is just a demo but the actual MCP server will be hosted.

Collapse
 
code42cate profile image
Jonas Scholz

Interested in that as well, blog post pls!

Thread Thread
 
shayy profile image
Shayan

That's a good idea! I'll write about it after I release this feature.

Collapse
 
lemii_ profile image
Lemmi

wow this is really cool.

Collapse
 
shayy profile image
Shayan

Glad to hear!