VKontakte channel plugin for Claude Code. Bridges VK community messages into an active Claude Code session via MCP, so you can chat with Claude from the VK Messenger (mobile or web).
Port of the official Telegram channel plugin to VK Bot Long Poll API.
VK user → VK community bot → VK Bot Long Poll → [this plugin] → Claude Code session
↕
Claude Code ← MCP Channel Protocol ← reply / edit / react / download_attachment tools
- Inbound:
groups.getLongPollServer+a_checkpoll loop →notifications/claude/channelinto the active CC session - Outbound:
messages.send/messages.edit/messages.sendReactionwith two-step photo and doc upload - Access control: pairing codes, allowlist, group chats with mention-only mode — state in
~/.claude/channels/vkontakte/access.json - Permission-request buttons: Claude Code's
permission_requestnotifications render as VK inline keyboards; taps come back viamessage_event
- Bun ≥ 1.0 (Node ≥ 18 should also work if you swap the shebang and build step)
- Claude Code ≥ 2.1.80
- A VK community (not a personal account) with a community access token that has scopes
messages,photos,docs,manage - VK Long Poll enabled on the community with events:
message_new,message_edit,message_reply,message_event,message_allow,message_deny,message_reaction_event
# 1) Clone into a local Claude Code marketplace
mkdir -p ~/.claude/plugins/marketplaces/local/plugins
cd ~/.claude/plugins/marketplaces/local/plugins
git clone https://github.com/nazbav/claude-code-vkontakte-channel.git vkontakte-channelCreate a minimal marketplace manifest at ~/.claude/plugins/marketplaces/local/.claude-plugin/marketplace.json:
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "local",
"description": "Local Claude Code plugins",
"owner": { "name": "you", "email": "you@example.com" },
"plugins": [
{
"name": "vkontakte",
"description": "VKontakte channel for Claude Code",
"category": "messaging",
"source": "./plugins/vkontakte-channel",
"author": { "name": "you" }
}
]
}Register the marketplace and install the plugin:
claude plugin marketplace add ~/.claude/plugins/marketplaces/local
claude plugin install vkontakte@localSet up the token:
mkdir -p ~/.claude/channels/vkontakte
cp ~/.claude/plugins/marketplaces/local/plugins/vkontakte-channel/.env.example \
~/.claude/channels/vkontakte/.env
$EDITOR ~/.claude/channels/vkontakte/.env # fill in VK_GROUP_TOKEN and VK_GROUP_IDEnable the required Long Poll events on your community (one-off, via API):
curl -s -X POST "https://api.vk.com/method/groups.setLongPollSettings" \
--data "group_id=<GROUP_ID>&v=5.199&access_token=<TOKEN>&api_version=5.199&enabled=1&message_new=1&message_edit=1&message_reply=1&message_event=1&message_allow=1&message_deny=1&message_reaction_event=1"Because local plugins aren't on Claude Code's approved-channels allowlist, you launch with the dev flag:
claude --dangerously-load-development-channels plugin:vkontakte@localOr alongside an allowlisted channel (e.g. Telegram):
claude --channels plugin:telegram@claude-plugins-official \
--dangerously-load-development-channels plugin:vkontakte@local- In the VK app or web, DM your community (any text message).
- The bot replies with a 6-character pairing code.
- In Claude Code, run the skill:
/vkontakte:access pair <code>
After that, your DMs to the community route straight into your Claude Code session as <channel source="vkontakte" chat_id="..." message_id="..." user="..." ts="..."> notifications, and Claude's replies come back to VK via the reply tool.
| Tool | What it does |
|---|---|
reply |
Send a message back. Chunks long text (>4096). Attaches images as VK photos (two-step upload), other files as VK documents. Optional reply_to for quote-reply. |
edit_message |
Edit a previously sent message (VK allows edits within 24h). Does not trigger push notifications — use a fresh reply for final completion so the user's device pings. |
react |
Add an emoji reaction from VK's fixed set: ❤ 🔥 👍 😁 😲 😢 🤔 😡 (reaction IDs 1–8). Custom emoji are rejected by the API. |
download_attachment |
Fetch a direct VK attachment URL into ~/.claude/channels/vkontakte/inbox/ and return the local path so Claude can Read it. |
Photos (auto-downloaded to inbox), documents, voice messages, audio, video (player URL only — VK doesn't expose direct mp4 without video.get), stickers, wall posts, links.
Skill built into the plugin — manages pairing, allowlists, and delivery settings by editing ~/.claude/channels/vkontakte/access.json. The channel server re-reads on every inbound.
/vkontakte:access — show status
/vkontakte:access pair <code> — approve a pending pairing
/vkontakte:access allow <userId> — add a VK user_id directly
/vkontakte:access remove <userId> — revoke
/vkontakte:access policy <mode> — pairing | allowlist | disabled
/vkontakte:access group add <peerId> — allow a VK group chat
/vkontakte:access set ackReaction 👍 — delivery/UX tweaks
Security note: the skill intentionally refuses access mutations that were requested through a channel message. Prompt-injection-safe by design.
| Feature | Telegram | VKontakte |
|---|---|---|
| Rich formatting (Markdown / MarkdownV2) | ✅ | ❌ (VK community bots send plain text only) |
| Reactions | ~60 emoji | 8 emoji (fixed VK set) |
| Video playable URL | Direct file_path |
Only player embed URL; direct mp4 needs video.get |
| Message edit window | Unlimited | 24 hours |
| File upload | One endpoint | Two-step: getMessagesUploadServer → POST → save |
.
├── .claude-plugin/plugin.json — plugin manifest
├── .mcp.json — MCP server registration
├── package.json — bun deps (@modelcontextprotocol/sdk, zod)
├── server.ts — the MCP server (~680 LOC)
├── skills/access/SKILL.md — /vkontakte:access skill
├── .env.example — token template (real .env lives in ~/.claude/channels/vkontakte/)
└── README.md
Apache-2.0. See LICENSE. Based on Anthropic's telegram channel plugin (Apache-2.0).