Skip to content

IA no teu editor (ponte MCP) ​

O @basaltkit/ai-mcp é um servidor Model Context Protocolsó de dev que expõe os fluxos de desenvolvimento com IA do Basalt — analyze, doctor, plan, review e scaffold — a clientes MCP como o Claude Code e o Claude Desktop, por stdio (predefinição) ou HTTP opcional. Aponta-o ao teu projeto e pede a um agente que construa uma funcionalidade; ele planeia contra o teu stack real, pré-visualiza o diff, e só escreve quando tu disseres.

É uma ponte, nunca uma dependência de runtime.

O @basaltkit/ai-mcp apenas usa as APIs públicas oficiais do framework (através do @basaltkit/ai). Depende exclusivamente do @basaltkit/ai e do @basaltkit/mcp-core (sem dependências) — nunca do @basaltkit/core, @basaltkit/http, @basaltkit/cli, nem do @basaltkit/mcp de runtime. Instala-o como devDependency (ou corre-o com npx). Dois testes impõem isto mecanicamente: o packages/ai-mcp/test/boundary.test.ts percorre o grafo de imports transitivo e falha se alguma vez chegar ao runtime, e o packages/ai-mcp/test/dev-only-guard.test.ts falha se algum package do workspace listar a camada de IA fora das devDependencies. Em runtime, o servidor recusa arrancar com NODE_ENV=production (AiMcpProductionError; o bin sai com 1), por isso um processo em produção que o tenha puxado falha de forma visível. Só um production explícito recusa — os clientes MCP lançam o bin sem NODE_ENV, o caminho normal de desenvolvimento. Contorna-o deliberadamente com --allow-production (allowProduction: true, BASALT_AI_MCP_ALLOW_PRODUCTION=1).

As quatro camadas ​

O Basalt mantém a inteligência, a ponte de dev, o fio e o runtime estritamente separados:

PackagePapelRuntime?
@basaltkit/aiInteligência — a CLI basalt ai, os providers, o motor plan/make/reviewsó dev
@basaltkit/ai-mcpEsta página. Um servidor MCP só de dev que expõe esses fluxos a clientes MCPsó dev
@basaltkit/mcp-coreProtocolo MCP sem dependências: tipos + servidor genérico + transportes stdio/HTTPpartilhado
@basaltkit/mcpA superfície MCP de runtime da aplicação — rotas opt-in tornam-se ferramentasruntime

O @basaltkit/ai-mcp e o @basaltkit/mcp falam ambos MCP, mas são produtos diferentes: o mcp de runtime expõe as rotas da tua app a agentes em produção; o ai-mcp expõe fluxos de desenvolvimento (scaffolding, diagnósticos) ao teu editor enquanto constróis. Nunca confundas os dois.

A ponte em si é fina. Constrói um McpServer do mcp-core com cinco ferramentas, quatro recursos e quatro prompts, cada um deles um invólucro fino sobre uma função exportada do @basaltkit/ai. Toda a inteligência vive uma camada abaixo; toda a segurança (confinamento do workspace, preview antes de escrever) vive aqui.

Início rápido (Claude Code / Desktop) ​

Não é preciso instalar — a ponte corre via npx. Lê o teu projeto a partir do --cwd.

Claude Code ​

A partir da raiz do teu projeto:

bash
claude mcp add basalt-ai -- npx -y @basaltkit/ai-mcp --cwd="$PWD"

Ou committa um .mcp.json com âmbito de projeto na raiz do repositório (é isto que o create-basalt --mcp gera por ti):

json
{
  "mcpServers": {
    "basalt-ai": {
      "command": "npx",
      "args": ["-y", "@basaltkit/ai-mcp", "--cwd=."]
    }
  }
}

Claude Desktop ​

Edita o claude_desktop_config.json (Settings → Developer → Edit Config) e depois reinicia o Claude Desktop:

json
{
  "mcpServers": {
    "basalt-ai": {
      "command": "npx",
      "args": ["-y", "@basaltkit/ai-mcp", "--cwd=/absolute/path/to/my-basalt-app"]
    }
  }
}

O que já podes pedir ​

Assim que estiver ligado, o agente tem o stack e as ferramentas do teu projeto. Experimenta:

  • "Analisa este projeto Basalt e diz-me o que está ativo." → basalt_analyze
  • "Corre o doctor e mostra-me problemas de tenancy ou segurança." → basalt_doctor
  • "Planeia um recurso Invoice com valor e estado, por tenant." → basalt_plan
  • "Pré-visualiza a implementação e aplica-a se parecer segura." → basalt_make

As ferramentas read-only (analyze, doctor) e o preview do make não precisam de chave de API. O planeamento e a revisão chamam um LLM — vê Configurar o provider mais abaixo.

Criar uma nova app já pronta para MCP ​

O create-basalt liga a ponte por ti quando optas por MCP:

bash
npm create basalt my-saas -- --mcp

Isto acrescenta o @basaltkit/ai-mcp às devDependencies (nunca às dependencies), escreve um .mcp.json na raiz do projeto, e documenta-o no README da app. Vê create-basalt.

As ferramentas ​

Cinco ferramentas, mapeadas na superfície da CLI basalt ai. O structuredContent espelha a saída em texto em todas as chamadas, e cada ferramenta anuncia um outputSchema derivado dos schemas Zod exportados do @basaltkit/ai.

FerramentaObjetivoPrecisa de provider?Escreve ficheiros?
basalt_analyzeStack detetado, modelo de dados, diagnósticosnãonão
basalt_doctorDiagnósticos + previews de correções em memórianãonão
basalt_planLinguagem natural → ArchitecturePlansimnão
basalt_reviewCrítica LLM de um build → vereditosimnão
basalt_makeGera um vertical de recursopreview: não* / apply: —só no apply

* O basalt_make só precisa de provider quando lhe passas um request em vez de um plan já pronto (planeia internamente primeiro).

Uma falha de ferramenta nunca é um erro de protocolo: argumentos inválidos, um provider em falta, uma escrita recusada e um cancelamento voltam todos como um resultado normal com isError: true e a razão em content — para que o agente a possa ler e adaptar-se. Só JSON-RPC malformado produz um código de erro real.

basalt_analyze ​

Análise estática e offline. Entrada { workspaceRoot? }; saída um AnalysisReport (capacidades, packages instalados, base de dados, models, models tenant-scoped vs não-scoped, diagnósticos). O workspaceRoot — aqui e no basalt_doctor / basalt_plan — fica confinado ao --cwd do servidor: um caminho absoluto noutro sítio, .., ou um symlink que resolve para fora é recusado (Refused: … is outside the project root).

basalt_doctor ​

Diagnostica problemas de configuração, segurança e tenancy, e pré-visualiza as auto-correções disponíveis — os ficheiros que cada uma mudaria, calculados em memória. Nunca escreve. Saída { diagnostics, hasErrors, fixes: [{ id, status, message, files }] }, em que status é ready · noop · unfixable.

Nota que fixes só lista regras que estão ao mesmo tempo a disparar e são auto-corrigíveis — o que hoje são apenas a fastify-logger-off e a insecure-app-secret. Tudo o resto em diagnostics é correção manual; vê a tabela completa de regras.

basalt_plan ​

Transforma um pedido num ArchitecturePlan fundamentado (entidades, passos, permissões, eventos de audit, avisos, schemaVersion). Entrada:

jsonc
{
  "request": "an Invoice resource: amount, status (pago|pendente), tenant-scoped",
  "workspaceRoot": ".",      // opcional
  "temperature": 0,          // opcional
  "maxTokens": 4096          // opcional
}

Read-only — produz um plano, não muda nada. Faz streaming do progresso e pode ser cancelado (vê Operações demoradas mais abaixo).

basalt_review ​

Uma passagem LLM sobre o resultado de um build contra o seu plano (tenancy, segurança, RBAC, validação, testes, fit). Entrada { plan, makeResult } — ambos objetos obrigatórios; saída um AgentReview cuja flag approved é derivada das issues — uma issue de severidade error bloqueia.

basalt_make ​

Implementa um plano: gera o vertical do recurso (schema, repositório, service, rotas, testes) e liga-o no src/app.ts. Seguro por construção — vê a secção seguinte. Entrada:

jsonc
{
  "plan": { /* um ArchitecturePlan vindo do basalt_plan */ },
  // ou, em vez de plan:
  "request": "an Invoice resource …",  // planeia e depois implementa (precisa de provider)
  "workspaceRoot": ".",                 // opcional, confinado ao diretório de arranque
  "mode": "preview",                    // "preview" (predefinição) | "apply"
  "force": false,                       // sobrescreve ficheiros existentes (só no apply)
  "migrate": false                      // corre `prisma db push` (só no apply)
}

O schema de entrada declara oneOf: [{ required: ['plan'] }, { required: ['request'] }] — exatamente um dos dois é o ponto de entrada.

A correlação plan↔make é stateless: é o cliente que transporta o ArchitecturePlan completo (com o seu schemaVersion) do basalt_plan para o basalt_make — não há nenhum armazenamento de planos no servidor.

make seguro ​

Escrever ficheiros a partir de um agente autónomo é a parte arriscada, por isso o modelo de segurança é o ponto central.

  • O preview é a predefinição e não escreve nada. Sem mode (ou com mode:"preview"), a ferramenta devolve preview.perFile[] — todos os ficheiros que escreveria, cada um com uma action (create | overwrite) e um diff unificado — mais preview.clashes (caminhos que já existem). Nada toca no disco.
  • O preview corre sempre primeiro. Mesmo um apply calcula o dry run antes de escrever, para que a verificação de confinamento abaixo corra contra a lista real de alvos.
  • O apply é explícito. É preciso mode:"apply" para escrever.
  • Sobrescrever exige force. Um apply recusa-se a esmagar ficheiros existentes a menos que force:true.
  • O migrate tem duplo portão. O prisma db push só corre com migrate:true, e nunca por predefinição.
  • As escritas estão confinadas ao workspace. Um workspaceRoot (ou qualquer caminho-alvo) que escape ao diretório de arranque — via travessia .., caminho absoluto, ou symlink — é rejeitado antes de qualquer escrita. O confinamento resolve o realpath do ancestral existente mais próximo, por isso uma fuga por symlink é apanhada mesmo para um caminho que ainda não existe. Um agente não consegue escrever fora do teu projeto.
  • Confirmação — falha fechado. Um apply é confirmado por elicitation MCP com um resumo de uma linha do que será escrito. Em stdio isto funciona quando o cliente anuncia a capacidade elicitation no initialize. Quando não é possível perguntar ao cliente (sem suporte de elicitation, ou o transporte HTTP), o apply é recusado — revê a pré-visualização e aplica-a tu — a não ser que o servidor tenha arrancado com --allow-unconfirmed-apply (programaticamente: allowUnconfirmedApply: true).

O ciclo recomendado:

text
basalt_analyze            → understand the stack
basalt_plan(request)      → get an ArchitecturePlan
basalt_make(plan)         → PREVIEW: read the diffs + clashes
basalt_review(plan, prev) → catch tenancy/security/RBAC issues
basalt_make(plan, apply)  → write, only when the preview + review look right

Recursos & prompts ​

Recursos — puxar o estado do projeto como contexto ​

Reflexos read-only do teu workspace que o agente pode ler diretamente. São calculados de novo em cada resources/read, e sempre contra a raiz de workspace do servidor (--cwd) — os recursos não recebem argumentos:

URIMIMEConteúdo
basalt://project/contextapplication/jsonO ProjectContext detetado — stack, models Prisma, ficheiros app/server/env
basalt://project/analysisapplication/jsonO AnalysisReport — capacidades, resumo do modelo de dados, diagnósticos
basalt://project/diagnosticsapplication/jsonAs ocorrências do doctor
basalt://knowledge/architecturetext/markdownAs convenções Basalt em que o planeador é fundamentado (BASALT_KNOWLEDGE)

Prompts — modelos de fluxo de trabalho ​

Quatro modelos de prompt codificam o ciclo seguro e referem as ferramentas pelo nome, para que até um agente ingénuo siga o preview-antes-de-escrever:

PromptArgumentosGuia
plan-featurerequest (obrigatório)analyze → plan → make preview → review → make apply
scaffold-resourcename (obrigatório), fields (opcional)um build focado de uma só entidade
harden-tenancy—doctor → rever correções de tenancy → aplicar
add-rbacresource (obrigatório)ligar guards de permissões a um recurso

No Claude Code, os prompts aparecem como slash commands (ex.: /plan-feature).

Configurar o provider (para plan / review) ​

O basalt_plan, o basalt_review e o basalt_make com um request chamam um modelo. A configuração é lida do ambiente com que o cliente MCP arranca o servidor — as mesmas variáveis que a CLI @basaltkit/ai usa:

VariávelSignificado
AI_PROVIDERanthropic (predefinição), openai (qualquer gateway compatível com OpenAI), ou ollama
AI_API_KEYA chave do fornecedor (não é precisa para o Ollama)
AI_BASE_URLURL base do gateway (ex.: um /v1 compatível com OpenAI)
AI_MODELSubstituição do id do modelo
AI_STREAM'false' desativa o streaming SSE no provider compatível com OpenAI

Passa-as pelo bloco env do cliente:

json
{
  "mcpServers": {
    "basalt-ai": {
      "command": "npx",
      "args": ["-y", "@basaltkit/ai-mcp", "--cwd=."],
      "env": { "AI_PROVIDER": "anthropic", "AI_API_KEY": "sk-ant-…" }
    }
  }
}

As chaves ficam em memória

A ponte lê as chaves do provider apenas para construir o provider em processo, e só quando uma ferramenta que precisa de modelo é de facto chamada (a sessão constrói-o de forma preguiçosa). Nunca as regista, persiste ou ecoa — e a mensagem de erro do providerHelp que te guia quando falta configuração nomeia deliberadamente apenas os parâmetros, nunca um valor. As ferramentas read-only (analyze, doctor) e o preview do make não precisam de chave nenhuma.

Operações demoradas ​

O plan, o review e o make reportam progresso e podem ser cancelados através do protocolo MCP:

  • Progresso — passa um _meta.progressToken no teu tools/call; a ponte emite notifications/progress à medida que o modelo faz streaming e à medida que o make constrói cada recurso. (O progresso ao vivo exige stdio — vê Transportes.)
  • Cancelamento — envia notifications/cancelled com o id do pedido; a geração em curso é abortada prontamente e a ferramenta devolve isError: true com o texto Cancelled.

Transportes ​

TransporteQuandoComo
stdio (predefinição)Dev local; o Claude Code/Desktop arranca o servidorbasta correr o bin
HTTP (opcional)Remoto/CI, servidor partilhado de equipabasalt-ai-mcp --http[=port]
bash
# stdio (predefinição) — o cliente arranca isto
npx @basaltkit/ai-mcp --cwd=.

# HTTP numa porta efémera (imprime o URL); apenas loopback
npx @basaltkit/ai-mcp --http --cwd=.

# HTTP numa porta fixa
npx @basaltkit/ai-mcp --http=8848 --cwd=.

O transporte HTTP é JSON-RPC pedido/resposta sobre POST /mcp (mínimo, sem SSE); usa stdio quando precisares de streaming de progresso ao vivo.

O HTTP é guardado, e liga-se ao loopback por predefinição

O transporte HTTP liga-se a 127.0.0.1 e rejeita pedidos cujo header Host não seja um nome de loopback (anti-DNS-rebinding) ou cujo Origin, quando presente, não seja uma origem de loopback (anti-CSRF — um browser envia sempre Origin num POST cross-site, por isso a sua ausência significa um cliente não-browser). Um pedido rejeitado recebe 403 e nunca chega a uma ferramenta.

Esse guard trava browsers; não é autenticação (qualquer cliente que não seja um browser pode enviar Host: 127.0.0.1). Por isso, ligar noutro sítio (--host=0.0.0.0 para CI) é recusado, a não ser que dês também um token — --token=<segredo> ou BASALT_AI_MCP_TOKEN — que todos os pedidos têm então de enviar como Authorization: Bearer <segredo>. Acrescenta os hostnames que os clientes usam com --allowed-hosts=ci.internal,…. Os corpos dos pedidos têm um tecto de 1 MiB (413).

Uso programático ​

Para testes ou embedding, constrói o servidor sem transporte e comanda-o diretamente:

ts
import { buildAiMcpServer } from '@basaltkit/ai-mcp'

const server = buildAiMcpServer({ cwd: '/path/to/project' })
const res = await server.handleMessage({ jsonrpc: '2.0', id: 1, method: 'tools/list' })

O createAiMcpServer(opts) arranca em stdio; o createAiMcpHttpServer(opts) arranca em HTTP. Ambos aceitam cwd, um createReader injetável (para testes sobre um projeto em memória), e createProvider (para injetar um modelo falso — sem rede).

Referência de opções ​

Flags do CLI (basalt-ai-mcp) ​

FlagTipoPredefiniçãoObjetivo
--cwd=<path>stringprocess.cwd()A raiz do projeto que todas as ferramentas e recursos leem. Com .mcp.json, --cwd=. resolve para o diretório que o cliente abriu
--http / --http=<port>boolean / numberstdio (desligado)Muda para o transporte HTTP. --http sozinho usa a porta 0 — uma porta efémera, impressa no stdout como basalt-ai-mcp listening on <url>
--host=<host>string127.0.0.1Endereço de bind; só é lido quando o --http está presente. Ligar fora do loopback exige --token
--token=<segredo>stringBASALT_AI_MCP_TOKENSó HTTP: exige Authorization: Bearer <segredo> em todos os pedidos. Obrigatório para um --host fora do loopback
--allowed-hosts=<a,b>lista separada por vírgulassó nomes de loopbackSó HTTP: hostnames Host extra a aceitar quando ligado fora do loopback
--sessionsbooleandesligado (sem estado)Só HTTP: liga as sessões Mcp-Session-Id, para que um notifications/cancelled enviado noutro POST cancele uma chamada em curso (vê sessions abaixo)
--allow-unconfirmed-applybooleandesligadoDeixa o basalt_make aplicar quando o cliente não consegue confirmar (sem elicitation). Desligado por omissão: esse apply é recusado
--allow-productionbooleandesligado (BASALT_AI_MCP_ALLOW_PRODUCTION)Arranca mesmo com NODE_ENV=production. Desligado por omissão: a ponte, só de desenvolvimento, recusa arrancar aí

buildAiMcpServer(options) · createAiMcpServer(options) ​

AiMcpOptions é a configuração da sessão; o createAiMcpServer acrescenta os streams de stdio.

OpçãoTipoPredefiniçãoObjetivo
cwdstringprocess.cwd()Raiz de workspace que ferramentas e recursos usam por predefinição; também a raiz de confinamento do workspaceRoot de todas as ferramentas (leituras e escritas)
envRecord<string, string | undefined>process.envDe onde a configuração do provider (e o NODE_ENV, para a guarda dev-only) é lida — injeta um ambiente fixo em vez do do processo
createReader(root: string) => ProjectReadernodeReaderComo os ficheiros do projeto são lidos. Injeta um reader em memória para testar sem disco
createProvider() => AIProviderconstruído a partir do envInjeta um modelo falso — sem rede, sem chaves
allowUnconfirmedApplybooleanfalseDeixa o basalt_make aplicar sem confirmação por elicitation. Por omissão: recusa (falha fechado)
allowProductionbooleanfalseConstrói mesmo com NODE_ENV=production. Por omissão: lança AiMcpProductionError (o createAiMcpHttpServer rejeita com ele)
inputNodeJS.ReadableStreamprocess.stdinSó stdio: ler JSON-RPC de outro stream (testes)
output{ write(chunk: string): unknown }process.stdoutSó stdio: escrever JSON-RPC para outro destino (testes)

O createAiMcpServer devolve um StdioHandle cujo close() desliga o listener do stdin.

createAiMcpHttpServer(options) ​

AiMcpOptions mais as ServeHttpOptions do mcp-core. Devolve um Promise<HttpHandle> ({ port, url, close() }).

OpçãoTipoPredefiniçãoObjetivo
portnumber00 escolhe uma porta efémera (lê-a de volta em handle.port / handle.url)
hoststring'127.0.0.1'Endereço de bind. Loopback por predefinição — isto é uma superfície de dev
pathstring'/mcp'Caminho do endpoint JSON-RPC. Sem flag no CLI; só programaticamente
allowedHostsstring[]só nomes de loopbackHostnames Host extra a aceitar quando ligas deliberadamente fora do loopback. Comparados sem distinguir maiúsculas, porta ignorada
allowedOriginsstring[]só origens de loopbackValores Origin extra a aceitar (esquema + host + porta completos)
allowRequest(origin, host, req) => boolean—Substituição total do guard; substitui as verificações de loopback/allowedHosts/allowedOrigins
tokenstring—Exige Authorization: Bearer <token> (comparação em tempo constante, via bearerAuthorizer). Necessário para um host fora do loopback
authorize(req) => boolean | Promise<boolean>—Autenticação própria em vez de token; false responde 401
maxBodyBytesnumber1048576Corpos maiores recebem 413
sessionsboolean | { ttlMs?, maxSessions? }falseSessões Streamable-HTTP: o initialize responde com um Mcp-Session-Id, cada pedido seguinte tem de o levar (400 sem ele, 404 desconhecido/expirado/alheio — volta a inicializar), DELETE termina-a, e um notifications/cancelled enviado à parte cancela a chamada que nomeia, só dentro da mesma sessão. Desligado por predefinição para que clientes sem o header continuem a funcionar
principal(req) => string | undefinedhash do AuthorizationA quem pertence uma sessão — um pedido que resolva para outro principal recebe 404

Argumentos das ferramentas ​

FerramentaArgumentoTipoPredefiniçãoObjetivo
basalt_analyze · basalt_doctorworkspaceRootstringcwd do servidorAnalisar um subprojeto (absoluto ou relativo). Tem de ficar dentro do cwd — imposto, com symlinks resolvidos
basalt_planrequeststring— (obrigatório)O que construir, em linguagem natural
basalt_planworkspaceRootstringcwd do servidorFundamentar o plano num subprojeto. Tem de ficar dentro do cwd — imposto
basalt_plantemperaturenumber0Temperatura de amostragem; 0 mantém os planos reprodutíveis
basalt_planmaxTokensinteger4096Aumenta-o para um plano grande, com várias entidades, que fique truncado
basalt_reviewplan / makeResultobjeto— (ambos obrigatórios)A saída do basalt_plan e a saída do basalt_make a criticar
basalt_makeplan ou requestobjeto / string— (exatamente um)Um plano pronto, ou um pedido para planear primeiro (precisa de provider)
basalt_makeworkspaceRootstringcwd do servidorTem de ficar dentro do diretório de arranque — imposto, não indicativo
basalt_makemode'preview' | 'apply''preview'apply é o único valor que escreve
basalt_makeforcebooleanfalsePermite sobrescrever os caminhos reportados em preview.clashes
basalt_makemigratebooleanfalseCorre prisma db push depois de escrever (só no apply)

Modos de falha & resolução de problemas ​

As falhas ao nível da ferramenta viajam no resultado (isError: true); só JSON-RPC malformado produz um código de erro de protocolo.

MensagemTipoOndeQuando
basalt_plan needs an AI provider — … (também basalt_make / basalt_review)isErrorproviderHelpO createProvider lançou — sem AI_API_KEY, ou um AI_PROVIDER desconhecido
basalt_plan requires a non-empty "request".isErrorbasalt_planO argumento request estava em falta ou vazio
basalt_make requires either a "plan" (from basalt_plan) or a "request" to plan.isErrorbasalt_makeNenhum dos pontos de entrada foi fornecido
basalt_review requires a "plan" object (from basalt_plan). / … a "makeResult" object …isErrorbasalt_reviewFaltava um argumento-objeto obrigatório
Refused: workspaceRoot '<x>' escapes the launch directory (<root>)isErrorWorkspaceEscapeErrorbasalt_make: o workspaceRoot resolveu fora do --cwd — por design
Refused: workspaceRoot '<x>' is outside the project root (<root>)isErrorWorkspaceEscapeErrorbasalt_analyze / basalt_doctor / basalt_plan: o workspaceRoot (ou um symlink nele) resolve para fora do --cwd
Refused: absolute path not allowed: <p> · Refused: path escapes workspace: <p> · Refused: path resolves outside workspace via symlink: <p>isErrorassertConfinedUm ficheiro-alvo cairia fora do workspace
Refusing to overwrite N existing file(s) without force:true — …isErrorbasalt_makeUm apply esbarrou em preview.clashes. Revê os diffs e volta a correr com force:true
Apply cancelled — not confirmed.isErrorbasalt_makeO prompt de elicitation do cliente foi recusado
Refusing to apply without confirmation — …isErrorbasalt_makeO cliente não suporta elicitation (ou transporte HTTP) e o servidor não arrancou com --allow-unconfirmed-apply
Cancelled.isErrorqualquer ferramenta com modeloUm notifications/cancelled abortou a chamada em curso
Unknown tool: <name>JSON-RPC -32602mcp-coreO cliente chamou uma ferramenta que não é uma das cinco
Method not found: <method>JSON-RPC -32601mcp-coreUm método MCP fora do conjunto implementado
Forbidden: host/origin not allowedHTTP 403serveHttpO guard HTTP rejeitou um Host/Origin estranho antes do dispatch
UnauthorizedHTTP 401serveHttpO --token está definido e o bearer token do pedido falta ou está errado
failed to start HTTP server — serveHttp: refusing to bind non-loopback host …arranquebin--host fora do loopback sem --token
failed to start … refuses to start with NODE_ENV=productionarranque (sai com 1)bin / AiMcpProductionErrorNODE_ENV=production no bloco env do cliente ou na shell, sem --allow-production
Bad Request: Mcp-Session-Id header required …HTTP 400serveHttpO --sessions está ligado e o pedido não traz o header de sessão — faz primeiro o initialize
Session not found (expired or unknown) — initialize againHTTP 404serveHttpO --sessions está ligado e o id de sessão é desconhecido, expirou ou foi aberto por outro token
  • O agente não vê o meu projeto — verifica que o --cwd aponta para a raiz do projeto (onde vivem o package.json / prisma/schema.prisma). Os recursos usam sempre o --cwd do servidor; só as ferramentas aceitam um workspaceRoot por chamada.
  • O basalt_doctor mostra erros mas quase nenhum fixes — é o esperado. Só duas regras têm auto-corretores; as restantes são decisões manuais deliberadas.
  • As rotas dão 500 depois do mode:"apply" — foi adicionado um model Prisma mas o cliente não foi regenerado. Volta a correr o apply com migrate:true, ou corre npx prisma db push tu mesmo, e depois reinicia o dev server.
  • O progresso nunca chega — estás no transporte HTTP. Ele é só pedido/resposta; as notificações servidor→cliente precisam de stdio.
  • O servidor arranca mas o cliente não mostra nada — em stdio, o stdout é o canal JSON-RPC. Tudo o resto escrito lá corrompe o stream; a própria ponte só escreve no stdout em modo --http.
  • É seguro deixar isto ligado? — Sim. Nada escreve sem um mode:"apply" explícito, sobrescrever exige force, mudanças na BD exigem migrate, e todas as escritas estão confinadas à subárvore do projeto.

Ver também ​

  • Desenvolvimento assistido por IA — a CLI basalt ai sobre a qual a ponte é construída, incluindo a tabela completa de regras do doctor e a configuração do provider.
  • @basaltkit/mcp-core — a camada de protocolo; constrói o teu próprio servidor MCP sobre ela.
  • MCP (runtime) — expõe as rotas da tua app como ferramentas em produção.
  • Arquitetura: docs/rfcs/0001-basaltkit-ai-mcp.md. Fonte: packages/ai-mcp/src/** (tools, resources, prompts, safety.ts, server.ts, bin.ts).

Publicado sob a licença MIT.