1
0
mirror of https://github.com/go-micro/go-micro.git synced 2026-04-30 19:15:24 +02:00
Files
Copilot ac47a4650a MCP gateway: add per-tool scopes, tracing, rate limiting, and audit logging (#2850)
* Initial plan

* Add MCP per-tool scopes, tracing, rate limiting, and audit logging

- Add Scopes field to Tool struct for per-tool scope requirements
- Add Auth (auth.Auth) integration to Options for token inspection
- Add trace ID generation (UUID) propagated via metadata to downstream RPCs
- Add per-tool rate limiting with configurable requests/sec and burst
- Add AuditFunc callback for immutable tool-call audit records
- Extract tool scopes from registry endpoint metadata ("scopes" key)
- Update both HTTP and stdio transports with auth/trace/rate/audit
- Add comprehensive tests for all new functionality

Co-authored-by: asim <17530+asim@users.noreply.github.com>

* Revert unrelated example go.mod changes

Co-authored-by: asim <17530+asim@users.noreply.github.com>

* Remove auto-generated example go.sum files

Co-authored-by: asim <17530+asim@users.noreply.github.com>

* Add WithEndpointScopes helper, gateway-level ToolScopes, and documentation

- Add server.WithEndpointScopes() for declaring per-endpoint auth scopes at
  handler registration time
- Add mcp.Options.ToolScopes for gateway-level scope overrides without
  changing individual services
- Update documented example to show WithEndpointScopes usage
- Update examples/mcp/README.md with scopes, tracing, and rate-limiting docs
- Update gateway/mcp/DOCUMENTATION.md with scopes section and FAQ
- Add tests for both new features

Co-authored-by: asim <17530+asim@users.noreply.github.com>

* Fix ToolScopes doc comment: clarify override (not merge) semantics

Co-authored-by: asim <17530+asim@users.noreply.github.com>

* Revert unrelated example go.mod/go.sum changes

Co-authored-by: asim <17530+asim@users.noreply.github.com>

* Rename ToolScopes to Scopes in MCP Options

The field name "Scopes" is more universal and consistent with how
auth scopes are used throughout go-micro. Updated all code references,
tests, and documentation.

Co-authored-by: asim <17530+asim@users.noreply.github.com>

* MCP gateway: add per-tool scopes, tracing, rate limiting, and audit logging

Co-authored-by: asim <17530+asim@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: asim <17530+asim@users.noreply.github.com>
2026-02-11 21:01:31 +00:00

99 lines
3.2 KiB
Go

package server
import "strings"
// Package server provides options for documenting service endpoints.
//
// Documentation is AUTOMATICALLY EXTRACTED from Go doc comments on handler methods.
// You don't need any extra code - just write good comments!
//
// Basic usage (automatic):
//
// // GetUser retrieves a user by ID from the database.
// //
// // @example {"id": "user-123"}
// func (s *UserService) GetUser(ctx context.Context, req *GetUserRequest, rsp *GetUserResponse) error {
// // implementation
// }
//
// // Register handler - docs extracted automatically from comments
// server.Handle(server.NewHandler(new(UserService)))
//
// Advanced usage (manual override):
//
// // Override auto-extracted docs with manual metadata
// server.Handle(
// server.NewHandler(
// new(UserService),
// server.WithEndpointDocs(map[string]server.EndpointDoc{
// "UserService.GetUser": {
// Description: "Custom description overrides comment",
// Example: `{"id": "user-123"}`,
// },
// }),
// ),
// )
// EndpointDoc contains documentation for an endpoint
type EndpointDoc struct {
Description string // What the endpoint does
Example string // Example JSON input
}
// WithEndpointDocs returns a HandlerOption that adds documentation to multiple endpoints.
// This metadata is stored in the registry and used by MCP gateway to generate
// rich tool descriptions for AI agents.
//
// This is a convenience wrapper around EndpointMetadata for adding docs to multiple endpoints at once.
func WithEndpointDocs(docs map[string]EndpointDoc) HandlerOption {
return func(o *HandlerOptions) {
if o.Metadata == nil {
o.Metadata = make(map[string]map[string]string)
}
for endpoint, doc := range docs {
if o.Metadata[endpoint] == nil {
o.Metadata[endpoint] = make(map[string]string)
}
if doc.Description != "" {
o.Metadata[endpoint]["description"] = doc.Description
}
if doc.Example != "" {
o.Metadata[endpoint]["example"] = doc.Example
}
}
}
}
// WithEndpointDescription is a convenience function for adding a description to a single endpoint.
// For multiple endpoints, use WithEndpointDocs instead.
func WithEndpointDescription(endpoint, description string) HandlerOption {
return EndpointMetadata(endpoint, map[string]string{
"description": description,
})
}
// WithEndpointExample is a convenience function for adding an example to a single endpoint.
func WithEndpointExample(endpoint, example string) HandlerOption {
return EndpointMetadata(endpoint, map[string]string{
"example": example,
})
}
// WithEndpointScopes sets the required auth scopes for a single endpoint.
// Scopes are stored as comma-separated values in endpoint metadata and
// enforced by the MCP gateway when an Auth provider is configured.
//
// Example:
//
// server.NewHandler(
// new(BlogService),
// server.WithEndpointScopes("Blog.Create", "blog:write", "blog:admin"),
// server.WithEndpointScopes("Blog.Read", "blog:read"),
// )
func WithEndpointScopes(endpoint string, scopes ...string) HandlerOption {
return EndpointMetadata(endpoint, map[string]string{
"scopes": strings.Join(scopes, ","),
})
}