Back to Home

Build MCP Servers on Your Favorite Stack

Building MCP servers seems simple at first, but you'll hit obscure issues when working with modern frameworks like Hono and runtimes like Bun. Here's the solution.

3 min read
mcpmodel-context-protocolmcp-handler
John Ryan Cottam
John Ryan Cottam
Build MCP Servers on Your Favorite Stack

The Long and Short of it

Building MCP servers seems simple at first, but you'll hit obscure issues when working with modern frameworks like Hono and runtimes like Bun. Vercel's MCP adapter solves this—it handles all the protocol complexity and runtime differences so you can build once and deploy anywhere.

What is Model Context Protocol (MCP)?

Model Context Protocol (MCP) is an open-source protocol created by Anthropic. It defines how AI agents communicate with external tools and services, and is quickly becoming the standard for AI-tool integration.

Think of it as a common language between AI and your APIs. MCP specifies the message format and rules for this communication, enabling AI agents to access databases, file systems, web APIs, or your custom services.

AI agents choose which tools to use based on the task. Need to query a database? The agent calls your database tool. Need to search the web? It uses your search tool. MCP makes this seamless.

Vercel's MCP Handler

Vercel's MCP Adapter makes building MCP servers straightforward. It works with any web framework—Next.js, Nuxt, Hono, Express, you name it. Define your tools with a simple API, and AI clients like Claude Desktop can connect instantly.

What the Adapter Actually Does

The adapter handles the messy details of MCP server implementation. It abstracts away the protocol handshakes, message serialization, transport negotiation, and error handling that you'd otherwise need to implement yourself.

More importantly, it bridges the gap between different JavaScript runtimes. Bun and Node.js handle HTTP requests, streams, and async operations differently under the hood. The adapter normalizes these differences, letting you write your MCP server once and run it anywhere. This runtime interoperability is critical for deploying the same code to different platforms without modification.

createMcpHandler Handles the Heavy Lifting

The magic is in the createMcpHandler helper function. It transforms your tool definitions into a fully-compliant MCP server with just a few lines of code:

const handler = createMcpHandler(
  (server) => {
    server.tool(
      "createAsciiArt",
      "Create ASCII art from text using figlet",
      { text: z.string() },
      async ({ text }) => {
        const art = figlet.textSync(text);
        return {
          content: [{ type: "text", text: art }],
        };
      }
    );
  },
  {},
  { basePath: "/", maxDuration: 60 }
);

// Mount the handler
app.all("/mcp/*", async (c) => {
  return await handler(c.req.raw);
});

export default app;

Here's what's happening: createMcpHandler takes your tool definition (a simple async function), handles all the MCP protocol complexity behind the scenes, and returns a request handler that works with any web framework. You focus on defining what your tool does—createMcpHandler handles how it communicates with AI clients.

View the complete implementation →

That's it—a production-ready MCP server in under 20 lines. Deploy to Vercel, Cloudflare Workers, or containerize it for AWS, GCP, or Azure.

Testing and Iteration

Start with the MCP Protocol Inspector

Use the MCP Protocol Inspector during development. It's a web-based debugging tool for testing your server, inspecting tool calls, and validating responses:

npx @modelcontextprotocol/inspector

Note: npx allows you to run packages without installing them globally.

Connect to your server and test your tools directly. Try invoking createAsciiArt with "MCP rocks!":

MCP Protocol Inspector

Once verified, connect to Claude Desktop, Cursor, or other MCP clients.

Connect to an MCP Client (Claude Desktop, Cursor, etc.)

Add your server to your MCP client configuration:

mcp-client-config.json
{
  "mcpServers": {
    "remote-mcp-server": {
      "url": "http://your-mcp-server-url.com/mcp"
    }
  }
}

This configuration tells your MCP client where to find your server. The url should point to your deployed MCP handler endpoint.

Key Features

  • Framework-agnostic: Works with any HTTP framework
  • Streamable HTTP transport: Uses HTTP streaming for efficient communication
  • Type-safe: Define tool inputs with Zod schemas
  • Authorization built-in: Secure your tools with MCP's authentication spec
  • Deploy anywhere: Vercel, Docker, or traditional servers

Resources