Projeto final: Crie um servidor MCP pronto para produção que integre múltiplos provedores, ferramentas e sistemas do mundo real
Parabéns por chegar ao projeto final! Agora você aplicará tudo o que aprendeu para construir um servidor MCP pronto para produção que demonstra padrões de integração do mundo real e melhores práticas.
Seu projeto final é um Servidor de Inteligência de Workspace - um servidor MCP que fornece às aplicações de IA acesso abrangente a ambientes de desenvolvimento. Este servidor integrará múltiplas fontes de dados e fornecerá ferramentas poderosas para gerenciamento de projetos, fluxos de trabalho de desenvolvimento e colaboração em equipe.
🔧 Arquitetura Multi-Provedor: Sistema de arquivos, Git, banco de dados, API e provedores de configuração 🛠️ Conjunto Abrangente de Ferramentas: Operações de arquivo, gerenciamento de projetos, comunicação e ferramentas de desenvolvimento ⚡ Pronto para Produção: Logging, monitoramento, tratamento de erros e desligamento gracioso 🔒 Seguro por Design: Validação de entrada, controles de acesso e logging de auditoria 📊 Observável: Verificações de saúde, métricas e monitoramento de performance 🧪 Bem Testado: Testes unitários, testes de integração e testes end-to-end
<CodeExample
title="Estrutura Completa do Projeto"
language="text"
code={mcp-workspace-server/ ├── src/ │   ├── index.ts                 # Entrada principal do servidor │   ├── config/ │   │   ├── index.ts            # Gerenciamento de configuração │   │   └── schema.ts           # Validação de config │   ├── providers/ │   │   ├── index.ts            # Registro de provedores │   │   ├── filesystem.ts       # Provedor de sistema de arquivos │   │   ├── database.ts         # Provedor de banco de dados │   │   ├── api.ts              # Provedor de API externa │   │   └── git.ts              # Provedor de repositório Git │   ├── tools/ │   │   ├── index.ts            # Registro de ferramentas │   │   ├── file-ops.ts         # Operações de arquivo │   │   ├── project-mgmt.ts     # Gerenciamento de projeto │   │   ├── communication.ts    # Ferramentas Email/Slack │   │   └── development.ts      # Ferramentas dev (git, npm, etc.) │   ├── middleware/ │   │   ├── auth.ts             # Autenticação │   │   ├── rate-limit.ts       # Limitação de taxa │   │   └── logging.ts          # Logging de requisições │   ├── utils/ │   │   ├── validation.ts       # Validação de entrada │   │   ├── security.ts         # Helpers de segurança │   │   └── errors.ts           # Classes de erro │   └── types/ │       ├── config.ts           # Tipos de configuração │       ├── providers.ts        # Interfaces de provedor │       └── tools.ts            # Interfaces de ferramenta ├── tests/ │   ├── unit/                   # Testes unitários │   ├── integration/            # Testes de integração │   └── fixtures/               # Dados de teste ├── docs/ │   ├── README.md               # Documentação principal │   ├── API.md                  # Referência da API │   └── DEPLOYMENT.md           # Guia de implantação ├── config/ │   ├── development.json        # Config de desenvolvimento │   ├── production.json         # Config de produção │   └── test.json               # Config de teste ├── scripts/ │   ├── build.sh               # Script de build │   ├── test.sh                # Script de teste │   └── deploy.sh              # Script de implantação ├── .github/ │   └── workflows/             # Workflows CI/CD ├── package.json ├── tsconfig.json ├── jest.config.js ├── .eslintrc.js └── .gitignore}
/>
Seu servidor seguirá estes princípios arquiteturais:
Filosofia de Design: Construa para produção desde o primeiro dia. Cada componente deve incluir tratamento de erros, logging, validação e testes.
Organização de servidor MCP pronto para produção
Module content not available.
Module content not available.
Seu servidor precisa de um conjunto robusto de ferramentas que cubra todo o espectro de tarefas de desenvolvimento e gerenciamento de projetos.
<CodeExample title="Implementação do Registro de Ferramentas" language="typescript" code={`export class ToolRegistry { private tools: Map<string, Tool> = new Map(); private toolProviders: Map<string, ToolProvider> = new Map(); private executionLog: ExecutionLog[] = []; private rateLimiter: RateLimiter;
constructor(private config: any, private logger: any) { this.rateLimiter = new RateLimiter(config.rateLimiting); }
async registerAll() { const providers = [ new FileOperationTools(this.config.filesystem), new ProjectManagementTools(this.config.project), new CommunicationTools(this.config.communication), new DevelopmentTools(this.config.development) ];
for (const provider of providers) {
  await this.registerToolProvider(provider);
}
}
async executeTool(name: string, args: any): Promise<ToolResult> { // Limitação de taxa if (!this.rateLimiter.allow(name)) { throw new Error(`Limite de taxa excedido para ferramenta: ${name}`); }
// Encontrar ferramenta
const tool = this.tools.get(name);
if (!tool) {
  throw new Error(\`Ferramenta não encontrada: \${name}\`);
}
// Validar argumentos
const validation = this.validateArguments(tool, args);
if (!validation.valid) {
  throw new Error(\`Argumentos inválidos: \${validation.errors.join(', ')}\`);
}
// Executar com monitoramento
const startTime = Date.now();
try {
  const result = await tool.execute(args);
  
  // Registrar execução
  this.logExecution({
    tool: name,
    success: !result.isError,
    duration: Date.now() - startTime,
    timestamp: new Date()
  });
  
  return result;
} catch (error) {
  this.logExecution({
    tool: name,
    success: false,
    duration: Date.now() - startTime,
    error: error.message,
    timestamp: new Date()
  });
  throw error;
}
}
getAllTools(): ToolDefinition[] { return Array.from(this.tools.values()).map(tool => ({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema })); }
getExecutionStats(): ExecutionStats { const recent = this.executionLog.filter( log => Date.now() - log.timestamp.getTime() < 24 * 60 * 60 * 1000 );
return {
  totalExecutions: recent.length,
  successRate: recent.filter(log => log.success).length / recent.length,
  averageDuration: recent.reduce((sum, log) => sum + log.duration, 0) / recent.length,
  topTools: this.getTopTools(recent)
};
} }`} />
<CodeExample title="Conjunto de Ferramentas de Desenvolvimento" language="typescript" code={`// src/tools/development.ts export class DevelopmentTools implements ToolProvider { getName() { return 'development'; }
getTools(): ToolDefinition[] { return [ { name: 'git_commit', description: 'Criar um commit git com mudanças preparadas', inputSchema: { type: 'object', properties: { message: { type: 'string', description: 'Mensagem de commit' }, addAll: { type: 'boolean', default: false, description: 'Adicionar todas as mudanças antes de commitar' } }, required: ['message'] } }, { name: 'npm_install', description: 'Instalar pacotes npm', inputSchema: { type: 'object', properties: { packages: { type: 'array', items: { type: 'string' }, description: 'Nomes dos pacotes para instalar' }, dev: { type: 'boolean', default: false, description: 'Instalar como dependências de desenvolvimento' }, global: { type: 'boolean', default: false, description: 'Instalar globalmente' } }, required: ['packages'] } }, { name: 'run_tests', description: 'Executar testes do projeto', inputSchema: { type: 'object', properties: { pattern: { type: 'string', description: 'Padrão de arquivo de teste' }, watch: { type: 'boolean', default: false, description: 'Executar em modo watch' }, coverage: { type: 'boolean', default: false, description: 'Gerar relatório de cobertura' } } } }, { name: 'build_project', description: 'Construir o projeto', inputSchema: { type: 'object', properties: { mode: { type: 'string', enum: ['development', 'production'], default: 'development', description: 'Modo de build' }, clean: { type: 'boolean', default: false, description: 'Limpar antes do build' } } } } ]; }
async executeTool(name: string, args: any): Promise<ToolResult> { switch (name) { case 'git_commit': return this.gitCommit(args); case 'npm_install': return this.npmInstall(args); case 'run_tests': return this.runTests(args); case 'build_project': return this.buildProject(args); default: throw new Error(`Ferramenta de desenvolvimento desconhecida: ${name}`); } }
private async gitCommit(args: any): Promise<ToolResult> { try { const commands = [];
  if (args.addAll) {
    commands.push('git add .');
  }
  
  commands.push(\`git commit -m "\${args.message}"\`);
  
  const results = [];
  for (const command of commands) {
    const result = await execAsync(command, { cwd: this.config.repositoryPath });
    results.push(result.stdout);
  }
  
  return {
    content: [
      {
        type: 'text',
        text: \`Commit git bem-sucedido:\\n\${results.join('\\n')}\`
      }
    ]
  };
} catch (error) {
  return {
    content: [
      {
        type: 'text',
        text: \`Commit git falhou: \${error.message}\`
      }
    ],
    isError: true
  };
}
}
private async npmInstall(args: any): Promise<ToolResult> { try { const flags = []; if (args.dev) flags.push('--save-dev'); if (args.global) flags.push('--global');
  const command = \`npm install \${args.packages.join(' ')} \${flags.join(' ')}\`;
  const result = await execAsync(command, { 
    cwd: this.config.projectPath,
    timeout: 300000 // 5 minutos
  });
  
  return {
    content: [
      {
        type: 'text',
        text: \`Pacotes instalados com sucesso:\\n\${result.stdout}\`
      }
    ]
  };
} catch (error) {
  return {
    content: [
      {
        type: 'text',
        text: \`npm install falhou: \${error.message}\`
      }
    ],
    isError: true
  };
}
} }`} />
<CodeExample title="Ferramentas de Comunicação" language="typescript" code={`// src/tools/communication.ts export class CommunicationTools implements ToolProvider { getName() { return 'communication'; }
getTools(): ToolDefinition[] { const tools = [ { name: 'send_email', description: 'Enviar uma notificação por e-mail', inputSchema: { type: 'object', properties: { to: { type: 'string', description: 'Endereço de e-mail do destinatário' }, subject: { type: 'string', description: 'Assunto do e-mail' }, body: { type: 'string', description: 'Conteúdo do corpo do e-mail' }, priority: { type: 'string', enum: ['low', 'normal', 'high'], default: 'normal', description: 'Prioridade do e-mail' } }, required: ['to', 'subject', 'body'] } } ];
// Adicionar ferramentas Slack se token estiver configurado
if (this.config.slackToken) {
  tools.push({
    name: 'slack_message',
    description: 'Enviar mensagem para canal Slack',
    inputSchema: {
      type: 'object',
      properties: {
        channel: { type: 'string', description: 'Nome ou ID do canal Slack' },
        message: { type: 'string', description: 'Texto da mensagem' },
        urgent: { type: 'boolean', default: false, description: 'Marcar como urgente' },
        threadId: { type: 'string', description: 'Responder a thread (opcional)' }
      },
      required: ['channel', 'message']
    }
  });
}
return tools;
}
async executeTool(name: string, args: any): Promise<ToolResult> { switch (name) { case 'send_email': return this.sendEmail(args); case 'slack_message': return this.sendSlackMessage(args); default: throw new Error(`Ferramenta de comunicação desconhecida: ${name}`); } }
private async sendSlackMessage(args: any): Promise<ToolResult> { try { const response = await fetch('https://slack.com/api/chat.postMessage', { method: 'POST', headers: { 'Authorization': `Bearer ${this.config.slackToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ channel: args.channel, text: args.message, thread_ts: args.threadId, ...(args.urgent && { attachments: [{ color: 'danger', text: '🚨 MENSAGEM URGENTE 🚨' }] }) }) });
  const result = await response.json();
  
  if (!result.ok) {
    throw new Error(result.error || 'Erro da API Slack');
  }
  
  return {
    content: [
      {
        type: 'text',
        text: \`Mensagem enviada para \${args.channel} com sucesso\`
      }
    ]
  };
} catch (error) {
  return {
    content: [
      {
        type: 'text',
        text: \`Falha ao enviar mensagem Slack: \${error.message}\`
      }
    ],
    isError: true
  };
}
} }`} />
Gerenciamento e execução centralizados de ferramentas
Um servidor de produção requer testes abrangentes e processos adequados de implantação.
<CodeExample title="Conjunto Abrangente de Testes" language="typescript" code={`// tests/integration/server.test.ts
describe('Integração do Servidor MCP Workspace', () => { let server: MCPWorkspaceServer; let transport: TestTransport;
beforeEach(async () => { // Configurar ambiente de teste process.env.NODE_ENV = 'test';
server = new MCPWorkspaceServer();
transport = new TestTransport();
await server.start(transport);
});
afterEach(async () => { await server.shutdown(); });
describe('Recursos', () => { test('deve listar todos os recursos disponíveis', async () => { const response = await transport.request('resources/list', {});
  expect(response.resources).toBeDefined();
  expect(Array.isArray(response.resources)).toBe(true);
  expect(response.resources.length).toBeGreaterThan(0);
});
test('deve ler recursos do sistema de arquivos', async () => {
  const response = await transport.request('resources/read', {
    uri: 'file://test-file.txt'
  });
  
  expect(response.contents).toBeDefined();
  expect(response.contents[0].text).toContain('conteúdo de teste');
});
test('deve lidar com URIs de recurso inválidos', async () => {
  await expect(
    transport.request('resources/read', { uri: 'invalid://uri' })
  ).rejects.toThrow('Nenhum provedor encontrado');
});
});
describe('Ferramentas', () => { test('deve listar todas as ferramentas disponíveis', async () => { const response = await transport.request('tools/list', {});
  expect(response.tools).toBeDefined();
  expect(Array.isArray(response.tools)).toBe(true);
  
  // Verificar ferramentas esperadas
  const toolNames = response.tools.map(t => t.name);
  expect(toolNames).toContain('read_file');
  expect(toolNames).toContain('write_file');
});
test('deve executar operações de arquivo', async () => {
  const response = await transport.request('tools/call', {
    name: 'write_file',
    arguments: {
      path: 'test-output.txt',
      content: 'Olá, MCP!'
    }
  });
  
  expect(response.isError).toBeFalsy();
  expect(response.content[0].text).toContain('Escrito com sucesso');
});
test('deve validar parâmetros de ferramentas', async () => {
  await expect(
    transport.request('tools/call', {
      name: 'write_file',
      arguments: {
        // Faltando parâmetro obrigatório 'content'
        path: 'test.txt'
      }
    })
  ).rejects.toThrow('Argumentos inválidos');
});
});
describe('Saúde e Monitoramento', () => { test('deve fornecer status de saúde', async () => { const response = await transport.request('health', {});
  expect(response.status).toBe('healthy');
  expect(response.providers).toBeGreaterThan(0);
  expect(response.tools).toBeGreaterThan(0);
});
}); });`} />
<CodeExample title="Configuração de Implantação de Produção" language="dockerfile" code={`# Dockerfile FROM node:18-alpine
RUN apk add --no-cache git
WORKDIR /app
COPY package*.json ./ COPY tsconfig.json ./
RUN npm ci --only=production
COPY src/ ./src/ COPY config/ ./config/
RUN npm run build
RUN addgroup -g 1001 -S nodejs RUN adduser -S mcp -u 1001
RUN mkdir -p /workspace && chown mcp:nodejs /workspace
USER mcp
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD node dist/health-check.js
CMD ["npm", "start"]`} />
<CodeExample title="Workflow GitHub Actions" language="yaml" code={`# .github/workflows/ci.yml name: Pipeline CI/CD
on: push: branches: [ main, develop ] pull_request: branches: [ main ]
jobs: test: runs-on: ubuntu-latest
strategy:
  matrix:
    node-version: [18.x, 20.x]
steps:
- uses: actions/checkout@v3
- name: Usar Node.js ${{ matrix.node-version }}
  uses: actions/setup-node@v3
  with:
    node-version: ${{ matrix.node-version }}
    cache: 'npm'
- name: Instalar dependências
  run: npm ci
- name: Executar linting
  run: npm run lint
- name: Executar verificação de tipos
  run: npm run type-check
- name: Executar testes
  run: npm run test:coverage
- name: Upload relatórios de cobertura
  uses: codecov/codecov-action@v3
  with:
    file: ./coverage/lcov.info
build: needs: test runs-on: ubuntu-latest if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- name: Construir imagem Docker
  run: docker build -t mcp-workspace-server .
- name: Executar scan de segurança
  run: docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image mcp-workspace-server
deploy: needs: [test, build] runs-on: ubuntu-latest if: github.ref == 'refs/heads/main'
steps:
- name: Implantar em produção
  run: echo "Implantar no ambiente de produção"`}
/>
Testes unitários e de integração para servidor MCP
Docker e configuração de implantação