Site
Todos os artigos

Publicado 20 de set. de 20265 min de leitura

MCP Fusion 5.1.0: correlacionar chamadas de ferramentas MCP na trace distribuída

Lançada em 20 de setembro de 2026. Os spans de ferramenta MCP eram ilhas: cada chamada iniciava uma raiz nova, e backends que não falam mcp.* não conseguiam consultá-los. A 5.1.0 adiciona correlação de contexto W3C Trace e emissão dupla GenAI/OpenInference em todo span de ferramenta, sem uma única dependência OpenTelemetry no core.

Renato Marinho

Por Renato Marinho

Founder · Vinkius

MCP Fusion 5.1.0 trace flow: the agent's W3C traceparent is extracted into an opaque parent context, so every tool span, including the 404 span, parents to the caller's trace while emitting native mcp.* plus GenAI/OpenInference attributes

As notas do release 5.1.0, publicado em 20 de setembro de 2026, listam duas frentes de trabalho: G1, correlação de pai via W3C Trace Context, e G2, emissão dupla de convenções, e as duas caem em um único pacote (notas do release · MCP Fusion no GitHub). Os outros 15 pacotes sobem para 5.1.0 em lockstep sem uma linha de código: o range ^5.0.0 que eles carregam sobre o core já é satisfeito, então, para eles, o release é uma linha de contabilidade semver. O que se mexeu é estreito, e mexe justamente na coisa que decide se você consegue ver as chamadas de ferramenta do seu agente no seu backend.

O waterfall morria no gateway

Antes deste release, o MCPFusionTracer.startSpan recebia dois argumentos, e os spans que produzia eram sempre raízes novas. Na prática, a trace distribuída do agente parava no gateway do MCP: cada chamada de ferramenta aparecia no backend como uma trace órfã própria, e seguir agente → ferramenta em um único waterfall era impossível. Era também a causa de outra cegueira: backends sem conhecimento do namespace privado mcp.* não conseguiam responder "todas as chamadas da última hora"; essa consulta só rodava onde você tinha ensinado o namespace ao fornecedor.

Antes: cada chamada de ferramenta criava sua própria raiz de trace. Depois: o traceparent W3C por requisição anexa o span da ferramenta à trace do chamador, inclusive 404 de ferramenta desconhecida.

Um handle de pai que o framework não toca

O novo tipo exportado MCPFusionSpanContext é um handle de pai estruturalmente opaco: traceId (32 caracteres hex minúsculos), spanId (16), flags (o byte W3C de flags, 0x01 quando amostrado), mais os opcionais remote, traceState, baggage e um slot raw para o contexto do próprio tracer do host. O host constrói um a partir de um par traceparent / tracestate / baggage recebido, headers HTTP, ou params._meta do MCP, e o framework faz exatamente uma coisa com ele: encaminha. Nunca inspeciona. Essa opacidade é o design, não um acidente: como um adaptador no host mapeia traceId / spanId / raw sobre o SpanContext + Context do OpenTelemetry, o @mcpfusion/core mantém zero dependências @opentelemetry/*. Um Tracer de OTel puro não é atribuível ao MCPFusionTracer (arrays de atributo imutáveis, mais a separação do Context), então a fronteira continua sendo um adaptador fino no seu código, não uma dependência de pacote.

O parsing é estrito por escolha. Os helpers de zero dependência assentam em crypto.randomUUID(): newTraceId(), newSpanId(), generateTraceparent(sampled = true), e o parseTraceparent só aceita versão 00, trace IDs de 32 hex minúsculos não-zero, span IDs de 16 hex minúsculos não-zero e flags de dois dígitos hex; qualquer desvio devolve undefined, nunca um pai fabricado. tracestate e baggage passam intactos sob os limites W3C (512 caracteres, 8192 bytes), e o extractW3CContext trata um traceparent válido como obrigatório: sem header válido, não há contexto, e o span é raiz nova. O formato em bytes é o mesmo que o SwarmGateway já emite, então as traces do monorepo se interoperam direto.

A captura é por requisição. O GroupedToolBuilder e o ToolRegistry leem uma chave convencional e duck-typed, ctx.mcpTraceContext (o mesmo padrão de ctx.handoffTraceparent), e a encaminham para o span da ferramenta, e o span de 404 de ferramenta desconhecida que o ToolRegistry.routeCall emite recebe o mesmo tratamento, o que importa exatamente porque o 404 costuma ser o momento em que o agente perdeu a noção de quais ferramentas existem. Um detalhe que vale conhecer: sem contextFactory, o attachToServer() instala um proxy de guarda que lança em qualquer acesso a propriedade; o novo helper readMcpTraceContext faz sua leitura única dentro de um try/catch e engole o throw, então habilitar tracing sozinho nunca obriga você a escrever um factory. Ausência de contexto é lida como "raiz nova", nunca como erro. Há um limite documentado: como o framework não segura um Context de OTel em runtime, chamadas a jusante auto-instrumentadas dentro do handler (Prisma, clientes HTTP, Redis) aparecem como irmãs do span MCP, não filhas. O pai recebido é honrado; o span da ferramenta não vira o contexto ativo para tudo a jusante.

Um span, três dialetos

Todo span de ferramenta passa a carregar, ao lado dos atributos nativos mcp.*, openinference.span.kind = "TOOL", gen_ai.operation.name = "tools/call" e tool.name, o span de 404 incluso. O mesmo span é assim portável para Datadog, Arize e Phoenix sem nenhum deles precisar entender mcp.*; filtre por openinference.span.kind = TOOL em qualquer um deles. O que não é emitido pesa tanto quanto o que é: nenhum atributo de token ou custo na fronteira da ferramenta, porque esses vivem no span de LLM do lado do agente, e a 5.1.0 se recusa a inventá-los na camada da ferramenta. A semântica de status segue o pipeline: UNSET para falhas do lado da IA (erros de validação, ações desconhecidas, ferramentas desconhecidas; o span de 404 é explicitamente UNSET com mensagem, não ERROR), OK em sucesso e ERROR só quando o handler lança falha de sistema. Um LLM chamando a ferramenta errada não aciona seu plantão.

Se você já roda um tracer do OpenTelemetry

Toda a adoção cabe em dois trechos. Primeiro, encapsule o tracer para o argumento de contexto opcional cair no lugar certo:

import { trace, type SpanOptions, type Context } from '@opentelemetry/api';

const otel = trace.getTracer('mcpfusion');
registry.attachToServer(server, {
  contextFactory: createContext,
  tracing: {
    startSpan: (name, options, context) =>
      otel.startSpan(name, options as SpanOptions, context?.raw as Context | undefined),
  },
});

Depois, no context factory por requisição, extraia o contexto W3C e guarde sob a chave convencional:

const ctx = {
  ...baseContext,
  mcpTraceContext: extractW3CContext(request.headers),
};

A partir daí, todo span de ferramenta, 404 de roteamento incluso, pendura na trace do chamador, e qualquer backend que fala as convenções GenAI/OpenInference o enxerga. O bloco de verificação do release sustenta isso: build do core com zero erros de TypeScript, os 16 pacotes satélite limpos, a suíte do core verde em 272 arquivos / 5.263 testes com zero falhas, e o @mcpfusion/swarm em 158/158. O novo Tracing.test.ts fixa a paridade de emissão dupla entre o span da ferramenta e o de 404, os round-trips W3C, a rejeição de entrada malformada, a tolerância ao proxy de guarda e a propagação do contexto-pai nos dois caminhos.

Tópicosmcptracingobservabilitymcpfusion