Skip to main content
Glama
adventureandre

@expertcustom/funilaria-mcp

@expertcustom/funilaria-mcp

Aurora의 AI가 Funilaria & Pintura 포털에 쓰고 읽을 때 사용하는, 타입이 지정된 tools를 갖춘 MCP(Model Context Protocol) 서버입니다.

mcp-fetch를 대체하며, system prompt에 적힌 비밀번호로 HTTP 요청을 직접 구성합니다. 여기서 각 작업은 스키마, 설명, 포르투갈어 오류 메시지를 갖춘 tool입니다.

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

ADR-001에 따라 이 패키지는 어댑터입니다. 비즈니스 규칙은 여기에 없습니다. 모든 tool은 이미 존재하는 엔드포인트를 호출하며, 백엔드 서비스가 결정의 주체로 남습니다.

Tools — 정의하는 쪽은 백엔드

이 패키지는 어떤 tools가 있는지 알지 못합니다. 시작 시 GET /mcp/catalogo를 가져와서 오는 대로 게시하고, 실행은 POST /mcp/executar로 진행되며 백엔드가 이름을 서비스로 해석합니다.

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

이유는 운영상의 문제입니다. 이전에는 새 tool을 추가하려면 이 패키지를 수정하고, 빌드하고, 커밋하고, 게시하고, Aurora에 MCP를 다시 설치해야 했습니다. 백엔드에 이미 존재하는 엔드포인트를 노출하는 데 다섯 단계가 걸렸습니다. 이제는 backend/src/mcp에서 모듈 하나만 커밋하면 됩니다.

현재 목록은 GET /mcp/catalogo에서 나옵니다. 여기에 의도적으로 복사본이 없습니다. 복사본은 오래되면 거짓말을 하기 시작하기 때문입니다.

카탈로그가 응답하지 않으면, 서버는 funilaria_catalogo_indisponivel이라는 단일 tool만 게시하며, 그 설명은 무엇을 확인해야 하는지 안내합니다. 이 tool이 없으면 증상은 "tools가 사라졌다"가 되고 진단이 잘못된 곳에서 시작될 것입니다.

카탈로그는 시작 시 한 번만 가져옵니다. MCP 클라이언트는 연결 직후 tools/list를 읽고 다시 묻지 않습니다. 백엔드에 추가된 tool은 Aurora에서 서버를 다음에 다시 설치할 때 반영됩니다.

Related MCP server: Telegram Bot MCP Server

인증

명시적 shopId가 있는 서비스 자격 증명이 쓰기와 읽기 모두의 기본 경로입니다. x-aurora-secret 헤더는 백엔드의 AURORA_WEBHOOK_SECRET과 같은 값입니다. 이는 어떤 사람도 나타내지 않으며 서비스를 나타냅니다.

여러 작업장을 담당하는 AI는 세션이 없으므로 작업장은 매개변수이며 암시적 컨텍스트가 아닙니다. 백엔드 쪽에서는 재고 읽기 라우트의 @AllowService()가 이를 처리합니다. JwtAuthGuard는 JWT 대신 비밀번호를 허용하고 ShopContextGuard는 shopId를 요구합니다. 존재하지 않는 id는 404 Oficina não encontrada로 응답하며, "작업장에 재고 없음"으로 오해될 수 있는 빈 목록이 아닙니다.

사용자 세션(POST /auth/entrar의 JWT)은 CLI 명령에 여전히 존재하지만 tools에는 더 이상 유효하지 않습니다. POST /mcp/executar는 항상 서비스 호출이며 작업장은 항상 명시적 매개변수입니다. 여러 작업장을 담당하는 AI는 세션이 없었습니다. 두 모드를 유지하면 shopId가 생략되었을 때 다른 의미를 갖는 경로가 생길 뿐입니다.

구성 — env가 기본 경로

프로덕션에서 이 프로세스를 실행하는 쪽은 Aurora 런타임이며 변수를 주입합니다. 터미널이 없고 로그인 명령도 실행되지 않습니다. 서버는 완전히 빈 디스크로 작동합니다.

Env

허용되는 별칭

용도

FUNILARIA_API_URL

PUBLIC_API_URL

API 기본 URL

FUNILARIA_SERVICE_SECRET

AURORA_WEBHOOK_SECRET

서비스 비밀번호 (x-aurora-secret)

FUNILARIA_SIGNING_SECRET

AURORA_WEBHOOK_SIGNING_SECRET

HMAC 서명 비밀번호 (선택 사항)

FUNILARIA_SHOP_ID

—

consultar_estoque의 기본 작업장

FUNILARIA_TOKEN

—

사용자 JWT (있는 경우, 선택 사항)

별칭이 있는 이유는 백엔드의 .env를 복사할 때 접두사가 달라 비밀번호가 "사라지는" 전형적인 실수 때문입니다. AURORA_WEBHOOK_SECRET은 양쪽에서 정확히 같은 값입니다.

비밀번호는 하드코딩되거나 프롬프트에서 읽히지 않습니다. ~/.config/funilaria-mcp/credentials.json 파일(모드 0600)은 로컬 개발의 편의를 위한 것입니다. env가 항상 우선하며 디스크에 기록되지 않습니다.

부팅 시 서버는 stderr(stdout은 MCP 프로토콜용)에 무엇이 구성되었는지, 각 항목이 어떤 env에서 왔는지를 한 줄로 씁니다. 값은 절대 쓰지 않습니다. 누군가 변수 이름을 잘못 입력했을 때 Aurora 로그에 나타나는 내용입니다.

[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 서명

FUNILARIA_SIGNING_SECRET이 있으면 모든 쓰기에 다음도 포함됩니다.

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

ADR-001에 매핑된 개선 사항입니다(재생 공격과 로그 누출을 차단). 백엔드는 아직 검증하지 않습니다. 알 수 없는 헤더는 무시되므로 이미 실행 중인 쪽을 깨지 않고 서버 쪽을 켤 수 있습니다.

설치

Aurora AI (프로덕션)

MCP 등록 자체에 변수와 함께 서버를 등록하세요. 로그인도, 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>"
  }
}

로컬, 개발용

# 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

백엔드의 미해결 사항

원래 네 가지 미해결 사항(도달할 수 없는 재고 웹훅, 서비스 자격 증명 없는 읽기, 검증 후에 확인되는 비밀번호, 죽은 코드로서의 거리)은 백엔드에서 수정되었고 localhost:3334로 재검증되었습니다. 남은 것:

  1. AI가 shopId를 알아낼 방법이 없습니다. AI가 외워야 하는 유일한 데이터이며, 현재는 FUNILARIA_SHOP_ID로만 전달됩니다. 이는 서버를 하나의 작업장에 묶고, 서비스 설계의 동기가 된 다중 작업장 사례를 무너뜨립니다.

    가장 저렴하게 해결할 지점은 lancar_consumo입니다. 백엔드는 이미 WhatsApp 번호로 직원과 작업장을 식별하지만 확인 텍스트만 반환합니다. IntakeResult에 shopId와 memberId가 포함되면 대화가 이어질 것입니다. "바니시 100ml 썼어" → "이번 달 얼마 썼지?"는 두 id를 손에 쥔 consultar_balancete가 될 것입니다. 이것이 없으면 두 번째 질문에는 답할 방법이 없습니다.

  2. GET /estoque/movimentos가 @AllowService() 밖에 있습니다. shopId는 ListMovementsDto에 선언되어 있지만 라우트는 서비스 자격 증명을 허용하지 않습니다. 매개변수를 사용할 방법이 없습니다. 라우트를 표시하거나, 존재하지 않는 기능을 암시하지 않도록 DTO에서 필드를 제거하세요.

  3. HMAC 서명이 아직 검증되지 않았습니다. 클라이언트는 서명 비밀번호가 있을 때 x-timestamp와 x-signature를 이미 보냅니다(위 참조). ADR-001이 예정한 대로 재생 공격과 로그 누출을 막으려면 서버 쪽이 필요합니다.

개발

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