@gethmy/mcp 2.2.0 → 2.2.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 +24292 -24173
- package/dist/index.js +24520 -24401
- package/dist/lib/__tests__/auto-session.test.js +33 -33
- package/dist/lib/api-client.js +116 -0
- package/dist/lib/auto-session.js +41 -5
- package/dist/lib/server.js +21 -96
- package/package.json +1 -1
- package/src/__tests__/auto-session.test.ts +33 -33
- package/src/api-client.ts +205 -0
- package/src/auto-session.ts +54 -4
- package/src/remote.ts +2 -1
- package/src/server.ts +25 -119
package/src/server.ts
CHANGED
|
@@ -59,13 +59,7 @@ import {
|
|
|
59
59
|
} from "./context-assembly.js";
|
|
60
60
|
import { autoExpandGraph } from "./graph-expansion.js";
|
|
61
61
|
import { runLifecycleMaintenance } from "./lifecycle-maintenance.js";
|
|
62
|
-
import {
|
|
63
|
-
type CardData,
|
|
64
|
-
type ColumnData,
|
|
65
|
-
generatePrompt,
|
|
66
|
-
type MemoryData,
|
|
67
|
-
type PromptVariant,
|
|
68
|
-
} from "./prompt-builder.js";
|
|
62
|
+
import type { PromptVariant } from "./prompt-builder.js";
|
|
69
63
|
|
|
70
64
|
/**
|
|
71
65
|
* Dependencies injected into tool handlers.
|
|
@@ -2699,14 +2693,11 @@ async function handleToolCall(
|
|
|
2699
2693
|
|
|
2700
2694
|
// Prompt generation
|
|
2701
2695
|
case "harmony_generate_prompt": {
|
|
2702
|
-
//
|
|
2703
|
-
let
|
|
2704
|
-
let columnData: ColumnData | null = null;
|
|
2696
|
+
// Resolve card ID — either directly or via short ID
|
|
2697
|
+
let cardId: string;
|
|
2705
2698
|
|
|
2706
2699
|
if (args.cardId) {
|
|
2707
|
-
|
|
2708
|
-
const cardResult = await client.getCard(cardId);
|
|
2709
|
-
cardData = cardResult.card as CardData;
|
|
2700
|
+
cardId = z.string().uuid().parse(args.cardId);
|
|
2710
2701
|
} else if (args.shortId !== undefined) {
|
|
2711
2702
|
const shortId = z.number().int().positive().parse(args.shortId);
|
|
2712
2703
|
const projectId =
|
|
@@ -2717,35 +2708,12 @@ async function handleToolCall(
|
|
|
2717
2708
|
);
|
|
2718
2709
|
}
|
|
2719
2710
|
const cardResult = await client.getCardByShortId(projectId, shortId);
|
|
2720
|
-
|
|
2711
|
+
cardId = (cardResult.card as { id: string }).id;
|
|
2721
2712
|
} else {
|
|
2722
2713
|
throw new Error("Either cardId or shortId must be provided");
|
|
2723
2714
|
}
|
|
2724
2715
|
|
|
2725
|
-
//
|
|
2726
|
-
const projectIdForBoard =
|
|
2727
|
-
(args.projectId as string) ||
|
|
2728
|
-
getActiveProjectId() ||
|
|
2729
|
-
(cardData as unknown as { project_id: string }).project_id;
|
|
2730
|
-
if (projectIdForBoard) {
|
|
2731
|
-
try {
|
|
2732
|
-
const board = await client.getBoard(projectIdForBoard, {
|
|
2733
|
-
summary: true,
|
|
2734
|
-
});
|
|
2735
|
-
const columnId = (cardData as unknown as { column_id: string })
|
|
2736
|
-
.column_id;
|
|
2737
|
-
const column = (
|
|
2738
|
-
board.columns as Array<{ id: string; name: string }>
|
|
2739
|
-
).find((col) => col.id === columnId);
|
|
2740
|
-
if (column) {
|
|
2741
|
-
columnData = { name: column.name };
|
|
2742
|
-
}
|
|
2743
|
-
} catch {
|
|
2744
|
-
// Column info not available, continue without it
|
|
2745
|
-
}
|
|
2746
|
-
}
|
|
2747
|
-
|
|
2748
|
-
const variant = (args.variant as PromptVariant) || "execute";
|
|
2716
|
+
// Parse MCP-specific context options
|
|
2749
2717
|
const contextOptions: Record<string, boolean> = {};
|
|
2750
2718
|
if (args.includeSubtasks !== undefined) {
|
|
2751
2719
|
contextOptions.includeSubtasks =
|
|
@@ -2761,89 +2729,24 @@ async function handleToolCall(
|
|
|
2761
2729
|
args.includeDescription === "true";
|
|
2762
2730
|
}
|
|
2763
2731
|
|
|
2764
|
-
//
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
if (workspaceId && cardData.title) {
|
|
2772
|
-
const cardLabels = (cardData.labels || []).map((l) => l.name);
|
|
2773
|
-
const taskContext = [cardData.title, cardData.description || ""]
|
|
2774
|
-
.filter(Boolean)
|
|
2775
|
-
.join(" ");
|
|
2776
|
-
|
|
2777
|
-
const assembled = await assembleContext({
|
|
2778
|
-
workspaceId,
|
|
2779
|
-
projectId: getActiveProjectId() || undefined,
|
|
2780
|
-
taskContext,
|
|
2781
|
-
cardLabels,
|
|
2782
|
-
cardId: cardData.id,
|
|
2783
|
-
client,
|
|
2784
|
-
});
|
|
2785
|
-
|
|
2786
|
-
if (assembled.context) {
|
|
2787
|
-
assembledContextStr = assembled.context;
|
|
2788
|
-
assemblyId = assembled.manifest.assemblyId;
|
|
2789
|
-
cacheManifest(assembled.manifest);
|
|
2790
|
-
}
|
|
2791
|
-
}
|
|
2792
|
-
} catch {
|
|
2793
|
-
// Context assembly failed, try legacy fallback
|
|
2794
|
-
try {
|
|
2795
|
-
const workspaceId = deps.getActiveWorkspaceId();
|
|
2796
|
-
if (workspaceId && cardData.title) {
|
|
2797
|
-
const memoryResult = await client.searchMemoryEntities(
|
|
2798
|
-
workspaceId,
|
|
2799
|
-
cardData.title,
|
|
2800
|
-
{
|
|
2801
|
-
project_id: getActiveProjectId() || undefined,
|
|
2802
|
-
limit: 5,
|
|
2803
|
-
},
|
|
2804
|
-
);
|
|
2805
|
-
if (memoryResult.entities?.length > 0) {
|
|
2806
|
-
memories = memoryResult.entities.map((e: unknown) => {
|
|
2807
|
-
const entity = e as {
|
|
2808
|
-
id: string;
|
|
2809
|
-
type: string;
|
|
2810
|
-
title: string;
|
|
2811
|
-
content: string;
|
|
2812
|
-
confidence: number;
|
|
2813
|
-
tags: string[];
|
|
2814
|
-
};
|
|
2815
|
-
return {
|
|
2816
|
-
id: entity.id,
|
|
2817
|
-
type: entity.type,
|
|
2818
|
-
title: entity.title,
|
|
2819
|
-
content: entity.content,
|
|
2820
|
-
confidence: entity.confidence,
|
|
2821
|
-
tags: entity.tags || [],
|
|
2822
|
-
};
|
|
2823
|
-
});
|
|
2824
|
-
}
|
|
2825
|
-
}
|
|
2826
|
-
} catch {
|
|
2827
|
-
// Memory fetch also failed, continue without memories
|
|
2828
|
-
}
|
|
2829
|
-
}
|
|
2830
|
-
|
|
2831
|
-
const result = generatePrompt({
|
|
2832
|
-
card: cardData,
|
|
2833
|
-
column: columnData,
|
|
2834
|
-
variant,
|
|
2835
|
-
contextOptions,
|
|
2732
|
+
// Delegate to the shared prompt generation pipeline
|
|
2733
|
+
const result = await client.generateCardPrompt({
|
|
2734
|
+
cardId,
|
|
2735
|
+
workspaceId: deps.getActiveWorkspaceId() || "",
|
|
2736
|
+
projectId:
|
|
2737
|
+
(args.projectId as string) || getActiveProjectId() || undefined,
|
|
2738
|
+
variant: (args.variant as PromptVariant) || "execute",
|
|
2836
2739
|
customConstraints: args.customConstraints as string | undefined,
|
|
2837
|
-
|
|
2838
|
-
assembledContext: assembledContextStr,
|
|
2839
|
-
assemblyId,
|
|
2740
|
+
contextOptions,
|
|
2840
2741
|
});
|
|
2841
2742
|
|
|
2743
|
+
// MCP-specific: cache the assembly manifest for the feedback loop
|
|
2744
|
+
if (result.assemblyId) {
|
|
2745
|
+
trackSessionAssembly(cardId, result.assemblyId);
|
|
2746
|
+
}
|
|
2747
|
+
|
|
2842
2748
|
return {
|
|
2843
2749
|
success: true,
|
|
2844
|
-
cardId: cardData.id,
|
|
2845
|
-
shortId: cardData.short_id,
|
|
2846
|
-
title: cardData.title,
|
|
2847
2750
|
...result,
|
|
2848
2751
|
};
|
|
2849
2752
|
}
|
|
@@ -3037,8 +2940,7 @@ async function handleToolCall(
|
|
|
3037
2940
|
// Track memory write action and flush (fire-and-forget)
|
|
3038
2941
|
const updateMemSession = getActiveMemorySession();
|
|
3039
2942
|
if (updateMemSession) {
|
|
3040
|
-
const updateTitle =
|
|
3041
|
-
(updates.title as string) || entityId.slice(0, 8);
|
|
2943
|
+
const updateTitle = (updates.title as string) || entityId.slice(0, 8);
|
|
3042
2944
|
appendMemoryAction(
|
|
3043
2945
|
updateMemSession.cardId,
|
|
3044
2946
|
`Updated memory: ${updateTitle}`,
|
|
@@ -4053,13 +3955,17 @@ export class HarmonyMCPServer {
|
|
|
4053
3955
|
await this.server.connect(transport);
|
|
4054
3956
|
console.error("Harmony MCP server running on stdio");
|
|
4055
3957
|
|
|
4056
|
-
// Initialize auto-session tracking
|
|
3958
|
+
// Initialize auto-session tracking with MCP client identity detection
|
|
4057
3959
|
const configDeps = createConfigDeps();
|
|
4058
3960
|
initAutoSession(
|
|
4059
3961
|
async (client, cardId, status) => {
|
|
4060
3962
|
await runEndSessionPipeline(client, configDeps, cardId, status);
|
|
4061
3963
|
},
|
|
4062
3964
|
() => getClient(),
|
|
3965
|
+
() => {
|
|
3966
|
+
const cv = this.server.getClientVersion();
|
|
3967
|
+
return cv ? { name: cv.name, version: cv.version } : null;
|
|
3968
|
+
},
|
|
4063
3969
|
);
|
|
4064
3970
|
|
|
4065
3971
|
// Graceful shutdown: end all auto-sessions
|