{"_id":"@7leirbag/my-first-mcp","_rev":"3-ad3c6f26dbca85e6d598ebaca720937b","name":"@7leirbag/my-first-mcp","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"@7leirbag/my-first-mcp","version":"1.0.0","_id":"@7leirbag/my-first-mcp@1.0.0","maintainers":[{"name":"7leirbag","email":"gabriel.dsn.pack@gmail.com"}],"bin":{"my-first-mcp":"dist/index.js"},"dist":{"shasum":"d9e2faa281ed8ed08d8864fc4fe6c5f2827c7900","tarball":"https://registry.npmjs.org/@7leirbag/my-first-mcp/-/my-first-mcp-1.0.0.tgz","fileCount":6,"integrity":"sha512-40tPWCj6VhgJY9gTV0P2KaujAHzDmPJ0FBqLvh3pU7ePCn/IofPfYyHkBEE9Tlk6DB2jU46pnLShML7Ywh4gIA==","signatures":[{"sig":"MEYCIQDzuaQX71/t8G/MtiBuJY6rEtu0y7InS1QsU8DcDuEs/wIhANMvRxJN8SV9eLSWL81ggKZOeQUSsmTEauYX6YyVtuju","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":5364},"main":"dist/index.js","type":"module","engines":{"node":">=18"},"scripts":{"test":"vitest --run","build":"tsc && node scripts/add-shebang.cjs","start":"node dist/index.js"},"_npmUser":{"name":"7leirbag","email":"gabriel.dsn.pack@gmail.com"},"_npmVersion":"11.6.2","description":"Servidor MCP educacional com tools de data/hora","directories":{},"_nodeVersion":"24.13.0","dependencies":{"@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.0.0","fast-check":"^3.0.0","typescript":"^5.0.0","@types/node":"^20.0.0"},"_npmOperationalInternal":{"tmp":"tmp/my-first-mcp_1.0.0_1773591907112_0.8609183848817843","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@7leirbag/my-first-mcp","version":"1.0.1","_id":"@7leirbag/my-first-mcp@1.0.1","maintainers":[{"name":"7leirbag","email":"gabriel.dsn.pack@gmail.com"}],"bin":{"my-first-mcp":"dist/index.js"},"dist":{"shasum":"5e2e15358a1b1c98fb71fa73c8f7496d4791ebb9","tarball":"https://registry.npmjs.org/@7leirbag/my-first-mcp/-/my-first-mcp-1.0.1.tgz","fileCount":7,"integrity":"sha512-4byEk/3vPYzH7vsYEVTjnWNW5XIzI8U88wSEiIJe8eMPUArYCAunb4XPQEwGHufiHAXI5o+5IEm/DOvfjzctaA==","signatures":[{"sig":"MEUCIEr2oVnogSMkB/AeEGWiynSvmAq9bWmuzMtyKXlMnVRxAiEA1gYATaMphQZyaRW/JdaU5le6Bo+s/QfTAEaVuqs4jmA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":15081},"main":"dist/index.js","type":"module","engines":{"node":">=18"},"gitHead":"98420b245e034a86afd0d0c5827c0ee1d2789f73","scripts":{"test":"vitest --run","build":"tsc && node scripts/add-shebang.cjs","start":"node dist/index.js"},"_npmUser":{"name":"7leirbag","email":"gabriel.dsn.pack@gmail.com"},"_npmVersion":"11.6.2","description":"Servidor MCP educacional com tools de data/hora","directories":{},"_nodeVersion":"24.13.0","dependencies":{"@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.0.0","fast-check":"^3.0.0","typescript":"^5.0.0","@types/node":"^20.0.0"},"_npmOperationalInternal":{"tmp":"tmp/my-first-mcp_1.0.1_1773606435793_0.8116612278554787","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@7leirbag/my-first-mcp","version":"1.0.2","description":"Servidor MCP educacional com tools de data/hora","type":"module","main":"dist/index.js","bin":{"my-first-mcp":"dist/index.js"},"scripts":{"build":"tsc && node scripts/add-shebang.cjs","start":"node dist/index.js","test":"vitest --run"},"dependencies":{"@modelcontextprotocol/sdk":"^1.0.0"},"devDependencies":{"typescript":"^5.0.0","vitest":"^1.0.0","fast-check":"^3.0.0","@types/node":"^20.0.0"},"engines":{"node":">=18"},"gitHead":"a70e5c0b002f23a3d43910358d1fdefb3b6058a6","_id":"@7leirbag/my-first-mcp@1.0.2","_nodeVersion":"24.13.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-nb6pI8tc4P1vS3hXZL3bygu+9HWRBH4HJugtHXnHIi7mhpCTW0hixOyYF6fxHNFrC8l7nhx0p+IjhuIbn3HqZA==","shasum":"db638fef297ce116ec065ad2505303981836d578","tarball":"https://registry.npmjs.org/@7leirbag/my-first-mcp/-/my-first-mcp-1.0.2.tgz","fileCount":7,"unpackedSize":15182,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCnECTt+1XKWpbn23MToQ5JdZ4uK/xTJJf7srFmNPFIFgIgJriz344q43IsxK5hKNH3WJ9mYvpw/WYmIbRxooHkGoQ="}]},"_npmUser":{"name":"7leirbag","email":"gabriel.dsn.pack@gmail.com"},"directories":{},"maintainers":[{"name":"7leirbag","email":"gabriel.dsn.pack@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/my-first-mcp_1.0.2_1773606737121_0.4110002442480396"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-15T16:25:07.002Z","modified":"2026-03-15T20:32:17.375Z","1.0.0":"2026-03-15T16:25:07.253Z","1.0.1":"2026-03-15T20:27:15.937Z","1.0.2":"2026-03-15T20:32:17.277Z"},"description":"Servidor MCP educacional com tools de data/hora","maintainers":[{"name":"7leirbag","email":"gabriel.dsn.pack@gmail.com"}],"readme":"# @7leirbag/my-first-mcp\r\n\r\nServidor MCP (Model Context Protocol) educacional escrito em TypeScript. O objetivo deste projeto é demonstrar o ciclo completo de desenvolvimento de um MCP server: implementação local → build → publicação no npm → consumo via `npx` em qualquer cliente compatível (Kiro, Claude Desktop, etc.).\r\n\r\n---\r\n\r\n## Por que TypeScript?\r\n\r\nJavaScript puro funcionaria, mas TypeScript foi escolhido por razões práticas:\r\n\r\n- **Tipagem estática**: as interfaces do SDK MCP (`McpServer`, `StdioServerTransport`, `CallToolResult`) são complexas. Com tipos, o editor aponta erros antes de rodar qualquer coisa.\r\n- **Autocompletar**: ao implementar cada tool, o TypeScript garante que a resposta retornada tem exatamente a forma que o SDK espera — `{ content: [{ type: \"text\", text: string }] }`.\r\n- **Documentação viva**: as interfaces em `src/types.ts` servem como contrato entre as tools e o entry point. Qualquer desvio vira erro de compilação, não bug em produção.\r\n- **Ecossistema**: o SDK oficial `@modelcontextprotocol/sdk` é escrito em TypeScript e exporta seus tipos, então aproveitamos isso ao máximo.\r\n\r\nO custo é um passo extra de compilação (`tsc`), mas o ganho em clareza e segurança compensa — especialmente num projeto educacional onde entender as interfaces é o objetivo.\r\n\r\n---\r\n\r\n## Como o MCP funciona\r\n\r\nO Model Context Protocol define um padrão de comunicação entre um **cliente** (ex: Kiro, Claude Desktop) e um **servidor** que expõe ferramentas (tools). A comunicação acontece via **JSON-RPC 2.0**.\r\n\r\nO transporte usado aqui é **stdio**: o cliente inicia o processo do servidor e troca mensagens pelo stdin/stdout. Não há porta de rede, não há servidor HTTP — tudo é local e efêmero.\r\n\r\n```\r\nCliente MCP (Kiro)\r\n    │\r\n    │  stdin  →  JSON-RPC request\r\n    ▼\r\nProcesso Node.js (@7leirbag/my-first-mcp)\r\n    │\r\n    │  stdout →  JSON-RPC response\r\n    ▼\r\nCliente MCP (Kiro)\r\n```\r\n\r\nQuando o cliente fecha a conexão (fecha o stdin), o processo do servidor encerra automaticamente.\r\n\r\n---\r\n\r\n## Estrutura do projeto\r\n\r\n```\r\nmy-first-mcp/\r\n├── src/\r\n│   ├── index.ts              # Entry point: instancia o servidor e registra as tools\r\n│   ├── types.ts              # Interfaces compartilhadas entre as tools\r\n│   └── tools/\r\n│       ├── datetime.ts       # Tool: get_current_datetime\r\n│       ├── server-info.ts    # Tool: get_server_info\r\n│       └── date-diff.ts      # Tool: calculate_date_diff\r\n├── dist/                     # Saída do compilador TypeScript (gerado pelo build)\r\n├── scripts/\r\n│   └── add-shebang.cjs       # Script pós-build: injeta #!/usr/bin/env node\r\n├── package.json\r\n└── tsconfig.json\r\n```\r\n\r\n---\r\n\r\n## Passo a passo: o que foi feito para o MCP funcionar\r\n\r\n### 1. Configurar o projeto\r\n\r\n**`package.json`** com os campos essenciais para publicação e execução:\r\n\r\n```json\r\n{\r\n  \"name\": \"@7leirbag/my-first-mcp\",\r\n  \"type\": \"module\",\r\n  \"main\": \"dist/index.js\",\r\n  \"bin\": { \"my-first-mcp\": \"dist/index.js\" },\r\n  \"files\": [\"dist\"],\r\n  \"engines\": { \"node\": \">=18\" }\r\n}\r\n```\r\n\r\n- `\"type\": \"module\"` — habilita ES Modules, necessário para `top-level await` no entry point\r\n- `\"bin\"` — diz ao npm qual arquivo executar quando o pacote for chamado via `npx`\r\n- `\"files\"` — garante que apenas a pasta `dist/` (código compilado) seja publicada no registry\r\n\r\n**`tsconfig.json`** com configurações para Node.js moderno:\r\n\r\n```json\r\n{\r\n  \"compilerOptions\": {\r\n    \"target\": \"ES2022\",\r\n    \"module\": \"Node16\",\r\n    \"moduleResolution\": \"Node16\",\r\n    \"outDir\": \"dist\",\r\n    \"strict\": true\r\n  }\r\n}\r\n```\r\n\r\n- `module: Node16` — usa a resolução de módulos do Node.js, exigindo extensão `.js` nos imports\r\n- `target: ES2022` — permite `top-level await` e outras features modernas\r\n\r\n### 2. Implementar as tools\r\n\r\nCada tool é uma função pura em `src/tools/` que recebe parâmetros e retorna um `ToolResponse`:\r\n\r\n```typescript\r\ninterface ToolResponse {\r\n  content: Array<{ type: \"text\"; text: string }>;\r\n  isError?: boolean;\r\n}\r\n```\r\n\r\nEsse é o contrato do SDK MCP: toda tool deve retornar um objeto com `content` contendo um array de blocos de texto. Se algo der errado, `isError: true` sinaliza o erro para o cliente.\r\n\r\n**`get_current_datetime`** — usa `Intl.DateTimeFormat` para validar o timezone IANA e formatar a data sem offset:\r\n\r\n```typescript\r\nexport function getCurrentDatetime(params: { timezone?: string }): ToolResponse\r\n```\r\n\r\n**`get_server_info`** — captura `startedAt` no momento do boot do módulo (variável de nível de módulo) e retorna metadados do servidor:\r\n\r\n```typescript\r\nconst startedAt = new Date().toISOString(); // capturado uma vez, no boot\r\n\r\nexport function getServerInfo(): ToolResponse\r\n```\r\n\r\n**`calculate_date_diff`** — valida ambas as datas com regex + `new Date()`, calcula a diferença absoluta em minutos e decompõe em dias, horas e minutos:\r\n\r\n```typescript\r\nexport function calculateDateDiff(params: { date1: string; date2: string }): ToolResponse\r\n```\r\n\r\n### 3. Registrar as tools no servidor MCP\r\n\r\nEm `src/index.ts`, o `McpServer` do SDK oficial é instanciado e cada tool é registrada com seu schema Zod:\r\n\r\n```typescript\r\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\r\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\r\nimport { z } from \"zod\";\r\n\r\nconst server = new McpServer({ name: \"my-first-mcp\", version: \"1.0.0\" });\r\n\r\nserver.tool(\"get_current_datetime\", \"Descrição...\", {\r\n  timezone: z.string().optional().describe(\"Fuso horário IANA. Padrão: UTC\"),\r\n}, (params) => getCurrentDatetime(params));\r\n\r\n// ... demais tools\r\n\r\nconst transport = new StdioServerTransport();\r\nawait server.connect(transport); // conecta via stdin/stdout\r\n\r\nprocess.stdin.on(\"close\", () => process.exit(0)); // encerra quando o cliente desconecta\r\n```\r\n\r\nO schema Zod serve dois propósitos: validação dos parâmetros recebidos e geração automática do JSON Schema que o cliente usa para saber como chamar a tool.\r\n\r\n### 4. Adicionar o shebang no arquivo compilado\r\n\r\nO TypeScript não preserva o `#!/usr/bin/env node` no arquivo compilado. Sem ele, o sistema operacional não sabe que deve usar o Node.js para executar o arquivo diretamente.\r\n\r\nO script `scripts/add-shebang.cjs` resolve isso após o `tsc`:\r\n\r\n```javascript\r\nconst fs = require(\"fs\");\r\nconst file = \"dist/index.js\";\r\nconst content = fs.readFileSync(file, \"utf8\");\r\nif (!content.startsWith(\"#!/usr/bin/env node\")) {\r\n  fs.writeFileSync(file, \"#!/usr/bin/env node\\n\" + content);\r\n}\r\nfs.chmodSync(file, \"755\"); // permissão de execução\r\n```\r\n\r\nO script usa extensão `.cjs` porque o `package.json` tem `\"type\": \"module\"` — sem isso, o Node tentaria interpretá-lo como ESM e o `require()` falharia.\r\n\r\nO build completo fica:\r\n\r\n```bash\r\nnpm run build\r\n# equivale a: tsc && node scripts/add-shebang.cjs\r\n```\r\n\r\n### 5. Publicar no npm\r\n\r\n```bash\r\n# Autenticar com um Granular Access Token (com bypass 2FA habilitado)\r\nnpm config set //registry.npmjs.org/:_authToken SEU_TOKEN\r\n\r\n# Publicar\r\nnpm publish --access public\r\n```\r\n\r\nO campo `\"files\": [\"dist\"]` no `package.json` garante que apenas o código compilado vai para o registry — sem `src/`, sem `node_modules/`, sem arquivos de configuração desnecessários.\r\n\r\n### 6. Configurar no cliente MCP (Kiro)\r\n\r\nEm `~/.kiro/settings/mcp.json`:\r\n\r\n```json\r\n{\r\n  \"mcpServers\": {\r\n    \"my-first-mcp\": {\r\n      \"command\": \"npx\",\r\n      \"args\": [\"-y\", \"@7leirbag/my-first-mcp\"]\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nO Kiro lê essa configuração, executa `npx -y @7leirbag/my-first-mcp` (que baixa e inicia o pacote automaticamente), e se comunica com o processo via stdin/stdout. A flag `-y` evita a confirmação interativa do npx.\r\n\r\n---\r\n\r\n## Tools disponíveis\r\n\r\n### `get_current_datetime`\r\n\r\nRetorna a data e hora atual no formato ISO 8601.\r\n\r\n| Parâmetro  | Tipo   | Obrigatório | Padrão | Descrição                          |\r\n|------------|--------|-------------|--------|------------------------------------|\r\n| `timezone` | string | não         | `UTC`  | Identificador IANA do fuso horário |\r\n\r\n```json\r\n// Resposta\r\n{ \"datetime\": \"2026-03-15T16:29:31\", \"timezone\": \"UTC\" }\r\n```\r\n\r\n### `get_server_info`\r\n\r\nRetorna metadados do servidor. Sem parâmetros.\r\n\r\n```json\r\n// Resposta\r\n{\r\n  \"name\": \"@7leirbag/my-first-mcp\",\r\n  \"version\": \"1.0.0\",\r\n  \"status\": \"running\",\r\n  \"startedAt\": \"2026-03-15T16:27:29.185Z\",\r\n  \"tools\": [\"get_current_datetime\", \"get_server_info\", \"calculate_date_diff\"]\r\n}\r\n```\r\n\r\n### `calculate_date_diff`\r\n\r\nCalcula a diferença absoluta entre duas datas.\r\n\r\n| Parâmetro | Tipo   | Obrigatório | Descrição                          |\r\n|-----------|--------|-------------|------------------------------------|\r\n| `date1`   | string | sim         | Data no formato ISO 8601 ou YYYY-MM-DD |\r\n| `date2`   | string | sim         | Data no formato ISO 8601 ou YYYY-MM-DD |\r\n\r\n```json\r\n// Resposta\r\n{ \"days\": 73, \"hours\": 0, \"minutes\": 0, \"totalMinutes\": 105120 }\r\n```\r\n\r\n---\r\n\r\n## Desenvolvimento local\r\n\r\n```bash\r\n# Instalar dependências\r\nnpm install\r\n\r\n# Compilar\r\nnpm run build\r\n\r\n# Rodar testes\r\nnpm test\r\n```\r\n\r\nPara usar a versão local no Kiro sem publicar no npm, aponte o `mcp.json` para o arquivo compilado diretamente:\r\n\r\n```json\r\n{\r\n  \"mcpServers\": {\r\n    \"my-first-mcp-local\": {\r\n      \"command\": \"node\",\r\n      \"args\": [\"C:/caminho/para/o/projeto/dist/index.js\"]\r\n    }\r\n  }\r\n}\r\n```\r\n\"# my-first-mcp\" \r\n","readmeFilename":"README.md"}