项目文件夹

文件
Asim Aslam c7657f73f4
goreleaser / goreleaser (push) Has been cancelled
Refactor agent plan storage, update docs, and release v6 (#2977)
* test(harness): read agent plan from the scoped store

The store-scoping change moved an agent's plan from the default table
key agent/{name}/plan to its own table (database "agent", table {name},
key "plan"). The plan-delegate harness tests still read the old key and
failed with 'not found'; read through store.Scope(mem, "agent", name)
like the agent does.

* docs: orient agents-first across README, landing, and docs overview

Lead with agents (then services and flows), surface MCP + A2A as the
interop story, and frame agents as services. Landing hero and feature
grid reordered agents-first with an A2A gateway card.

* v6: module path go-micro.dev/v6, TLS secure by default, NewService

Cut v6. Three breaking changes, bundled so the major bump is paid once:

- Module path go-micro.dev/v5 -> go-micro.dev/v6 across all imports + go.mod.
- TLS verification on by default (was off). MICRO_TLS_SECURE removed;
  MICRO_TLS_INSECURE=true opts out for self-signed/dev.
- micro.NewService(name, opts...) is the canonical service constructor,
  symmetric with NewAgent/NewFlow; micro.New kept as a deprecated alias;
  the old name-less NewService(opts...) removed. Generators emit NewService.

Also ports the JWT auth token provider in-module (go-micro.dev/v6/auth/jwt/token
on golang-jwt/jwt/v5), dropping the v5-pinned github.com/micro/plugins/v5/auth/jwt
and the deprecated dgrijalva/jwt-go.

Docs/README/landing updated to v6 and @latest; v5->v6 migration guide added;
CHANGELOG cut as [6.0.0]. Blog posts left at their historical versions.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-18 11:55:35 +01:00

116 行
3.4 KiB
Go

package mcp
import (
"context"
"go-micro.dev/v6/metadata"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
)
const instrumentationName = "go-micro.dev/v6/gateway/mcp"
// Span and attribute names for MCP OpenTelemetry integration.
const (
spanNameToolCall = "mcp.tool.call"
// AttrToolName is the tool being called (e.g. "blog.Blog.Create").
AttrToolName = "mcp.tool.name"
// AttrTransport is the transport type ("http" or "stdio").
AttrTransport = "mcp.transport"
// AttrAccountID is the authenticated account ID.
AttrAccountID = "mcp.account.id"
// AttrTraceID is the MCP-specific UUID trace ID (kept for compatibility).
AttrTraceID = "mcp.trace_id"
// AttrAuthAllowed records whether auth was granted.
AttrAuthAllowed = "mcp.auth.allowed"
// AttrAuthDeniedReason records why auth was denied.
AttrAuthDeniedReason = "mcp.auth.denied_reason"
// AttrScopesRequired lists the scopes required by the tool.
AttrScopesRequired = "mcp.auth.scopes_required"
// AttrRateLimited records whether the call was rate-limited.
AttrRateLimited = "mcp.rate_limited"
)
// tracer returns the OTel tracer from the configured provider.
// If no TraceProvider is set, returns a noop tracer.
func (s *Server) tracer() trace.Tracer {
if s.opts.TraceProvider != nil {
return s.opts.TraceProvider.Tracer(instrumentationName)
}
return trace.NewNoopTracerProvider().Tracer(instrumentationName)
}
// startToolSpan creates a new server span for an MCP tool call.
// It extracts any incoming trace context from metadata and injects
// the new span's context back into metadata for downstream propagation.
func (s *Server) startToolSpan(ctx context.Context, toolName, transport, mcpTraceID string) (context.Context, trace.Span) {
if s.opts.TraceProvider == nil {
return ctx, trace.SpanFromContext(ctx)
}
// Extract incoming trace context from go-micro metadata (if any).
md, ok := metadata.FromContext(ctx)
if ok {
carrier := metadataCarrier(md)
ctx = otel.GetTextMapPropagator().Extract(ctx, carrier)
}
ctx, span := s.tracer().Start(ctx, spanNameToolCall,
trace.WithSpanKind(trace.SpanKindServer),
trace.WithAttributes(
attribute.String(AttrToolName, toolName),
attribute.String(AttrTransport, transport),
attribute.String(AttrTraceID, mcpTraceID),
),
)
// Inject OTel trace context back into metadata so downstream
// RPC calls (via client wrappers) continue the trace.
if md == nil {
md = make(metadata.Metadata)
}
carrier := make(propagation.MapCarrier)
otel.GetTextMapPropagator().Inject(ctx, carrier)
for k, v := range carrier {
md.Set(k, v)
}
ctx = metadata.NewContext(ctx, md)
return ctx, span
}
// setSpanOK marks a span as successful.
func setSpanOK(span trace.Span) {
span.SetStatus(codes.Ok, "")
}
// setSpanError records an error on the span.
func setSpanError(span trace.Span, err error) {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
}
// metadataCarrier adapts go-micro metadata to OTel's TextMapCarrier.
type metadataCarrier metadata.Metadata
func (c metadataCarrier) Get(key string) string {
v, _ := metadata.Metadata(c).Get(key)
return v
}
func (c metadataCarrier) Set(key, value string) {
metadata.Metadata(c).Set(key, value)
}
func (c metadataCarrier) Keys() []string {
keys := make([]string, 0, len(c))
for k := range c {
keys = append(keys, k)
}
return keys
}