Skip to main content
Glama
adventureandre

@expertcustom/funilaria-mcp

@expertcustom/funilaria-mcp

MCP-Server (Model Context Protocol) mit den typisierten Tools, die die KI von Aurora zum Schreiben und Lesen im Portal Funilaria & Pintura verwendet.

Er ersetzt mcp-fetch, indem er HTTP-Anfragen von Hand mit dem im Systemprompt geschriebenen Geheimnis aufbaut: Hier ist jede Operation ein Tool mit Schema, Beschreibung und Fehler auf Portugiesisch.

IA do Aurora ──stdio──> npx @expertcustom/funilaria-mcp ──HTTPS──> backend NestJS

Gemäß ADR-001 ist dieses Paket ein Adapter: Hier wohnt keine Geschäftslogik. Jedes Tool ruft einen bereits existierenden Endpoint auf, und der Backend-Dienst bleibt der Entscheidungsträger.

Tools – wer definiert, ist das Backend

Dieses Paket weiß nicht, welche Tools existieren. Beim Start ruft es GET /mcp/catalogo ab und veröffentlicht, was kommt; die Ausführung läuft über POST /mcp/executar, und das Backend löst den Namen zum Dienst auf.

subida  ──> GET  /mcp/catalogo   → lista publicada em tools/list
chamada ──> POST /mcp/executar   → { name, args }

Der Grund ist operativ: Früher kostete ein neues Tool das Bearbeiten dieses Pakets, das Bauen, Committen, Veröffentlichen und Neuinstallieren des MCP im Aurora – fünf Schritte, um einen Endpoint freizuschalten, der bereits im Backend existierte. Jetzt ist es ein Commit eines einzigen Moduls in backend/src/mcp.

Die aktuelle Liste stammt von GET /mcp/catalogo. Es gibt hier absichtlich keine Kopie davon: Eine Kopie altert und beginnt zu lügen.

Wenn der Katalog nicht antwortet, veröffentlicht der Server ein einziges Tool, funilaria_catalogo_indisponivel, dessen Beschreibung erklärt, was zu prüfen ist. Ohne es wäre das Symptom „die Tools sind verschwunden" und die Diagnose würde an der falschen Stelle beginnen.

Der Katalog wird einmal, beim Start, abgerufen: Der MCP-Client liest tools/list direkt nach dem Verbinden und fragt nicht erneut. Ein im Backend hinzugefügtes Tool kommt bei der nächsten Neuinstallation des Servers im Aurora.

Related MCP server: Telegram Bot MCP Server

Authentifizierung

Dienst-Anmeldedaten mit explizitem shopId sind der Hauptweg, sowohl zum Schreiben als auch zum Lesen. Header x-aurora-secret, derselbe Wert wie AURORA_WEBHOOK_SECRET im Backend; er repräsentiert keine Person, sondern den Dienst.

Eine KI, die mehrere Werkstätten bedient, hat keine Sitzung, also ist die Werkstatt ein Parameter, niemals impliziter Kontext. Auf der Backend-Seite ist das das @AllowService() in den Lese-Routen des Bestands: Der JwtAuthGuard akzeptiert das Geheimnis anstelle des JWT, und der ShopContextGuard verlangt dann den shopId – eine nicht existierende ID antwortet mit 404 Oficina não encontrada und nicht mit einer leeren Liste, die mit „Werkstatt ohne Bestand" verwechselt werden könnte.

Benutzersitzung (JWT von POST /auth/entrar) existiert weiterhin für die CLI-Befehle, gilt aber nicht mehr für die Tools: POST /mcp/executar ist immer ein Dienstaufruf, und die Werkstatt ist immer ein expliziter Parameter. Eine KI, die mehrere Werkstätten bedient, hatte nie eine Sitzung; beide Modi beizubehalten schuf nur einen Weg, auf dem ein weggelassener shopId verschiedene Dinge bedeutete.

Konfiguration – env ist der Hauptweg

In Produktion startet die Laufzeit von Aurora diesen Prozess, die die Variablen injiziert: Es gibt kein Terminal, und es wird kein Login-Befehl ausgeführt. Der Server funktioniert mit völlig leerem Datenträger.

Env

Akzeptierter Alias

Wofür

FUNILARIA_API_URL

PUBLIC_API_URL

Basis der API

FUNILARIA_SERVICE_SECRET

AURORA_WEBHOOK_SECRET

Dienst-Geheimnis (x-aurora-secret)

FUNILARIA_SIGNING_SECRET

AURORA_WEBHOOK_SIGNING_SECRET

Geheimnis der HMAC-Signatur (optional)

FUNILARIA_SHOP_ID

—

Standard-Werkstatt von consultar_estoque

FUNILARIA_TOKEN

—

Benutzer-JWT, falls vorhanden (optional)

Die Aliase existieren für den klassischen Fehler, die .env des Backends zu kopieren und das Geheimnis „verschwinden" zu lassen, weil das Präfix anders ist – AURORA_WEBHOOK_SECRET ist auf beiden Seiten exakt derselbe Wert.

Geheimnisse sind nie hartcodiert und werden nie aus dem Prompt gelesen. Die Datei ~/.config/funilaria-mcp/credentials.json (Modus 0600) ist eine Bequemlichkeit für die lokale Entwicklung; die env gewinnt immer und wird nie auf die Platte geschrieben.

Beim Boot schreibt der Server auf stderr (stdout gehört zum MCP-Protokoll) eine Zeile, die sagt, was konfiguriert ist und aus welcher env jede Sache stammt – nie den Wert. Das ist, was im Log von Aurora erscheint, wenn jemand den Variablennamen falsch schreibt:

[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.

HMAC-Signatur

Wenn FUNILARIA_SIGNING_SECRET existiert, bringt jedes Schreiben auch mit:

x-timestamp: <epoch em segundos>
x-signature: sha256=<HMAC-SHA256(`${timestamp}.${corpo}`)>

Das ist die in ADR-001 kartierte Verbesserung (schließt Replay und Leck durch Logs). Das Backend prüft noch nicht – unbekannte Header werden ignoriert, also kann man die Server-Seite aktivieren, ohne die laufenden Systeme zu brechen.

Installation

In der KI von Aurora (Produktion)

Registrieren Sie den Server mit den Variablen direkt in der MCP-Registrierung – kein Login, kein Geheimnis im Systemprompt:

{
  "command": "npx",
  "args": ["-y", "@expertcustom/funilaria-mcp"],
  "env": {
    "FUNILARIA_API_URL": "https://<api-do-portal>",
    "FUNILARIA_SERVICE_SECRET": "<mesmo valor de AURORA_WEBHOOK_SECRET>"
  }
}

Lokal, zum Entwickeln

# 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-mcp

Offene Punkte im Backend

Die vier ursprünglichen offenen Punkte (nicht erreichbarer Bestands-Webhook, Lesen ohne Dienst-Anmeldedaten, Geheimnis nach der Validierung geprüft, Distanz als toter Code) wurden im Backend korrigiert und gegen localhost:3334 erneut validiert. Was übrig blieb:

  1. Die KI hat keine Möglichkeit, den shopId herauszufinden. Es ist die einzige Information, die sie auswendig wissen muss, und heute kommt sie nur über FUNILARIA_SHOP_ID – was einen Server an eine Werkstatt bindet und den Multi-Werkstatt-Fall zerstört, der das Dienst-Design motiviert hat.

    Der günstigste Punkt zum Lösen ist lancar_consumo: Das Backend hat bereits Mitarbeiter und Werkstatt über die WhatsApp-Nummer identifiziert, gibt aber nur den Bestätigungstext zurück. Wenn IntakeResult shopId und memberId enthielte, würde das Gespräch fließen – „Ich habe 100 ml Lack verwendet" → „Wie viel habe ich diesen Monat ausgegeben?" wäre consultar_balancete mit beiden IDs in der Hand. Ohne das hat die zweite Frage keine mögliche Antwort.

  2. GET /estoque/movimentos blieb außerhalb von @AllowService(). Der shopId ist im ListMovementsDto deklariert, aber die Route akzeptiert keine Dienst-Anmeldedaten – der Parameter kann nicht verwendet werden. Entweder markiert man die Route oder entfernt das Feld aus dem DTO, um keine Fähigkeit vorzutäuschen, die es nicht gibt.

  3. HMAC-Signatur wird noch nicht geprüft. Der Client sendet bereits x-timestamp und x-signature, wenn ein Signatur-Geheimnis vorhanden ist (siehe oben). Es fehlt die Server-Seite, um Replay und Leck durch Logs zu schließen, wie in ADR-001 vorgesehen.

Entwicklung

npm install
npm run build     # tsc estrito, gera dist/
npm start         # sobe o servidor MCP em stdio

Available Tools

1 tool
funilaria_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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines5/5

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. 1 tool updatev0.1.0
    • First observedfunilaria_catalogo_indisponivel

TDQS

A4.1/5.0

Scored across 1 tool

Disambiguation5/5

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.

Naming Consistency5/5

The single tool name is descriptive and domain-specific, following a clear pattern. With no other tools, there is no inconsistency to penalize.

Tool Count1/5

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.

Completeness1/5

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

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers