qURL

qURL é o portal para a internet invisível — URLs com expiração e escopo limitado que permitem que agentes de IA acessem serviços que ninguém mais pode ver.

Documentação

@layervai/qurl-mcp

npm version

⚠️ Renomeado de @layerv/qurl-mcp na v0.4.0. O pacote antigo está obsoleto e não receberá mais atualizações. Se você está usando @layerv/qurl-mcp@0.3.x, troque o escopo na configuração do seu cliente MCP — mesmo binário, mesma chave de API, nenhuma outra alteração.

Um servidor MCP qURL que suporta tanto o modo local stdio quanto o modo remoto HTTP para criar, gerenciar, resolver e compartilhar links de acesso seguros.

Visão geral

qURL MCP expõe os recursos do qURL para clientes MCP, GPTs, ChatGPT e outras integrações remotas.

Atualmente suporta:

  • criar, ler, atualizar e excluir qURLs
  • resolver tokens de acesso
  • gerenciar tokens e sessões qURL
  • enviar conteúdo de texto ou arquivo e gerar qURLs
  • opcionalmente servir páginas legais públicas da LayerV
  • servir uma página de reprodução de vídeo MP4 configurável

Início rápido: sem necessidade de conta

Compartilhe um aplicativo em execução na sua máquina, ou uma URL, de forma privada pelo Claude Desktop, Claude Code, Cursor, Codex ou qualquer cliente MCP local. Você não precisa de conta nem chave de API: sem QURL_API_KEY definido, o servidor aciona o CLI qURL instalado na sua máquina, e a primeira publicação cria a identidade desta máquina por conta própria.

1. Instale o CLI qURL (macOS e Linux; Node.js 22.12 ou posterior é necessário para o servidor MCP):

(umask 022 && mkdir -p "$HOME/.local/bin" "$HOME/.local/state") && chmod go-w "$HOME/.local" "$HOME/.local/bin" "$HOME/.local/state" && curl -fsSL --proto '=https' https://raw.githubusercontent.com/layervai/qurl-integrations/main/scripts/install.sh | INSTALL_DIR="$HOME/.local/bin" sh

No Windows, baixe o qurl.exe do último lançamento e coloque sua pasta no PATH. O servidor encontra o qurl no PATH, e também em ~/.local/bin, /opt/homebrew/bin e /usr/local/bin, que muitos clientes MCP deixam de fora do PATH que fornecem aos servidores. Se o CLI estiver ausente, todas as ferramentas respondem com este comando de instalação em vez de falhar.

2. Adicione o servidor ao seu cliente MCP, sem bloco env.

Claude Desktop (claude_desktop_config.json) e Cursor (~/.cursor/mcp.json):

{
  "mcpServers": {
    "qurl": {
      "command": "npx",
      "args": ["-y", "@layervai/qurl-mcp"]
    }
  }
}

Codex (~/.codex/config.toml):

[mcp_servers.qurl]
command = "npx"
args = ["-y", "@layervai/qurl-mcp"]

Claude Code:

claude mcp add qurl -- npx -y @layervai/qurl-mcp

3. Peça o que você quer, por exemplo "compartilhe o aplicativo em localhost:3000 com meu cliente". O agente publica o aplicativo (ele permanece na sua máquina; o serviço em segundo plano do CLI mantém o compartilhamento ativo) e fornece um link de curta duração para uma pessoa, ou ativa solicitações de acesso para que as pessoas possam pedir acesso.

Ferramentas sem conta

FerramentaO que fazComando CLI
publish_cridPublicar um aplicativo local ou URL de forma privada e retornar seu CRIDqurl publish <url> [--allow-requests] [--access <mode>]
share_by_cridCriar um link de acesso de curta duração para um CRID publicado por esta máquinaqurl share <CRID> [--ttl] [--session-duration]
list_cridsListar os recursos publicados desta máquina (somente leitura)qurl list --status active
manage_crid_requestsListar, aprovar por código ou negar solicitações de acesso; listar ou remover pessoas aprovadas; ativar ou desativar solicitaçõesqurl requests, qurl approve, qurl deny, qurl grants
manage_crid_accessPolítica de acesso privado, convites e concessões de consumidoresqurl access <action> <CRID>
set_crid_sharingParar, iniciar ou reiniciar o compartilhamento de um aplicativo localqurl stop, qurl start, qurl restart
delete_cridExcluir um recurso permanentementequrl delete <CRID> --yes

As ferramentas seguem as mesmas regras da habilidade de agente qURL (https://layerv.ai/skills/qurl/SKILL.md):

  • Tudo é publicado de forma privada. Estas ferramentas não têm opção de publicação pública.
  • Uma solicitação de acesso pendente é aprovada somente com o código de seis dígitos que a pessoa fornece. Nenhuma listagem mostra um código, e nenhuma ferramenta aprova por nome: qualquer pessoa pode digitar qualquer nome, e os nomes retornam como dados não verificados.
  • Um link de acesso é um segredo portador para um destinatário. Um CRID não concede nada por si só e é seguro compartilhar.

O servidor executa o CLI com uma matriz de argumentos (nunca um shell), com saída JSON, stdin fechado, timeout e saída limitada, e não registra o que o CLI imprime. As ferramentas que precisam de chave de conta (as ferramentas de link, token, sessão e upload do qURL, e os recursos e prompts qurl://) não são listadas neste modo.

Com chave de conta

Defina QURL_API_KEY para uma chave de API LayerV e o servidor usa a API qURL diretamente, com o conjunto completo de ferramentas descrito no mapa de recursos:

{
  "mcpServers": {
    "qurl": {
      "command": "npx",
      "args": ["-y", "@layervai/qurl-mcp"],
      "env": { "QURL_API_KEY": "lv_live_xxx" }
    }
  }
}

Servidor HTTP remoto

O transporte HTTP (qurl-mcp-http) atende runtimes de agentes remotos. Ele é baseado em conta: cada solicitação carrega a chave de API qURL do chamador como token portador, e nunca executa um CLI local. Consulte Autenticação HTTP e o guia MCP da LayerV.

Acesso privado do consumidor

Node.js 22.12 ou posterior é necessário pelo SDK qURL compartilhado.

publish_crid cria um recurso de URL privado com acesso por chaves, somente convite, captura de e-mail, revisão ou contrato. manage_crid_access altera a política com sua versão atual, envia convites, lista concessões, aprova ou nega solicitações e remove acesso. As ferramentas retornam recibos com escopo de recurso e omitem segredos de convite e links portadores. Aplicativos locais usam o CLI qURL na máquina do publicador.

Por exemplo, um assistente pode transformar "compartilhe isso com ana@example.com e não permita solicitações" em um recurso somente convite e um convite autorizado. Para captura de e-mail, o consumidor deve saber que o publicador recebe seu e-mail verificado. Um e-mail verificado prova controle da caixa de entrada, não identidade legal. A aprovação de contrato requer um recibo de direito de backend confiável do publicador; estas ferramentas não verificam pagamento. Não relate a remoção de conexão como concluída enquanto session_cleanup estiver pendente.

Este recurso requer o serviço correspondente e leitores de admissão. Mantenha-o desativado até que os fluxos do publicador e do consumidor passem. O pacote fixa o SDK 3.0.0 publicado e suporta instalação limpa com scripts de dependência bloqueados. Esta versão requer Node.js 22.12 ou posterior; Node.js 20 não é mais suportado.

Modos de execução

ModoPropósitoComando de inícioCaso de uso típico
stdioServidor MCP subprocesso localnpm run startClaude Desktop, Cursor, Codex e outros clientes MCP locais
httpServidor MCP remoto autenticadonpm run start:httpRuntimes de agentes remotos atrás de HTTPS

Mapa de recursos

Ferramentas de gerenciamento qURL

FerramentaDescrição
create_qurlCriar um novo qURL
resolve_qurlResolver um token de acesso em uma URL de destino protegida
list_qurlsListar recursos qURL
get_qurlBuscar detalhes de um único qURL
delete_qurlExcluir um qURL
extend_qurlEstender a expiração de um link (precisa de qurl:read também)
update_qurlAtualizar metadados ou expiração do qURL
mint_linkCriar um novo link de acesso para um recurso existente
share_by_cridCriar um link de acesso temporário a partir de um CRID de recurso
batch_create_qurlsCriar vários qURLs em uma única solicitação
revoke_qurl_tokenRevogar um token específico
update_qurl_tokenAtualizar um token específico
list_qurl_sessionsListar sessões de acesso ativas
terminate_qurl_sessionsEncerrar uma ou todas as sessões ativas

share_by_crid reconhece um valor $<CRID> isolado como uma solicitação explícita para criar um link temporário para esse CRID. O $ é um marcador voltado ao usuário e é removido antes que o CRID seja enviado à API qURL. Um CRID simples permanece suportado. Esta ferramenta requer qurl:resolve. Seu ttl opcional no formato de duração Go deve resolver para um número inteiro positivo de segundos. O serviço limita o tempo de vida solicitado. O compartilhamento faz uma solicitação com timeout de 30 segundos e não tenta novamente automaticamente. Repetir a chamada da ferramenta pode criar outro link.

Os filtros de status de recurso aceitam active, revoked ou active,revoked. Um recurso permanece ativo ou revogado mesmo quando seu expires_at está no passado; tokens de acesso individuais podem expirar. expired não é aceito por list_qurls, embora a análise da resposta tolere valores legados. O instantâneo mantém o texto de expiração desatualizado do upstream; seu enum de status ativo/revogado é autoritativo.

O SDK qURL reutiliza o mesmo Idempotency-Key e corpo de solicitação ao tentar novamente solicitações POST/PATCH após falha de rede ou HTTP 429. Respostas HTTP 5xx mutáveis não são tentadas novamente automaticamente. Cada nova invocação de ferramenta MCP é uma nova operação com uma nova chave, então repetir create_qurl, batch_create_qurls ou mint_link pode criar tokens adicionais. O MCP não expõe uma chave fornecida pelo chamador.

Ferramentas de upload

FerramentaModoDescrição
upload_file_qurlstdioEnviar um arquivo local e criar um qURL
upload_file_data_qurlstdio/HTTPEnviar conteúdo de arquivo em base64 e criar um qURL
upload_text_qurlstdio/HTTPEnviar conteúdo de texto e criar um qURL
upload_file_qurl é intencionalmente apenas stdio. Ele pode ler qualquer
PDF/imagem suportado que o usuário do processo MCP local possa acessar, portanto,
agentes devem invocá-lo apenas para um caminho que o usuário selecionou
explicitamente para compartilhamento. Não o exponha a prompts não confiáveis
ou agentes autônomos: injeção de prompt poderia, de outra forma, selecionar
outro PDF/imagem legível no host. Execute stdio sob uma conta de sistema
operacional cujo acesso ao sistema de arquivos seja limitado ao conteúdo
compartilhável pretendido. O modo HTTP nunca registra esta ferramenta de
arquivo do host.
As ferramentas de byte/texto também estão disponíveis em stdio para que
clientes locais possam compartilhar anexos no chat sem primeiro materializá-los
em um caminho conhecido do host.
O upload do conector e a criação de links são operações separadas. O link vem
do POST /api/mint_link/:resource_id do conector (no modo túnel, uma
visualização com marca d'água por destinatário), não do qURL mint_link, portanto,
arquivos enviados não podem ser re-linkados com mint_link; execute a ferramenta
de upload novamente. Links de upload suportam expires_in (1m-30d, convertido
para uma expiração absoluta no relógio do host MCP, portanto, um relógio do host
que esteja desregulado encurta ou alonga o link; um link cuja expiração retornada
já passou pelo relógio deste host é retornado com expires_at_already_past), one_time_use e
session_duration (segundos inteiros, até 24h); access_policy e
max_sessions devem ser omitidos ou nulos; valores não nulos são rejeitados
antes do upload. Se o conector criar mais links do que o solicitado, o resultado
relata quantos extras em unexpected_extra_link_count e quaisquer IDs que ele retornou em
unexpected_extra_qurl_ids (no máximo 10); eles podem estar ativos mesmo quando o relógio
deste host sugere expiração, então informe o usuário. Se a criação falhar após o
upload, o conector atualmente não tem endpoint de exclusão; o servidor registra o
resource_id órfão para limpeza pelo operador e retorna a falha de criação.
Links de upload ainda não podem ser revogados deste servidor: delete_qurl no
resource_id do upload não interrompe um link criado pelo conector (a revogação
precisa do /api/revoke_links do conector), portanto, prefira expirações curtas para
arquivos sensíveis.
Entradas de duração aceitam dias ou semanas inteiros (7d, 1w),
ou sequências de unidades Go sem sinal (1h30m, 1.5h). Sequências
mistas de dias/semanas (1d12h), sinais iniciais, frações com ponto
inicial e mu grego (μs) são rejeitados; o sinal de micro (µs)
é aceito.
Tentativas de upload HTTP permanecem limitadas pelos limites de taxa MCP por IP
e por credencial; operadores de stdio devem restringir separadamente loops de
repetição autônomos.
A validação de upload vincula o tipo de mídia declarado ao nome do arquivo mais
marcadores de início/fim de formato; não é um scanner de malware nem um
decodificador completo de PDF/imagem.
Para resistência a poliglotas, o marcador final %%EOF de um PDF deve ser
seguido apenas por espaços em branco ASCII; a saída do produtor com outros bytes
finais é rejeitada mesmo que um leitor de PDF permissivo a aceitasse. A validação
JPEG verifica enquadramento e marcadores terminais em vez de decodificar
segmentos de imagem. O conector autenticado deve decodificar ou validar
completamente o conteúdo de forma independente antes do armazenamento quando a
validade semântica da mídia for importante. Ele também deve preservar o tipo de
mídia seguro declarado e servir downloads com `X-Content-Type-Options:
nosniff` em vez de inferir um tipo executável.
Não há intencionalmente uma lista de permissões de caminho em nível de
aplicação: symlinks e corridas de tempo-de-verificação/tempo-de-uso tornam uma
verificação de prefixo lexical um limite de segurança enganoso. Use uma conta de
SO dedicada, contêiner ou montagem somente leitura cujos arquivos legíveis já
estejam limitados ao diretório de compartilhamento pretendido.
O componente final do caminho é aberto com O_NOFOLLOW; symlinks de diretórios
intermediários mantêm o comportamento normal do sistema de arquivos sob este
limite de usuário local confiável.

Recursos MCP

URIDescrição
qurl://linksLista qURL atual
qurl://usageInformações atuais de cota e uso

Prompts MCP

PromptDescrição
secure_a_servicePrompt de integração segura de serviço
audit_linksPrompt de auditoria de links
rotate_accessPrompt de rotação de acesso

Início Rápido

1. Instalar Dependências

npm install

Para uma instalação local apenas stdio a partir da fonte, use npm install --omit=optional; isso omite o AWS SDK. Implantações HTTP que usam a cota de credenciais DynamoDB devem usar a instalação comum para que o SDK opcional seja empacotado.

2. Compilar

npm run build

3. Iniciar

Modo stdio local:

npm run start

Modo HTTP remoto:

npm run start:http

Exemplo de Cliente MCP

Se você quiser usar este servidor no modo stdio com um cliente MCP local, use a configuração de Início rápido. Deixe de fora env para trabalhar sem uma conta por meio do CLI qURL local, ou adicione "env": { "QURL_API_KEY": "lv_live_xxx" } para usar a API qURL com uma chave de conta.

Arquivos de Configuração

Copie os exemplos rastreados para criar arquivos de configuração locais:

cp qurl-mcp.config.example.json qurl-mcp.config.json
cp qurl-mcp.http.example.json qurl-mcp.http.json

Os arquivos locais são ignorados pelo git, portanto, credenciais e caminhos específicos da máquina não são commitados.

Suas responsabilidades são:

ArquivoPropósito
qurl-mcp.config.jsonConfiguração de runtime compartilhada usada pelos modos stdio e http
qurl-mcp.http.jsonConfiguração de listener e acesso público do servidor apenas HTTP

Referência do qurl-mcp.config.json

Configurações Centrais Compartilhadas

CampoPropósito
maxUploadFileDataBytesLimita uploads decodificados e de arquivos locais (padrão 10mb)
defaultQurlApiUrlURL base da API de backend qURL
defaultQurlConnectorUrlURL base do conector de upload

As configurações compartilhadas têm estas substituições de ambiente. Os valores de ambiente têm precedência sobre o arquivo de configuração compartilhado. O processo armazena em cache as configurações compartilhadas resolvidas, mas invalida automaticamente esse cache quando os metadados do arquivo ou qualquer valor de ambiente relevante muda.

Variável de ambienteCampo de configuração
MCP_MAX_UPLOAD_FILE_DATA_BYTESmaxUploadFileDataBytes
QURL_API_URLdefaultQurlApiUrl
QURL_CONNECTOR_URLdefaultQurlConnectorUrl
QURL_SMTP_HOSTsmtp.host
QURL_SMTP_PORTsmtp.port
QURL_SMTP_SECUREsmtp.secure
QURL_SMTP_USERNAMEsmtp.username
QURL_SMTP_PASSWORDsmtp.password
QURL_SMTP_FROM_EMAILsmtp.fromEmail
QURL_SMTP_FROM_NAMEsmtp.fromName
QURL_SMTP_ALLOWED_RECIPIENTSsmtp.allowedRecipients
QURL_SMTP_ALLOWED_RECIPIENT_DOMAINSsmtp.allowedRecipientDomains
QURL_SMTP_MAX_RECIPIENTS_PER_MESSAGEsmtp.maxRecipientsPerMessage
QURL_SMTP_MAX_RECIPIENTS_PER_HOURsmtp.maxRecipientsPerHour
QURL_PUBLIC_VIDEO_FILE_PATHpublicVideo.filePath
QURL_PUBLIC_VIDEO_TITLEpublicVideo.title
QURL_PUBLIC_VIDEO_PAGE_PATHpublicVideo.pagePath

QURL_API_KEY é intencionalmente apenas de ambiente e não tem campo de arquivo de configuração. Prefira QURL_SMTP_PASSWORD para o segredo SMTP também. Se smtp.password for armazenado no arquivo de configuração em um host POSIX, restrinja esse arquivo a permissões somente do proprietário (por exemplo, chmod 600); a inicialização avisa quando bits de leitura de grupo/outros estão presentes. Esta verificação é intencionalmente consultiva para que implantações existentes não falhem após uma atualização, e é ignorada no Windows porque os bits de modo POSIX não estão disponíveis lá. A entrega de e-mail em si é fechada em caso de falha, a menos que pelo menos uma entrada exata de smtp.allowedRecipients ou uma entrada de smtp.allowedRecipientDomains seja configurada; a inicialização avisa quando credenciais SMTP completas não têm essa política.

Aumentar maxUploadFileDataBytes também aumenta o teto de memória por solicitação do parser JSON HTTP para aproximadamente 1,5 vezes esse valor (até cerca de 150 MB no máximo de 100 MB), antes que a decodificação base64 aplique o limite exato de bytes. Até que uma sessão tenha concluído uma chamada bem-sucedida à API qURL downstream (a criação de link de um upload concluído conta), seu teto de parser permanece na configuração padrão menor de upload de 10 MB; clientes configurados para um primeiro upload maior devem validar a sessão com uma chamada pequena à API qURL ou um upload menor primeiro. Dimensione o máximo configurado e o limite de concorrência do proxy reverso juntos.

Defina QURL_API_KEY no ambiente para o modo stdio usar a API qURL. Sem ele, o modo stdio executa por meio do CLI qURL local e não precisa de conta (veja Início rápido). No modo HTTP, cada solicitação de cliente fornece sua própria chave de API qURL como token bearer.

defaultQurlApiUrl e QURL_API_URL exigem HTTPS para hosts que não são de loopback porque chaves e dados da API qURL são enviados como bearer para esse destino. HTTP simples é aceito apenas para endpoints literais de desenvolvimento em loopback. URLs do conector de upload seguem a mesma regra HTTPS-exceto-loopback. Loopback significa 127.0.0.0/8 ou ::1; endereços de bind curinga, como 0.0.0.0 e ::, são intencionalmente não aceitos como destinos HTTP de saída. Destinos do conector são configuração confiável do operador, não entrada do chamador; endereços privados e resolução de DNS são, portanto, permitidos. Fixe o nome do host do conector no DNS de implantação e não o aponte para serviços de metadados. A credencial bearer qURL do chamador é encaminhada para este host, portanto, trate o controle de URL e DNS do conector como parte do limite de confiança da credencial. Configure a URL base do serviço do conector, não uma rota de upload: o qurl-mcp anexa /api/upload a caminhos base comuns, aceita esse sufixo de endpoint exato e rejeita caminhos ambíguos semelhantes a upload, como /upload ou /api/upload/v2. O servidor MCP executa verificações limitadas de enquadramento de arquivo, não análise completa de mídia; o conector deve revalidar independentemente o conteúdo enviado antes do armazenamento ou serviço, e a entrega deve manter o comportamento de nosniff como o limite de tipo autoritativo.

URLs base de API e conector que contêm credenciais incorporadas, uma string de consulta ou um fragmento agora são rejeitados durante a inicialização. Implantações que usavam anteriormente uma dessas formas incomuns de URL devem mover credenciais para QURL_API_KEY e manter a URL de serviço configurada em sua origem e prefixo de caminho opcional.

Configurações SMTP

CampoFinalidade
smtp.hostNome do host do servidor SMTP
smtp.portPorta do servidor SMTP
smtp.securetrue para TLS implícito; false para STARTTLS obrigatório
smtp.usernameNome de usuário de login SMTP
smtp.passwordSenha de login SMTP ou código específico do aplicativo
smtp.fromEmailEndereço de e-mail do remetente
smtp.fromNameNome de exibição do remetente
smtp.allowedRecipientsLista de permissões opcional de endereços exatos
smtp.allowedRecipientDomainsLista de permissões opcional de domínios exatos (subdomínios não são incluídos)
smtp.maxRecipientsPerMessageLimite de destinatários por mensagem (padrão 10)
smtp.maxRecipientsPerHourLimite de destinatários tentados por chave qURL por janela horária fixa (padrão 100)

Estas configurações são usadas quando o envio de e-mail é solicitado por ferramentas como:

  • create_qurl
  • mint_link
  • upload_text_qurl
  • upload_file_qurl
  • upload_file_data_qurl

Se qualquer lista de permissões de destinatários estiver configurada, apenas um endereço ou domínio exato é entregue. Se ambas estiverem vazias, os limites de mensagem e horário ainda se aplicam. Entradas de domínio são exatas: example.com não permite implicitamente mail.example.com; liste cada subdomínio permitido explicitamente. Endereços e domínios são normalizados para minúsculas NFC/IDNA ASCII e um ponto raiz de DNS final é removido antes da comparação e entrega. Cada lista de permissões de destinatários é limitada a 1.000 entradas configuradas. O limite de destinatários por mensagem se aplica ao fan-out único solicitado completo antes da filtragem da lista de permissões, portanto endereços bloqueados não podem ser usados para enviar um lote superdimensionado. No modo HTTP, qualquer chamador com uma chave de API qURL válida pode solicitar uma entrega SMTP no lado do servidor. Configure allowedRecipients ou allowedRecipientDomains antes de habilitar SMTP em uma implantação HTTP voltada para a Internet; listas de permissões vazias permitem entrega a qualquer endereço sintaticamente válido sujeito às cotas. O transporte SMTP usa timeouts limitados de conexão/socket e é fechado após cada lote de entrega. Tentativas SMTP com falha ainda consomem cota—incluindo quando uma interrupção transitória resulta em zero mensagens entregues—portanto falhas repetidas não podem contornar o limite de abuso. Cada solicitação de entrega também tem um prazo agregado de 60 segundos. Destinatários não iniciados antes desse prazo são relatados como pulados; filas do lado do provedor são o caminho suportado para fan-out maior ou mais lento. A criptografia de transporte é obrigatória: smtp.secure: true usa TLS implícito, enquanto smtp.secure: false exige uma atualização STARTTLS bem-sucedida. A porta 465 é reservada para TLS implícito e, portanto, exige smtp.secure: true. O estado da cota horária é mantido por processo do servidor: ele é redefinido na reinicialização e não é compartilhado entre réplicas. Operadores que executam múltiplas instâncias devem aplicar um limite agregado correspondente no provedor SMTP ou gateway. A cota no processo é, portanto, uma proteção contra abuso, não um limite global durável de segurança; o comportamento fail-open de reinicialização/escala horizontal deve ser coberto por esse limite do lado do provedor. O rastreamento falha fechado para novos principais após 10.000 principais serem retidos em um processo; principais existentes continuam usando seus buckets atuais até que entradas expiradas sejam removidas. Restrinja a emissão de chaves de API qURL e monitore rejeições de cota de novos principais: alternar muitas chaves válidas pode deliberadamente manter essa tabela compartilhada na capacidade por até uma janela de cota. A cota usa uma janela horária fixa que começa com a primeira entrega tentada após a janela anterior expirar. Como em qualquer janela fixa, o tráfego imediatamente antes e depois de um limite pode totalizar quase o dobro do valor horário configurado; use um limite deslizante ou contínuo do lado do provedor quando esse pico de limite precisar ser evitado entre réplicas.

A entrega SMTP HTTP é restrita à credencial do operador configurada em QURL_API_KEY. Uma chave qURL válida de um cliente diferente não autoriza o uso da conta SMTP do operador. Sem essa chave explícita do operador, o envio de e-mail HTTP é desabilitado. Stdio mantém seu modelo de confiança do operador local. Listas de permissões de destinatários e cotas se aplicam em ambos os modos.

Links qURL gerados são incluídos no corpo do e-mail em texto simples. Restrinja destinatários com as listas de permissões SMTP e configure a criptografia de transporte no servidor/provedor SMTP quando a confidencialidade do link for importante.

Prefira variáveis de ambiente para credenciais e políticas SMTP: QURL_SMTP_USERNAME, QURL_SMTP_PASSWORD, QURL_SMTP_FROM_EMAIL, QURL_SMTP_ALLOWED_RECIPIENTS, QURL_SMTP_ALLOWED_RECIPIENT_DOMAINS, QURL_SMTP_MAX_RECIPIENTS_PER_MESSAGE, e QURL_SMTP_MAX_RECIPIENTS_PER_HOUR.

Configurações da Página Pública de Vídeo

CampoFinalidade
publicVideo.titleTítulo exibido na página pública de vídeo
publicVideo.pagePathCaminho público da página de reprodução de vídeo
publicVideo.filePathCaminho absoluto do servidor para o arquivo MP4

Quando configurado, o servidor HTTP também expõe:

  • uma página pública de reprodução de vídeo
  • um endpoint de streaming para o arquivo MP4

publicVideo.filePath é configuração confiável do operador. O componente final deve ser um arquivo .mp4 regular sem symlink; symlinks de diretórios intermediários mantêm a resolução normal do sistema de arquivos e, portanto, devem permanecer sob controle do operador. Na inicialização, este ativo opcional é verificado e um aviso é emitido quando está ausente, vazio ou não regular, mas intencionalmente mantém o serviço MCP e /healthz disponíveis. A rota do arquivo de vídeo ainda falha fechada com 404 até que o ativo seja corrigido.

Referência do qurl-mcp.http.json

Use qurl-mcp.http.example.json para desenvolvimento local e com estado. qurl-mcp.http.stateless.example.json mostra todos os campos de armazenamento e métricas exigidos por um serviço sem estado implantado.

CampoFinalidade
portPorta do listener HTTP MCP
hostEndereço de bind HTTP MCP
baseUrlURL base pública do serviço
allowedHostsLista de permissões de hosts para validação do cabeçalho Host
trustProxyHopsContagem exata de saltos de proxy reverso confiável (padrão 0)
statelessTransporte HTTP com escopo de solicitação sem afinidade de sessão (padrão false)
maxConcurrentRequestsLimite de concorrência de POST/parser somente sem estado por processo (padrão 20)
credentialRateLimitStoreBackend do contador de credenciais: memory ou dynamodb (padrão memory)
rateLimitDynamoDbTableTabela DynamoDB usada pelo contador de credenciais compartilhado
metricsNamespaceNamespace CloudWatch EMF para métricas de saturação sem estado
metricsServiceDimensão estável de Serviço CloudWatch EMF
metricsEnvironmentDimensão estável de Ambiente CloudWatch EMF
maxSessionsLimite rígido de sessões MCP ativas (padrão 1000)
maxSessionsPerCredentialLimite de sessões ativas e inicializando por portador (padrão 20)
maxUnvalidatedSessionsLimite de sessões que não concluíram uma chamada de API qURL downstream (padrão 100)
sessionIdleTtlMsJanela de evicção por inatividade de sessão conectada (padrão 15 minutos)
sessionAbsoluteTtlMsVida útil absoluta da sessão, incluindo solicitações SSE/ferramentas ativas (padrão 24 horas)
unvalidatedSessionTtlMsPrazo absoluto de validação para sessões de portador nunca validadas (padrão 1 minuto)
mcpRateLimitPerMinuteLimite de solicitações /mcp por cliente (padrão 120)
publicFileRateLimitPerMinuteLimite de solicitações de rota pública por cliente (padrão 300)

Os campos HTTP têm substituições de ambiente correspondentes:

Variável de ambienteCampo de configuração
MCP_PORTport
MCP_HOSThost
MCP_BASE_URLbaseUrl
MCP_ALLOWED_HOSTSallowedHosts
MCP_TRUST_PROXY_HOPStrustProxyHops
MCP_HTTP_STATELESSstateless
MCP_MAX_CONCURRENT_REQUESTSmaxConcurrentRequests
MCP_CREDENTIAL_RATE_LIMIT_STOREcredentialRateLimitStore
MCP_SERVE_LAYERV_LEGAL_PAGESserveLayerVLegalPages (padrão false)
MCP_RATE_LIMIT_DYNAMODB_TABLErateLimitDynamoDbTable
MCP_METRICS_NAMESPACEmetricsNamespace
MCP_METRICS_SERVICEmetricsService
MCP_METRICS_ENVIRONMENTmetricsEnvironment
MCP_MAX_SESSIONSmaxSessions
MCP_MAX_SESSIONS_PER_CREDENTIALmaxSessionsPerCredential
MCP_MAX_UNVALIDATED_SESSIONSmaxUnvalidatedSessions
MCP_SESSION_IDLE_TTL_MSsessionIdleTtlMs
MCP_SESSION_ABSOLUTE_TTL_MSsessionAbsoluteTtlMs
MCP_UNVALIDATED_SESSION_TTL_MSunvalidatedSessionTtlMs
MCP_RATE_LIMIT_PER_MINUTEmcpRateLimitPerMinute
MCP_PUBLIC_FILE_RATE_LIMIT_PER_MINUTEpublicFileRateLimitPerMinute
MCP_MAX_UPLOAD_FILE_DATA_BYTESmaxUploadFileDataBytes (compartilhado)
O listener usa como padrão 127.0.0.1. Um host que não seja de loopback é rejeitado, a menos que
allowedHosts esteja explicitamente configurado. Defina trustProxyHops (ou
MCP_TRUST_PROXY_HOPS) para o número exato de saltos de proxy confiáveis; deixe-o em
0 para conexões diretas, para que cabeçalhos de IP encaminhado não possam falsificar chaves de rate-limit.
A allowlist de Hosts é limitada a 1.000 entradas para que a validação em tempo de requisição permaneça
delimitada mesmo sob configuração operacional patológica.
/mcp aplica a cota de requisições configurada de forma independente tanto ao
IP do cliente quanto ao digest SHA-256 do bearer autenticado. O armazenamento em memória
é local ao processo; o armazenamento DynamoDB usa um contador atômico de janela fixa
chaveado pelo digest da credencial e pelo minuto UTC. Ele nunca armazena o bearer. Como em qualquer
janela fixa, requisições em torno de uma fronteira de minuto podem totalizar quase o dobro da
cota configurada. O contrato da tabela é uma chave de partição string chamada
rate_key; a atualização atômica grava um contador numérico request_count e um
timestamp numérico de TTL expires_at. Habilite o TTL do DynamoDB em expires_at para que
linhas expiradas não se acumulem; o TTL apenas agenda limpeza assíncrona, e
o minuto na chave—não a exclusão física—reinicia a janela ativa. A role da tarefa
exige dynamodb:DescribeTable para inicialização e dynamodb:UpdateItem no
caminho da requisição. Use capacidade sob demanda ou provisione capacidade de escrita suficiente para
a taxa esperada da frota; throttling falha de forma fechada com 503 e nunca cai
de volta para a memória. O cliente usa o modo de retry padrão com no máximo duas tentativas,
um timeout de conexão de um segundo e um timeout de requisição de dois segundos que lança exceção;
esses limites explícitos restringem por quanto tempo uma requisição segura uma permissão de concorrência
durante uma falha parcial do armazenamento. A dependência opcional do AWS SDK é fixada em versão exata
de nível superior, enquanto o package lock commitado fixa seu grafo transitivo
@aws-sdk/* e @smithy/*. Qualquer bump do SDK deve atualizar o lockfile e
manter o teste de regressão de materialização de timeout com NodeHttpHandler real verde.
A dependência é carregada somente quando o armazenamento DynamoDB é selecionado, então
consumidores somente stdio podem instalar com --omit=optional. Imagens HTTP implantadas
devem incluir dependências opcionais; a inicialização falha antes de escutar se o SDK
estiver ausente ou expuser uma superfície de runtime incompatível. O cliente usa a
cadeia padrão de AWS_REGION e de provedor de credenciais; implantações ECS
normalmente obtêm ambos do ambiente da tarefa e da role da tarefa. Implantações com
reverse-proxy devem definir a contagem de saltos correta, ou todos os chamadores atrás do proxy
compartilharão o único bucket de IP do proxy. Somente a cota de credenciais do DynamoDB é
fleet-wide: o limitador de IP é local ao processo, então sua cota efetiva de frota
multiplica pela contagem de tarefas e deve ser respaldada por um limite de borda compartilhado. A
implantação gerenciada no PR #1305 do qurl-integrations-infra aplica tanto um
limite WAF por IP de origem quanto um teto agregado de frota /mcp menor, com
prova de headroom ao vivo rastreada na issue #1306. O bucket de credenciais também impede que uma
chave burle a cota de requisições rotacionando IPs de origem, enquanto
maxSessionsPerCredential impede que ela ocupe todo o pool de sessões.
Cada valor de bearer distinto retém uma entrada de bucket de credenciais para a janela
atual de um minuto. O limitador de IP executa primeiro, então a rotação de token de uma única fonte
não pode criar entradas mais rápido que mcpRateLimitPerMinute; tráfego
distribuído hostil ainda exige o limite de borda compartilhado documentado. O bucket de IP é o
principal controle em processo contra rotação arbitrária de bearer, porque strings de bearer
distintas não validadas ocupam necessariamente buckets de credenciais distintos.
No modo stateful, orce a memória do parser de sessões pendentes como
maxUnvalidatedSessions vezes aproximadamente
1,5 vezes o menor entre maxUploadFileDataBytes e 10 MB (mais cerca de 64 KiB
por requisição). Nos padrões, o teto teórico de concorrência é de cerca de
1,5 GiB. Reduza maxUnvalidatedSessions e o limite de concorrência de borda compartilhado
juntos quando a implantação tiver um orçamento de memória menor.
Credenciais de bearer são validadas de forma conclusiva pela primeira chamada bem-sucedida
à API qURL downstream. Até lá, sessões usam o teto menor de sessões pendentes
e o prazo de validação de um minuto, então strings de bearer arbitrárias não vazias
não podem ocupar todo o pool de sessões pelo TTL normal de 15 minutos. Um cliente que
executa apenas introspecção MCP permanece pendente por design; após a evicção por prazo,
ele deve reinicializar antes da próxima requisição. Os tetos de sessão e o
prazo de validação são configuráveis para clientes com lacunas maiores entre
introspecção e chamada de ferramenta. O prazo é absoluto e se aplica independentemente
da atividade, incluindo um stream SSE aberto ou uma primeira chamada de ferramenta de longa duração.
Clientes validados que desconectam sem enviar DELETE /mcp retêm seu
slot de sessão limitado por um período de graça de reconexão de 30 segundos. Uma reconexão limpa
esse prazo; caso contrário, a sessão é removida sem esperar pelo TTL ocioso mais longo. Dimensione maxSessions e o TTL ocioso para clientes que permanecem conectados
mas não realizam teardown explícito de sessão.
Sessões validadas também expiram em sessionAbsoluteTtlMs (24 horas por padrão),
mesmo durante um stream SSE ativo ou requisição de ferramenta. Isso impede que keepalives
fixem um slot de sessão global ou por credencial indefinidamente.
A primeira operação qURL downstream deve, portanto, ser concluída antes desse
prazo; uma primeira chamada de API excepcionalmente lenta pode ser interrompida e o cliente
deve reinicializar. Esse comportamento fail-closed impede que uma credencial inválida
estenda seu slot pendente com uma requisição deliberadamente de longa duração.

No teto de sessões não validadas, uma nova inicialização substitui a sessão não validada ociosa mais antiga, então handshakes de lixo não podem reservar todos os slots pelo TTL completo de validação. Sessões validadas e requisições ativas nunca são evictadas; inicializações pendentes e teardown assíncrono permanecem limitados. Tráfego sustentado ainda pode causar churn de sessões não validadas, então implantações públicas devem usar o modo stateless e controles de admissão de borda.

Aceitar um bearer não vazio durante a inicialização MCP é intencional: mantém a introspecção de protocolo disponível antes da primeira operação qURL, enquanto o teto global de sessões, o teto de sessões por credencial, o teto de sessões pendentes, o prazo absoluto e o limite de taxa de requisições limitam o uso de slots por chaves inválidas. O middleware MCP não valida a chave em si; somente uma resposta bem-sucedida da API qURL downstream promove a sessão. Erros downstream, incluindo respostas não-2xx que parecem autenticadas, não a promovem, porque um intermediário pode tê-las gerado antes de a API qURL autenticar o bearer. A promoção, portanto, assume que o endpoint HTTPS da API qURL configurado e cada intermediário confiável não armazenam em cache nem sintetizam respostas de sucesso autenticadas. Proxies reversos nesse caminho devem encaminhar a autorização e desabilitar o cache de respostas para tráfego da API qURL. Consequentemente, qualquer chamador com um bearer não vazio pode enumerar o catálogo público de ferramentas/recursos/prompts e segurar brevemente estado de sessão pendente limitado. Em redes hostis, coloque implantações não-loopback atrás de um proxy ciente de identidade que preserve a credencial de bearer qURL do chamador para autorização /mcp. Inicialização e listagem de catálogo retornam apenas metadados estáticos de propriedade do servidor; elas não invocam handlers de ferramentas/recursos/prompts, não leem arquivos do host, não contatam a API qURL ou o conector, nem enviam e-mail. Chamadas de handler dependem da API qURL configurada para autenticar o bearer encaminhado antes de retornar dados ou aplicar uma operação. O conector configurado é uma segunda autoridade de credencial: ele deve autenticar o bearer qURL encaminhado antes de aceitar ou armazenar bytes de upload. Implantar um conector não autenticado não é suportado, pois permitiria que um chamador MCP não validado criasse estado no lado do conector.

O modo stateful é o padrão de compatibilidade e mantém o registro de sessão MCP existente, GET SSE, comportamento explícito de DELETE e cobrança de cota de credencial local ao processo para todos os três métodos MCP. O modo stateless cria e fecha um servidor e transporte para cada POST, ignora mcp-session-id e retorna respostas 405 em formato JSON-RPC para GET e DELETE. É o modo exigido atrás de um load balancer ou serviço de autoscaling, porque nenhuma requisição depende de afinidade local ao processo. A permissão de concorrência é adquirida antes do parsing de JSON e liberada em todos os caminhos de resposta/erro/desconexão. O modo stateless usa o teto de parser maxUploadFileDataBytes configurado diretamente, porque a permissão de concorrência pré-parsing fornece seu limite de amplificação de memória. Orce aproximadamente maxConcurrentRequests vezes (1,5 vezes maxUploadFileDataBytes mais 64 KiB) por processo; a concorrência padrão no teto de upload de 100 MB é de aproximadamente 3 GiB antes do trabalho downstream. A inicialização stateless rejeita configurações cujo orçamento de parser conservador exceda 4 GiB. Reduza ainda mais ambas as configurações quando a tarefa ECS tiver um limite de memória menor. Em contraste, sessões stateful acima do teto padrão devem primeiro concluir uma chamada bem-sucedida à API qURL downstream. Em redes hostis, um limite de tamanho de requisição de borda autenticado não maior que o teto de parser configurado é um requisito de implantação: a permissão limita a memória agregada, mas um bearer não vazio não é validado de forma autoritativa até a operação parseada alcançar a API qURL downstream.

O listener stateless limita o recebimento de cabeçalhos a 15 segundos e tanto o recebimento completo da requisição quanto o tempo de vida ocioso do socket a 120 segundos. Uma permissão de concorrência abrange do parsing até a conclusão da resposta, então clientes travados não podem reter todo o pool de permissões indefinidamente. Uma chamada de ferramenta que não produz tráfego de socket por 120 segundos é abortada intencionalmente; integrações que precisam de operações silenciosas mais longas devem mover esse trabalho para trás de uma API assíncrona, em vez de elevar esse limite de retenção fleet-wide. O modo stateless (não-loopback) implantado requer o armazenamento de credenciais DynamoDB e todos os três campos estáveis de identidade de métricas. Ele emite um heartbeat EMF de 30 segundos: McpConcurrencyUtilization é a utilização máxima de permissões observada durante o intervalo na admissão de requisições e no heartbeat (incluindo requisições que iniciam e terminam entre heartbeats), enquanto McpConcurrencyRejected e McpRateLimitStoreErrors são deltas de intervalo snapshot-and-zero que incluem zeros explícitos. Limites de sessão e cotas de destinatários de e-mail permanecem em memória; a cota de credenciais DynamoDB é de toda a frota e conta cada POST HTTP autenticado, incluindo inicialização, descoberta e chamadas de ferramentas. Dimensione essa cota para o padrão completo de requisições esperado, em vez de apenas chamadas de ferramentas. A permissão também abrange o incremento DynamoDB limitado: durante uma queda de energia do armazenamento, cada requisição admitida pode reter uma permissão por aproximadamente quatro segundos (duas tentativas de dois segundos) antes de falhar de forma fechada, enquanto requisições excedentes recebem um 503 de concorrência rápida. O contador de janela fixa incrementa a cada tentativa, incluindo tentativas já acima do limite de credenciais; limites de taxa de borda e alarmes de gravação/limite do DynamoDB devem, portanto, limitar a amplificação de gravação abusiva. Os proprietários da implantação devem tornar tanto os alarmes quanto uma sonda de amplificação de gravação acima do limite portões de promoção rígidos, em vez de tratá-los como observabilidade opcional. A implantação gerenciada em qurl-integrations-infra#1305 provisiona esses alarmes, com prova ao vivo rastreada em seu registro de rollout e issue #1306 antes da promoção. Integradores diretos de createHttpRuntime que injetam uma implementação de armazenamento de credenciais ainda devem declarar credentialRateLimitStore: "dynamodb" para o modo stateless não-loopback. A interface de injeção genérica não pode provar que um backend personalizado é compartilhado entre réplicas, então a injeção deliberadamente não é uma saída de emergência do contrato implantado. Campos de identidade de métricas são rejeitados no modo stateful para que o medidor de concorrência não possa silenciosamente relatar um zero enganoso. Cada POST stateless possui um novo servidor MCP e transporte, então nenhuma requisição pode herdar o estado do manipulador de outra credencial. O encerramento de resposta concluída é rastreado de forma assíncrona. A admissão para quando esse backlog atinge maxConcurrentRequests; requisições já em andamento podem então terminar, então o backlog pode transitoriamente se aproximar do dobro dessa contagem, mas permanece limitado. Enquanto o portão de admissão está fechado, novas requisições falham com 503 e incrementam McpConcurrencyRejected em vez de crescer a memória de encerramento sem limite. Esse contador representa intencionalmente falha de admissão por saturação de requisições ativas ou pressão de backlog de encerramento. O autoscaling deve usar McpConcurrencyUtilization sozinho; o contador de rejeições permanece digno de página, e baixa utilização junto com rejeições identifica atraso de encerramento. Agrupar esses objetos enfraqueceria o isolamento de requisições e deliberadamente não é uma otimização de desempenho sem pressão de registro medida. /healthz e o endpoint público de arquivos de vídeo cada um usa seu próprio bucket publicFileRateLimitPerMinute, isolado do tráfego legal/página de vídeo e um do outro. Mantenha o balanceador de carga, a sonda de liveness e a frequência esperada de requisições de intervalo de vídeo abaixo dessa permissão por IP de origem (300 requisições/minuto por padrão), ou aumente-a para clientes excepcionalmente agressivos.

Prioridade de Configuração

Por padrão, a configuração é carregada dos dois arquivos JSON locais acima. Se um arquivo estiver ausente, padrões embutidos e variáveis de ambiente são usados. Caminhos de configuração relativos—incluindo os padrões—são resolvidos a partir do diretório de trabalho do processo. Defina as variáveis de caminho explícitas abaixo quando um supervisor, npx, ou um host MCP iniciar o servidor a partir de um diretório diferente.

As seguintes variáveis de ambiente substituem independentemente os caminhos dos arquivos de configuração:

  • QURL_MCP_CONFIG
  • QURL_MCP_HTTP_CONFIG

QURL_MCP_HTTP_CONFIG nunca substitui o caminho de configuração de runtime compartilhado. Isso mantém as configurações do listener de sombrear silenciosamente as configurações de SMTP, conector ou API.

server.json e smithery.yaml descrevem o transporte stdio publicado, então eles incluem configurações compartilhadas de upload/SMTP, mas omitem intencionalmente variáveis de listener somente HTTP, como QURL_MCP_HTTP_CONFIG e MCP_MAX_SESSIONS.

Não commite chaves de API, credenciais SMTP ou caminhos privados de sistema de arquivos.

Rotas HTTP

Após iniciar no modo http, as rotas comuns são:

RotaPropósito
/mcpEndpoint MCP remoto principal
/healthzEndpoint de verificação de saúde
/legal/privacyPágina pública de política de privacidade
/legal/termsPágina pública de termos de serviço
publicVideo.pagePathPágina pública de reprodução de vídeo
publicVideo.pagePath + /fileEndpoint de streaming MP4

/healthz é intencionalmente não autenticado e sem validação de Host para cada chamador, expõe apenas { "ok": true }, e usa o limite de requisições de rota pública configurado em um bucket separado para que sondas de saúde não possam consumir a permissão da rota legal/vídeo. Um 429 desta rota significa que a fonte da sonda excedeu publicFileRateLimitPerMinute, não que a aplicação falhou em sua verificação de liveness; mantenha a frequência da sonda abaixo desse limite. Ela é registrada antes da validação de Host porque as sondas de alvo ALB usam o IP da tarefa e porta como Host; rotas públicas MCP e de navegador permanecem validadas por Host.

Autenticação HTTP

O endpoint /mcp requer Authorization: Bearer <qURL API key> em cada requisição. No modo stateful, o token bearer é vinculado à sessão MCP resultante, então um ID de sessão não pode ser reutilizado com uma credencial diferente. No modo stateless, o bearer permanece no escopo da requisição e é descartado quando a resposta fecha.

Limite de autenticação do operador: a inicialização aceita qualquer token bearer não vazio e permite que o catálogo público de ferramentas/recursos/prompts seja lido antes da validação autoritativa pela primeira chamada de API qURL downstream. Esse catálogo é montado a partir de esquemas e descrições estáticas e não inclui tokens bearer, credenciais SMTP ou outra configuração do operador. Limites de sessão não validados, um prazo curto de validação e limites de taxa de requisição limitam esse estado de pré-validação; o token fornecido é encaminhado apenas para a API qURL configurada e, para ferramentas de upload, o Conector qURL configurado. Sessões somente de introspecção, portanto, permanecem não validadas e são fechadas em unvalidatedSessionTtlMs; clientes podem reinicializar se precisarem de uma sessão de vida mais longa. Uma sessão é promovida somente após uma chamada de API qURL bem-sucedida ou um link de upload entregável cunhado através do conector configurado (que encaminha o bearer para a API qURL)—chamadas rejeitadas ou limitadas por taxa não provam a credencial válida. O conector é, portanto, parte desse limite de confiança: aponte QURL_CONNECTOR_URL apenas para um conector que autentique o bearer. Seu texto de erro de upload (limitado a 1 KiB, caracteres de controle achatados) e os links que ele cunha são retornados ao agente, e links cunhados podem ser enviados por e-mail. Sessões desconectadas permanecem registradas por um período de graça de reconexão SSE de 30 segundos, enquanto maxSessions e maxSessionsPerCredential limitam essa permissão sob rotatividade.

Requisições sem um cabeçalho Origin são aceitas para clientes MCP não-navegador. Quando Origin está presente, ele deve corresponder à origem de baseUrl; valores malformados ou de origem cruzada são rejeitados em /mcp. Rotas públicas de saúde, legais e de vídeo configuradas não usam estado de origem de navegador e não são limitadas por esta verificação.

Configure clientes MCP remotos com:

ConfiguraçãoValor
URL do Servidor MCPSua URL HTTPS pública mais /mcp
AutenticaçãoToken Bearer
TokenA chave de API qURL do chamador

Se um cliente suportar apenas descoberta OAuth, coloque um gateway compatível com OAuth na frente deste servidor em vez de expor /mcp sem autenticação.

Como Verificar a Implantação

Verificações de Nível de Serviço

Comece com:

  • /healthz
  • /mcp

Os documentos legais da LayerV estão desabilitados por padrão. Somente serviços operados pela LayerV devem definir MCP_SERVE_LAYERV_LEGAL_PAGES=true (ou serveLayerVLegalPages: true na configuração HTTP). Operadores auto-hospedados devem publicar suas próprias políticas.

Verificações de Página Pública

Quando habilitado, verifique as páginas legais e a página de vídeo configurada:

  • /legal/privacy
  • /legal/terms
  • o caminho da página pública de vídeo configurada

Verificação de Domínio

Se você planeja usar a Plataforma OpenAI, certifique-se de que o seguinte caminho de nível raiz exista:

/.well-known/openai-apps-challenge

Este arquivo de verificação deve viver sob o caminho raiz do domínio .well-known, não sob /mcp.

Docker

O repositório inclui um Dockerfile para implantação em contêiner.

Exemplo:

docker build -t qurl-mcp .
docker run -i -e QURL_API_KEY=lv_live_xxx qurl-mcp

Se você implantar com Docker, certifique-se de que o contêiner ainda possa acessar os arquivos de configuração corretos, ou substitua os caminhos dos arquivos de configuração com variáveis de ambiente.

Execute o listener HTTP localmente no Docker:

A imagem usa como padrão o ponto de entrada stdio e o servidor HTTP usa como padrão loopback local do contêiner. Implantações HTTP devem substituir o comando e vincular a 0.0.0.0 com uma lista de permissões de Host explícita e origem pública HTTPS. Este exemplo publica apenas para loopback do host; coloque um proxy reverso TLS na frente dele para a origem https://mcp.example.com configurada:

docker run --rm -p 127.0.0.1:3000:3000 \
  -e MCP_HOST=0.0.0.0 \
  -e MCP_BASE_URL=https://mcp.example.com \
  -e MCP_ALLOWED_HOSTS=mcp.example.com,127.0.0.1,localhost \
  qurl-mcp node dist/http.js

Para um único proxy reverso de produção confiável, defina MCP_TRUST_PROXY_HOPS=1, use a origem HTTPS pública em MCP_BASE_URL, e defina MCP_ALLOWED_HOSTS para o hostname público. Não exponha o listener do contêiner diretamente quando a confiança do proxy estiver habilitada.

Comandos Comuns

ComandoPropósito
npm run buildCompilar TypeScript
npm testExecutar testes
npm run test:coverageExecutar cobertura forçada
npm run lintExecutar ESLint
npm run devModo de observação TypeScript
npm run formatFormatar código-fonte
npm run format:checkVerificar formatação
npm run startIniciar modo stdio
npm run start:httpIniciar modo HTTP

Ordem de Implantação Recomendada

  1. Copie e atualize os dois arquivos de configuração de exemplo
  2. Defina credenciais através de variáveis de ambiente
  3. Execute npm install
  4. Execute npm run build
  5. Execute npm run start:http
  6. Verifique /healthz
  7. Verifique se requisições não autenticadas /mcp recebem 401
  8. Configure o proxy reverso HTTPS
  9. Verifique uma inicialização MCP autenticada e as páginas públicas opcionais

Ativos de Terceiros

A geração de texto para PDF inclui a fonte Noto Sans SC de peso regular como TrueType (cerca de 10 MB) para cobertura offline de glifos multilíngues. A fonte estática retém todos os caracteres da fonte variável original; o PDFKit incorpora apenas os glifos usados por cada documento. Nenhum download ou dependência adicional de runtime é necessário. Sua Licença de Fonte Aberta SIL e aviso de direitos autorais estão incluídos em assets/fonts/OFL.txt; detalhes de conversão estão em assets/fonts/README.md.

Licença

MIT -- LayerV AI