@jaypie/mcp 0.2.12 → 0.3.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.
- package/README.md +62 -0
- package/dist/aws.d.ts +197 -0
- package/dist/index.js +1179 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/prompts/Jaypie_CDK_Constructs_and_Patterns.md +4 -5
- package/prompts/Jaypie_CICD_with_GitHub_Actions.md +141 -14
- package/prompts/Jaypie_Init_CICD_with_GitHub_Actions.md +143 -96
- package/prompts/Jaypie_Init_Lambda_Package.md +8 -0
- package/prompts/Jaypie_MCP_Package.md +249 -0
- package/prompts/Jaypie_Streaming.md +90 -31
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: MCP server package with documentation, AWS, Datadog, and LLM tools
|
|
3
|
+
include: "packages/mcp/**"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @jaypie/mcp Package
|
|
7
|
+
|
|
8
|
+
The `@jaypie/mcp` package provides a Model Context Protocol (MCP) server for AI agents working with Jaypie projects. It includes tools for accessing documentation, AWS CLI operations, Datadog observability, and LLM debugging.
|
|
9
|
+
|
|
10
|
+
## Package Structure
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
packages/mcp/
|
|
14
|
+
├── src/
|
|
15
|
+
│ ├── index.ts # CLI entrypoint, exports createMcpServer and mcpExpressHandler
|
|
16
|
+
│ ├── createMcpServer.ts # Core MCP server factory with tool definitions
|
|
17
|
+
│ ├── mcpExpressHandler.ts # Express middleware for HTTP transport
|
|
18
|
+
│ ├── aws.ts # AWS CLI integration (spawn-based)
|
|
19
|
+
│ ├── datadog.ts # Datadog API integration (https-based)
|
|
20
|
+
│ └── llm.ts # LLM debug utilities
|
|
21
|
+
├── prompts/ # Markdown guides served via list_prompts/read_prompt tools
|
|
22
|
+
└── dist/ # Built output
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### CLI (stdio transport)
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx jaypie-mcp # Run MCP server via stdio
|
|
31
|
+
npx jaypie-mcp --verbose # Run with debug logging
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Express Integration (HTTP transport)
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import express from "express";
|
|
38
|
+
import { mcpExpressHandler } from "@jaypie/mcp";
|
|
39
|
+
|
|
40
|
+
const app = express();
|
|
41
|
+
app.use(express.json());
|
|
42
|
+
app.use("/mcp", await mcpExpressHandler({ version: "1.0.0" }));
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Direct Server Creation
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { createMcpServer } from "@jaypie/mcp";
|
|
49
|
+
|
|
50
|
+
const server = createMcpServer({ version: "1.0.0", verbose: true });
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## MCP Tools (27 total)
|
|
54
|
+
|
|
55
|
+
### Documentation Tools (3)
|
|
56
|
+
|
|
57
|
+
| Tool | Description |
|
|
58
|
+
|------|-------------|
|
|
59
|
+
| `list_prompts` | Lists all `.md` files in `prompts/` with descriptions and required file patterns |
|
|
60
|
+
| `read_prompt` | Returns content of a specific prompt file |
|
|
61
|
+
| `version` | Returns package version string |
|
|
62
|
+
|
|
63
|
+
### AWS CLI Tools (16)
|
|
64
|
+
|
|
65
|
+
Requires AWS CLI installed and configured. All tools accept optional `profile` and `region` parameters.
|
|
66
|
+
|
|
67
|
+
| Tool | Description |
|
|
68
|
+
|------|-------------|
|
|
69
|
+
| `aws_list_profiles` | List available AWS profiles from ~/.aws/config and credentials |
|
|
70
|
+
| `aws_stepfunctions_list_executions` | List Step Function executions for a state machine |
|
|
71
|
+
| `aws_stepfunctions_stop_execution` | Stop a running Step Function execution |
|
|
72
|
+
| `aws_lambda_list_functions` | List Lambda functions with optional prefix filtering |
|
|
73
|
+
| `aws_lambda_get_function` | Get configuration and details for a specific Lambda function |
|
|
74
|
+
| `aws_logs_filter_log_events` | Search CloudWatch Logs with pattern and time range filtering |
|
|
75
|
+
| `aws_s3_list_objects` | List objects in an S3 bucket with optional prefix filtering |
|
|
76
|
+
| `aws_cloudformation_describe_stack` | Get details and status of a CloudFormation stack |
|
|
77
|
+
| `aws_dynamodb_describe_table` | Get metadata about a DynamoDB table |
|
|
78
|
+
| `aws_dynamodb_scan` | Scan a DynamoDB table (use sparingly on large tables) |
|
|
79
|
+
| `aws_dynamodb_query` | Query a DynamoDB table by partition key |
|
|
80
|
+
| `aws_dynamodb_get_item` | Get a single item from a DynamoDB table by primary key |
|
|
81
|
+
| `aws_sqs_list_queues` | List SQS queues with optional prefix filtering |
|
|
82
|
+
| `aws_sqs_get_queue_attributes` | Get queue attributes including message counts |
|
|
83
|
+
| `aws_sqs_receive_message` | Peek at messages in an SQS queue (does not delete) |
|
|
84
|
+
| `aws_sqs_purge_queue` | Delete all messages from an SQS queue (irreversible) |
|
|
85
|
+
|
|
86
|
+
### Datadog Tools (6)
|
|
87
|
+
|
|
88
|
+
Requires `DATADOG_API_KEY` and `DATADOG_APP_KEY` environment variables.
|
|
89
|
+
|
|
90
|
+
| Tool | Description |
|
|
91
|
+
|------|-------------|
|
|
92
|
+
| `datadog_logs` | Search individual log entries |
|
|
93
|
+
| `datadog_log_analytics` | Aggregate logs with groupBy operations |
|
|
94
|
+
| `datadog_monitors` | List and filter monitors by status/tags |
|
|
95
|
+
| `datadog_synthetics` | List synthetic tests or get results for a specific test |
|
|
96
|
+
| `datadog_metrics` | Query timeseries metrics |
|
|
97
|
+
| `datadog_rum` | Search Real User Monitoring events |
|
|
98
|
+
|
|
99
|
+
### LLM Tools (2)
|
|
100
|
+
|
|
101
|
+
| Tool | Description |
|
|
102
|
+
|------|-------------|
|
|
103
|
+
| `llm_debug_call` | Debug LLM API calls and inspect raw responses |
|
|
104
|
+
| `llm_list_providers` | List available LLM providers with their models |
|
|
105
|
+
|
|
106
|
+
## Environment Variables
|
|
107
|
+
|
|
108
|
+
### AWS CLI Integration
|
|
109
|
+
|
|
110
|
+
| Variable | Description |
|
|
111
|
+
|----------|-------------|
|
|
112
|
+
| `AWS_PROFILE` | Default profile if not specified per-call |
|
|
113
|
+
| `AWS_REGION` or `AWS_DEFAULT_REGION` | Default region if not specified |
|
|
114
|
+
|
|
115
|
+
AWS tools use the host's existing credential chain:
|
|
116
|
+
- `~/.aws/credentials` and `~/.aws/config` files
|
|
117
|
+
- Environment variables (`AWS_ACCESS_KEY_ID`, etc.)
|
|
118
|
+
- SSO sessions established via `aws sso login`
|
|
119
|
+
|
|
120
|
+
### Datadog Integration
|
|
121
|
+
|
|
122
|
+
| Variable | Description |
|
|
123
|
+
|----------|-------------|
|
|
124
|
+
| `DATADOG_API_KEY` or `DD_API_KEY` | Datadog API key |
|
|
125
|
+
| `DATADOG_APP_KEY` or `DD_APP_KEY` | Datadog Application key |
|
|
126
|
+
| `DD_ENV` | Default environment filter |
|
|
127
|
+
| `DD_SERVICE` | Default service filter |
|
|
128
|
+
| `DD_SOURCE` | Default log source (defaults to "lambda") |
|
|
129
|
+
| `DD_QUERY` | Default query terms appended to searches |
|
|
130
|
+
|
|
131
|
+
## Adding New Tools
|
|
132
|
+
|
|
133
|
+
Tools are registered in `createMcpServer.ts` using the MCP SDK pattern:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
server.tool(
|
|
137
|
+
"tool_name",
|
|
138
|
+
"Description shown to AI agents",
|
|
139
|
+
{
|
|
140
|
+
// Zod schema for parameters
|
|
141
|
+
param1: z.string().describe("Parameter description"),
|
|
142
|
+
param2: z.number().optional().describe("Optional parameter"),
|
|
143
|
+
},
|
|
144
|
+
async ({ param1, param2 }) => {
|
|
145
|
+
// Implementation
|
|
146
|
+
return {
|
|
147
|
+
content: [{ type: "text" as const, text: "Result text" }],
|
|
148
|
+
};
|
|
149
|
+
},
|
|
150
|
+
);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### AWS Tool Pattern
|
|
154
|
+
|
|
155
|
+
AWS tools use `child_process.spawn` to call the AWS CLI:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
// In aws.ts
|
|
159
|
+
export async function myAwsOperation(
|
|
160
|
+
options: MyOperationOptions,
|
|
161
|
+
logger: Logger = nullLogger,
|
|
162
|
+
): Promise<AwsCommandResult<MyResultType>> {
|
|
163
|
+
const args = ["--required-arg", options.requiredArg];
|
|
164
|
+
if (options.optionalArg) {
|
|
165
|
+
args.push("--optional-arg", options.optionalArg);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return executeAwsCommand(
|
|
169
|
+
"service-name", // e.g., "stepfunctions", "lambda", "s3api"
|
|
170
|
+
"command-name", // e.g., "list-executions", "get-function"
|
|
171
|
+
args,
|
|
172
|
+
{ profile: options.profile, region: options.region },
|
|
173
|
+
logger,
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Datadog Tool Pattern
|
|
179
|
+
|
|
180
|
+
Datadog tools use Node.js `https` module directly:
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// In datadog.ts
|
|
184
|
+
export async function myDatadogOperation(
|
|
185
|
+
credentials: DatadogCredentials,
|
|
186
|
+
options: MyOptions,
|
|
187
|
+
logger: Logger = nullLogger,
|
|
188
|
+
): Promise<MyResult> {
|
|
189
|
+
const requestOptions = {
|
|
190
|
+
hostname: "api.datadoghq.com",
|
|
191
|
+
port: 443,
|
|
192
|
+
path: "/api/v2/endpoint",
|
|
193
|
+
method: "POST",
|
|
194
|
+
headers: {
|
|
195
|
+
"DD-API-KEY": credentials.apiKey,
|
|
196
|
+
"DD-APPLICATION-KEY": credentials.appKey,
|
|
197
|
+
"Content-Type": "application/json",
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
return new Promise((resolve) => {
|
|
202
|
+
const req = https.request(requestOptions, (res) => {
|
|
203
|
+
// Handle response
|
|
204
|
+
});
|
|
205
|
+
req.write(JSON.stringify(body));
|
|
206
|
+
req.end();
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Adding New Prompts
|
|
212
|
+
|
|
213
|
+
Prompts are markdown files in `prompts/` with optional YAML frontmatter:
|
|
214
|
+
|
|
215
|
+
```yaml
|
|
216
|
+
---
|
|
217
|
+
description: Brief description shown in list_prompts
|
|
218
|
+
include: "packages/express/**" # File patterns this guide applies to
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
# Prompt Title
|
|
222
|
+
|
|
223
|
+
Markdown content here...
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Prompts are automatically available via `list_prompts` and `read_prompt` tools.
|
|
227
|
+
|
|
228
|
+
## Exports
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
import { createMcpServer, mcpExpressHandler } from "@jaypie/mcp";
|
|
232
|
+
import type { CreateMcpServerOptions, McpExpressHandlerOptions } from "@jaypie/mcp";
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Commands
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
npm run build -w packages/mcp # Build with rollup
|
|
239
|
+
npm run test -w packages/mcp # Run tests (vitest run)
|
|
240
|
+
npm run typecheck -w packages/mcp # Type check (tsc --noEmit)
|
|
241
|
+
npm run format packages/mcp # Format with eslint --fix
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Security Considerations
|
|
245
|
+
|
|
246
|
+
1. **Allowlisted operations only** - No arbitrary command execution
|
|
247
|
+
2. **Read-heavy design** - Most tools are read-only; mutating operations have explicit warnings
|
|
248
|
+
3. **No credential exposure** - Credentials never passed through MCP; uses host's credential chain
|
|
249
|
+
4. **Profile isolation** - Each call can specify a different profile for multi-account work
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Complete guide to streaming in Jaypie - Lambda, Express, and
|
|
2
|
+
description: Complete guide to streaming in Jaypie - Lambda, Express, SSE, and NLJSON patterns
|
|
3
3
|
globs: packages/express/**, packages/lambda/**, packages/aws/**
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -7,6 +7,23 @@ globs: packages/express/**, packages/lambda/**, packages/aws/**
|
|
|
7
7
|
|
|
8
8
|
Jaypie provides three distinct streaming patterns for different deployment scenarios. This guide explains when to use each approach and how to implement streaming correctly.
|
|
9
9
|
|
|
10
|
+
## Stream Formats
|
|
11
|
+
|
|
12
|
+
Jaypie supports two stream output formats:
|
|
13
|
+
|
|
14
|
+
| Format | Content-Type | Use Case |
|
|
15
|
+
|--------|--------------|----------|
|
|
16
|
+
| SSE (default) | `text/event-stream` | Browser EventSource, real-time UI updates |
|
|
17
|
+
| NLJSON | `application/x-ndjson` | Machine-to-machine, log processing |
|
|
18
|
+
|
|
19
|
+
### Format Comparison
|
|
20
|
+
|
|
21
|
+
| Aspect | SSE | NLJSON |
|
|
22
|
+
|--------|-----|--------|
|
|
23
|
+
| Data format | `event: <type>\ndata: {...}\n\n` | `{...}\n` |
|
|
24
|
+
| Error format | `event: error\ndata: {...}\n\n` | `{"error":{...}}\n` |
|
|
25
|
+
| Browser support | Native EventSource API | Requires manual parsing |
|
|
26
|
+
|
|
10
27
|
## Quick Reference
|
|
11
28
|
|
|
12
29
|
| Handler | Package | Express Required | Use Case |
|
|
@@ -31,8 +48,11 @@ All streaming utilities are exported from `@jaypie/aws` and re-exported through
|
|
|
31
48
|
| `createExpressStream(stream, res)` | Pipe async iterable to Express response with SSE headers |
|
|
32
49
|
| `JaypieStream` | Wrapper class with `.toLambda()` and `.toExpress()` methods |
|
|
33
50
|
| `createJaypieStream(source)` | Factory function for JaypieStream |
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
51
|
+
| `formatSse(chunk)` | Format a chunk as SSE event string |
|
|
52
|
+
| `formatNljson(chunk)` | Format a chunk as NLJSON string |
|
|
53
|
+
| `formatStreamError(errorBody, format)` | Format error based on stream format |
|
|
54
|
+
| `getContentTypeForFormat(format)` | Get content type for stream format |
|
|
55
|
+
| `streamToSse(stream)` | Convert async iterable to SSE-formatted strings |
|
|
36
56
|
|
|
37
57
|
### Types
|
|
38
58
|
|
|
@@ -40,8 +60,9 @@ All streaming utilities are exported from `@jaypie/aws` and re-exported through
|
|
|
40
60
|
import type {
|
|
41
61
|
ExpressStreamResponse,
|
|
42
62
|
LambdaStreamWriter,
|
|
43
|
-
|
|
63
|
+
SseEvent,
|
|
44
64
|
StreamChunk,
|
|
65
|
+
StreamFormat, // "sse" | "nljson"
|
|
45
66
|
} from "jaypie";
|
|
46
67
|
```
|
|
47
68
|
|
|
@@ -49,13 +70,16 @@ import type {
|
|
|
49
70
|
|
|
50
71
|
Use for pure Lambda functions without Express. Requires AWS Lambda Response Streaming via Function URL.
|
|
51
72
|
|
|
73
|
+
**Note:** `lambdaStreamHandler` automatically wraps with `awslambda.streamifyResponse()` in the Lambda runtime. You no longer need to wrap manually.
|
|
74
|
+
|
|
52
75
|
### Basic Usage
|
|
53
76
|
|
|
54
77
|
```typescript
|
|
55
78
|
import { lambdaStreamHandler } from "jaypie";
|
|
56
79
|
import type { StreamHandlerContext } from "@jaypie/lambda";
|
|
57
80
|
|
|
58
|
-
|
|
81
|
+
// Auto-wrapped with awslambda.streamifyResponse() in Lambda runtime
|
|
82
|
+
export const handler = lambdaStreamHandler(
|
|
59
83
|
async (event: unknown, context: StreamHandlerContext) => {
|
|
60
84
|
const { responseStream } = context;
|
|
61
85
|
|
|
@@ -70,13 +94,18 @@ const streamWorker = lambdaStreamHandler(
|
|
|
70
94
|
},
|
|
71
95
|
{
|
|
72
96
|
name: "streamWorker",
|
|
73
|
-
contentType: "text/event-stream",
|
|
74
97
|
}
|
|
75
98
|
);
|
|
99
|
+
```
|
|
76
100
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
### With Format Option
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// SSE format (default)
|
|
105
|
+
export const sseHandler = lambdaStreamHandler(myHandler, { format: "sse" });
|
|
106
|
+
|
|
107
|
+
// NLJSON format
|
|
108
|
+
export const nljsonHandler = lambdaStreamHandler(myHandler, { format: "nljson" });
|
|
80
109
|
```
|
|
81
110
|
|
|
82
111
|
### With LLM Streaming
|
|
@@ -89,7 +118,8 @@ interface PromptEvent {
|
|
|
89
118
|
prompt?: string;
|
|
90
119
|
}
|
|
91
120
|
|
|
92
|
-
|
|
121
|
+
// Auto-wrapped with awslambda.streamifyResponse() in Lambda runtime
|
|
122
|
+
export const handler = lambdaStreamHandler(
|
|
93
123
|
async (event: PromptEvent, context: StreamHandlerContext) => {
|
|
94
124
|
const llm = new Llm("anthropic");
|
|
95
125
|
const stream = llm.stream(event.prompt || "Hello");
|
|
@@ -102,25 +132,23 @@ const llmStreamHandler = lambdaStreamHandler(
|
|
|
102
132
|
secrets: ["ANTHROPIC_API_KEY"],
|
|
103
133
|
}
|
|
104
134
|
);
|
|
105
|
-
|
|
106
|
-
declare const awslambda: { streamifyResponse: <T>(handler: T) => T };
|
|
107
|
-
export const handler = awslambda.streamifyResponse(llmStreamHandler);
|
|
108
135
|
```
|
|
109
136
|
|
|
110
137
|
### Handler Options
|
|
111
138
|
|
|
112
139
|
```typescript
|
|
113
|
-
import type { LambdaStreamHandlerOptions } from "@jaypie/lambda";
|
|
140
|
+
import type { LambdaStreamHandlerOptions, StreamFormat } from "@jaypie/lambda";
|
|
114
141
|
|
|
115
142
|
const options: LambdaStreamHandlerOptions = {
|
|
116
143
|
name: "myStreamHandler", // Handler name for logging
|
|
117
|
-
|
|
144
|
+
format: "sse", // Stream format: "sse" (default) or "nljson"
|
|
145
|
+
contentType: "text/event-stream", // Response content type (auto-set from format)
|
|
118
146
|
chaos: "low", // Chaos testing level
|
|
119
147
|
secrets: ["API_KEY"], // AWS secrets to load into process.env
|
|
120
148
|
setup: [], // Setup function(s)
|
|
121
149
|
teardown: [], // Teardown function(s)
|
|
122
150
|
validate: [], // Validation function(s)
|
|
123
|
-
throw: false, // Re-throw errors instead of
|
|
151
|
+
throw: false, // Re-throw errors instead of streaming error
|
|
124
152
|
unavailable: false, // Return 503 if true
|
|
125
153
|
};
|
|
126
154
|
```
|
|
@@ -137,11 +165,19 @@ const streamingLambda = new JaypieLambda(this, "StreamingFunction", {
|
|
|
137
165
|
timeout: Duration.minutes(5),
|
|
138
166
|
});
|
|
139
167
|
|
|
140
|
-
//
|
|
168
|
+
// For direct Function URL access:
|
|
141
169
|
streamingLambda.addFunctionUrl({
|
|
142
170
|
authType: FunctionUrlAuthType.NONE,
|
|
143
171
|
invokeMode: InvokeMode.RESPONSE_STREAM,
|
|
144
172
|
});
|
|
173
|
+
|
|
174
|
+
// Or use JaypieDistribution with streaming: true
|
|
175
|
+
new JaypieDistribution(this, "Distribution", {
|
|
176
|
+
handler: streamingLambda,
|
|
177
|
+
streaming: true,
|
|
178
|
+
host: "api.example.com",
|
|
179
|
+
zone: "example.com",
|
|
180
|
+
});
|
|
145
181
|
```
|
|
146
182
|
|
|
147
183
|
## Pattern 2: expressStreamHandler
|
|
@@ -180,14 +216,25 @@ const llmStreamRoute = expressStreamHandler(async (req: Request, res: Response)
|
|
|
180
216
|
app.post("/chat", llmStreamRoute);
|
|
181
217
|
```
|
|
182
218
|
|
|
219
|
+
### With Format Option
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
// SSE format (default)
|
|
223
|
+
app.get("/stream-sse", expressStreamHandler(myHandler, { format: "sse" }));
|
|
224
|
+
|
|
225
|
+
// NLJSON format
|
|
226
|
+
app.get("/stream-nljson", expressStreamHandler(myHandler, { format: "nljson" }));
|
|
227
|
+
```
|
|
228
|
+
|
|
183
229
|
### Handler Options
|
|
184
230
|
|
|
185
231
|
```typescript
|
|
186
|
-
import type { ExpressStreamHandlerOptions } from "jaypie";
|
|
232
|
+
import type { ExpressStreamHandlerOptions, StreamFormat } from "jaypie";
|
|
187
233
|
|
|
188
234
|
const options: ExpressStreamHandlerOptions = {
|
|
189
235
|
name: "myStreamHandler", // Handler name for logging
|
|
190
|
-
|
|
236
|
+
format: "sse", // Stream format: "sse" (default) or "nljson"
|
|
237
|
+
contentType: "text/event-stream", // Response content type (auto-set from format)
|
|
191
238
|
chaos: "low", // Chaos testing level
|
|
192
239
|
secrets: ["API_KEY"], // Secrets to load
|
|
193
240
|
setup: [], // Setup function(s)
|
|
@@ -296,17 +343,17 @@ for await (const sseEvent of stream.toSSE()) {
|
|
|
296
343
|
### Manual SSE Formatting
|
|
297
344
|
|
|
298
345
|
```typescript
|
|
299
|
-
import {
|
|
346
|
+
import { formatSse } from "jaypie";
|
|
300
347
|
|
|
301
348
|
const chunk = { type: "message", content: "Hello" };
|
|
302
|
-
const sseString =
|
|
349
|
+
const sseString = formatSse(chunk);
|
|
303
350
|
// "event: message\ndata: {\"type\":\"message\",\"content\":\"Hello\"}\n\n"
|
|
304
351
|
```
|
|
305
352
|
|
|
306
353
|
### Converting Async Iterables
|
|
307
354
|
|
|
308
355
|
```typescript
|
|
309
|
-
import {
|
|
356
|
+
import { streamToSse } from "jaypie";
|
|
310
357
|
|
|
311
358
|
async function* myGenerator() {
|
|
312
359
|
yield { type: "start", data: {} };
|
|
@@ -314,28 +361,36 @@ async function* myGenerator() {
|
|
|
314
361
|
yield { type: "end", data: {} };
|
|
315
362
|
}
|
|
316
363
|
|
|
317
|
-
for await (const sseEvent of
|
|
364
|
+
for await (const sseEvent of streamToSse(myGenerator())) {
|
|
318
365
|
responseStream.write(sseEvent);
|
|
319
366
|
}
|
|
320
367
|
```
|
|
321
368
|
|
|
322
369
|
## Error Handling
|
|
323
370
|
|
|
324
|
-
Errors in streaming handlers are written
|
|
371
|
+
Errors in streaming handlers are written to the stream in the configured format:
|
|
372
|
+
|
|
373
|
+
**SSE format (default):**
|
|
374
|
+
```
|
|
375
|
+
event: error
|
|
376
|
+
data: {"errors":[{"status":500,"title":"Internal Error"}]}
|
|
325
377
|
|
|
326
|
-
```
|
|
327
|
-
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
**NLJSON format:**
|
|
381
|
+
```
|
|
382
|
+
{"error":{"errors":[{"status":500,"title":"Internal Error"}]}}
|
|
328
383
|
```
|
|
329
384
|
|
|
330
385
|
For `lambdaStreamHandler`, set `throw: true` to re-throw errors instead of writing to stream:
|
|
331
386
|
|
|
332
387
|
```typescript
|
|
333
|
-
const handler = lambdaStreamHandler(
|
|
388
|
+
export const handler = lambdaStreamHandler(
|
|
334
389
|
async (event, context) => {
|
|
335
390
|
throw new InternalError("Something went wrong");
|
|
336
391
|
},
|
|
337
392
|
{
|
|
338
|
-
throw: true, // Re-throw instead of
|
|
393
|
+
throw: true, // Re-throw instead of streaming error
|
|
339
394
|
}
|
|
340
395
|
);
|
|
341
396
|
```
|
|
@@ -383,10 +438,13 @@ Use the Docker setup in `packages/express/docker/` for local Lambda streaming te
|
|
|
383
438
|
```typescript
|
|
384
439
|
// From @jaypie/lambda
|
|
385
440
|
import type {
|
|
441
|
+
AwsStreamingHandler,
|
|
442
|
+
LambdaHandler, // Wrapped handler type (after awslambda.streamifyResponse)
|
|
386
443
|
LambdaStreamHandlerOptions,
|
|
387
|
-
|
|
444
|
+
RawStreamingHandler, // Alias for AwsStreamingHandler (for testing)
|
|
388
445
|
ResponseStream,
|
|
389
|
-
|
|
446
|
+
StreamFormat, // "sse" | "nljson" (re-exported from @jaypie/aws)
|
|
447
|
+
StreamHandlerContext,
|
|
390
448
|
} from "@jaypie/lambda";
|
|
391
449
|
|
|
392
450
|
// From @jaypie/express (or jaypie)
|
|
@@ -402,7 +460,8 @@ import type {
|
|
|
402
460
|
import type {
|
|
403
461
|
ExpressStreamResponse,
|
|
404
462
|
LambdaStreamWriter,
|
|
405
|
-
|
|
463
|
+
SseEvent,
|
|
406
464
|
StreamChunk,
|
|
465
|
+
StreamFormat, // "sse" | "nljson"
|
|
407
466
|
} from "jaypie";
|
|
408
467
|
```
|