Um servidor MCP entrega números a uma coisa que vai depois raciocinar sobre eles em voz alta, com confiança, para alguém que não os consegue verificar. Isso é um problema de desenho diferente do de uma API para um programa, e a maior parte dele não é sobre o protocolo.
Estas são seis decisões do servidor MCP da Skomi e aquilo de que cada uma se defende. Nenhuma é engenhosa; várias são a segunda versão, depois de a óbvia se ter revelado uma armadilha.
1. O código é um cabeçalho, nunca um parâmetro de ferramenta
O desenho óbvio é um parâmetro token em cada ferramenta. Documenta-se a si próprio, funciona, e põe o segredo do cliente dentro da conversa, onde chega aos registos do cliente, a qualquer transcrição que venha a ser exportada, e ao que quer que o modelo escolha repetir enquanto explica o que acabou de fazer.
Um cabeçalho é invisível para o modelo. Não pode ser citado porque não está no contexto.
O mesmo raciocínio diz que o servidor não deve ter código nenhum próprio. O da Skomi reencaminha o que quer que o chamador envie e não guarda nada, portanto não consegue fazer nada que já não conseguisses fazer com o curl. Não há modo nenhum em que tenha acesso permanente aos dados de quem quer que seja, que é a única versão de "levamos a segurança a sério" que se consegue verificar.
2. Nada escreve
Todas as ferramentas estão anotadas com readOnlyHint, e a API por trás delas é só de leitura à partida, portanto a anotação é uma descrição e não uma promessa.
Vale a pena dizê-lo com todas as letras porque a tentação corre no sentido contrário: um assistente que conseguisse mudar uma definição faz uma demonstração lindíssima. Quer também dizer que uma instrução mal lida tem consequências que sobrevivem à conversa. Ler é recuperável; escrever não é, e uma ferramenta de analítica não tem nada para escrever que valha isso.
3. Uma indisponibilidade devolve um erro, não zeros
Quando o armazenamento está indisponível, as ferramentas falham. Deliberadamente não devolvem uma página de zeros.
Os zeros seriam a resposta mais simpática e a mais perigosa, porque um modelo não consegue distinguir uma semana partida de uma semana sossegada. "O tráfego caiu para nada na terça-feira" é uma frase que um assistente vai produzir, de boa-fé, a partir de dados com ar plausível, e a pessoa que a lê não tem maneira nenhuma de saber que foi uma indisponibilidade na analítica e não uma indisponibilidade no sítio dela.
Um erro é uma experiência pior e é verdadeiro. A regra geral: nunca devolvas um valor indistinguível de uma medição verdadeira quando não tens medição nenhuma.
4. "Sem comparação" em vez de um número inventado
Todas as métricas vêm com a variação delas contra o período anterior. Quando o período anterior foi zero, a variação é nula: não infinito, não 100%, não um número grande que por acaso se consegue apresentar.
A variação percentual a partir de zero é indefinida, e qualquer valor concreto que lá ponhas é um número que o modelo vai repetir como um facto. As ferramentas dizem "sem comparação". É menos satisfatório e é a única coisa honesta disponível.
5. As linhas não somam 100, e a ferramenta di-lo
Uma desagregação conta visitantes distintos por linha. Uma pessoa num telemóvel e num portátil está em duas linhas, portanto as linhas somam mais do que o total e as percentagens não dão 100.
Não dito, isto é uma armadilha com uma falha muito específica: um modelo a quem se peça a "fatia de tráfego por país" vai prestavelmente normalizar as linhas para 100%, uma coisa completamente razoável de fazer com uma lista de números, e errada aqui de uma maneira que ninguém a jusante vai apanhar.
Portanto a própria descrição da ferramenta di-lo: divide pelo total de visitantes do período vindo da ferramenta de resumo, nunca pela soma das linhas. A correção tem de viver onde o modelo está a olhar, que é a descrição da ferramenta, e não a documentação que outra pessoa leu.
6. Os filtros são dimensões, e há um só interpretador
Todos os nomes de dimensão funcionam também como filtro, com o mesmo significado nos dois sítios:
breakdown dimension=path filters={"country":"EE","device":"mobile"}
Um só interpretador quer dizer que os dois não podem discordar: um filtro que o modelo constrói é exatamente um filtro que o painel poderia aplicar, e uma dimensão que ele descobriu ao perguntar é uma dimensão sobre a qual pode filtrar de imediato. Há também uma ferramenta que não devolve mais nada senão as dimensões, os períodos e as regras de filtro aceites, para um modelo poder perguntar o que é legal em vez de adivinhar e tentar outra vez.
O canto desajeitado: para filtrar por um valor que nunca foi gravado (visitas sem campanha, digamos), passas __none__. Uma cadeia vazia é indistinguível de um parâmetro ausente depois de o pedido ser interpretado, portanto o valor vazio tem de viajar como alguma coisa. Todas as API acabam por ganhar uma destas; o gesto honesto é documentá-la em vez de fingir que a forma é uniforme.
O que isto dá no conjunto
A maior parte é um princípio aplicado repetidamente: uma resposta ambígua é pior do que uma recusa, porque a coisa que consome a tua API vai resolver a ambiguidade com confiança e em voz alta.
Isso não é especial do MCP. É só que o consumidor habitual (um programa com um programador por trás) teria lançado uma exceção, e este escreve um parágrafo.
O servidor da Skomi está em mcp.skomi.com e não há nada para instalar; a API de perguntas que ele lê é a mesma que tudo o resto pode usar.
Os números que lê são os mesmos que o Analytics te mostra, através da mesma API de perguntas; não há um segundo canal sobre o qual o modelo se possa enganar. O servidor MCP define o termo se for novo para ti.