MCP Fusion/Protocol and runtime/Motor de prompts
Motor de prompts
Prompts são cidadãos de primeira classe ao lado das tools: schemas de argumentos tipados, execução de tools em loopback a partir de handlers de prompt, paginação com cursores assinados, interceptadores e prazos de hidratação.
Tools executam; prompts semeiam. Um prompt é um template reutilizável, do lado do servidor, para uma conversa: o cliente lista os prompts, o usuário escolhe um e o servidor devolve o conjunto de mensagens. O MCP Fusion trata os prompts com a mesma engenharia das tools: entradas tipadas, middleware, paginação e um loopback para o seu próprio tool pipeline.
Definindo um prompt
import { z } from 'zod';
export default f.prompt('issue.review')
.describe('Review a pull request with the team checklist')
.input(z.object({
repo: z.string().describe('Repository slug'),
pr: z.number().describe('Pull request number'),
}))
.handler(async (ctx, args) => ({
description: 'Review acme/product#42 against the checklist',
messages: [
{ role: 'user', content: `Review PR ${args.pr} in ${args.repo}. Use the checklist.` },
{ role: 'assistant', content: 'Sharing the checklist first, then the diff.' },
],
}));A forma fluent espelha a das tools: .describe(), .input() (um objeto Zod, ou um map plano de descritores de argumentos primitivos), .use(middleware), .title(), .icons(), .tags() e o terminal .handler((ctx, args) => PromptResult). O resultado é { description?, messages } com os papéis user e assistant, múltiplos turnos são permitidos, e há blocos de conteúdo além de texto: image, audio, resource_link, resource e os helpers de fábrica do PromptMessage (.system() é codificado como user: o MCP não tem papel system).
A forma declarativa, definePrompt, e a forma f.prompt(name, config) no estilo f.presenter() existem para layouts de config-as-code. Os argumentos compilam para Zod com validação plana e estrita: só primitivos, sem arrays nem objetos aninhados. Essa é uma restrição do MCP, imposta no momento da definição com um erro claro, e não no momento do wire.
Loopback: prompts que chamam tools
O contexto do handler de prompt inclui invokeTool(name, args), um dispatcher para o mesmo tool pipeline, com middleware, validação e Presenters. Um prompt, portanto, não é uma string estática: ele pode buscar o diff ao vivo do PR com as próprias tools do usuário, hidratar o checklist e só então devolver as mensagens semeadas. O RBAC é aplicado dentro do loopback (o contexto de quem chama é o contexto de quem chama), e o AbortSignal da requisição se propaga, de modo que um prompt cancelado cancela o trabalho de tools que ele disparou.
A hidratação tem limite: um prazo por registry (.timeout(ms) no builder ou setDefaultHydrationTimeout) define quanto tempo um prompt pode gastar chamando tools antes de devolver. Passado o prazo, a resposta sai com um bloco de alerta de hidratação, em vez de travar o cliente.
Paginação e ciclo de vida
prompts/list é paginado no servidor: CursorCodec transforma o nome "after" em um cursor que é assinado com HMAC-SHA256 ou criptografado com AES-GCM (configurado com um segredo de 32 bytes; sem um, vale uma chave efêmera por processo). O tamanho de página padrão é 50, com suporte a filtragem por tags. Por design, um cursor é opaco para os clientes.
notifyPromptListChanged() (ou o caminho do evento list_changed em mutações de f.prompt em tempo de execução) envia notifications/prompts/list_changed com debounce de 100ms, para que um registry que cresce durante uma sessão não inunde o cliente.
Interceptadores
registry.useInterceptor(fn) roda depois que um handler retorna e antes que o cliente veja o resultado: acrescentar um <compliance_notice>, prefixar um turno de usuário ou injetar blocos de contexto envolvidos em uma tag. Interceptar é o jeito seguro de adicionar diretrizes para toda a organização sem editar cada prompt.
Por que isso importa
O imposto de integração de quem constrói sobre o MCP costuma ser "o cliente só tem tools". Os prompts fecham a outra metade: você entrega o workflow, não apenas a capacidade. Combinados com Tools, Resources e o Wire format, um único conector pode entregar a um agente a forma completa de como trabalhar com os seus dados, no protocolo nativo do agente.
Próximos passos
- Tools: a metade da execução
- Runtime architecture: onde o registry fica
- Skills: prompts também são o caminho pelo qual o SKILL.md chega aos agentes
