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

@nozomtechs/grc-mcp

v1.1.0

Published

MCP server for the Nozom Cybersecurity GRC Platform — exposes GRC API endpoints as Model Context Protocol tools. R-EXTSPEC: @modelcontextprotocol/sdk v1.29.0 — https://modelcontextprotocol.io/specification/latest

Readme

grc-mcp — Nozom GRC MCP Server

MCP (Model Context Protocol) server for the Nozom Cybersecurity GRC Platform. Exposes the GRC API as MCP tools consumable by Claude Desktop, Cursor, and other MCP clients.

Spec: @modelcontextprotocol/sdk v1.29.0 — https://modelcontextprotocol.io/specification/latest Backend: Nozom GRC API (grc-backend) — authenticated via Personal Access Token (PAT).


Quickstart

Zero-install (recommended): the MCP client launches grc-mcp on demand via npx. No global install needed; npm fetches the package the first time and caches it.

Or install globally for repeat use without npx overhead:

npm install -g @nozomtechs/grc-mcp

1. Create a scoped PAT

In the GRC web app: Profile → API → Create Token. Select scope: MCP read-only, MCP read+write, or MCP admin depending on what you need. Copy the grc_… token immediately — it is shown only once.

2. Configure your MCP client

Claude Desktop (claude_desktop_config.json)

{
  "mcpServers": {
    "grc": {
      "command": "npx",
      "args": ["-y", "@nozomtechs/grc-mcp", "--backend-url", "https://grc-api.nozomtechs.sa"],
      "env": {
        "GRC_PAT": "grc_<your-token-here>"
      }
    }
  }
}

Cursor (.cursor/mcp.json)

{
  "mcpServers": {
    "grc": {
      "command": "npx",
      "args": ["-y", "@nozomtechs/grc-mcp", "--backend-url", "https://grc-api.nozomtechs.sa"],
      "env": {
        "GRC_PAT": "grc_<your-token-here>"
      }
    }
  }
}

If you npm install -g @nozomtechs/grc-mcp instead, replace "command": "npx" and "args": ["-y", "@nozomtechs/grc-mcp", ...] with "command": "grc-mcp" and "args": [...] (the rest stays the same).

4. Verify

In Claude Desktop or Cursor, ask: "List the available GRC tools." — the tool list should appear.


CLI Options

| Flag | Default | Description | |------|---------|-------------| | --backend-url <url> | http://localhost:5282 | GRC API base URL | | --transport <stdio\|http> | stdio | Transport type (stdio or http) | | --port <N> | 3000 | HTTP listen port (HTTP transport only) | | --host <H> | 127.0.0.1 | HTTP bind address (HTTP transport only; loopback by default — AI-58) | | --cors-origin <origin> | (none) | Allowed CORS origin for browser clients (e.g. https://app.example.com; * = all origins, insecure) | | --smoke-test | — | Validate PAT + list tools, then exit 0 or 1 | | --cache-ttl <seconds> | 300 | PAT validation cache TTL (0 = disabled) | | --scope <read\|write\|admin> | (PAT governs) | Server-level scope downgrade. Effective scope = min(PAT scope, this flag). | | --readonly | — | Alias for --scope=read (shorthand for read-only AI agent configs). | | --no-confirm-delete | — | Disable the confirm-delete gate (see Safety Rails below). | | --rate-limit <N> | 60 | Max tool calls per minute (0 = disabled). Token bucket per session/PAT. | | --include-modules <csv> | (all) | Comma-separated list of modules to expose (e.g. Risks,Findings). | | --preset <name> | (all) | Curated module group (see Safety Rails below). Mutually exclusive with --include-modules. |

Environment variables (override CLI flags):

| Variable | Description | |----------|-------------| | GRC_PAT | PAT token (grc_…) — required for stdio; not required for HTTP (PAT comes per-connection via Authorization: Bearer) | | GRC_BACKEND_URL | Backend URL — optional |


Safety Rails

Story 32-5 adds four orthogonal safety layers that narrow the tool set and call budget without touching auth or transport.

1. Server-level scope downgrade (--scope / --readonly)

The --scope flag downgrades the effective scope below what the PAT allows. Effective scope = min(PAT scope, --scope flag) — the flag can only restrict, never elevate.

# Read-only mode (even if PAT has write scope)
grc-mcp --readonly --backend-url https://grc-api.nozomtechs.sa

# Equivalent
grc-mcp --scope=read --backend-url https://grc-api.nozomtechs.sa

| PAT scope | --scope flag | Effective scope | |-----------|---------------|-----------------| | mcp:write | read | mcp:read (flag wins) | | mcp:read | write | mcp:read (PAT wins) | | null (full) | read | mcp:read (server downgrade) | | null (full) | admin | null (admin flag + null PAT = no restriction) |

Unknown --scope values print an error and exit 1.

2. Confirm-delete gate (--no-confirm-delete)

By default, every DELETE tool requires { confirm: true } in its arguments to execute. The tool description shows: ⚠️ DESTRUCTIVE: Set confirm=true to execute this delete.

If an AI agent calls a DELETE tool without confirm: true, the MCP server returns an error immediately — no HTTP request is sent to the backend.

# Disable the confirm gate (e.g. when scripting known-safe automated runs)
grc-mcp --no-confirm-delete --backend-url https://grc-api.nozomtechs.sa

AI-58: The confirm field value is never logged.

3. Rate limiting (--rate-limit)

Token bucket rate limiter: default 60 tool calls per minute.

  • stdio mode: one bucket per process (stdio is single-PAT by design — AI-58: no full token in bucket scope).
  • HTTP mode: one bucket per session (created at session init; reclaimed when the session's MCP server closes).
  • Exceeding the limit returns a rate-limit error with Retry after Ns. — no HTTP request sent.
  • Invalid --rate-limit values (non-integer, negative) exit with process.exit(1).
# Custom rate limit
grc-mcp --rate-limit=120 --backend-url https://grc-api.nozomtechs.sa

# Disable rate limiting
grc-mcp --rate-limit=0 --backend-url https://grc-api.nozomtechs.sa

4. Module filter (--include-modules / --preset)

Restrict which modules' tools are registered. Useful when an AI agent only needs a subset (e.g. risk-only for a risk analyst agent).

# Only Risks and Findings modules
grc-mcp --include-modules=Risks,Findings --backend-url https://grc-api.nozomtechs.sa

# Use a preset
grc-mcp --preset=risk --backend-url https://grc-api.nozomtechs.sa

Available presets:

| Preset | Modules | |--------|---------| | risk | Risks, Methodologies | | compliance | Frameworks, Controls, Compliance | | audit | Audit | | bcm | Bcm | | phishing | Phishing | | core | Risks, Findings, Tasks, Exceptions |

--preset and --include-modules are mutually exclusive (error if both set).

Startup log confirms what's being exposed:

[grc-mcp] Exposing 80 tools across 4 modules: Exceptions, Findings, Risks, Tasks

Example: read-only risk analyst agent

{
  "mcpServers": {
    "grc-risks": {
      "command": "grc-mcp",
      "args": [
        "--backend-url", "https://grc-api.nozomtechs.sa",
        "--readonly",
        "--preset=risk",
        "--rate-limit=30"
      ],
      "env": {
        "GRC_PAT": "grc_<mcp-read-token>"
      }
    }
  }
}

HTTP Transport

Story 32-4 adds a second transport — Streamable HTTP — per the MCP 2025-11-25 specification. Use HTTP transport for cloud AI agents, server-to-server MCP calls, or HTTP clients.

Starting in HTTP mode

# Bind to loopback (default — safe for local use)
grc-mcp --transport=http --backend-url https://grc-api.nozomtechs.sa

# Bind to a specific interface (non-loopback — ensure network-level access controls)
grc-mcp --transport=http --host 0.0.0.0 --port 4000 --backend-url https://grc-api.nozomtechs.sa

# With CORS for browser-based clients
grc-mcp --transport=http --cors-origin https://app.example.com --backend-url https://grc-api.nozomtechs.sa

HTTP endpoint

All MCP requests go to POST /mcp (or GET /mcp for SSE streams, DELETE /mcp for session termination).

Auth in HTTP mode

In HTTP mode, PAT comes from the Authorization: Bearer <PAT> header of each initialization request:

POST /mcp HTTP/1.1
Authorization: Bearer grc_<your-token>
Content-Type: application/json
Accept: application/json, text/event-stream
  • GRC_PAT env var is NOT required in HTTP mode (a warning is logged if it is set).
  • Each connection validates its PAT independently — sessions with different PATs are fully isolated.

Example curl flow

# 1. Initialize — get a session ID
curl -X POST http://127.0.0.1:3000/mcp \
  -H "Authorization: Bearer grc_<your-token>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2025-11-05","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}},"id":1}'

# The response includes:  MCP-Session-Id: <uuid>

# 2. List tools (use the session ID from the initialize response)
curl -X POST http://127.0.0.1:3000/mcp \
  -H "MCP-Session-Id: <uuid-from-step-1>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":2}'

# 3. Call a tool
curl -X POST http://127.0.0.1:3000/mcp \
  -H "MCP-Session-Id: <uuid-from-step-1>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"grc.list_risks","arguments":{"pageSize":5}},"id":3}'

# 4. Terminate session
curl -X DELETE http://127.0.0.1:3000/mcp \
  -H "MCP-Session-Id: <uuid-from-step-1>"

Generic HTTP MCP client config

{
  "mcpServers": {
    "grc": {
      "transport": "http",
      "url": "http://127.0.0.1:3000/mcp",
      "headers": {
        "Authorization": "Bearer grc_<your-token>"
      }
    }
  }
}

Security

  • Default bind is loopback (127.0.0.1) — only local processes can connect. Pass --host 0.0.0.0 to expose remotely (logged as SECURITY WARNING).
  • Origin validation per MCP spec: non-loopback Origin headers are rejected with 403 unless --cors-origin is configured.
  • PAT never logged — log lines include only session ID prefix, HTTP status code, and endpoint path.
  • 401 responses contain only {"error": "Unauthorized"} — no token, no Bearer prefix in the body.

Architecture

  • Transports: stdio (Story 32-2) and Streamable HTTP (Story 32-4).
  • Auth: PAT validated via GET /v1/users/me/pat-info; cached per session (5 min TTL).
  • Tool registry: Generated from manifest/api-manifest.json at startup (Story 32-3).
  • Scope enforcement: pat_scope claim checked — mcp:read for GET tools, mcp:write for mutating tools, mcp:admin for cross-tenant tools.

stdio connection lifecycle

  1. MCP client launches grc-mcp as a subprocess (stdio transport).
  2. src/index.ts parses CLI args → reads GRC_PAT env var.
  3. src/server.ts creates McpServer + StdioServerTransport, calls server.connect(transport).
  4. At startup, src/auth.ts validates the PAT via backend /v1/users/me/pat-info.
  5. If valid: PAT info cached 5 min. Tools registered per PAT scope.
  6. If invalid/expired/revoked: server exits 1 at startup.
  7. Client disconnects → StdioServerTransport closes → process exits.

HTTP connection lifecycle

  1. src/index.ts starts src/http-server.tshttp.createServer() binds to --host:--port.
  2. Client sends POST /mcp with Authorization: Bearer <PAT> + InitializeRequest body.
  3. Server validates PAT via src/auth.ts → if invalid, returns 401 (body: {"error":"Unauthorized"}).
  4. If valid: new McpServer + StreamableHTTPServerTransport created per session; tools registered with PAT's scope.
  5. SDK assigns MCP-Session-Id: <uuid> in the initialize response header.
  6. Subsequent requests include MCP-Session-Id header → routed to the correct session's transport.
  7. Client sends DELETE /mcp with session ID → session cleaned up; McpServer + transport released.
  8. Multiple simultaneous sessions (with different PATs) are supported — each fully isolated.

Branch Policy

  • master — demo/release branch. Direct commits only at demo cuts.
  • feature/epic-{N}-{slug} — feature branches (base off master). Used during epic development.
  • Single-branch model: no integration branch needed (npm release cadence, no dev environment).

Security

  • PAT never logged. AI-58: the grc_… plaintext token is read from GRC_PAT env var, used as an Authorization: Bearer header only, and never written to stderr, any log file, or error message.
  • Scope enforced on both sides: backend PatScopePreProcessor (Story 32-1) enforces scope; MCP server enforces scope as a defense-in-depth layer (Story 32-5).
  • Cache invalidated on revoke: if backend returns 401, PAT cache entry is immediately removed.

Development

git clone https://git.nozomtechs.sa/software-practice/grc-mcp.git
cd grc-mcp
npm install
npm run build
GRC_PAT=grc_<token> GRC_BACKEND_URL=http://localhost:5282 npm run test:smoke

Related