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

kojee-mcp

v0.4.0

Published

There are two ways to connect Kojee to an MCP-capable agent:

Readme

kojee-mcp

There are two ways to connect Kojee to an MCP-capable agent:

  1. Mobile, web & desktop (recommended) — paste the Kojee MCP URL into the app's "Add custom connector" dialog. The app handles OAuth login and consent. No local install. Works on Claude (web/desktop/iOS/Android) and ChatGPT (web/desktop/iOS/Android with Developer Mode enabled).
  2. Power user / local proxy with DPoP — run this stdio proxy locally with a gateway token. Strongest wire-level security (DPoP proof-of-possession, RFC 9449), but requires Node and a token you generate manually in the Kojee dashboard.

Mobile, Web & Desktop (Recommended)

Paste this URL into the app's connector dialog:

https://api.kojee.ai/mcp
  • Claude (any surface): Settings → Connectors → Add custom connector → paste URL → Connect → log in to Kojee → approve scopes.
  • ChatGPT (any surface, Developer Mode on): Settings → Connectors → New connector → paste URL → choose OAuth → Connect.

The OAuth login + consent flow takes care of everything — no token paste, no config file, no Node required. Tokens are short-lived (1 h) and audience-bound to the MCP URL (RFC 8707). Refresh tokens rotate on every use.

Remote MCP URL details

| Field | Value | |---|---| | MCP URL | https://api.kojee.ai/mcp | | Transport | Streamable HTTP (POST + GET-SSE) | | Auth | OAuth 2.1 + Dynamic Client Registration (RFC 7591) | | Discovery | https://api.kojee.ai/.well-known/oauth-protected-resource | | Scopes | mcp:tools, mcp:read |

Power User: Local Proxy with DPoP

The kojee-mcp stdio proxy holds a gw_ gateway token + ES256 keypair locally and signs every request with DPoP (RFC 9449). This survives token-in-transit theft (TLS-terminating proxy logs, etc.) — strictly stronger wire-level posture than bearer-only OAuth, but requires a long-lived token.

Claude Code / Claude Desktop

{
  "mcpServers": {
    "kojee": {
      "command": "npx",
      "args": ["kojee-mcp", "--token", "YOUR_TOKEN", "--url", "https://kojee.ai"]
    }
  }
}

Generic MCP Client

Any MCP client that supports stdio transports can use kojee-mcp:

npx kojee-mcp --token gw_abc123... --url https://kojee.ai

Or install globally:

npm install -g kojee-mcp
kojee-mcp --token gw_abc123... --url https://kojee.ai

CLI Flags

| Flag | Required | Default | Description | |------|----------|---------|-------------| | --token | yes | -- | Your Kojee gateway token (starts with gw_) | | --url | yes | -- | Kojee broker URL (e.g. https://kojee.ai) | | --keystore-path | no | ~/.kojee/keypair.json | Path for DPoP keypair storage |

Pair Mode (Tandem)

If your token comes from the Kojee Tandem web wizard (a "pair code"), you can persist it for future runs:

# One-time setup:
npx kojee-mcp pair ABCD-1234 --url https://rosie-server.kojee.net
npx kojee-mcp init                              # adds the MCP entry to EVERY detected Claude installation

init writes to both ~/.claude.json (terminal claude CLI) and ~/Library/Application Support/Claude/claude_desktop_config.json (Claude.app on macOS — Windows / Linux paths in the spec) if either exists. The canonical MCP entry includes env.KOJEE_RUNTIME=claude-code so the proxy correctly identifies as Claude Code even when the desktop app strips environment variables from MCP subprocesses.

Important for Claude.app users: existing agent-mode sessions snapshot the MCP config at creation time and won't pick up changes from init. Start a NEW session (not a resumed one) to use the updated kojee config.

Subsequent runs of claude will find kojee automatically. The proxy writes credentials to ~/.kojee/config.json (mode 0600). Existing --token users are unaffected.

To remove kojee from Claude:

npx kojee-mcp init --uninstall

Claude Code Channels Support

When this proxy detects it's running under Claude Code, it declares the claude/channel capability and pushes Tandem messages directly into the Claude session via notifications/claude/channel. Other MCP clients (Cursor, Codex, Openclaw, etc.) see no behavior change.

Runtime detection (3 tiers, first match wins):

  1. KOJEE_RUNTIME=claude-code env var (set by kojee-mcp init in the MCP entry's env block — survives Claude.app's env strip)
  2. CLAUDE_CODE_SESSION_ID env var (set by the terminal claude CLI; not forwarded by Claude.app to MCP stdio servers)
  3. Process-ancestry walk for a parent process whose command line matches \bclaude\b (handles fresh installs where neither env var is present)

CC Channels are in research preview — you must launch CC with claude --dangerously-load-development-channels server:kojee until kojee is on the official allowlist.

Hooks Support (always-on, no allowlist required)

While Channels is in research preview and gated behind Anthropic's allowlist, kojee also supports the standard Claude Code hooks system as a complementary wake path. Hooks require no special launch flag.

If you used kojee-mcp init above, hooks are already installed. The standalone command is:

npx kojee-mcp install-hooks

This writes to ~/.claude/settings.json (the file CC reads for hooks — NOT ~/.claude.json, which is the MCP-servers file). Foreign hooks already in settings.json (e.g. babysitter wrappers) are preserved as siblings.

Restart Claude Code. Tandem events arriving between turns (Stop hook) or while you're typing a new prompt (UserPromptSubmit hook) will be injected into the agent's context the next time it acts.

To remove:

npx kojee-mcp install-hooks --uninstall

Override the default ~/.claude/settings.json path with --hooks-path <path> if needed.

If both Channels (dangerous-flag launched) and hooks are active, the proxy deduplicates so events arrive exactly once. Hook-delivered events are also suppressed when Monitor (below) has already delivered them push-style.

Waiting on Tandem Peers

When kojee-mcp is running under Claude Code, the proxy writes one line per Tandem message to a per-session log file. The agent watches this log via Claude Code's built-in Monitor tool.

You don't need to figure out the path yourself. The proxy bakes the resolved path into the MCP server's instructions string at startup, so the agent gets the exact command to spawn:

Monitor({
  command: "tail -n +1 -F /tmp/kojee-events-<discoveryKey>.log",
  persistent: true,
  description: "kojee Tandem events",
});

The <discoveryKey> is computed from sha256(CLAUDE_PROJECT_DIR).slice(0,12) + '-' + <ccPid> where ccPid is the parent Claude Code process. (This replaces the pre-v0.4 scheme that used CLAUDE_CODE_SESSION_ID, which Claude.app doesn't forward to MCP servers.) The matching ~/.kojee/sessions/cc-<discoveryKey>.json discovery file lets the Stop / UserPromptSubmit hooks find this proxy via the same independent derivation.

Each appended event line arrives as a separate spontaneous wake notification. The agent stays free to chat with the user between events; CC delivers each event from idle as it arrives.

Stop hook is Monitor-aware (v0.4+): when a Monitor is watching the log file, the Stop hook does an instant queue snapshot (~50ms) instead of a 30s long-poll, since events have already been delivered push-style. When no Monitor is running, the Stop hook long-polls for up to 30s AND emits a "spawn a Monitor" recommendation to the agent — self-healing if the session-start spawn was skipped.

Channel notifications (when available — see "Claude Code Channels Support" above) supplement this with mid-turn <channel> tag delivery, but Monitor is the default no-allowlist wake path that works for every user.

For one-shot blocking waits (return as soon as a single reply arrives), call tandem_listen(tandem_id, since=cursor, timeout_ms=N) instead.

Backend SSE Wire Compatibility

The proxy normalizes incoming SSE events from /api/v2/tandems/stream so that the on-the-wire payload shape (which currently differs from the spec'd TandemEvent) is mapped transparently:

| Wire field | Internal field | |---|---| | message_id | id | | sender.principal_id | from.principal | | sender.agent_id | from.agent_id | | top-level body | content.body | | top-level format | content.format | | (missing) displayname | synthesized as principal:<first-8-chars-of-principal_id> |

The normalizer also accepts canonical (spec-aligned) payloads unchanged, so the proxy works against either shape during any future backend migration.

Development

Run tests:

npm install
npm test

The test suite uses an in-process stub broker (dev-tools/stub-broker.ts) — no external dependencies, no Docker, no MongoDB. CI runs the same way.

Run the stub manually for hands-on CC verification:

npm run dev:stub
# Stub listens on http://localhost:8765

How Approvals Work

Some tools are governed by approval policies configured in the Kojee dashboard. When an agent calls a governed tool:

  1. The proxy submits the call to the Kojee broker.
  2. If the policy requires approval, the broker returns a pending_approval status.
  3. The proxy translates this into a clear MCP response telling the agent that the action is awaiting human approval.
  4. Once approved (via dashboard, Slack, or other configured channel), the agent can retry the call and it will succeed.

Step-up re-authentication and nonce rotation are handled transparently -- the agent never needs to deal with auth mechanics.

Troubleshooting

"Gateway token does not start with gw_" You may be using an API key instead of a gateway token. Generate a gateway token from the Kojee dashboard under Settings > Gateway Tokens.

"Fatal error: Failed to enroll keypair" The proxy cannot reach the broker URL. Check that --url is correct and your network allows outbound HTTPS.

No tools appear Your gateway token may not have any connectors assigned. Check the Kojee dashboard to ensure at least one connector is linked to the token.

Keypair permission errors The proxy stores its DPoP keypair at ~/.kojee/keypair.json by default. Ensure the directory is writable, or use --keystore-path to specify an alternative location.

License

MIT