mcpField
V
Velog

Velog

本地服务
github.com社交媒体36 天前更新

关于 Velog

Velog 是供 Claude 等 MCP 客户端使用的服务,可读取、搜索、备份和编写 Velog 文章,并生成图表。公开发布默认关闭,需由配置者显式启用。

主要功能

  1. 01读取、搜索和统计文章
  2. 02创建草稿并管理文章
  3. 03导出带 YAML 元数据的 Markdown
  4. 04生成图表、时序图和封面
  5. 05公开发布需显式授权

适用场景

  1. 01检索自己的旧文章
  2. 02备份博客文章并统计表现
  3. 03起草文章并关联已有系列
  4. 04为文章生成图表或封面

MCP 相关

作为 stdio MCP 服务,向本地 MCP 客户端提供 Velog 文章读取、写入、备份、统计和图像生成工具。公开发布能力由环境变量控制。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"milcho0604-velog": {
"command": "npx",
"args": [
"-y",
"@milcho0604/velog-mcp"
],
"env": {
"VELOG_ACCESS_TOKEN": "<VELOG_ACCESS_TOKEN>",
"VELOG_REFRESH_TOKEN": "<VELOG_REFRESH_TOKEN>",
"VELOG_ALLOW_PUBLIC": "<VELOG_ALLOW_PUBLIC>",
"VELOG_ALLOW_PROFILE": "<VELOG_ALLOW_PROFILE>",
"VELOG_CHROME_PATH": "<VELOG_CHROME_PATH>"
}
}
}
}
启动命令npx -y @milcho0604/velog-mcp
需要配置的环境变量
VELOG_ACCESS_TOKEN密钥벨로그 access token. 둘 중 아무거나 있으면 쓰기가 열린다. 이쪽이 먼저 만료된다.
VELOG_REFRESH_TOKEN密钥벨로그 refresh token. 둘 중 아무거나 있으면 쓰기가 열린다. 이쪽은 30일 간다.
VELOG_ALLOW_PUBLIC1 이면 공개 발행이 열린다. 기본은 꺼짐이고, 모델은 이 값을 못 바꾼다.
VELOG_ALLOW_PROFILE1 이면 프로필 수정이 열린다. 프로필 읽기는 언제나 된다.
VELOG_CHROME_PATH로컬 크롬 실행 파일 경로. 다이어그램, 시퀀스, 표지 렌더링에 쓴다.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@milcho0604/velog-mcp0.9.6

工具

23

收录的工具列表 · 更新于 6 天前

参数类型必填说明
idstring否글 UUID. 이걸 주면 username/url_slug 는 불필요
url_slugstring否URL 的最后一段
usernamestring否不带 @。例如:"velopert"

详细介绍

velog-mcp

npm Node License Runtime deps

在 Claude 等 MCP 客户端中操作벨로그的服务。 读取文章、撰写草稿、发布文章,并完整备份。

在 Claude 中撰写草稿、找出浏览量最高的文章并绘制结构图的演示

English →


为什么又做一个

已经有两个 벨로그 MCP 服务了。这个实现有三点不同。

1. 发布是权限,而不是默认功能。 安装后可以撰写草稿并私密发布。公开发布需要设置环境变量才能启用。模型无法更改这个开关——只有打开 MCP 配置文件的人才能更改。

2. 不猜测 벨로그 的行为,而是实测验证。 벨로그 GraphQL 是非官方接口,没有文档。这个仓库通过查看 velog-io/velog 源码并实际调用,确认并记录了它的实际行为。服务端的 6 个陷阱见 docs/api-reference.md,其中包括无报错却返回空结果,以及将已发布文章变为私密文章的情况。

3. 只有 2 个运行时依赖。 只有 @modelcontextprotocol/sdk 和 zod。 HTTP、测试运行器和 TypeScript 执行都使用 Node 内置功能。


安装

需要 Node.js 22.18 或更高版本。实际运行的是编译后的 dist/index.js,但开发和验证会直接运行 .ts 文件,而第一个无需标志即可运行它们的版本是 22.18。CI 会在 22.18、24 和 26 上运行。

作为 Claude Code 插件安装(推荐)
/plugin marketplace add milcho0604/velog-mcp
/plugin install velog@milcho

安装时会询问四项内容。即使一项都不填写,也能完成安装,并以只读模式运行。

询问内容不填写时
Velog refresh token只读(查询、搜索和统计照常可用)
是否允许公开发布只能撰写草稿和私密发布
是否允许修改个人资料个人资料工具将关闭
Chrome 路径自动在标准位置查找

**令牌会存入 macOS 钥匙串。**不会以明文形式留在配置文件中——只有声明为 sensitive: true 的值才会存入钥匙串,测试会强制检查这一点(P7)。

如需稍后更改值,请运行 /plugin manage。

直接作为 MCP 服务使用

软件包已发布到 npm,无需克隆,MCP 客户端会通过 npx 启动它。配置块和客户端支持范围请参阅配置。

claude mcp add velog -e VELOG_REFRESH_TOKEN=여기에_토큰 \
  -- npx -y @milcho0604/[email protected]

这种方式会将令牌留在客户端配置文件中。上面的插件方式会将令牌存入钥匙串。

自行构建
git clone https://github.com/milcho0604/velog-mcp.git
cd velog-mcp
npm install && npm run build

配置

将以下内容添加到 MCP 客户端配置文件(claude_desktop_config.json、.mcp.json 等)中。

{
  "mcpServers": {
    "velog": {
      "command": "npx",
      "args": ["-y", "@milcho0604/[email protected]"],
      "env": {
        "VELOG_REFRESH_TOKEN": "여기에 토큰"
      }
    }
  }
}

如果使用 Claude Code CLI:

claude mcp add velog -e VELOG_REFRESH_TOKEN=여기에_토큰 \
  -- npx -y @milcho0604/[email protected]

如需从本地检出版本运行,请将 command 改为 node /절대경로/velog-mcp/dist/index.js。

**支持哪些客户端?**这是一个 stdio 服务——由客户端作为本地进程启动。 可用于在本地运行 MCP 服务的客户端,例如 Claude Code、Claude Desktop 和 Cursor。 不支持 claude.ai 和 ChatGPT 网页应用——两者都只接受可通过 HTTP 访问的远程 MCP 服务。这是因为连接是从对方的服务器发起,而非从你的设备发起。若要在网页上使用,就必须公开托管服务并将 벨로그 令牌提供给该部署版本,这样一来,原本只将令牌保留在自己设备上的理由也就不复存在了。

如何获取令牌

벨로그 没有公开写入 API,因此使用浏览器会话 Cookie 进行身份验证。

  1. 登录 velog.io
  2. 开发者工具(F12)→ Application → Cookies → https://velog.io
  3. 复制 refresh_token 的值

只需设置 VELOG_REFRESH_TOKEN。 벨로그 服务端会自动重新签发有效期较短的 access_token(authPlugin.mts),本服务会接收并使用响应中附带的续期 Cookie。设置一次即可使用 30 天。

也接受 VELOG_ACCESS_TOKEN,但单独使用时 1 小时后就会过期。

令牌只通过环境变量读取。不会写入磁盘,也不会访问浏览器 Cookie 数据库或 OS 钥匙串。不过,写入 MCP 配置文件的值会以明文形式保留在该文件中——该文件由用户自行管理。

**没有令牌也能启动服务。**服务会以只读模式运行;无需身份验证即可查询公开文章、搜索、查看趋势和博客统计信息。


权限

环境变量可执行的操作
(未设置)完整读取 · 撰写草稿 · 私密发布 · 生成和上传图片 · 检查架构 — 共 23 个工具
VELOG_ALLOW_PUBLIC=1…额外允许公开发布(会出现 is_private 参数)
VELOG_ALLOW_PROFILE=1…额外允许修改个人资料(共 5 个工具)

两个开关相互独立——可以只开启其中一个,也可以同时开启。

"env": {
  "VELOG_REFRESH_TOKEN": "...",
  "VELOG_ALLOW_PUBLIC": "1",
  "VELOG_ALLOW_PROFILE": "1"
}

只有 1、true、yes、on 会被视为“开启”。其他值一律视为关闭——不会因拼写错误而意外开启。

关闭公开发布时,任何工具中都不存在 is_private 参数。模型根本无法请求公开发布。开启后,该参数会出现,但默认值仍为 true(私密)。

为什么默认设为私密

这不是谨慎过度,而是有实测依据。벨로그 的发布限制只统计 is_private: false 的文章:

// apps/server/src/services/PostApiService/index.mts
count({ where: { fk_user_id, is_private: false, released_at: { gt: 5분전 } } })
if (count >= 10) {
  updateMany({ where: { fk_user_id, released_at: { gt: 5분전 } },
               data: { is_private: true } })   // 최근 글을 '전부' 비공개로
}

私密文章不会增加此计数。不过,isPostLimitReached() 会在检查是否公开之前无条件执行,因此,如果最近 5 分钟内已经累积了 10 篇公开文章,私密草稿请求也可能触发这一破坏性行为——“不会增加计数”和“不会触发行为”并不是一回事。因此,写入操作不重试,并保留了自行设置的上限。

公开文章会增加计数;一旦公开,就会通过 RSS、搜索索引和订阅邮件发出,即使删除也无法撤回。这种不对称性正是设置明确 opt-in 的理由。

详情请参阅:docs/security.md


工具

共 23 个工具,其中只有 10 个会改变 벨로그 状态。

읽기 — 인증 불필요
도구하는 일
velog_get_post글 하나를 본문까지
velog_list_posts사용자의 글 목록, 태그로 좁힐 수 있음
velog_search_posts키워드 검색. username 을 주면 그 블로그 안에서만
velog_trending_posts트렌딩 (day/week/month/year)
velog_recent_posts벨로그 전체 최신 글
velog_get_user프로필·팔로워 수·소개
velog_list_series시리즈 목록 (글 수와 id 포함)
velog_user_tags사용자가 쓰는 태그와 글 수
읽기 — 인증 필요
도구하는 일
velog_whoami토큰이 어느 계정인지 (토큰 생존 확인용으로도)
velog_list_drafts내 초안 목록과 id
파생 — 벨로그에 없는 기능
도구하는 일
velog_blog_stats조회수·좋아요·댓글 집계, 상위 글, 연도별·태그별 분포
velog_export_posts글을 YAML 프론트매터 붙은 마크다운으로 저장
velog_diagnose지금 벨로그 스키마가 이 서버의 기준선과 같은지 대조
쓰기
도구효과
velog_create_draft초안 저장. 어떤 설정에서도 발행하지 않는다
velog_update_draft초안 전체 교체 — 생략한 필드는 초기화된다
velog_publish_post새 글 발행
velog_publish_draft기존 초안을 발행 (저장된 본문을 그대로 씀)
velog_unpublish_post발행글을 초안으로 되돌림
velog_update_post발행글 수정 — 생략한 필드는 유지된다

velog_update_draft 는 생략하면 초기화하고, velog_update_post 는 유지한다. 의도한 비대칭이고 이유는 docs/tools.md 에 있다.

썸네일 자동 채움

thumbnail 을 생략하면 본문 첫 이미지를 썸네일로 쓴다. 목록·공유 카드가 글자만 나오는 걸 막기 위해서다. 무엇을 넣었는지는 결과에 항상 표시하고, 후보가 여럿이면 나머지도 함께 보여준다.

thumbnail 값동작
생략본문 첫 이미지로 자동 설정
URL그대로 사용
null자동 채움 끄기 — 일부러 비워 두는 경우

코드블록·인라인코드 안의 이미지는 후보에서 제외한다(예제로 적어둔 마크다운이 썸네일이 되면 안 되므로). velog_update_post 는 기존 썸네일이 있으면 덮지 않는다 — 제목만 고쳤는데 목록 카드가 바뀌는 일이 없도록 한 것이고, 이때 null 은 "채우지 마라"이지 "지워라"가 아니다.

시리즈 — 이름으로 한 번에

series_name 에 이름을 주면 저장 전에 내 시리즈에서 찾아 같은 요청에 실어 보낸다. 글쓰기와 시리즈 등록이 한 번의 호출로 끝난다. id 는 사람도 AI 도 모르기 때문에 이름을 받는다.

series_name: "PostgreSQL"     ← 대소문자·앞뒤 공백은 무시하고 찾는다
series_id:   "e53810ca-..."   ← id 를 알면 이쪽이 우선

⚠️ 못 찾으면 글을 저장하지 않는다. 조용히 시리즈 없이 저장하면 들어간 줄 알기 때문이다. 이때 있는 시리즈 목록을 함께 알려준다.

series_name·series_id 를 둘 다 생략하면 저장 뒤 결과에 내 시리즈 목록을 붙여준다. 이 조회가 실패해도 글은 이미 저장된 뒤이므로 저장을 실패시키지 않는다(취소도 삼킨다 — 여기서 실패로 보고하면 재시도 때 글이 두 번 생긴다).

⚠️ 벨로그 API 로는 시리즈를 만들 수 없다. 뮤테이션에 시리즈 관련이 하나도 없고 WritePostInput 도 series_id 만 받는다. 새 시리즈는 벨로그 웹에서 한 번 만들면 그 뒤부터 이 도구로 붙일 수 있다.

username 을 받는 도구 중 velog_list_drafts·velog_blog_stats·velog_export_posts 는 생략하면 내 계정을 쓴다. velog_search_posts 는 생략하면 벨로그 전체를 검색한다.

그림 — 다이어그램·표지
도구효과
velog_render_diagram구성도·흐름도를 그려 올린다
velog_render_sequence참가자와 순서 있는 메시지로 시퀀스 다이어그램을 그린다
velog_render_cover글 표지 카드(1200×630)를 만든다
velog_upload_image로컬 이미지를 올리고 마크다운을 돌려준다

넘기는 건 무엇이 있고 무엇이 어디로 흐르는지뿐이다. 색·여백·글자 실측·모서리 라운딩·캔버스 크기는 렌더러가 쥔다. 매번 처음부터 그리면 매번 다르게 생기기 때문이다.

수치는 전부 실측이다. 노드 폭과 줄바꿈은 브라우저 getBBox() 로 잰다 — 글자수로 추정하면 한글·영문이 섞인 라벨에서 반드시 틀린다. 캔버스는 다 그린 뒤에 내용 bbox 로 정하므로 그림이 잘릴 수가 없다.

그리고 스스로 감사해서 여섯 가지를 보고한다:

카드 밖으로 삐져나온 글자 · 억지로 맞추려 눌린 자간
노드를 관통하거나 노드 뒤에 숨은 선 · 그룹 이름표를 가린 선
선끼리 겹침 · 노드끼리 겹침 · 라벨이 카드나 그룹 이름표에 얹히거나 그룹 테두리에 걸침

감사에 하나라도 걸리면 올리지 않는다. 그리고 그걸 끄는 스위치는 없다. 벨로그에는 이미지 삭제 API 가 없고 업로드 한도도 깎이니, 어설픈 그림은 올리는 것보다 고쳐 그리는 게 낫다. 모델이 스스로 켤 수 있는 우회는 방어가 아니다 — 공개 발행 스위치와 같은 이유다(ADR 0004). 감사에 떨어진 PNG 는 이 서버로 올릴 길이 없다. upload:false 로 그려도 그 산출물은 거부 목록에 오르고, 경로를 velog_upload_image 에 줘도 막힌다 — 그 두 단계 우회를 막으려고 만든 장치다. 고쳐서 다시 그리는 것이 유일한 경로다. (감사를 통과한 PNG 는 upload:false 로 그린 뒤 경로를 넘겨 올릴 수 있다.)

아이콘은 내장 28종(server·database·cloud·clock·alert …)이고 전부 도형 조합이다. 밖에서 받아오는 게 하나도 없다 — 렌더러는 DNS 를 막은 채로 돈다.

크롬이 필요하다 (크로미움 계열이면 된다: Edge·Brave·Chromium). macOS·리눅스· 윈도우에서 알아서 찾고, 다른 데 있으면 VELOG_CHROME_PATH 로 지정한다. 이 중 브라우저를 쓰는 건 velog_render_diagram, velog_render_sequence, velog_render_cover 셋뿐이고, velog_upload_image 를 포함한 나머지 19개는 크롬 없이 동작한다.

비용은 실측해서 밝혀 둔다. 그림 한 장에 크롬 911개·최대 약 1GB 를 34초 쓰고 0 으로 돌아온다. 이건 크롬의 바닥이지 우리 그림 탓이 아니다. 좌표·글자·개수에는 전부 상한이 있고, 캔버스 상한(6000px/900만px)은 페이지 안에서 걸린다 — 브라우저는 크기를 받는 순간 표면을 준비하므로 바깥에서 막으면 늦다. 렌더는 줄을 세운다 — MCP 클라이언트가 도구를 병렬로 부르기 때문에, 안 그러면 그림 다섯 장 요청에 크롬 45개·6GB 가 된다. 줄을 세우면 동시 4회도 한 장 분량으로 고정된다. 10회 연속에서 누적이 없는 것도 확인했다.

프로필 수정 — VELOG_ALLOW_PROFILE=1

도구 5개가 추가된다: velog_update_profile(이름·한줄소개), velog_update_about, velog_update_blog_title, velog_update_social_links, velog_update_profile_image. 설정이 없으면 등록조차 되지 않는다.

게이트를 둔 건 위험해서가 아니다 — 전부 되돌릴 수 있고 본인 계정에만 영향이며 어디로도 배포되지 않는다. 이유는 혼동이다: 프로필의 short_bio 와 글의 short_description 은 이름이 비슷하다. "소개 좀 고쳐줘" 가 어느 쪽인지 모호할 때, 스위치가 꺼져 있으면 잘못 짚어도 프로필에 손이 닿지 않는다.

velog_update_profile 은 생략한 항목을 유지한다. 벨로그의 UpdateProfileInput 은 display_name 과 short_bio 를 둘 다 필수로 받아서 한쪽만 보내면 다른 쪽이 빈 문자열로 덮인다 — 그래서 현재 값을 읽어 채워 보낸다.


사용법

설정이 끝나면 MCP 클라이언트에 그냥 말하면 된다.

"오늘 고친 버그로 벨로그 초안 잡아줘"
   → 마크다운을 쓰고 초안으로 저장, 편집 URL 을 준다

"작년에 HTTP/2 로 뭐 썼더라"
   → 내 글 안에서 검색

"내 글 조회수 상위 10개랑 어떤 태그가 제일 많이 읽혔는지"
   → 블로그 전체를 훑어 집계

"내 글 전부 ~/blog-backup 에 백업해"
   → 프론트매터 붙은 .md 로 저장

"그 초안 발행해줘"
   → 기본은 비공개. 공개는 VELOG_ALLOW_PUBLIC=1 이 있어야 한다

"요청이 LB 에서 워커 거쳐 레디스까지 어떻게 흐르는지 그려줘"
   → 그림을 그리고 자가감사한 뒤 올리고, 본문에 붙일 마크다운을 준다

"이 글 표지 이미지 만들어줘"
   → 1200×630 카드. 주소를 velog_update_post 의 thumbnail 에 넣으면 표지가 된다

되돌릴 수 없는 도구에는 destructiveHint 가 붙어 있다. 다만 annotation 은 «힌트» 이지 차단이 아니다 — 호출 전에 승인을 물을지는 MCP 클라이언트 설정에 달렸다. 서버가 막는 것은 따로다: 공개 발행은 VELOG_ALLOW_PUBLIC=1 없이는 경로 자체가 없고, 쓰기는 재시도하지 않으며, 공개 발행은 이 서버 인스턴스 안에서 5분에 5건으로 스스로 제한한다(비공개 발행·초안에는 이 제한이 걸리지 않는다).

백업 파일 형식
---
title: "글 제목"
date: 2022-12-31T18:32:39.790Z
slug: "url-slug"
url: "https://velog.io/@username/url-slug"
tags: ["태그1", "태그2"]
likes: 260
views: 16323
---

마크다운 본문…

개발

npm test              # node:test 로 .ts 직접 실행 — jest·ts-node 없음
npm run typecheck     # 테스트 포함 — 종전엔 제외돼 실제 오류가 숨어 있었다
npm run lint          # typescript-eslint (타입 기반)
npm run build         # tsconfig.build.json (dist 에 테스트 미포함)
npm run schema:dump   # 현재 벨로그 GraphQL 스키마 덤프
npm run schema:baseline  # schema/baseline.json 을 실측으로 다시 만든다 (velog_diagnose 의 기준선)
npm run schema:baseline -- --check   # 쓰지 않고 «지금 기준선이 맞는지» 만 본다

테스트 684건(0.9.6 기준). safety.test.ts 가 보안 불변식(A1A13)을, render.test.ts 가 구성도 불변식(R1R23, D1)과 시퀀스 불변식(S1S12)을, plugin.test.ts 가 포장 불변식(P1P28)을 고정한다. 깨지면 우회하지 말고 왜 깨졌는지부터 볼 것.

여기 있는 방어는 전부 일부러 망가뜨려 확인했다. 소스 변이 54종 + 발행 관문 자체를 겨눈 변이 12종(scripts/gate-mutation.sh), 각각이 검사를 정확히 1건씩 실패시켜야 한다. 방어를 지웠는데도 통과하는 테스트는 테스트가 아니다. 이 저장소에도 그런 게 여럿 있었고, 그렇게 해서 고쳤다.

문서

문서내용
docs/PRD.md기획서 — 목표·비목표·성공 기준
docs/architecture.md구조, Node 타입 스트리핑이 허용하는 TS 부분집합
docs/api-reference.md벨로그 GraphQL 스키마 실측 + 서버 함정
docs/security.md토큰 취급, 권한 모델, 의도적으로 뺀 기능
docs/tools.md도구 카탈로그와 주의사항
docs/decisions/설계 결정 기록 (ADR)
CHANGELOG.md버전별로 무엇이 깨져 있었고 무엇이 고쳐졌나

참고

벨로그 내부 GraphQL API 를 쓴다. 비공식이라 예고 없이 바뀔 수 있다. 뭔가 깨지면 npm run schema:dump 를 돌려 docs/api-reference.md 와 diff 하는 게 가장 빠르다.

벨로그 이용약관에는 자동화 접근을 제한하는 조항이 없다. 본인 토큰으로 본인 글을 다루는 것은 권한 내 행위이고, 게시물 저작권은 회원에게 귀속된다(제5조).

라이선스

MIT

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。