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)
-
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_venuesyget_attestationno necesitan token. Nota qué hace realmente cada uno, porque solo uno de ellos habla con nosotros:get_attestationobtiene un documento vivo firmado por NSM desde la puerta de enlace, mientras quelist_venuesresponde desde un manifiesto estático compilado en este paquete y no hace ninguna llamada de red. -
Edita
claude_desktop_config.json. La ruta es~/Library/Application Support/Claude/claude_desktop_config.jsonen 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 incluyendo0.5.0tiene por defectoSIGNER_GATEWAY_URLahttps://signer.usenami.io, que301-redirige cada ruta a la página de aterrizaje de marketing. Las herramientas de red entonces reciben HTML y mueren conUnexpected token '<'.0.6.0cambió 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.
-
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 queget_verified_pricese lanzó.) -
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.
-
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):
| Variable | Requerida | Valor por defecto | Notas |
|---|---|---|---|
SIGNER_GATEWAY_URL | no | https://signer-demo.usenami.io:8443 | El enclave de demostración atestiguado alojado. Sobrescribe para despliegues autoalojados. |
SIGNER_API_TOKEN | sí (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_MS | no | 30000 | Tiempo 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_KEY | solo 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 venue | estado | clase de activo | esquema de autenticación | ejemplo de símbolo | notas |
|---|---|---|---|---|---|
binance | vivo | perp | hmac_sha256 | BTCUSDT | Futuros USD-M de Binance. ⚠️ Asume mainnet, fondos reales — la red la establece la política de tu token, no esta tabla |
okx | vivo | perp | hmac_sha256 | BTC-USDT-SWAP | Swap 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) |
asterdex | vivo | perp | eip712 (bsc) | BTC-USD | Perp en cadena de Asterdex (BSC) |
kucoin | vivo | perp | hmac_sha256 | XBTUSDTM | Futuros de KuCoin (HMAC + frase de contraseña cifrada); cantidad en contratos |
bybit | vivo | perp | hmac_sha256 | BTCUSDT | Bybit V5 lineal (category=linear) |
hyperliquid_testnet | vivo | perp | eip712 (hyperliquid) | BTC | Mismo código de enclave que mainnet, fuente de agente fantasma de testnet. No alcanzable vía place_order/cancel_order en v0 |
hyperliquid_main | vivo | perp | eip712 (hyperliquid) | BTC | Solo 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ón | qué evita |
|---|---|
| el indexador firmó los bytes exactos que llegaron | un 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ón | una firma de nadie en particular |
| la lectura es un precio utilizable | una 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 subgrafo | una 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_attestationexiste 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 debinance | okx | asterdex | kucoin | bybit | hyperliquid_testnet | hyperliquid_main. ⚠️ v0 tiene rutas de orden estructuradas parabinance | okxsolamente — otros exchanges devuelven un error claro (exponen acceso de solo lectura a la cuenta); y verificalist_venuesstatusprimerosymbol— 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|sellqty— 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 enBTC-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|limitprice— requerido sitype=limit, ignorado sitype=marketpolicy_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 — usaplace_orderpara límites) y exchanges limitados abinance | okx. Cobertura típica: mismo símbolo, lados opuestos, cantidad igual del activo base en dos exchanges.- Los símbolos y
qtyusan la misma traducción canónica/activo base queplace_order; lostranslationspor 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 patarejected. Nunca recoloces una pata cuyo resultado esunknown.unknown— 🔴 se perdió el recibo de una pata (tiempo de espera / 5xx del exchange) — esa orden puede estar viva. NO reintentesplace_hedge; concilia primero víaget_accounten 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 | okxorder_id— el id del exchange devuelto porplace_ordersymbol— requerido (canónicoBTCo nativo del exchange; traducido exactamente comoplace_order) — las rutas de cancelación REST de ambos exchanges lo necesitan junto conorder_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:
- Llama a
get_attestation. Verifica queverifiedsea verdadero y leepcr0— 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. Siverifiedes falso, detente aquí:checksnombra cuál falló. - Pregunta a la cadena, que no es nuestra para editar. Llama a
isPCR0Active(pcr0)en0x38b42eED740b0fDeb211bBDf773F2238cAEec240(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. - Encuentra la misma medición en la tabla de etiquetas de
docs/REPRODUCIBLE-BUILD.md. Las etiquetas allí se nombranpcr0-<first eight hex of the measurement>y cada fila nombra el commit del que se cortó y el carril para el que se cortó. - 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_ordertoma un solo venue; la única herramienta multi-venue es elplace_hedgefijo 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.