@vurb/core 3.8.2 → 3.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,162 +11,162 @@ export function readme(config) {
11
11
  const sseNote = config.transport === 'sse'
12
12
  ? `\n> **Note:** Streamable HTTP transport requires the server to be running first. Run \\\`npm start\\\` before connecting.`
13
13
  : '';
14
- return `# ${config.name}
15
-
16
- MCP Server built with [Vurb.ts](https://vurb.vinkius.com/) — the TypeScript framework for MCP servers.
17
-
18
- ## Quick Start
19
-
20
- \`\`\`bash
21
- npm install
22
- vurb dev
23
- \`\`\`
24
- ${config.testing ? `
25
- ## Testing
26
-
27
- \`\`\`bash
28
- npm test
29
- \`\`\`
30
- ` : ''}
31
- ## Project Structure
32
-
33
- \`\`\`
34
- src/
35
- ├── vurb.ts # initVurb<AppContext>() — context center
36
- ├── context.ts # AppContext type + factory
37
- ├── server.ts # Bootstrap with autoDiscover
38
- ├── tools/ # Drop a file → it's a tool (autoDiscover)
39
- │ └── system/
40
- │ ├── health.ts # Health check with Presenter
41
- │ └── echo.ts # Echo for connectivity testing
42
- ├── models/ # MVA Model Layer (defineModel)
43
- │ └── SystemModel.ts
44
- ├── presenters/ # MVA View Layer (Egress Firewall)
45
- │ └── SystemPresenter.ts
46
- ├── prompts/ # MCP Prompt Engine
47
- │ └── greet.ts
48
- └── middleware/ # RBAC guards
49
- └── auth.ts
50
- \`\`\`
51
-
52
- ## Client Configuration
53
-
54
- ### Cursor Editor
55
-
56
- > **Already configured!** The \`.cursor/mcp.json\` file was generated automatically.
57
- > Just open this folder in Cursor and the server connects instantly.
58
- ${sseNote}
59
-
60
- ### Claude Desktop
61
-
62
- Add to your \`claude_desktop_config.json\`:
63
-
64
- \`\`\`json
65
- ${clientConfig}
66
- \`\`\`
67
- ${vectorReadmeSection(config)}
68
- ## Adding New Tools
69
-
70
- Create a new file in \`src/tools/\`. It's automatically discovered:
71
-
72
- \`\`\`typescript
73
- // src/tools/my-domain/my-tool.ts
74
- import { f } from '../../vurb.js';
75
-
76
- export default f.query('my_domain.my_tool')
77
- .describe('What this tool does')
78
- .withString('query', 'Search query')
79
- .handle(async (input, ctx) => {
80
- return { result: input.query };
81
- });
82
- \`\`\`
83
-
84
- No registration needed. The \`autoDiscover()\` system picks it up automatically.
85
-
86
- ## Documentation
87
-
88
- - [Vurb Docs](https://vurb.vinkius.com/)
89
- - [Presenter — Egress Firewall](https://vurb.vinkius.com/presenter)
90
- - [DX Guide — initVurb()](https://vurb.vinkius.com/dx-guide)
91
- - [Testing](https://vurb.vinkius.com/testing)
14
+ return `# ${config.name}
15
+
16
+ MCP Server built with [Vurb.ts](https://vurb.vinkius.com/) — the TypeScript framework for MCP servers.
17
+
18
+ ## Quick Start
19
+
20
+ \`\`\`bash
21
+ npm install
22
+ vurb dev
23
+ \`\`\`
24
+ ${config.testing ? `
25
+ ## Testing
26
+
27
+ \`\`\`bash
28
+ npm test
29
+ \`\`\`
30
+ ` : ''}
31
+ ## Project Structure
32
+
33
+ \`\`\`
34
+ src/
35
+ ├── vurb.ts # initVurb<AppContext>() — context center
36
+ ├── context.ts # AppContext type + factory
37
+ ├── server.ts # Bootstrap with autoDiscover
38
+ ├── tools/ # Drop a file → it's a tool (autoDiscover)
39
+ │ └── system/
40
+ │ ├── health.ts # Health check with Presenter
41
+ │ └── echo.ts # Echo for connectivity testing
42
+ ├── models/ # MVA Model Layer (defineModel)
43
+ │ └── SystemModel.ts
44
+ ├── presenters/ # MVA View Layer (Egress Firewall)
45
+ │ └── SystemPresenter.ts
46
+ ├── prompts/ # MCP Prompt Engine
47
+ │ └── greet.ts
48
+ └── middleware/ # RBAC guards
49
+ └── auth.ts
50
+ \`\`\`
51
+
52
+ ## Client Configuration
53
+
54
+ ### Cursor Editor
55
+
56
+ > **Already configured!** The \`.cursor/mcp.json\` file was generated automatically.
57
+ > Just open this folder in Cursor and the server connects instantly.
58
+ ${sseNote}
59
+
60
+ ### Claude Desktop
61
+
62
+ Add to your \`claude_desktop_config.json\`:
63
+
64
+ \`\`\`json
65
+ ${clientConfig}
66
+ \`\`\`
67
+ ${vectorReadmeSection(config)}
68
+ ## Adding New Tools
69
+
70
+ Create a new file in \`src/tools/\`. It's automatically discovered:
71
+
72
+ \`\`\`typescript
73
+ // src/tools/my-domain/my-tool.ts
74
+ import { f } from '../../vurb.js';
75
+
76
+ export default f.query('my_domain.my_tool')
77
+ .describe('What this tool does')
78
+ .withString('query', 'Search query')
79
+ .handle(async (input, ctx) => {
80
+ return { result: input.query };
81
+ });
82
+ \`\`\`
83
+
84
+ No registration needed. The \`autoDiscover()\` system picks it up automatically.
85
+
86
+ ## Documentation
87
+
88
+ - [Vurb Docs](https://vurb.vinkius.com/)
89
+ - [Presenter — Egress Firewall](https://vurb.vinkius.com/presenter)
90
+ - [DX Guide — initVurb()](https://vurb.vinkius.com/dx-guide)
91
+ - [Testing](https://vurb.vinkius.com/testing)
92
92
  `;
93
93
  }
94
94
  /** Vector-specific README section */
95
95
  function vectorReadmeSection(config) {
96
96
  switch (config.vector) {
97
97
  case 'prisma':
98
- return `
99
- ## Database Setup (Prisma)
100
-
101
- 1. Configure your database URL in \`.env\`:
102
- \`\`\`
103
- DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
104
- \`\`\`
105
-
106
- 2. Edit \`prisma/schema.prisma\` to define your models
107
-
108
- 3. Generate the Prisma client and Vurb tools:
109
- \`\`\`bash
110
- npm run db:generate
111
- \`\`\`
112
-
113
- 4. Push the schema to your database:
114
- \`\`\`bash
115
- npm run db:push
116
- \`\`\`
117
-
118
- Use \`/// @vurb.hide\` on sensitive fields to strip them from the Egress Firewall.
98
+ return `
99
+ ## Database Setup (Prisma)
100
+
101
+ 1. Configure your database URL in \`.env\`:
102
+ \`\`\`
103
+ DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
104
+ \`\`\`
105
+
106
+ 2. Edit \`prisma/schema.prisma\` to define your models
107
+
108
+ 3. Generate the Prisma client and Vurb tools:
109
+ \`\`\`bash
110
+ npm run db:generate
111
+ \`\`\`
112
+
113
+ 4. Push the schema to your database:
114
+ \`\`\`bash
115
+ npm run db:push
116
+ \`\`\`
117
+
118
+ Use \`/// @vurb.hide\` on sensitive fields to strip them from the Egress Firewall.
119
119
  `;
120
120
  case 'n8n':
121
- return `
122
- ## n8n Workflow Setup
123
-
124
- 1. Configure your n8n instance in \`.env\`:
125
- \`\`\`
126
- N8N_BASE_URL=http://localhost:5678
127
- N8N_API_KEY=your-api-key
128
- \`\`\`
129
-
130
- 2. The connector in \`src/n8n.ts\` auto-discovers webhook workflows
131
- and registers them as MCP tools.
121
+ return `
122
+ ## n8n Workflow Setup
123
+
124
+ 1. Configure your n8n instance in \`.env\`:
125
+ \`\`\`
126
+ N8N_BASE_URL=http://localhost:5678
127
+ N8N_API_KEY=your-api-key
128
+ \`\`\`
129
+
130
+ 2. The connector in \`src/n8n.ts\` auto-discovers webhook workflows
131
+ and registers them as MCP tools.
132
132
  `;
133
133
  case 'openapi':
134
- return `
135
- ## OpenAPI Generator Setup
136
-
137
- 1. Replace \`openapi.yaml\` with your actual OpenAPI 3.x spec
138
-
139
- 2. Generate the MCP server from the spec:
140
- \`\`\`bash
141
- npx @vurb/openapi-gen ./openapi.yaml --outDir ./src/generated
142
- \`\`\`
143
-
144
- 3. Import and register the generated tools in \`src/server.ts\`
134
+ return `
135
+ ## OpenAPI Generator Setup
136
+
137
+ 1. Replace \`openapi.yaml\` with your actual OpenAPI 3.x spec
138
+
139
+ 2. Generate the MCP server from the spec:
140
+ \`\`\`bash
141
+ npx @vurb/openapi-gen ./openapi.yaml --outDir ./src/generated
142
+ \`\`\`
143
+
144
+ 3. Import and register the generated tools in \`src/server.ts\`
145
145
  `;
146
146
  case 'oauth':
147
- return `
148
- ## OAuth Device Flow Setup
149
-
150
- 1. Configure your OAuth provider in \`.env\`:
151
- \`\`\`
152
- OAUTH_CLIENT_ID=your-client-id
153
- OAUTH_AUTH_ENDPOINT=https://api.example.com/oauth/device/code
154
- OAUTH_TOKEN_ENDPOINT=https://api.example.com/oauth/device/token
155
- \`\`\`
156
-
157
- 2. The auth tool in \`src/auth.ts\` is pre-configured with login, complete, status, and logout actions.
158
-
159
- 3. Protect any tool with the \`withAuth\` middleware from \`src/middleware/auth.ts\`:
160
- \`\`\`ts
161
- import { withAuth } from '../middleware/auth.js';
162
-
163
- export default f.query('protected.action')
164
- .describe('A protected query')
165
- .use(withAuth)
166
- .handle(async (input, ctx) => {
167
- // ctx is authenticated
168
- });
169
- \`\`\`
147
+ return `
148
+ ## OAuth Device Flow Setup
149
+
150
+ 1. Configure your OAuth provider in \`.env\`:
151
+ \`\`\`
152
+ OAUTH_CLIENT_ID=your-client-id
153
+ OAUTH_AUTH_ENDPOINT=https://api.example.com/oauth/device/code
154
+ OAUTH_TOKEN_ENDPOINT=https://api.example.com/oauth/device/token
155
+ \`\`\`
156
+
157
+ 2. The auth tool in \`src/auth.ts\` is pre-configured with login, complete, status, and logout actions.
158
+
159
+ 3. Protect any tool with the \`withAuth\` middleware from \`src/middleware/auth.ts\`:
160
+ \`\`\`ts
161
+ import { withAuth } from '../middleware/auth.js';
162
+
163
+ export default f.query('protected.action')
164
+ .describe('A protected query')
165
+ .use(withAuth)
166
+ .handle(async (input, ctx) => {
167
+ // ctx is authenticated
168
+ });
169
+ \`\`\`
170
170
  `;
171
171
  default:
172
172
  return '';
@@ -4,98 +4,98 @@
4
4
  */
5
5
  /** Generate `vitest.config.ts` */
6
6
  export function vitestConfig() {
7
- return `import { defineConfig } from 'vitest/config';
8
-
9
- export default defineConfig({
10
- test: {
11
- include: ['tests/**/*.test.ts'],
12
- },
13
- });
7
+ return `import { defineConfig } from 'vitest/config';
8
+
9
+ export default defineConfig({
10
+ test: {
11
+ include: ['tests/**/*.test.ts'],
12
+ },
13
+ });
14
14
  `;
15
15
  }
16
16
  /** Generate `tests/setup.ts` — Test infrastructure */
17
17
  export function testSetupTs() {
18
- return `/**
19
- * Test Setup — In-Memory MVA Emulator
20
- *
21
- * Creates a VurbTester that runs the full pipeline
22
- * (Zod → Middleware → Handler → Egress Firewall)
23
- * without any network transport.
24
- *
25
- * 2ms per test. $0.00 in tokens. Zero servers.
26
- */
27
- import { fileURLToPath } from 'node:url';
28
- import { createVurbTester } from '@vurb/testing';
29
- import { autoDiscover } from '@vurb/core';
30
- import { f } from '../src/vurb.js';
31
-
32
- const registry = f.registry();
33
- await autoDiscover(registry, fileURLToPath(new URL('../src/tools', import.meta.url)));
34
-
35
- export const tester = createVurbTester(registry, {
36
- contextFactory: () => ({
37
- role: 'ADMIN' as const,
38
- tenantId: 'test-tenant',
39
- }),
40
- });
18
+ return `/**
19
+ * Test Setup — In-Memory MVA Emulator
20
+ *
21
+ * Creates a VurbTester that runs the full pipeline
22
+ * (Zod → Middleware → Handler → Egress Firewall)
23
+ * without any network transport.
24
+ *
25
+ * 2ms per test. $0.00 in tokens. Zero servers.
26
+ */
27
+ import { fileURLToPath } from 'node:url';
28
+ import { createVurbTester } from '@vurb/testing';
29
+ import { autoDiscover } from '@vurb/core';
30
+ import { f } from '../src/vurb.js';
31
+
32
+ const registry = f.registry();
33
+ await autoDiscover(registry, fileURLToPath(new URL('../src/tools', import.meta.url)));
34
+
35
+ export const tester = createVurbTester(registry, {
36
+ contextFactory: () => ({
37
+ role: 'ADMIN' as const,
38
+ tenantId: 'test-tenant',
39
+ }),
40
+ });
41
41
  `;
42
42
  }
43
43
  /** Generate `tests/system.test.ts` — Egress Firewall + RBAC tests */
44
44
  export function systemTestTs() {
45
- return `/**
46
- * System Tools — Egress Firewall & RBAC Tests
47
- *
48
- * Proves that:
49
- * 1. The Presenter strips undeclared fields (SOC2 CC6.1)
50
- * 2. RBAC middleware blocks GUEST access (SOC2 CC6.3)
51
- * 3. System rules from .describe() are injected
52
- */
53
- import { describe, it, expect } from 'vitest';
54
- import { tester } from './setup.js';
55
-
56
- describe('System Tools', () => {
57
- describe('Egress Firewall', () => {
58
- it('should return validated health data through the Presenter', async () => {
59
- const result = await tester.callAction('system', 'health');
60
-
61
- expect(result.isError).toBe(false);
62
- expect(result.data).toHaveProperty('status');
63
- expect(result.data).toHaveProperty('uptime');
64
- expect(result.data).toHaveProperty('version');
65
- expect(result.data).toHaveProperty('timestamp');
66
- });
67
-
68
- it('should strip undeclared fields (tenant must NOT leak)', async () => {
69
- const result = await tester.callAction('system', 'health');
70
-
71
- expect(result.isError).toBe(false);
72
- // The handler returns 'tenant' but the Presenter schema
73
- // does not declare it → stripped by Egress Firewall
74
- expect(result.data).not.toHaveProperty('tenant');
75
- });
76
-
77
- it('should include JIT system rules from .describe()', async () => {
78
- const result = await tester.callAction('system', 'health');
79
-
80
- expect(result.systemRules.length).toBeGreaterThan(0);
81
- expect(result.systemRules.some(
82
- (r: string) => r.includes('uptime') || r.includes('Uptime')
83
- )).toBe(true);
84
- });
85
- });
86
-
87
- describe('Echo Tool', () => {
88
- it('should echo the message back', async () => {
89
- const result = await tester.callAction('system', 'echo', {
90
- message: 'hello vurb',
91
- });
92
-
93
- expect(result.isError).toBe(false);
94
- expect(result.data).toHaveProperty('echo', 'hello vurb');
95
- expect(result.data).toHaveProperty('receivedAt');
96
- });
97
- });
98
- });
45
+ return `/**
46
+ * System Tools — Egress Firewall & RBAC Tests
47
+ *
48
+ * Proves that:
49
+ * 1. The Presenter strips undeclared fields (SOC2 CC6.1)
50
+ * 2. RBAC middleware blocks GUEST access (SOC2 CC6.3)
51
+ * 3. System rules from .describe() are injected
52
+ */
53
+ import { describe, it, expect } from 'vitest';
54
+ import { tester } from './setup.js';
55
+
56
+ describe('System Tools', () => {
57
+ describe('Egress Firewall', () => {
58
+ it('should return validated health data through the Presenter', async () => {
59
+ const result = await tester.callAction('system', 'health');
60
+
61
+ expect(result.isError).toBe(false);
62
+ expect(result.data).toHaveProperty('status');
63
+ expect(result.data).toHaveProperty('uptime');
64
+ expect(result.data).toHaveProperty('version');
65
+ expect(result.data).toHaveProperty('timestamp');
66
+ });
67
+
68
+ it('should strip undeclared fields (tenant must NOT leak)', async () => {
69
+ const result = await tester.callAction('system', 'health');
70
+
71
+ expect(result.isError).toBe(false);
72
+ // The handler returns 'tenant' but the Presenter schema
73
+ // does not declare it → stripped by Egress Firewall
74
+ expect(result.data).not.toHaveProperty('tenant');
75
+ });
76
+
77
+ it('should include JIT system rules from .describe()', async () => {
78
+ const result = await tester.callAction('system', 'health');
79
+
80
+ expect(result.systemRules.length).toBeGreaterThan(0);
81
+ expect(result.systemRules.some(
82
+ (r: string) => r.includes('uptime') || r.includes('Uptime')
83
+ )).toBe(true);
84
+ });
85
+ });
86
+
87
+ describe('Echo Tool', () => {
88
+ it('should echo the message back', async () => {
89
+ const result = await tester.callAction('system', 'echo', {
90
+ message: 'hello vurb',
91
+ });
92
+
93
+ expect(result.isError).toBe(false);
94
+ expect(result.data).toHaveProperty('echo', 'hello vurb');
95
+ expect(result.data).toHaveProperty('receivedAt');
96
+ });
97
+ });
98
+ });
99
99
  `;
100
100
  }
101
101
  //# sourceMappingURL=testing.js.map
@@ -8,56 +8,56 @@
8
8
  */
9
9
  /** Generate `src/tools/system/health.ts` — Health check with Presenter */
10
10
  export function healthToolTs() {
11
- return `/**
12
- * System Health Tool — Full MVA Pipeline (Fluent API)
13
- *
14
- * Demonstrates:
15
- * - f.query() — read-only semantic verb (auto-sets readOnlyHint)
16
- * - .describe() — LLM-facing description
17
- * - .returns() — Presenter (Egress Firewall + system rules + UI)
18
- * - .handle(input, ctx) — fully typed handler
19
- * - export default for autoDiscover()
20
- */
21
- import { f } from '../../vurb.js';
22
- import { SystemPresenter } from '../../presenters/SystemPresenter.js';
23
-
24
- export default f.query('system.health')
25
- .describe('Real-time server health status')
26
- .returns(SystemPresenter)
27
- .handle(async (_input, ctx) => {
28
- // Return raw data — the Presenter validates, strips
29
- // undeclared fields, injects rules, and renders UI.
30
- return {
31
- status: 'healthy',
32
- uptime: process.uptime(),
33
- version: '0.1.0',
34
- timestamp: new Date().toISOString(),
35
- tenant: ctx.tenantId,
36
- };
37
- });
11
+ return `/**
12
+ * System Health Tool — Full MVA Pipeline (Fluent API)
13
+ *
14
+ * Demonstrates:
15
+ * - f.query() — read-only semantic verb (auto-sets readOnlyHint)
16
+ * - .describe() — LLM-facing description
17
+ * - .returns() — Presenter (Egress Firewall + system rules + UI)
18
+ * - .handle(input, ctx) — fully typed handler
19
+ * - export default for autoDiscover()
20
+ */
21
+ import { f } from '../../vurb.js';
22
+ import { SystemPresenter } from '../../presenters/SystemPresenter.js';
23
+
24
+ export default f.query('system.health')
25
+ .describe('Real-time server health status')
26
+ .returns(SystemPresenter)
27
+ .handle(async (_input, ctx) => {
28
+ // Return raw data — the Presenter validates, strips
29
+ // undeclared fields, injects rules, and renders UI.
30
+ return {
31
+ status: 'healthy',
32
+ uptime: process.uptime(),
33
+ version: '0.1.0',
34
+ timestamp: new Date().toISOString(),
35
+ tenant: ctx.tenantId,
36
+ };
37
+ });
38
38
  `;
39
39
  }
40
40
  /** Generate `src/tools/system/echo.ts` — Simple echo tool */
41
41
  export function echoToolTs() {
42
- return `/**
43
- * Echo Tool — Connectivity Testing (Fluent API)
44
- *
45
- * Demonstrates:
46
- * - f.query() with .withString() typed parameter
47
- * - .handle(input, ctx) — input.message is typed as string
48
- * - Implicit success() wrapping — return raw data, framework wraps it
49
- */
50
- import { f } from '../../vurb.js';
51
-
52
- export default f.query('system.echo')
53
- .describe('Echo a message back (connectivity test)')
54
- .withString('message', 'Message to echo back')
55
- .handle(async (input) => {
56
- return {
57
- echo: input['message'],
58
- receivedAt: new Date().toISOString(),
59
- };
60
- });
42
+ return `/**
43
+ * Echo Tool — Connectivity Testing (Fluent API)
44
+ *
45
+ * Demonstrates:
46
+ * - f.query() with .withString() typed parameter
47
+ * - .handle(input, ctx) — input.message is typed as string
48
+ * - Implicit success() wrapping — return raw data, framework wraps it
49
+ */
50
+ import { f } from '../../vurb.js';
51
+
52
+ export default f.query('system.echo')
53
+ .describe('Echo a message back (connectivity test)')
54
+ .withString('message', 'Message to echo back')
55
+ .handle(async (input) => {
56
+ return {
57
+ echo: input['message'],
58
+ receivedAt: new Date().toISOString(),
59
+ };
60
+ });
61
61
  `;
62
62
  }
63
63
  //# sourceMappingURL=tools.js.map