Files
2026-06-04 23:44:39 +02:00

7.8 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path, params, output
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports tested tests test_file_path file_path params output
tee_anthropic_sse function py cybersecurity 1.0.0 impure class AnthropicSSETee — mitmproxy addon loaded via mitmdump -s Addon de mitmproxy que intercepta el stream SSE de la API de Anthropic (/v1/messages) y emite cada evento significativo a stdout como NDJSON en tiempo real. Cada interaccion de la CLI claude dispara una o varias llamadas a /v1/messages; el addon las etiqueta con stream_id, model y has_tools para que el consumidor pueda distinguir la respuesta principal (claude-opus-X con tools) de las auxiliares (titulo/clasificador en haiku sin tools). Las funciones puras split_sse_events y event_to_ndjson son testeables sin mitmproxy.
web-proxy
claude
mitmproxy
sse
streaming
anthropic
cybersecurity
false error_go_core
json
os
sys
mitmproxy
true
split buffer completo devuelve 8 bloques
split bloques contienen event y data
split buffer cortado preserva incompleto
split resto mas continuacion reconstruye evento
split buffer vacio
split evento unico sin separador final
text delta p
text delta ong
message stop con stop holder previo
ping devuelve lista vacia
content block start text devuelve vacio
content block start tool use
tool json delta
json invalido en data devuelve vacio
bloque sin data devuelve vacio
integracion secuencia completa produce pong y stop
integracion stream id se propaga
integracion determinismo
python/functions/cybersecurity/tests/test_tee_anthropic_sse.py python/functions/cybersecurity/tee_anthropic_sse.py
name desc
mitmdump_invocation No recibe argumentos directos. Se carga con `mitmdump -s tee_anthropic_sse.py`. El puerto del proxy se controla con el flag -p de mitmdump (ej. -p 8901). La flag -q suprime el log de mitmdump en stderr dejando solo el NDJSON en stdout.
name desc
FN_WIRE_ONLY_TOOLS Variable de entorno opcional. Si vale '1', suprime los streams cuyo request body no incluye el array 'tools' (llamadas auxiliares de titulo/clasificador que usan haiku). Por defecto (sin la env) emite todos los streams etiquetados con stream_id, model y has_tools para que el consumidor filtre.
NDJSON a stdout, un objeto JSON por linea (flush inmediato). Tipos de linea: message_start{stream_id,model,has_tools} al inicio de cada stream; text_delta{stream_id,text} por cada fragmento de texto del modelo; tool_use_start{stream_id,tool_name,tool_id} cuando el modelo inicia una herramienta; tool_json_delta{stream_id,partial_json} por cada fragmento de argumentos JSON de la herramienta; message_stop{stream_id,stop_reason} al finalizar el stream. stderr recibe solo mensajes de diagnóstico del addon (errores, warnings), nunca NDJSON.

Ejemplo

# Terminal 1: lanzar mitmproxy como proxy de interceptacion
# -q suprime el log de mitmdump; solo se ve el NDJSON en stdout
mitmdump -p 8901 \
  -s python/functions/cybersecurity/tee_anthropic_sse.py \
  -q

# Terminal 2: lanzar claude por el proxy
# NODE_EXTRA_CA_CERTS hace que el runtime Node de claude confie en la CA de mitmproxy
export HTTPS_PROXY=http://127.0.0.1:8901
export NODE_EXTRA_CA_CERTS="$HOME/.mitmproxy/mitmproxy-ca-cert.pem"
claude -p "di hola"

# Salida en stdout de mitmdump (Terminal 1):
# {"type": "message_start", "stream_id": 1, "model": "claude-haiku-4-5", "has_tools": false}
# {"type": "text_delta", "stream_id": 1, "text": "H"}
# {"type": "text_delta", "stream_id": 1, "text": "ola"}
# {"type": "message_stop", "stream_id": 1, "stop_reason": "end_turn"}
# ...
# {"type": "message_start", "stream_id": 2, "model": "claude-opus-4-8", "has_tools": true}
# {"type": "text_delta", "stream_id": 2, "text": "Hola"}
# ...

# Filtrar solo la respuesta principal (has_tools=true) con jq:
mitmdump -p 8901 -s python/functions/cybersecurity/tee_anthropic_sse.py -q \
  | jq -c 'select(.has_tools == true or .stream_id != null and (.type == "text_delta"))'

# O usar la variable de entorno para que el addon ya filtre en origen:
FN_WIRE_ONLY_TOOLS=1 mitmdump -p 8901 \
  -s python/functions/cybersecurity/tee_anthropic_sse.py -q

Cuando usarla

Cuando quieras el texto exacto que el modelo genera en tiempo real desde una sesion claude (TUI interactiva o claude -p), interceptando la red, sin parsear el render de la terminal ni depender de warmup/idle de la TUI. Util para: capturar la salida del modelo para procesado downstream (logging estructurado, metricas de tokens, replay), observar tool_use en construccion (argumentos parciales), o depurar la diferencia entre streams principales y auxiliares en una misma sesion TUI.

Gotchas

  • Descompresion via strip de Accept-Encoding: el hook request elimina el header Accept-Encoding de las llamadas a /v1/messages para que la API responda con el SSE SIN comprimir. Esto es obligatorio: el modo streaming de mitmproxy (flow.response.stream) entrega al tee los bytes CRUDOS del cuerpo, que si vinieran con Content-Encoding: gzip/br nunca contendrian el delimitador \n\n de eventos SSE (se veria binario) y no se emitiria ningun delta. Verificado empiricamente el 2026-06-04: sin el strip, solo se emitia message_start; con el strip, los text_delta salen correctamente. La alternativa (un decompresor de streaming con estado por flujo) es mas fragil. El coste es unos bytes extra en el salto local, irrelevante.
  • NO usar --set stream_large_bodies: el modo streaming se activa con flow.response.stream = func en responseheaders, sin necesidad de ese flag. Ademas stream_large_bodies=N bajo rompe el acceso a flow.request.content (necesario para has_tools), porque tambien streamea el cuerpo del request y deja de bufferearlo.
  • Requiere mitmproxy + CA confiada por claude: la CA de mitmproxy (~/.mitmproxy/mitmproxy-ca-cert.pem) debe estar configurada en NODE_EXTRA_CA_CERTS para que el runtime Node de la CLI claude acepte el certificado MITM. Sin esto, claude rechaza la conexion con error de TLS. Instalar mitmproxy: uv tool install mitmproxy o pip install mitmproxy. claude tambien respeta HTTPS_PROXY para enrutar su trafico por el proxy.
  • Una interaccion TUI dispara varias /v1/messages: la respuesta real del usuario usa el modelo principal (p.ej. claude-opus-4-8) y su request body incluye el array tools con las herramientas de Claude Code. Las llamadas auxiliares (generador de titulo, clasificador) usan claude-haiku y su request NO lleva tools. Usa has_tools=true o FN_WIRE_ONLY_TOOLS=1 para aislar la respuesta principal y no mezclar streams.
  • Solo funciona mientras claude no haga TLS pinning: hoy (2026-06-04) la CLI claude no hace certificate pinning, por lo que el MITM funciona con NODE_EXTRA_CA_CERTS. Si una version futura de claude añade pinning, el addon dejara de interceptar.
  • Es trafico de tu propia cuenta y maquina: el addon captura unicamente el trafico local que tu proxy intercepta. No hay acceso a otras cuentas ni sesiones remotas. El NDJSON se emite solo a stdout local.
  • El endpoint puede cambiar: la CLI claude hoy usa POST /v1/messages?beta=true. El addon filtra por prefix /v1/messages para tolerar variantes de query string, pero si Anthropic cambia la ruta base en versiones futuras del protocolo, actualizar el check en responseheaders.
  • Chunks parciales: el addon mantiene un buffer por stream para manejar eventos SSE partidos entre chunks TCP. Si mitmdump se mata con SIGKILL durante un stream activo, el ultimo bloque incompleto del buffer se descarta (no se emite un message_stop artificial).
  • stdout debe ser exclusivamente NDJSON: no añadir prints de debug a stdout; redirigir diagnosticos a stderr. Si se canaliza la salida a jq u otro parser, cualquier linea no-JSON rompe el pipeline.