npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mcp-server-blueprint

v1.0.0

Published

Production-ready MCP server template with 10 example tools across 5 modules. Build custom AI-agent tooling for Claude, Cursor, and any MCP client in minutes.

Readme

MCP Server Starter Kit

A production-ready Model Context Protocol server template. Build custom tools for Claude, Cursor, Windsurf, and any MCP-compatible AI client — in minutes, not hours.

What You Get

  • 10 working tools across 5 modules, covering the patterns you'll use most
  • Modular architecture — each tool module is a separate file, easy to add or remove
  • TypeScript + Zod validation with strict types and runtime input checking
  • Shared response helpers (success() / failure()) for consistent output
  • Error handling patterns that produce structured, AI-readable error messages
  • Test suite using Node's built-in test runner (zero extra dependencies)
  • Docker support for containerized deployment
  • CLAUDE.md template to teach AI assistants about your project

Quick Start

# 1. Install dependencies
npm install

# 2. Build TypeScript
npm run build

# 3. Verify it compiles
npm start
# (Press Ctrl+C — the server runs on stdio, so it waits for input)

Connect to Claude Code

Add to .mcp.json in your project root:

{
  "mcpServers": {
    "my-mcp-server": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-server-starter/dist/index.js"],
      "env": {
        "MCP_SERVER_NAME": "my-mcp-server"
      }
    }
  }
}

Restart Claude Code. Your tools appear automatically.

Connect to Cursor

Settings > MCP Servers > Add:

{
  "my-mcp-server": {
    "command": "node",
    "args": ["/absolute/path/to/mcp-server-starter/dist/index.js"]
  }
}

Included Tools

Calculator (src/tools/calculator.ts)

| Tool | Description | |------|-------------| | calculate | Math operations: add, subtract, multiply, divide, percentage, power |

Pattern demonstrated: Pure synchronous logic, enum-based dispatch, input validation edge cases.

Web Fetcher (src/tools/web-fetcher.ts)

| Tool | Description | |------|-------------| | fetch_url | Fetch any URL — supports GET/POST/PUT/DELETE, custom headers, timeouts |

Pattern demonstrated: Async HTTP with fetch, AbortSignal timeouts, response truncation, JSON auto-detection.

File Manager (src/tools/file-manager.ts)

| Tool | Description | |------|-------------| | read_file | Read a file (auto-detects JSON for pretty output) | | write_file | Write or append to a file (creates parent dirs) | | list_files | List directory contents (flat or recursive) |

Pattern demonstrated: File I/O with path traversal prevention, security sandboxing via FILE_ROOT, recursive directory walking with limits.

Database Query (src/tools/database-query.ts)

| Tool | Description | |------|-------------| | db_list_tables | List all tables with row counts | | db_describe_table | Show column schema for a table | | db_query | Execute read-only SELECT queries | | db_execute | Execute write statements (INSERT/UPDATE/DELETE/CREATE) |

Pattern demonstrated: Embedded SQLite with better-sqlite3, parameterized queries (SQL injection prevention), read/write separation, graceful degradation when the optional dependency is missing.

Note: Database tools require better-sqlite3 (listed as an optional dependency). They return a helpful install message if it's missing — the server still works fine without it.

API Caller (src/tools/api-caller.ts)

| Tool | Description | |------|-------------| | api_list | List all configured API endpoints | | api_call | Call a pre-configured API by name |

Pattern demonstrated: Registry pattern (configure APIs once, call by name), environment-based configuration, auth header injection, URL construction.

Project Structure

mcp-server-starter/
  src/
    index.ts                 # Server entry point — imports and registers all tool modules
    types.ts                 # Shared types: ToolResponse, success(), failure()
    tools/
      calculator.ts          # Sync computation pattern
      web-fetcher.ts         # Async HTTP fetch pattern
      file-manager.ts        # File I/O with security pattern
      database-query.ts      # SQLite CRUD pattern
      api-caller.ts          # REST API registry pattern
  test/
    tools.test.ts            # Tests for all tools
  dist/                      # Compiled JavaScript (generated by npm run build)
  package.json
  tsconfig.json
  .env.example               # Environment variable template
  CLAUDE.md                  # Template for teaching AI about your project
  Dockerfile                 # Containerized deployment
  README.md                  # This file

How to Add Your Own Tool

Step 1: Create the tool file

Create src/tools/my-tool.ts:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { success, failure } from "../types.js";

export function registerMyTools(server: McpServer): void {
  server.tool(
    "my_tool_name",
    "Clear description of what this tool does (the AI reads this to decide when to call it)",
    {
      query: z.string().describe("What to search for"),
      limit: z.number().optional().default(10).describe("Max results to return"),
    },
    async ({ query, limit }) => {
      try {
        // Your logic here
        const results = await doSomething(query, limit);
        return success({ query, results, count: results.length });
      } catch (err) {
        return failure(
          `Operation failed: ${err instanceof Error ? err.message : String(err)}`,
          "Check your input and try again."
        );
      }
    }
  );
}

Step 2: Register it in index.ts

import { registerMyTools } from "./tools/my-tool.js";

// ... after other registrations:
registerMyTools(server);

Step 3: Build and test

npm run build
npm test

Tool Checklist

When building a new tool, ensure:

  • [ ] Tool name is unique and uses snake_case
  • [ ] Description is specific enough for the AI to know when to use it
  • [ ] Every Zod parameter has .describe("...") — the AI reads these
  • [ ] Errors return failure() with a helpful hint, never throw
  • [ ] Optional parameters have .default() values
  • [ ] Response uses success() for consistent formatting

Configuration

All configuration happens through environment variables. Copy .env.example to .env and customize:

cp .env.example .env

You can also pass env vars through the MCP client config:

{
  "mcpServers": {
    "my-server": {
      "command": "node",
      "args": ["dist/index.js"],
      "env": {
        "DATABASE_PATH": "./my-data.db",
        "FILE_ROOT": "/home/user/projects",
        "API_CONFIG": "[{\"name\":\"github\",\"base_url\":\"https://api.github.com\",\"headers\":{\"Authorization\":\"Bearer ghp_xxxx\"}}]"
      }
    }
  }
}

| Variable | Default | Description | |----------|---------|-------------| | MCP_SERVER_NAME | my-mcp-server | Server name shown in client UIs | | FILE_ROOT | Current working directory | Sandbox root for file operations | | DATABASE_PATH | ./data.db | SQLite database file path | | API_CONFIG | Public test APIs | JSON array of API endpoint configs |

Development Workflow

# Watch mode — auto-rebuilds on file changes
npm run dev

# In another terminal, restart your MCP client to pick up changes
# Claude Code: Cmd/Ctrl+Shift+P > "MCP: Restart"

# Run tests
npm test

# Clean build artifacts
npm run clean

Deployment Options

Local (most common)

Point your MCP client config at dist/index.js. This is the simplest and most common setup.

Docker

# Build the image
docker build -t my-mcp-server .

# Run with stdin (required for MCP stdio transport)
docker run -i my-mcp-server

# Run with environment variables and a data volume
docker run -i \
  -e API_CONFIG='[{"name":"github","base_url":"https://api.github.com","headers":{"Authorization":"Bearer ghp_xxxx"}}]' \
  -v ./data:/app/data \
  my-mcp-server

npm package

To publish as an installable package (users run via npx):

  1. Update name in package.json to your package name
  2. Set "files": ["dist/", "README.md"] (already configured)
  3. Run npm publish
  4. Users add to their MCP config: "command": "npx", "args": ["-y", "your-package-name"]

How MCP Works (60-Second Version)

  1. Your server runs as a subprocess spawned by the AI client
  2. Communication happens over stdio (stdin/stdout) using JSON-RPC 2.0
  3. At startup, the client calls tools/list to discover your tools
  4. Each tool has a name, description, and input schema (Zod)
  5. When the LLM decides to use a tool, the client sends a tools/call request
  6. Your handler runs, and returns structured data (JSON in a text content block)
  7. The LLM incorporates your response into its answer to the user

No HTTP servers, no WebSockets, no API keys. Just a subprocess that speaks JSON-RPC over stdin/stdout.

Requirements

  • Node.js 18+ (for built-in fetch and test runner)
  • TypeScript 5.4+
  • An MCP-compatible client (Claude Code, Cursor, Windsurf, or any MCP client)

License

MIT