mirror of
				https://gitea.com/gitea/gitea-mcp.git
				synced 2025-10-30 01:41:50 +00:00 
			
		
		
		
	refactor: refactor MCP tool registration and pagination handling (#86)
- Add documentation for MCP tool constants and tool registration - Use configurable default values for pagination arguments in user organization queries - Introduce registerTools helper to streamline MCP tool registration - Refactor pagination argument parsing into a reusable getIntArg function - Add descriptive logging for tool handler execution - Improve code organization for defining and registering MCP tools Signed-off-by: appleboy <appleboy.tw@gmail.com> Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/86 Co-authored-by: appleboy <appleboy.tw@gmail.com> Co-committed-by: appleboy <appleboy.tw@gmail.com>
This commit is contained in:
		| @@ -15,68 +15,94 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
|  | 	// GetMyUserInfoToolName is the unique tool name used for MCP registration and lookup of the get_my_user_info command. | ||||||
| 	GetMyUserInfoToolName = "get_my_user_info" | 	GetMyUserInfoToolName = "get_my_user_info" | ||||||
|  | 	// GetUserOrgsToolName is the unique tool name used for MCP registration and lookup of the get_user_orgs command. | ||||||
| 	GetUserOrgsToolName = "get_user_orgs" | 	GetUserOrgsToolName = "get_user_orgs" | ||||||
|  |  | ||||||
|  | 	// defaultPage is the default starting page number used for paginated organization listings. | ||||||
|  | 	defaultPage = 1 | ||||||
|  | 	// defaultPageSize is the default number of organizations per page for paginated queries. | ||||||
|  | 	defaultPageSize = 100 | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // Tool is the MCP tool manager instance for registering all MCP tools in this package. | ||||||
| var Tool = tool.New() | var Tool = tool.New() | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
|  | 	// GetMyUserInfoTool is the MCP tool for retrieving the current user's info. | ||||||
|  | 	// It is registered with a specific name and a description string. | ||||||
| 	GetMyUserInfoTool = mcp.NewTool( | 	GetMyUserInfoTool = mcp.NewTool( | ||||||
| 		GetMyUserInfoToolName, | 		GetMyUserInfoToolName, | ||||||
| 		mcp.WithDescription("Get my user info"), | 		mcp.WithDescription("Get my user info"), | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
|  | 	// GetUserOrgsTool is the MCP tool for listing organizations for the authenticated user. | ||||||
|  | 	// It supports pagination via "page" and "pageSize" arguments with default values specified above. | ||||||
| 	GetUserOrgsTool = mcp.NewTool( | 	GetUserOrgsTool = mcp.NewTool( | ||||||
| 		GetUserOrgsToolName, | 		GetUserOrgsToolName, | ||||||
| 		mcp.WithDescription("Get organizations associated with the authenticated user"), | 		mcp.WithDescription("Get organizations associated with the authenticated user"), | ||||||
| 		mcp.WithNumber("page", mcp.Description("page number"), mcp.DefaultNumber(1)), | 		mcp.WithNumber("page", mcp.Description("page number"), mcp.DefaultNumber(defaultPage)), | ||||||
| 		mcp.WithNumber("pageSize", mcp.Description("page size"), mcp.DefaultNumber(100)), | 		mcp.WithNumber("pageSize", mcp.Description("page size"), mcp.DefaultNumber(defaultPageSize)), | ||||||
| 	) | 	) | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // init registers all MCP tools in Tool at package initialization. | ||||||
|  | // This function ensures the handler functions are registered before server usage. | ||||||
| func init() { | func init() { | ||||||
| 	Tool.RegisterRead(server.ServerTool{ | 	registerTools() | ||||||
| 		Tool:    GetMyUserInfoTool, |  | ||||||
| 		Handler: GetUserInfoFn, |  | ||||||
| 	}) |  | ||||||
|  |  | ||||||
| 	Tool.RegisterRead(server.ServerTool{ |  | ||||||
| 		Tool:    GetUserOrgsTool, |  | ||||||
| 		Handler: GetUserOrgsFn, |  | ||||||
| 	}) |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // registerTools registers all local MCP tool definitions and their handler functions. | ||||||
|  | // To add new functionality, append your tool/handler pair to the tools slice below. | ||||||
|  | func registerTools() { | ||||||
|  | 	tools := []server.ServerTool{ | ||||||
|  | 		{Tool: GetMyUserInfoTool, Handler: GetUserInfoFn}, | ||||||
|  | 		{Tool: GetUserOrgsTool, Handler: GetUserOrgsFn}, | ||||||
|  | 	} | ||||||
|  | 	for _, t := range tools { | ||||||
|  | 		Tool.RegisterRead(t) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // getIntArg parses an integer argument from the MCP request arguments map. | ||||||
|  | // Returns def if missing, not a number, or less than 1. Used for pagination arguments. | ||||||
|  | func getIntArg(req mcp.CallToolRequest, name string, def int) int { | ||||||
|  | 	val, ok := req.GetArguments()[name].(float64) | ||||||
|  | 	if !ok || val < 1 { | ||||||
|  | 		return def | ||||||
|  | 	} | ||||||
|  | 	return int(val) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GetUserInfoFn is the handler for "get_my_user_info" MCP tool requests. | ||||||
|  | // Logs invocation, fetches current user info from gitea, wraps result for MCP. | ||||||
| func GetUserInfoFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { | func GetUserInfoFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { | ||||||
| 	log.Debugf("Called GetUserInfoFn") | 	log.Debugf("[User] Called GetUserInfoFn") | ||||||
| 	user, _, err := gitea.Client().GetMyUserInfo() | 	user, _, err := gitea.Client().GetMyUserInfo() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return to.ErrorResult(fmt.Errorf("get user info err: %v", err)) | 		return to.ErrorResult(fmt.Errorf("get user info err: %v", err)) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return to.TextResult(user) | 	return to.TextResult(user) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // GetUserOrgsFn is the handler for "get_user_orgs" MCP tool requests. | ||||||
|  | // Logs invocation, pulls validated pagination arguments from request, | ||||||
|  | // performs Gitea organization listing, and wraps the result for MCP. | ||||||
| func GetUserOrgsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { | func GetUserOrgsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { | ||||||
| 	log.Debugf("Called GetUserOrgsFn") | 	log.Debugf("[User] Called GetUserOrgsFn") | ||||||
| 	page, ok := req.GetArguments()["page"].(float64) | 	page := getIntArg(req, "page", defaultPage) | ||||||
| 	if !ok || page < 1 { | 	pageSize := getIntArg(req, "pageSize", defaultPageSize) | ||||||
| 		page = 1 |  | ||||||
| 	} |  | ||||||
| 	pageSize, ok := req.GetArguments()["pageSize"].(float64) |  | ||||||
| 	if !ok || pageSize < 1 { |  | ||||||
| 		pageSize = 100 |  | ||||||
| 	} |  | ||||||
| 	opt := gitea_sdk.ListOrgsOptions{ | 	opt := gitea_sdk.ListOrgsOptions{ | ||||||
| 		ListOptions: gitea_sdk.ListOptions{ | 		ListOptions: gitea_sdk.ListOptions{ | ||||||
| 			Page:     int(page), | 			Page:     page, | ||||||
| 			PageSize: int(pageSize), | 			PageSize: pageSize, | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 	orgs, _, err := gitea.Client().ListMyOrgs(opt) | 	orgs, _, err := gitea.Client().ListMyOrgs(opt) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return to.ErrorResult(fmt.Errorf("get user orgs err: %v", err)) | 		return to.ErrorResult(fmt.Errorf("get user orgs err: %v", err)) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return to.TextResult(orgs) | 	return to.TextResult(orgs) | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user