Skip to content
PluginStats

@gnldev/mcp weekly downloads statistics

By gnldev (7 listings) · npm · AI SDKs

MCP client → AI SDK tools. With @gnldev/durable, external MCP tool calls become exactly-once + replayable.

View on npm Stale · Oct 18, 2026

@gnldev/mcp has 447 recorded weekly downloads on npm, ranking #1568 of 2,322 tracked listings.

Weekly downloads
447
Official API · Oct 18, 2026
7-day growth
—
Insufficient history
30-day growth
—
Insufficient history
90-day growth
—
Insufficient history
Rank
#1568
Among tracked npm listings

About @gnldev/mcp

@gnldev/mcp

MCP client + server. Client: adapts external MCP tools to AI SDK tools → inside runDurable they become journaled and replayable: a call already recorded as done is not made again on resume (at-most-once for the effect). Server: exposes your own tools as MCP (callTool deduped against the journal, keyed by the CALLER the transport authenticated — see Who the caller is).

Install: pnpm add @gnldev/mcp — or use it from a repo clone: pnpm install && pnpm -r build.

npm i @gnldev/mcp   # peer: @gnldev/durable, ai  ·  dep: @modelcontextprotocol/sdk, @gnldev/auth (installed for you)
import { mcpTools, createMcpServer } from '@gnldev/mcp';

// Client: connect to an MCP server with the real @modelcontextprotocol/sdk (stdio or http),
// discover via tools/list, convert to AI SDK tools. The connection is LAZY: no I/O happens
// until the first tools()/describeTools() call.
const handle = mcpTools({ transport: { kind: 'stdio', command: 'npx', args: ['-y', 'some-mcp-server'] }, prefix: 'github_' });
const tools = await handle.tools();
await runDurable({ runId: 'r1', journal, model, tools, prompt: '…' }); // MCP calls are journaled
await handle.close();

// Server: expose your own tools as MCP.
const server = createMcpServer({ tools: { lookupOrder } });

API

  • mcpTools(opts: { transport, prefix?, info? }) → McpToolsHandle — connects to the REAL SDK (stdio/http/custom transport), lazy connect
    • handle.tools() → Promise<Record<string, AISDKTool>> — discovered tools, in AI SDK tool() shape
    • handle.describeTools() → Promise<McpToolSummary[]> — a firewall-ready summary: { name, description, inputSchema, descriptionHash } (consumed by W2)
    • handle.close() → Promise<void> — closes the connection, idempotent (no-op if never connected)
  • createMcpTools(client, { prefix? }) / connectMcp(transport, info?) — older, lower-level APIs (kept for compatibility); mcpTools is a higher-level, lazy handle wrapping them
  • createMcpServer(opts: { tools, journal?, identify?, allowTool?, rateLimit?, workKey?, workScope? }) / serveMcp(server, transport, info?) — server side, callTool is idempotent (journal + the derived run id)
    • identify(req) → Principal | undefined — WHO is calling (Identify from @gnldev/auth, the same function every GNL door takes). Handed the HTTP request the call came in, or one carrying the token the transport validated
    • allowTool({ name, caller, principal, runsAs }) → boolean — WHAT they may call. Applied to tools/list AND tools/call
    • rateLimit: { maxCalls, windowMs } | fn — HOW OFTEN. The object form counts per caller, in this process
    • tools: {...} | (ctx) => {...} — the function form hands the tool a sealed caller context, so it can answer "is this object theirs"
    • workKey(req) → string | undefined — what NAMES the unit of work when the client sends no _meta.idempotencyKey. Defaults to the client's key; returning undefined means that call is not deduped
  • listTools(req?) is async and takes the caller (breaking from 0.5.0) — a per-caller list cannot be computed without knowing who asks
  • mcpFirewall(opts: { server, journal, tools, allow?, deny?, maxCallsPerRun? }) → Guard — an MCP-specific Guard: allowlist/denylist + description pinning (tool-poisoning/rug-pull defense) + per-tool call limit (see the section below)
  • composeGuards(first, second) → Guard — chains two Guards (if first allows, second runs; deny/require-approval short-circuits)

How it works

Each MCP tool is wrapped with tool(); execute calls the MCP callTool. When wrapped with durableTool inside runDurable, the call is journaled → not called again on resume (see packages/durable/src/durable-tool.ts: keyed by toolCallId, if a succeeded record exists execute does NOT RUN AGAIN). Name collisions are avoided with the prefix. There is NO SEPARATE journal/dedup logic here — the durability of an MCP tool call is entirely delegated to @gnldev/durable's run/tool journal.

serveMcp uses ListToolsRequestSchema/CallToolRequestSchema (Zod schemas) when connecting to the real SDK Server — the SDK doesn't accept a plain { method: '...' } object. Raw tool outputs (string/object) are wrapped into the { content: [...] } format the SDK expects, in the bridge. A standard MCP tools/call request has no separate idempotencyKey field, but the spec defines params._meta as a free ('loose') meta carrier: mcpTools/createMcpTools (client) carries the idempotencyKey (${runId}:${toolCallId}) coming from runDurable's durableTool wrapper via params._meta.idempotencyKey; serveMcp reads it via req.params._meta?.idempotencyKey and passes it to createMcpServer.callTool — so journal-based server-side dedup — at-most-once for the effect — also works for calls coming through a real MCP Client (if _meta is absent, every call runs normally — backward compatible, and see workKey below).

Who the caller is, and why it is not the request

@gnldev/durable decided this for its own doors: workScope is read from the AGENT's configuration rather than from the call, because a per-call override "would put the dangerous half within reach of a request body". This server used to hand the request body the WHOLE identity — the dedup key was _meta.idempotencyKey, a string the client chose, and it became the journal's run id directly.

Three things were measured on a server built exactly as this README described, over the real SDK:…

Description from the npm listing.

  • ai
  • agent
  • llm
  • typescript
  • ai-sdk
  • durable
  • exactly-once
  • model-context-protocol
  • tools

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

@gnldev/mcp weekly downloads on npm, last 90 days: 447 weekly downloads as of Oct 18, 2026.@gnldev/mcpWeekly downloads on npm · Last 90 days447downloads / week400420440460480500Jul 20Aug 4Aug 19Sep 3Sep 18Oct 3Oct 18downloads / weekOct 18, 2026 – Oct 18, 2026 · 1 observations · Updated Oct 18, 2026pluginstats.com
@gnldev/mcp weekly downloads on npm, last 90 days: 447 weekly downloads as of Oct 18, 2026.

7/30/90-day growth

@gnldev/mcp weekly downloads growth on npm: 7-day growth unavailable, 30-day growth unavailable, 90-day growth unavailable.@gnldev/mcpWeekly downloads growth on npm447downloads / week now7-day growthinsufficient historyInsufficient history30-day growthinsufficient historyInsufficient history90-day growthinsufficient historyInsufficient historyGrowth vs. nearest observation to each baseline date · Updated Oct 18, 2026pluginstats.com
@gnldev/mcp weekly downloads growth on npm: 7-day growth unavailable, 30-day growth unavailable, 90-day growth unavailable.

Ranking history

@gnldev/mcp npm ranking history: currently #1568 (by weekly downloads).@gnldev/mcpnpm ranking · by weekly downloads · Last 90 days#1568current rank#1566#1567#1568#1569#1570Jul 22Aug 6Aug 21Sep 5Sep 20Oct 5Oct 20rankOct 20, 2026 – Oct 20, 2026 · 1 observations · Updated Oct 18, 2026pluginstats.com
@gnldev/mcp npm ranking history: currently #1568 (by weekly downloads).

Listing placement

All npm2,320 listings · 116 pages · 1,162 shown · page 79, #12 (overall #1,572)
All npm: every listing in weekly downloads order

Listing placement

AI SDKs259 listings · 13 pages · page 10, #1 (overall #181)
AI SDKs: every listing in weekly downloads order

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 (1)
Recent weekly downloads observations for @gnldev/mcp
Date (UTC)Weekly downloadsChange vs. previous
447—

Similar npm AI SDKs plugins

All 20 @gnldev/mcp alternatives

Data 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/@gnldev/mcp. First seen Oct 20, 2026; last successful collection Oct 20, 2026. See the methodology.