DEV Community

Kiell Tampubolon
Kiell Tampubolon

Posted on

Finishing a Read-Only MCP Server: From 6 Tools to 9

This is a submission for the GitHub Finish-Up-A-Thon Challenge

What I Built

I took an unfinished open-source MCP server for DEV.to and added the missing half.

The original repo (nickytonline/dev-to-mcp) was built by an actual DEV.to engineer and shipped six read-only tools: get_articles, get_article, get_user, get_tags, get_comments, search_articles. Useful for reading, useless for writing.

I extended it with three write tools:

  • create_article for publishing new articles (draft or live)
  • update_article for editing existing ones
  • delete_article for unpublishing

The result is a full read-write MCP server that lets Claude (or any MCP client) treat DEV.to like a CMS. This article was created and published using it.

Demo

The tool list in Claude Desktop after the build:

Read-only tools (6):
  Get Articles, Get Article, Get User, Get Tags, Get Comments, Search Articles

Write/delete tools (3):
  Create Article, Update Article, Delete Article
Enter fullscreen mode Exit fullscreen mode

A draft creation call looks like this:

{
  "tool": "create_article",
  "args": {
    "title": "My new post",
    "body_markdown": "# Hello world",
    "tags": ["webdev", "ai"],
    "published": false
  }
}
Enter fullscreen mode Exit fullscreen mode

The MCP server hits POST https://dev.to/api/articles with the user's DEVTO_API_KEY from env, returns the article ID, and Claude can immediately call update_article against it. No browser, no copy-paste from chat to editor.

The Journey

The original repo was solid but limited. I asked myself: why use an MCP server that can only read?

Setup was the first wall. The npm package wasn't published, so npx -y @nickytonline/dev-to-mcp returned 404. Then npm install -g github:... failed because the repo had no top-level package.json at the install path npm expected. The fix was unglamorous: git clone, npm install, npm run build, point Claude Desktop's config at the local dist/index.js.

There was also a Windows-specific gotcha. Claude Desktop on Windows needs npx.cmd, not npx. The error message was just Server disconnected. Logs showed bad option: -y because the config still had the npx flag while the command had been swapped to node. Small things, two hours.

Once the read-only server was running, the actual finish-up work was straightforward. The codebase used a clean handler pattern: each tool was a function that called the DEV.to API and returned a typed response. I followed the same pattern for the three new tools:

// Pattern from the existing read tools
async function getArticle(id: number) {
  const res = await fetch(`https://dev.to/api/articles/${id}`, {
    headers: { 'api-key': process.env.DEVTO_API_KEY }
  });
  return res.json();
}

// New write tool, same shape
async function createArticle(article: ArticleInput) {
  const res = await fetch('https://dev.to/api/articles', {
    method: 'POST',
    headers: {
      'api-key': process.env.DEVTO_API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ article })
  });
  return res.json();
}
Enter fullscreen mode Exit fullscreen mode

Register the new handlers in the MCP server's tool list, rebuild with npm run build, restart Claude Desktop. Done.

Tech Stack

  • TypeScript for the server code
  • Vite for the build (12.83 kB output, builds in 133ms)
  • Model Context Protocol SDK for the server scaffolding
  • DEV.to API v1 as the backend
  • Claude Desktop as the MCP client

What I Learned

Two things stood out.

First, finishing someone else's project is faster than starting from scratch. The repo had types, patterns, error handling, and tests already in place. Adding three tools meant matching an existing shape, not inventing one. The full add-rebuild-test cycle was under thirty minutes.

Second, AI assistance works best when there's existing structure to imitate. I gave Claude Code the repo path and asked for three tools matching the existing pattern. It read the codebase, identified the handler signature, knew the DEV.to API endpoints from training data, and produced working code on the first build. Without the existing read-only tools as reference, the output would have needed more iteration.

What's Next

The MCP server still has gaps:

  • No image upload (DEV.to requires base64 inline or external URLs)
  • No get_followers or get_following
  • No comment write/delete
  • No analytics endpoints

These are small additions following the same pattern. The hard part was the first three.

Repo

The forked repo with write tools: github.com/glatinone/dev-to-mcp

Original credit to @nickytonline for the read-only foundation.

Top comments (0)