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

@vurb/testing

v3.6.8

Published

In-memory MVA lifecycle emulator for Vurb. Runs the full pipeline (Zod Input → Middlewares → Handler → Egress Firewall) without network transport. Returns structured MvaTestResult objects — zero coupling to Jest/Vitest.

Readme


The official test runner for Vurb.ts applications. In-memory MVA lifecycle emulator — runs the full execution pipeline without network transport. Zero runtime dependencies. Runner agnostic (Vitest, Jest, Mocha, node:test).

Why

Every MCP server today is tested with HTTP mocks, raw JSON.stringify assertions, and string matching. That's like testing a REST API by reading TCP packets.

Vurb.ts applications have five auditable layers (Zod Validation → Middleware Chain → Handler → Presenter Egress Firewall → System Rules). The VurbTester lets you assert each layer independently, in-memory, without starting a server.

┌─────────────────────────────────────────────────────────┐
│                    VurbTester                          │
│                                                         │
│  ┌──────────┐   ┌────────────┐   ┌─────────┐           │
│  │   Zod    │──▶│ Middleware  │──▶│ Handler │           │
│  │  Input   │   │   Chain    │   │         │           │
│  └──────────┘   └────────────┘   └────┬────┘           │
│                                       │                 │
│                                  ┌────▼────┐            │
│                                  │Presenter│            │
│                                  │ (Egress │            │
│                                  │Firewall)│            │
│                                  └────┬────┘            │
│                                       │                 │
│  ┌────────────────────────────────────▼──────────────┐  │
│  │              MvaTestResult                        │  │
│  │  ┌──────┐ ┌───────────┐ ┌────────┐ ┌───────────┐ │  │
│  │  │ data │ │systemRules│ │uiBlocks│ │rawResponse│ │  │
│  │  └──────┘ └───────────┘ └────────┘ └───────────┘ │  │
│  └───────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘

What You Can Audit

| MVA Layer | What VurbTester asserts | SOC2 Relevance | |---|---|---| | Egress Firewall | Hidden fields (passwordHash, tenantId) are physically absent from result.data | Data leak prevention | | OOM Guard | Zod rejects take: 10000 before it reaches the handler | Memory exhaustion protection | | System Rules | result.systemRules contains the expected domain rules | Deterministic LLM governance | | UI Blocks | SSR blocks (echarts, summaries) are correctly generated | Agent response quality | | Middleware | Auth guards block unauthorized calls, isError is true | Access control verification | | Agent Limit | Collections are truncated at cognitive guardrail bounds | Context window protection | | HATEOAS | suggestActions produces correct next-step affordances | Agent navigation safety |

Quick Start

import { describe, it, expect } from 'vitest';
import { createVurbTester } from '@vurb/testing';
import { registry } from './server/registry.js';

const tester = createVurbTester(registry, {
    contextFactory: () => ({
        prisma: mockPrisma,
        tenantId: 't_enterprise_42',
        role: 'ADMIN',
    }),
});

describe('User MVA Audit', () => {
    it('Egress Firewall strips sensitive fields', async () => {
        const result = await tester.callAction('db_user', 'find_many', { take: 10 });

        expect(result.data[0]).not.toHaveProperty('passwordHash');
        expect(result.data[0]).not.toHaveProperty('tenantId');
        expect(result.data[0].email).toBe('[email protected]');
    });

    it('System rules are injected by Presenter', async () => {
        const result = await tester.callAction('db_user', 'find_many', { take: 5 });

        expect(result.systemRules).toContain(
            'Data originates from the database via Prisma ORM.'
        );
    });

    it('OOM Guard rejects unbounded queries', async () => {
        const result = await tester.callAction('db_user', 'find_many', { take: 99999 });
        expect(result.isError).toBe(true);
    });
});

API Reference

createVurbTester(registry, options)

Factory function — creates a VurbTester instance.

function createVurbTester<TContext>(
    registry: ToolRegistry<TContext>,
    options: TesterOptions<TContext>,
): VurbTester<TContext>;

| Parameter | Type | Description | |---|---|---| | registry | ToolRegistry<TContext> | Your application's tool registry — the same one wired to the MCP server | | options | TesterOptions<TContext> | Configuration object |

TesterOptions<TContext>

interface TesterOptions<TContext> {
    contextFactory: () => TContext | Promise<TContext>;
}

tester.callAction(toolName, actionName, args?, overrideContext?)

Executes a single tool action through the full MVA pipeline and returns a decomposed result.

async callAction<TArgs>(
    toolName: string,
    actionName: string,
    args?: TArgs,
    overrideContext?: Partial<TContext>,
): Promise<MvaTestResult>;

| Parameter | Type | Required | Description | |---|---|---|---| | toolName | string | ✅ | The registered tool name (e.g. 'db_user', 'analytics') | | actionName | string | ✅ | The action discriminator (e.g. 'find_many', 'create') | | args | object | ❌ | Arguments for the action — omit the action discriminator | | overrideContext | Partial<TContext> | ❌ | Per-test context overrides. Shallow-merged with contextFactory() output |

MvaTestResult<TData>

Decomposed MVA response — each field maps to a specific pipeline layer.

| Field | Type | Source | Description | |---|---|---|---| | data | TData | Presenter Zod schema | Validated data after the Egress Firewall. Hidden fields are physically absent. | | systemRules | string[] | Presenter .systemRules() | JIT domain rules injected by the Presenter. Empty array if no Presenter. | | uiBlocks | unknown[] | Presenter .uiBlocks() | SSR UI blocks (charts, summaries, markdown). Empty array if no Presenter. | | isError | boolean | Pipeline | true if Zod rejected, middleware blocked, or handler returned error(). | | rawResponse | unknown | Pipeline | The raw MCP ToolResponse for protocol-level inspection. |

Cookbook

Egress Firewall Audit

it('strips PII from response', async () => {
    const result = await tester.callAction('db_user', 'find_many', { take: 5 });

    const users = result.data as Array<Record<string, unknown>>;
    for (const user of users) {
        expect(user).not.toHaveProperty('passwordHash');
        expect(user).not.toHaveProperty('tenantId');
    }
});

Middleware Guards (RBAC)

it('blocks GUEST role', async () => {
    const result = await tester.callAction(
        'db_user', 'find_many', { take: 5 },
        { role: 'GUEST' },
    );
    expect(result.isError).toBe(true);
});

it('allows ADMIN role', async () => {
    const result = await tester.callAction(
        'db_user', 'find_many', { take: 5 },
        { role: 'ADMIN' },
    );
    expect(result.isError).toBe(false);
});

Agent Limit (Cognitive Guardrail)

it('truncates at agentLimit', async () => {
    const result = await tester.callAction('analytics', 'list', { limit: 100 });
    expect((result.data as any[]).length).toBe(20);
});

Protocol-Level Inspection

it('raw response follows MCP shape', async () => {
    const result = await tester.callAction('db_user', 'find_many', { take: 1 });
    const raw = result.rawResponse as { content: Array<{ type: string; text: string }> };

    expect(raw.content).toBeInstanceOf(Array);
    expect(raw.content[0].type).toBe('text');
});

How It Works

The VurbTester runs the real execution pipeline — the exact same code path as your production MCP server:

ToolRegistry.routeCall()
  → Concurrency Semaphore
    → Discriminator Parsing
      → Zod Input Validation
        → Compiled Middleware Chain
          → Handler Execution
            → PostProcessor (Presenter auto-application)
              → Egress Guard

The key insight: ResponseBuilder.build() attaches structured MVA metadata via a global Symbol (MVA_META_SYMBOL). Symbols are ignored by JSON.stringify, so the MCP transport never sees them — but the VurbTester reads them in RAM.

No XML regex. No string parsing. Zero coupling to response formatting.

Installation

npm install @vurb/testing

Peer Dependencies

| Package | Version | |---------|---------| | vurb | ^2.0.0 | | zod | ^3.25.1 \|\| ^4.0.0 |

Requirements

  • Node.js ≥ 18.0.0
  • TypeScript 5.7+
  • Vurb.ts ≥ 2.0.0 (peer dependency)

License

Apache-2.0