npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

servemcp

v0.1.0

Published

Biblioteca leve e rápida para criar e implantar servidores MCP (Model Context Protocol) em TypeScript.

Readme

servemcp

Biblioteca leve e rápida para criar e implantar servidores MCP (Model Context Protocol) em TypeScript. É uma camada fina sobre o SDK oficial (@modelcontextprotocol/sdk) que remove boilerplate comum — registrar tools/resources/prompts, tratar erros e subir um transporte — sem esconder o SDK: o servidor bruto continua acessível via .raw para qualquer coisa avançada.

Por que

  • Leve: zero dependências além do SDK oficial e do zod; o transporte HTTP usa node:http puro, sem Express.
  • Rápida: build ESM único via tsup, sem camadas extras em runtime.
  • Segura por padrão: erros lançados dentro de uma tool viram um isError result em vez de derrubar a conexão; logs sempre vão para stderr (nunca poluem o stdout, que no transporte stdio é reservado para mensagens JSON-RPC); o HTTP escuta em 127.0.0.1 por padrão.
  • stdio e HTTP prontos: serveStdio() para servidores lançados por CLI (Claude Desktop, Claude Code, etc.) e serveHttp() para servir Streamable HTTP com sessões multiusuário isoladas corretamente.

Instalação

npm install servemcp zod

Uso rápido

import { createServer, z } from "servemcp";

const server = createServer({ name: "weather-server", version: "1.0.0" });

server.tool(
  "get_weather",
  {
    description: "Retorna a previsão do tempo para uma cidade.",
    input: { city: z.string().describe("Nome da cidade") },
  },
  async ({ city }) => ({
    content: [{ type: "text", text: `Ensolarado em ${city}, 24°C.` }],
  }),
);

await server.serveStdio();

Isso já é um servidor MCP completo, pronto para ser referenciado no claude_desktop_config.json (ou equivalente) apontando para este script.

Registrando tools, resources e prompts

Tools

import { toolError } from "servemcp";

server.tool(
  "divide",
  { description: "Divide a por b.", input: { a: z.number(), b: z.number() } },
  async ({ a, b }) => {
    if (b === 0) return toolError("Divisão por zero não é permitida.");
    return { content: [{ type: "text", text: String(a / b) }] };
  },
);

Exceções não tratadas dentro do handler são capturadas automaticamente e retornadas como isError: true — o modelo vê a falha e pode reagir, em vez da conexão simplesmente cair.

Use os helpers text(...) e json(value) para montar resultados comuns:

import { text, json } from "servemcp";

server.tool("ping", {}, async () => text("pong"));
server.tool("status", {}, async () => json({ ok: true, uptime: process.uptime() }));

Resources

server.resource(
  "config",
  "config://app",
  { title: "Configuração da app", mimeType: "application/json" },
  () => ({ text: JSON.stringify({ debug: false }) }),
);

Prompts

server.prompt(
  "resumir",
  { description: "Gera um prompt para resumir um texto.", args: { texto: z.string() } },
  ({ texto }) => ({
    messages: [
      { role: "user", content: { type: "text", text: `Resuma o texto a seguir:\n\n${texto}` } },
    ],
  }),
);

server.tool(), server.resource() e server.prompt() retornam a própria instância (this), então dá para encadear:

createServer({ name: "x", version: "1.0.0" })
  .tool("a", { input: {} }, async () => text("a"))
  .tool("b", { input: {} }, async () => text("b"))
  .serveStdio();

Transportes

stdio (padrão para clientes desktop/CLI)

await server.serveStdio();

Conecta em stdin/stdout e trata SIGINT/SIGTERM para fechar a conexão de forma limpa.

HTTP (Streamable HTTP)

const handle = await server.serveHttp({ port: 3000, cors: true });
console.error(`ouvindo em ${handle.url}`);
// depois, para desligar:
await handle.close();

Opções de serveHttp:

| Opção | Padrão | Descrição | |---|---|---| | port | 3000 (ou process.env.PORT) | Porta TCP | | host | 127.0.0.1 | Interface de rede. Use 0.0.0.0 só com allowedHosts configurado | | path | /mcp | Caminho do endpoint | | mode | "stateful" | "stateful" mantém sessão por cliente (Mcp-Session-Id) com stream SSE via GET; "stateless" cria uma sessão nova a cada POST | | cors | false | Responde CORS permissivo para clientes de navegador | | allowedHosts | — | Lista de Host permitidos (proteção contra DNS rebinding ao expor além de localhost) |

Internamente, cada sessão HTTP recebe sua própria instância do servidor MCP subjacente (o SDK permite apenas um transporte ativo por instância) — isso é feito automaticamente reaplicando os registros de tools/resources/prompts, então múltiplos clientes concorrentes nunca interferem uns nos outros.

Escape hatch

Qualquer recurso do SDK que não tenha um atalho aqui continua acessível via server.raw, que é a instância padrão de McpServer:

server.raw.sendLoggingMessage({ level: "info", data: "oi" });

Exemplos

Veja examples/stdio-server.js e examples/http-server.js. Rode com:

npm run build
npm run example:stdio   # sobe um servidor via stdio (aguarda um cliente MCP)
npm run example:http    # sobe um servidor HTTP em http://127.0.0.1:3000/mcp

Desenvolvimento

npm run typecheck
npm run build