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

@postqode/mcp

v0.9.0

Published

Host-agnostic Model Context Protocol client for PostQode: hub, OAuth manager, typed Zod schemas, shared server/tool/resource types.

Downloads

1,366

Readme

@postqode/mcp

Host-agnostic Model Context Protocol client layer. Covers everything from typed Zod schemas and shared server/tool/resource types up through the full connection orchestrator (McpHub) and OAuth flow (McpOAuthManager).

The extension's VS Code adapter lives in src/core/controller/index.ts. Any other consumer — CLI, standalone runtime, another agent harness — can supply its own callbacks for UI notifications, webview state pushes, telemetry, callback URLs, browser opening, and secret storage.

What ships

  • Constants & schemasDEFAULT_MCP_TIMEOUT_SECONDS, POSTQODE_MCP_TOOL_IDENTIFIER, BaseConfigSchema, ServerConfigSchema, McpSettingsSchema (Zod).
  • Shared typesMcpServer, McpTool, McpResource, McpResourceTemplate, McpOAuthAuthStatus, McpMode, McpConnection, Transport, McpServerConfig.
  • McpHub — watches the settings file, connects to each configured server over stdio / SSE / streamable-HTTP, and dispatches tools/call / resources/read requests. Handles timeout config, auto-approve, reconnects on UnauthorizedError, and tool-result notifications.
  • McpOAuthManager — per-server OAuthClientProvider with PKCE state, token refresh, pending-URL buffering so the browser only opens when the user clicks "Authenticate".
  • getServerAuthHash, getMcpServerCallbackPath — the two stable helpers shared by callback-URL routing and secret keying.

Minimal usage

import { McpHub, type McpHubConfig } from "@postqode/mcp"
import * as os from "node:os"
import * as path from "node:path"
import * as fs from "node:fs/promises"

// Pluggable secret store — use a dotfile here; the extension wires
// VS Code's secretStorage instead.
const secretsFile = path.join(os.homedir(), ".postqode", "mcp-secrets.json")
const authTokenStore = {
	get: async (key: string) => {
		const raw = await fs.readFile(secretsFile, "utf8").catch(() => "{}")
		return (JSON.parse(raw) as Record<string, string>)[key]
	},
	set: async (key: string, value: string) => {
		const raw = await fs.readFile(secretsFile, "utf8").catch(() => "{}")
		const obj = JSON.parse(raw) as Record<string, string>
		obj[key] = value
		await fs.writeFile(secretsFile, JSON.stringify(obj))
	},
}

const config: McpHubConfig = {
	getMcpServersPath: async () => path.join(os.homedir(), ".postqode", "mcp"),
	getSettingsDirectoryPath: async () => path.join(os.homedir(), ".postqode"),
	clientVersion: "my-cli/0.1.0",
	oauth: {
		getCallbackUrl: async () => "http://localhost:3000",
		openExternalUrl: async (url) => {
			console.log("Open this URL to authenticate:", url)
		},
		authTokenStore,
	},
	host: {
		showMessage: ({ type, message }) => console[type === "error" ? "error" : "log"](message),
		onServersUpdated: (servers) => console.log(`[mcp] ${servers.length} servers connected`),
		// captureToolCall is optional — omit if you don't need telemetry.
	},
}

const hub = new McpHub(config)
// hub.getServers() → read current server list
// hub.callTool(serverName, toolName, args) → invoke a tool

Callback surface

Required callbacks — no sane SDK defaults exist.

| Field | Purpose | |---|---| | oauth.getCallbackUrl() | Base URL the OAuth provider redirects to. | | oauth.openExternalUrl(url) | Opens the URL in the user's browser. | | oauth.authTokenStore.{get,set} | Pluggable secret storage for tokens + PKCE. |

Optional host callbacks — default to no-ops.

| Field | Default | Purpose | |---|---|---| | host.showMessage | no-op | Surface a user-visible notification (info / warning / error). | | host.onServersUpdated | no-op | Called on every server-list change. The extension pushes to its webview. | | host.captureToolCall | no-op | Lifecycle event for telemetry (started / success / error). | | mcpSettingsFileName | "postqode_mcp_settings.json" | Basename of the settings file. |

Design note

The 1,700 LOC orchestration layer is genuinely reusable — the coupling to HostProvider, StateManager, PostHog, and the webview RPC was the only reason it used to live in src/services/mcp/. Every site is now a callback; the extension's adapter is ~35 lines.

Sibling packages