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

@mcpeak/core

v0.6.2

Published

MCP protocol client, transports, and process lifecycle for MCPeak

Readme

English · 한국어

@mcpeak/core

@mcpeak/core attaches to an MCP server, completes the handshake, and then provides a frozen McpClient. There are two transports. A local server is attached by starting its process over stdio, and a remote server is attached at a URL over Streamable HTTP. On the stdio path, Core owns the server process, stdin/stdout, bounded stderr, and the shutdown lifecycle.

Public API

For simple use, connect gives you just the frozen client.

import { connect } from "@mcpeak/core";

const client = await connect({
  command: process.execPath,
  args: ["./server.mjs"],
  env: { MCP_MODE: "test" },
  cwd: process.cwd(),
  connectTimeoutMs: 10_000,
  maxMessageBytes: 10 * 1024 * 1024,
  maxStderrBytes: 64 * 1024,
});

try {
  const tools = await client.listTools();
  const result = await client.callTool("get_weather", { city: "Seoul" });
  console.log(tools, result);
} finally {
  await client.close();
}

When the CLI or another composition root needs to distinguish a graceful shutdown from an immediate forced shutdown, use connectStdio.

import { connectStdio } from "@mcpeak/core";

const connection = await connectStdio({
  command: "node",
  args: ["./server.mjs"],
  env: { MCP_MODE: "test" },
  cwd: process.cwd(),
});

try {
  await connection.client.listTools();
} finally {
  await connection.close();
  // pending MCP 요청과 무관하게 종료해야 할 때:
  // await connection.forceClose();
}

console.log(connection.getDiagnostics());

connect returns the connection.client of connectStdio(options). ConnectOptions takes command, args, an explicit env, cwd, the handshake time limit, the maximum stdout message size, and the maximum stderr size. The defaults are 10 seconds, 10 MiB, and 64 KiB respectively. Values must be finite integers, and anything outside the allowed range fails before the child process is started.

Environment variables do not inherit the whole of process.env. The parent environment can contain secrets such as auth tokens, and values that change from run to run can break test determinism. Only the safe default environment variables allowed by the SDK are passed, and additional values are passed to the child process only when specified in env.

stderr is treated as untrusted child process input. Only the most recent bytes are kept in a bounded buffer, with a default cap of 64 KiB. stderr content may be included in diagnostic snapshots but is not included in the default error message or McpClientError.toJSON(). The error JSON contains only the code, phase, fixed message and hint, exit code, signal, and whether stderr was truncated.

Execution does not go through a shell, so even if args contains spaces or shell characters, they are not reinterpreted. On Windows, .cmd and .bat commands are rejected. Give an executable the operating system can run directly as command, and pass the script path and script arguments in args. Windows command wrapping and command-line quoting are outside the scope of this transport.

SSE, WebSocket, and OAuth-based remote authentication will be decided separately in a follow-up design and ADR.

Connecting over Streamable HTTP

For an MCP server reachable only by URL, give url instead of command. The same connect picks the transport by the shape of the options.

import { connect } from "@mcpeak/core";

const token = process.env.MCP_TOKEN;
if (!token) throw new Error("MCP_TOKEN is required");

const client = await connect({
  url: "https://mcp.example.com/mcp",
  headers: { Authorization: `Bearer ${token}` },
  connectTimeoutMs: 10_000,
});

try {
  const tools = await client.listTools();
  console.log(tools);
} finally {
  await client.close();
}

HttpConnectOptions takes only url, optional headers, and optional connectTimeoutMs. With no process there is no forceClose, and close() cuts pending requests with an internal abort. Failure diagnostics are tagged transport: "http" and carry url, status, statusText, and sessionId. Header values never appear in diagnostics or error JSON.

OAuth and reconnection are not supported. Authentication is attached only through headers you build yourself, a 401 ends as HTTP_UNAUTHORIZED, and a dropped connection fails immediately without retrying (for the detailed reasoning, see ADR-0020).

Core does not import Runner. Runner receives an injected McpClient, and the CLI is the composition root that assembles connectStdio's client, close, and forceClose into Runner's shutdown boundary.

Scope and stability

McpClient, ToolDef, and ToolResult in src/types.ts are a frozen contract between packages. Only the optional ToolDef.outputSchema agreed in #406 carries the output contract of tools/list without loss, and the existing shape of McpClient and ToolResult is not changed. Core uses @modelcontextprotocol/sdk 1.x and does not upgrade the SDK version.

Owners: @seodduu @endl24 @sunghoon0303 (MCP server testing part)