@jaypie/mcp 0.8.0 → 0.8.2

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.0#cb8527ad"
12
+ const BUILD_VERSION_STRING = "@jaypie/mcp@0.8.2#6d5f241e"
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.0",
3
+ "version": "0.8.2",
4
4
  "description": "Jaypie MCP",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,12 @@
1
+ ---
2
+ version: 1.2.17
3
+ date: 2026-03-26
4
+ summary: Pre-parse request body in LambdaRequest — express.json() no longer required
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - LambdaRequest now eagerly pre-parses the body in the constructor: JSON bodies are parsed automatically, non-JSON bodies are set as strings
10
+ - Sets `_body` flag so body-parser middleware (express.json()) skips if present, preserving the raw stream for consumers like MCP transport
11
+ - `express.json()` middleware is no longer required for JSON body parsing on Lambda
12
+ - Closes #246
@@ -0,0 +1,10 @@
1
+ ---
2
+ version: 1.2.25
3
+ date: 2026-03-26
4
+ summary: Bump @jaypie/express to 1.2.17 for automatic body parsing
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - Updated `@jaypie/express` dependency to ^1.2.17
10
+ - JSON request bodies are now automatically parsed in Lambda handlers without requiring `express.json()` middleware
@@ -0,0 +1,10 @@
1
+ ---
2
+ version: 1.2.20
3
+ date: 2026-03-26
4
+ summary: Fix orphaned tool_use block when tool call throws during streaming
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - Fix: When a tool's `call` function throws during `Llm.stream()`, inject an error `tool_result` into the message history so the next turn has a matching pair, preventing Anthropic API 400 errors
10
+ - Fix: Apply the same correction in `OperateLoop` for non-streaming tool call failures
@@ -0,0 +1,11 @@
1
+ ---
2
+ version: 0.8.2
3
+ date: 2026-03-26
4
+ summary: Updated skills documentation for logs, practice, and new JaypieDatadogForwarder
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - Updated `logs` skill with Jaypie logging best practices, log.var usage, and level guidance
10
+ - Updated `practice` skill with scrub documentation and style audit workflows
11
+ - Added `JaypieDatadogForwarder` skill documenting the CDK construct for Datadog log forwarding
@@ -0,0 +1,99 @@
1
+ ---
2
+ description: JaypieDatadogForwarder CDK construct for deploying and importing the Datadog log forwarder
3
+ related: cdk, datadog, aws
4
+ ---
5
+
6
+ # JaypieDatadogForwarder
7
+
8
+ CDK construct that wraps Datadog's official CloudFormation forwarder template. Deploys a Lambda that forwards logs to Datadog.
9
+
10
+ ## Import
11
+
12
+ ```typescript
13
+ import { JaypieDatadogForwarder, resolveDatadogForwarderFunction } from "@jaypie/constructs";
14
+ ```
15
+
16
+ ## Creating the Forwarder (Provider Stack)
17
+
18
+ ```typescript
19
+ const forwarder = new JaypieDatadogForwarder(this);
20
+ ```
21
+
22
+ Uses environment variables for defaults and automatically exports the Lambda ARN as a CloudFormation output.
23
+
24
+ ### Constructor Signatures
25
+
26
+ ```typescript
27
+ new JaypieDatadogForwarder(scope);
28
+ new JaypieDatadogForwarder(scope, props);
29
+ new JaypieDatadogForwarder(scope, id, props);
30
+ ```
31
+
32
+ ### Props
33
+
34
+ | Parameter | Type | Default | Description |
35
+ |-----------|------|---------|-------------|
36
+ | `id` | string | `"DatadogForwarder"` | Construct ID |
37
+ | `datadogApiKey` | string | `CDK_ENV_DATADOG_API_KEY` | Datadog API key |
38
+ | `account` | string | `CDK_ENV_ACCOUNT` | Account identifier for tags |
39
+ | `reservedConcurrency` | string | `"10"` | Lambda reserved concurrency (must be string) |
40
+ | `additionalTags` | string | undefined | Extra Datadog tags (comma-separated) |
41
+ | `service` | string | `"datadog"` | Service tag value |
42
+ | `project` | string | undefined | Project tag value |
43
+ | `enableCloudFormationEvents` | boolean | `true` | EventBridge rule for CF events |
44
+ | `enableRoleExtension` | boolean | `true` | Extend Datadog IAM role permissions |
45
+ | `createOutput` | boolean | `true` | Export forwarder ARN as CfnOutput |
46
+ | `exportName` | string | `"account-datadog-forwarder"` | Export name for cross-stack reference |
47
+
48
+ ### Resources Created
49
+
50
+ 1. **Nested CloudFormation Stack** — deploys Datadog's official forwarder template
51
+ 2. **EventBridge Rule** — forwards CloudFormation events to Datadog (on by default)
52
+ 3. **CfnOutput** — exports forwarder Lambda ARN with name `"account-datadog-forwarder"`
53
+ 4. **Extended IAM Permissions** — adds `budgets:ViewBudget`, `logs:DescribeLogGroups` to Datadog role (if `CDK_ENV_DATADOG_ROLE_ARN` is set)
54
+
55
+ ### Public Properties
56
+
57
+ ```typescript
58
+ forwarder.cfnStack // CfnStack — the nested CloudFormation stack
59
+ forwarder.forwarderFunction // IFunction — the Datadog forwarder Lambda
60
+ forwarder.eventsRule // Rule | undefined — EventBridge rule (if enabled)
61
+ ```
62
+
63
+ ## Importing from Another Stack
64
+
65
+ Use the `resolveDatadogForwarderFunction` helper:
66
+
67
+ ```typescript
68
+ import { resolveDatadogForwarderFunction } from "@jaypie/constructs";
69
+
70
+ const forwarderFunction = resolveDatadogForwarderFunction(this);
71
+ ```
72
+
73
+ This imports the Lambda via `Fn.importValue("account-datadog-forwarder")` and caches per scope (WeakMap), so multiple calls in the same stack return the same reference.
74
+
75
+ ### For Log Subscription Filters
76
+
77
+ Use `resolveDatadogLoggingDestination` to get a `LambdaDestination`:
78
+
79
+ ```typescript
80
+ import { resolveDatadogLoggingDestination } from "@jaypie/constructs";
81
+
82
+ new SubscriptionFilter(this, "DatadogSubscription", {
83
+ logGroup,
84
+ destination: resolveDatadogLoggingDestination(this),
85
+ filterPattern: FilterPattern.allEvents(),
86
+ });
87
+ ```
88
+
89
+ ## Environment Variables
90
+
91
+ | Variable | Purpose |
92
+ |----------|---------|
93
+ | `CDK_ENV_DATADOG_API_KEY` | Default Datadog API key |
94
+ | `CDK_ENV_ACCOUNT` | Default account identifier for tagging |
95
+ | `CDK_ENV_DATADOG_ROLE_ARN` | Optional: Datadog IAM role ARN to extend permissions |
96
+
97
+ ## Tags
98
+
99
+ All resources tagged with: `role=monitoring`, `service=datadog`, `vendor=datadog`, and optionally `project`.
package/skills/express.md CHANGED
@@ -128,7 +128,7 @@ The Lambda adapter provides Express-compatible request properties:
128
128
  | `req.path` | URL path without query string |
129
129
  | `req.query` | Parsed query parameters (with array support) |
130
130
  | `req.headers` | Normalized headers (lowercase keys) |
131
- | `req.body` | Parsed body (via body-parser middleware) |
131
+ | `req.body` | Pre-parsed body (JSON auto-parsed, text as string; no middleware needed) |
132
132
  | `req.params` | Route parameters (set by Express router) |
133
133
  | `req._lambdaContext` | Original Lambda context |
134
134
  | `req._lambdaEvent` | Original Lambda event |
package/skills/logs.md CHANGED
@@ -9,6 +9,14 @@ Jaypie provides structured logging for observability.
9
9
 
10
10
  ## Basic Usage
11
11
 
12
+ - All logging should use `log` from `jaypie`, custom functions should be eliminated
13
+ - Logging should tell a story as the process unfolds; a non-developer should be able to read and follow
14
+ - `log.trace` the happy path at major checkpoints or junctures where logic forks or errors may be thrown
15
+ - `log.debug` things that should stand out, anything off the happy path that might impact operations later
16
+ - Avoid `log.info`. Reserve info for values that must be recorded such as metrics
17
+ - Use `log.warn` when the problem is unexpected and warrants attention but is recoverable. Use `log.debug` for unusual things that are part of normal operations
18
+ - Use `log.error` when unrecoverable or "really bad." Do not use `log.error` just because an error occurs that is part of normal operations (e.g., 404)
19
+
12
20
  ```typescript
13
21
  import { log } from "jaypie";
14
22
 
@@ -17,129 +25,49 @@ log.debug("Debug information");
17
25
  log.info("Informational message");
18
26
  log.warn("Warning message");
19
27
  log.error("Error message");
20
- log.fatal("Fatal error");
28
+ log.fatal("Fatal error"); // only used internally in jaypie
21
29
  ```
22
30
 
23
- ## Structured Logging
24
-
25
- Always include context as the second argument:
31
+ ## Logging Objects
26
32
 
33
+ DO NOT use multiple parameters when logging:
34
+ <BAD>
27
35
  ```typescript
28
- log.info("User logged in", {
29
- userId: user.id,
30
- email: user.email,
31
- method: "oauth",
32
- });
33
-
34
- log.error("Payment failed", {
35
- orderId: order.id,
36
- amount: order.total,
37
- error: error.message,
38
- });
39
- ```
40
-
41
- ## Log Levels
42
-
43
- | Level | Use For |
44
- |-------|---------|
45
- | trace | Very detailed debugging (loops, iterations) |
46
- | debug | Development debugging |
47
- | info | Normal operations, business events |
48
- | warn | Unexpected but handled situations |
49
- | error | Errors that need attention |
50
- | fatal | Application cannot continue |
51
-
52
- ## Setting Log Level
53
-
54
- Via environment variable:
55
-
56
- ```bash
57
- LOG_LEVEL=debug npm run dev
58
- LOG_LEVEL=trace npm test
36
+ log.info("Processing", { id: "my-id" });
59
37
  ```
38
+ </BAD>
60
39
 
61
- In production, typically `info` or `warn`.
62
-
63
- ## Request Context
64
-
65
- Include request identifiers for tracing:
66
-
40
+ Use `log.var` to log single-key objects that parse in Datadog:
41
+ <GOOD>
67
42
  ```typescript
68
- log.info("Processing request", {
69
- requestId: req.id,
70
- path: req.path,
71
- userId: req.user?.id,
72
- });
43
+ log.trace("Processing", { id: "my-id" });
44
+ log.var({ id: "my-id" });
73
45
  ```
46
+ </GOOD>
74
47
 
75
- ## Error Logging
76
-
77
- Log errors with full context:
78
-
48
+ Or have the variable name tell the story:
49
+ <GOOD>
79
50
  ```typescript
80
- try {
81
- await riskyOperation();
82
- } catch (error) {
83
- log.error("Operation failed", {
84
- error: error.message,
85
- stack: error.stack,
86
- input: sanitizedInput,
87
- });
88
- throw error;
89
- }
51
+ log.var({ Processing: id });
90
52
  ```
53
+ </GOOD>
91
54
 
92
- ## Sensitive Data
93
-
94
- Never log sensitive data:
95
-
55
+ Nest multi-key objects under a single key:
96
56
  ```typescript
97
- // BAD
98
- log.info("User auth", { password: user.password });
99
-
100
- // GOOD
101
- log.info("User auth", { userId: user.id, hasPassword: !!user.password });
57
+ log.var({ Processing: {
58
+ id,
59
+ amount,
60
+ quantity,
61
+ } });
102
62
  ```
103
63
 
104
- ## Searching Logs
105
-
106
- ### Via MCP (Datadog)
107
-
108
- ```
109
- # Search by requestId
110
- datadog_logs --query "@requestId:abc-123"
111
-
112
- # Search errors
113
- datadog_logs --query "status:error" --from "now-1h"
114
-
115
- # Search by user
116
- datadog_logs --query "@userId:user-456"
117
- ```
118
-
119
- ### Via MCP (CloudWatch)
120
-
121
- ```
122
- aws_logs_filter_log_events \
123
- --logGroupName "/aws/lambda/my-function" \
124
- --filterPattern "ERROR"
125
- ```
126
-
127
- ## Log Format
64
+ ## Setting Log Level
128
65
 
129
- Jaypie logs are JSON-formatted for Datadog:
66
+ Via environment variable:
130
67
 
131
- ```json
132
- {
133
- "level": "info",
134
- "message": "User logged in",
135
- "timestamp": "2024-01-15T10:00:00.000Z",
136
- "userId": "user-123",
137
- "method": "oauth",
138
- "dd": {
139
- "trace_id": "abc123",
140
- "span_id": "def456"
141
- }
142
- }
68
+ ```bash
69
+ LOG_LEVEL=debug npm run dev
70
+ LOG_LEVEL=trace npm test
143
71
  ```
144
72
 
145
73
  ## Lambda Logging
@@ -150,17 +78,24 @@ Lambda handlers automatically add context:
150
78
  import { lambdaHandler } from "@jaypie/lambda";
151
79
 
152
80
  export const handler = lambdaHandler(async (event) => {
153
- // Logs automatically include:
154
- // - requestId
155
- // - functionName
156
- // - cold_start indicator
157
- log.info("Processing", { customField: "value" });
81
+ log.trace("Begin Processing");
82
+ }, {
83
+ name: "exampleHandler"
158
84
  });
159
85
  ```
160
86
 
87
+ Logs will include the `env`, `invoke`, and `handler` name. For example:
88
+
89
+ ```json
90
+ {
91
+ "env": "sandbox",
92
+ "invoke": "uuid",
93
+ "handler": "exampleHandler"
94
+ }
95
+ ```
96
+
161
97
  ## See Also
162
98
 
163
99
  - **`skill("datadog")`** - Datadog integration and log forwarding
164
100
  - **`skill("handlers")`** - Handler lifecycle with automatic log context
165
101
  - **`skill("variables")`** - LOG_LEVEL and other environment variables
166
-
@@ -4,7 +4,40 @@ description: Updates to Jaypie code, deploy, documentation, and other practices
4
4
 
5
5
  # Jaypie Practice
6
6
 
7
- ## Workflow Dispatch Actions
7
+ - These are Jaypie practices
8
+ - Confirm any implementation before taking action
9
+ - Do not assume a reference to this skill means to run it all
10
+
11
+ ## GitHub Workflow Dispatch Actions
8
12
 
9
13
  - Prefer workflow dispatch actions over branch names and tagging
10
- - Most work is agent-driven so "deploy to production" is more natural
14
+ - Most work is agent-driven so "deploy to production" is more natural
15
+
16
+ ## Logs
17
+
18
+ - Review ~logs and audit logging in the app
19
+
20
+ ## Scrub
21
+
22
+ ### Scrub Documentation
23
+
24
+ - Use a subagent to find essential directories that do not contain a CLAUDE.md, if any
25
+ - Use a subagent to write a CLAUDE.md for each essential directory without one
26
+ - Parallelize this work except when one essential directory contains another
27
+ - In that case, complete the descendant CLAUDE first
28
+ - Whenever possible, offer a terse overview in the root or ancestor CLAUDE and reference the descendant for detail
29
+ - Find CLAUDE.md file not impacted by the above
30
+ - Use a subagent to update each CLAUDE.md
31
+ - Also parallelize this work except when dealing with ancestor- descendant chains
32
+ - Resolve descendants as described
33
+ - Find all README.md
34
+ - Use a subagent to update each
35
+ - Optimize both CLAUDE and README for agents
36
+ - Use terse, direct language
37
+ - Avoid superlatives, rationalizing the technology, or anything resembling hype/sales
38
+
39
+ ### Scrub Style
40
+
41
+ - Do not allow imports from subpackages that are exported from `jaypie`
42
+ - Importing from `@jaypie/express` is not allowed because `jaypie` exports it
43
+ - Importing from `@jaypie/llm` is allowed because `jaypie` does not export it