← Back to Blog

Build a Production-Ready MCP Server with TypeScript: A Complete Guide

May 1, 2026 By 155143783 MCP, TypeScript, AI

The Model Context Protocol (MCP) has emerged as a game-changer in the AI ecosystem, enabling developers to build servers that expose data and functionality to Large Language Models in a standardized way. In this comprehensive guide, we'll walk through building a production-ready MCP server with TypeScript, implementing secure HTTP transport for public exposure, and deploying it to Smithery and mcp.so.

What is MCP and Why Does It Matter in 2026?

The Model Context Protocol is rapidly becoming the de facto standard for AI-tool integration. With the explosion of AI agents and copilots in 2026, the need for standardized, secure ways to connect LLMs to external tools and data sources has never been greater.

MCP servers allow you to:

Unlike traditional REST APIs, MCP is specifically designed for AI interactions, providing built-in support for structured tool calling, context management, and capability negotiation between clients and servers.

Setting Up Your TypeScript MCP Server

Prerequisites

Installation

npm init -y
npm install @modelcontextprotocol/sdk zod express cors
npm install -D typescript @types/node @types/express @types/cors tsx

Project Structure

mcp-data-api/
├── src/
│   ├── index.ts          # Main entry point
│   ├── server.ts         # MCP server implementation
│   ├── resources/        # Resource handlers
│   ├── tools/            # Tool implementations
│   └── transports/       # Transport configurations
├── tsconfig.json
├── package.json
└── Dockerfile

Implementing StreamableHTTPServerTransport

The StreamableHTTPServerTransport is essential for exposing your MCP server publicly. Unlike stdio (which requires local process communication), HTTP transport allows remote AI clients to connect.

Why Streamable HTTP?

  1. Remote Access: Clients can connect from anywhere
  2. Scalability: Works with load balancers and container orchestration
  3. Standard Integration: Uses familiar HTTP/HTTPS protocols

DNS Rebinding Protection

When exposing MCP servers publicly, DNS rebinding attacks are a significant threat. Here's how to protect your server:

Origin Validation Middleware

app.use((req, res, next) => {
  const allowedOrigins = [
    "https://your-production-domain.com",
    "https://smithery.ai",
    "https://mcp.so"
  ];
  
  const origin = req.headers.origin;
  if (origin && !allowedOrigins.includes(origin)) {
    return res.status(403).json({ error: "Origin not allowed" });
  }
  
  next();
});

Secret Token Validation

const API_SECRET = process.env.MCP_API_SECRET;

app.use("/mcp", (req, res, next) => {
  const secret = req.headers["x-mcp-secret"];
  
  if (!secret || secret !== API_SECRET) {
    return res.status(401).json({ error: "Invalid or missing secret" });
  }
  
  next();
});

Deployment to Smithery

Smithery provides an excellent platform for hosting MCP servers with built-in discovery, OAuth support, and client configuration management.

# Install Smithery CLI
npm install -g @smithery/cli

# Authenticate
smithery login

# Publish your server
smithery mcp publish "https://api.your-domain.com/mcp" -n @your-org/mcp-data-api

Best Practices for Production

  1. Health Checks: Implement /health endpoint for container orchestration
  2. Rate Limiting: Use express-rate-limit to prevent abuse
  3. Logging: Implement structured logging with request IDs
  4. Metrics: Add Prometheus metrics for monitoring
  5. Graceful Shutdown: Handle SIGTERM properly
  6. CORS Configuration: Be explicit about allowed origins

Conclusion

Building a production-ready MCP server with TypeScript is straightforward with the official SDK. The key considerations for public exposure are: