Skip to content

Commit d7b31aa

Browse files
authored
feat(server): Support removing tools, prompts and resources (#85)
* Add removing APIs for tools, prompts and resources * Add remove tests * API dump
1 parent c3efd65 commit d7b31aa

File tree

3 files changed

+652
-0
lines changed

3 files changed

+652
-0
lines changed

api/kotlin-sdk.api

+6
Original file line numberDiff line numberDiff line change
@@ -2794,6 +2794,12 @@ public class io/modelcontextprotocol/kotlin/sdk/server/Server : io/modelcontextp
27942794
public final fun onClose (Lkotlin/jvm/functions/Function0;)V
27952795
public final fun onInitalized (Lkotlin/jvm/functions/Function0;)V
27962796
public final fun ping (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
2797+
public final fun removePrompt (Ljava/lang/String;)Z
2798+
public final fun removePrompts (Ljava/util/List;)I
2799+
public final fun removeResource (Ljava/lang/String;)Z
2800+
public final fun removeResources (Ljava/util/List;)I
2801+
public final fun removeTool (Ljava/lang/String;)Z
2802+
public final fun removeTools (Ljava/util/List;)I
27972803
public final fun sendLoggingMessage (Lio/modelcontextprotocol/kotlin/sdk/LoggingMessageNotification;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
27982804
public final fun sendPromptListChanged (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
27992805
public final fun sendResourceListChanged (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;

src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt

+162
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,60 @@ public open class Server(
173173
}
174174
}
175175

176+
/**
177+
* Removes a single tool by name.
178+
*
179+
* @param name The name of the tool to remove.
180+
* @return True if the tool was removed, false if it wasn't found.
181+
* @throws IllegalStateException If the server does not support tools.
182+
*/
183+
public fun removeTool(name: String): Boolean {
184+
if (capabilities.tools == null) {
185+
logger.error { "Failed to remove tool '$name': Server does not support tools capability" }
186+
throw IllegalStateException("Server does not support tools capability.")
187+
}
188+
logger.info { "Removing tool: $name" }
189+
val removed = tools.remove(name) != null
190+
logger.debug {
191+
if (removed) {
192+
"Tool removed: $name"
193+
} else {
194+
"Tool not found: $name"
195+
}
196+
}
197+
return removed
198+
}
199+
200+
/**
201+
* Removes multiple tools at once.
202+
*
203+
* @param toolNames A list of tool names to remove.
204+
* @return The number of tools that were successfully removed.
205+
* @throws IllegalStateException If the server does not support tools.
206+
*/
207+
public fun removeTools(toolNames: List<String>): Int {
208+
if (capabilities.tools == null) {
209+
logger.error { "Failed to remove tools: Server does not support tools capability" }
210+
throw IllegalStateException("Server does not support tools capability.")
211+
}
212+
logger.info { "Removing ${toolNames.size} tools" }
213+
var removedCount = 0
214+
for (name in toolNames) {
215+
logger.debug { "Removing tool: $name" }
216+
if (tools.remove(name) != null) {
217+
removedCount++
218+
}
219+
}
220+
logger.info {
221+
if (removedCount > 0) {
222+
"Removed $removedCount tools"
223+
} else {
224+
"No tools were removed"
225+
}
226+
}
227+
return removedCount
228+
}
229+
176230
/**
177231
* Registers a single prompt. The prompt can then be retrieved by the client.
178232
*
@@ -226,6 +280,60 @@ public open class Server(
226280
}
227281
}
228282

283+
/**
284+
* Removes a single prompt by name.
285+
*
286+
* @param name The name of the prompt to remove.
287+
* @return True if the prompt was removed, false if it wasn't found.
288+
* @throws IllegalStateException If the server does not support prompts.
289+
*/
290+
public fun removePrompt(name: String): Boolean {
291+
if (capabilities.prompts == null) {
292+
logger.error { "Failed to remove prompt '$name': Server does not support prompts capability" }
293+
throw IllegalStateException("Server does not support prompts capability.")
294+
}
295+
logger.info { "Removing prompt: $name" }
296+
val removed = prompts.remove(name) != null
297+
logger.debug {
298+
if (removed) {
299+
"Prompt removed: $name"
300+
} else {
301+
"Prompt not found: $name"
302+
}
303+
}
304+
return removed
305+
}
306+
307+
/**
308+
* Removes multiple prompts at once.
309+
*
310+
* @param promptNames A list of prompt names to remove.
311+
* @return The number of prompts that were successfully removed.
312+
* @throws IllegalStateException If the server does not support prompts.
313+
*/
314+
public fun removePrompts(promptNames: List<String>): Int {
315+
if (capabilities.prompts == null) {
316+
logger.error { "Failed to remove prompts: Server does not support prompts capability" }
317+
throw IllegalStateException("Server does not support prompts capability.")
318+
}
319+
logger.info { "Removing ${promptNames.size} prompts" }
320+
var removedCount = 0
321+
for (name in promptNames) {
322+
logger.debug { "Removing prompt: $name" }
323+
if (prompts.remove(name) != null) {
324+
removedCount++
325+
}
326+
}
327+
logger.info {
328+
if (removedCount > 0) {
329+
"Removed $removedCount prompts"
330+
} else {
331+
"No prompts were removed"
332+
}
333+
}
334+
return removedCount
335+
}
336+
229337
/**
230338
* Registers a single resource. The resource content can then be read by the client.
231339
*
@@ -269,6 +377,60 @@ public open class Server(
269377
}
270378
}
271379

380+
/**
381+
* Removes a single resource by URI.
382+
*
383+
* @param uri The URI of the resource to remove.
384+
* @return True if the resource was removed, false if it wasn't found.
385+
* @throws IllegalStateException If the server does not support resources.
386+
*/
387+
public fun removeResource(uri: String): Boolean {
388+
if (capabilities.resources == null) {
389+
logger.error { "Failed to remove resource '$uri': Server does not support resources capability" }
390+
throw IllegalStateException("Server does not support resources capability.")
391+
}
392+
logger.info { "Removing resource: $uri" }
393+
val removed = resources.remove(uri) != null
394+
logger.debug {
395+
if (removed) {
396+
"Resource removed: $uri"
397+
} else {
398+
"Resource not found: $uri"
399+
}
400+
}
401+
return removed
402+
}
403+
404+
/**
405+
* Removes multiple resources at once.
406+
*
407+
* @param uris A list of resource URIs to remove.
408+
* @return The number of resources that were successfully removed.
409+
* @throws IllegalStateException If the server does not support resources.
410+
*/
411+
public fun removeResources(uris: List<String>): Int {
412+
if (capabilities.resources == null) {
413+
logger.error { "Failed to remove resources: Server does not support resources capability" }
414+
throw IllegalStateException("Server does not support resources capability.")
415+
}
416+
logger.info { "Removing ${uris.size} resources" }
417+
var removedCount = 0
418+
for (uri in uris) {
419+
logger.debug { "Removing resource: $uri" }
420+
if (resources.remove(uri) != null) {
421+
removedCount++
422+
}
423+
}
424+
logger.info {
425+
if (removedCount > 0) {
426+
"Removed $removedCount resources"
427+
} else {
428+
"No resources were removed"
429+
}
430+
}
431+
return removedCount
432+
}
433+
272434
/**
273435
* Sends a ping request to the client to check connectivity.
274436
*

0 commit comments

Comments
 (0)