@jaypie/mcp 0.3.0 → 0.3.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/index.js +201 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
- package/prompts/Jaypie_CDK_Constructs_and_Patterns.md +4 -5
- package/prompts/Jaypie_Fabric_MCP.md +22 -2
- package/prompts/Jaypie_Init_Lambda_Package.md +8 -0
- package/prompts/Jaypie_MCP_Package.md +34 -2
- package/prompts/Jaypie_Streaming.md +90 -31
- package/release-notes/fabric/0.1.1.md +17 -0
- package/release-notes/mcp/0.3.2.md +14 -0
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
import * as fs from 'node:fs/promises';
|
|
10
10
|
import matter from 'gray-matter';
|
|
11
|
+
import { gt } from 'semver';
|
|
11
12
|
import * as https from 'node:https';
|
|
12
13
|
import { Llm } from '@jaypie/llm';
|
|
13
14
|
import { spawn } from 'node:child_process';
|
|
@@ -1208,11 +1209,12 @@ async function purgeSQSQueue(options, logger = nullLogger) {
|
|
|
1208
1209
|
return executeAwsCommand("sqs", "purge-queue", ["--queue-url", options.queueUrl], { profile: options.profile, region: options.region }, logger);
|
|
1209
1210
|
}
|
|
1210
1211
|
|
|
1211
|
-
const BUILD_VERSION_STRING = "@jaypie/mcp@0.3.
|
|
1212
|
+
const BUILD_VERSION_STRING = "@jaypie/mcp@0.3.2#f7a87775"
|
|
1212
1213
|
;
|
|
1213
1214
|
const __filename$1 = fileURLToPath(import.meta.url);
|
|
1214
1215
|
const __dirname$1 = path.dirname(__filename$1);
|
|
1215
1216
|
const PROMPTS_PATH = path.join(__dirname$1, "..", "prompts");
|
|
1217
|
+
const RELEASE_NOTES_PATH = path.join(__dirname$1, "..", "release-notes");
|
|
1216
1218
|
// Logger utility
|
|
1217
1219
|
function createLogger(verbose) {
|
|
1218
1220
|
return {
|
|
@@ -1260,6 +1262,75 @@ function formatPromptListItem(prompt) {
|
|
|
1260
1262
|
return `* ${filename}`;
|
|
1261
1263
|
}
|
|
1262
1264
|
}
|
|
1265
|
+
async function parseReleaseNoteFile(filePath) {
|
|
1266
|
+
try {
|
|
1267
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
1268
|
+
const filename = path.basename(filePath, ".md");
|
|
1269
|
+
if (content.startsWith("---")) {
|
|
1270
|
+
const parsed = matter(content);
|
|
1271
|
+
const frontMatter = parsed.data;
|
|
1272
|
+
return {
|
|
1273
|
+
date: frontMatter.date,
|
|
1274
|
+
filename,
|
|
1275
|
+
summary: frontMatter.summary,
|
|
1276
|
+
version: frontMatter.version || filename,
|
|
1277
|
+
};
|
|
1278
|
+
}
|
|
1279
|
+
return { filename, version: filename };
|
|
1280
|
+
}
|
|
1281
|
+
catch {
|
|
1282
|
+
return { filename: path.basename(filePath, ".md") };
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
function formatReleaseNoteListItem(note) {
|
|
1286
|
+
const { date, packageName, summary, version } = note;
|
|
1287
|
+
const parts = [`* ${packageName}@${version}`];
|
|
1288
|
+
if (date) {
|
|
1289
|
+
parts.push(`(${date})`);
|
|
1290
|
+
}
|
|
1291
|
+
if (summary) {
|
|
1292
|
+
parts.push(`- ${summary}`);
|
|
1293
|
+
}
|
|
1294
|
+
return parts.join(" ");
|
|
1295
|
+
}
|
|
1296
|
+
async function getPackageReleaseNotes(packageName) {
|
|
1297
|
+
const packageDir = path.join(RELEASE_NOTES_PATH, packageName);
|
|
1298
|
+
try {
|
|
1299
|
+
const files = await fs.readdir(packageDir);
|
|
1300
|
+
const mdFiles = files.filter((file) => file.endsWith(".md"));
|
|
1301
|
+
const notes = await Promise.all(mdFiles.map(async (file) => {
|
|
1302
|
+
const parsed = await parseReleaseNoteFile(path.join(packageDir, file));
|
|
1303
|
+
return { ...parsed, packageName };
|
|
1304
|
+
}));
|
|
1305
|
+
// Sort by version descending (newest first)
|
|
1306
|
+
return notes.sort((a, b) => {
|
|
1307
|
+
if (!a.version || !b.version)
|
|
1308
|
+
return 0;
|
|
1309
|
+
try {
|
|
1310
|
+
return gt(a.version, b.version) ? -1 : 1;
|
|
1311
|
+
}
|
|
1312
|
+
catch {
|
|
1313
|
+
// If semver comparison fails, fall back to string comparison
|
|
1314
|
+
return b.version.localeCompare(a.version);
|
|
1315
|
+
}
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
catch {
|
|
1319
|
+
return [];
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
function filterReleaseNotesSince(notes, sinceVersion) {
|
|
1323
|
+
return notes.filter((note) => {
|
|
1324
|
+
if (!note.version)
|
|
1325
|
+
return false;
|
|
1326
|
+
try {
|
|
1327
|
+
return gt(note.version, sinceVersion);
|
|
1328
|
+
}
|
|
1329
|
+
catch {
|
|
1330
|
+
return false;
|
|
1331
|
+
}
|
|
1332
|
+
});
|
|
1333
|
+
}
|
|
1263
1334
|
/**
|
|
1264
1335
|
* Creates and configures an MCP server instance with Jaypie tools
|
|
1265
1336
|
* @param options - Configuration options (or legacy version string)
|
|
@@ -1367,6 +1438,135 @@ function createMcpServer(options = {}) {
|
|
|
1367
1438
|
};
|
|
1368
1439
|
});
|
|
1369
1440
|
log.info("Registered tool: version");
|
|
1441
|
+
// Release Notes Tools
|
|
1442
|
+
server.tool("list_release_notes", "List available release notes for Jaypie packages. Filter by package name and/or get only versions newer than a specified version.", {
|
|
1443
|
+
package: z
|
|
1444
|
+
.string()
|
|
1445
|
+
.optional()
|
|
1446
|
+
.describe("Filter by package name (e.g., 'jaypie', 'mcp'). If not provided, lists release notes for all packages."),
|
|
1447
|
+
since_version: z
|
|
1448
|
+
.string()
|
|
1449
|
+
.optional()
|
|
1450
|
+
.describe("Only show versions newer than this (e.g., '1.0.0'). Uses semver comparison."),
|
|
1451
|
+
}, async ({ package: packageFilter, since_version: sinceVersion }) => {
|
|
1452
|
+
log.info("Tool called: list_release_notes");
|
|
1453
|
+
log.info(`Release notes directory: ${RELEASE_NOTES_PATH}`);
|
|
1454
|
+
try {
|
|
1455
|
+
// Get list of package directories
|
|
1456
|
+
const entries = await fs.readdir(RELEASE_NOTES_PATH, {
|
|
1457
|
+
withFileTypes: true,
|
|
1458
|
+
});
|
|
1459
|
+
const packageDirs = entries
|
|
1460
|
+
.filter((entry) => entry.isDirectory())
|
|
1461
|
+
.map((entry) => entry.name);
|
|
1462
|
+
log.info(`Found ${packageDirs.length} package directories`);
|
|
1463
|
+
// Filter by package if specified
|
|
1464
|
+
const packagesToList = packageFilter
|
|
1465
|
+
? packageDirs.filter((pkg) => pkg === packageFilter)
|
|
1466
|
+
: packageDirs;
|
|
1467
|
+
if (packagesToList.length === 0 && packageFilter) {
|
|
1468
|
+
return {
|
|
1469
|
+
content: [
|
|
1470
|
+
{
|
|
1471
|
+
type: "text",
|
|
1472
|
+
text: `No release notes found for package "${packageFilter}".`,
|
|
1473
|
+
},
|
|
1474
|
+
],
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1477
|
+
// Get release notes for each package
|
|
1478
|
+
const allNotes = await Promise.all(packagesToList.map((pkg) => getPackageReleaseNotes(pkg)));
|
|
1479
|
+
let flatNotes = allNotes.flat();
|
|
1480
|
+
// Filter by since_version if specified
|
|
1481
|
+
if (sinceVersion) {
|
|
1482
|
+
flatNotes = filterReleaseNotesSince(flatNotes, sinceVersion);
|
|
1483
|
+
}
|
|
1484
|
+
if (flatNotes.length === 0) {
|
|
1485
|
+
const filterDesc = sinceVersion
|
|
1486
|
+
? ` newer than ${sinceVersion}`
|
|
1487
|
+
: "";
|
|
1488
|
+
return {
|
|
1489
|
+
content: [
|
|
1490
|
+
{
|
|
1491
|
+
type: "text",
|
|
1492
|
+
text: `No release notes found${filterDesc}.`,
|
|
1493
|
+
},
|
|
1494
|
+
],
|
|
1495
|
+
};
|
|
1496
|
+
}
|
|
1497
|
+
const formattedList = flatNotes
|
|
1498
|
+
.map(formatReleaseNoteListItem)
|
|
1499
|
+
.join("\n");
|
|
1500
|
+
log.info(`Successfully listed ${flatNotes.length} release notes`);
|
|
1501
|
+
return {
|
|
1502
|
+
content: [
|
|
1503
|
+
{
|
|
1504
|
+
type: "text",
|
|
1505
|
+
text: formattedList,
|
|
1506
|
+
},
|
|
1507
|
+
],
|
|
1508
|
+
};
|
|
1509
|
+
}
|
|
1510
|
+
catch (error) {
|
|
1511
|
+
log.error("Error listing release notes:", error);
|
|
1512
|
+
return {
|
|
1513
|
+
content: [
|
|
1514
|
+
{
|
|
1515
|
+
type: "text",
|
|
1516
|
+
text: `Error listing release notes: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
1517
|
+
},
|
|
1518
|
+
],
|
|
1519
|
+
};
|
|
1520
|
+
}
|
|
1521
|
+
});
|
|
1522
|
+
log.info("Registered tool: list_release_notes");
|
|
1523
|
+
server.tool("read_release_note", "Read the full content of a specific release note. Call list_release_notes first to see available versions.", {
|
|
1524
|
+
package: z
|
|
1525
|
+
.string()
|
|
1526
|
+
.describe("Package name (e.g., 'jaypie', 'mcp')"),
|
|
1527
|
+
version: z
|
|
1528
|
+
.string()
|
|
1529
|
+
.describe("Version number (e.g., '1.2.3')"),
|
|
1530
|
+
}, async ({ package: packageName, version }) => {
|
|
1531
|
+
log.info(`Tool called: read_release_note (package: ${packageName}, version: ${version})`);
|
|
1532
|
+
try {
|
|
1533
|
+
const filePath = path.join(RELEASE_NOTES_PATH, packageName, `${version}.md`);
|
|
1534
|
+
log.info(`Reading file: ${filePath}`);
|
|
1535
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
1536
|
+
log.info(`Successfully read release note for ${packageName}@${version} (${content.length} bytes)`);
|
|
1537
|
+
return {
|
|
1538
|
+
content: [
|
|
1539
|
+
{
|
|
1540
|
+
type: "text",
|
|
1541
|
+
text: content,
|
|
1542
|
+
},
|
|
1543
|
+
],
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
catch (error) {
|
|
1547
|
+
if (error.code === "ENOENT") {
|
|
1548
|
+
log.error(`Release note not found: ${packageName}@${version}`);
|
|
1549
|
+
return {
|
|
1550
|
+
content: [
|
|
1551
|
+
{
|
|
1552
|
+
type: "text",
|
|
1553
|
+
text: `Error: Release note for "${packageName}@${version}" not found. Use list_release_notes to see available versions.`,
|
|
1554
|
+
},
|
|
1555
|
+
],
|
|
1556
|
+
};
|
|
1557
|
+
}
|
|
1558
|
+
log.error("Error reading release note:", error);
|
|
1559
|
+
return {
|
|
1560
|
+
content: [
|
|
1561
|
+
{
|
|
1562
|
+
type: "text",
|
|
1563
|
+
text: `Error reading release note: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
1564
|
+
},
|
|
1565
|
+
],
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
});
|
|
1569
|
+
log.info("Registered tool: read_release_note");
|
|
1370
1570
|
// Datadog Logs Tool
|
|
1371
1571
|
server.tool("datadog_logs", "Search and retrieve individual Datadog log entries. Use this to view actual log messages and details. For aggregated counts/statistics (e.g., 'how many errors by service?'), use datadog_log_analytics instead. Requires DATADOG_API_KEY and DATADOG_APP_KEY environment variables.", {
|
|
1372
1572
|
query: z
|