@classytic/arc 2.4.3 → 2.6.1

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.
Files changed (78) hide show
  1. package/README.md +22 -6
  2. package/dist/{BaseController-CkM5dUh_.mjs → BaseController-AbbRx3e0.mjs} +5 -2
  3. package/dist/adapters/index.d.mts +2 -2
  4. package/dist/adapters/index.mjs +1 -1
  5. package/dist/{adapters-DTC4Ug66.mjs → adapters-CTn28N4y.mjs} +72 -11
  6. package/dist/audit/index.d.mts +1 -1
  7. package/dist/audit/index.mjs +11 -1
  8. package/dist/audit/mongodb.d.mts +1 -1
  9. package/dist/auth/index.d.mts +1 -1
  10. package/dist/auth/index.mjs +2 -2
  11. package/dist/cli/commands/init.mjs +12 -9
  12. package/dist/core/index.d.mts +2 -2
  13. package/dist/core/index.mjs +2 -2
  14. package/dist/{createApp-CBgVaFyh.mjs → createApp-Bol7DLUf.mjs} +404 -279
  15. package/dist/{defineResource-B22gcNvn.mjs → defineResource-bVKHjQzE.mjs} +116 -19
  16. package/dist/discovery/index.mjs +1 -1
  17. package/dist/docs/index.d.mts +1 -1
  18. package/dist/dynamic/index.d.mts +1 -1
  19. package/dist/dynamic/index.mjs +2 -2
  20. package/dist/{elevation-Ca_yveIO.d.mts → elevation-C_taLQrM.d.mts} +27 -1
  21. package/dist/{errorHandler-DMbGdzBG.mjs → errorHandler-r2595m8T.mjs} +1 -1
  22. package/dist/{errors-CPpvPHT0.d.mts → errors-CcVbl1-T.d.mts} +17 -1
  23. package/dist/{errors-rxhfP7Hf.mjs → errors-NoQKsbAT.mjs} +23 -1
  24. package/dist/{eventPlugin-iGrSEmwJ.d.mts → eventPlugin-DW45v4V5.d.mts} +30 -2
  25. package/dist/events/index.d.mts +2 -2
  26. package/dist/events/index.mjs +40 -10
  27. package/dist/factory/index.d.mts +44 -23
  28. package/dist/factory/index.mjs +136 -2
  29. package/dist/hooks/index.d.mts +1 -1
  30. package/dist/idempotency/index.d.mts +3 -3
  31. package/dist/idempotency/mongodb.d.mts +1 -1
  32. package/dist/idempotency/redis.d.mts +1 -1
  33. package/dist/{index-yhxyjqNb.d.mts → index-BIsZ_su5.d.mts} +4 -8
  34. package/dist/{index-BL8CaQih.d.mts → index-Cb3gtbg7.d.mts} +2 -2
  35. package/dist/{index-Diqcm14c.d.mts → index-NGZksqM5.d.mts} +30 -1
  36. package/dist/index.d.mts +6 -6
  37. package/dist/index.mjs +8 -7
  38. package/dist/integrations/event-gateway.mjs +1 -1
  39. package/dist/integrations/index.d.mts +1 -1
  40. package/dist/integrations/mcp/index.d.mts +4 -2
  41. package/dist/integrations/mcp/index.mjs +1 -1
  42. package/dist/integrations/mcp/testing.d.mts +1 -1
  43. package/dist/integrations/mcp/testing.mjs +1 -1
  44. package/dist/{interface-DGmPxakH.d.mts → interface-DDW43OmS.d.mts} +194 -13
  45. package/dist/{mongodb-CUpYfxfD.d.mts → mongodb-kltrBPa1.d.mts} +10 -0
  46. package/dist/{mongodb-bga9AbkD.d.mts → mongodb-pMvOlR5_.d.mts} +1 -1
  47. package/dist/org/index.d.mts +1 -1
  48. package/dist/org/index.mjs +1 -1
  49. package/dist/permissions/index.d.mts +2 -2
  50. package/dist/permissions/index.mjs +2 -2
  51. package/dist/{permissions-Jk5x3sxz.mjs → permissions-C8ImI8gC.mjs} +44 -2
  52. package/dist/plugins/index.d.mts +1 -1
  53. package/dist/plugins/index.mjs +3 -3
  54. package/dist/plugins/tracing-entry.mjs +1 -1
  55. package/dist/presets/index.d.mts +1 -1
  56. package/dist/presets/index.mjs +1 -1
  57. package/dist/presets/multiTenant.d.mts +1 -1
  58. package/dist/presets/multiTenant.mjs +1 -1
  59. package/dist/{presets-OMPaHMTY.mjs → presets-BMfdy34e.mjs} +2 -2
  60. package/dist/{redis-CQ5YxMC5.d.mts → redis-D0Qc-9EW.d.mts} +1 -1
  61. package/dist/registry/index.d.mts +1 -1
  62. package/dist/{resourceToTools-PMFE8HIv.mjs → resourceToTools-DH3c3e-T.mjs} +81 -7
  63. package/dist/scope/index.d.mts +2 -2
  64. package/dist/scope/index.mjs +2 -2
  65. package/dist/{sse-BkViJPlT.mjs → sse-BF7GR7IB.mjs} +1 -1
  66. package/dist/testing/index.d.mts +2 -2
  67. package/dist/testing/index.mjs +1 -1
  68. package/dist/types/index.d.mts +3 -3
  69. package/dist/types/index.mjs +23 -2
  70. package/dist/{types-C6TQjtdi.mjs → types-BhtYdxZU.mjs} +26 -1
  71. package/dist/{types-Dt0-AI6E.d.mts → types-D5hJ-k_3.d.mts} +189 -6
  72. package/dist/{types-BJmgxNbF.d.mts → types-D5rjsS_i.d.mts} +1 -1
  73. package/dist/utils/index.d.mts +2 -2
  74. package/dist/utils/index.mjs +1 -1
  75. package/package.json +6 -5
  76. package/skills/arc/SKILL.md +104 -4
  77. package/skills/arc/references/mcp.md +160 -2
  78. /package/dist/{interface-B4awm1RJ.d.mts → interface-gr-7qo9j.d.mts} +0 -0
@@ -12,11 +12,34 @@ npm install @modelcontextprotocol/sdk zod
12
12
 
13
13
  ```typescript
14
14
  import { mcpPlugin } from '@classytic/arc/mcp';
15
+ import { createApp, loadResources } from '@classytic/arc/factory';
15
16
 
16
- await app.register(mcpPlugin, {
17
+ // Option A: Explicit resources
18
+ const app = await createApp({
17
19
  resources: [productResource, taskResource],
18
20
  auth: false,
19
- exclude: ['credential'],
21
+ plugins: async (f) => {
22
+ await f.register(mcpPlugin, { resources: [productResource, taskResource], auth: false });
23
+ },
24
+ });
25
+
26
+ // Option B: Auto-discover from directory
27
+ const resources = await loadResources('./src/resources');
28
+ const app = await createApp({
29
+ resources,
30
+ plugins: async (f) => {
31
+ await f.register(mcpPlugin, { resources, auth: false });
32
+ },
33
+ });
34
+ ```
35
+
36
+ Per-resource overrides:
37
+
38
+ ```typescript
39
+ await app.register(mcpPlugin, {
40
+ resources,
41
+ auth: false,
42
+ include: ['product', 'order'], // only these get MCP tools
20
43
  overrides: { product: { operations: ['list', 'get'] } },
21
44
  });
22
45
  ```
@@ -429,3 +452,138 @@ await app.register(mcpPlugin, {
429
452
  - `DELETE /mcp` — terminates session
430
453
 
431
454
  Sessions: lazily created, TTL-cached, LRU-evicted at max capacity, auto-cleaned on shutdown.
455
+
456
+ ## Health Endpoint
457
+
458
+ `GET /mcp/health` — no MCP protocol needed, plain JSON:
459
+
460
+ ```json
461
+ {
462
+ "status": "ok",
463
+ "mode": "stateless",
464
+ "tools": 11,
465
+ "resources": 2,
466
+ "toolNames": ["list_products", "get_product", ...],
467
+ "sessions": null
468
+ }
469
+ ```
470
+
471
+ Use to verify the MCP server is alive before configuring Claude CLI.
472
+
473
+ ## DX Helpers (v2.4.4)
474
+
475
+ ### ArcRequest — Typed Fastify Request
476
+
477
+ For `wrapHandler: false` routes, use `ArcRequest` instead of `(req as any).user`:
478
+
479
+ ```typescript
480
+ import type { ArcRequest } from '@classytic/arc';
481
+
482
+ handler: async (req: ArcRequest, reply) => {
483
+ req.user?.id; // typed
484
+ req.scope.organizationId; // typed (when member)
485
+ req.signal; // AbortSignal (Fastify 5 built-in)
486
+ }
487
+ ```
488
+
489
+ ### envelope() — Response Helper
490
+
491
+ ```typescript
492
+ import { envelope } from '@classytic/arc';
493
+
494
+ handler: async (req, reply) => {
495
+ const data = await service.getResults();
496
+ return reply.send(envelope(data));
497
+ // → { success: true, data }
498
+ return reply.send(envelope(data, { total: 100, page: 1 }));
499
+ // → { success: true, data, total: 100, page: 1 }
500
+ }
501
+ ```
502
+
503
+ ### getOrgContext() — Canonical Org Extraction
504
+
505
+ Eliminates duplicated `req.user.organizationId || req.headers['x-organization-id']` patterns:
506
+
507
+ ```typescript
508
+ import { getOrgContext } from '@classytic/arc/scope';
509
+
510
+ handler: async (req, reply) => {
511
+ const { userId, organizationId, roles, orgRoles } = getOrgContext(req);
512
+ // Works regardless of auth type (JWT, Better Auth, custom)
513
+ }
514
+ ```
515
+
516
+ ### createDomainError() — Error Factory
517
+
518
+ Eliminates manual `if (err.code) return status` mapping:
519
+
520
+ ```typescript
521
+ import { createDomainError } from '@classytic/arc';
522
+
523
+ throw createDomainError('MEMBER_NOT_FOUND', 'Member does not exist', 404);
524
+ throw createDomainError('SELF_REFERRAL', 'Cannot refer yourself', 422);
525
+ throw createDomainError('INSUFFICIENT_BALANCE', 'Not enough credits', 402, { balance: 0 });
526
+ // Arc's error handler auto-maps statusCode to HTTP response
527
+ ```
528
+
529
+ ### onRegister — Resource Lifecycle Hook
530
+
531
+ Called during plugin registration with the scoped Fastify instance:
532
+
533
+ ```typescript
534
+ defineResource({
535
+ name: 'notification',
536
+ onRegister: (fastify) => {
537
+ setSseManager(fastify.sseManager);
538
+ },
539
+ })
540
+ ```
541
+
542
+ ### preAuth — Pre-Auth Handlers for SSE/WebSocket
543
+
544
+ Run before auth middleware. Use for promoting `?token=` to `Authorization` header (EventSource can't set headers):
545
+
546
+ ```typescript
547
+ additionalRoutes: [{
548
+ method: 'GET',
549
+ path: '/stream',
550
+ wrapHandler: false,
551
+ permissions: requireAuth(),
552
+ preAuth: [(req) => {
553
+ const token = req.query?.token;
554
+ if (token) req.headers.authorization = `Bearer ${token}`;
555
+ }],
556
+ handler: sseHandler,
557
+ }]
558
+ ```
559
+
560
+ ### streamResponse — SSE Route Flag
561
+
562
+ Auto-sets SSE headers and bypasses Arc's response wrapper:
563
+
564
+ ```typescript
565
+ additionalRoutes: [{
566
+ method: 'POST',
567
+ path: '/stream',
568
+ streamResponse: true, // SSE headers + no { success, data } wrapper
569
+ permissions: requireAuth(),
570
+ handler: async (request, reply) => {
571
+ const { stream } = await generateStream({ abortSignal: request.signal });
572
+ return reply.send(stream);
573
+ },
574
+ }]
575
+ ```
576
+
577
+ ## Test Coverage
578
+
579
+ 165 test files, 2439 tests. MCP-specific:
580
+
581
+ | Test File | Tests | Covers |
582
+ |-----------|-------|--------|
583
+ | `mcp-auth-e2e.test.ts` | 16 | All auth modes, multi-tenancy, permission filters, async permissions |
584
+ | `mcp-dx-features.test.ts` | 14 | include, names, prefix, disableDefaultRoutes, mcpHandler, guards, CRUD lifecycle |
585
+ | `resourceToTools.test.ts` | 12 | Tool generation, annotations, field hiding, soft delete |
586
+ | `createMcpServer.test.ts` | 10 | Server creation, tool registration, InMemoryTransport |
587
+ | `guards.test.ts` | 8 | requireAuth, requireOrg, requireRole, customGuard, composition |
588
+ | `dx-features.test.ts` | 17 | envelope, getOrgContext, createDomainError, onRegister, preAuth, streamResponse |
589
+ | Others | 32 | fieldRulesToZod, defineTool, definePrompt, buildRequestContext, sessionCache, authCache |