ralph-hero-mcp-server 2.4.73 → 2.4.74
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.
|
@@ -446,6 +446,158 @@ export function registerProjectManagementTools(server, client, fieldCache) {
|
|
|
446
446
|
}
|
|
447
447
|
});
|
|
448
448
|
// -------------------------------------------------------------------------
|
|
449
|
+
// ralph_hero__get_draft_issue
|
|
450
|
+
// -------------------------------------------------------------------------
|
|
451
|
+
server.tool("ralph_hero__get_draft_issue", "Get the full content of one or more draft issues. Accepts DI_ (content node) or PVTI_ (project item) IDs — auto-detected by prefix. PVTI_ IDs also return project field values. Returns: array of { draftIssueId, projectItemId, title, body, creator, createdAt, updatedAt, workflowState?, estimate?, priority? }.", {
|
|
452
|
+
owner: z.string().optional().describe("GitHub owner. Defaults to env var"),
|
|
453
|
+
repo: z.string().optional().describe("Repository name. Defaults to env var"),
|
|
454
|
+
projectNumber: z.coerce.number().optional()
|
|
455
|
+
.describe("Project number override (defaults to configured project)"),
|
|
456
|
+
ids: z.union([
|
|
457
|
+
z.string().describe("Single draft issue ID (DI_... or PVTI_...)"),
|
|
458
|
+
z.array(z.string()).describe("Array of draft issue IDs"),
|
|
459
|
+
]).describe("One or more draft issue IDs. DI_ prefix fetches content only. PVTI_ prefix also fetches project field values."),
|
|
460
|
+
}, async (args) => {
|
|
461
|
+
try {
|
|
462
|
+
const idList = Array.isArray(args.ids) ? args.ids : [args.ids];
|
|
463
|
+
if (idList.length === 0) {
|
|
464
|
+
return toolError("At least one ID must be provided");
|
|
465
|
+
}
|
|
466
|
+
// Validate all IDs have valid prefixes
|
|
467
|
+
const invalidIds = idList.filter((id) => !id.startsWith("DI_") && !id.startsWith("PVTI_"));
|
|
468
|
+
if (invalidIds.length > 0) {
|
|
469
|
+
return toolError(`Invalid ID prefix(es): ${invalidIds.join(", ")}. IDs must start with DI_ or PVTI_.`);
|
|
470
|
+
}
|
|
471
|
+
// Partition into DI_ and PVTI_ groups
|
|
472
|
+
const diIds = [];
|
|
473
|
+
const pvtiIds = [];
|
|
474
|
+
for (let i = 0; i < idList.length; i++) {
|
|
475
|
+
if (idList[i].startsWith("DI_")) {
|
|
476
|
+
diIds.push({ id: idList[i], index: i });
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
pvtiIds.push({ id: idList[i], index: i });
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
// Build aliased GraphQL query
|
|
483
|
+
const queryParts = [];
|
|
484
|
+
const variables = {};
|
|
485
|
+
const variableDecls = [];
|
|
486
|
+
for (let i = 0; i < diIds.length; i++) {
|
|
487
|
+
const varName = `diId${i}`;
|
|
488
|
+
variableDecls.push(`$${varName}: ID!`);
|
|
489
|
+
variables[varName] = diIds[i].id;
|
|
490
|
+
queryParts.push(`
|
|
491
|
+
draft${i}: node(id: $${varName}) {
|
|
492
|
+
... on DraftIssue {
|
|
493
|
+
id
|
|
494
|
+
title
|
|
495
|
+
body
|
|
496
|
+
creator { login }
|
|
497
|
+
createdAt
|
|
498
|
+
updatedAt
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
`);
|
|
502
|
+
}
|
|
503
|
+
for (let i = 0; i < pvtiIds.length; i++) {
|
|
504
|
+
const varName = `pvtiId${i}`;
|
|
505
|
+
variableDecls.push(`$${varName}: ID!`);
|
|
506
|
+
variables[varName] = pvtiIds[i].id;
|
|
507
|
+
queryParts.push(`
|
|
508
|
+
item${i}: node(id: $${varName}) {
|
|
509
|
+
... on ProjectV2Item {
|
|
510
|
+
id
|
|
511
|
+
content {
|
|
512
|
+
... on DraftIssue {
|
|
513
|
+
id
|
|
514
|
+
title
|
|
515
|
+
body
|
|
516
|
+
creator { login }
|
|
517
|
+
createdAt
|
|
518
|
+
updatedAt
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
fieldValues(first: 20) {
|
|
522
|
+
nodes {
|
|
523
|
+
... on ProjectV2ItemFieldSingleSelectValue {
|
|
524
|
+
name
|
|
525
|
+
field { ... on ProjectV2FieldCommon { name } }
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
`);
|
|
532
|
+
}
|
|
533
|
+
const fullQuery = `query(${variableDecls.join(", ")}) {\n${queryParts.join("\n")}\n}`;
|
|
534
|
+
const result = await client.projectQuery(fullQuery, variables);
|
|
535
|
+
const drafts = [];
|
|
536
|
+
// Process DI_ results
|
|
537
|
+
for (let i = 0; i < diIds.length; i++) {
|
|
538
|
+
const node = result[`draft${i}`];
|
|
539
|
+
if (!node || !node.id) {
|
|
540
|
+
drafts.push({ id: diIds[i].id, error: "Not found" });
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
drafts.push({
|
|
544
|
+
draftIssueId: node.id,
|
|
545
|
+
projectItemId: null,
|
|
546
|
+
title: node.title ?? "",
|
|
547
|
+
body: node.body ?? null,
|
|
548
|
+
creator: node.creator?.login ?? null,
|
|
549
|
+
createdAt: node.createdAt ?? null,
|
|
550
|
+
updatedAt: node.updatedAt ?? null,
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
// Process PVTI_ results
|
|
555
|
+
for (let i = 0; i < pvtiIds.length; i++) {
|
|
556
|
+
const node = result[`item${i}`];
|
|
557
|
+
if (!node || !node.id) {
|
|
558
|
+
drafts.push({ id: pvtiIds[i].id, error: "Not found" });
|
|
559
|
+
}
|
|
560
|
+
else if (!node.content || !node.content.id) {
|
|
561
|
+
drafts.push({ id: pvtiIds[i].id, error: "Not a draft issue" });
|
|
562
|
+
}
|
|
563
|
+
else {
|
|
564
|
+
// Extract field values
|
|
565
|
+
let workflowState;
|
|
566
|
+
let estimate;
|
|
567
|
+
let priority;
|
|
568
|
+
if (node.fieldValues?.nodes) {
|
|
569
|
+
for (const fv of node.fieldValues.nodes) {
|
|
570
|
+
const fieldName = fv.field?.name;
|
|
571
|
+
if (fieldName === "Workflow State")
|
|
572
|
+
workflowState = fv.name;
|
|
573
|
+
else if (fieldName === "Estimate")
|
|
574
|
+
estimate = fv.name;
|
|
575
|
+
else if (fieldName === "Priority")
|
|
576
|
+
priority = fv.name;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
drafts.push({
|
|
580
|
+
draftIssueId: node.content.id,
|
|
581
|
+
projectItemId: pvtiIds[i].id,
|
|
582
|
+
title: node.content.title ?? "",
|
|
583
|
+
body: node.content.body ?? null,
|
|
584
|
+
creator: node.content.creator?.login ?? null,
|
|
585
|
+
createdAt: node.content.createdAt ?? null,
|
|
586
|
+
updatedAt: node.content.updatedAt ?? null,
|
|
587
|
+
...(workflowState !== undefined && { workflowState }),
|
|
588
|
+
...(estimate !== undefined && { estimate }),
|
|
589
|
+
...(priority !== undefined && { priority }),
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
return toolSuccess({ drafts });
|
|
594
|
+
}
|
|
595
|
+
catch (error) {
|
|
596
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
597
|
+
return toolError(`Failed to get draft issue(s): ${message}`);
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
// -------------------------------------------------------------------------
|
|
449
601
|
// ralph_hero__reorder_item
|
|
450
602
|
// -------------------------------------------------------------------------
|
|
451
603
|
server.tool("ralph_hero__reorder_item", "Set item position within project views. Moves an issue before or after another item. Omit afterNumber to move to the top. Returns: number, position.", {
|