ralph-hero-mcp-server 2.4.89 → 2.4.90
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.
|
@@ -14,7 +14,7 @@ import { resolveState } from "../lib/state-resolution.js";
|
|
|
14
14
|
import { parseDateMath } from "../lib/date-math.js";
|
|
15
15
|
import { expandProfile } from "../lib/filter-profiles.js";
|
|
16
16
|
import { toolSuccess, toolError } from "../types.js";
|
|
17
|
-
import { ensureFieldCache, resolveIssueNodeId, resolveProjectItemId, updateProjectItemField,
|
|
17
|
+
import { ensureFieldCache, resolveIssueNodeId, resolveProjectItemId, updateProjectItemField, resolveConfig, resolveFullConfig, resolveFullConfigOptionalRepo, } from "../lib/helpers.js";
|
|
18
18
|
// ---------------------------------------------------------------------------
|
|
19
19
|
// Register issue tools
|
|
20
20
|
// ---------------------------------------------------------------------------
|
|
@@ -876,198 +876,6 @@ export function registerIssueTools(server, client, fieldCache) {
|
|
|
876
876
|
}
|
|
877
877
|
});
|
|
878
878
|
// -------------------------------------------------------------------------
|
|
879
|
-
// ralph_hero__update_issue
|
|
880
|
-
// -------------------------------------------------------------------------
|
|
881
|
-
server.tool("ralph_hero__update_issue", "Update a GitHub issue's basic properties (title, body, labels, assignees). Returns: number, title, url. Use update_workflow_state for state changes, update_estimate for estimates, update_priority for priorities.", {
|
|
882
|
-
owner: z
|
|
883
|
-
.string()
|
|
884
|
-
.optional()
|
|
885
|
-
.describe("GitHub owner. Defaults to GITHUB_OWNER env var"),
|
|
886
|
-
repo: z
|
|
887
|
-
.string()
|
|
888
|
-
.optional()
|
|
889
|
-
.describe("Repository name. Defaults to GITHUB_REPO env var"),
|
|
890
|
-
number: z.coerce.number().describe("Issue number"),
|
|
891
|
-
title: z.string().optional().describe("New issue title"),
|
|
892
|
-
body: z.string().optional().describe("New issue body (Markdown)"),
|
|
893
|
-
labels: z
|
|
894
|
-
.array(z.string())
|
|
895
|
-
.optional()
|
|
896
|
-
.describe("Label names (replaces existing labels)"),
|
|
897
|
-
assignees: z
|
|
898
|
-
.array(z.string())
|
|
899
|
-
.optional()
|
|
900
|
-
.describe("GitHub usernames to assign (replaces existing)"),
|
|
901
|
-
}, async (args) => {
|
|
902
|
-
try {
|
|
903
|
-
const { owner, repo } = resolveConfig(client, args);
|
|
904
|
-
const issueId = await resolveIssueNodeId(client, owner, repo, args.number);
|
|
905
|
-
// Resolve label IDs if provided
|
|
906
|
-
let labelIds;
|
|
907
|
-
if (args.labels) {
|
|
908
|
-
const labelResult = await client.query(`query($owner: String!, $repo: String!) {
|
|
909
|
-
repository(owner: $owner, name: $repo) {
|
|
910
|
-
labels(first: 100) {
|
|
911
|
-
nodes { id name }
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
}`, { owner, repo }, { cache: true, cacheTtlMs: 5 * 60 * 1000 });
|
|
915
|
-
const allLabels = labelResult.repository.labels.nodes;
|
|
916
|
-
labelIds = args.labels
|
|
917
|
-
.map((name) => allLabels.find((l) => l.name === name)?.id)
|
|
918
|
-
.filter((id) => id !== undefined);
|
|
919
|
-
}
|
|
920
|
-
const result = await client.mutate(`mutation($issueId: ID!, $title: String, $body: String, $labelIds: [ID!], $assigneeIds: [ID!]) {
|
|
921
|
-
updateIssue(input: {
|
|
922
|
-
id: $issueId,
|
|
923
|
-
title: $title,
|
|
924
|
-
body: $body,
|
|
925
|
-
labelIds: $labelIds,
|
|
926
|
-
assigneeIds: $assigneeIds
|
|
927
|
-
}) {
|
|
928
|
-
issue {
|
|
929
|
-
number
|
|
930
|
-
title
|
|
931
|
-
url
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
}`, {
|
|
935
|
-
issueId,
|
|
936
|
-
title: args.title || null,
|
|
937
|
-
body: args.body || null,
|
|
938
|
-
labelIds: labelIds || null,
|
|
939
|
-
assigneeIds: null, // Would need username -> ID resolution
|
|
940
|
-
});
|
|
941
|
-
return toolSuccess({
|
|
942
|
-
number: result.updateIssue.issue.number,
|
|
943
|
-
title: result.updateIssue.issue.title,
|
|
944
|
-
url: result.updateIssue.issue.url,
|
|
945
|
-
});
|
|
946
|
-
}
|
|
947
|
-
catch (error) {
|
|
948
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
949
|
-
return toolError(`Failed to update issue: ${message}`);
|
|
950
|
-
}
|
|
951
|
-
});
|
|
952
|
-
// -------------------------------------------------------------------------
|
|
953
|
-
// ralph_hero__update_workflow_state
|
|
954
|
-
// -------------------------------------------------------------------------
|
|
955
|
-
server.tool("ralph_hero__update_workflow_state", "Change an issue's Workflow State using semantic intents or direct state names. Returns: number, previousState, newState, command. Semantic intents: __LOCK__ (lock for processing), __COMPLETE__ (mark done), __ESCALATE__ (needs human), __CLOSE__, __CANCEL__. Recovery: if state transition fails, verify the issue is in the project and the state name is valid.", {
|
|
956
|
-
owner: z
|
|
957
|
-
.string()
|
|
958
|
-
.optional()
|
|
959
|
-
.describe("GitHub owner. Defaults to GITHUB_OWNER env var"),
|
|
960
|
-
repo: z
|
|
961
|
-
.string()
|
|
962
|
-
.optional()
|
|
963
|
-
.describe("Repository name. Defaults to GITHUB_REPO env var"),
|
|
964
|
-
projectNumber: z.coerce.number().optional()
|
|
965
|
-
.describe("Project number override (defaults to configured project)"),
|
|
966
|
-
number: z.coerce.number().describe("Issue number"),
|
|
967
|
-
state: z
|
|
968
|
-
.string()
|
|
969
|
-
.describe("Target state: semantic intent (__LOCK__, __COMPLETE__, __ESCALATE__, __CLOSE__, __CANCEL__) " +
|
|
970
|
-
"or direct state name (e.g., 'Research Needed', 'In Progress')"),
|
|
971
|
-
command: z
|
|
972
|
-
.string()
|
|
973
|
-
.describe("Ralph command making this transition (e.g., 'ralph_research', 'ralph_plan'). " +
|
|
974
|
-
"Required for validation and semantic intent resolution."),
|
|
975
|
-
}, async (args) => {
|
|
976
|
-
try {
|
|
977
|
-
const { owner, repo, projectNumber, projectOwner } = resolveFullConfig(client, args);
|
|
978
|
-
// Resolve semantic intent or validate direct state
|
|
979
|
-
const { resolvedState, wasIntent, originalState } = resolveState(args.state, args.command);
|
|
980
|
-
// Ensure field cache is populated
|
|
981
|
-
await ensureFieldCache(client, fieldCache, projectOwner, projectNumber);
|
|
982
|
-
// Get current state for the response
|
|
983
|
-
const previousState = await getCurrentFieldValue(client, fieldCache, owner, repo, args.number, "Workflow State", projectNumber);
|
|
984
|
-
// Resolve project item ID
|
|
985
|
-
const projectItemId = await resolveProjectItemId(client, fieldCache, owner, repo, args.number, projectNumber);
|
|
986
|
-
// Update the field with the resolved state
|
|
987
|
-
await updateProjectItemField(client, fieldCache, projectItemId, "Workflow State", resolvedState, projectNumber);
|
|
988
|
-
// Sync default Status field (best-effort, one-way)
|
|
989
|
-
await syncStatusField(client, fieldCache, projectItemId, resolvedState, projectNumber);
|
|
990
|
-
const result = {
|
|
991
|
-
number: args.number,
|
|
992
|
-
previousState: previousState || "(unknown)",
|
|
993
|
-
newState: resolvedState,
|
|
994
|
-
command: args.command,
|
|
995
|
-
};
|
|
996
|
-
if (wasIntent) {
|
|
997
|
-
result.resolvedFrom = originalState;
|
|
998
|
-
}
|
|
999
|
-
return toolSuccess(result);
|
|
1000
|
-
}
|
|
1001
|
-
catch (error) {
|
|
1002
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1003
|
-
return toolError(`Failed to update workflow state: ${message}`);
|
|
1004
|
-
}
|
|
1005
|
-
});
|
|
1006
|
-
// -------------------------------------------------------------------------
|
|
1007
|
-
// ralph_hero__update_estimate
|
|
1008
|
-
// -------------------------------------------------------------------------
|
|
1009
|
-
server.tool("ralph_hero__update_estimate", "Change an issue's Estimate in the project. Returns: number, estimate. Valid values: XS, S, M, L, XL. Recovery: if the issue is not in the project, add it first via create_issue.", {
|
|
1010
|
-
owner: z
|
|
1011
|
-
.string()
|
|
1012
|
-
.optional()
|
|
1013
|
-
.describe("GitHub owner. Defaults to GITHUB_OWNER env var"),
|
|
1014
|
-
repo: z
|
|
1015
|
-
.string()
|
|
1016
|
-
.optional()
|
|
1017
|
-
.describe("Repository name. Defaults to GITHUB_REPO env var"),
|
|
1018
|
-
projectNumber: z.coerce.number().optional()
|
|
1019
|
-
.describe("Project number override (defaults to configured project)"),
|
|
1020
|
-
number: z.coerce.number().describe("Issue number"),
|
|
1021
|
-
estimate: z.string().describe("Estimate value (XS, S, M, L, XL)"),
|
|
1022
|
-
}, async (args) => {
|
|
1023
|
-
try {
|
|
1024
|
-
const { owner, repo, projectNumber, projectOwner } = resolveFullConfig(client, args);
|
|
1025
|
-
await ensureFieldCache(client, fieldCache, projectOwner, projectNumber);
|
|
1026
|
-
const projectItemId = await resolveProjectItemId(client, fieldCache, owner, repo, args.number, projectNumber);
|
|
1027
|
-
await updateProjectItemField(client, fieldCache, projectItemId, "Estimate", args.estimate, projectNumber);
|
|
1028
|
-
return toolSuccess({
|
|
1029
|
-
number: args.number,
|
|
1030
|
-
estimate: args.estimate,
|
|
1031
|
-
});
|
|
1032
|
-
}
|
|
1033
|
-
catch (error) {
|
|
1034
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1035
|
-
return toolError(`Failed to update estimate: ${message}`);
|
|
1036
|
-
}
|
|
1037
|
-
});
|
|
1038
|
-
// -------------------------------------------------------------------------
|
|
1039
|
-
// ralph_hero__update_priority
|
|
1040
|
-
// -------------------------------------------------------------------------
|
|
1041
|
-
server.tool("ralph_hero__update_priority", "Change an issue's Priority in the project. Returns: number, priority. Valid values: P0, P1, P2, P3. Recovery: if the issue is not in the project, add it first via create_issue.", {
|
|
1042
|
-
owner: z
|
|
1043
|
-
.string()
|
|
1044
|
-
.optional()
|
|
1045
|
-
.describe("GitHub owner. Defaults to GITHUB_OWNER env var"),
|
|
1046
|
-
repo: z
|
|
1047
|
-
.string()
|
|
1048
|
-
.optional()
|
|
1049
|
-
.describe("Repository name. Defaults to GITHUB_REPO env var"),
|
|
1050
|
-
projectNumber: z.coerce.number().optional()
|
|
1051
|
-
.describe("Project number override (defaults to configured project)"),
|
|
1052
|
-
number: z.coerce.number().describe("Issue number"),
|
|
1053
|
-
priority: z.string().describe("Priority value (P0, P1, P2, P3)"),
|
|
1054
|
-
}, async (args) => {
|
|
1055
|
-
try {
|
|
1056
|
-
const { owner, repo, projectNumber, projectOwner } = resolveFullConfig(client, args);
|
|
1057
|
-
await ensureFieldCache(client, fieldCache, projectOwner, projectNumber);
|
|
1058
|
-
const projectItemId = await resolveProjectItemId(client, fieldCache, owner, repo, args.number, projectNumber);
|
|
1059
|
-
await updateProjectItemField(client, fieldCache, projectItemId, "Priority", args.priority, projectNumber);
|
|
1060
|
-
return toolSuccess({
|
|
1061
|
-
number: args.number,
|
|
1062
|
-
priority: args.priority,
|
|
1063
|
-
});
|
|
1064
|
-
}
|
|
1065
|
-
catch (error) {
|
|
1066
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1067
|
-
return toolError(`Failed to update priority: ${message}`);
|
|
1068
|
-
}
|
|
1069
|
-
});
|
|
1070
|
-
// -------------------------------------------------------------------------
|
|
1071
879
|
// ralph_hero__create_comment
|
|
1072
880
|
// -------------------------------------------------------------------------
|
|
1073
881
|
server.tool("ralph_hero__create_comment", "Add a comment to a GitHub issue. Returns: commentId, issueNumber. Recovery: if issue not found, verify the issue number exists in the repository.", {
|
|
@@ -242,51 +242,6 @@ export function registerProjectManagementTools(server, client, fieldCache) {
|
|
|
242
242
|
}
|
|
243
243
|
});
|
|
244
244
|
// -------------------------------------------------------------------------
|
|
245
|
-
// ralph_hero__clear_field
|
|
246
|
-
// -------------------------------------------------------------------------
|
|
247
|
-
server.tool("ralph_hero__clear_field", "Clear a field value on a project item. Works for any single-select field (Workflow State, Estimate, Priority, Status, etc.). Returns: number, field, cleared.", {
|
|
248
|
-
owner: z.string().optional().describe("GitHub owner. Defaults to env var"),
|
|
249
|
-
repo: z.string().optional().describe("Repository name. Defaults to env var"),
|
|
250
|
-
projectNumber: z.coerce.number().optional()
|
|
251
|
-
.describe("Project number override (defaults to configured project)"),
|
|
252
|
-
number: z.coerce.number().describe("Issue number"),
|
|
253
|
-
field: z.string().describe("Field name to clear (e.g., 'Estimate', 'Priority', 'Workflow State')"),
|
|
254
|
-
}, async (args) => {
|
|
255
|
-
try {
|
|
256
|
-
const { owner, repo, projectNumber, projectOwner } = resolveFullConfig(client, args);
|
|
257
|
-
await ensureFieldCache(client, fieldCache, projectOwner, projectNumber);
|
|
258
|
-
const projectId = fieldCache.getProjectId(projectNumber);
|
|
259
|
-
if (!projectId) {
|
|
260
|
-
return toolError("Could not resolve project ID");
|
|
261
|
-
}
|
|
262
|
-
const fieldId = fieldCache.getFieldId(args.field, projectNumber);
|
|
263
|
-
if (!fieldId) {
|
|
264
|
-
const validFields = fieldCache.getFieldNames(projectNumber);
|
|
265
|
-
return toolError(`Field "${args.field}" not found in project. ` +
|
|
266
|
-
`Valid fields: ${validFields.join(", ")}`);
|
|
267
|
-
}
|
|
268
|
-
const projectItemId = await resolveProjectItemId(client, fieldCache, owner, repo, args.number, projectNumber);
|
|
269
|
-
await client.projectMutate(`mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!) {
|
|
270
|
-
clearProjectV2ItemFieldValue(input: {
|
|
271
|
-
projectId: $projectId,
|
|
272
|
-
itemId: $itemId,
|
|
273
|
-
fieldId: $fieldId
|
|
274
|
-
}) {
|
|
275
|
-
projectV2Item { id }
|
|
276
|
-
}
|
|
277
|
-
}`, { projectId, itemId: projectItemId, fieldId });
|
|
278
|
-
return toolSuccess({
|
|
279
|
-
number: args.number,
|
|
280
|
-
field: args.field,
|
|
281
|
-
cleared: true,
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
catch (error) {
|
|
285
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
286
|
-
return toolError(`Failed to clear field: ${message}`);
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
// -------------------------------------------------------------------------
|
|
290
245
|
// ralph_hero__create_draft_issue
|
|
291
246
|
// -------------------------------------------------------------------------
|
|
292
247
|
server.tool("ralph_hero__create_draft_issue", "Create a draft issue in the project (no repo required). Optionally set workflow state, priority, and estimate after creation. Returns: projectItemId, title, fieldsSet.", {
|