diff --git a/json-logs/samples/api/slackbot.skills.update.json b/json-logs/samples/api/slackbot.skills.update.json new file mode 100644 index 000000000..f1d48b821 --- /dev/null +++ b/json-logs/samples/api/slackbot.skills.update.json @@ -0,0 +1,47 @@ +{ + "ok": false, + "error": "", + "needed": "", + "provided": "", + "warning": "", + "invalid_mcp_servers": [ + { + "service_type": "", + "app_id": "A00000000", + "server_id": "" + } + ], + "response_metadata": { + "messages": [ + "" + ] + }, + "skill": { + "access": "", + "category": "", + "creator_id": "U00000000", + "date_created": 12345, + "date_updated": 12345, + "description": "", + "display_name": "", + "example_prompt": "", + "id": "F00000000", + "instructions": "", + "is_official": false, + "library_count": 12345, + "mcp_servers": [ + { + "service_type": "", + "app_id": "A00000000", + "server_id": "", + "display_name": "", + "is_available": false + } + ], + "name": "", + "permalink": "", + "type": "", + "usage_count": 12345, + "visibility": "" + } +} \ No newline at end of file diff --git a/metadata/web-api/rate_limit_tiers.json b/metadata/web-api/rate_limit_tiers.json index 5b62712fa..5e1072b03 100644 --- a/metadata/web-api/rate_limit_tiers.json +++ b/metadata/web-api/rate_limit_tiers.json @@ -298,6 +298,7 @@ "slackLists.update": "Tier2", "slackbot.skills.create": "Tier2", "slackbot.skills.info": "Tier3", + "slackbot.skills.update": "Tier3", "stars.add": "Tier2", "stars.list": "Tier3", "stars.remove": "Tier2", diff --git a/slack-api-client/src/main/java/com/slack/api/methods/AsyncMethodsClient.java b/slack-api-client/src/main/java/com/slack/api/methods/AsyncMethodsClient.java index d42e25f61..922fc856e 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/AsyncMethodsClient.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/AsyncMethodsClient.java @@ -131,6 +131,7 @@ import com.slack.api.methods.request.slack_lists.SlackListsUpdateRequest; import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsCreateRequest; import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsInfoRequest; +import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsUpdateRequest; import com.slack.api.methods.request.stars.StarsAddRequest; import com.slack.api.methods.request.stars.StarsListRequest; import com.slack.api.methods.request.stars.StarsRemoveRequest; @@ -287,6 +288,7 @@ import com.slack.api.methods.response.slack_lists.SlackListsUpdateResponse; import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsCreateResponse; import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsInfoResponse; +import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsUpdateResponse; import com.slack.api.methods.response.stars.StarsAddResponse; import com.slack.api.methods.response.stars.StarsListResponse; import com.slack.api.methods.response.stars.StarsRemoveResponse; @@ -1547,6 +1549,10 @@ CompletableFuture CompletableFuture slackbotSkillsInfo(RequestConfigurator req); + CompletableFuture slackbotSkillsUpdate(SlackbotSkillsUpdateRequest req); + + CompletableFuture slackbotSkillsUpdate(RequestConfigurator req); + // ------------------------------ // slackLists // ------------------------------ diff --git a/slack-api-client/src/main/java/com/slack/api/methods/Methods.java b/slack-api-client/src/main/java/com/slack/api/methods/Methods.java index 581c84000..6b480ba3d 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/Methods.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/Methods.java @@ -690,6 +690,7 @@ private Methods() { public static final String SLACKBOT_SKILLS_CREATE = "slackbot.skills.create"; public static final String SLACKBOT_SKILLS_INFO = "slackbot.skills.info"; + public static final String SLACKBOT_SKILLS_UPDATE = "slackbot.skills.update"; // ------------------------------ // slackLists diff --git a/slack-api-client/src/main/java/com/slack/api/methods/MethodsClient.java b/slack-api-client/src/main/java/com/slack/api/methods/MethodsClient.java index d7751caba..71bac3782 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/MethodsClient.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/MethodsClient.java @@ -147,6 +147,7 @@ import com.slack.api.methods.request.slack_lists.SlackListsUpdateRequest; import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsCreateRequest; import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsInfoRequest; +import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsUpdateRequest; import com.slack.api.methods.request.team.*; import com.slack.api.methods.request.team.external_teams.TeamExternalTeamsDisconnectRequest; import com.slack.api.methods.request.team.external_teams.TeamExternalTeamsListRequest; @@ -312,6 +313,7 @@ import com.slack.api.methods.response.slack_lists.SlackListsUpdateResponse; import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsCreateResponse; import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsInfoResponse; +import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsUpdateResponse; import com.slack.api.methods.response.stars.StarsAddResponse; import com.slack.api.methods.response.stars.StarsListResponse; import com.slack.api.methods.response.stars.StarsRemoveResponse; @@ -2682,6 +2684,11 @@ SlackbotSkillsCreateResponse slackbotSkillsCreate(RequestConfigurator req) throws IOException, SlackApiException; + SlackbotSkillsUpdateResponse slackbotSkillsUpdate(SlackbotSkillsUpdateRequest req) throws IOException, SlackApiException; + + SlackbotSkillsUpdateResponse slackbotSkillsUpdate(RequestConfigurator req) + throws IOException, SlackApiException; + // ------------------------------ // slackLists // ------------------------------ diff --git a/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java b/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java index d0309465a..637dfd1a3 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java @@ -446,6 +446,7 @@ public static void setRateLimitTier(String methodName, MethodsRateLimitTier tier setRateLimitTier(SLACKBOT_SKILLS_CREATE, Tier2); setRateLimitTier(SLACKBOT_SKILLS_INFO, Tier3); + setRateLimitTier(SLACKBOT_SKILLS_UPDATE, Tier3); setRateLimitTier(SLACKLISTS_ACCESS_DELETE, Tier3); setRateLimitTier(SLACKLISTS_ACCESS_SET, Tier3); diff --git a/slack-api-client/src/main/java/com/slack/api/methods/RequestFormBuilder.java b/slack-api-client/src/main/java/com/slack/api/methods/RequestFormBuilder.java index e44a0c25c..98b6ba975 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/RequestFormBuilder.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/RequestFormBuilder.java @@ -144,6 +144,7 @@ import com.slack.api.methods.request.slack_lists.SlackListsUpdateRequest; import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsCreateRequest; import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsInfoRequest; +import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsUpdateRequest; import com.slack.api.methods.request.stars.StarsAddRequest; import com.slack.api.methods.request.stars.StarsListRequest; import com.slack.api.methods.request.stars.StarsRemoveRequest; @@ -3041,6 +3042,20 @@ public static FormBody.Builder toForm(SlackbotSkillsInfoRequest req) { return form; } + public static FormBody.Builder toForm(SlackbotSkillsUpdateRequest req) { + FormBody.Builder form = new FormBody.Builder(); + setIfNotNull("skill_id", req.getSkillId(), form); + setIfNotNull("display_name", req.getDisplayName(), form); + setIfNotNull("instructions", req.getInstructions(), form); + setIfNotNull("description", req.getDescription(), form); + setIfNotNull("category", req.getCategory(), form); + setIfNotNull("example_prompt", req.getExamplePrompt(), form); + if (req.getMcpServers() != null) { + setIfNotNull("mcp_servers", GSON.toJson(req.getMcpServers()), form); + } + return form; + } + public static FormBody.Builder toForm(SlackListsAccessDeleteRequest req) { FormBody.Builder form = new FormBody.Builder(); setIfNotNull("list_id", req.getListId(), form); diff --git a/slack-api-client/src/main/java/com/slack/api/methods/impl/AsyncMethodsClientImpl.java b/slack-api-client/src/main/java/com/slack/api/methods/impl/AsyncMethodsClientImpl.java index 66fe0f23b..a97bc5bd7 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/impl/AsyncMethodsClientImpl.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/impl/AsyncMethodsClientImpl.java @@ -135,6 +135,7 @@ import com.slack.api.methods.request.slack_lists.SlackListsUpdateRequest; import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsCreateRequest; import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsInfoRequest; +import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsUpdateRequest; import com.slack.api.methods.request.stars.StarsAddRequest; import com.slack.api.methods.request.stars.StarsListRequest; import com.slack.api.methods.request.stars.StarsRemoveRequest; @@ -291,6 +292,7 @@ import com.slack.api.methods.response.slack_lists.SlackListsUpdateResponse; import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsCreateResponse; import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsInfoResponse; +import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsUpdateResponse; import com.slack.api.methods.response.stars.StarsAddResponse; import com.slack.api.methods.response.stars.StarsListResponse; import com.slack.api.methods.response.stars.StarsRemoveResponse; @@ -2767,6 +2769,16 @@ public CompletableFuture slackbotSkillsInfo(RequestC return slackbotSkillsInfo(req.configure(SlackbotSkillsInfoRequest.builder()).build()); } + @Override + public CompletableFuture slackbotSkillsUpdate(SlackbotSkillsUpdateRequest req) { + return executor.execute(SLACKBOT_SKILLS_UPDATE, toMap(req), () -> methods.slackbotSkillsUpdate(req)); + } + + @Override + public CompletableFuture slackbotSkillsUpdate(RequestConfigurator req) { + return slackbotSkillsUpdate(req.configure(SlackbotSkillsUpdateRequest.builder()).build()); + } + @Override public CompletableFuture slackListsAccessDelete(SlackListsAccessDeleteRequest req) { return executor.execute(SLACKLISTS_ACCESS_DELETE, toMap(req), () -> methods.slackListsAccessDelete(req)); diff --git a/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java b/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java index 795962eee..c66c533b0 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java @@ -145,6 +145,7 @@ import com.slack.api.methods.request.slack_lists.SlackListsUpdateRequest; import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsCreateRequest; import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsInfoRequest; +import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsUpdateRequest; import com.slack.api.methods.request.stars.StarsAddRequest; import com.slack.api.methods.request.stars.StarsListRequest; import com.slack.api.methods.request.stars.StarsRemoveRequest; @@ -314,6 +315,7 @@ import com.slack.api.methods.response.slack_lists.SlackListsUpdateResponse; import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsCreateResponse; import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsInfoResponse; +import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsUpdateResponse; import com.slack.api.methods.response.stars.StarsAddResponse; import com.slack.api.methods.response.stars.StarsListResponse; import com.slack.api.methods.response.stars.StarsRemoveResponse; @@ -3445,6 +3447,16 @@ public SlackbotSkillsInfoResponse slackbotSkillsInfo(RequestConfigurator req) throws IOException, SlackApiException { + return slackbotSkillsUpdate(req.configure(SlackbotSkillsUpdateRequest.builder()).build()); + } + @Override public SlackListsAccessDeleteResponse slackListsAccessDelete(SlackListsAccessDeleteRequest req) throws IOException, SlackApiException { return postFormWithTokenAndParseResponse(toForm(req), Methods.SLACKLISTS_ACCESS_DELETE, getToken(req), SlackListsAccessDeleteResponse.class); diff --git a/slack-api-client/src/main/java/com/slack/api/methods/request/slackbot/skills/SlackbotSkillsUpdateRequest.java b/slack-api-client/src/main/java/com/slack/api/methods/request/slackbot/skills/SlackbotSkillsUpdateRequest.java new file mode 100644 index 000000000..e8e4a477e --- /dev/null +++ b/slack-api-client/src/main/java/com/slack/api/methods/request/slackbot/skills/SlackbotSkillsUpdateRequest.java @@ -0,0 +1,58 @@ +package com.slack.api.methods.request.slackbot.skills; + +import com.slack.api.methods.SlackApiRequest; +import com.slack.api.model.slackbot.SkillMcpServer; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +/** + * https://docs.slack.dev/reference/methods/slackbot.skills.update + */ +@Data +@Builder +public class SlackbotSkillsUpdateRequest implements SlackApiRequest { + + /** + * Authentication token bearing required scopes. Tokens should be passed as an HTTP Authorization header or alternatively, as a POST parameter. + */ + private String token; + + /** + * Skill to change. + */ + private String skillId; + + /** + * Human-readable label. Max 255 characters. + */ + private String displayName; + + /** + * Markdown that replaces the whole document. + */ + private String instructions; + + /** + * When Slackbot should use the skill. Max 400 characters. Send an empty string to clear. + */ + private String description; + + /** + * One of the skill categories. Send an empty string to clear. + * Acceptable values: `communication`, `customer_support`, `data_and_analytics`, `engineering`, `product_management`, `productivity`, `professional_development`, `project_management`, `sales`, `system`, `team_management`, `other` + */ + private String category; + + /** + * Max 200 characters. May contain `{skill}`. Send an empty string to clear. + */ + private String examplePrompt; + + /** + * Apps the skill needs. Replaces the whole list; send `[]` to clear. + */ + private List mcpServers; + +} diff --git a/slack-api-client/src/main/java/com/slack/api/methods/response/slackbot/skills/SlackbotSkillsUpdateResponse.java b/slack-api-client/src/main/java/com/slack/api/methods/response/slackbot/skills/SlackbotSkillsUpdateResponse.java new file mode 100644 index 000000000..533316baa --- /dev/null +++ b/slack-api-client/src/main/java/com/slack/api/methods/response/slackbot/skills/SlackbotSkillsUpdateResponse.java @@ -0,0 +1,25 @@ +package com.slack.api.methods.response.slackbot.skills; + +import com.slack.api.methods.SlackApiTextResponse; +import com.slack.api.model.ResponseMetadata; +import com.slack.api.model.slackbot.Skill; +import com.slack.api.model.slackbot.SkillMcpServer; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Data +public class SlackbotSkillsUpdateResponse implements SlackApiTextResponse { + + private boolean ok; + private String warning; + private String error; + private String needed; + private String provided; + private transient Map> httpResponseHeaders; + + private List invalidMcpServers; + private ResponseMetadata responseMetadata; + private Skill skill; +} diff --git a/slack-api-client/src/test/java/test_locally/api/MethodsTest.java b/slack-api-client/src/test/java/test_locally/api/MethodsTest.java index 72f4fbc8b..e0d812989 100644 --- a/slack-api-client/src/test/java/test_locally/api/MethodsTest.java +++ b/slack-api-client/src/test/java/test_locally/api/MethodsTest.java @@ -19,8 +19,8 @@ public class MethodsTest { public void verifyTheCoverage() { // https://docs.slack.dev/reference/methods // var methodNames = [].slice.call(document.getElementsByClassName('apiReferenceFilterableList__listItemLink')).map(e => e.href.replace("https://docs.slack.dev/reference/methods/", ""));console.log(methodNames.toString());console.log(methodNames.length); - // 315 endpoints as of November 11, 2026 (apps.user.connection.bulkUpdate and requestAuth added ahead of their docs.slack.dev pages) - String methods = "admin.analytics.getFile,admin.apps.activities.list,admin.apps.approve,admin.apps.clearResolution,admin.apps.restrict,admin.apps.uninstall,admin.apps.approved.list,admin.apps.config.lookup,admin.apps.config.set,admin.apps.requests.cancel,admin.apps.requests.list,admin.apps.restricted.list,admin.audit.anomaly.allow.getItem,admin.audit.anomaly.allow.updateItem,admin.auth.policy.assignEntities,admin.auth.policy.getEntities,admin.auth.policy.removeEntities,admin.barriers.create,admin.barriers.delete,admin.barriers.list,admin.barriers.update,admin.conversations.archive,admin.conversations.bulkArchive,admin.conversations.bulkDelete,admin.conversations.bulkMove,admin.conversations.convertToPrivate,admin.conversations.convertToPublic,admin.conversations.create,admin.conversations.createForObjects,admin.conversations.delete,admin.conversations.disconnectShared,admin.conversations.getConversationPrefs,admin.conversations.getCustomRetention,admin.conversations.getTeams,admin.conversations.invite,admin.conversations.linkObjects,admin.conversations.lookup,admin.conversations.removeCustomRetention,admin.conversations.rename,admin.conversations.search,admin.conversations.setConversationPrefs,admin.conversations.setCustomRetention,admin.conversations.setTeams,admin.conversations.unarchive,admin.conversations.unlinkObjects,admin.conversations.ekm.listOriginalConnectedChannelInfo,admin.conversations.restrictAccess.addGroup,admin.conversations.restrictAccess.listGroups,admin.conversations.restrictAccess.removeGroup,admin.emoji.add,admin.emoji.addAlias,admin.emoji.list,admin.emoji.remove,admin.emoji.rename,admin.functions.list,admin.functions.permissions.lookup,admin.functions.permissions.set,admin.inviteRequests.approve,admin.inviteRequests.deny,admin.inviteRequests.list,admin.inviteRequests.approved.list,admin.inviteRequests.denied.list,admin.roles.addAssignments,admin.roles.listAssignments,admin.roles.removeAssignments,admin.teams.admins.list,admin.teams.create,admin.teams.list,admin.teams.owners.list,admin.teams.settings.info,admin.teams.settings.setDefaultChannels,admin.teams.settings.setDescription,admin.teams.settings.setDiscoverability,admin.teams.settings.setIcon,admin.teams.settings.setName,admin.usergroups.addChannels,admin.usergroups.addTeams,admin.usergroups.listChannels,admin.usergroups.removeChannels,admin.users.assign,admin.users.getExpiration,admin.users.invite,admin.users.list,admin.users.remove,admin.users.setAdmin,admin.users.setExpiration,admin.users.setOwner,admin.users.setRegular,admin.users.session.clearSettings,admin.users.session.getSettings,admin.users.session.invalidate,admin.users.session.list,admin.users.session.reset,admin.users.session.resetBulk,admin.users.session.setSettings,admin.users.unsupportedVersions.export,admin.workflows.collaborators.add,admin.workflows.collaborators.remove,admin.workflows.permissions.lookup,admin.workflows.search,admin.workflows.unpublish,admin.workflows.triggers.types.permissions.lookup,admin.workflows.triggers.types.permissions.set,api.test,apps.activities.list,apps.auth.external.delete,apps.auth.external.get,apps.connections.open,apps.datastore.bulkDelete,apps.datastore.bulkGet,apps.datastore.bulkPut,apps.datastore.count,apps.datastore.delete,apps.datastore.get,apps.datastore.put,apps.datastore.query,apps.datastore.update,apps.event.authorizations.list,apps.manifest.create,apps.manifest.delete,apps.manifest.export,apps.manifest.update,apps.manifest.validate,apps.uninstall,apps.user.connection.bulkUpdate,apps.user.connection.requestAuth,apps.user.connection.update,assistant.search.context,assistant.threads.setStatus,assistant.threads.setSuggestedPrompts,assistant.threads.setTitle,auth.revoke,auth.test,auth.teams.list,blocks.validate,bookmarks.add,bookmarks.edit,bookmarks.list,bookmarks.remove,bots.info,calls.add,calls.end,calls.info,calls.update,calls.participants.add,calls.participants.remove,canvases.access.delete,canvases.access.set,canvases.create,canvases.delete,canvases.edit,canvases.getContent,canvases.sections.lookup,channels.mark,chat.appendStream,chat.delete,chat.deleteScheduledMessage,chat.getPermalink,chat.meMessage,chat.postEphemeral,chat.postMessage,chat.scheduleMessage,chat.startStream,chat.stopStream,chat.unfurl,chat.update,chat.scheduledMessages.list,conversations.acceptSharedInvite,conversations.approveSharedInvite,conversations.archive,conversations.close,conversations.create,conversations.declineSharedInvite,conversations.history,conversations.info,conversations.invite,conversations.inviteShared,conversations.join,conversations.kick,conversations.leave,conversations.list,conversations.listConnectInvites,conversations.mark,conversations.members,conversations.open,conversations.rename,conversations.replies,conversations.setPurpose,conversations.setTopic,conversations.unarchive,conversations.canvases.create,conversations.externalInvitePermissions.set,conversations.requestSharedInvite.approve,conversations.requestSharedInvite.deny,conversations.requestSharedInvite.list,dialog.open,dnd.endDnd,dnd.endSnooze,dnd.info,dnd.setSnooze,dnd.teamInfo,emoji.list,files.comments.delete,files.completeUploadExternal,files.delete,files.getUploadURLExternal,files.info,files.list,files.revokePublicURL,files.sharedPublicURL,files.upload,files.remote.add,files.remote.info,files.remote.list,files.remote.remove,files.remote.share,files.remote.update,functions.completeError,functions.completeSuccess,functions.distributions.permissions.add,functions.distributions.permissions.list,functions.distributions.permissions.remove,functions.distributions.permissions.set,functions.workflows.steps.list,functions.workflows.steps.responses.export,groups.mark,migration.exchange,oauth.access,oauth.v2.access,oauth.v2.exchange,openid.connect.token,openid.connect.userInfo,pins.add,pins.list,pins.remove,reactions.add,reactions.get,reactions.list,reactions.remove,reminders.add,reminders.complete,reminders.delete,reminders.info,reminders.list,rtm.connect,rtm.start,search.all,search.files,search.messages,slackbot.skills.create,slackbot.skills.info,slackLists.access.delete,slackLists.access.set,slackLists.create,slackLists.download.get,slackLists.download.start,slackLists.items.create,slackLists.items.delete,slackLists.items.deleteMultiple,slackLists.items.info,slackLists.items.list,slackLists.items.update,slackLists.update,stars.add,stars.list,stars.remove,team.accessLogs,team.billableInfo,team.info,team.integrationLogs,team.billing.info,team.externalTeams.disconnect,team.externalTeams.list,team.preferences.list,team.profile.get,tooling.tokens.rotate,usergroups.create,usergroups.disable,usergroups.enable,usergroups.list,usergroups.update,usergroups.users.list,usergroups.users.update,users.conversations,users.deletePhoto,users.getPresence,users.identity,users.info,users.list,users.lookupByEmail,users.setActive,users.setPhoto,users.setPresence,users.discoverableContacts.lookup,users.profile.get,users.profile.set,views.open,views.publish,views.push,views.update,workflows.featured.add,workflows.featured.list,workflows.featured.remove,workflows.featured.set,workflows.stepCompleted,workflows.stepFailed,workflows.updateStep,workflows.triggers.permissions.add,workflows.triggers.permissions.list,workflows.triggers.permissions.remove,workflows.triggers.permissions.set,im.list,im.mark,mpim.list,mpim.mark"; + // 316 endpoints as of November 11, 2026 (apps.user.connection.bulkUpdate and requestAuth added ahead of their docs.slack.dev pages) + String methods = "admin.analytics.getFile,admin.apps.activities.list,admin.apps.approve,admin.apps.clearResolution,admin.apps.restrict,admin.apps.uninstall,admin.apps.approved.list,admin.apps.config.lookup,admin.apps.config.set,admin.apps.requests.cancel,admin.apps.requests.list,admin.apps.restricted.list,admin.audit.anomaly.allow.getItem,admin.audit.anomaly.allow.updateItem,admin.auth.policy.assignEntities,admin.auth.policy.getEntities,admin.auth.policy.removeEntities,admin.barriers.create,admin.barriers.delete,admin.barriers.list,admin.barriers.update,admin.conversations.archive,admin.conversations.bulkArchive,admin.conversations.bulkDelete,admin.conversations.bulkMove,admin.conversations.convertToPrivate,admin.conversations.convertToPublic,admin.conversations.create,admin.conversations.createForObjects,admin.conversations.delete,admin.conversations.disconnectShared,admin.conversations.getConversationPrefs,admin.conversations.getCustomRetention,admin.conversations.getTeams,admin.conversations.invite,admin.conversations.linkObjects,admin.conversations.lookup,admin.conversations.removeCustomRetention,admin.conversations.rename,admin.conversations.search,admin.conversations.setConversationPrefs,admin.conversations.setCustomRetention,admin.conversations.setTeams,admin.conversations.unarchive,admin.conversations.unlinkObjects,admin.conversations.ekm.listOriginalConnectedChannelInfo,admin.conversations.restrictAccess.addGroup,admin.conversations.restrictAccess.listGroups,admin.conversations.restrictAccess.removeGroup,admin.emoji.add,admin.emoji.addAlias,admin.emoji.list,admin.emoji.remove,admin.emoji.rename,admin.functions.list,admin.functions.permissions.lookup,admin.functions.permissions.set,admin.inviteRequests.approve,admin.inviteRequests.deny,admin.inviteRequests.list,admin.inviteRequests.approved.list,admin.inviteRequests.denied.list,admin.roles.addAssignments,admin.roles.listAssignments,admin.roles.removeAssignments,admin.teams.admins.list,admin.teams.create,admin.teams.list,admin.teams.owners.list,admin.teams.settings.info,admin.teams.settings.setDefaultChannels,admin.teams.settings.setDescription,admin.teams.settings.setDiscoverability,admin.teams.settings.setIcon,admin.teams.settings.setName,admin.usergroups.addChannels,admin.usergroups.addTeams,admin.usergroups.listChannels,admin.usergroups.removeChannels,admin.users.assign,admin.users.getExpiration,admin.users.invite,admin.users.list,admin.users.remove,admin.users.setAdmin,admin.users.setExpiration,admin.users.setOwner,admin.users.setRegular,admin.users.session.clearSettings,admin.users.session.getSettings,admin.users.session.invalidate,admin.users.session.list,admin.users.session.reset,admin.users.session.resetBulk,admin.users.session.setSettings,admin.users.unsupportedVersions.export,admin.workflows.collaborators.add,admin.workflows.collaborators.remove,admin.workflows.permissions.lookup,admin.workflows.search,admin.workflows.unpublish,admin.workflows.triggers.types.permissions.lookup,admin.workflows.triggers.types.permissions.set,api.test,apps.activities.list,apps.auth.external.delete,apps.auth.external.get,apps.connections.open,apps.datastore.bulkDelete,apps.datastore.bulkGet,apps.datastore.bulkPut,apps.datastore.count,apps.datastore.delete,apps.datastore.get,apps.datastore.put,apps.datastore.query,apps.datastore.update,apps.event.authorizations.list,apps.manifest.create,apps.manifest.delete,apps.manifest.export,apps.manifest.update,apps.manifest.validate,apps.uninstall,apps.user.connection.bulkUpdate,apps.user.connection.requestAuth,apps.user.connection.update,assistant.search.context,assistant.threads.setStatus,assistant.threads.setSuggestedPrompts,assistant.threads.setTitle,auth.revoke,auth.test,auth.teams.list,blocks.validate,bookmarks.add,bookmarks.edit,bookmarks.list,bookmarks.remove,bots.info,calls.add,calls.end,calls.info,calls.update,calls.participants.add,calls.participants.remove,canvases.access.delete,canvases.access.set,canvases.create,canvases.delete,canvases.edit,canvases.getContent,canvases.sections.lookup,channels.mark,chat.appendStream,chat.delete,chat.deleteScheduledMessage,chat.getPermalink,chat.meMessage,chat.postEphemeral,chat.postMessage,chat.scheduleMessage,chat.startStream,chat.stopStream,chat.unfurl,chat.update,chat.scheduledMessages.list,conversations.acceptSharedInvite,conversations.approveSharedInvite,conversations.archive,conversations.close,conversations.create,conversations.declineSharedInvite,conversations.history,conversations.info,conversations.invite,conversations.inviteShared,conversations.join,conversations.kick,conversations.leave,conversations.list,conversations.listConnectInvites,conversations.mark,conversations.members,conversations.open,conversations.rename,conversations.replies,conversations.setPurpose,conversations.setTopic,conversations.unarchive,conversations.canvases.create,conversations.externalInvitePermissions.set,conversations.requestSharedInvite.approve,conversations.requestSharedInvite.deny,conversations.requestSharedInvite.list,dialog.open,dnd.endDnd,dnd.endSnooze,dnd.info,dnd.setSnooze,dnd.teamInfo,emoji.list,files.comments.delete,files.completeUploadExternal,files.delete,files.getUploadURLExternal,files.info,files.list,files.revokePublicURL,files.sharedPublicURL,files.upload,files.remote.add,files.remote.info,files.remote.list,files.remote.remove,files.remote.share,files.remote.update,functions.completeError,functions.completeSuccess,functions.distributions.permissions.add,functions.distributions.permissions.list,functions.distributions.permissions.remove,functions.distributions.permissions.set,functions.workflows.steps.list,functions.workflows.steps.responses.export,groups.mark,migration.exchange,oauth.access,oauth.v2.access,oauth.v2.exchange,openid.connect.token,openid.connect.userInfo,pins.add,pins.list,pins.remove,reactions.add,reactions.get,reactions.list,reactions.remove,reminders.add,reminders.complete,reminders.delete,reminders.info,reminders.list,rtm.connect,rtm.start,search.all,search.files,search.messages,slackbot.skills.create,slackbot.skills.info,slackbot.skills.update,slackLists.access.delete,slackLists.access.set,slackLists.create,slackLists.download.get,slackLists.download.start,slackLists.items.create,slackLists.items.delete,slackLists.items.deleteMultiple,slackLists.items.info,slackLists.items.list,slackLists.items.update,slackLists.update,stars.add,stars.list,stars.remove,team.accessLogs,team.billableInfo,team.info,team.integrationLogs,team.billing.info,team.externalTeams.disconnect,team.externalTeams.list,team.preferences.list,team.profile.get,tooling.tokens.rotate,usergroups.create,usergroups.disable,usergroups.enable,usergroups.list,usergroups.update,usergroups.users.list,usergroups.users.update,users.conversations,users.deletePhoto,users.getPresence,users.identity,users.info,users.list,users.lookupByEmail,users.setActive,users.setPhoto,users.setPresence,users.discoverableContacts.lookup,users.profile.get,users.profile.set,views.open,views.publish,views.push,views.update,workflows.featured.add,workflows.featured.list,workflows.featured.remove,workflows.featured.set,workflows.stepCompleted,workflows.stepFailed,workflows.updateStep,workflows.triggers.permissions.add,workflows.triggers.permissions.list,workflows.triggers.permissions.remove,workflows.triggers.permissions.set,im.list,im.mark,mpim.list,mpim.mark"; final List existingMethods = new ArrayList<>(); for (Field f : Methods.class.getDeclaredFields()) { int modifiers = f.getModifiers(); diff --git a/slack-api-client/src/test/java/test_locally/api/methods/RequestFormBuilderTest.java b/slack-api-client/src/test/java/test_locally/api/methods/RequestFormBuilderTest.java index 05ee3116b..717afdd2c 100644 --- a/slack-api-client/src/test/java/test_locally/api/methods/RequestFormBuilderTest.java +++ b/slack-api-client/src/test/java/test_locally/api/methods/RequestFormBuilderTest.java @@ -6,6 +6,7 @@ import com.slack.api.methods.request.calls.CallsAddRequest; import com.slack.api.methods.request.chat.ChatPostMessageRequest; import com.slack.api.methods.request.chat.ChatUnfurlRequest; +import com.slack.api.methods.request.slackbot.skills.SlackbotSkillsUpdateRequest; import com.slack.api.methods.request.team.TeamInfoRequest; import com.slack.api.model.Attachment; import com.slack.api.model.CallParticipant; @@ -13,6 +14,7 @@ import com.slack.api.model.block.composition.OptionObject; import com.slack.api.model.block.composition.PlainTextObject; import com.slack.api.model.block.element.OverflowMenuElement; +import com.slack.api.model.slackbot.SkillMcpServer; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -22,6 +24,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -45,6 +48,31 @@ public void teamInfoSlackbotAvailability() { } } + @Test + public void slackbotSkillsUpdateMcpServers() { + FormBody omitted = RequestFormBuilder.toForm(SlackbotSkillsUpdateRequest.builder() + .skillId("F0123ABCD").build()).build(); + assertThat(omitted.size(), is(1)); + assertThat(omitted.name(0), is("skill_id")); + + FormBody cleared = RequestFormBuilder.toForm(SlackbotSkillsUpdateRequest.builder() + .skillId("F0123ABCD").mcpServers(Collections.emptyList()).build()).build(); + assertThat(cleared.size(), is(2)); + assertThat(cleared.name(1), is("mcp_servers")); + assertThat(cleared.value(1), is("[]")); + + FormBody declared = RequestFormBuilder.toForm(SlackbotSkillsUpdateRequest.builder() + .skillId("F0123ABCD") + .mcpServers(Arrays.asList(SkillMcpServer.builder() + .serviceType("app") + .appId("A0123ABCD") + .serverId("Amcp0456EFGH") + .build())) + .build()).build(); + assertThat(declared.name(1), is("mcp_servers")); + assertThat(declared.value(1), is("[{\"service_type\":\"app\",\"app_id\":\"A0123ABCD\",\"server_id\":\"Amcp0456EFGH\"}]")); + } + @Test public void testBlocksJsonSerialization() { // GIVEN diff --git a/slack-api-client/src/test/java/test_locally/api/methods/SlackbotSkillsTest.java b/slack-api-client/src/test/java/test_locally/api/methods/SlackbotSkillsTest.java index 20a78c2f2..91b4d483d 100644 --- a/slack-api-client/src/test/java/test_locally/api/methods/SlackbotSkillsTest.java +++ b/slack-api-client/src/test/java/test_locally/api/methods/SlackbotSkillsTest.java @@ -4,6 +4,7 @@ import com.slack.api.SlackConfig; import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsCreateResponse; import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsInfoResponse; +import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsUpdateResponse; import com.slack.api.model.slackbot.SkillMcpServer; import com.slack.api.util.json.GsonFactory; import org.junit.After; @@ -12,6 +13,7 @@ import util.MockSlackApiServer; import java.util.Arrays; +import java.util.Collections; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; @@ -56,6 +58,15 @@ public void test() throws Exception { assertThat(slack.methods(ValidToken).slackbotSkillsInfo(r -> r .skillId("F0123ABCD") ).isOk(), is(true)); + assertThat(slack.methods(ValidToken).slackbotSkillsUpdate(r -> r + .skillId("F0123ABCD") + .displayName("Daily priorities") + .instructions("# Purpose\nSuggest the three most important things to work on today.") + .description("") + .category("") + .examplePrompt("") + .mcpServers(Collections.emptyList()) + ).isOk(), is(true)); } @Test @@ -79,6 +90,15 @@ public void test_async() throws Exception { assertThat(slack.methodsAsync(ValidToken).slackbotSkillsInfo(r -> r .skillId("F0123ABCD") ).get().isOk(), is(true)); + assertThat(slack.methodsAsync(ValidToken).slackbotSkillsUpdate(r -> r + .skillId("F0123ABCD") + .displayName("Daily priorities") + .instructions("# Purpose\nSuggest the three most important things to work on today.") + .description("") + .category("") + .examplePrompt("") + .mcpServers(Collections.emptyList()) + ).get().isOk(), is(true)); } @Test @@ -186,4 +206,52 @@ public void slackbotSkillsInfoResponse() { assertThat(response.getSkill().getMcpServers().get(0).getDisplayName(), is("Google Calendar")); assertThat(response.getSkill().getMcpServers().get(0).getIsAvailable(), is(true)); } + + @Test + public void slackbotSkillsUpdateResponse() { + SlackConfig strict = new SlackConfig(); + strict.setFailOnUnknownProperties(true); + + String json = "{" + + " \"ok\": true," + + " \"skill\": {" + + " \"id\": \"F0123ABCD\"," + + " \"type\": \"canvas\"," + + " \"display_name\": \"Daily priorities\"," + + " \"name\": null," + + " \"description\": \"Suggests priorities for the day.\"," + + " \"category\": \"productivity\"," + + " \"example_prompt\": \"Run {skill} for today\"," + + " \"instructions\": null," + + " \"visibility\": \"invite_only\"," + + " \"is_official\": false," + + " \"access\": \"owner\"," + + " \"mcp_servers\": [" + + " {" + + " \"service_type\": \"app\"," + + " \"display_name\": \"Google Calendar\"," + + " \"is_available\": true," + + " \"app_id\": \"A0123ABCD\"," + + " \"server_id\": \"Amcp0456EFGH\"" + + " }" + + " ]," + + " \"usage_count\": 0," + + " \"library_count\": 0," + + " \"creator_id\": \"U0123ABCD\"," + + " \"date_created\": 1794467151," + + " \"date_updated\": 1794467151," + + " \"permalink\": \"https://example.slack.com/skills/F0123ABCD\"" + + " }" + + "}"; + SlackbotSkillsUpdateResponse response = GsonFactory.createSnakeCase(strict).fromJson(json, SlackbotSkillsUpdateResponse.class); + assertThat(response.isOk(), is(true)); + assertThat(response.getSkill().getDescription(), is("Suggests priorities for the day.")); + assertThat(response.getSkill().getInstructions(), is(nullValue())); + assertThat(response.getSkill().getDateUpdated(), is(1794467151)); + assertThat(response.getSkill().getMcpServers().get(0).getServiceType(), is("app")); + assertThat(response.getSkill().getMcpServers().get(0).getAppId(), is("A0123ABCD")); + assertThat(response.getSkill().getMcpServers().get(0).getServerId(), is("Amcp0456EFGH")); + assertThat(response.getSkill().getMcpServers().get(0).getDisplayName(), is("Google Calendar")); + assertThat(response.getSkill().getMcpServers().get(0).getIsAvailable(), is(true)); + } } diff --git a/slack-api-client/src/test/java/test_with_remote_apis/methods/slackbot_skills_Test.java b/slack-api-client/src/test/java/test_with_remote_apis/methods/slackbot_skills_Test.java index 3a91b1bd0..e1946b67b 100644 --- a/slack-api-client/src/test/java/test_with_remote_apis/methods/slackbot_skills_Test.java +++ b/slack-api-client/src/test/java/test_with_remote_apis/methods/slackbot_skills_Test.java @@ -6,8 +6,10 @@ import com.slack.api.methods.response.canvases.CanvasesCreateResponse; import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsCreateResponse; import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsInfoResponse; +import com.slack.api.methods.response.slackbot.skills.SlackbotSkillsUpdateResponse; import com.slack.api.model.canvas.CanvasDocumentContent; import com.slack.api.model.slackbot.Skill; +import com.slack.api.model.slackbot.SkillMcpServer; import config.Constants; import config.SlackTestConfig; import lombok.extern.slf4j.Slf4j; @@ -17,6 +19,8 @@ import org.junit.Test; import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -65,6 +69,23 @@ public void skills() throws Exception { SlackbotSkillsInfoResponse info = client.slackbotSkillsInfo(r -> r.skillId(skillId)); assertThat(info.getError(), is(nullValue())); assertThat(info.getSkill().getInstructions(), is(notNullValue())); + + SlackbotSkillsUpdateResponse update = client.slackbotSkillsUpdate(r -> r + .skillId(skillId) + .description("Updated test skill for SDK development.") + .mcpServers(Collections.emptyList())); + assertThat(update.getError(), is(nullValue())); + assertThat(update.getSkill().getDescription(), is("Updated test skill for SDK development.")); + + SlackbotSkillsUpdateResponse invalidUpdate = client.slackbotSkillsUpdate(r -> r + .skillId(skillId) + .mcpServers(Arrays.asList(SkillMcpServer.builder() + .serviceType("app") + .appId("A0123ABCD") + .serverId("Amcp0456EFGH") + .build()))); + assertThat(invalidUpdate.getError(), is("mcp_server_not_found")); + assertThat(invalidUpdate.getInvalidMcpServers().get(0).getAppId(), is("A0123ABCD")); } finally { deleteSkill(client, botToken, skillId); }