@expertcustom/funilaria-mcp
@expertcustom/funilaria-mcp
Servidor MCP (Model Context Protocol) con las tools tipadas que la IA de Aurora usa para escribir y leer en el portal Funilaria & Pintura.
Sustituye a mcp-fetch montando la petición HTTP a mano con el secreto escrito en el system prompt: aquí cada operación es una tool con schema, descripción y error en portugués.
IA do Aurora ──stdio──> npx @expertcustom/funilaria-mcp ──HTTPS──> backend NestJSSegún la ADR-001, este paquete es adaptador: ninguna regla de negocio vive aquí. Cada tool llama a un endpoint que ya existe, y el servicio del backend sigue siendo el dueño de la decisión.
Tools — quién las define es el backend
Este paquete no sabe qué tools existen. Al arrancar busca GET /mcp/catalogo y publica lo que venga; la ejecución va por POST /mcp/ejecutar, y el backend resuelve el nombre hacia el servicio.
subida ──> GET /mcp/catalogo → lista publicada em tools/list
chamada ──> POST /mcp/executar → { name, args }El motivo es operativo: antes, una tool nueva costaba editar este paquete, compilar, commitear, publicar y reinstalar el MCP en Aurora — cinco pasos para exponer un endpoint que ya existía en el backend. Ahora es un commit de un solo módulo, en backend/src/mcp.
La lista actual sale de GET /mcp/catalogo. No hay copia aquí a propósito: una copia envejece y acaba mintiendo.
Cuando el catálogo no responde, el servidor publica una única tool, funilaria_catalogo_indisponible, cuya descripción explica qué comprobar. Sin ella, el síntoma sería "han desaparecido las tools" y el diagnóstico empezaría por el lugar equivocado.
El catálogo se busca una vez, al arrancar: el cliente MCP lee tools/list justo después de conectar y no vuelve a preguntar. Una tool añadida en el backend entra en la próxima reinstalación del servidor en Aurora.
Related MCP server: Telegram Bot MCP Server
Autenticación
Credencial de servicio con shopId explícito es el camino principal, tanto para escribir como para leer. Header x-aurora-secret, el mismo valor de AURORA_WEBHOOK_SECRET en el backend; no representa a ninguna persona, representa al servicio.
Una IA que atiende a varios talleres no tiene sesión, así que el taller es parámetro, nunca contexto implícito. Del lado del backend eso es el @AllowService() en las rutas de lectura de stock: el JwtAuthGuard acepta el secreto en lugar del JWT y el ShopContextGuard pasa a exigir el shopId — un id inexistente responde 404 Taller no encontrado, y no una lista vacía que se confundiría con "taller sin stock".
Sesión de usuario (JWT de POST /auth/entrar) sigue existiendo para los comandos de CLI, pero ya no vale para las tools: POST /mcp/ejecutar es siempre una llamada de servicio, y el taller es siempre un parámetro explícito. Una IA que atiende a varios talleres nunca tuvo sesión; mantener los dos modos solo creaba un camino en el que shopId omitido significaba cosas distintas.
Configuración — env es el camino principal
En producción, quien levanta este proceso es el runtime de Aurora, que inyecta las variables: no hay terminal, y no se ejecuta ningún comando de login. El servidor funciona con el disco totalmente vacío.
Env | Apodo aceptado | Para qué |
|
| Base de la API |
|
| Secreto de servicio ( |
|
| Secreto de la firma HMAC (opcional) |
| — | Taller por defecto de |
| — | JWT de usuario, si lo hay (opcional) |
Los apodos existen para el error clásico de copiar el .env del backend y que el secreto "desaparezca" por el prefijo distinto — AURORA_WEBHOOK_SECRET es exactamente el mismo valor en ambos lados.
El secreto nunca está hardcodeado ni se lee del prompt. El archivo ~/.config/funilaria-mcp/credentials.json (modo 0600) es una comodidad de desarrollo local; la env siempre gana y nunca se escribe en disco.
En el arranque, el servidor escribe en stderr (stdout es del protocolo MCP) una línea que dice qué está configurado y de qué env viene cada cosa — nunca el valor. Es lo que aparece en el log de Aurora cuando alguien se equivoca con el nombre de la variable:
[funilaria-mcp] API: https://api.exemplo.com (FUNILARIA_API_URL) · Credencial de serviço: configurada via AURORA_WEBHOOK_SECRET · ...
[funilaria-mcp] Sem credencial de serviço: as tools de escrita vão recusar toda chamada. Defina FUNILARIA_SERVICE_SECRET no ambiente deste processo.Firma HMAC
Cuando FUNILARIA_SIGNING_SECRET existe, toda escritura lleva también:
x-timestamp: <epoch em segundos>
x-signature: sha256=<HMAC-SHA256(`${timestamp}.${corpo}`)>Es la mejora mapeada en la ADR-001 (cierra replay y fuga por log). El backend todavía no la verifica — un header desconocido se ignora, así que se puede activar el lado del servidor sin romper a quien ya está corriendo.
Instalación
En la IA de Aurora (producción)
Registra el servidor con las variables en el propio registro del MCP — nada de login, nada de secreto en el system prompt:
{
"command": "npx",
"args": ["-y", "@expertcustom/funilaria-mcp"],
"env": {
"FUNILARIA_API_URL": "https://<api-do-portal>",
"FUNILARIA_SERVICE_SECRET": "<mesmo valor de AURORA_WEBHOOK_SECRET>"
}
}Local, para desarrollar
# opção A — env no shell (igual à produção)
FUNILARIA_API_URL=http://localhost:3334 FUNILARIA_SERVICE_SECRET=... npx @expertcustom/funilaria-mcp
# opção B — guardar em ~/.config para não exportar em todo shell
npx @expertcustom/funilaria-mcp login-servico
# sessão de usuário: só é necessária para consultar_estoque sem shopId
npx @expertcustom/funilaria-mcp login
# conferir o que está valendo e de onde veio (nunca imprime segredo)
npx @expertcustom/funilaria-mcp status
# registrar no Claude Code
claude mcp add funilaria --env FUNILARIA_API_URL=http://localhost:3334 -- npx -y @expertcustom/funilaria-mcpPendientes en el backend
Las cuatro pendientes originales (webhook de stock inalcanzable, lectura sin credencial de servicio, secreto comprobado después de la validación, distancia como código muerto) fueron corregidas en el backend y revalidadas contra localhost:3334. Lo que queda:
La IA no tiene forma de descubrir el
shopId. Es el único dato que necesita saber de memoria, y hoy solo llega porFUNILARIA_SHOP_ID— lo que ata un servidor a un taller y tumba el caso multi-taller que motivó el diseño de servicio.El punto más barato de resolver es
lanzar_consumo: el backend ya identificó empleado y taller por el número de WhatsApp, pero devuelve solo el texto de confirmación. SiIntakeResultincluyerashopIdymemberId, la conversación fluiría — "he usado 100ml de barniz" → "¿cuánto he gastado este mes?" seríaconsultar_balancecon los dos ids en la mano. Sin eso, la segunda pregunta no tiene respuesta posible.GET /stock/movimientosquedó fuera del@AllowService(). ElshopIdestá declarado en elListMovementsDto, pero la ruta no acepta credencial de servicio — el parámetro no tiene forma de usarse. O se marca la ruta, o se quita el campo del DTO para no sugerir una capacidad que no existe.La firma HMAC todavía no se verifica. El cliente ya envía
x-timestampyx-signaturecuando hay secreto de firma (ver arriba). Falta el lado del servidor para cerrar replay y fuga por log, como prevé la ADR-001.
Desarrollo
npm install
npm run build # tsc estrito, gera dist/
npm start # sobe o servidor MCP em stdioAvailable Tools
1 toolfunilaria_catalogo_indisponivelCatálogo do Funilaria indisponívelA
O backend do Funilaria não respondeu GET /mcp/catalogo, então NENHUMA tool do portal está disponível nesta sessão — não é que elas não existam. Verifique se FUNILARIA_API_URL aponta para o backend certo e se FUNILARIA_SERVICE_SECRET (ou AURORA_WEBHOOK_SECRET) está definido no processo deste MCP; o motivo exato saiu no stderr do servidor. Não tente cumprir a tarefa por outro caminho: não monte requisição HTTP à mão, não invente URL nem segredo. Avise quem pediu que a integração com o portal está fora do ar.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It explains that the tool is not a functional operation but a signal that the catalog is down, that no portal tools are available, and that the exact cause is in the server's stderr. It also discloses the expected fallback behavior (informing the requester) and explicitly forbids bypass attempts. This fully discloses the tool's non-functional nature and the reasoning behind it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, dense paragraph that front-loads the core message (backend down, no tools available) and then provides corrective actions and prohibitions. Every sentence contributes essential information: the root cause, the implication, troubleshooting steps, and explicit instructions. There is no fluff or redundancy, making it both concise and structurally sound.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that there is no output schema and the tool is essentially a status indicator, the description is complete. It specifies what happened, why, what to check, what not to do, and what to tell the requester. All necessary operational context is provided, and because the tool has zero parameters and no output expectations, the description fully covers what an agent needs to handle this situation correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema is empty with 0 parameters, so the baseline is 4. The description does not need to add parameter details, but it explains why the tool takes no arguments (it is a placeholder for an unavailable catalog). It also provides environment variable checks (FUNILARIA_API_URL, FUNILARIA_SERVICE_SECRET) as context, which indirectly explains the setup. This exceeds the baseline by giving operational context beyond the mere absence of parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool indicates the backend did not respond to GET /mcp/catalogo, making the entire portal's tools unavailable in this session. It does not use a classic verb+resource phrasing, but its purpose as an unavailability signal is unambiguous and distinct from any normal tool. Since there are no siblings, the distinguishing aspect is not relevant, but the description still clearly explains what it represents.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs when to use this tool (when it appears, treat it as a session-wide unavailability) and what NOT to do: do not attempt to fulfill the task by other means, do not craft HTTP requests manually, do not invent URLs or secrets. It also tells the agent to inform the requester. This is direct, actionable context with explicit exclusions, covering both usage and alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.1.0- First observed
funilaria_catalogo_indisponivel
TDQS
Scored across 1 tool
With only one tool, there is no possibility of tool confusion. The tool's purpose—to report that the catalog is unavailable—is uniquely clear.
The single tool name is descriptive and domain-specific, following a clear pattern. With no other tools, there is no inconsistency to penalize.
A single tool that serves only as an error placeholder is far below the expected scope for a catalog server. This is an extreme mismatch with the apparent purpose.
The server provides no actual catalog operations; the only tool explicitly states that all functional tools are unavailable. The surface is severely incomplete and unusable.
Maintenance
Related MCP Connectors
100+ MCP tools for AI agents: content metadata, trade intelligence, business-expertise analysis.
Pay-per-use tool marketplace for AI agents. Search, price-check, and call APIs via MCP.
The Mercado Pago MCP Server implements the Model Context Protocol to provide AI agents and LLMs with access to Mercado Pago's APIs and tools within compatible development environments. It acts as an intermediary that translates Mercado Pago resources into executable functions (tools) that AI applications can invoke to perform actions and automate flows. The server simplifies integration, enables using documentation to implement or improve code, and optimizes operations through natural language interactions without manual implementations.
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage and interact with WordPress sites through MCP, providing tools for content creation, moderation, WooCommerce operations, and governance.47GPL 2.0
- AlicenseAqualityDmaintenanceEnables AI assistants to publish, edit, search, and manage messages in Telegram channels via a set of MCP tools.8MIT
- AlicenseBqualityDmaintenanceEnables AI assistants to interact with Labradoc's document management, email ingestion, task extraction, and integration features through MCP tools.179 npmMIT
- AlicenseBqualityCmaintenanceEnables AI assistants to manage WhatsApp business operations including chatbots, broadcasts, campaigns, and contacts through 120+ MCP tools.10059 npmMIT