Skip to main content
Glama
adventureandre

@expertcustom/funilaria-mcp

@expertcustom/funilaria-mcp

MCP服务器(模型上下文协议),带有Aurora AI用于在Funilaria & Pintura门户上写入和读取的带类型工具。

它取代了mcp-fetch,手动构建HTTP请求,并将密钥写在系统提示中:这里每个操作都是一个带有schema、描述和葡萄牙语错误的工具。

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

根据ADR-001,这个包是适配器:这里没有业务规则。每个工具都调用一个已存在的端点,后端服务仍然是决策的拥有者。

工具——由后端定义

这个包不知道存在哪些工具。启动时它获取GET /mcp/catalogo并发布返回的内容;执行通过POST /mcp/executar进行,后端将名称解析为服务。

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

原因是操作性的:以前,新工具需要编辑这个包、构建、提交、发布并在Aurora中重新安装MCP——五个步骤才能暴露一个后端已经存在的端点。现在只需在backend/src/mcp中提交一个模块。

当前列表来自GET /mcp/catalogo。这里故意没有它的副本:副本会过时并开始撒谎。

当目录不响应时,服务器发布一个单一工具funilaria_catalogo_indisponivel,其描述说明要检查什么。没有它,症状将是“工具消失了”,诊断会从错误的地方开始。

目录在启动时获取一次:MCP客户端在连接后立即读取tools/list,不会再次询问。后端添加的工具将在下次在Aurora中重新安装服务器时生效。

Related MCP server: Telegram Bot MCP Server

认证

带有显式shopId的服务凭据是主要路径,无论是写入还是读取。Header x-aurora-secret,与后端AURORA_WEBHOOK_SECRET的值相同;它不代表任何人,代表服务。

一个服务多家店铺的AI没有会话,所以店铺是参数,绝不是隐式上下文。在后端,这是库存读取路由上的@AllowService():JwtAuthGuard接受密钥代替JWT,ShopContextGuard开始要求shopId——不存在的id返回404 Oficina não encontrada,而不是一个会与“店铺无库存”混淆的空列表。

用户会话(来自POST /auth/entrar的JWT)仍然存在用于CLI命令,但不再适用于工具:POST /mcp/executar始终是服务调用,店铺始终是显式参数。一个服务多家店铺的AI从未有过会话;保留两种模式只会创造一个shopId被省略时含义不同的路径。

配置——env是主要路径

在生产环境中,启动此进程的是Aurora运行时,它注入变量:没有终端,也不执行任何登录命令。服务器在磁盘完全为空的情况下运行。

环境变量

接受的别名

用途

FUNILARIA_API_URL

PUBLIC_API_URL

API的基础地址

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中规划的改进(防止重放和日志泄露)。后端尚未验证——未知header会被忽略,所以可以启用服务器端而不会破坏已经在运行的系统。

安装

在Aurora AI中(生产环境)

在MCP注册中注册服务器并带上变量——无需登录,系统提示中也没有密钥:

{
  "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

后端待办事项

最初的四个待办事项(库存webhook不可达、没有服务凭据的读取、验证后才检查密钥、距离作为死代码)已在后端修复,并针对localhost:3334重新验证。剩下的:

  1. **AI无法发现shopId。**这是它唯一需要记住的数据,目前只能通过FUNILARIA_SHOP_ID获得——这会将一个服务器绑定到一家店铺,并破坏了促使服务设计的多店铺场景。

    最便宜的解决点是lancar_consumo:后端已经通过WhatsApp号码识别了员工和店铺,但只返回确认文本。如果IntakeResult包含shopId和memberId,对话就能流畅进行——“我用了100毫升清漆”→“我这个月花了多少?”就可以用这两个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