惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

M
MIT News - Artificial intelligence
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
J
Java Code Geeks
G
Google Developers Blog
美团技术团队
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
腾讯CDC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
The Blog of Author Tim Ferriss
月光博客
月光博客
B
Blog
WordPress大学
WordPress大学
云风的 BLOG
云风的 BLOG
博客园_首页
人人都是产品经理
人人都是产品经理
aimingoo的专栏
aimingoo的专栏
Y
Y Combinator Blog
Jina AI
Jina AI
S
SegmentFault 最新的问题
H
Help Net Security
博客园 - 聂微东
Microsoft Azure Blog
Microsoft Azure Blog
Google DeepMind News
Google DeepMind News

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I built an MCP server that lets Claude manage my GitHub p...
Enjoy Kumawat · 2026-06-21 · via DEV Community

Enjoy Kumawat

I wanted Claude to know about my developer presence — my repos, my articles, my stats — without me having to paste links every time. So I built a small MCP server that connects both GitHub and DEV.to directly to Claude.

Now I can just say: "What's my most starred repo?" or "Draft a DEV.to article about my latest project" — and Claude actually does it.

Here's how I built it in under 100 lines of Python.

What is MCP?

Model Context Protocol is an open standard that lets you connect external tools and APIs to Claude (and other LLMs). You define tools with a decorator, run a server, and Claude can call those tools during a conversation.

I'm a contributor to the MCP Python SDK, so naturally I wanted to build something real with it.

What it does

The server exposes 7 tools across two APIs:

GitHub:

  • get_github_profile — followers, repos, bio
  • list_repos — sort by stars/forks/updated
  • get_repo_stats — stars, forks, issues for any repo

DEV.to:

  • list_articles — all your articles with reaction/view counts
  • create_article — draft or publish a new article
  • update_article — edit title, body, or publish state
  • get_article_stats — reactions, comments, page views

The code

Install the only dependency:

pip install mcp[cli]

Create a .env file:

GITHUB_TOKEN=your_github_token
GITHUB_USERNAME=your_github_username
DEV_TO_API=your_devto_api_key
DEV_USERNAME=your_devto_username

Here's the full server (server.py):

import os, json, urllib.request
from mcp.server.fastmcp import FastMCP

GITHUB_USERNAME = os.environ.get("GITHUB_USERNAME", "")
DEV_USERNAME = os.environ.get("DEV_USERNAME", "")

mcp = FastMCP("developer-presence")

def _gh(path, method="GET", data=None):
    req = urllib.request.Request(f"https://api.github.com{path}", method=method)
    req.add_header("Authorization", f"token {os.environ['GITHUB_TOKEN']}")
    req.add_header("Accept", "application/vnd.github.v3+json")
    if data:
        req.add_header("Content-Type", "application/json")
        req.data = json.dumps(data).encode()
    with urllib.request.urlopen(req) as r:
        return json.loads(r.read())

def _dev(path, method="GET", data=None):
    req = urllib.request.Request(f"https://dev.to/api{path}", method=method)
    req.add_header("api-key", os.environ["DEV_TO_API"])
    req.add_header("Content-Type", "application/json")
    if data:
        req.data = json.dumps(data).encode()
    with urllib.request.urlopen(req) as r:
        return json.loads(r.read())

@mcp.tool()
def get_github_profile() -> dict:
    """Fetch public GitHub profile stats."""
    u = _gh(f"/users/{GITHUB_USERNAME}")
    return {"login": u["login"], "name": u.get("name"), "bio": u.get("bio"),
            "public_repos": u["public_repos"], "followers": u["followers"]}

@mcp.tool()
def list_repos(sort: str = "updated", limit: int = 10) -> list:
    """List public repos sorted by updated/stars/forks."""
    repos = _gh(f"/users/{GITHUB_USERNAME}/repos?sort={sort}&per_page={min(limit,100)}")
    return [{"name": r["name"], "stars": r["stargazers_count"],
             "language": r.get("language"), "url": r["html_url"]} for r in repos]

@mcp.tool()
def list_articles(per_page: int = 10) -> list:
    """List your DEV.to articles with stats."""
    articles = _dev(f"/articles/me?per_page={min(per_page,30)}")
    return [{"id": a["id"], "title": a["title"],
             "reactions": a.get("positive_reactions_count", 0),
             "page_views": a.get("page_views_count", 0)} for a in articles]

@mcp.tool()
def create_article(title: str, body_markdown: str,
                   tags: list[str] = None, published: bool = False) -> dict:
    """Create a new DEV.to article."""
    payload = {"article": {"title": title, "body_markdown": body_markdown, "published": published}}
    if tags:
        payload["article"]["tags"] = tags
    result = _dev("/articles", method="POST", data=payload)
    return {"id": result["id"], "url": result.get("url")}

if __name__ == "__main__":
    mcp.run()

(Full version with all 7 tools on GitHub)

Run it

# Dev mode — opens MCP Inspector in browser
mcp dev server.py

# Or wire into Claude Desktop

For Claude Desktop, add this to claude_desktop_config.json:

{
  "mcpServers": {
    "developer-presence": {
      "command": "python",
      "args": ["/path/to/server.py"],
      "env": {
        "GITHUB_TOKEN": "...",
        "GITHUB_USERNAME": "...",
        "DEV_TO_API": "...",
        "DEV_USERNAME": "..."
      }
    }
  }
}

What I can do now

Once connected, I can ask Claude things like:

  • "List my top 5 repos by stars"
  • "What are the stats on my last DEV.to article?"
  • "Write and publish a draft article about X"
  • "How many followers do I have on GitHub?"

It sounds simple, but having your developer presence queryable from a conversation is surprisingly useful — especially when you're writing content and want to reference your own work.

Get the code

Everything is on GitHub: enjoykumawat/developer-presence-mcp

If you want to adapt it for your own username, just update the .env file — no other changes needed.


I'm a contributor to the MCP Python SDK. If you're interested in building MCP servers, feel free to reach out or check out the official SDK — it's a great place to start.

Follow me here on DEV.to @enjoy_kumawat for more AI tooling content.