@gethmy/mcp 2.11.0 → 2.11.1

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/cli.js CHANGED
@@ -1913,6 +1913,12 @@ class HarmonyApiClient {
1913
1913
  async startAgentSession(cardId, data) {
1914
1914
  return this.request("POST", `/cards/${cardId}/agent-context`, data);
1915
1915
  }
1916
+ async getPendingMessages(cardId, sessionId, sinceSeq) {
1917
+ const params = new URLSearchParams;
1918
+ params.set("sessionId", sessionId);
1919
+ params.set("sinceSeq", String(sinceSeq));
1920
+ return this.request("GET", `/cards/${cardId}/agent-messages?${params.toString()}`);
1921
+ }
1916
1922
  async updateAgentProgress(cardId, data) {
1917
1923
  return this.request("POST", `/cards/${cardId}/agent-context`, data);
1918
1924
  }
@@ -4172,6 +4178,10 @@ var TOOLS = {
4172
4178
  type: "array",
4173
4179
  items: { type: "string" },
4174
4180
  description: 'Label names to add to card (e.g., ["agent"]). Case-insensitive match.'
4181
+ },
4182
+ steerable: {
4183
+ type: "boolean",
4184
+ description: "Set true only if this session will poll harmony_get_pending_messages at its checkpoints. Enables the live steering composer for the run; leave unset/false if you won't consume steering messages."
4175
4185
  }
4176
4186
  },
4177
4187
  required: ["cardId", "agentIdentifier", "agentName"]
@@ -4262,6 +4272,27 @@ var TOOLS = {
4262
4272
  required: ["cardId"]
4263
4273
  }
4264
4274
  },
4275
+ harmony_get_pending_messages: {
4276
+ description: "Drain queued steering messages a teammate sent to your live agent session (card #473). Call at your progress checkpoints with the session id from harmony_start_agent_session and the highest seq you've already consumed; returns user messages with seq > sinceSeq, oldest first. Fold them into your next step and advance sinceSeq to the largest returned seq so each is handled exactly once.",
4277
+ inputSchema: {
4278
+ type: "object",
4279
+ properties: {
4280
+ cardId: {
4281
+ type: "string",
4282
+ description: "Card ID with the live session"
4283
+ },
4284
+ sessionId: {
4285
+ type: "string",
4286
+ description: "Agent session id (the `session.id` returned by harmony_start_agent_session)"
4287
+ },
4288
+ sinceSeq: {
4289
+ type: "number",
4290
+ description: "Return only messages with seq greater than this (the last seq you consumed). Defaults to 0 to fetch all."
4291
+ }
4292
+ },
4293
+ required: ["cardId", "sessionId"]
4294
+ }
4295
+ },
4265
4296
  harmony_generate_prompt: {
4266
4297
  description: "Generate an AI-ready prompt from a card. Automatically infers role and focus based on labels (bug, feature, design, etc.). Use this to create context-rich prompts for working on cards.",
4267
4298
  inputSchema: {
@@ -5597,7 +5628,8 @@ async function handleToolCall(name, args, deps) {
5597
5628
  agentName,
5598
5629
  status: "working",
5599
5630
  currentTask: args.currentTask,
5600
- estimatedMinutesRemaining: args.estimatedMinutesRemaining
5631
+ estimatedMinutesRemaining: args.estimatedMinutesRemaining,
5632
+ steerable: args.steerable === true || args.steerable === "true" ? true : undefined
5601
5633
  });
5602
5634
  markExplicit(cardId, {
5603
5635
  agentIdentifier,
@@ -5636,6 +5668,7 @@ async function handleToolCall(name, args, deps) {
5636
5668
  } else if (callerRecentActions.length > 0) {
5637
5669
  mergedRecentActions = callerRecentActions;
5638
5670
  }
5671
+ const runActivity = (callerActions || []).map((a) => a.description).filter((d) => typeof d === "string" && d.length > 0);
5639
5672
  const result = await client3.updateAgentProgress(cardId, {
5640
5673
  agentIdentifier,
5641
5674
  agentName,
@@ -5644,7 +5677,8 @@ async function handleToolCall(name, args, deps) {
5644
5677
  currentTask: args.currentTask,
5645
5678
  blockers: args.blockers,
5646
5679
  estimatedMinutesRemaining: args.estimatedMinutesRemaining,
5647
- ...mergedRecentActions && { recentActions: mergedRecentActions }
5680
+ ...mergedRecentActions && { recentActions: mergedRecentActions },
5681
+ ...runActivity.length > 0 && { runActivity }
5648
5682
  });
5649
5683
  return { success: true, midSessionLearnings: 0, ...result };
5650
5684
  }
@@ -5700,6 +5734,13 @@ async function handleToolCall(name, args, deps) {
5700
5734
  });
5701
5735
  return { success: true, ...result };
5702
5736
  }
5737
+ case "harmony_get_pending_messages": {
5738
+ const cardId = z.string().uuid().parse(args.cardId);
5739
+ const sessionId = z.string().min(1).parse(args.sessionId);
5740
+ const sinceSeq = args.sinceSeq !== undefined ? z.number().int().min(0).parse(args.sinceSeq) : 0;
5741
+ const result = await client3.getPendingMessages(cardId, sessionId, sinceSeq);
5742
+ return { success: true, ...result };
5743
+ }
5703
5744
  case "harmony_generate_prompt": {
5704
5745
  let cardId;
5705
5746
  if (args.cardId) {
package/dist/index.js CHANGED
@@ -1908,6 +1908,12 @@ class HarmonyApiClient {
1908
1908
  async startAgentSession(cardId, data) {
1909
1909
  return this.request("POST", `/cards/${cardId}/agent-context`, data);
1910
1910
  }
1911
+ async getPendingMessages(cardId, sessionId, sinceSeq) {
1912
+ const params = new URLSearchParams;
1913
+ params.set("sessionId", sessionId);
1914
+ params.set("sinceSeq", String(sinceSeq));
1915
+ return this.request("GET", `/cards/${cardId}/agent-messages?${params.toString()}`);
1916
+ }
1911
1917
  async updateAgentProgress(cardId, data) {
1912
1918
  return this.request("POST", `/cards/${cardId}/agent-context`, data);
1913
1919
  }
@@ -4167,6 +4173,10 @@ var TOOLS = {
4167
4173
  type: "array",
4168
4174
  items: { type: "string" },
4169
4175
  description: 'Label names to add to card (e.g., ["agent"]). Case-insensitive match.'
4176
+ },
4177
+ steerable: {
4178
+ type: "boolean",
4179
+ description: "Set true only if this session will poll harmony_get_pending_messages at its checkpoints. Enables the live steering composer for the run; leave unset/false if you won't consume steering messages."
4170
4180
  }
4171
4181
  },
4172
4182
  required: ["cardId", "agentIdentifier", "agentName"]
@@ -4257,6 +4267,27 @@ var TOOLS = {
4257
4267
  required: ["cardId"]
4258
4268
  }
4259
4269
  },
4270
+ harmony_get_pending_messages: {
4271
+ description: "Drain queued steering messages a teammate sent to your live agent session (card #473). Call at your progress checkpoints with the session id from harmony_start_agent_session and the highest seq you've already consumed; returns user messages with seq > sinceSeq, oldest first. Fold them into your next step and advance sinceSeq to the largest returned seq so each is handled exactly once.",
4272
+ inputSchema: {
4273
+ type: "object",
4274
+ properties: {
4275
+ cardId: {
4276
+ type: "string",
4277
+ description: "Card ID with the live session"
4278
+ },
4279
+ sessionId: {
4280
+ type: "string",
4281
+ description: "Agent session id (the `session.id` returned by harmony_start_agent_session)"
4282
+ },
4283
+ sinceSeq: {
4284
+ type: "number",
4285
+ description: "Return only messages with seq greater than this (the last seq you consumed). Defaults to 0 to fetch all."
4286
+ }
4287
+ },
4288
+ required: ["cardId", "sessionId"]
4289
+ }
4290
+ },
4260
4291
  harmony_generate_prompt: {
4261
4292
  description: "Generate an AI-ready prompt from a card. Automatically infers role and focus based on labels (bug, feature, design, etc.). Use this to create context-rich prompts for working on cards.",
4262
4293
  inputSchema: {
@@ -5592,7 +5623,8 @@ async function handleToolCall(name, args, deps) {
5592
5623
  agentName,
5593
5624
  status: "working",
5594
5625
  currentTask: args.currentTask,
5595
- estimatedMinutesRemaining: args.estimatedMinutesRemaining
5626
+ estimatedMinutesRemaining: args.estimatedMinutesRemaining,
5627
+ steerable: args.steerable === true || args.steerable === "true" ? true : undefined
5596
5628
  });
5597
5629
  markExplicit(cardId, {
5598
5630
  agentIdentifier,
@@ -5631,6 +5663,7 @@ async function handleToolCall(name, args, deps) {
5631
5663
  } else if (callerRecentActions.length > 0) {
5632
5664
  mergedRecentActions = callerRecentActions;
5633
5665
  }
5666
+ const runActivity = (callerActions || []).map((a) => a.description).filter((d) => typeof d === "string" && d.length > 0);
5634
5667
  const result = await client3.updateAgentProgress(cardId, {
5635
5668
  agentIdentifier,
5636
5669
  agentName,
@@ -5639,7 +5672,8 @@ async function handleToolCall(name, args, deps) {
5639
5672
  currentTask: args.currentTask,
5640
5673
  blockers: args.blockers,
5641
5674
  estimatedMinutesRemaining: args.estimatedMinutesRemaining,
5642
- ...mergedRecentActions && { recentActions: mergedRecentActions }
5675
+ ...mergedRecentActions && { recentActions: mergedRecentActions },
5676
+ ...runActivity.length > 0 && { runActivity }
5643
5677
  });
5644
5678
  return { success: true, midSessionLearnings: 0, ...result };
5645
5679
  }
@@ -5695,6 +5729,13 @@ async function handleToolCall(name, args, deps) {
5695
5729
  });
5696
5730
  return { success: true, ...result };
5697
5731
  }
5732
+ case "harmony_get_pending_messages": {
5733
+ const cardId = z.string().uuid().parse(args.cardId);
5734
+ const sessionId = z.string().min(1).parse(args.sessionId);
5735
+ const sinceSeq = args.sinceSeq !== undefined ? z.number().int().min(0).parse(args.sinceSeq) : 0;
5736
+ const result = await client3.getPendingMessages(cardId, sessionId, sinceSeq);
5737
+ return { success: true, ...result };
5738
+ }
5698
5739
  case "harmony_generate_prompt": {
5699
5740
  let cardId;
5700
5741
  if (args.cardId) {
@@ -1361,6 +1361,12 @@ class HarmonyApiClient {
1361
1361
  async startAgentSession(cardId, data) {
1362
1362
  return this.request("POST", `/cards/${cardId}/agent-context`, data);
1363
1363
  }
1364
+ async getPendingMessages(cardId, sessionId, sinceSeq) {
1365
+ const params = new URLSearchParams;
1366
+ params.set("sessionId", sessionId);
1367
+ params.set("sinceSeq", String(sinceSeq));
1368
+ return this.request("GET", `/cards/${cardId}/agent-messages?${params.toString()}`);
1369
+ }
1364
1370
  async updateAgentProgress(cardId, data) {
1365
1371
  return this.request("POST", `/cards/${cardId}/agent-context`, data);
1366
1372
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gethmy/mcp",
3
- "version": "2.11.0",
3
+ "version": "2.11.1",
4
4
  "description": "MCP server for Harmony Kanban board - enables AI coding agents to manage your boards",
5
5
  "publishConfig": {
6
6
  "access": "public"
package/src/api-client.ts CHANGED
@@ -792,6 +792,8 @@ export class HarmonyApiClient {
792
792
  agentIdentifier: string;
793
793
  agentName: string;
794
794
  agentId?: string | null;
795
+ /** Advertise that this session polls for queued steering messages (card #473). */
796
+ steerable?: boolean;
795
797
  status?: "working" | "blocked" | "paused" | "completed";
796
798
  progressPercent?: number;
797
799
  currentTask?: string;
@@ -802,6 +804,26 @@ export class HarmonyApiClient {
802
804
  return this.request("POST", `/cards/${cardId}/agent-context`, data);
803
805
  }
804
806
 
807
+ /**
808
+ * Drain queued `user_message` steering events for a session (card #473).
809
+ * Wraps the existing `GET /cards/{id}/agent-messages` endpoint that the daemon
810
+ * already polls — exposed so MCP/human sessions (e.g. /hmy) can consume steering
811
+ * at their checkpoints. Returns messages with `seq > sinceSeq`, oldest first.
812
+ */
813
+ async getPendingMessages(
814
+ cardId: string,
815
+ sessionId: string,
816
+ sinceSeq: number,
817
+ ): Promise<{ messages: unknown[] }> {
818
+ const params = new URLSearchParams();
819
+ params.set("sessionId", sessionId);
820
+ params.set("sinceSeq", String(sinceSeq));
821
+ return this.request(
822
+ "GET",
823
+ `/cards/${cardId}/agent-messages?${params.toString()}`,
824
+ );
825
+ }
826
+
805
827
  async updateAgentProgress(
806
828
  cardId: string,
807
829
  data: {
@@ -828,6 +850,8 @@ export class HarmonyApiClient {
828
850
  modelName?: string;
829
851
  numTurns?: number;
830
852
  recentActions?: { action: string; ts: string }[];
853
+ /** Per-call activity descriptions → one assistant_text timeline event each (card #470). */
854
+ runActivity?: string[];
831
855
  failureReason?:
832
856
  | "verification"
833
857
  | "review"
package/src/server.ts CHANGED
@@ -1002,6 +1002,11 @@ export const TOOLS = {
1002
1002
  description:
1003
1003
  'Label names to add to card (e.g., ["agent"]). Case-insensitive match.',
1004
1004
  },
1005
+ steerable: {
1006
+ type: "boolean",
1007
+ description:
1008
+ "Set true only if this session will poll harmony_get_pending_messages at its checkpoints. Enables the live steering composer for the run; leave unset/false if you won't consume steering messages.",
1009
+ },
1005
1010
  },
1006
1011
  required: ["cardId", "agentIdentifier", "agentName"],
1007
1012
  },
@@ -1097,6 +1102,30 @@ export const TOOLS = {
1097
1102
  required: ["cardId"],
1098
1103
  },
1099
1104
  },
1105
+ harmony_get_pending_messages: {
1106
+ description:
1107
+ "Drain queued steering messages a teammate sent to your live agent session (card #473). Call at your progress checkpoints with the session id from harmony_start_agent_session and the highest seq you've already consumed; returns user messages with seq > sinceSeq, oldest first. Fold them into your next step and advance sinceSeq to the largest returned seq so each is handled exactly once.",
1108
+ inputSchema: {
1109
+ type: "object",
1110
+ properties: {
1111
+ cardId: {
1112
+ type: "string",
1113
+ description: "Card ID with the live session",
1114
+ },
1115
+ sessionId: {
1116
+ type: "string",
1117
+ description:
1118
+ "Agent session id (the `session.id` returned by harmony_start_agent_session)",
1119
+ },
1120
+ sinceSeq: {
1121
+ type: "number",
1122
+ description:
1123
+ "Return only messages with seq greater than this (the last seq you consumed). Defaults to 0 to fetch all.",
1124
+ },
1125
+ },
1126
+ required: ["cardId", "sessionId"],
1127
+ },
1128
+ },
1100
1129
 
1101
1130
  // Prompt generation
1102
1131
  harmony_generate_prompt: {
@@ -2836,6 +2865,10 @@ async function handleToolCall(
2836
2865
  estimatedMinutesRemaining: args.estimatedMinutesRemaining as
2837
2866
  | number
2838
2867
  | undefined,
2868
+ steerable:
2869
+ args.steerable === true || args.steerable === "true"
2870
+ ? true
2871
+ : undefined,
2839
2872
  });
2840
2873
 
2841
2874
  // Mark as explicit so auto-session won't interfere
@@ -2896,6 +2929,13 @@ async function handleToolCall(
2896
2929
  mergedRecentActions = callerRecentActions;
2897
2930
  }
2898
2931
 
2932
+ // Per-call deltas for the run timeline. Sourced from THIS call's `actions`
2933
+ // only (not the cumulative `recentActions` cache), so each lands as exactly
2934
+ // one assistant_text event without duplication. (card #470)
2935
+ const runActivity = (callerActions || [])
2936
+ .map((a) => a.description)
2937
+ .filter((d): d is string => typeof d === "string" && d.length > 0);
2938
+
2899
2939
  const result = await client.updateAgentProgress(cardId, {
2900
2940
  agentIdentifier,
2901
2941
  agentName,
@@ -2912,6 +2952,7 @@ async function handleToolCall(
2912
2952
  | number
2913
2953
  | undefined,
2914
2954
  ...(mergedRecentActions && { recentActions: mergedRecentActions }),
2955
+ ...(runActivity.length > 0 && { runActivity }),
2915
2956
  });
2916
2957
 
2917
2958
  // Phase 0 (memory architecture v2): mid-session learning extraction removed.
@@ -3008,6 +3049,21 @@ async function handleToolCall(
3008
3049
  return { success: true, ...result };
3009
3050
  }
3010
3051
 
3052
+ case "harmony_get_pending_messages": {
3053
+ const cardId = z.string().uuid().parse(args.cardId);
3054
+ const sessionId = z.string().min(1).parse(args.sessionId);
3055
+ const sinceSeq =
3056
+ args.sinceSeq !== undefined
3057
+ ? z.number().int().min(0).parse(args.sinceSeq)
3058
+ : 0;
3059
+ const result = await client.getPendingMessages(
3060
+ cardId,
3061
+ sessionId,
3062
+ sinceSeq,
3063
+ );
3064
+ return { success: true, ...result };
3065
+ }
3066
+
3011
3067
  // Prompt generation
3012
3068
  // TODO Phase 1: rebuild full context assembly per docs/superpowers/plans/2026-05-07-memory-architecture-v2.md §10
3013
3069
  case "harmony_generate_prompt": {