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

hashnode-mcp

v1.0.1

Published

A comprehensive MCP server for the Hashnode GraphQL API with full TDD coverage

Readme

📝 Hashnode MCP Server

Supercharge your AI assistant with complete Hashnode integration

License: AGPL-3.0 TypeScript MCP TDD

A comprehensive Model Context Protocol server that exposes the complete Hashnode GraphQL API as MCP tools, enabling seamless integration between your Hashnode blog and MCP-compatible applications like Claude Desktop and Cline.

FeaturesInstallationAvailable ToolsConfigurationDevelopment


✨ Features

  • 📝 21 Comprehensive Tools - Complete Hashnode API coverage
  • 🔄 Hot-Swap Architecture - Automatic tool discovery with zero-config
  • 🎯 Type-Safe - Built with TypeScript strict mode and Zod validation
  • 📊 High Test Coverage - 95%+ coverage with TDD methodology
  • 🚀 Zero Dependencies - Minimal footprint, maximum performance
  • 🔌 Drop-in Integration - Works with Claude Desktop, Cline, and other MCP clients
  • ✍️ Full CRUD Operations - Read, write, update, and delete posts and drafts
  • 📅 Scheduling Support - Schedule and manage post publication times

🛠️ Available Tools

This MCP server provides 21 tools covering the full spectrum of Hashnode API operations:

📚 Publication Management

| Tool | Description | |------|-------------| | getPublicationByHost | Retrieve publication information by domain | | getPublicationPosts | Fetch posts from a publication with pagination |

📄 Post Operations

| Tool | Description | |------|-------------| | getPostBySlug | Get a specific post by its slug | | searchPosts | Search for posts within a publication |

👤 User Operations

| Tool | Description | |------|-------------| | getUserByUsername | Retrieve user profile information | | getMe | Get current authenticated user information | | getMyDrafts | Retrieve drafts for the authenticated user | | getMyPosts | Retrieve published posts for the authenticated user |

✍️ Draft & Publishing Operations (Requires Auth)

| Tool | Description | |------|-------------| | createDraft | Create a new draft for a publication | | updateDraft | Update an existing draft | | publishDraft | Publish a draft to make it a live post | | createPost | Create and publish a post directly | | updatePost | Update an existing published post | | removePost | Remove/delete a published post | | restorePost | Restore a previously removed post |

📅 Scheduling Operations (Requires Auth)

| Tool | Description | |------|-------------| | scheduleDraft | Schedule a draft for future publication | | rescheduleDraft | Reschedule a previously scheduled draft | | cancelScheduledDraft | Cancel a scheduled draft |

📖 Series Operations

| Tool | Description | |------|-------------| | getSeriesBySlug | Get series information by slug | | getSeriesPosts | Retrieve posts from a series with pagination | | addPostToSeries | Add a post to an existing series |

📑 Static Page Operations

| Tool | Description | |------|-------------| | getStaticPageBySlug | Get a static page by its slug |

📦 Installation

Quick Start with Claude Desktop

Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "hashnode": {
      "command": "npx",
      "args": ["-y", "hashnode-mcp"]
    }
  }
}

Global Installation

npm install -g hashnode-mcp

For Cline (VS Code)

Add to your Cline MCP settings (cline_mcp_settings.json):

{
  "mcpServers": {
    "hashnode": {
      "command": "npx",
      "args": ["-y", "hashnode-mcp"]
    }
  }
}

⚙️ Configuration

Authentication

Some operations require a Hashnode Personal Access Token (PAT). Get your PAT from Hashnode Settings.

With Environment Variable

export HASHNODE_API_TOKEN="your-token-here"

With Claude Desktop/Cline

Add the token to your MCP configuration:

{
  "mcpServers": {
    "hashnode": {
      "command": "npx",
      "args": ["-y", "hashnode-mcp"],
      "env": {
        "HASHNODE_API_TOKEN": "your-token-here"
      }
    }
  }
}

Operations requiring authentication:

  • ✅ Getting authenticated user info (getMe, getMyDrafts, getMyPosts)
  • ✅ Creating/updating drafts and posts
  • ✅ Publishing and scheduling
  • ✅ Series management
  • ✅ Post removal and restoration

🎯 Usage Examples

Get Publication Information

// MCP clients can invoke:
{
  "tool": "getPublicationByHost",
  "arguments": {
    "host": "blog.hashnode.com"
  }
}

Search Posts

{
  "tool": "searchPosts",
  "arguments": {
    "publicationId": "your-publication-id",
    "query": "GraphQL tutorial",
    "first": 10
  }
}

Create and Publish a Draft

{
  "tool": "createDraft",
  "arguments": {
    "publicationId": "your-publication-id",
    "title": "My New Post",
    "contentMarkdown": "# Hello World\n\nThis is my post content."
  }
}

Schedule a Post

{
  "tool": "scheduleDraft",
  "arguments": {
    "draftId": "your-draft-id",
    "authorId": "your-author-id",
    "publishAt": "2024-12-31T00:00:00.000Z"
  }
}

🏗️ Architecture

This server uses a hot-swap autoloader pattern:

src/
├── index.ts          # Entry point with MCP server setup
├── server.ts         # Server creation and tool registration
├── autoloader.ts     # Dynamic tool discovery
├── utils/
│   └── graphql-client.ts # GraphQL client with error handling
└── tools/            # Tool implementations
    ├── publication.ts    # Each exports toolDefinitions
    ├── post.ts
    ├── user.ts
    ├── me.ts
    ├── draft.ts
    ├── series.ts
    └── static-page.ts

Key Benefits:

  • Add new tools by dropping files in src/tools/
  • Zero server code changes required
  • Each tool is independently testable
  • 95%+ coverage on all tools

📚 API Reference

getPublicationByHost

Retrieves publication information by host domain.

  • host (string, required) - The host domain of the publication
  • Returns: Publication object with id, title, description, and metadata

getPublicationPosts

Fetches posts from a publication with pagination support.

  • publicationId (string, required) - The ID of the publication
  • first (number, optional, default: 10) - Number of posts to fetch
  • after (string, optional) - Cursor for pagination
  • Returns: PostConnection with edges, pageInfo for pagination

getPostBySlug

Gets a specific post by its slug from a publication.

  • publicationHost (string, required) - The host domain of the publication
  • slug (string, required) - The slug of the post
  • Returns: Post object with id, title, slug, brief, url, and content

searchPosts

Searches for posts within a publication.

  • publicationId (string, required) - The ID of the publication
  • query (string, required) - Search query string
  • first (number, optional, default: 10) - Number of results to fetch
  • Returns: SearchPostConnection with matching posts

getUserByUsername

Retrieves user information by username.

  • username (string, required) - The username of the user
  • Returns: User object with id, username, name, tagline, and bio

getMe

Gets information about the currently authenticated user. Requires auth.

  • Returns: User object with id, username, name, tagline, and bio

getMyDrafts

Retrieves drafts for the authenticated user. Requires auth.

  • first (number, optional, default: 10) - Number of drafts to fetch
  • Returns: DraftConnection with edges and pageInfo for pagination

getMyPosts

Retrieves published posts for the authenticated user. Requires auth.

  • first (number, optional, default: 10) - Number of posts to fetch
  • Returns: PostConnection with edges and pageInfo for pagination

All tools in this section require authentication via HASHNODE_API_TOKEN.

createDraft

Creates a new draft for a publication.

  • publicationId (string, required) - The ID of the publication
  • title (string, required) - The title of the draft
  • contentMarkdown (string, required) - The content in Markdown format
  • Returns: Draft object with id, title, and slug

updateDraft

Updates an existing draft.

  • draftId (string, required) - The ID of the draft to update
  • title (string, required) - The updated title
  • contentMarkdown (string, required) - The updated content in Markdown
  • Returns: Updated Draft object

publishDraft

Publishes a draft to make it a live post.

  • draftId (string, required) - The ID of the draft to publish
  • Returns: Published Post object with id, title, slug, and url

createPost

Creates and publishes a post directly without creating a draft first.

  • publicationId (string, required) - The ID of the publication
  • title (string, required) - The title of the post
  • contentMarkdown (string, required) - The content in Markdown format
  • Returns: Published Post object with id, title, slug, and url

updatePost

Updates an existing published post.

  • postId (string, required) - The ID of the post to update
  • title (string, required) - The updated title
  • contentMarkdown (string, required) - The updated content in Markdown
  • Returns: Updated Post object with id, title, slug, and url

removePost

Removes/deletes a published post.

  • postId (string, required) - The ID of the post to remove
  • Returns: Removed Post object with id, title, slug, and url

restorePost

Restores a previously removed post.

  • postId (string, required) - The ID of the post to restore
  • Returns: Restored Post object with id, title, slug, and url

All tools in this section require authentication via HASHNODE_API_TOKEN.

scheduleDraft

Schedules a draft for future publication.

  • draftId (string, required) - The ID of the draft to schedule
  • authorId (string, required) - The ID of the author scheduling the draft
  • publishAt (string, required) - ISO 8601 date-time string (e.g., "2024-12-31T00:00:00.000Z")
  • Returns: ScheduledPost object with id and scheduledDate

rescheduleDraft

Reschedules a previously scheduled draft to a new date/time.

  • draftId (string, required) - The ID of the scheduled draft
  • publishAt (string, required) - New ISO 8601 date-time string for publication
  • Returns: ScheduledPost object with id and updated scheduledDate

cancelScheduledDraft

Cancels a scheduled draft and returns it to normal draft status.

  • draftId (string, required) - The ID of the scheduled draft to cancel
  • Returns: ScheduledPost object with id and scheduledDate

getSeriesBySlug

Gets series information by slug from a publication.

  • publicationHost (string, required) - The host domain of the publication
  • slug (string, required) - The slug of the series
  • Returns: Series object with id, name, slug, and description

getSeriesPosts

Retrieves posts from a series with pagination support.

  • publicationHost (string, required) - The host domain of the publication
  • seriesSlug (string, required) - The slug of the series
  • first (number, optional, default: 10) - Number of posts to fetch
  • Returns: SeriesPostConnection with edges and pageInfo

addPostToSeries

Adds a post to an existing series. Requires auth.

  • seriesId (string, required) - The ID of the series
  • postId (string, required) - The ID of the post to add
  • Returns: Series object with id, name, and slug

getStaticPageBySlug

Gets a static page by its slug from a publication.

  • publicationHost (string, required) - The host domain of the publication
  • slug (string, required) - The slug of the static page
  • Returns: StaticPage object with id, title, slug, and content

🧪 Development

Prerequisites

  • Node.js v16+
  • npm or pnpm

Setup

# Clone repository
git clone https://github.com/rawveg/hashnode-mcp.git
cd hashnode-mcp

# Install dependencies
npm install

# Build project
npm run build

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

Test Coverage

This project follows a strict TDD methodology:

Statements   : 95%+
Branches     : 95%+
Functions    : 100%
Lines        : 95%+

Testing Philosophy:

  • Red-Green-Refactor cycle for all features
  • Critical paths always tested
  • Edge cases selectively tested
  • Error paths prioritized by impact

Adding a New Tool

  1. Create src/tools/your-tool.ts:
import { ToolDefinition } from '../autoloader.js';
import { GraphQLClient } from '../utils/graphql-client.js';

export const toolDefinitions: ToolDefinition[] = [
  {
    name: 'yourTool',
    description: 'Your tool description',
    inputSchema: {
      type: 'object',
      properties: {
        param: { type: 'string' }
      },
      required: ['param']
    },
    handler: async (client, args) => {
      // Implementation
      return 'result';
    }
  }
];
  1. Create tests in __tests__/tools/your-tool.test.ts
  2. Done! The autoloader discovers it automatically.

🤝 Contributing

Contributions are welcome! Please follow these guidelines:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Write tests - We maintain 95%+ coverage
  4. Commit with clear messages (git commit -m 'Add amazing feature')
  5. Push to your branch (git push origin feature/amazing-feature)
  6. Open a Pull Request

Code Quality Standards

  • All new tools must export toolDefinitions
  • Maintain ≥80% test coverage
  • Follow existing TypeScript patterns
  • TypeScript strict mode is non-negotiable
  • Follow the Red-Green-Refactor TDD cycle

📄 License

This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).

See LICENSE for details.

🔗 Related Projects

🙏 Acknowledgments

Built with:


⬆ back to top

Made with ❤️ by Tim Green