mirror of
https://github.com/go-micro/go-micro.git
synced 2026-06-03 18:44:36 +02:00
ac47a4650a
* 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>
127 lines
2.8 KiB
Go
127 lines
2.8 KiB
Go
package mcp
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
|
|
"go-micro.dev/v5"
|
|
"go-micro.dev/v5/auth/jwt"
|
|
"go-micro.dev/v5/registry"
|
|
)
|
|
|
|
// Example_inlineGateway shows how to add MCP gateway to an existing service
|
|
func Example_inlineGateway() {
|
|
service := micro.NewService(micro.Name("myservice"))
|
|
service.Init()
|
|
|
|
// Add MCP gateway alongside your service
|
|
go func() {
|
|
if err := Serve(Options{
|
|
Registry: service.Options().Registry,
|
|
Address: ":3000",
|
|
}); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}()
|
|
|
|
// Run your service normally
|
|
service.Run()
|
|
}
|
|
|
|
// Example_standaloneGateway shows how to run MCP gateway as a separate service
|
|
func Example_standaloneGateway() {
|
|
// Standalone MCP gateway
|
|
// Discovers all services via registry
|
|
if err := ListenAndServe(":3000", Options{
|
|
Registry: registry.NewMDNSRegistry(),
|
|
}); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// Example_withAuthentication shows how to add authentication
|
|
func Example_withAuthentication() {
|
|
service := micro.NewService(micro.Name("myservice"))
|
|
service.Init()
|
|
|
|
go func() {
|
|
if err := Serve(Options{
|
|
Registry: service.Options().Registry,
|
|
Address: ":3000",
|
|
AuthFunc: func(r *http.Request) error {
|
|
token := r.Header.Get("Authorization")
|
|
if token == "" {
|
|
return fmt.Errorf("missing authorization header")
|
|
}
|
|
// Validate token here
|
|
return nil
|
|
},
|
|
}); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}()
|
|
|
|
service.Run()
|
|
}
|
|
|
|
// Example_customContext shows how to use a custom context for graceful shutdown
|
|
func Example_customContext() {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
service := micro.NewService(micro.Name("myservice"))
|
|
service.Init()
|
|
|
|
go func() {
|
|
if err := Serve(Options{
|
|
Registry: service.Options().Registry,
|
|
Address: ":3000",
|
|
Context: ctx,
|
|
}); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}()
|
|
|
|
service.Run()
|
|
// cancel() will stop the MCP gateway
|
|
}
|
|
|
|
// Example_withScopesAndTracing shows how to add per-tool scopes, tracing, rate
|
|
// limiting and audit logging to the MCP gateway. Services register scope
|
|
// requirements via endpoint metadata ("scopes" key, comma-separated).
|
|
func Example_withScopesAndTracing() {
|
|
service := micro.NewService(micro.Name("blog"))
|
|
service.Init()
|
|
|
|
// Use JWT auth provider
|
|
authProvider := jwt.NewAuth()
|
|
|
|
go func() {
|
|
if err := Serve(Options{
|
|
Registry: service.Options().Registry,
|
|
Address: ":3000",
|
|
|
|
// Auth inspects Bearer tokens and enforces per-tool scopes
|
|
Auth: authProvider,
|
|
|
|
// Rate limit all tools to 10 req/s with burst of 20
|
|
RateLimit: &RateLimitConfig{
|
|
RequestsPerSecond: 10,
|
|
Burst: 20,
|
|
},
|
|
|
|
// Audit every tool call for compliance
|
|
AuditFunc: func(r AuditRecord) {
|
|
log.Printf("[audit] trace=%s tool=%s account=%s allowed=%v reason=%s",
|
|
r.TraceID, r.Tool, r.AccountID, r.Allowed, r.DeniedReason)
|
|
},
|
|
}); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}()
|
|
|
|
service.Run()
|
|
}
|