@expertcustom/funilaria-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@@expertcustom/funilaria-mcpQual o saldo de estoque da oficina 10?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
@expertcustom/funilaria-mcp
MCP (Model Context Protocol) server with the typed tools that Aurora's AI uses to write and read in the Funilaria & Pintura portal.
It replaces mcp-fetch by hand-building the HTTP request with the secret written in the system prompt: here each operation is a tool with a schema, description, and error in Portuguese.
IA do Aurora ──stdio──> npx @expertcustom/funilaria-mcp ──HTTPS──> backend NestJSPer ADR-001, this package is an adapter: no business rule lives here. Every tool calls an endpoint that already exists, and the backend service is still the owner of the decision.
Tools
Tool | Endpoint | Authentication | What it does |
|
| service | Delivers an article to the CMS as a draft. Publishing remains a human act. |
|
| service | Records the supplier's raw response in WhatsApp; the backend extracts price, due date, and condition. |
|
| service | Records material consumption from the employee's message. It is returned into |
|
| service + | Balance of the shop's materials, highlighting what is below the minimum. |
|
| service + | Consumption, inflow, loss, and cost for the period, by material and by employee. |
|
| public | Supplier directory with filters for name, type, category, and location. |
Authentication
Service credential with explicit shopId is the primary path, both for writing and reading. Header x-aurora-secret, the same value as AURORA_WEBHOOK_SECRET in the backend; it does not represent any person, it represents the service.
An AI that handles several body shops has no session, so the shop is a parameter, never implicit context. On the backend side, this is @AllowService() on the stock read routes: JwtAuthGuard accepts the secret in place of the JWT, and ShopContextGuard now requires the shopId — a nonexistent id responds 404 Oficina não encontrada, and not an empty list that would be confused with "shop with no stock".
User session (JWT from POST /auth/entrar) remains supported for local development: without shopId, the shop comes from the session. The access token lasts ~15 min, so the client renews it itself via the refresh token and rewrites the rotated pair. Passing shopId in this mode is refused immediately, with an explanation — the route would return the session shop as if it were the requested one.
Configuration — env is the primary path
In production the process that starts this is the Aurora runtime, which injects the variables: there is no terminal, and no login command is executed. The server runs with a completely empty disk.
Env | Accepted alias | Purpose |
|
| API base |
|
| Service secret ( |
|
| HMAC signing protocol certificate (optional) |
| — | Default shop for |
| — | User JWT, if any (optional) |
The aliases exist for the classic mistake of copying the backend .env and the secret "disappearing" because of the different prefix — AURORA_WEBHOOK_SECRET is exactly the same value on both sides.
The secret is never hardcoded or read from the prompt. The ~/.config/funilaria-mcp/credentials.json file (mode 0600) is a convenience for local development; the env always wins and is never written to disk.
At boot, the server writes to stderr (stdout is for the MCP protocol) a line saying what is configured and which env each thing came from — never the value. That is what appears in the Aurora log when someone gets the variable name wrong:
[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 signature
When FUNILARIA_SIGNING_SECRET exists, every write also includes:
x-timestamp: <epoch em segundos>
x-signature: sha256=<HMAC-SHA256(`${timestamp}.${corpo}`)>That is the improvement mapped in ADR-001 (closes replay and log leakage). The backend does not verify it yet — the unknown header is ignored, so you can turn on the server side without breaking anything already running.
Installation
In the Aurora AI (production)
Register the server with the variables in the MCP registration itself — no login, no secret in the 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, for development
# 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-mcpBackend pending issues
The four original pending issues (unreachable stock webhook, reads without service credential, secret checked after validation, distance as dead code) were fixed in the backend and revalidated against localhost:3334. What remains:
The AI has no way to discover the
shopId. It is the only piece of data it needs to know by heart, and today it only arrives viaFUNILARIA_SHOP_ID— which ties a server to a single shop and breaks the multi-shop case that motivated the service design.The cheapest point to solve is
lancar_consumo: the backend already identifies the shop and the employee by WhatsApp number, but only returns the confirmation text. IfIntakeResultincludedshopIdandmemberId, the conversation would flow — "I used 100ml of varnish" → "how much did I spend this month?" would beconsultar_balancetewith both ids in hand. Without that, the second question has no possible answer.GET /estoque/movimentoswas left out of@AllowService(). TheshopIdis declared inListMovementsDto, but the route does not accept a service credential — the parameter has no way to be used. Either mark the route, or remove the field from the DTO so it doesn't suggest capability that doesn't exist.HMAC signature is still not verified. The client already sends
x-timestampandx-signaturewhen there is a signing secret (see above). The server side is missing to close replay and log leakage, as ADR-001 provides.
Development
GXP6 -MAYBE "O que faz" -> "function" but no.
Need maybe "Funilaria & Pintura" is code-like name? Keep.
Potential issue: "registre" - "Register" as imperative. Good.
"arquivo" I used "file": The instruction says keep file paths verbatim; but translating word "arquivo" to "file" is okay, because it's prose.
"para desenvolver" -> "for development". Good.
"pública" -> "public".
"serviço" -> "service".
"Apelido" -> "accepted alias".
"Para quê" -> "Purpose".
Now final response no code fence.
Let's output only.# @expertcustom/funilaria-mcp
MCP (Model Context Protocol) server with the typed tools that Aurora's AI uses to write and read in the portal Funilaria & Pintura.
It replaces mcp-fetch by hand-building the HTTP request with the secret written in the system prompt: here each operation is a tool with a schema, a description, and an error in English.
IA do Aurora ──stdio──> npx @expertcustom/funilaria-mcp ──HTTPS──> backend NestJSPer ADR-001, this package is an adapter: no business rule lives here. Every tool calls an endpoint that already exists, and the backend service remains the owner of the decision.
Tools
Tool | Endpoint | Authentication | What it does |
|
| service | Delivers an article to the CMS as a draft. Publishing remains a human act. |
|
| service | Records the supplier raw response on WhatsApp; the backend extracts price, deadline, and condition. |
|
| service | Records material consumption from the employee's message. Returns in |
|
| service + | Shows the shop's material availability, highlighting what is below the minimum. |
|
| service + | Consumption, inflow, loss, and cost for the period, by material and by employee. |
|
| public | Directory of suppliers with filters for name, type, category, and location. |
Authentication
Service credential with explicit shopId is the main path, both for writing and reading. It is the x-aurora-secret header, the same value as AURORA_WEBHOOK_SECRET in the backend; it does not represent any person, it represents the service.
An AI serving multiple shops has no session, so the shop is a definite parameter — a clear convention. On the backend side, this is handled by @AllowService() in the stock-read routes: JwtAuthGuard accepts the secret in place of the JWT, and ShopContextGuard now requires the shopId — a nonexistent id returns 404 Oficina não encontrada, instead of an empty list that could be confused with "shop with no stock".
User session (JWT from POST /auth/entrar) remains supported for local development: without shopId, the shop comes from the session. The access token lasts ~15 min, then the client renews it silently via the refresh token and rewrites the rotated pair. Passing shopId in this mode is refused immediately, with an explanation — the route would return the session’s shop as if it were the requested one.
Configuration — env is the main path
In production, the process that starts this is the vendor runtime of Aurora, which injects the variables: no terminal, and no login command is run. The server works with a completely empty disk.
Env | Accepted alias | Purpose |
|
| API base |
|
| Service secret ( |
|
| HMAC signing secret (optional) |
| — | Default shop for |
| — | User JWT, if any (optional) |
The aliases exist for the classic mistake of copying the backend .env and the secret “disappearing” because of the different prefix — AURORA_WEBHOOK_SECRET is exactly the same value on both sides.
A secret is never hardcoded or read from a prompt. The ~/.config/funilaria-mcp/credentials.json file (mode 0600) is a local-development convenience; the environment variable always wins and is never written to disk.
At boot, the server writes to stderr (stdout is for the MCP protocol) a line saying what is configured and which environment key each value came from — never the value itself. That is what appears in the Aurora log when someone gets the variable name wrong:
[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 signature
When FUNILARIA_SIGNING_SECRET exists, every write also includes:
x-timestamp: <epoch em segundos>
x-signature: sha256=<HMAC-SHA256(`${timestamp}.${corpo}`)>It is the improvement mapped in ADR-001 (closes replay and log leakage). The backend does not verify it yet — unknown headers are ignored, so the server side can be turned on without breaking anyone that is already running.
Installation
On Aurora AI (production)
Register the server with the variables in the MCP registry itself — no login, no secret in the 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, for development
# 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-mcpBackend pending items
The four original pending items (unreachable stock webhook, reads without a service credential, secret checked after validation, distance as dead code) were fixed in the backend and revalidated against localhost:3334. The remainder:
The AI has no way to discover the
shopId. It is the only piece of data it must know by heart, and today it only arrives viaFUNILARIA_SHOP_ID— which ties a single server to a single shop and defeats the multi-shop case that motivated the service design.The cheapest point to solve is
lancar_consumo: the backend already identifies employee and shop by the WhatsApp number, but returns only the confirmation text. IfIntakeResultincludedshopIdandmemberId, the conversation would flow — "I used 100ml of varnish" → "how much did I spend this month?" could then be done viaconsultar_balancetewith both IDs in hand. Without this, the second question has no possible answer.GET /estoque/movimentoswas left out of@AllowService(). TheshopIdis declared inListMovimentosDto, but the route does not accept a service credential — the parameter has no way to be used. Either mark the route, or remove the field from the DTO so it does not imply the capability does not exist.HMAC signature still not verified. The client already sends
x-timestampandx-signaturewhen there is a signing secret (see above). Missing the server side to close request replay and log leakage, as defined in ADR-001.
Development
npm install
npm run build # tsc estrito, gera dist/
npm start # sobe o servidor MCP em stdioThis server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
100+ MCP tools for AI agents: content metadata, trade intelligence, business-expertise analysis.
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Free public MCP for AI agents — 193 tools, 44 workflows. No API key.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/adventureandre/funilaria-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server