@jaypie/mcp 0.8.38 → 0.8.40

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.
@@ -9,7 +9,7 @@ import { gt } from 'semver';
9
9
  /**
10
10
  * Docs Suite - Documentation services (skill, version, release_notes)
11
11
  */
12
- const BUILD_VERSION_STRING = "@jaypie/mcp@0.8.38#ff8c48d7"
12
+ const BUILD_VERSION_STRING = "@jaypie/mcp@0.8.40#d3b7b298"
13
13
  ;
14
14
  const __filename$1 = fileURLToPath(import.meta.url);
15
15
  const __dirname$1 = path.dirname(__filename$1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jaypie/mcp",
3
- "version": "0.8.38",
3
+ "version": "0.8.40",
4
4
  "description": "Jaypie MCP",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,17 @@
1
+ ---
2
+ version: 1.2.48
3
+ date: 2026-04-17
4
+ summary: Add managedRuleScopeDowns to JaypieWafConfig
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - `JaypieDistribution` WAF config now accepts `managedRuleScopeDowns?: Record<string, CfnWebACL.StatementProperty>`, allowing any managed rule group to be narrowed to a specific URL pattern (or any other WAFv2 statement shape).
10
+ - Keyed by managed rule group name, parallel to `managedRuleOverrides`.
11
+ - Use case: scope `AWSManagedRulesCommonRuleSet` away from `/chat` paths so large chat request bodies don't collide with `SizeRestrictions_BODY` without weakening protection globally.
12
+
13
+ ## Skills
14
+
15
+ - ~cdk — WAF section adds a `managedRuleScopeDowns` example alongside the existing `managedRuleOverrides` one.
16
+
17
+ Closes #306.
@@ -0,0 +1,23 @@
1
+ ---
2
+ version: 1.2.49
3
+ date: 2026-04-18
4
+ summary: Consolidate JaypieHostedZone Route53 query log resource policy into a single stack-level singleton
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - `JaypieHostedZone` no longer creates a per-zone `AWS::Logs::ResourcePolicy`. A single stack-level `CfnResourcePolicy` with a wildcard resource ARN (`arn:<partition>:logs:<region>:<account>:log-group:/aws/route53/*:*`) now grants Route53 permission to write query logs to every zone in the stack.
10
+ - New `queryLoggingPolicy?: boolean` prop (default `true`). Set to `false` to skip the managed policy when provisioning an account-wide policy externally (useful for accounts with many small stacks each owning a hosted zone).
11
+ - New `ensureRoute53QueryLoggingPolicy(scope)` helper exported from `@jaypie/constructs` for custom constructs that need the same stack-level singleton.
12
+
13
+ ## Motivation
14
+
15
+ CloudWatch Logs enforces a 10-resource-policy-per-region account quota. The previous per-zone `grantWrite` call produced one policy per zone, so the 11th zone in a region failed to deploy with `ServiceLimitExceeded`.
16
+
17
+ ## Deploy Caveats
18
+
19
+ - **Under the limit (< 10 zones per stack)**: CloudFormation swaps N per-zone policies for 1 consolidated policy on next deploy. A brief gap in Route53 query-log permissions is possible during the change window.
20
+ - **At or past the 10-per-region limit**: CloudFormation does not guarantee delete-before-create across unrelated logical IDs. Creating the new consolidated policy may fail while the legacy per-zone policies still exist. Before deploying, manually delete one or more legacy `/aws/route53/*` resource policies to create headroom, then deploy.
21
+ - **Many small stacks (1 zone each)**: The stack-level singleton still yields N policies across N stacks. Set `queryLoggingPolicy: false` on every zone and manage one account-wide policy externally.
22
+
23
+ Closes #311.
@@ -0,0 +1,25 @@
1
+ ---
2
+ version: 1.2.22
3
+ date: 2026-04-17
4
+ summary: Add fabricApiResponse helper and expressHandler fabric option
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - New export `fabricApiResponse(value)` wraps a value in the canonical Jaypie API envelope:
10
+ - `null` / `undefined` → `{ data: null }`
11
+ - `{ data }` with exactly one key → passthrough
12
+ - `{ errors }` with exactly one key → passthrough
13
+ - anything else (including `{ data, other }`) → `{ data: value }`
14
+ - New `expressHandler` option `{ fabric: true }` applies `fabricApiResponse` to the handler's return value before `res.json()`, removing the `apiResponse(await service())` boilerplate.
15
+
16
+ ## Why
17
+
18
+ The `skill("api")` envelope contract says a response contains either `data` or `errors`, never both, and no other top-level keys. The helper and handler option make conforming to that contract the easy path.
19
+
20
+ ## Skills
21
+
22
+ - ~express — Handler Options block documents the new `fabric` flag; new "fabricApiResponse and `{ fabric: true }`" section covers the helper and wrap rules.
23
+ - ~handlers — Express handler example now shows `{ fabric: true }` as the recommended envelope path.
24
+
25
+ Closes #309.
@@ -0,0 +1,23 @@
1
+ ---
2
+ version: 0.3.2
3
+ date: 2026-04-17
4
+ summary: fabricExpress integrates expressHandler lifecycle
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - `FabricExpressConfig` now accepts the full set of `expressHandler` lifecycle options: `chaos`, `locals`, `name`, `secrets`, `setup`, `teardown`, `unavailable`, `validate`.
10
+ - `fabricExpress` wraps the inner middleware with `expressHandler` so per-request lifecycle (secrets loading, setup/teardown, validate, unavailable, locals, observability) runs automatically — matching `fabricLambda` / `fabricWebSocket` adapter patterns.
11
+ - Inner middleware still calls `res.json` / `res.status` / `res.send` directly; `expressHandler` captures these as illegal calls and replays them after postprocess, preserving existing envelope and 405/204 behavior.
12
+
13
+ ## Peer dependencies
14
+
15
+ - Adds `@jaypie/express` as an optional peer dependency (alongside `@jaypie/lambda`).
16
+
17
+ ## Why
18
+
19
+ Previously `fabricExpress` was a plain middleware — an asymmetry with `fabricLambda` (wraps `lambdaHandler`) and `fabricWebSocket` (wraps `websocketHandler`). Consumers had to stack `expressHandler(fabricExpress(...))` themselves to get lifecycle, defeating convenience. This change makes lifecycle the default.
20
+
21
+ ## Skills
22
+
23
+ - ~fabric — Adapters section adds an Express Middleware example covering `fabricHttp` + `fabricExpress` + `FabricRouter`, including lifecycle pass-through.
@@ -0,0 +1,11 @@
1
+ ---
2
+ version: 1.2.40
3
+ date: 2026-04-17
4
+ summary: Bump @jaypie/express and @jaypie/llm deps
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - Dependency bumps:
10
+ - `@jaypie/express` ^1.2.21 → ^1.2.22 (`fabricApiResponse` helper, `{ fabric: true }` handler option)
11
+ - `@jaypie/llm` ^1.2.28 → ^1.2.29 (peer; xAI retries transient ingest-bytes 400s)
@@ -0,0 +1,16 @@
1
+ ---
2
+ version: 1.2.29
3
+ date: 2026-04-17
4
+ summary: xAI adapter retries transient "failed to ingest inline file bytes" 400s
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - `XaiAdapter` now overrides `classifyError` to mark HTTP 400 responses whose message contains `"failed to ingest inline file bytes"` as retryable. The existing exponential-backoff retry loop then retries them (same pattern as transient-network retries).
10
+ - Unrelated `BadRequestError`s remain non-retryable — they fall through to the parent OpenAI-compatible classifier.
11
+
12
+ ## Why
13
+
14
+ xAI's media-ingest service enters a bad state after ~12 consecutive file-bearing calls and self-clears after a short pause. Previously these 400s were terminal, losing all downstream work in a batch; they're now transparently retried.
15
+
16
+ Closes #301.
@@ -0,0 +1,23 @@
1
+ ---
2
+ version: 0.8.39
3
+ date: 2026-04-17
4
+ summary: Add release notes for the #301/#306/#309 + fabricExpress lifecycle batch
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ Added release notes for:
10
+
11
+ - `@jaypie/constructs@1.2.48` (#306 — WAF scopeDownStatement)
12
+ - `@jaypie/express@1.2.22` (#309 — fabricApiResponse + fabric option)
13
+ - `@jaypie/fabric@0.3.2` (fabricExpress wraps expressHandler)
14
+ - `@jaypie/llm@1.2.29` (#301 — xAI ingest-bytes retry)
15
+ - `@jaypie/testkit@1.2.35` (mock fabricApiResponse)
16
+ - `jaypie@1.2.40` (dependency bumps)
17
+
18
+ ## Skills updated
19
+
20
+ - ~cdk — WAF section adds `managedRuleScopeDowns` example.
21
+ - ~express — documents `fabric` option and `fabricApiResponse` helper.
22
+ - ~fabric — Adapters section adds Express Middleware / FabricRouter example with lifecycle pass-through.
23
+ - ~handlers — Express handler example uses `{ fabric: true }`.
@@ -0,0 +1,9 @@
1
+ ---
2
+ version: 0.8.40
3
+ date: 2026-04-18
4
+ summary: Include @jaypie/constructs 1.2.49 release notes
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - Adds release notes for `@jaypie/constructs` 1.2.49 (consolidated Route53 query log resource policy).
@@ -0,0 +1,9 @@
1
+ ---
2
+ version: 1.2.35
3
+ date: 2026-04-17
4
+ summary: Mock fabricApiResponse from @jaypie/express
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - Added a mock for `fabricApiResponse` (new export in `@jaypie/express@1.2.22`) so consumers get a wrapped mock via `@jaypie/testkit/mock` alongside `cors`, `expressHandler`, etc.
package/skills/cdk.md CHANGED
@@ -359,6 +359,31 @@ new JaypieDistribution(this, "Dist", {
359
359
  },
360
360
  },
361
361
  });
362
+
363
+ // Scope a managed rule group to (or away from) specific URL patterns
364
+ new JaypieDistribution(this, "Dist", {
365
+ handler,
366
+ waf: {
367
+ name: "api",
368
+ managedRuleScopeDowns: {
369
+ // Only run the CommonRuleSet for paths OTHER than /chat — lets /chat
370
+ // handle large AI-generated request bodies without weakening protection
371
+ // elsewhere.
372
+ AWSManagedRulesCommonRuleSet: {
373
+ notStatement: {
374
+ statement: {
375
+ byteMatchStatement: {
376
+ fieldToMatch: { uriPath: {} },
377
+ positionalConstraint: "STARTS_WITH",
378
+ searchString: "/chat",
379
+ textTransformations: [{ priority: 0, type: "NONE" }],
380
+ },
381
+ },
382
+ },
383
+ },
384
+ },
385
+ },
386
+ });
362
387
  ```
363
388
 
364
389
  Cost: $5/month per WebACL + $1/month per rule + $0.60 per million requests. Use `waf: false` to opt out.
package/skills/express.md CHANGED
@@ -46,8 +46,10 @@ app.get("/api/users", expressHandler(async (req, res) => {
46
46
 
47
47
  ```typescript
48
48
  expressHandler(handler, {
49
+ fabric: false, // Wrap return with fabricApiResponse before res.json (default false)
49
50
  locals: {}, // Values passed to res.locals
50
51
  name: "handler", // Handler name for logging
52
+ secrets: [], // AWS Secrets names to load into process.env
51
53
  setup: async (req, res) => {}, // Pre-handler setup
52
54
  teardown: async (req, res) => {}, // Post-handler cleanup
53
55
  unavailable: false, // Return 503 immediately if true
@@ -55,6 +57,29 @@ expressHandler(handler, {
55
57
  });
56
58
  ```
57
59
 
60
+ ### fabricApiResponse and `{ fabric: true }`
61
+
62
+ Return plain domain objects and opt into the canonical Jaypie API envelope:
63
+
64
+ ```typescript
65
+ import { expressHandler, fabricApiResponse } from "jaypie";
66
+
67
+ // Handler option — wraps the return value automatically
68
+ app.get(
69
+ "/ping",
70
+ expressHandler(async (req) => ping(req.query), { fabric: true }),
71
+ );
72
+
73
+ // Standalone helper — same rules as `{ fabric: true }`
74
+ fabricApiResponse({ id: "1" }); // { data: { id: "1" } }
75
+ fabricApiResponse([{ id: "1" }]); // { data: [{ id: "1" }] }
76
+ fabricApiResponse({ data: {...} }); // passthrough
77
+ fabricApiResponse({ errors: [...] }); // passthrough
78
+ fabricApiResponse(null); // { data: null }
79
+ ```
80
+
81
+ Wrap rules: only `{ data }` alone or `{ errors }` alone pass through. Anything else (including `{ data, other }`) gets wrapped as `{ data: value }`.
82
+
58
83
  ## Lambda Adapter
59
84
 
60
85
  Convert Express apps to Lambda handlers:
package/skills/fabric.md CHANGED
@@ -77,6 +77,37 @@ const tools = [fabricLlmTool(greetService)];
77
77
  // Available to LLM as function call
78
78
  ```
79
79
 
80
+ ### Express Middleware
81
+
82
+ ```typescript
83
+ import { fabricHttp } from "@jaypie/fabric/http";
84
+ import { fabricExpress, FabricRouter } from "@jaypie/fabric/express";
85
+
86
+ // Wrap service with fabricHttp first (HTTP context + default input transform)
87
+ const greetHttp = fabricHttp({ service: greetService });
88
+
89
+ // Single-route middleware — alias becomes default path ("/greet")
90
+ app.get("/greet", fabricExpress({ service: greetHttp }));
91
+
92
+ // Lifecycle pass-through (forwarded to expressHandler): secrets, setup,
93
+ // teardown, validate, unavailable, locals, name, chaos
94
+ app.post(
95
+ "/records",
96
+ fabricExpress({
97
+ service: recordsHttp,
98
+ secrets: ["MONGODB_URI"],
99
+ setup: async (req) => { /* ... */ },
100
+ }),
101
+ );
102
+
103
+ // Multi-service router — alias-derived paths under a prefix
104
+ app.use(FabricRouter({ services: [greetHttp, searchHttp], prefix: "/api" }));
105
+ ```
106
+
107
+ `fabricExpress` wraps the middleware with `expressHandler` internally, so
108
+ per-route lifecycle and observability come along for the ride (parallel to
109
+ `fabricLambda` → `lambdaHandler` and `fabricWebSocket` → `websocketHandler`).
110
+
80
111
  ## Service Suites
81
112
 
82
113
  Group related services:
@@ -90,6 +90,13 @@ app.get("/api/users", expressHandler(async (req, res) => {
90
90
  return { users: [] };
91
91
  }));
92
92
 
93
+ // Return plain domain objects and let `{ fabric: true }` apply the
94
+ // canonical Jaypie `{ data }` envelope automatically.
95
+ app.get(
96
+ "/ping",
97
+ expressHandler(async (req) => ping(req.query), { fabric: true }),
98
+ );
99
+
93
100
  // Convert Express app to Lambda
94
101
  export const handler = createLambdaHandler(app);
95
102
  ```