MCP Docs Server
A centralized MCP server for internal technical documentation that integrates with IDEs like Claude Code and VS Code, enabling semantic search and management of Markdown documents via natural language.
README
DevVault — MCP Docs Server
Servidor MCP para centralizar documentações técnicas internas da empresa. Integra com Claude Code, VS Code, JetBrains e qualquer cliente compatível com o protocolo MCP.
A busca usa matching semântico pela IA da IDE — a IA lê o contexto extraído de cada documento e identifica os relevantes usando sua própria compreensão de linguagem natural, sem depender de APIs externas de embeddings.
Stack
| Camada | Tecnologia |
|---|---|
| Servidor | Node.js 20 + Express |
| Protocolo | MCP SDK (@modelcontextprotocol/sdk) via HTTP + SSE |
| ORM | Prisma 6 |
| Banco | PostgreSQL 16 |
| Storage de arquivos | MinIO (compatível S3) |
| Rate limiting / cache | Redis 7 |
| Validação de schema | Zod |
Pré-requisitos
- Node.js 20+
- Docker e Docker Compose
Setup inicial
# 1. Instalar dependências
cd docs-mcp-server
npm install
# 2. Copiar e editar variáveis de ambiente
cp .env.example .env
# 3. Subir infraestrutura (PostgreSQL + Redis + MinIO)
npm run infra:up
# 4. Criar tabelas
npm run db:migrate
# 5. Gerar Prisma Client
npm run db:generate
# 6. Criar usuários e API keys iniciais
npm run db:seed
# 7. Fazer upload dos documentos de exemplo no MinIO
npx tsx scripts/upload-example-docs.ts
# 8. Iniciar servidor (porta 3339)
npm run dev
Guarde as API keys exibidas pelo seed — elas são geradas com hash SHA-256 e não podem ser recuperadas depois.
Variáveis de ambiente
# Banco de dados
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/mcp_docs
# Redis (rate limiting)
REDIS_URL=redis://localhost:6379
# MinIO (storage de arquivos Markdown)
S3_ENDPOINT=http://localhost:9002
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=minioadmin
S3_SECRET_ACCESS_KEY=minioadmin
S3_BUCKET=mcp-docs-internal
S3_FORCE_PATH_STYLE=true
# Servidor
PORT=3339
NODE_ENV=development
# Segurança
API_KEY_SECRET_LENGTH=32
RATE_LIMIT_MAX_REQUESTS=100
RATE_LIMIT_WINDOW_SECONDS=60
Configurar no Claude Code
Crie .mcp.json na raiz do projeto:
{
"mcpServers": {
"DevVault": {
"type": "http",
"url": "http://localhost:3339/mcp",
"headers": {
"Authorization": "Bearer docsk_dev_xxxx_<sua-api-key>"
}
}
}
}
Atenção: a chave correta é
"mcpServers"(não"servers"). Editar~/.claude/settings.jsonnão ativa o MCP — o arquivo.mcp.jsonna raiz do projeto é o que o Claude Code reconhece.
Configurar no VS Code (extensão Claude Code)
Crie .mcp.json na raiz do workspace:
{
"mcpServers": {
"DevVault": {
"type": "http",
"url": "http://localhost:3339/mcp",
"headers": {
"Authorization": "Bearer docsk_dev_xxxx_<sua-api-key>"
}
}
}
}
Atenção: a chave correta é
"mcpServers"(não"servers"). Após criar ou editar o arquivo, recarregue a janela do VS Code (Ctrl+Shift+P→ "Developer: Reload Window").
Tools MCP disponíveis
| Tool | Escopo | Descrição |
|---|---|---|
list_docs_for_matching |
docs:search |
Retorna metadados + contexto para matching semântico pela IA |
get_doc |
docs:read |
Retorna conteúdo Markdown completo pelo ID |
download_doc |
docs:download |
Gera URL pré-assinada de download (5 min) |
upload_markdown_doc |
docs:upload |
Faz upload, extrai contexto e indexa automaticamente |
validate_markdown_doc |
docs:upload |
Valida estrutura antes do upload |
list_recent_docs |
docs:search |
Lista documentações recentes por projeto/módulo |
suggest_doc_template |
docs:search |
Gera template Markdown no padrão da empresa |
create_user |
admin:keys |
Cria usuário e gera API key — retorna a chave raw (exibida uma única vez) |
Escopos por perfil
| Perfil | Escopos |
|---|---|
| Admin | todos (docs:* + admin:keys + admin:audit) |
| Colaborador | docs:search, docs:read, docs:download, docs:upload |
| Somente leitura | docs:search, docs:read, docs:download |
Parâmetros da tool create_user
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
name |
string | sim | Nome completo do usuário |
email |
string | sim | E-mail (deve ser único na base) |
role |
admin | collaborator | readonly |
sim | Perfil — define os escopos da API key gerada automaticamente |
allowed_projects |
string[] | não | Projetos permitidos. Omita ou passe [] para acesso a todos |
expires_at |
string (ISO 8601) | não | Data de expiração da chave. Omita para chave sem expiração |
Atenção: a API key retornada em
api_keyé exibida uma única vez. O servidor armazena apenas o hash SHA-256 — não é possível recuperá-la depois.
Como a busca semântica funciona
Fluxo de busca
Usuário: "como resolver consumer-timeout no RabbitMQ?"
1. IA chama list_docs_for_matching(query: "consumer-timeout rabbitmq")
→ banco pré-filtra por texto em título, tags e context (ILIKE)
→ retorna até 50 docs com { doc_id, title, project, category, tags, context[0:500] }
2. IA lê os contextos e identifica semanticamente os relevantes
(sem API externa — usa a própria compreensão de linguagem)
3. IA chama get_doc(doc_id) para obter o conteúdo completo
ou download_doc(doc_id) para gerar link de download
Escalabilidade
| Tamanho da base | Estratégia recomendada |
|---|---|
| Até ~200 docs | list_docs_for_matching sem query — IA lê todos os contextos |
| 200–1000 docs | list_docs_for_matching(query: "termos do problema") — pré-filtro textual reduz o conjunto |
| 1000+ docs | Pré-filtro por project + category + query para manter o conjunto pequeno |
O parâmetro query realiza ILIKE em título, tags, filename e no campo context do banco — retornando apenas candidatos texualmente relacionados para a IA analisar semanticamente.
Melhoria possível: Full-Text Search com PostgreSQL
A busca atual usa ILIKE %termo%, que funciona bem para bases pequenas e médias mas tem duas limitações relevantes em português:
- Não entende variações morfológicas:
"download"não bate em"downloads","erro"não bate em"erros". - Performance:
ILIKEcom%no início da string não usa índices B-tree — em bases grandes, vira full table scan.
O PostgreSQL tem suporte nativo a Full-Text Search via to_tsvector / plainto_tsquery, com dicionário portuguese que faz stemming (reduz as palavras à raiz), normaliza acentos e ignora stopwords. Com isso:
"erros de download"bate em documentos com"erro","baixar","downloads"etc.- A busca usa índice GIN — muito mais rápida em bases com milhares de documentos.
- É possível ordenar resultados por relevância via
ts_rank.
Como implementar:
-
Criar índice GIN na migration:
CREATE INDEX idx_documents_fts ON documents USING gin(to_tsvector('portuguese', title || ' ' || COALESCE(context, '') || ' ' || array_to_string(tags, ' '))); -
Substituir os filtros
ILIKEporto_tsvector+plainto_tsqueryemlistDocsForMatching, viaprisma.$queryRawpara o trecho da query, mantendo os filtros deallowedProjects,project,moduleecategorycomo condiçõesANDnormais do Prisma. -
Usar
ts_rankpara ordenar por relevância em vez de apenasupdatedAt.
O fallback automático (quando a busca textual retorna zero) continua sendo válido com FTS — apenas o critério de "não encontrou nada" muda de "nenhum ILIKE bateu" para "nenhum documento passou no plainto_tsquery".
Veja docs/postgres-vs-dynamodb.md para a análise de por que o DynamoDB não é adequado como substituto do PostgreSQL para este projeto.
Upload de documento
Markdown recebido
→ extractTitle() + extractMetadata() — título, categoria, projeto, módulo, tags
→ extractContext() — corpo sem seção de metadados nem blocos de código
→ validateMarkdown() — seções obrigatórias, secrets, HTML perigoso
→ MinIO/S3 — arquivo .md completo armazenado
→ PostgreSQL documents — metadados + context salvos
→ PostgreSQL document_chunks — seções indexadas por heading
O campo context extraído é o que a IA usa para matching semântico — quanto mais rico o conteúdo das seções do documento, mais precisa a identificação.
Infraestrutura local
| Serviço | URL / Acesso |
|---|---|
| MCP Server | http://localhost:3339 |
| Health check | http://localhost:3339/health |
| MinIO Console | http://localhost:9003 — minioadmin / minioadmin |
| PostgreSQL | localhost:5432 — postgres / postgres / db: mcp_docs |
| Redis | localhost:6379 |
Scripts
npm run dev # Servidor com hot-reload
npm run build # Compila TypeScript
npm test # Roda testes (Vitest)
npm run test:mcp # Teste e2e com MCP SDK
npm run db:migrate # Aplica migrations pendentes
npm run db:generate # Regenera Prisma Client
npm run db:seed # Cria usuários e API keys de dev
npm run db:studio # Prisma Studio (visualizar banco)
npm run infra:up # Sobe PostgreSQL + Redis + MinIO
npm run infra:down # Para os containers
npx tsx scripts/upload-example-docs.ts # Upload dos docs de exemplo no MinIO
Exemplos de uso na IDE
Consulte o DevVault: existe documentação sobre erro de consumer-timeout no RabbitMQ?
Busque nas docs se já resolvemos problema com URL assinada expirando no módulo Admin do Reg+.
Faça upload deste arquivo como documentação do projeto Reg+, categoria Bug, módulo Mensageria.
Gere um template de documentação para um Bug no projeto SafeDocs, módulo Admin.
Liste as documentações mais recentes do projeto Reg+.
Crie um usuário chamado João Silva, e-mail joao@empresa.com, role collaborator, com acesso apenas ao projeto Reg+.
Arquitetura e fluxo de comunicação
Veja docs/ARCHITECTURE.md para os diagramas completos.
Veja docs/search-flow.md para o detalhamento do fluxo de busca (ILIKE atual vs Full-Text Search).
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。