@earendil-works/pi-mcp weekly downloads statistics
By earendil-works · npm · MCP servers
Standalone Model Context Protocol client for pi and other applications
@earendil-works/pi-mcp has 1,380,341 recorded weekly downloads on npm, a change of -14.9% over the past 7 days, ranking #178 of 2,391 tracked listings.
About @earendil-works/pi-mcp
@earendil-works/pi-mcp
A small, standalone Model Context Protocol client. It does not depend on the official MCP SDK or other pi packages.
The package provides a transport-neutral client core, stdio and Streamable HTTP transports, and an in-memory testing transport.
Usage
import { McpClient, StdioTransport } from "@earendil-works/pi-mcp";
const transport = new StdioTransport({
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"],
});
const client = new McpClient({
name: "my-client",
version: "1.0.0",
roots: [{ uri: "file:///workspace", name: "workspace" }],
});
await client.connect(transport);
const tools = await client.listTools();
const result = await client.callTool("search", { query: "MCP" });
await client.close();
For a remote server, use new StreamableHttpTransport({ url, headers }). Fetch can be injected for proxying or custom networking.
Tools for an LLM
toLlmContent(result) converts a CallToolResult to text and image content for a model, in the shape of @earendil-works/pi-ai's TextContent and ImageContent. Text and images pass through, embedded text and image resources are unwrapped, and audio, resource links, and binary resources become short text placeholders. A result without content blocks but with structuredContent becomes its JSON.
Wrapping an MCP tool as a pi-agent-core AgentTool:
import type { AgentTool } from "@earendil-works/pi-agent-core";
import { toLlmContent } from "@earendil-works/pi-mcp";
import { Type } from "typebox";
const tools: AgentTool[] = (await client.listTools()).map((tool) => ({
// Providers allow at most 64 characters of [A-Za-z0-9_-].
name: `mcp_${tool.name}`.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 64),
label: tool.title ?? tool.name,
description: tool.description ?? tool.name,
// Providers require an object schema, and some reject one without `properties`.
parameters: Type.Unsafe({ ...tool.inputSchema, type: "object", properties: tool.inputSchema.properties ?? {} }),
execute: async (_toolCallId, params, signal) => {
const result = await client.callTool(tool.name, params as Record<string, unknown>, { signal });
// MCP reports tool failures in the result instead of as a protocol error.
return { content: toLlmContent(result), details: undefined, isError: result.isError === true };
},
}));
The mcp-codemode example also forwards progress, passes structuredContent through, and lets @earendil-works/pi-codemode scripts call the tools.
OAuth
@earendil-works/pi-mcp/oauth provides the MCP OAuth client subset without depending on the official SDK:
import { McpClient, StreamableHttpTransport } from "@earendil-works/pi-mcp";
import {
adaptOAuthProvider,
authorizeMcp,
McpOAuthAuthorizationRequiredError,
McpOAuthProvider,
OAuthCallbackServer,
} from "@earendil-works/pi-mcp/oauth";
const serverUrl = "https://mcp.example.com/mcp";
const callback = await OAuthCallbackServer.listen();
let authorizationUrl: URL | undefined;
const oauth = new McpOAuthProvider({
serverUrl,
redirectUrl: callback.redirectUrl,
clientMetadata: { client_name: "My MCP client" },
onRedirect: (url) => {
authorizationUrl = url;
},
});
const connect = () => {
const client = new McpClient({ name: "my-client", version: "1.0.0" });
return {
client,
connected: client.connect(
new StreamableHttpTransport({ url: serverUrl, authProvider: adaptOAuthProvider(oauth) }),
),
};
};
const first = connect();
try {
await first.connected;
} catch (error) {
if (!(error instanceof McpOAuthAuthorizationRequiredError)) throw error;
const state = await oauth.state();
const result = callback.waitForCallback(state);
// Open authorizationUrl in the user's browser here.
const { code } = await result;
await authorizeMcp(oauth, { serverUrl, authorizationCode: code });
}
const { client, connected } = connect();
await connected;
Inject McpOAuthStateStore into McpOAuthProvider for durable credentials. The package does not open a browser or choose where credentials are stored.
The OAuth implementation is adapted from the MIT-licensed Model Context Protocol TypeScript SDK v1.29.0. Its license is included under LICENSES/.
An MCP transport owns framing and I/O. It delivers individual JSON-RPC messages to McpClient; the client owns request correlation, initialization, timeouts, cancellation, server requests, and protocol-level helpers.
Supported protocol surface
- MCP protocol version
2025-11-25, accepting servers that negotiate2025-06-18,2025-03-26, or2024-11-05 - initialization and
notifications/initialized - ping
- paginated
tools/list tools/call, including structured content- progress notifications and timeout renewal
- request cancellation
- Streamable HTTP sessions, the server-to-client GET stream with reconnection, and resumption of dropped response streams with
Last-Event-ID - stdio shutdown per the spec (close stdin, then SIGTERM, then SIGKILL), applied to the server's whole process group
- server
pingandroots/listrequests - logging and tool-list-change notifications through the generic notification API
- OAuth protected-resource and authorization-server discovery
- PKCE authorization code flow, dynamic client registration, token refresh (one refresh shared by concurrent 401s), and step-up authorization for
insufficient_scope
Batch JSON-RPC messages, legacy HTTP+SSE, servers, sampling, and tasks are outside the initial core.
Testing
@earendil-works/pi-mcp/testing exports createInMemoryTransportPair() for client and adapter tests.
Description from the npm listing.
- mcp
- model-context-protocol
- client
README badge
Show your rank in a README or on your website. The badge updates automatically.
Charts
Images: 30d · 1y · all time · 1600×900 dark
Adoption over time
7/30/90-day growth
Ranking history
Listing placement
Listing placement
Filled points are observed values; hollow points come from Internet Archive snapshots of the listing page. Dashed segments span periods with no observations — values between points are not interpolated.
Each band is one page of 20. Weekly downloads on a linear scale. Placement is projected from weekly downloads, so it can differ from the marketplace's own sort order. Hover a dot to see the listing.
Recent observations
Full history (544)Similar npm MCP servers plugins
All 20 @earendil-works/pi-mcp alternativesData source
Weekly downloads (trailing 7 complete days) come from the official npm downloads API. Downloads include CI and mirrors and are not equivalent to installs or users. npm publishes no ratings.
Listing: https://www.npmjs.com/package/@earendil-works/pi-mcp. First seen Oct 16, 2026; last successful collection Oct 21, 2026. See the methodology.