Skip to content

feature: Support log/cancelled/progress notification #321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
dugenkui03 opened this issue May 23, 2025 · 7 comments · May be fixed by #329
Open

feature: Support log/cancelled/progress notification #321

dugenkui03 opened this issue May 23, 2025 · 7 comments · May be fixed by #329
Labels
area: sdk SDK improvements unrelated to MCP specification type: enhancement New feature or enhancement request

Comments

@dugenkui03
Copy link
Collaborator

dugenkui03 commented May 23, 2025

Problem Statement

There's already a discussion and implementation about logging: #301, and this issue could be use to discuss more details about the log implementation.

Also the cancelled_notification and progress_notification, maybe there are some design ideas they could share( all of them are notification).

Proposed Solution

java-sdk/python-skd idea

There are some great idea we can get inspiration from them.

pass the log/cancelled/progress capability to toolFunc, like java-sdk and python-skd

Proposal

We could pass more capability to ToolHandlerFunc to allow develop do more thing, mcp.CallToolRequest is not enough. Also we could do similar thing in the ResourceHandlerFuncPromptHandlerFunc.

MCP Spec Reference

@pottekkat
Copy link
Collaborator

@dugenkui03 Thank you for the detailed description. I will add my thoughts as well soon.

@pottekkat pottekkat added type: enhancement New feature or enhancement request area: sdk SDK improvements unrelated to MCP specification labels May 24, 2025
@dugenkui03
Copy link
Collaborator Author

dugenkui03 commented May 24, 2025

The proposal is that:

We could pass more capability to ToolHandlerFunc to allow develop do more thing, mcp.CallToolRequest is not enough. Also we could do similar thing in the ResourceHandlerFunc、PromptHandlerFunc.

there are more detail about design.

Goal

We want to allow the requestHandlerFunc( like ToolHandlerFunc/ResourceHandlerFunc/PromptHandlerFunc) to DO something other than only handle client request:

  • send logging/progress/cancelled notification
  • send roots/list/sample request and so on
  • maybe something else

Design

So we could pass the capability to requestHandlerFunc, pass a struct with these capabilities is a choice( just like java-sdk and python-sdk, and I present the details above).

The struct definition with logging/progress/cancelled notification capabilities maybe like that:

// RequestSession represents an exchange with MCP client. The exchange provides
// methods to interact with the client and query its capabilities.
type RequestSession struct {
	mcpServer *MCPServer

	progressToken *mcp.ProgressToken
}

func NewRequestSession(mcpServer *MCPServer, requestParamMeta *mcp.Meta) RequestSession {
	// see pr
}

// IsLoggingNotificationSupported returns true if server supports logging notification
func (exchange *RequestSession) IsLoggingNotificationSupported() bool {
	return exchange.mcpServer != nil && exchange.mcpServer.capabilities.logging != nil && *exchange.mcpServer.capabilities.logging
}

// SendLoggingNotification send logging notification to client.
// If server does not support logging notification, this method will do nothing.
func (exchange *RequestSession) SendLoggingNotification(ctx context.Context, level mcp.LoggingLevel, message map[string]any) error {
	// see pr
}

// SendProgressNotification send progress notification only if the client has requested progress
func (exchange *RequestSession) SendProgressNotification(ctx context.Context, progress, total *float64, message *string) error {
	// see pr
}

// SendCancellationNotification send cancellation notification to client
func (exchange *RequestSession) SendCancellationNotification(ctx context.Context, reason *string) error {
	// see pr
}

// TODO should implement other methods like 'roots/list', this still could happen when server handle client request

How to use

	mcpServer.AddTool(mcp.NewTool(
		"test-RequestSession",
		mcp.WithDescription("test RequestSession"),
	), func(ctx context.Context, session server.RequestSession, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// you could invoke `session.IsLoggingNotificationSupported()` first the check if server supports logging notification
		// ff server does not support logging notification, this method will do nothing.
		_ = session.SendLoggingNotification(ctx, mcp.LoggingLevelInfo, map[string]any{
			"testLog": "test send log notification",
		})
 
                // server should send progress notification if request metadata includes a progressToken
		total := float64(100)
		progressMessage := "human readable progress information"
		_ = session.SendProgressNotification(ctx, float64(50), &total, &progressMessage)

		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.TextContent{
					Type: "text",
					Text: "context from header: " + ctx.Value(testHeaderKey).(string) + ", " + ctx.Value(testHeaderFuncKey).(string),
				},
			},
		}, nil
	})

Appendix

I add RequestSession in the readme as Core Concepts, because RequestSession provide 'develop-side capabilities', and I believe developers will use it frequently.

Also referenced the Python SDK: https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#context

@dugenkui03 dugenkui03 linked a pull request May 24, 2025 that will close this issue
16 tasks
@dugenkui03
Copy link
Collaborator Author

dugenkui03 commented May 24, 2025

I created a draft for this issue #329 . and I'll add some test code after we discuss the solution further, in case there are design issues in this draft.

@dugenkui03
Copy link
Collaborator Author

dugenkui03 commented May 25, 2025

I have completed this pr #329, but feel free discuss the design.

The current breaking changes( and reason )are listed below to facilitate the release notes:

  1. added RequestSession to ResourceHandlerFunc, ResourceTemplateHandlerFunc, PromptHandlerFunc, and ToolHandlerFunc
  2. moved typed_tools_handler_func from mcp package to server package, because both TypedToolHandlerFunc and ToolHandlerFunc are tool_func
  3. Removed SessionWithLogging and integrated its methods into ClientSession, because I think logging is a part of specification. and in fact, all the current implementations of ClientSession support logging

@dugenkui03
Copy link
Collaborator Author

The SDK currently supports sending any notification anywhere (without even worrying about any restrictions), so this PR is more like a syntactic sugar method

@dugenkui03
Copy link
Collaborator Author

@pottekkat @ezynda3 please help review this design

problem

sdk provides an exported function to get MCPServer, that seems not safe, because in the request_handle_func any can get MCPServer and then do anything, such as RemoveResource.

// ServerFromContext retrieves the MCPServer instance from a context
func ServerFromContext(ctx context.Context) *MCPServer {
	if srv, ok := ctx.Value(serverKey{}).(*MCPServer); ok {
		return srv
	}
	return nil
}

solution

How about providing a common way allow developer send any kind notification and making ServerFromContext unexported.

@pottekkat
Copy link
Collaborator

Sorry for the late review. The overall design looks good. Thank you for investigating how the other SDKs do this so we have some framework to build on. I will add my comments directly to the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: sdk SDK improvements unrelated to MCP specification type: enhancement New feature or enhancement request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants