{"slug": "i-built-an-mcp-server-that-lets-claude-manage-my-github-profile-and-dev-to-here", "title": "I built an MCP server that lets Claude manage my GitHub profile and DEV.to articles — here's how", "summary": "A developer built an MCP server in under 100 lines of Python that connects Claude to GitHub and DEV.to APIs, enabling natural language commands to manage repositories and articles. The server exposes seven tools for fetching profile stats, listing repos, and creating or updating DEV.to articles.", "body_md": "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.\n\nNow 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.\n\nHere's how I built it in under 100 lines of Python.\n\n[Model Context Protocol](https://github.com/modelcontextprotocol/python-sdk) 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.\n\nI'm a contributor to the MCP Python SDK, so naturally I wanted to build something real with it.\n\nThe server exposes 7 tools across two APIs:\n\n**GitHub:**\n\n`get_github_profile`\n\n— followers, repos, bio`list_repos`\n\n— sort by stars/forks/updated`get_repo_stats`\n\n— stars, forks, issues for any repo**DEV.to:**\n\n`list_articles`\n\n— all your articles with reaction/view counts`create_article`\n\n— draft or publish a new article`update_article`\n\n— edit title, body, or publish state`get_article_stats`\n\n— reactions, comments, page viewsInstall the only dependency:\n\n```\npip install mcp[cli]\n```\n\nCreate a `.env`\n\nfile:\n\n```\nGITHUB_TOKEN=your_github_token\nGITHUB_USERNAME=your_github_username\nDEV_TO_API=your_devto_api_key\nDEV_USERNAME=your_devto_username\n```\n\nHere's the full server (`server.py`\n\n):\n\n``` python\nimport os, json, urllib.request\nfrom mcp.server.fastmcp import FastMCP\n\nGITHUB_USERNAME = os.environ.get(\"GITHUB_USERNAME\", \"\")\nDEV_USERNAME = os.environ.get(\"DEV_USERNAME\", \"\")\n\nmcp = FastMCP(\"developer-presence\")\n\ndef _gh(path, method=\"GET\", data=None):\n    req = urllib.request.Request(f\"https://api.github.com{path}\", method=method)\n    req.add_header(\"Authorization\", f\"token {os.environ['GITHUB_TOKEN']}\")\n    req.add_header(\"Accept\", \"application/vnd.github.v3+json\")\n    if data:\n        req.add_header(\"Content-Type\", \"application/json\")\n        req.data = json.dumps(data).encode()\n    with urllib.request.urlopen(req) as r:\n        return json.loads(r.read())\n\ndef _dev(path, method=\"GET\", data=None):\n    req = urllib.request.Request(f\"https://dev.to/api{path}\", method=method)\n    req.add_header(\"api-key\", os.environ[\"DEV_TO_API\"])\n    req.add_header(\"Content-Type\", \"application/json\")\n    if data:\n        req.data = json.dumps(data).encode()\n    with urllib.request.urlopen(req) as r:\n        return json.loads(r.read())\n\n@mcp.tool()\ndef get_github_profile() -> dict:\n    \"\"\"Fetch public GitHub profile stats.\"\"\"\n    u = _gh(f\"/users/{GITHUB_USERNAME}\")\n    return {\"login\": u[\"login\"], \"name\": u.get(\"name\"), \"bio\": u.get(\"bio\"),\n            \"public_repos\": u[\"public_repos\"], \"followers\": u[\"followers\"]}\n\n@mcp.tool()\ndef list_repos(sort: str = \"updated\", limit: int = 10) -> list:\n    \"\"\"List public repos sorted by updated/stars/forks.\"\"\"\n    repos = _gh(f\"/users/{GITHUB_USERNAME}/repos?sort={sort}&per_page={min(limit,100)}\")\n    return [{\"name\": r[\"name\"], \"stars\": r[\"stargazers_count\"],\n             \"language\": r.get(\"language\"), \"url\": r[\"html_url\"]} for r in repos]\n\n@mcp.tool()\ndef list_articles(per_page: int = 10) -> list:\n    \"\"\"List your DEV.to articles with stats.\"\"\"\n    articles = _dev(f\"/articles/me?per_page={min(per_page,30)}\")\n    return [{\"id\": a[\"id\"], \"title\": a[\"title\"],\n             \"reactions\": a.get(\"positive_reactions_count\", 0),\n             \"page_views\": a.get(\"page_views_count\", 0)} for a in articles]\n\n@mcp.tool()\ndef create_article(title: str, body_markdown: str,\n                   tags: list[str] = None, published: bool = False) -> dict:\n    \"\"\"Create a new DEV.to article.\"\"\"\n    payload = {\"article\": {\"title\": title, \"body_markdown\": body_markdown, \"published\": published}}\n    if tags:\n        payload[\"article\"][\"tags\"] = tags\n    result = _dev(\"/articles\", method=\"POST\", data=payload)\n    return {\"id\": result[\"id\"], \"url\": result.get(\"url\")}\n\nif __name__ == \"__main__\":\n    mcp.run()\n```\n\n(Full version with all 7 tools on [GitHub](https://github.com/enjoykumawat/developer-presence-mcp))\n\n```\n# Dev mode — opens MCP Inspector in browser\nmcp dev server.py\n\n# Or wire into Claude Desktop\n```\n\nFor Claude Desktop, add this to `claude_desktop_config.json`\n\n:\n\n```\n{\n  \"mcpServers\": {\n    \"developer-presence\": {\n      \"command\": \"python\",\n      \"args\": [\"/path/to/server.py\"],\n      \"env\": {\n        \"GITHUB_TOKEN\": \"...\",\n        \"GITHUB_USERNAME\": \"...\",\n        \"DEV_TO_API\": \"...\",\n        \"DEV_USERNAME\": \"...\"\n      }\n    }\n  }\n}\n```\n\nOnce connected, I can ask Claude things like:\n\nIt 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.\n\nEverything is on GitHub: [enjoykumawat/developer-presence-mcp](https://github.com/enjoykumawat/developer-presence-mcp)\n\nIf you want to adapt it for your own username, just update the `.env`\n\nfile — no other changes needed.\n\nI'm a contributor to the [MCP Python SDK](https://github.com/modelcontextprotocol/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.\n\n*Follow me here on DEV.to @enjoy_kumawat for more AI tooling content.*", "url": "https://wpnews.pro/news/i-built-an-mcp-server-that-lets-claude-manage-my-github-profile-and-dev-to-here", "canonical_source": "https://dev.to/enjoy_kumawat/i-built-an-mcp-server-that-lets-claude-manage-my-github-profile-and-devto-articles-heres-how-kid", "published_at": "2026-06-21 08:53:50+00:00", "updated_at": "2026-06-21 09:06:35.715395+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "large-language-models", "ai-agents"], "entities": ["Claude", "GitHub", "DEV.to", "Model Context Protocol", "MCP Python SDK", "FastMCP"], "alternates": {"html": "https://wpnews.pro/news/i-built-an-mcp-server-that-lets-claude-manage-my-github-profile-and-dev-to-here", "markdown": "https://wpnews.pro/news/i-built-an-mcp-server-that-lets-claude-manage-my-github-profile-and-dev-to-here.md", "text": "https://wpnews.pro/news/i-built-an-mcp-server-that-lets-claude-manage-my-github-profile-and-dev-to-here.txt", "jsonld": "https://wpnews.pro/news/i-built-an-mcp-server-that-lets-claude-manage-my-github-profile-and-dev-to-here.jsonld"}}