canli-validation-mcp
Valide um backtest antes de confiar nele: índice de Sharpe deflacionado, overfitting de backtest (CSCV), verificações de evidência em papel e amplitude por meio de uma API gratuita, cada uma retornando um recibo recomputável. Também lê o histórico financeiro reportado pelas empresas a partir de arquivos da SEC. Execute com npx -y canli-validation-mcp.
Documentação
canli-validation-mcp
Um servidor MCP (Model Context Protocol) sobre a API de validação gratuita e com chave do canlicapital.com. Ele fornece a um agente de codificação nove ferramentas: emitir uma chave gratuita, executar os cinco validadores (Sharpe deflacionado, CSCV de sobreajuste, conformidade com evidência de artigo, teto de amplitude, duração mínima do histórico), buscar um recibo armazenado, ler o status do serviço e ler o histórico financeiro reportado de uma empresa a partir de arquivos da SEC. Cada ferramenta retorna o envelope completo da API como texto de resultado, seja sucesso ou erro, para que o agente não veja um número sem as frases ao lado que explicam o que o número não estabelece.
Este pacote é publicado no npm como canli-validation-mcp.
Também está listado no Registro Oficial de MCP (io.github.arhancanli/canli-validation-mcp) e no
cursor.directory. Execute-o com npx, sem etapa de instalação, como mostrado abaixo. Uma cópia local só é necessária para desenvolver ou
testar este pacote em si; veja "Cópia local" perto do final.
Este README descreve a versão em package.json. npx sem versão executa o lançamento mais recente do npm;
npx -y canli-validation-mcp@<version> fixa uma versão específica.
O que a API é (e não é)
O motor é o produto. O serviço executa os números que você envia através da mesma aritmética de honestidade
que o registro de artigos do próprio canlicapital.com usa em si mesmo e devolve um veredito que qualquer pessoa pode
recalcular a partir do recibo. Ele não aceita dados de mercado, não assina recibos, não
avalia uma estratégia e nunca viu sua fonte de dados, seus custos ou qualquer lookahead em como uma série foi
construída. Veja docs/superpowers/specs/2026-09-05-developer-key-validation-api-design.md no repositório principal
para o design completo.
Ferramentas
| Ferramenta | Chamadas | Chave necessária |
|---|---|---|
get_key | POST /api/v1/keys | não |
validate_deflated_sharpe | POST /api/v1/validate/deflated-sharpe | sim |
validate_overfitting | POST /api/v1/validate/overfitting | sim |
validate_paper_evidence | POST /api/v1/validate/paper-evidence | sim |
validate_breadth | POST /api/v1/validate/breadth | sim |
validate_track_record | POST /api/v1/validate/track-record | sim |
get_receipt | GET /api/v1/receipts/{id} | não |
service_status | GET /api/v1/validate/status | não |
company_financial_history | GET /company-data/{cik}.json (um ticker é resolvido através de GET /api/v1/company-tickers.json) | não |
validate_deflated_sharpe aceita exatamente uma de duas formas de entrada, nunca uma mistura de ambas:
- os sete campos do contrato:
observed_sharpe_annualized,observations,periods_per_year,skew,non_excess_kurtosis,effective_independent_trials,cross_trial_sharpe_sd_annualized; - ou uma série de retornos mais as tentativas por trás dela:
returns,periods_per_year,effective_independent_trials,cross_trial_sharpe_sd_annualized.
Enviar campos de ambas as formas, ou de nenhuma, é rejeitado antes que qualquer requisição saia do
processo; veja src/schemas.mjs.
company_financial_history é diferente das outras ferramentas: ela lê a referência de empresa pública
no canlicapital.com, não a API de validação. Forneça um CIK (1 a 10 dígitos) para listar os
históricos financeiros disponíveis de uma empresa, ou um CIK e um conceito us-gaap como Revenues para
obter as observações, das mais recentes para as mais antigas (limit tem padrão de 40, máximo 200). Cada observação
mantém seu accession de arquivamento, formulário, data de arquivamento e unidade, e o resultado carrega o SHA-256 da
resposta original da SEC e a frase de limite do próprio registro: estes são valores contábeis como
reportados à SEC, não preços de mercado, retornos ou uma recomendação. Empresas e conceitos
fora do lançamento atual retornam um erro com os conceitos disponíveis listados.
Prompts, recursos e resultados estruturados
Clientes que mostram prompts de MCP oferecem dois fluxos de trabalho guiados: validate_backtest (Sharpe deflacionado, depois
sobreajuste, depois o histórico necessário, reportado com o que cada número não estabelece) e
track_record_needed. Dois recursos podem ser lidos: canli://limits, as frases de limite que cada
resultado carrega, e canli://sources, os artigos por trás de cada validador e como cada um é verificado
contra eles. Cada resultado de ferramenta carrega seu envelope tanto como texto quanto como structuredContent.
Contexto compacto (0.3.0)
Um agente paga por cada token que uma ferramenta retorna, incluindo espaços em branco que ele nunca lê. Desde 0.3.0
cada resultado é JSON minificado, e um histórico de empresa retorna suas observações como um cabeçalho columns
e uma linha por observação, com uma unidade compartilhada por todas as linhas declarada uma única vez. Nenhum campo é
removido: cada frase de limite, número de accession, formulário, data de arquivamento e hash de origem ainda está
no resultado, e columns + rows reconstroem cada observação exatamente.
Medido com bench/token_cost.py em registros ao vivo (tokenizador: tiktoken o200k_base; outros
tokenizadores dão contagens absolutas diferentes), 20 observações cada:
| Registro | 0.2.0 (recuado) | minificado | 0.3.0 (minificado, colunar) |
|---|---|---|---|
| Apple, StockholdersEquity | 2.214 | 1.560 (−29,5%) | 1.060 (−52,1%) |
| Microsoft, CashAndCashEquivalentsAtCarryingValue | 2.231 | 1.574 (−29,4%) | 1.065 (−52,3%) |
As ferramentas de validação ganham apenas a minificação: o envelope service_status ao vivo mediu 593
tokens recuados e 475 minificados (−19,9%); suas frases de limite são mantidas palavra por palavra. Estas
são medições destes resultados, não uma afirmação sobre qualquer outro servidor.
Mudança que quebra compatibilidade desde 0.2.0: history.observations agora é {unit?, columns, rows} em vez de
um array de objetos.
Configuração
| Variável | Padrão | Significado |
|---|---|---|
CANLI_API_BASE | https://canlicapital.com | Onde a API vive. Aponte para uma implantação de pré-visualização para testes. |
CANLI_KEY | não definido | Uma chave já emitida de POST /api/v1/keys. Quando definida, get_key não envia nenhuma requisição e reporta que a chave já está configurada; toda outra ferramenta a envia como Authorization: Bearer <key>. |
CANLI_LOCAL | não definido | 1 ou true executa os cinco validadores nesta máquina (modo local privado, abaixo): sem chave, sem rede, sem recibo. |
Se CANLI_KEY não estiver definida e o modo local estiver desligado, chame get_key uma vez por sessão antes dos validadores. A chave que ela
retorna vive apenas na memória deste processo durante a vida da sessão; ela não é gravada em
disco.
Falhas HTTP e envelopes de erro da API são marcados como erros de ferramenta MCP enquanto preservam o envelope JSON completo. Uma validação bem-sucedida com um veredito negativo permanece um resultado normal. Requisições têm um prazo de 30 segundos cobrindo cabeçalhos e corpo, rejeitam redirecionamentos e nunca são repetidas automaticamente. Um timeout pode ocorrer depois que o serviço processou uma requisição; verifique o status do serviço antes de decidir enviar novamente. Corpos de resposta não-JSON e erros de rede brutos são omitidos dos erros de ferramenta.
Instalação
Sem etapa de instalação. npx busca o pacote publicado na primeira execução, então cada configuração de cliente abaixo
apenas inicia npx -y canli-validation-mcp. Veja "Cópia local" perto do final para desenvolver ou testar
este pacote em si em vez de executar o publicado.
Endpoint hospedado (sem instalação)
As mesmas ferramentas são servidas em https://canlicapital.com/mcp via MCP Streamable HTTP, para clientes
que se conectam a uma URL em vez de iniciar um processo (conectores Claude.ai, ChatGPT, servidores remotos do Cursor).
Nada para instalar, e sem Node.js na sua máquina.
claude mcp add --transport http canli https://canlicapital.com/mcp
Sem uma chave, as requisições rodam sob uma chave anônima compartilhada, então a cota diária de validação é compartilhada por todos os chamadores hospedados. Para sua própria cota, emita uma chave gratuita (veja /developers) e envie-a como um cabeçalho:
claude mcp add --transport http canli https://canlicapital.com/mcp --header "Authorization: Bearer $CANLI_KEY"
O endpoint é sem estado. Nele, get_key não emite nada e diz qual chave está em uso, porque uma
chave emitida lá não alcançaria a próxima requisição. Um cabeçalho Authorization malformado é recusado
em vez de substituído pela chave compartilhada.
Claude Desktop
Adicione a claude_desktop_config.json (Configurações, Desenvolvedor, Editar Config):
{
"mcpServers": {
"canli": {
"command": "npx",
"args": ["-y", "canli-validation-mcp"]
}
}
}
Reinicie o Claude Desktop depois. Adicione um objeto "env" com CANLI_API_BASE para apontar isto para uma
implantação de pré-visualização em vez do padrão.
Claude Code
claude mcp add canli -- npx -y canli-validation-mcp
Execute claude mcp list para confirmar que está registrado, e claude mcp remove canli para removê-lo.
Modo local privado
Defina CANLI_LOCAL=1 e os cinco validadores rodam na sua máquina: nada sobre a série que você
envia é mandado para canlicapital.com, nenhuma chave é necessária e nenhum recibo é armazenado. O cálculo é
o da própria API, enviado byte por byte em src/local (um teste falha se houver divergência), então um resultado local
é igual ao hospedado; ele não nomeia um id de recibo porque nenhum foi criado.
claude mcp add canli-local --env CANLI_LOCAL=1 -- npx -y canli-validation-mcp
get_receipt, service_status e company_financial_history ainda leem de canlicapital.com;
eles não enviam séries. Na extensão do Claude Desktop, esta é a configuração "Modo local privado".
Cliente stdio genérico
Qualquer cliente MCP que possa iniciar um processo e falar stdio funcionará. Usando o SDK oficial diretamente, a partir do Node:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
const transport = new StdioClientTransport({
command: "npx",
args: ["-y", "canli-validation-mcp"],
env: { ...process.env, CANLI_API_BASE: "https://canlicapital.com" },
});
const client = new Client({ name: "my-agent", version: "0.1.0" });
await client.connect(transport);
const { tools } = await client.listTools();
console.log(tools.map((t) => t.name));
const keyResult = await client.callTool({ name: "get_key", arguments: { label: "my-agent" } });
if (keyResult.isError) throw new Error("Key setup failed; inspect the error privately.");
// The session retains the issued key. Avoid printing its envelope into logs.
const result = await client.callTool({
name: "validate_deflated_sharpe",
arguments: {
returns: [0.004, -0.002, 0.007, 0.001, -0.003, 0.005, 0.002, -0.001],
periods_per_year: 252,
effective_independent_trials: 30,
cross_trial_sharpe_sd_annualized: 0.5,
},
});
console.log(result.content[0].text); // the full envelope, including limits and receipt.url
await client.close();
O que um resultado não estabelece (linguagem de limite)
Cada envelope que este servidor retorna carrega estas frases, verbatim, da própria API
(api/_lib/limits.js):
- Este veredito é sobre a série exatamente como enviada. O serviço nunca viu a fonte de dados, seus custos, sobrevivência ou qualquer lookahead em como a série foi construída.
- Uma probabilidade de Sharpe deflacionado ou sobreajuste acima ou abaixo de qualquer limite não é admissão a nada e não é uma previsão.
- O recibo tem hash de conteúdo e é reproduzível a partir do núcleo de código aberto que ele nomeia. Ele não é assinado.
- Cotas: 1000 validações por chave por dia UTC, 5 chaves por cliente por dia UTC, 1048576 bytes por requisição, 20000 observações por série, 200 variantes por matriz.
A descrição de cada ferramenta também declara uma destas frases, então um agente vê o limite antes
de chamar a ferramenta, não apenas depois. Nenhuma ferramenta neste servidor remove limits ou receipt.url de
uma resposta; o envelope completo é sempre o texto do resultado.
Cópia local
Necessária apenas para desenvolver ou testar este pacote em si, não para executar o publicado.
cd mcp
npm ci
node src/server.mjs
Aponte um cliente para a cópia em vez do npm iniciando node /absolute/path/to/meridian/mcp/src/server.mjs
no lugar de npx -y canli-validation-mcp em qualquer configuração acima.
Testes
npm test
npm run test:package
Executa node --test sobre test/*.test.mjs: round-trips de esquema contra o OpenAPI da própria API e
exemplos de manifest, um caso de sucesso, envelope de erro e cota-429 por ferramenta com chave (um fetch falso
substitui a rede), uma verificação de que cada descrição de ferramenta carrega uma frase de limites, uma
verificação de que essas frases não se desviaram de api/_lib/limits.js, uma verificação de que nenhum arquivo
enviado contém um travessão, e um teste que inicia o binário real do servidor e realiza um
handshake MCP real de tools/list e callTool via stdio contra um stub HTTP local, para que a fiação seja
comprovada em vez de assumida.
test:package cria o tarball npm real, verifica sua lista exata de arquivos e licença,
instala-o em um diretório temporário de consumidor e executa o teste stdio contra essa
entrada instalada. A instalação de dependências contata o npm; as chamadas de ferramenta usam apenas o
stub HTTP local. Ele não publica um pacote nem emite uma chave de API de produção.
Dependências
Apenas @modelcontextprotocol/sdk (fixado exato) e zod (fixado exato). Nenhuma outra dependência
de runtime é adicionada, e nada neste pacote toca o package.json raiz do site,
.vercelignore, api/, scripts/, js/ ou public/.