@jaypie/mcp 0.2.8 → 0.2.9

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.
package/dist/index.js CHANGED
@@ -885,7 +885,7 @@ function listLlmProviders() {
885
885
  };
886
886
  }
887
887
 
888
- const BUILD_VERSION_STRING = "@jaypie/mcp@0.2.8"
888
+ const BUILD_VERSION_STRING = "@jaypie/mcp@0.2.9#f022ac30"
889
889
  ;
890
890
  const __filename$1 = fileURLToPath(import.meta.url);
891
891
  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.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "Jaypie MCP",
5
5
  "repository": {
6
6
  "type": "git",
@@ -102,54 +102,52 @@ Preconfigured with API-optimized timeouts and role tags.
102
102
 
103
103
  ### Streaming Lambda Functions
104
104
 
105
- Enable Lambda Response Streaming via Function URLs for real-time SSE responses:
105
+ Use `JaypieStreamingLambda` for Express apps with AWS Lambda Web Adapter and streaming support:
106
106
 
107
107
  ```typescript
108
- import { FunctionUrlAuthType, InvokeMode } from "aws-cdk-lib/aws-lambda";
109
-
110
- const streamingLambda = new JaypieLambda(this, "StreamingFunction", {
111
- code: "dist",
112
- handler: "stream.handler",
113
- timeout: Duration.minutes(5), // Longer timeout for streaming
108
+ import { JaypieStreamingLambda, JaypieDistribution } from "@jaypie/constructs";
109
+
110
+ // Create streaming Lambda with Web Adapter
111
+ const streamingLambda = new JaypieStreamingLambda(this, "StreamingApi", {
112
+ code: "dist/api",
113
+ handler: "run.sh", // Shell script to start Express app
114
+ streaming: true, // Enables RESPONSE_STREAM invoke mode
115
+ port: 8000, // Port your app listens on (default: 8000)
114
116
  });
115
117
 
116
- // Add Function URL with streaming enabled
117
- const functionUrl = streamingLambda.addFunctionUrl({
118
- authType: FunctionUrlAuthType.NONE, // Public access
119
- // authType: FunctionUrlAuthType.AWS_IAM, // IAM authentication
120
- invokeMode: InvokeMode.RESPONSE_STREAM, // Enable streaming
121
- });
122
-
123
- // Output the URL
124
- new cdk.CfnOutput(this, "StreamingUrl", {
125
- value: functionUrl.url,
118
+ // CloudFront auto-detects invokeMode from JaypieStreamingLambda
119
+ new JaypieDistribution(this, "Distribution", {
120
+ handler: streamingLambda,
121
+ host: "api.example.com",
122
+ zone: "example.com",
126
123
  });
127
124
  ```
128
125
 
129
126
  Features:
130
- - `RESPONSE_STREAM` invoke mode enables real-time streaming
131
- - Works with `lambdaStreamHandler` from `@jaypie/lambda`
132
- - Use `FunctionUrlAuthType.AWS_IAM` for authenticated endpoints
133
- - Combine with API Gateway for custom domains via `JaypieApiGateway`
127
+ - Automatically adds AWS Lambda Web Adapter layer (supports ARM64 and x86_64)
128
+ - Sets `AWS_LAMBDA_EXEC_WRAPPER` and `AWS_LWA_INVOKE_MODE` environment variables
129
+ - Exposes `invokeMode` property for auto-detection by `JaypieDistribution`
130
+ - Use `streaming: false` for buffered mode (traditional Lambda behavior)
134
131
 
135
- For Express-based streaming with custom domains:
132
+ For direct Function URL access (bypass CloudFront):
136
133
  ```typescript
137
- // Express app with streaming routes
138
- const expressLambda = new JaypieExpressLambda(this, "ExpressStream", {
134
+ import { FunctionUrlAuthType, InvokeMode } from "aws-cdk-lib/aws-lambda";
135
+
136
+ const streamingLambda = new JaypieLambda(this, "StreamingFunction", {
139
137
  code: "dist",
140
- handler: "app.handler",
138
+ handler: "stream.handler",
141
139
  timeout: Duration.minutes(5),
142
140
  });
143
141
 
144
- // API Gateway handles the domain routing
145
- new JaypieApiGateway(this, "Api", {
146
- handler: expressLambda,
147
- host: "api.example.com",
148
- zone: "example.com",
142
+ const functionUrl = streamingLambda.addFunctionUrl({
143
+ authType: FunctionUrlAuthType.NONE,
144
+ invokeMode: InvokeMode.RESPONSE_STREAM,
149
145
  });
146
+
147
+ new cdk.CfnOutput(this, "StreamingUrl", { value: functionUrl.url });
150
148
  ```
151
149
 
152
- Note: API Gateway has a 29-second timeout limit. For longer streaming operations, use Function URLs directly.
150
+ Note: API Gateway has a 29-second timeout limit. For longer streaming operations, use Function URLs or CloudFront with Lambda Function URLs.
153
151
 
154
152
  ### Stack Types
155
153
 
@@ -430,6 +430,99 @@ try {
430
430
  }
431
431
  ```
432
432
 
433
+ ## Seed and Export Utilities
434
+
435
+ Idempotent seeding and data export for migrations and bootstrapping.
436
+
437
+ ### seedEntityIfNotExists
438
+
439
+ Seed a single entity if it doesn't already exist (checked by alias):
440
+
441
+ ```typescript
442
+ import { APEX, seedEntityIfNotExists } from "@jaypie/dynamodb";
443
+
444
+ const created = await seedEntityIfNotExists({
445
+ alias: "config-main",
446
+ model: "config",
447
+ name: "Main Configuration",
448
+ ou: APEX,
449
+ });
450
+ // Returns true if created, false if already exists
451
+ ```
452
+
453
+ ### seedEntities
454
+
455
+ Seed multiple entities with idempotency:
456
+
457
+ ```typescript
458
+ import { APEX, seedEntities } from "@jaypie/dynamodb";
459
+
460
+ const result = await seedEntities([
461
+ { alias: "vocab-en", model: "vocabulary", name: "English", ou: APEX },
462
+ { alias: "vocab-es", model: "vocabulary", name: "Spanish", ou: APEX },
463
+ ]);
464
+ // result.created: aliases of created entities
465
+ // result.skipped: aliases of entities that already existed
466
+ // result.errors: { alias, error } for failed operations
467
+
468
+ // Dry run (preview without writing)
469
+ const preview = await seedEntities(entities, { dryRun: true });
470
+
471
+ // Replace existing entities
472
+ await seedEntities(entities, { replace: true });
473
+ ```
474
+
475
+ Auto-generates `id` (UUID), `createdAt`, `updatedAt`, and `sequence` if missing.
476
+
477
+ ### exportEntities
478
+
479
+ Export entities by model and organizational unit:
480
+
481
+ ```typescript
482
+ import { APEX, exportEntities } from "@jaypie/dynamodb";
483
+
484
+ const { entities, count } = await exportEntities("vocabulary", APEX);
485
+ // entities: FabricEntity[] sorted by sequence ascending
486
+ // count: number of entities
487
+
488
+ // With limit
489
+ const { entities: limited } = await exportEntities("vocabulary", APEX, 100);
490
+ ```
491
+
492
+ ### exportEntitiesToJson
493
+
494
+ Export as JSON string:
495
+
496
+ ```typescript
497
+ import { APEX, exportEntitiesToJson } from "@jaypie/dynamodb";
498
+
499
+ const json = await exportEntitiesToJson("vocabulary", APEX);
500
+ // Pretty printed by default
501
+
502
+ const compact = await exportEntitiesToJson("vocabulary", APEX, false);
503
+ // Compact JSON
504
+ ```
505
+
506
+ ### SeedResult Interface
507
+
508
+ ```typescript
509
+ interface SeedResult {
510
+ created: string[]; // Aliases of created entities
511
+ skipped: string[]; // Aliases of skipped entities (already exist)
512
+ errors: Array<{ alias: string; error: string }>;
513
+ }
514
+
515
+ interface SeedOptions {
516
+ replace?: boolean; // Overwrite existing (default: false)
517
+ dryRun?: boolean; // Preview without writing (default: false)
518
+ }
519
+
520
+ interface ExportResult<T extends FabricEntity = FabricEntity> {
521
+ entities: T[]; // Exported entities
522
+ count: number; // Number of entities
523
+ }
524
+ ```
525
+
433
526
  ## Testing
434
527
 
435
528
  Mock implementations in `@jaypie/testkit`:
@@ -445,9 +538,17 @@ vi.mock("@jaypie/dynamodb", async () => {
445
538
  // Key builders and indexEntity work correctly (delegate to real implementations)
446
539
  // Query functions return empty results by default
447
540
  // Entity operations return sensible defaults
541
+ // Seed functions return { created: [], skipped: [], errors: [] } by default
542
+ // Export functions return { entities: [], count: 0 } by default
448
543
 
449
544
  // Customize mock behavior:
450
- import { queryByOu, getEntity, putEntity } from "@jaypie/testkit/mock";
545
+ import {
546
+ exportEntities,
547
+ getEntity,
548
+ putEntity,
549
+ queryByOu,
550
+ seedEntities,
551
+ } from "@jaypie/testkit/mock";
451
552
 
452
553
  queryByOu.mockResolvedValue({
453
554
  items: [{ id: "123", name: "Test" }],
@@ -455,6 +556,17 @@ queryByOu.mockResolvedValue({
455
556
  });
456
557
 
457
558
  getEntity.mockResolvedValue({ id: "123", model: "record", name: "Test" });
559
+
560
+ seedEntities.mockResolvedValue({
561
+ created: ["entity-1", "entity-2"],
562
+ skipped: [],
563
+ errors: [],
564
+ });
565
+
566
+ exportEntities.mockResolvedValue({
567
+ entities: [{ id: "123", model: "record" }],
568
+ count: 1,
569
+ });
458
570
  ```
459
571
 
460
572
  ## Best Practices
@@ -407,6 +407,50 @@ expressHandler automatically sets these headers:
407
407
 
408
408
  When Datadog environment variables are configured, expressHandler automatically submits metrics for each request including status code and path.
409
409
 
410
+ ## Server Creation
411
+
412
+ Use `createServer` to quickly set up an Express server with standard Jaypie middleware.
413
+
414
+ ### Basic Server Usage
415
+
416
+ ```typescript
417
+ import express from "express";
418
+ import { createServer, expressHandler } from "jaypie";
419
+
420
+ const app = express();
421
+
422
+ app.get("/", expressHandler(async (req, res) => {
423
+ return { message: "Hello World" };
424
+ }));
425
+
426
+ const { server, port } = await createServer(app);
427
+ console.log(`Server running on port ${port}`);
428
+ ```
429
+
430
+ ### Server Options
431
+
432
+ ```typescript
433
+ import { createServer } from "jaypie";
434
+ import type { CreateServerOptions } from "jaypie";
435
+
436
+ const options: CreateServerOptions = {
437
+ port: 3000, // Port to listen on (default: PORT env var or 8080)
438
+ cors: { origin: "*" }, // CORS config (false to disable)
439
+ jsonLimit: "10mb", // JSON body parser limit (default: "1mb")
440
+ middleware: [myMiddleware], // Additional middleware to apply
441
+ };
442
+
443
+ const { server, port } = await createServer(app, options);
444
+ ```
445
+
446
+ ### Server Result
447
+
448
+ ```typescript
449
+ import type { ServerResult } from "jaypie";
450
+
451
+ // { server: Server, port: number }
452
+ ```
453
+
410
454
  ## Streaming Responses
411
455
 
412
456
  Use `expressStreamHandler` for Server-Sent Events (SSE) streaming responses. Ideal for real-time updates, LLM streaming, and long-running operations.
@@ -497,3 +541,33 @@ import type {
497
541
  JaypieStreamHandlerValidate,
498
542
  } from "jaypie";
499
543
  ```
544
+
545
+ ## Invoke UUID Detection
546
+
547
+ Use `getCurrentInvokeUuid` to get the current request ID. Automatically detects the environment (Lambda, Lambda Web Adapter, or local development).
548
+
549
+ ### Basic Usage
550
+
551
+ ```typescript
552
+ import { getCurrentInvokeUuid } from "jaypie";
553
+
554
+ const handler = expressHandler(async (req, res) => {
555
+ const invokeUuid = getCurrentInvokeUuid(req);
556
+ // Returns AWS request ID in Lambda, or generates a local UUID
557
+ return { requestId: invokeUuid };
558
+ });
559
+ ```
560
+
561
+ ### Environment Detection
562
+
563
+ The function adapts to different runtime environments:
564
+
565
+ 1. **Lambda (native)**: Uses `awsRequestId` from Lambda context
566
+ 2. **Lambda Web Adapter**: Extracts from `x-amzn-request-id` header or `_X_AMZN_TRACE_ID` env var
567
+ 3. **Local development**: Generates a UUID for consistent tracing
568
+
569
+ ### Lambda Web Adapter Headers
570
+
571
+ When running Express behind AWS Lambda Web Adapter, the function extracts the request ID from:
572
+ - `x-amzn-request-id` header (set by Lambda Web Adapter)
573
+ - `_X_AMZN_TRACE_ID` environment variable (X-Ray trace ID, set by Lambda runtime)