Getting Started: Build a Model Context Protocol Server

Build a lightweight MCP server in JavaScript to expose Hacker News tools to LLMs using Anthropic’s open Model Context Protocol. Learn how to integrate, test, and extend AI capabilities with minimal boilerplate.

Savita Bharti

a month ago

getting-started-build-a-model-context-protocol-server

Why MCP Matters

Integrating LLMs into real products is still messy. Developers often write custom code to connect models to APIs or databases, but that code isn’t reusable or scalable.

The Model Context Protocol (MCP) is an open standard by Anthropic designed to fix that. It acts as a unified interface for exposing tools, data, and prompts to LLMs — a kind of “universal adapter” for AI integrations.

With MCP, instead of reinventing the wheel every time, devs can build once and reuse across clients like Claude Desktop, Cursor, and Windsurf.

MCP: Core Concepts

  • Clients: Connect the model (e.g., Claude) to an MCP server. Handle discovery, requests, and security.

  • Servers: Expose structured tools and data to models. Communicate using JSON-RPC 2.0 via stdio or SSE.

  • Key Types:

    • Tools: Functions the model can call

    • Resources: External data like APIs or files

    • Prompts: Predefined templates for consistent behavior

Demo: Create an MCP Server for Hacker News

Goal:

Expose two tools:

  1. list-top-stories – get top 10 Hacker News posts

  2. story-details – fetch details about a selected post

Step 1: Setup

bash

git clone git@github.com:kenzic/mcp-hacker-news-demo.git cd mcp-hacker-news-demo git checkout -b origin/demo demo npm install

Project has:

  • index.js: where you write the server logic

  • hacker-client.js: a prebuilt client to access Hacker News API

Step 2: Create the Server

js

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; const server = new McpServer( { name: "Hacker News", version: "1.0.0" }, { capabilities: { logging: {} } } );

Step 3: Add Tools

1. list-top-stories Tool

js

server.tool("list-top-stories", {}, async () => { const topStories = await client.listTopStories(); const formattedTopStories = formatTopStories(topStories); return { content: [{ type: "text", text: formattedTopStories }], }; });

2. story-details Tool

js

server.tool("story-details", { id: z.number() }, async ({ id }) => { const story = await client.getStoryDetails(id); const formattedStory = formatStoryDetail(story); return { content: [{ type: "text", text: formattedStory }], }; });

Step 4: Connect via stdio

js

import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; const transport = new StdioServerTransport(); await server.connect(transport);

Step 5: Connect to Claude Desktop

  1. Go to Settings → Developer → Edit Config

  2. Add:

json

{ "mcpServers": { "hackernews": { "command": "node", "args": ["/path-to-folder/mcp-hacker-news-demo/index.js"] } } }

  1. Restart Claude and run:
    “tell me about the top stories on hacker news.”

Debugging

Logging

Use:

js

server.server.sendLoggingMessage({ level: "info", data: "Your log message here", });

Claude saves logs here:

bash

tail -n 20 -F ~/Library/Logs/Claude/mcp-server-hackernews.log

MCP Inspector

Test your MCP server using:

bash

npx @modelcontextprotocol/inspector node index.js

Next Steps

  • Add tools for Ask HN and Polls

  • Make list-top-stories support custom story counts

  • Explore Resources and Prompts

Final Thoughts

MCP provides a clean, reusable way to expose structured tools and data to LLMs — no more duct-taped APIs or hard-coded context. If you're building serious AI features, this is a standard worth learning early.