@jaypie/mcp 0.3.2 → 0.4.0

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.
Files changed (79) hide show
  1. package/dist/createMcpServer.d.ts +7 -1
  2. package/dist/index.js +26 -3135
  3. package/dist/index.js.map +1 -1
  4. package/dist/suite.d.ts +1 -0
  5. package/dist/suite.js +2442 -0
  6. package/dist/suite.js.map +1 -0
  7. package/package.json +8 -3
  8. package/release-notes/constructs/1.2.17.md +11 -0
  9. package/release-notes/fabric/0.1.2.md +11 -0
  10. package/release-notes/fabric/0.1.3.md +25 -0
  11. package/release-notes/fabric/0.1.4.md +42 -0
  12. package/release-notes/mcp/0.3.3.md +12 -0
  13. package/release-notes/mcp/0.3.4.md +36 -0
  14. package/release-notes/mcp/0.4.0.md +27 -0
  15. package/release-notes/testkit/1.2.15.md +23 -0
  16. package/skills/agents.md +25 -0
  17. package/skills/aws.md +107 -0
  18. package/skills/cdk.md +141 -0
  19. package/skills/cicd.md +152 -0
  20. package/skills/datadog.md +129 -0
  21. package/skills/debugging.md +148 -0
  22. package/skills/dns.md +134 -0
  23. package/skills/dynamodb.md +140 -0
  24. package/skills/errors.md +142 -0
  25. package/skills/fabric.md +191 -0
  26. package/skills/index.md +7 -0
  27. package/skills/jaypie.md +100 -0
  28. package/skills/legacy.md +97 -0
  29. package/skills/logs.md +160 -0
  30. package/skills/mocks.md +174 -0
  31. package/skills/models.md +195 -0
  32. package/skills/releasenotes.md +94 -0
  33. package/skills/secrets.md +155 -0
  34. package/skills/services.md +175 -0
  35. package/skills/style.md +190 -0
  36. package/skills/tests.md +209 -0
  37. package/skills/tools.md +127 -0
  38. package/skills/topics.md +116 -0
  39. package/skills/variables.md +146 -0
  40. package/skills/writing.md +153 -0
  41. package/prompts/Branch_Management.md +0 -34
  42. package/prompts/Development_Process.md +0 -89
  43. package/prompts/Jaypie_Agent_Rules.md +0 -110
  44. package/prompts/Jaypie_Auth0_Express_Mongoose.md +0 -736
  45. package/prompts/Jaypie_Browser_and_Frontend_Web_Packages.md +0 -18
  46. package/prompts/Jaypie_CDK_Constructs_and_Patterns.md +0 -430
  47. package/prompts/Jaypie_CICD_with_GitHub_Actions.md +0 -371
  48. package/prompts/Jaypie_Commander_CLI_Package.md +0 -166
  49. package/prompts/Jaypie_Core_Errors_and_Logging.md +0 -39
  50. package/prompts/Jaypie_DynamoDB_Package.md +0 -774
  51. package/prompts/Jaypie_Eslint_NPM_Package.md +0 -78
  52. package/prompts/Jaypie_Express_Package.md +0 -630
  53. package/prompts/Jaypie_Fabric_Commander.md +0 -411
  54. package/prompts/Jaypie_Fabric_LLM.md +0 -312
  55. package/prompts/Jaypie_Fabric_Lambda.md +0 -308
  56. package/prompts/Jaypie_Fabric_MCP.md +0 -316
  57. package/prompts/Jaypie_Fabric_Package.md +0 -513
  58. package/prompts/Jaypie_Fabricator.md +0 -617
  59. package/prompts/Jaypie_Ideal_Project_Structure.md +0 -78
  60. package/prompts/Jaypie_Init_CICD_with_GitHub_Actions.md +0 -1186
  61. package/prompts/Jaypie_Init_Express_on_Lambda.md +0 -115
  62. package/prompts/Jaypie_Init_Jaypie_CDK_Package.md +0 -35
  63. package/prompts/Jaypie_Init_Lambda_Package.md +0 -505
  64. package/prompts/Jaypie_Init_Monorepo_Project.md +0 -44
  65. package/prompts/Jaypie_Init_Project_Subpackage.md +0 -65
  66. package/prompts/Jaypie_Legacy_Patterns.md +0 -15
  67. package/prompts/Jaypie_Llm_Calls.md +0 -449
  68. package/prompts/Jaypie_Llm_Tools.md +0 -155
  69. package/prompts/Jaypie_MCP_Package.md +0 -281
  70. package/prompts/Jaypie_Mocks_and_Testkit.md +0 -137
  71. package/prompts/Jaypie_Repokit.md +0 -103
  72. package/prompts/Jaypie_Scrub.md +0 -177
  73. package/prompts/Jaypie_Streaming.md +0 -467
  74. package/prompts/Templates_CDK_Subpackage.md +0 -115
  75. package/prompts/Templates_Express_Subpackage.md +0 -187
  76. package/prompts/Templates_Project_Monorepo.md +0 -326
  77. package/prompts/Templates_Project_Subpackage.md +0 -93
  78. package/prompts/Write_Efficient_Prompt_Guides.md +0 -48
  79. package/prompts/Write_and_Maintain_Engaging_Readme.md +0 -67
@@ -0,0 +1,195 @@
1
+ ---
2
+ description: Data models and type definitions
3
+ related: fabric, dynamodb, services
4
+ ---
5
+
6
+ # Data Models
7
+
8
+ Patterns for defining data models and types in Jaypie applications.
9
+
10
+ ## TypeScript Interfaces
11
+
12
+ ### Basic Model
13
+
14
+ ```typescript
15
+ export interface User {
16
+ id: string;
17
+ email: string;
18
+ name: string;
19
+ role: "user" | "admin";
20
+ createdAt: string;
21
+ updatedAt: string;
22
+ }
23
+ ```
24
+
25
+ ### Input/Output Types
26
+
27
+ Separate types for different operations:
28
+
29
+ ```typescript
30
+ // Create input - required fields only
31
+ export interface UserCreateInput {
32
+ email: string;
33
+ name: string;
34
+ role?: "user" | "admin";
35
+ }
36
+
37
+ // Update input - all optional
38
+ export interface UserUpdateInput {
39
+ name?: string;
40
+ role?: "user" | "admin";
41
+ }
42
+
43
+ // Response type - full model
44
+ export interface UserResponse extends User {
45
+ // Additional computed fields
46
+ displayName: string;
47
+ }
48
+ ```
49
+
50
+ ## Fabric Service Models
51
+
52
+ Define input schemas inline with fabric services:
53
+
54
+ ```typescript
55
+ import { fabricService } from "@jaypie/fabric";
56
+
57
+ const createUser = fabricService({
58
+ alias: "user_create",
59
+ description: "Create a new user",
60
+ input: {
61
+ email: {
62
+ type: String,
63
+ required: true,
64
+ description: "User email address",
65
+ },
66
+ name: {
67
+ type: String,
68
+ required: true,
69
+ description: "User display name",
70
+ },
71
+ role: {
72
+ type: ["user", "admin"] as const,
73
+ required: false,
74
+ description: "User role (defaults to user)",
75
+ },
76
+ },
77
+ service: async ({ email, name, role }) => {
78
+ // Input is validated and typed
79
+ return createUserInDatabase({ email, name, role: role || "user" });
80
+ },
81
+ });
82
+ ```
83
+
84
+ ## Validation Patterns
85
+
86
+ ### Zod Schemas
87
+
88
+ ```typescript
89
+ import { z } from "zod";
90
+
91
+ export const userSchema = z.object({
92
+ email: z.string().email(),
93
+ name: z.string().min(1).max(100),
94
+ role: z.enum(["user", "admin"]).default("user"),
95
+ });
96
+
97
+ export type User = z.infer<typeof userSchema>;
98
+
99
+ // Validate input
100
+ const validated = userSchema.parse(input);
101
+ ```
102
+
103
+ ### Custom Validators
104
+
105
+ ```typescript
106
+ const emailValidator = (email: string): boolean => {
107
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
108
+ };
109
+
110
+ const service = fabricService({
111
+ alias: "user_create",
112
+ input: {
113
+ email: { type: String, required: true },
114
+ },
115
+ service: async ({ email }) => {
116
+ if (!emailValidator(email)) {
117
+ throw new BadRequestError("Invalid email format");
118
+ }
119
+ // ...
120
+ },
121
+ });
122
+ ```
123
+
124
+ ## DynamoDB Models
125
+
126
+ See `skill("dynamodb")` for DynamoDB-specific patterns.
127
+
128
+ ```typescript
129
+ // Single-table design types
130
+ export interface DynamoItem {
131
+ pk: string; // Partition key
132
+ sk: string; // Sort key
133
+ type: string;
134
+ data: Record<string, unknown>;
135
+ createdAt: string;
136
+ updatedAt: string;
137
+ ttl?: number;
138
+ }
139
+
140
+ export interface UserItem extends DynamoItem {
141
+ type: "USER";
142
+ data: {
143
+ email: string;
144
+ name: string;
145
+ role: "user" | "admin";
146
+ };
147
+ }
148
+ ```
149
+
150
+ ## API Response Models
151
+
152
+ ```typescript
153
+ // Standard response wrapper
154
+ export interface ApiResponse<T> {
155
+ success: boolean;
156
+ data?: T;
157
+ error?: {
158
+ code: string;
159
+ message: string;
160
+ };
161
+ }
162
+
163
+ // Paginated response
164
+ export interface PaginatedResponse<T> {
165
+ items: T[];
166
+ nextToken?: string;
167
+ total?: number;
168
+ }
169
+ ```
170
+
171
+ ## Best Practices
172
+
173
+ 1. **Export types** - Make types available for consumers
174
+ 2. **Separate concerns** - Input, output, and storage types differ
175
+ 3. **Use const assertions** - `as const` for literal types
176
+ 4. **Document fields** - Add JSDoc comments for complex types
177
+ 5. **Prefer interfaces** - Use `interface` over `type` for objects
178
+
179
+ ## Type Documentation
180
+
181
+ ```typescript
182
+ /**
183
+ * Represents a user in the system.
184
+ * @property id - Unique identifier (UUID)
185
+ * @property email - Validated email address
186
+ * @property role - Access level for permissions
187
+ */
188
+ export interface User {
189
+ id: string;
190
+ email: string;
191
+ name: string;
192
+ role: "user" | "admin";
193
+ }
194
+ ```
195
+
@@ -0,0 +1,94 @@
1
+ ---
2
+ description: Version history and release notes
3
+ ---
4
+
5
+ # Release Notes
6
+
7
+ How to access and write release notes for Jaypie packages.
8
+
9
+ ## MCP Tools
10
+
11
+ ```
12
+ mcp__jaypie__list_release_notes()
13
+ mcp__jaypie__list_release_notes(package: "mcp")
14
+ mcp__jaypie__list_release_notes(package: "jaypie", since_version: "1.0.0")
15
+ mcp__jaypie__read_release_note(package: "mcp", version: "0.3.4")
16
+ ```
17
+
18
+ ## Directory Structure
19
+
20
+ ```
21
+ packages/mcp/release-notes/
22
+ ├── jaypie/
23
+ │ └── 1.2.3.md
24
+ ├── mcp/
25
+ │ └── 0.3.4.md
26
+ └── testkit/
27
+ └── 2.0.0.md
28
+ ```
29
+
30
+ ## File Format
31
+
32
+ Create `release-notes/<package>/<version>.md`:
33
+
34
+ ```yaml
35
+ ---
36
+ version: 0.3.4
37
+ date: 2025-01-20
38
+ summary: Brief one-line summary for listing
39
+ ---
40
+
41
+ ## Changes
42
+
43
+ ### New Features
44
+
45
+ - Feature description
46
+
47
+ ### Bug Fixes
48
+
49
+ - Fix description
50
+
51
+ ### Breaking Changes
52
+
53
+ - Breaking change description
54
+ ```
55
+
56
+ ## When to Add
57
+
58
+ Add release notes when:
59
+ - Bumping package version (required)
60
+ - Merging significant features
61
+ - Making breaking changes
62
+ - Fixing notable bugs
63
+
64
+ ## Writing Guidelines
65
+
66
+ 1. **Summary** - One line, present tense, describes the release
67
+ 2. **Changes** - Group by type: New Features, Bug Fixes, Breaking Changes
68
+ 3. **Bullets** - Start with verb (Add, Fix, Update, Remove)
69
+ 4. **Links** - Reference issues/PRs when relevant
70
+
71
+ ## Example
72
+
73
+ ```markdown
74
+ ---
75
+ version: 1.2.0
76
+ date: 2025-01-15
77
+ summary: Add streaming support for LLM providers
78
+ ---
79
+
80
+ ## Changes
81
+
82
+ ### New Features
83
+
84
+ - Add streaming response support for Anthropic and OpenAI
85
+ - Add `onChunk` callback for real-time token processing
86
+
87
+ ### Bug Fixes
88
+
89
+ - Fix timeout handling in concurrent requests
90
+
91
+ ### Breaking Changes
92
+
93
+ - Remove deprecated `legacyMode` option
94
+ ```
@@ -0,0 +1,155 @@
1
+ ---
2
+ description: Secret management with AWS Secrets Manager
3
+ related: aws, cdk, variables
4
+ ---
5
+
6
+ # Secret Management
7
+
8
+ Jaypie uses AWS Secrets Manager for secure credential storage.
9
+
10
+ ## Basic Usage
11
+
12
+ ```typescript
13
+ import { getSecret } from "jaypie";
14
+
15
+ const apiKey = await getSecret("my-api-key");
16
+ const dbUri = await getSecret("mongodb-connection-string");
17
+ ```
18
+
19
+ ## Environment Variables
20
+
21
+ Reference secrets via environment variables in CDK:
22
+
23
+ ```typescript
24
+ const handler = new JaypieLambda(this, "Handler", {
25
+ environment: {
26
+ SECRET_MONGODB_URI: "mongodb-connection-string",
27
+ SECRET_API_KEY: "third-party-api-key",
28
+ },
29
+ });
30
+ ```
31
+
32
+ In code:
33
+
34
+ ```typescript
35
+ const secretName = process.env.SECRET_MONGODB_URI;
36
+ const mongoUri = await getSecret(secretName);
37
+ ```
38
+
39
+ ## Creating Secrets
40
+
41
+ ### Via CDK
42
+
43
+ ```typescript
44
+ import { Secret } from "aws-cdk-lib/aws-secretsmanager";
45
+
46
+ const secret = new Secret(this, "ApiKey", {
47
+ secretName: `${projectKey}/api-key`,
48
+ description: "Third-party API key",
49
+ });
50
+
51
+ // Grant read access
52
+ secret.grantRead(lambdaFunction);
53
+ ```
54
+
55
+ ### Via AWS CLI
56
+
57
+ ```bash
58
+ aws secretsmanager create-secret \
59
+ --name "my-project/api-key" \
60
+ --secret-string "sk_live_abc123"
61
+ ```
62
+
63
+ ## Secret Naming Convention
64
+
65
+ Use project-prefixed names:
66
+
67
+ ```
68
+ {project-key}/{secret-name}
69
+
70
+ Examples:
71
+ - my-api/mongodb-uri
72
+ - my-api/stripe-key
73
+ - my-api/auth0-secret
74
+ ```
75
+
76
+ ## JSON Secrets
77
+
78
+ Store structured data:
79
+
80
+ ```bash
81
+ aws secretsmanager create-secret \
82
+ --name "my-project/db-credentials" \
83
+ --secret-string '{"username":"admin","password":"secret123"}'
84
+ ```
85
+
86
+ Retrieve in code:
87
+
88
+ ```typescript
89
+ const credentialsJson = await getSecret("my-project/db-credentials");
90
+ const credentials = JSON.parse(credentialsJson);
91
+ ```
92
+
93
+ ## Caching
94
+
95
+ Secrets are cached by default to reduce API calls:
96
+
97
+ ```typescript
98
+ // First call: fetches from Secrets Manager
99
+ const key1 = await getSecret("api-key");
100
+
101
+ // Second call: returns cached value
102
+ const key2 = await getSecret("api-key");
103
+ ```
104
+
105
+ Cache is scoped to Lambda execution context (warm starts reuse cache).
106
+
107
+ ## Rotation
108
+
109
+ Configure automatic rotation for supported secrets:
110
+
111
+ ```typescript
112
+ const secret = new Secret(this, "DbPassword", {
113
+ secretName: "my-project/db-password",
114
+ generateSecretString: {
115
+ excludePunctuation: true,
116
+ passwordLength: 32,
117
+ },
118
+ });
119
+
120
+ secret.addRotationSchedule("Rotation", {
121
+ automaticallyAfter: Duration.days(30),
122
+ rotationLambda: rotationFunction,
123
+ });
124
+ ```
125
+
126
+ ## Local Development
127
+
128
+ For local development, use environment variables:
129
+
130
+ ```bash
131
+ # .env.local (not committed)
132
+ MONGODB_URI=mongodb://localhost:27017/dev
133
+ API_KEY=test_key_123
134
+ ```
135
+
136
+ In code, check for direct value first:
137
+
138
+ ```typescript
139
+ const mongoUri = process.env.MONGODB_URI || await getSecret(process.env.SECRET_MONGODB_URI);
140
+ ```
141
+
142
+ ## IAM Permissions
143
+
144
+ Lambda needs `secretsmanager:GetSecretValue`:
145
+
146
+ ```typescript
147
+ secret.grantRead(lambdaFunction);
148
+
149
+ // Or via policy
150
+ lambdaFunction.addToRolePolicy(new PolicyStatement({
151
+ actions: ["secretsmanager:GetSecretValue"],
152
+ resources: [secret.secretArn],
153
+ }));
154
+ ```
155
+
@@ -0,0 +1,175 @@
1
+ ---
2
+ description: Service layer patterns and architecture
3
+ related: fabric, models, tests
4
+ ---
5
+
6
+ # Service Layer Patterns
7
+
8
+ Organizing business logic in Jaypie applications.
9
+
10
+ ## Service Structure
11
+
12
+ Keep business logic in service modules:
13
+
14
+ ```
15
+ src/
16
+ ├── handlers/ # Lambda/Express handlers
17
+ ├── services/ # Business logic
18
+ │ ├── user.ts
19
+ │ └── order.ts
20
+ ├── models/ # Data models
21
+ └── utils/ # Utilities
22
+ ```
23
+
24
+ ## Basic Service Pattern
25
+
26
+ ```typescript
27
+ // services/user.ts
28
+ import { log, NotFoundError, BadRequestError } from "jaypie";
29
+ import { User } from "../models/user.js";
30
+
31
+ export async function getUser(userId: string) {
32
+ log.debug("Getting user", { userId });
33
+
34
+ const user = await User.findById(userId);
35
+ if (!user) {
36
+ throw new NotFoundError(`User ${userId} not found`);
37
+ }
38
+
39
+ return user;
40
+ }
41
+
42
+ export async function createUser(input: UserCreateInput) {
43
+ log.info("Creating user", { email: input.email });
44
+
45
+ const existing = await User.findOne({ email: input.email });
46
+ if (existing) {
47
+ throw new BadRequestError("Email already registered");
48
+ }
49
+
50
+ return User.create(input);
51
+ }
52
+ ```
53
+
54
+ ## Handler Integration
55
+
56
+ Handlers call services:
57
+
58
+ ```typescript
59
+ // handlers/user.ts
60
+ import { lambdaHandler } from "@jaypie/lambda";
61
+ import { getUser, createUser } from "../services/user.js";
62
+
63
+ export const getUserHandler = lambdaHandler(async (event) => {
64
+ const { userId } = event.pathParameters;
65
+ return getUser(userId);
66
+ });
67
+
68
+ export const createUserHandler = lambdaHandler(async (event) => {
69
+ const input = JSON.parse(event.body);
70
+ return createUser(input);
71
+ });
72
+ ```
73
+
74
+ ## Service Dependencies
75
+
76
+ Inject dependencies for testability:
77
+
78
+ ```typescript
79
+ // services/notification.ts
80
+ import { log } from "jaypie";
81
+
82
+ export interface NotificationService {
83
+ sendEmail(to: string, subject: string, body: string): Promise<void>;
84
+ sendSms(to: string, message: string): Promise<void>;
85
+ }
86
+
87
+ export function createNotificationService(
88
+ emailClient: EmailClient,
89
+ smsClient: SmsClient
90
+ ): NotificationService {
91
+ return {
92
+ async sendEmail(to, subject, body) {
93
+ log.info("Sending email", { to, subject });
94
+ await emailClient.send({ to, subject, body });
95
+ },
96
+ async sendSms(to, message) {
97
+ log.info("Sending SMS", { to });
98
+ await smsClient.send({ to, message });
99
+ },
100
+ };
101
+ }
102
+ ```
103
+
104
+ ## Transaction Patterns
105
+
106
+ For DynamoDB operations that must succeed together, use TransactWriteItems:
107
+
108
+ ```typescript
109
+ import { TransactWriteItemsCommand } from "@aws-sdk/client-dynamodb";
110
+
111
+ export async function transferFunds(fromId: string, toId: string, amount: number) {
112
+ const from = await getAccount(fromId);
113
+
114
+ if (from.balance < amount) {
115
+ throw new BadRequestError("Insufficient funds");
116
+ }
117
+
118
+ const command = new TransactWriteItemsCommand({
119
+ TransactItems: [
120
+ {
121
+ Update: {
122
+ TableName: TABLE_NAME,
123
+ Key: { pk: { S: `ACCOUNT#${fromId}` }, sk: { S: "BALANCE" } },
124
+ UpdateExpression: "SET balance = balance - :amount",
125
+ ExpressionAttributeValues: { ":amount": { N: String(amount) } },
126
+ },
127
+ },
128
+ {
129
+ Update: {
130
+ TableName: TABLE_NAME,
131
+ Key: { pk: { S: `ACCOUNT#${toId}` }, sk: { S: "BALANCE" } },
132
+ UpdateExpression: "SET balance = balance + :amount",
133
+ ExpressionAttributeValues: { ":amount": { N: String(amount) } },
134
+ },
135
+ },
136
+ ],
137
+ });
138
+
139
+ await dynamoClient.send(command);
140
+ log.info("Transfer completed", { fromId, toId, amount });
141
+ }
142
+ ```
143
+
144
+ ## Service Testing
145
+
146
+ ```typescript
147
+ import { describe, it, expect, vi, beforeEach } from "vitest";
148
+ import { getUser } from "./user.js";
149
+ import { User } from "../models/user.js";
150
+
151
+ vi.mock("../models/user.js");
152
+
153
+ describe("getUser", () => {
154
+ beforeEach(() => {
155
+ vi.clearAllMocks();
156
+ });
157
+
158
+ it("returns user when found", async () => {
159
+ const mockUser = { id: "123", name: "John" };
160
+ vi.mocked(User.findById).mockResolvedValue(mockUser);
161
+
162
+ const result = await getUser("123");
163
+
164
+ expect(result).toEqual(mockUser);
165
+ expect(User.findById).toHaveBeenCalledWith("123");
166
+ });
167
+
168
+ it("throws NotFoundError when missing", async () => {
169
+ vi.mocked(User.findById).mockResolvedValue(null);
170
+
171
+ await expect(getUser("123")).rejects.toThrow(NotFoundError);
172
+ });
173
+ });
174
+ ```
175
+