From aa0c441177c9d5ddfaaec14c2a48f5c1ae550b05 Mon Sep 17 00:00:00 2001 From: Sergey Goncharov Date: Mon, 15 Jun 2026 13:41:13 +0300 Subject: [PATCH] feat: add vk_groups_search and vk_groups_get_members tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - vk_groups_search: search communities by name with filters (type, country, city, sort) - vk_groups_get_members: get subscribers list with profile fields and role filters Includes null/undefined params fix (see #4). Tested: vk_groups_search returns 15 304 communities for "программирование"; vk_groups_get_members returns 11 000 members of group 27758718. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- src/index.js | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 26ebf9d..d470ba7 100644 --- a/src/index.js +++ b/src/index.js @@ -27,8 +27,9 @@ class VKClient { } async call(method, params = {}) { + const clean = Object.fromEntries(Object.entries(params).filter(([, v]) => v !== undefined && v !== null)); const body = new URLSearchParams({ - ...params, + ...clean, access_token: this.accessToken, v: this.apiVersion, }); @@ -62,6 +63,8 @@ class VKClient { // Groups groupsGet(params) { return this.call('groups.get', { ...params, extended: 1 }); } groupsGetById(params) { return this.call('groups.getById', params); } + groupsGetMembers(params) { return this.call('groups.getMembers', params); } + groupsSearch(params) { return this.call('groups.search', params); } // Friends friendsGet(params) { return this.call('friends.get', params); } @@ -234,6 +237,41 @@ const tools = [ required: ['image'], }, }, + { + name: 'vk_groups_search', + description: 'Search for VK communities by name and other criteria', + inputSchema: { + type: 'object', + properties: { + q: { type: 'string', description: 'Search query' }, + count: { type: 'number', description: 'Number of results (max 1000)' }, + offset: { type: 'number', description: 'Offset for pagination' }, + fields: { type: 'string', description: 'Additional community fields to return' }, + type: { type: 'string', description: 'Community type: group, page or event', enum: ['group', 'page', 'event'] }, + country_id: { type: 'number', description: 'Country ID to filter by' }, + city_id: { type: 'number', description: 'City ID to filter by' }, + future: { type: 'number', description: 'Filter future events: 1 — only future events', enum: [0, 1] }, + sort: { type: 'number', description: 'Sort order: 0 — default, 1 — by speed, 6 — by likes', enum: [0, 1, 6] }, + }, + required: ['q'], + }, + }, + { + name: 'vk_groups_get_members', + description: 'Get members (subscribers) of a VK community', + inputSchema: { + type: 'object', + properties: { + group_id: { type: 'string', description: 'Community ID or short name' }, + count: { type: 'number', description: 'Number of members to return (max 1000)' }, + offset: { type: 'number', description: 'Offset for pagination' }, + fields: { type: 'string', description: 'Additional profile fields to return (e.g. photo_200,online,sex,city)' }, + filter: { type: 'string', description: 'Filter: managers, editors, mods, advertisers, friends, unsure', enum: ['managers', 'editors', 'mods', 'advertisers', 'friends', 'unsure'] }, + sort: { type: 'string', description: 'Sort order: id_asc, id_desc, time_asc, time_desc', enum: ['id_asc', 'id_desc', 'time_asc', 'time_desc'] }, + }, + required: ['group_id'], + }, + }, { name: 'vk_groups_get', description: 'Get list of communities the user is a member of', @@ -398,6 +436,31 @@ async function handleToolCall(name, args) { break; } + case 'vk_groups_search': + result = await vk.groupsSearch({ + q: args.q, + count: args.count || 20, + offset: args.offset, + fields: args.fields, + type: args.type, + country_id: args.country_id, + city_id: args.city_id, + future: args.future, + sort: args.sort, + }); + break; + + case 'vk_groups_get_members': + result = await vk.groupsGetMembers({ + group_id: args.group_id, + count: args.count || 1000, + offset: args.offset, + fields: args.fields, + filter: args.filter, + sort: args.sort || 'id_asc', + }); + break; + case 'vk_groups_get': result = await vk.groupsGet({ user_id: args.user_id,