@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.
- package/dist/suites/docs/index.js +1 -1
- package/package.json +1 -1
- package/release-notes/express/1.2.17.md +12 -0
- package/release-notes/jaypie/1.2.25.md +10 -0
- package/release-notes/llm/1.2.20.md +10 -0
- package/release-notes/mcp/0.8.2.md +11 -0
- package/skills/JaypieDatadogForwarder.md +99 -0
- package/skills/express.md +1 -1
- package/skills/logs.md +47 -112
- package/skills/practice.md +35 -2
|
@@ -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.
|
|
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
|
@@ -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` |
|
|
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
|
-
##
|
|
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("
|
|
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
|
-
|
|
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.
|
|
69
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
Log errors with full context:
|
|
78
|
-
|
|
48
|
+
Or have the variable name tell the story:
|
|
49
|
+
<GOOD>
|
|
79
50
|
```typescript
|
|
80
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
Never log sensitive data:
|
|
95
|
-
|
|
55
|
+
Nest multi-key objects under a single key:
|
|
96
56
|
```typescript
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
57
|
+
log.var({ Processing: {
|
|
58
|
+
id,
|
|
59
|
+
amount,
|
|
60
|
+
quantity,
|
|
61
|
+
} });
|
|
102
62
|
```
|
|
103
63
|
|
|
104
|
-
##
|
|
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
|
-
|
|
66
|
+
Via environment variable:
|
|
130
67
|
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
|
package/skills/practice.md
CHANGED
|
@@ -4,7 +4,40 @@ description: Updates to Jaypie code, deploy, documentation, and other practices
|
|
|
4
4
|
|
|
5
5
|
# Jaypie Practice
|
|
6
6
|
|
|
7
|
-
|
|
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
|