| 140 | } |
| 141 | |
| 142 | func child(port string) { |
| 143 | // Create a server with a single tool that increments a counter and sends a notification. |
| 144 | server := mcp.NewServer(&mcp.Implementation{Name: "counter"}, nil) |
| 145 | |
| 146 | var count atomic.Int64 |
| 147 | inc := func(ctx context.Context, req *mcp.CallToolRequest, args struct{}) (*mcp.CallToolResult, struct{ Count int64 }, error) { |
| 148 | n := count.Add(1) |
| 149 | if *verbose { |
| 150 | log.Printf("request %d (session %s)", n, req.Session.ID()) |
| 151 | } |
| 152 | // Send a notification in the context of the request |
| 153 | // Hint: in stateless mode, at least log level 'info' is required to send notifications |
| 154 | req.Session.Log(ctx, &mcp.LoggingMessageParams{Data: fmt.Sprintf("request %d (session %s)", n, req.Session.ID()), Level: "info"}) |
| 155 | return nil, struct{ Count int64 }{n}, nil |
| 156 | } |
| 157 | mcp.AddTool(server, &mcp.Tool{Name: "inc"}, inc) |
| 158 | |
| 159 | handler := mcp.NewStreamableHTTPHandler(func(*http.Request) *mcp.Server { |
| 160 | return server |
| 161 | }, &mcp.StreamableHTTPOptions{ |
| 162 | Stateless: true, |
| 163 | }) |
| 164 | log.Printf("child listening on localhost:%s", port) |
| 165 | log.Fatal(http.ListenAndServe(fmt.Sprintf("localhost:%s", port), handler)) |
| 166 | } |