signer-mcp

Firma sin claves para CEX/DEX para agentes de IA: las claves API de intercambio permanecen dentro de un AWS Nitro Enclave, por lo que un agente con inyección de prompt no puede filtrarlas. Binance, OKX, Bybit, KuCoin, Hyperliquid, Asterdex.

Documentación

@usenami/signer-mcp

Firme órdenes de CEX desde cualquier agente de IA compatible con MCP — el secreto de firma nunca sale del AWS Nitro Enclave.

signer-mcp es la cara pública de Usenami Signer. Le da a Claude Desktop, Cursor, ElizaOS y cualquier otro cliente compatible con MCP una superficie de seis herramientas para operar cuentas reales de perp CEX/DEX (Binance, OKX, Asterdex, KuCoin, Bybit, Hyperliquid) sin que el secreto de firma entre jamás en el proceso del agente — ni en el tuyo.

Estado: v0 (alfa), piloto por invitación. Manifiesto de venues, atestación, lectura de cuenta, colocación/cancelación de órdenes y un hedge de dos patas. ⚠️ Asume que las órdenes son reales. Qué venue y red reciben tus órdenes lo decide la política vinculada a tu token, y ni esta página ni list_venues pueden decírtelo — pregunta a quien emitió el token. No hay red de seguridad implícita de testnet, así que trata cada orden como dinero de mainnet hasta que confirmes lo contrario. Lee place_order antes de enviar nada.


Por qué existe esto

Cada framework de agentes que toca una CEX hoy carga la clave de API en el proceso del agente. Eso pone el secreto en disco, en variables de entorno, en paquetes npm, en llamadas de herramientas manipuladas por prompt y en tu historial de shell. Una inyección de prompt, un compromiso de la cadena de suministro, una línea de log accidental, un compañero curioso — y la clave se filtra.

Signer toma el enfoque opuesto. La clave de firma se genera dentro de un AWS Nitro Enclave atestiguado por el propio AWS. La medición del enclave (PCR0) se publica en https://usenami.io/signer/attestations. El servidor MCP que instalas aquí puede pedirle al enclave que firme una orden específica — limitada por una política explícita (tope por activo, tope por período, venues permitidos) — pero no puede leer la clave. Tampoco pueden el agente, tu laptop, tu IaC ni nuestros propios ingenieros.

Si el agente se ve comprometido, lo peor que puede hacer es colocar órdenes dentro de tu ventana de política. La clave en sí permanece atestiguada.


Inicio rápido (Claude Desktop)

  1. Obtén un token. El acceso es por invitación durante el piloto — no hay registro de autoservicio todavía; solicita acceso vía usenami.io/signer (enlace de contacto al final) y tu token se aprovisiona en el onboarding, vinculado a una política con topes por venue. ¿Aún no tienes token? Los pasos 2–4 funcionan igual: list_venues y get_attestation no necesitan token. Nota qué hace realmente cada uno, porque solo uno de ellos habla con nosotros: get_attestation obtiene un documento vivo firmado por NSM desde la puerta de enlace, mientras que list_venues responde desde un manifiesto estático compilado en este paquete y no hace ninguna llamada de red.

  2. Edita claude_desktop_config.json. La ruta es ~/Library/Application Support/Claude/claude_desktop_config.json en macOS.

    {
      "mcpServers": {
        "signer": {
          "command": "npx",
          "args": ["-y", "@usenami/signer-mcp@^0.6.0"],
          "env": {
            "SIGNER_GATEWAY_URL": "https://signer-demo.usenami.io:8443",
            "SIGNER_API_TOKEN": "sk_live_..."
          }
        }
      }
    }
    

Fija @^0.6.0 — las versiones anteriores no funcionan de fábrica. Cada versión publicada hasta e incluyendo 0.5.0 tiene por defecto SIGNER_GATEWAY_URL a https://signer.usenami.io, que 301-redirige cada ruta a la página de aterrizaje de marketing. Las herramientas de red entonces reciben HTML y mueren con Unexpected token '<'. 0.6.0 cambió el valor por defecto a la puerta de enlace de demostración. Si estás pegando una configuración de una publicación antigua o una respuesta en caché, verifica esto primero — el síntoma parece un servidor roto y es un valor por defecto obsoleto.

  1. Reinicia Claude Desktop y busca el icono de enchufe 🔌. Deberías ver siete herramientas listadas bajo signer: list_venues, get_attestation, get_verified_price, get_account, place_order, place_hedge, cancel_order. (La lista se nombra en lugar de contarse a propósito — un conteo en prosa queda obsoleto en cuanto se añade una herramienta, y este lo hizo: decía seis hasta que get_verified_price se lanzó.)

  2. Prueba primero las herramientas de solo lectura. Pregúntale a Claude:

    "Lista los venues disponibles a través de Signer, luego devuelve el documento de atestación actual."

    Sin fondos en riesgo — estas no firman nada, y ninguna necesita token.

  3. Una vez que tengas un token y confíes en la atestación, puedes colocar una primera orden — a sabiendas. ⚠️ Esto firma una orden real en el venue que la política de tu token permite, y deberías asumir que eso significa mainnet, dinero real — 0.001 BTC es una posición real, no un ejercicio de testnet, a menos que la persona que emitió tu token te haya dicho lo contrario. Empieza con el tamaño más pequeño que tu política permita, y solo entonces:

    "Obtén mi cuenta de Binance, y si tengo al menos $20 de margen libre, coloca una compra de mercado por 0.001 BTC."

Si algo parece mal, el agente puede llamar a cancel_order inmediatamente.


Inicio rápido (ElizaOS)

ElizaOS tiene un plugin nativo: @usenami/plugin-signer (mismo contrato de puerta de enlace — un token emitido para uno funciona con el otro). Prefiérelo: las acciones llegan directamente al agente, más un proveedor de atestación que mantiene el PCR0 actual en contexto.

Alternativamente, ElizaOS puede alcanzar este servidor MCP a través del puente genérico @elizaos/plugin-mcp sobre stdio:

npm install @elizaos/plugin-mcp

Luego en tu configuración de personaje / agente:

{
  "plugins": ["@elizaos/plugin-mcp"],
  "settings": {
    "mcp": {
      "servers": {
        "signer": {
          "type": "stdio",
          "command": "npx",
          "args": ["-y", "@usenami/signer-mcp@^0.6.0"],
          "env": {
            "SIGNER_GATEWAY_URL": "https://signer-demo.usenami.io:8443",
            "SIGNER_API_TOKEN": "sk_live_..."
          }
        }
      }
    }
  }
}

El agente ahora expone las mismas siete herramientas (list_venues, get_attestation, get_verified_price, get_account, place_order, place_hedge, cancel_order). Mismo modelo de confianza: la clave de firma nunca entra en el proceso de Eliza — inicia el agente con las herramientas de solo lectura (list_venues / get_attestation) y verifica la atestación antes de dejar que coloque órdenes. Solo get_attestation llega a la puerta de enlace; list_venues se sirve desde un manifiesto estático dentro del paquete, así que un list_venues verde no dice nada sobre si tu puerta de enlace es alcanzable.


Configuración

Variables de entorno pasadas a través del bloque env de claude_desktop_config.json (o el equivalente de tu cliente):

VariableRequeridaValor por defectoNotas
SIGNER_GATEWAY_URLnohttps://signer-demo.usenami.io:8443El enclave de demostración atestiguado alojado. Sobrescribe para despliegues autoalojados.
SIGNER_API_TOKENsí (para herramientas de cuenta/orden)—Token Bearer aprovisionado en el onboarding (piloto por invitación). list_venues y get_attestation funcionan sin uno — pero solo get_attestation contacta la puerta de enlace (list_venues es estático, ver su sección abajo); get_account, place_order, place_hedge, cancel_order lo requieren.
SIGNER_FETCH_TIMEOUT_MSno30000Tiempo de espera de fetch por solicitud en ms. Bájalo para CI / pruebas de humo; súbelo en enlaces lentos. Debe ser un entero positivo.
X402_PRIVATE_KEYsolo para get_verified_price—Clave de pagador para la puerta de enlace x402: cada consulta de precio cuesta un centavo en USDC en Base. Sin ella la herramienta rechaza no_payer_key y no gasta nada — nunca envía una solicitud no pagada y nunca recurre a una fuente no verificada. Usa una billetera financiada para esto y nada más; el tope por pago está limitado en el código.

El propio servidor MCP no almacena nada en disco. Los tokens se leen del entorno al inicio y se mantienen en memoria durante la vida del proceso — mata al agente, el token se va con él.


Referencia de herramientas

list_venues

Devuelve el manifiesto estático de venues para los que este Signer puede firmar. Solo lectura, no contacta la puerta de enlace, funciona sin token. Llama a esto primero para descubrir qué está soportado.

{
  "venues": [
    {
      "venue": "binance",
      "asset_class": "perp",
      "auth_scheme": "hmac_sha256",
      "status": "live",
      "notes": "..."
    }
  ],
  "count": 7
}

Cada entrada lleva un status: live (el enclave firmará para él) o denied (el enclave lo rechaza por política — proporcionar credenciales no lo cambiará). Algunas entradas añaden un campo network (bsc, hyperliquid-testnet, …). Lee status y notes antes de elegir un venue.

Venues soportados

id venueestadoclase de activoesquema de autenticaciónejemplo de símbolonotas
binancevivoperphmac_sha256BTCUSDTFuturos USD-M de Binance. ⚠️ Asume mainnet, fondos reales — la red la establece la política de tu token, no esta tabla
okxvivoperphmac_sha256BTC-USDT-SWAPSwap perpetuo de OKX. Firma donde hay una clave de OKX aprovisionada; solo la puerta de enlace a la que apuntas puede decir si la hay. Los tamaños están en contratos (1 BTC-USDT-SWAP = 0.01 BTC)
asterdexvivoperpeip712 (bsc)BTC-USDPerp en cadena de Asterdex (BSC)
kucoinvivoperphmac_sha256XBTUSDTMFuturos de KuCoin (HMAC + frase de contraseña cifrada); cantidad en contratos
bybitvivoperphmac_sha256BTCUSDTBybit V5 lineal (category=linear)
hyperliquid_testnetvivoperpeip712 (hyperliquid)BTCMismo código de enclave que mainnet, fuente de agente fantasma de testnet. No alcanzable vía place_order/cancel_order en v0
hyperliquid_mainvivoperpeip712 (hyperliquid)BTCSolo orden y cancelación — el enclave no tiene acción de retiro o transferencia para este venue. Mainnet lleva un piso de dinero incondicional (política firmada por autoridad + topes vinculantes por activo por índice entero de activo), no relajable por una bandera de compilación. La lectura de cuenta es el clearinghouseState público

El bloque de configuración del agente es idéntico para cada venue — apunta SIGNER_GATEWAY_URL a tu Signer y establece SIGNER_API_TOKEN. Qué venues puede operar un token dado está vinculado en el lado del servidor a la política de ese token; list_venues informa el conjunto completo que la puerta de enlace puede firmar, no tu lista de permitidos por token.

get_attestation

Obtiene el documento de atestación de Nitro con un nonce fresco y lo verifica localmente antes de devolver nada. PCR0/PCR1/PCR2 se leen de los bytes firmados.

🔴 Corregido en 0.7.1, y vale la pena decirlo claramente. Hasta 0.7.0 esta herramienta no enviaba nonce y no verificaba nada — reenviaba el JSON de la puerta de enlace y se describía a sí misma como prueba de que "el código que actualmente firma tus órdenes coincide con la fuente publicada". Ninguna de las dos mitades se sostenía. Sin un nonce el documento no está vinculado a nada, así que una repetición de una atestación más antigua era indistinguible de una fresca, y "actualmente" no estaba ganado. Y nada se comprobaba: ni la firma de hardware, ni la cadena de certificados, ni la raíz. Esta es la única superficie que consume un agente de terceros, lo que la convertía en el peor lugar del producto para mantener un verificador decorativo.

{
  "verified": true,
  "checks": {
    "document_readable": true,
    "nonce_echoed": true,
    "root_pinned": true,
    "chain_verified": true,
    "signature_verified": true
  },
  "pcr0": "...sha384 hex, read from the SIGNED document...",
  "nonce_sent": "...16 random bytes, hex...",
  "nonce_in_document": "...the same value, or the check above is false...",
  "root_sha256": "641a0321...bb5b",
  "pinned_root_sha256": "641a0321...bb5b",
  "proves": ["..."],
  "do_not_trust_for": ["..."],
  "document": { "attestation_doc_b64": "...", "pcr0_sha384": "...", "timestamp_ms": 0 }
}

Cada comprobación puede fallar por sí sola, y verified es el Y de las cinco. Cuando algo es falso el documento aún se devuelve — puede que quieras mirarlo — pero proves está vacío y do_not_trust_for lidera con la única lectura honesta: un documento que no verifica no es evidencia más débil, es ninguna.

Lo que la herramienta no puede establecer, declarado en su propia salida en lugar de dejarse inferir: que PCR0 corresponde a la fuente publicada (reconstruye desde el clon público y compara, o pregunta al registro en cadena), y cualquier cosa sobre una firma pasada — una atestación habla sobre el código que respondió esta solicitud.

root_pinned es el que soporta la carga. Quien responda en SIGNER_GATEWAY_URL puede acuñar su propia CA bajo el nombre de sujeto del propio AWS, firmar su propia cadena y un documento que lleve cualquier medición que quiera, y hacer eco del nonce; las otras cuatro comprobaciones entonces pasan. La huella fijada es lo que no pueden falsificar. Deliberadamente no hay variable de entorno para relajarla. Para dejar de tomar nuestra palabra sobre esa constante, compárala una vez:

curl -sO https://aws-nitro-enclaves.amazonaws.com/AWS_NitroEnclaves_Root-G1.zip
unzip -p AWS_NitroEnclaves_Root-G1.zip > aws-nitro-root
openssl x509 -in aws-nitro-root -outform DER | shasum -a 256

⚠️ La muestra anterior ya no muestra registered_onchain. Ese campo solía estar en la respuesta de la puerta de enlace y se ha ido — medido contra el endpoint vivo el 12 de septiembre, con un nonce el cuerpo lleva attestation_doc_b64, nonce, pcr0_sha384 y timestamp_ms, y sin uno lo mismo menos nonce. Habría sido la propia configuración del operador reportada como si fuera un hecho sobre la cadena, que es por lo que nada aquí depende de él. ⚠️ Y el eco del nonce del cuerpo no vale nada como verificación. La puerta de enlace lo escribe, de la misma manera que escribe el pcr0_sha384. nonce_echoed compara con el nonce dentro del documento firmado; un cliente que comparara el campo del cuerpo en su lugar estaría preguntando al operador si el operador fue honesto.

Solo lectura, funciona sin token. La verificación no necesita red más allá de la llamada a la puerta de enlace y no tiene dependencias: el propio crypto de Node realiza la cadena y la firma ES384.

get_verified_price

Lee el precio de un token de Uniswap V3 desde The Graph y lo devuelve solo si pasan cuatro comprobaciones. Se ejecuta completamente fuera del enclave — esto es una lectura, no una firma, y el README lo dice donde un lector podría asumir que el enclave avalaba el número.

get_verified_price(token_address="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")
la comprobaciónqué evita
el indexador firmó los bytes exactos que llegaronun cuerpo re-serializado tiene un hash diferente, por lo que una respuesta "verificada" sobre JSON modificado
ese firmante se resuelve en cadena a un indexador con participaciónuna firma de nadie en particular
la lectura es un precio utilizableuna firma verificada sobre un error de GraphQL, o sobre un cero, no es un precio
la antigüedad del propio precio, medida aparte de la cabeza del subgrafouna cabeza fresca que lleva un precio de hace un año — los precios se escriben en los manejadores de eventos, por lo que un mercado muerto mantiene uno muerto bajo indexación verde

Ante la negativa, no se devuelve ningún precio, y la respuesta nombra tanto la comprobación que lo detuvo (stage) como la razón de esa comprobación (cause). price_absent_or_zero, graphql_errors y price_stale son tres problemas diferentes con tres soluciones diferentes, por eso son tres palabras diferentes.

Nombra el token por dirección cuando puedas. Un ticker no es una clave en este subgrafo: pedirle WETH devuelve varios tokens con ese nombre, todos ellos reales. Por lo tanto, cada coincidencia se comprueba y se devuelve en lugar de adivinar la primera. Sin dirección ni ticker, la herramienta devuelve los tokens con precio más reciente, filtrados a aquellos que realmente tienen un precio.

Cuesta dinero y lo dice por adelantado: un centavo en USDC en Base por consulta, pagado a través de la puerta de enlace x402, que necesita X402_PRIVATE_KEY. Sin esa clave, la herramienta rechaza no_payer_key y no gasta nada — no envía una solicitud impaga y no recurre silenciosamente a una fuente no verificada.

Dónde van los encabezados firmados

🔴 En get_account, place_order y cancel_order, los encabezados de autenticación firmados pasan a través de tu cliente. La puerta de enlace devuelve {method, url, headers}; este paquete luego envía esa solicitud a esa URL por sí mismo. Esos encabezados son lo que te autentica ante el exchange: la clave de la API viaja en ellos (X-MBX-APIKEY en Binance, OK-ACCESS-KEY en OKX) y en OKX la frase de contraseña viaja con ella. Solo el secreto de firma permanece dentro del enclave — esa es la afirmación que hacemos, y es más estrecha que "tus credenciales nunca salen".

Lo que se deduce de esto, dicho claramente en lugar de dejarlo a la inferencia:

  • Cualquier cosa que pueda leer la memoria de tu proceso, tus registros o tu tráfico saliente en ese momento puede leer esos encabezados. Son de corta duración y están limitados a una solicitud, lo que limita el daño; no lo elimina.
  • No hay una lista de permitidos de hosts en este cliente. Envía a cualquier URL que nombre la puerta de enlace. Una puerta de enlace comprometida o suplantada podría nombrar su propio host y recopilar la clave. Fija la puerta de enlace en la que confías (SIGNER_GATEWAY_URL) y verifica su atestación — get_attestation existe para esto, y la medición del enclave es lo que te dice qué código respondió.

place_hedge es la excepción y el modelo para el resto: ambas patas están firmadas y ambas llamadas al exchange se disparan del lado del servidor, por lo que nada autenticador llega a tu proceso. Mover las otras tres a esa forma es la solución; hasta que llegue, esta sección es la descripción honesta de lo que sucede hoy.

get_account

Devuelve capital, margen libre y posiciones abiertas para un exchange.

{
  "venue": "binance",
  "equity_usd": 145.32,
  "free_margin_usd": 92.10,
  "positions": [
    { "symbol": "BTCUSDT", "qty": 0.002, "entry_price": 67120.5 }
  ],
  "updated_at": "2026-05-31T18:01:11Z"
}

Solo lectura. Requiere SIGNER_API_TOKEN. Los encabezados firmados para esta llamada pasan a través de tu cliente — consulta Dónde van los encabezados firmados.

place_order

Coloca una sola orden de mercado o límite. El enclave firma la carga útil después de verificar los límites de la política, y tu cliente luego envía la solicitud firmada al exchange — consulta Dónde van los encabezados firmados.

Argumentos:

  • venue — uno de binance | okx | asterdex | kucoin | bybit | hyperliquid_testnet | hyperliquid_main. ⚠️ v0 tiene rutas de orden estructuradas para binance | okx solamente — otros exchanges devuelven un error claro (exponen acceso de solo lectura a la cuenta); y verifica list_venues status primero
  • symbol — canónico (BTC, BTCUSDT, BTC/USDT) o nativo del exchange (BTC-USDT-SWAP, XBTUSDTM, …). El cliente traduce al formato nativo del exchange y lo devuelve.
  • side — buy | sell
  • qty — siempre cantidad del activo base (por ejemplo, 0.001 para 0.001 BTC). No es nocional en USD, no son contratos del exchange. Los exchanges denominados en contratos (okx: 1 contrato = 0.01 BTC en BTC-USDT-SWAP) se convierten automáticamente; los tamaños fuera de la cuadrícula de contratos del exchange se rechazan, nunca se redondean silenciosamente.
  • type — market | limit
  • price — requerido si type=limit, ignorado si type=market
  • policy_id — anulación opcional; por defecto la política vinculada a tu token

El resultado incluye un eco de translation — verifica translation.sent para ver el símbolo y tamaño nativos exactos del exchange que llegaron al exchange:

{
  "requested": { "symbol": "BTC", "qty": 0.01, "unit": "base_asset" },
  "sent": { "symbol": "BTC-USDT-SWAP", "qty": "1", "unit": "contracts", "ctVal": "0.01" }
}
{
  "venue": "binance",
  "order_id": "...",
  "status": "FILLED",
  "filled_qty": 0.001,
  "avg_fill_price": 67128.9,
  "policy_id": "default",
  "attested_at": "..."
}

Destructivo. Requiere SIGNER_API_TOKEN. ⚠️ Las órdenes van a donde envía la política de tu token — no hay enrutamiento implícito a testnet. En Binance, si una puerta de enlace dada firma contra mainnet o testnet, y con qué límites, es una propiedad de esa implementación y de la política de tu token — esta página no puede decírtelo, y tampoco puede list_venues. En Hyperliquid, el enclave firma tanto testnet como mainnet, y mainnet adicionalmente requiere una política firmada por la autoridad que lleva límites vinculantes por activo — un blob sin ellos se rechaza al cargar, incondicionalmente. Ten en cuenta que ninguno de los exchanges de Hyperliquid es alcanzable a través de place_order / cancel_order en v0: esos llevan rutas estructuradas para binance y okx solamente. Una revisión anterior de esta sección decía "v0 enruta Binance/OKX a testnet" — eso estaba mal, consulta CHANGELOG 0.6.0.

place_hedge

Coloca una cobertura de 2 patas con firma atómica: ambas patas se firman dentro del enclave todo-o-nada (una denegación de política en cualquiera de las patas significa que nada se envía siquiera), luego la puerta de enlace dispara ambas llamadas al exchange del lado del servidor en paralelo — la brecha entre patas se reduce a la propia latencia de los exchanges y los encabezados de autenticación firmados nunca transitan por tu cliente. 🔴 Esa última parte es cierta solo de esta herramienta: get_account, place_order y cancel_order sí los transitan, por las razones en Dónde van los encabezados firmados. No leas esta frase como una propiedad del paquete. ⚠️ La ejecución en el exchange no es atómica: los estados partial y unknown a continuación existen precisamente porque un exchange puede aceptar una pata y perder o rechazar la otra.

Argumentos:

  • legs — exactamente 2, cada {venue, symbol, side, qty, type}. Restricciones v1: type: "market" solamente (una pata límite en reposo permitiría que "ejecutado" oculte una pata no llenada — usa place_order para límites) y exchanges limitados a binance | okx. Cobertura típica: mismo símbolo, lados opuestos, cantidad igual del activo base en dos exchanges.
  • Los símbolos y qty usan la misma traducción canónica/activo base que place_order; los translations por pata se devuelven.

Lee el status del resultado antes que cualquier otra cosa:

  • executed — ambas patas vivas.
  • partial — 🔴 exactamente una pata viva: la posición está DESCUBIERTA. Repara cerrando la pata viva o recolocando la pata rejected. Nunca recoloces una pata cuyo resultado es unknown.
  • unknown — 🔴 se perdió el recibo de una pata (tiempo de espera / 5xx del exchange) — esa orden puede estar viva. NO reintentes place_hedge; concilia primero vía get_account en ambos exchanges.
  • failed — ambas patas definitivamente rechazadas, nada vivo, seguro corregir y reintentar.

Destructivo (mueve posiciones reales en dos exchanges a la vez). Requiere SIGNER_API_TOKEN. Las puertas de enlace más antiguas que el endpoint /hedge devuelven un error claro de "usa dos llamadas place_order".

cancel_order

Cancela una orden pendiente por su id de orden del exchange. Idempotente — cancelar una orden ya llenada o inexistente devuelve ok: false con una razón del exchange en lugar de un error.

Disponible para binance | okx en v0 — otros exchanges no tienen una ruta de cancelación estructurada todavía y devuelven un error claro (misma limitación que place_order). Los encabezados firmados para esta llamada pasan a través de tu cliente — consulta Dónde van los encabezados firmados.

Argumentos:

  • venue — binance | okx
  • order_id — el id del exchange devuelto por place_order
  • symbol — requerido (canónico BTC o nativo del exchange; traducido exactamente como place_order) — las rutas de cancelación REST de ambos exchanges lo necesitan junto con order_id

Requiere SIGNER_API_TOKEN.


Verificando la atestación

Un Signer confiable es aquel cuya medición del enclave coincide con una compilación que puedas auditar. El flujo de trabajo:

  1. Llama a get_attestation. Verifica que verified sea verdadero y lee pcr0 — la herramienta ya lo ha extraído del documento firmado, verificado el nonce que acaba de enviar, recorrido la cadena de certificados y comparado la raíz contra la huella digital fijada. Si verified es falso, detente aquí: checks nombra cuál falló.
  2. Pregunta a la cadena, que no es nuestra para editar. Llama a isPCR0Active(pcr0) en 0x38b42eED740b0fDeb211bBDf773F2238cAEec240 (Base). Devuelve dos valores y ambos deciden: si esa medición está activa, y la dirección del propietario que la registró. Lee lo que responde en lugar de buscar una respuesta particular — el registro mantiene una medición activa por propietario, por lo que cuál de nuestros carriles la tiene se mueve con el tiempo.
  3. Encuentra la misma medición en la tabla de etiquetas de docs/REPRODUCIBLE-BUILD.md. Las etiquetas allí se nombran pcr0-<first eight hex of the measurement> y cada fila nombra el commit del que se cortó y el carril para el que se cortó.
  4. Reconstruye el EIF desde ese commit y compara el número que obtienes contra el del que empezaste: VERIFY-SIGNER-YOURSELF. Este es el paso que no necesita nada de nosotros en absoluto.

Detente y no operes si alguna de estas es verdadera — y la primera es fácil de pasar por alto:

  • el registro nombra un propietario que no reconoces. Una medición puede estar activa y registrada por otra persona por completo; "activa" por sí sola no es un pase, y una verificación del propietario que solo ocurre en tu cabeza no es una verificación.
  • el registro dice que esa medición no está activa;
  • la tabla de etiquetas no nombra tu medición;
  • tu propia reconstrucción produce un número diferente.

Abre un issue en cualquiera de esos casos.

🔴 Por qué esto ya no te lleva primero a nuestra página. La página en usenami.io/signer/attestations lee su valor en vivo desde el gateway público de demostración — verificado: el propio marcado de la página llama a signer-demo.usenami.io:8443/attestation. Ese no es necesariamente el servidor con el que tu MCP server se comunica. Cuando dos de nuestros servidores ejecutan la misma medición, comparar uno contra el otro parece verificación y no prueba nada: estarías comprobando un gateway contra otro gateway, ambos nuestros.

Eso no es hipotético hoy. La tabla de etiquetas enlazada arriba lista tres mediciones, dos de ellas retiradas, y registra producción y el demo público compartiendo una medición desde 2026-09-11 — así que ahora mismo la comparación coincide por casualidad, que es exactamente cuando una verificación vacía es más difícil de notar.

La página sigue valiendo la pena leerla: contiene la dirección del registro y la receta de reconstrucción. Pero las tres cosas que pueden contradecirnos — la cadena, la tabla de etiquetas y tu propio build — son las que deciden, y ninguna de ellas es un servidor que operamos.


Lo que v0 deliberadamente NO hace

v0 mantiene la superficie deliberadamente limitada:

  • Sin multi-tenant: una cuenta por venue por token.
  • Sin interfaz de edición de UPL: las políticas se configuran fuera de banda en usenami.io/signer.
  • Sin herramientas WebSocket / streaming — solo REST.
  • Sin enrutamiento entre venues (place_order toma un solo venue; la única herramienta multi-venue es el place_hedge fijo de 2 patas).
  • Sin configuración de apalancamiento (set_leverage) — usa los valores predeterminados de la cuenta.
  • Sin retiros / transferencias (lo más cercano es cancel_order).
  • Sin TWAP / iceberg — solo órdenes de un solo disparo.
  • Solo transporte stdio — sin SSE ni HTTP remoto.

Si necesitas cualquiera de lo anterior, abre un issue describiendo el caso de uso. v0 mantiene la superficie limitada a propósito.


Desarrollo

# install deps
npm install

# typecheck + build
npm run build

# run from source against the hosted demo enclave
SIGNER_GATEWAY_URL=https://signer-demo.usenami.io:8443 \
SIGNER_API_TOKEN=sk_test_... \
npm run dev

El transporte es stdio; necesitarás un cliente compatible con MCP para ejercitar realmente las herramientas. El mcp-inspector de Anthropic es la forma más rápida de probarlo localmente.


Licencia

MIT. Ver LICENSE.