Springing into AI - Part 15: MCP Server - Tools Playground ( Notifications )

Project

For a sample playground, we being the owners of Hobbits Inc will be creating a dumb hobbit food party planner tool that emulates a long running task and provides notification to user in terms of overall percentage completed for a task at certain checkpoints. This is extremly powerful and a very good user experience as certain task processing can delay a bit in providing response especially when there are lot of external system interactions. The notification that we generate will be seen in the MCP Inspector. An architecture overview of our tools playground is shown below:



Setup

Our project setup encompasses the following:
  • Java:                    17
  • Spring AI:           1.1.2
  • Spring Boot:       4.0.3
  • Testing tool:        MCP Inspector
  • Source code:       MCP Server ( Notifications ) can be viewed here
  • Project Demo:    Youtube (MCP Server - Tools) here 

Demo Screenshots

We select the hobbitPartyPlanner tool that demonstrates progress notification as shown below.


As we run the tool, we will see the notifications popup in the Server Notification section. The below are representation of the notifications as they appear after a while indicating the progress of a task, and that it is still busy. This serves as a great user experience especially for long running tasks that may vary in its completion time. 
    
    
Second notification showing further update on the task as it reaches on more step closer to completion

    
Third and final notification indicating 100% completion of the overall task. As this is completed the result is shown to the user. In real world scenarios the demonstration above can outline for example, taking to the database, or fetching data from an external third party provider.


Finally, since the task is completed, the result of the task is shown to the user. Figure below provides an illustration of a sample dummy response used in our playground. 
    

Code Walkthrough


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    @McpTool(
            name = "hobbitPartyPlanner",
            description = "Provides direction to hobbits for planning a party"
    )
    public String hobbitPartyPlanning(
            final McpSyncRequestContext exchange,
            @McpProgressToken Object token) throws InterruptedException {

        Object progressTracer = token == null ? "1" : token;
        exchange.progress(new McpSchema.ProgressNotification(progressTracer,
                10, 100d, "Analyzing party items...."));

        TimeUnit.SECONDS.sleep(10);

        exchange.progress(new McpSchema.ProgressNotification(progressTracer,
                50, 100d, "I have list of items, preparing party plan...."));

        TimeUnit.SECONDS.sleep(10);

        exchange.progress(new McpSchema.ProgressNotification(progressTracer,
                100, 100d, "I have list of items, preparing party plan...."));

        return """
                Okay, here is what I have planned.
                1. Arrange drinks.
                2. Hobbits love their music, so get a nice music with grooving beats.
                3. Bilbo loves to give speech, so get a mike and awesome speaker system
                4. Food, hobbits love food. Get burgers, pizza and a very large birthday cake
                5. What party is a party without firecrackers. Get a dragon fire cracker and keep it out of
                   arms way from Merry and Pippin.
                6. Have a dance floor for everyone to enjoy the evening.
                """;
    }

From the code above:
  • Line 1 - 4: Annotation used to declare the business function as a MCP Tool. The metadata listed inside the annotation is of great importance as when a user in real world prompts the LLM,  it will based on the description of the tool determine whether to invoke the tool or not
  • Line 6: McpSyncRequestContext is a class provided by SpringAI that will help us gain metadata information as well as certain utility methods that we can use to invoke some of the capability of the tool. For this playground, we use Notification capability on this object.
  • Line 7: This is a different annotation provided by SpringAI which is used to keep track of the progress token per session. The parameter has to be an Object as SpringAI community pointed out that this could either be an Integer or a String. Trying a different type would result in error. 
  • Line 9: We simply check if token exist or not, if not we create a new one and use that for further progress tracking.
  • Line 10 - 20: We use the progress on the context object discussed for Line 2 to submit a progress notification along with the description of the progress. This makes it a really nice user experience as they can see as we progress towards task completion, the different indicators. We use the sleep  method on Thread to simulate a certain delay. In enterprise application this could be a tool talking to the database or communicating with the external system.
  • Line 11: Here we create a system prompt for the LLM to use. This is used to streer the LLM in direction to the context of what we trying to achieve and the boundaries in which it should operate.
  • Line 16 - 20. This is an ASSISTANT level prompt that is provided to LLM. Imagine this as a sample user interacting with the LLM, only difference here being that the end user here is our MCP server interacting with the LLM. 
  • Line 23 - 32: Since the task progress is completed, we present a dummy response to the user providing idea of how to go about planning for a hobbit party in Middle Earth.

Comments

Popular posts from this blog

Springing into AI - Part 4: LLM - Machine Setup

Springing into AI - Part 1: 1000 feet overview

Springing into AI - Part 2: Generative AI