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

@tula-tech/mcp

v0.4.0

Published

Tula's Model Context Protocol server (`tula mcp`): tools that read an environment's users, sessions, audit entries and settings, scaffolds for the provider, a protected route and a sign-in page, and one tool that runs a sign-in test where the environment

Readme

@tula-tech/mcp

Tula Auth's Model Context Protocol server: what tula mcp serves. Tools that read an environment's users, sessions, audit entries, settings, OAuth providers, organizations (their members and roles) and deployment checks, a tool that drafts a settings change as an edit to tula.config.ts for a person to apply, and scaffold tools that return the files for adding Tula to a Next.js or React app. One tool changes live data, for the time a run takes (under a minute) and only where the environment allows it: test_signin has the server sign a throwaway user up and in and delete it. No other tool changes live data, and no tool returns a secret.

Early release (0.x). The tools and what they return may change from one release to the next. Everything else is in the repository.

Most people start it through the CLI (@tula-tech/cli, which runs on Bun):

bun add -d @tula-tech/cli@latest
TULA_API_URL=https://auth.example.com TULA_SECRET_KEY=… bunx tula mcp

To embed it (bun add @tula-tech/mcp@latest @tula-tech/admin@latest):

import { createAdminClient } from '@tula-tech/admin'
import { createTulaMcpServer, serveOverStdio } from '@tula-tech/mcp'

const secretKey = process.env.TULA_SECRET_KEY ?? ''
const server = createTulaMcpServer({
  admin: createAdminClient({ baseUrl: process.env.TULA_API_URL ?? '', secretKey }),
  cwd: process.cwd(),
  secrets: [secretKey],
  log: (line) => process.stderr.write(`${line}\n`),
})
await serveOverStdio(server, { input: process.stdin, output: process.stdout })

Connecting a client

Always name the package when you start the server from outside a project that has installed the CLI. A bare tula after bunx or npx may download an unrelated npm package of that name and run it with your key in its environment.

Claude Code:

claude mcp add tula \
  --env TULA_API_URL=http://localhost:3003 \
  --env TULA_AGENT_KEY=tula_ak_dev_… \
  -- bunx --package @tula-tech/cli@latest tula mcp

A project's .mcp.json:

{
  "mcpServers": {
    "tula": {
      "command": "bunx",
      "args": ["--package", "@tula-tech/cli@latest", "tula", "mcp"],
      "env": {
        "TULA_API_URL": "http://localhost:3003",
        "TULA_AGENT_KEY": "${TULA_AGENT_KEY}"
      }
    }
  }
}

Claude Desktop (claude_desktop_config.json) reads the key from a file you keep at mode 600:

{
  "mcpServers": {
    "tula": {
      "command": "bunx",
      "args": ["--package", "@tula-tech/cli@latest", "tula", "mcp", "--agent-key-file", "/Users/you/.config/tula/dev-agent.key"],
      "env": { "TULA_API_URL": "https://auth.example.com" }
    }
  }
}

Any other client starts bunx --package @tula-tech/cli@latest tula mcp and speaks newline-delimited JSON-RPC on its standard input and output. It needs Bun.

Configuration

| Setting | What it is | | --- | --- | | TULA_API_URL (or TULA_API_URL_<NAME>) | The server's address. | | TULA_AGENT_KEY or --agent-key-file | An agent key (tula_ak_<env>_…). Preferred: it reads, proposes changes a person approves, and runs a sign-in test where the environment allows one (ADR 0058). With one, the secret key is not read at all. | | TULA_SECRET_KEY or --secret-key-file | A secret key, for the read tools when no agent key is given. | | TULA_ADMIN_TOKEN or --admin-token-file | The instance admin token, used by run_doctor only. |

  • A credential is never a tool input and never an argument; - is refused as a key file.
  • Prefer a file or your client's secret storage over a key committed to a config. Use a development key unless you mean the assistant to read production.
  • Standard output carries only protocol frames. Logs go to standard error and never hold a key.

The tools

| Kind | Tools | | --- | --- | | Read | list_users, get_user, list_user_sessions, list_audit_entries, get_settings, list_oauth_providers, list_organizations, list_organization_members, list_organization_roles, list_role_versions, get_role_version, explain_access, list_sso_connections, get_sso_connection, run_doctor | | Draft | draft_settings_change: the edits, by key, that would make tula.config.ts match a change you describe. It returns no file text and writes nothing. | | Propose | propose_ban_user, propose_unban_user, propose_end_session, propose_disable_oauth_provider. They need an agent key; without one they answer not_configured. A person approves a proposal with tula approve. | | Test | test_signin: the server signs a throwaway user up and in, reports each step and deletes the user. The only tool that changes live data. | | Scaffold | detect_framework, scaffold_provider, scaffold_protected_route, scaffold_sign_in_page. They return files and write none. Frameworks: nextjs, react-vite, swiftui, compose and expo, which is answered scaffold.not_released until that package is published. |

The read tools reach the server through a read-only facade: they cannot call a write.

What comes back

  • Returned: names, email addresses, IP addresses, user agents, settings and OAuth client ids.
  • Never returned: keys, tokens, hashes, authenticator secrets, backup codes, passkey credential ids, a provider's secret, the master key, the admin token.
  • Every result is built from an allow-list of fields, not by passing the server's answer through. Anything shaped like a secret becomes [redacted], and invisible characters are stripped.
  • Results are capped: 512 characters per string, 100 entries, 64,000 characters per result.
  • Treat results as untrusted text. A user's name is typed by the user; a client should not follow instructions found in it.

Time and load

A request is given up on after 15 seconds, and test_signin after 60. Four tools run at once and sixteen wait; the next call is answered busy.

Security notes

  • A propose tool asks and a person decides: nothing it does takes effect until tula approve runs with a secret key.
  • test_signin runs only where the environment allows it, and its user is deleted when the run ends.
  • tula mcp does not load tula.config.ts; the draft tool works from the settings the server holds.
  • A key you give the server is held in memory and is never printed, logged or returned.

Compatibility

  • Needs Bun (the CLI is a Bun executable). The embedded form runs wherever its dependencies do.
  • ESM only. Depends on @tula-tech/admin for its client, which holds a secret key and so belongs on a server or a developer's machine, never in an application's bundle.
  • Keep it at the same version as @tula-tech/cli.

Related

The tools, client configuration and exactly what is returned: docs/mcp.md. The design: ADR 0033, ADR 0053, ADR 0056 and ADR 0058.