@gethmy/mcp 2.1.3 → 2.2.0
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 +159 -16
- package/dist/index.js +152 -9
- package/dist/lib/auto-session.js +8 -3
- package/dist/lib/cli.js +1 -1
- package/dist/lib/config.js +1 -1
- package/dist/lib/http.js +1 -0
- package/dist/lib/prompt-builder.js +1 -0
- package/dist/lib/remote.js +2 -2
- package/dist/lib/server.js +179 -4
- package/dist/lib/skills.js +3 -3
- package/dist/lib/tui/setup.js +3 -3
- package/package.json +1 -1
- package/src/auto-session.ts +10 -3
- package/src/cli.ts +1 -1
- package/src/config.ts +1 -1
- package/src/http.ts +1 -0
- package/src/prompt-builder.ts +3 -0
- package/src/remote.ts +2 -2
- package/src/server.ts +244 -4
- package/src/skills.ts +3 -3
- package/src/tui/setup.ts +3 -3
package/dist/lib/http.js
CHANGED
|
@@ -301,6 +301,7 @@ export function generatePrompt(options) {
|
|
|
301
301
|
roleFraming.focus.forEach((f) => {
|
|
302
302
|
sections.push(`- ${f}`);
|
|
303
303
|
});
|
|
304
|
+
sections.push(`- **Memory:** When you discover important domain knowledge, architectural decisions, or infrastructure details, store them via \`harmony_remember\`. Focus on durable knowledge that future agents would benefit from — not ephemeral task details (those are auto-extracted from your session).`);
|
|
304
305
|
// Output suggestions
|
|
305
306
|
sections.push(`\n## Suggested Outputs`);
|
|
306
307
|
roleFraming.outputSuggestions.forEach((s) => {
|
package/dist/lib/remote.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Claude.ai → POST https://mcp.gethmy.com/mcp (Bearer: hmy_xxx)
|
|
10
10
|
*
|
|
11
11
|
* Env vars:
|
|
12
|
-
* HARMONY_API_URL - Harmony API base URL (default: https://gethmy.com/api)
|
|
12
|
+
* HARMONY_API_URL - Harmony API base URL (default: https://app.gethmy.com/api)
|
|
13
13
|
* PORT - Listen port (default: 3002)
|
|
14
14
|
*/
|
|
15
15
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -22,7 +22,7 @@ import { registerHandlers } from "./server.js";
|
|
|
22
22
|
// ---------------------------------------------------------------------------
|
|
23
23
|
// Config from env
|
|
24
24
|
// ---------------------------------------------------------------------------
|
|
25
|
-
const HARMONY_API_URL = process.env.HARMONY_API_URL || "https://gethmy.com/api";
|
|
25
|
+
const HARMONY_API_URL = process.env.HARMONY_API_URL || "https://app.gethmy.com/api";
|
|
26
26
|
const PORT = parseInt(process.env.PORT || "3002", 10);
|
|
27
27
|
async function validateApiKey(apiKey) {
|
|
28
28
|
try {
|
package/dist/lib/server.js
CHANGED
|
@@ -12,6 +12,118 @@ import { assembleContext, cacheManifest, computeRelevanceScore, getCachedManifes
|
|
|
12
12
|
import { autoExpandGraph } from "./graph-expansion.js";
|
|
13
13
|
import { runLifecycleMaintenance } from "./lifecycle-maintenance.js";
|
|
14
14
|
import { generatePrompt, } from "./prompt-builder.js";
|
|
15
|
+
const memorySessions = new Map();
|
|
16
|
+
function initMemorySession(cardId, agentIdentifier, agentName) {
|
|
17
|
+
memorySessions.set(cardId, {
|
|
18
|
+
cardId,
|
|
19
|
+
agentIdentifier,
|
|
20
|
+
agentName,
|
|
21
|
+
memoryReadCount: 0,
|
|
22
|
+
pendingActions: [],
|
|
23
|
+
allActions: [],
|
|
24
|
+
dirty: false,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function getMemorySession(cardId) {
|
|
28
|
+
return memorySessions.get(cardId);
|
|
29
|
+
}
|
|
30
|
+
function appendMemoryAction(cardId, action) {
|
|
31
|
+
const session = memorySessions.get(cardId);
|
|
32
|
+
if (!session)
|
|
33
|
+
return;
|
|
34
|
+
const truncated = action.length > 512 ? action.slice(0, 509) + "..." : action;
|
|
35
|
+
const entry = { action: truncated, ts: new Date().toISOString() };
|
|
36
|
+
session.pendingActions.push(entry);
|
|
37
|
+
session.dirty = true;
|
|
38
|
+
}
|
|
39
|
+
function incrementMemoryReads(cardId) {
|
|
40
|
+
const session = memorySessions.get(cardId);
|
|
41
|
+
if (!session)
|
|
42
|
+
return;
|
|
43
|
+
session.memoryReadCount++;
|
|
44
|
+
session.dirty = true;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Flush pending memory actions to the backend via updateAgentProgress.
|
|
48
|
+
* Fire-and-forget: errors are logged but never thrown.
|
|
49
|
+
*/
|
|
50
|
+
async function flushMemoryActions(client, cardId) {
|
|
51
|
+
const session = memorySessions.get(cardId);
|
|
52
|
+
if (!session || !session.dirty)
|
|
53
|
+
return;
|
|
54
|
+
try {
|
|
55
|
+
// Batch reads into a single summary line
|
|
56
|
+
if (session.memoryReadCount > 0) {
|
|
57
|
+
session.allActions.push({
|
|
58
|
+
action: `Recalled ${session.memoryReadCount} memor${session.memoryReadCount === 1 ? "y" : "ies"}`,
|
|
59
|
+
ts: new Date().toISOString(),
|
|
60
|
+
});
|
|
61
|
+
session.memoryReadCount = 0;
|
|
62
|
+
}
|
|
63
|
+
// Move pending writes to allActions
|
|
64
|
+
if (session.pendingActions.length > 0) {
|
|
65
|
+
session.allActions.push(...session.pendingActions);
|
|
66
|
+
session.pendingActions = [];
|
|
67
|
+
}
|
|
68
|
+
// Trim to max 10 (drop oldest)
|
|
69
|
+
if (session.allActions.length > 10) {
|
|
70
|
+
session.allActions = session.allActions.slice(-10);
|
|
71
|
+
}
|
|
72
|
+
await client.updateAgentProgress(cardId, {
|
|
73
|
+
agentIdentifier: session.agentIdentifier,
|
|
74
|
+
agentName: session.agentName,
|
|
75
|
+
recentActions: session.allActions,
|
|
76
|
+
});
|
|
77
|
+
session.dirty = false;
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
// Fire-and-forget: log but don't propagate
|
|
81
|
+
console.error("[memory-session] flush failed:", err);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Merge memory actions into an existing recentActions array from a progress update.
|
|
86
|
+
* Returns the merged array (caller's actions first, then memory actions appended).
|
|
87
|
+
*/
|
|
88
|
+
function mergeMemoryActionsInto(cardId, callerActions) {
|
|
89
|
+
const session = memorySessions.get(cardId);
|
|
90
|
+
if (!session)
|
|
91
|
+
return callerActions;
|
|
92
|
+
// Flush reads into allActions
|
|
93
|
+
if (session.memoryReadCount > 0) {
|
|
94
|
+
session.allActions.push({
|
|
95
|
+
action: `Recalled ${session.memoryReadCount} memor${session.memoryReadCount === 1 ? "y" : "ies"}`,
|
|
96
|
+
ts: new Date().toISOString(),
|
|
97
|
+
});
|
|
98
|
+
session.memoryReadCount = 0;
|
|
99
|
+
}
|
|
100
|
+
// Move pending to allActions
|
|
101
|
+
if (session.pendingActions.length > 0) {
|
|
102
|
+
session.allActions.push(...session.pendingActions);
|
|
103
|
+
session.pendingActions = [];
|
|
104
|
+
}
|
|
105
|
+
// Merge: caller actions + memory actions, trim to 10
|
|
106
|
+
const merged = [...callerActions, ...session.allActions];
|
|
107
|
+
const trimmed = merged.length > 10 ? merged.slice(-10) : merged;
|
|
108
|
+
// Update allActions to the merged state
|
|
109
|
+
session.allActions = trimmed;
|
|
110
|
+
session.dirty = false;
|
|
111
|
+
return trimmed;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get the first (and typically only) active memory session.
|
|
115
|
+
* Memory tools don't carry a cardId, so we find the active session.
|
|
116
|
+
*/
|
|
117
|
+
function getActiveMemorySession() {
|
|
118
|
+
// Return the first active session (there should be at most one)
|
|
119
|
+
for (const session of memorySessions.values()) {
|
|
120
|
+
return session;
|
|
121
|
+
}
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
function cleanupMemorySession(cardId) {
|
|
125
|
+
memorySessions.delete(cardId);
|
|
126
|
+
}
|
|
15
127
|
// Tool definitions
|
|
16
128
|
const TOOLS = {
|
|
17
129
|
// Card operations
|
|
@@ -1597,7 +1709,7 @@ async function handleToolCall(name, args, deps) {
|
|
|
1597
1709
|
const unauthenticatedTools = ["harmony_signup", "harmony_onboard"];
|
|
1598
1710
|
if (!unauthenticatedTools.includes(name) && !deps.isConfigured()) {
|
|
1599
1711
|
throw new Error('Not configured. Run "npx @gethmy/mcp setup" to set your API key.\n' +
|
|
1600
|
-
"You can generate an API key at https://gethmy.com → Settings → API Keys.\n" +
|
|
1712
|
+
"You can generate an API key at https://app.gethmy.com → Settings → API Keys.\n" +
|
|
1601
1713
|
'Or use "harmony_onboard" to create an account and configure automatically.');
|
|
1602
1714
|
}
|
|
1603
1715
|
const client = deps.isConfigured()
|
|
@@ -1944,7 +2056,9 @@ async function handleToolCall(name, args, deps) {
|
|
|
1944
2056
|
estimatedMinutesRemaining: args.estimatedMinutesRemaining,
|
|
1945
2057
|
});
|
|
1946
2058
|
// Mark as explicit so auto-session won't interfere
|
|
1947
|
-
markExplicit(cardId);
|
|
2059
|
+
markExplicit(cardId, { agentIdentifier, agentName });
|
|
2060
|
+
// Initialize memory session tracking for action visibility
|
|
2061
|
+
initMemorySession(cardId, agentIdentifier, agentName);
|
|
1948
2062
|
// Prefetch relevant context (non-blocking, best-effort)
|
|
1949
2063
|
let prefetchedMemoryIds = [];
|
|
1950
2064
|
try {
|
|
@@ -2011,6 +2125,16 @@ async function handleToolCall(name, args, deps) {
|
|
|
2011
2125
|
const progressPercent = args.progressPercent !== undefined
|
|
2012
2126
|
? z.number().min(0).max(100).parse(args.progressPercent)
|
|
2013
2127
|
: undefined;
|
|
2128
|
+
// Merge any pending memory actions into the progress update
|
|
2129
|
+
const callerRecentActions = args.recentActions;
|
|
2130
|
+
const memSession = getMemorySession(cardId);
|
|
2131
|
+
let mergedRecentActions;
|
|
2132
|
+
if (memSession?.dirty) {
|
|
2133
|
+
mergedRecentActions = mergeMemoryActionsInto(cardId, callerRecentActions || []);
|
|
2134
|
+
}
|
|
2135
|
+
else if (callerRecentActions) {
|
|
2136
|
+
mergedRecentActions = callerRecentActions;
|
|
2137
|
+
}
|
|
2014
2138
|
const result = await client.updateAgentProgress(cardId, {
|
|
2015
2139
|
agentIdentifier,
|
|
2016
2140
|
agentName,
|
|
@@ -2019,6 +2143,7 @@ async function handleToolCall(name, args, deps) {
|
|
|
2019
2143
|
currentTask: args.currentTask,
|
|
2020
2144
|
blockers: args.blockers,
|
|
2021
2145
|
estimatedMinutesRemaining: args.estimatedMinutesRemaining,
|
|
2146
|
+
...(mergedRecentActions && { recentActions: mergedRecentActions }),
|
|
2022
2147
|
});
|
|
2023
2148
|
// Mid-session learning extraction (fire-and-forget)
|
|
2024
2149
|
let midSessionLearnings = 0;
|
|
@@ -2049,6 +2174,9 @@ async function handleToolCall(name, args, deps) {
|
|
|
2049
2174
|
const endProgressPercent = args.progressPercent !== undefined
|
|
2050
2175
|
? z.number().min(0).max(100).parse(args.progressPercent)
|
|
2051
2176
|
: undefined;
|
|
2177
|
+
// Final flush of any pending memory actions before ending the session
|
|
2178
|
+
await flushMemoryActions(client, cardId);
|
|
2179
|
+
cleanupMemorySession(cardId);
|
|
2052
2180
|
const result = await client.endAgentSession(cardId, {
|
|
2053
2181
|
status: sessionStatus,
|
|
2054
2182
|
progressPercent: endProgressPercent,
|
|
@@ -2270,6 +2398,8 @@ async function handleToolCall(name, args, deps) {
|
|
|
2270
2398
|
}
|
|
2271
2399
|
const entityType = args.type || "context";
|
|
2272
2400
|
const entityTags = args.tags || [];
|
|
2401
|
+
// Use session's agent identifier if available, otherwise null
|
|
2402
|
+
const activeMemSession = getActiveMemorySession();
|
|
2273
2403
|
const result = await client.createMemoryEntity({
|
|
2274
2404
|
workspace_id: workspaceId,
|
|
2275
2405
|
project_id: args.projectId || deps.getActiveProjectId() || undefined,
|
|
@@ -2283,7 +2413,7 @@ async function handleToolCall(name, args, deps) {
|
|
|
2283
2413
|
? z.number().min(0).max(1).parse(args.confidence)
|
|
2284
2414
|
: undefined,
|
|
2285
2415
|
tags: entityTags.length > 0 ? entityTags : undefined,
|
|
2286
|
-
agent_identifier:
|
|
2416
|
+
agent_identifier: activeMemSession?.agentIdentifier || undefined,
|
|
2287
2417
|
});
|
|
2288
2418
|
// Fire-and-forget graph expansion: link new entity to semantically similar ones
|
|
2289
2419
|
const newEntityIdForGraph = result.entity?.id;
|
|
@@ -2303,6 +2433,11 @@ async function handleToolCall(name, args, deps) {
|
|
|
2303
2433
|
// Don't block creation if contradiction detection fails
|
|
2304
2434
|
}
|
|
2305
2435
|
}
|
|
2436
|
+
// Track memory write action and flush (fire-and-forget)
|
|
2437
|
+
if (activeMemSession) {
|
|
2438
|
+
appendMemoryAction(activeMemSession.cardId, `Stored memory: ${title}`);
|
|
2439
|
+
flushMemoryActions(client, activeMemSession.cardId).catch(() => { });
|
|
2440
|
+
}
|
|
2306
2441
|
return {
|
|
2307
2442
|
success: true,
|
|
2308
2443
|
...result,
|
|
@@ -2373,6 +2508,11 @@ async function handleToolCall(name, args, deps) {
|
|
|
2373
2508
|
}
|
|
2374
2509
|
})).catch(() => { });
|
|
2375
2510
|
}
|
|
2511
|
+
// Track memory read (batched on flush)
|
|
2512
|
+
const recallMemSession = getActiveMemorySession();
|
|
2513
|
+
if (recallMemSession) {
|
|
2514
|
+
incrementMemoryReads(recallMemSession.cardId);
|
|
2515
|
+
}
|
|
2376
2516
|
return markdown || "No memories found.";
|
|
2377
2517
|
}
|
|
2378
2518
|
case "harmony_update_memory": {
|
|
@@ -2393,11 +2533,35 @@ async function handleToolCall(name, args, deps) {
|
|
|
2393
2533
|
if (args.metadata !== undefined)
|
|
2394
2534
|
updates.metadata = args.metadata;
|
|
2395
2535
|
const result = await client.updateMemoryEntity(entityId, updates);
|
|
2536
|
+
// Track memory write action and flush (fire-and-forget)
|
|
2537
|
+
const updateMemSession = getActiveMemorySession();
|
|
2538
|
+
if (updateMemSession) {
|
|
2539
|
+
const updateTitle = updates.title || entityId.slice(0, 8);
|
|
2540
|
+
appendMemoryAction(updateMemSession.cardId, `Updated memory: ${updateTitle}`);
|
|
2541
|
+
flushMemoryActions(client, updateMemSession.cardId).catch(() => { });
|
|
2542
|
+
}
|
|
2396
2543
|
return { success: true, ...result };
|
|
2397
2544
|
}
|
|
2398
2545
|
case "harmony_forget": {
|
|
2399
2546
|
const entityId = z.string().uuid().parse(args.entityId);
|
|
2547
|
+
// Fetch title before deletion for action tracking
|
|
2548
|
+
let forgetTitle = null;
|
|
2549
|
+
const forgetMemSession = getActiveMemorySession();
|
|
2550
|
+
if (forgetMemSession) {
|
|
2551
|
+
try {
|
|
2552
|
+
const { entity } = await client.getMemoryEntity(entityId);
|
|
2553
|
+
forgetTitle = entity?.title || null;
|
|
2554
|
+
}
|
|
2555
|
+
catch {
|
|
2556
|
+
// Non-fatal: use truncated ID if fetch fails
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2400
2559
|
await client.deleteMemoryEntity(entityId);
|
|
2560
|
+
// Track memory write action and flush (fire-and-forget)
|
|
2561
|
+
if (forgetMemSession) {
|
|
2562
|
+
appendMemoryAction(forgetMemSession.cardId, `Removed memory: ${forgetTitle || entityId.slice(0, 8)}`);
|
|
2563
|
+
flushMemoryActions(client, forgetMemSession.cardId).catch(() => { });
|
|
2564
|
+
}
|
|
2401
2565
|
return { success: true };
|
|
2402
2566
|
}
|
|
2403
2567
|
case "harmony_relate": {
|
|
@@ -2423,6 +2587,12 @@ async function handleToolCall(name, args, deps) {
|
|
|
2423
2587
|
? z.number().min(0).max(1).parse(args.confidence)
|
|
2424
2588
|
: undefined,
|
|
2425
2589
|
});
|
|
2590
|
+
// Track memory write action and flush (fire-and-forget)
|
|
2591
|
+
const relateMemSession = getActiveMemorySession();
|
|
2592
|
+
if (relateMemSession) {
|
|
2593
|
+
appendMemoryAction(relateMemSession.cardId, `Linked memories: ${relationType}`);
|
|
2594
|
+
flushMemoryActions(client, relateMemSession.cardId).catch(() => { });
|
|
2595
|
+
}
|
|
2426
2596
|
return { success: true, ...result };
|
|
2427
2597
|
}
|
|
2428
2598
|
case "harmony_memory_search": {
|
|
@@ -2438,6 +2608,11 @@ async function handleToolCall(name, args, deps) {
|
|
|
2438
2608
|
type: args.type,
|
|
2439
2609
|
limit: args.limit,
|
|
2440
2610
|
});
|
|
2611
|
+
// Track memory read (batched on flush)
|
|
2612
|
+
const searchMemSession = getActiveMemorySession();
|
|
2613
|
+
if (searchMemSession) {
|
|
2614
|
+
incrementMemoryReads(searchMemSession.cardId);
|
|
2615
|
+
}
|
|
2441
2616
|
return markdown || "No memories found.";
|
|
2442
2617
|
}
|
|
2443
2618
|
// Vault index
|
|
@@ -2537,7 +2712,7 @@ async function handleToolCall(name, args, deps) {
|
|
|
2537
2712
|
tasks: args.tasks,
|
|
2538
2713
|
});
|
|
2539
2714
|
// Build URL for viewing the plan
|
|
2540
|
-
const planUrl = `https://gethmy.com/plans/${result.plan.id}`;
|
|
2715
|
+
const planUrl = `https://app.gethmy.com/plans/${result.plan.id}`;
|
|
2541
2716
|
return {
|
|
2542
2717
|
success: true,
|
|
2543
2718
|
planId: result.plan.id,
|
package/dist/lib/skills.js
CHANGED
|
@@ -246,7 +246,7 @@ Once you have the plan ID, call \`harmony_get_plan\` to fetch the full plan with
|
|
|
246
246
|
## [Plan Title]
|
|
247
247
|
**Status:** draft/active/archived | **Phase:** plan/execute/verify/done
|
|
248
248
|
**Tasks:** N total (X pending, Y in_progress, Z completed)
|
|
249
|
-
**URL:** https://gethmy.com/plans/{id}
|
|
249
|
+
**URL:** https://app.gethmy.com/plans/{id}
|
|
250
250
|
\\\`\\\`\\\`
|
|
251
251
|
|
|
252
252
|
If plan is in execute phase and tasks already have linked cards, note which tasks have cards and which don't.
|
|
@@ -280,7 +280,7 @@ Only offer **(A) Single card**, **(C) Analyze only**, or **(D) Skip**.
|
|
|
280
280
|
#### Option A — Single card
|
|
281
281
|
1. Call \`harmony_create_card\` with:
|
|
282
282
|
- \`title\`: Plan title
|
|
283
|
-
- \`description\`: Brief 2-3 sentence summary of the plan + \`\\n\\n[View plan](https://gethmy.com/plans/{planId})\`
|
|
283
|
+
- \`description\`: Brief 2-3 sentence summary of the plan + \`\\n\\n[View plan](https://app.gethmy.com/plans/{planId})\`
|
|
284
284
|
- \`priority\`: based on plan task priorities (use highest)
|
|
285
285
|
2. Call \`harmony_update_plan\` to set \`status: "active"\`, \`workflowPhase: "execute"\`
|
|
286
286
|
|
|
@@ -402,7 +402,7 @@ Call \`harmony_create_plan\` with:
|
|
|
402
402
|
### 2B.5 — User Approval
|
|
403
403
|
|
|
404
404
|
Show the user:
|
|
405
|
-
- Plan URL: \`https://gethmy.com/plans/{id}\`
|
|
405
|
+
- Plan URL: \`https://app.gethmy.com/plans/{id}\`
|
|
406
406
|
- Number of tasks created
|
|
407
407
|
- Brief summary
|
|
408
408
|
|
package/dist/lib/tui/setup.js
CHANGED
|
@@ -11,7 +11,7 @@ import { getWriteSummary, writeFilesWithProgress } from "./writer.js";
|
|
|
11
11
|
// Central skills directory for global installation
|
|
12
12
|
const GLOBAL_SKILLS_DIR = join(homedir(), ".agents", "skills");
|
|
13
13
|
// API base URL
|
|
14
|
-
const API_URL = "https://gethmy.com/api";
|
|
14
|
+
const API_URL = "https://app.gethmy.com/api";
|
|
15
15
|
/**
|
|
16
16
|
* Register MCP server using Claude CLI
|
|
17
17
|
* Returns true if successful, false if CLI unavailable or failed
|
|
@@ -422,7 +422,7 @@ export async function runSetup(options = {}) {
|
|
|
422
422
|
if (!validation.valid) {
|
|
423
423
|
spinner.stop(colors.error("API key validation failed"));
|
|
424
424
|
p.log.error(validation.error || "Could not connect to Harmony API");
|
|
425
|
-
p.log.info("Get an API key at: https://gethmy.com/user/keys");
|
|
425
|
+
p.log.info("Get an API key at: https://app.gethmy.com/user/keys");
|
|
426
426
|
process.exit(1);
|
|
427
427
|
}
|
|
428
428
|
if (!userEmail) {
|
|
@@ -765,6 +765,6 @@ export async function runSetup(options = {}) {
|
|
|
765
765
|
}
|
|
766
766
|
console.log("");
|
|
767
767
|
console.log(` ${colors.dim("Add to new project: npx @gethmy/mcp setup")}`);
|
|
768
|
-
console.log(` ${colors.dim("Need help? Visit https://gethmy.com/docs/mcp")}`);
|
|
768
|
+
console.log(` ${colors.dim("Need help? Visit https://app.gethmy.com/docs/mcp")}`);
|
|
769
769
|
console.log("");
|
|
770
770
|
}
|
package/package.json
CHANGED
package/src/auto-session.ts
CHANGED
|
@@ -118,11 +118,18 @@ export async function trackActivity(
|
|
|
118
118
|
|
|
119
119
|
/**
|
|
120
120
|
* Mark a session as explicitly started (won't be auto-ended by card switching or inactivity).
|
|
121
|
+
* Optionally accepts the real agent identifier/name to store in the session.
|
|
121
122
|
*/
|
|
122
|
-
export function markExplicit(
|
|
123
|
+
export function markExplicit(
|
|
124
|
+
cardId: string,
|
|
125
|
+
options?: { agentIdentifier?: string; agentName?: string },
|
|
126
|
+
): void {
|
|
123
127
|
const existing = activeSessions.get(cardId);
|
|
124
128
|
if (existing) {
|
|
125
129
|
existing.isExplicit = true;
|
|
130
|
+
if (options?.agentIdentifier)
|
|
131
|
+
existing.agentIdentifier = options.agentIdentifier;
|
|
132
|
+
if (options?.agentName) existing.agentName = options.agentName;
|
|
126
133
|
} else {
|
|
127
134
|
// Track the explicit session even if we didn't auto-start it
|
|
128
135
|
activeSessions.set(cardId, {
|
|
@@ -130,8 +137,8 @@ export function markExplicit(cardId: string): void {
|
|
|
130
137
|
startedAt: Date.now(),
|
|
131
138
|
lastActivityAt: Date.now(),
|
|
132
139
|
isExplicit: true,
|
|
133
|
-
agentIdentifier: "explicit",
|
|
134
|
-
agentName: "Explicit Agent",
|
|
140
|
+
agentIdentifier: options?.agentIdentifier ?? "explicit",
|
|
141
|
+
agentName: options?.agentName ?? "Explicit Agent",
|
|
135
142
|
});
|
|
136
143
|
}
|
|
137
144
|
}
|
package/src/cli.ts
CHANGED
|
@@ -113,7 +113,7 @@ program
|
|
|
113
113
|
} else {
|
|
114
114
|
console.log("Status: Not configured\n");
|
|
115
115
|
console.log("Run: npx @gethmy/mcp setup");
|
|
116
|
-
console.log("Get an API key at: https://gethmy.com/user/keys");
|
|
116
|
+
console.log("Get an API key at: https://app.gethmy.com/user/keys");
|
|
117
117
|
}
|
|
118
118
|
});
|
|
119
119
|
|
package/src/config.ts
CHANGED
|
@@ -20,7 +20,7 @@ export interface LocalConfig {
|
|
|
20
20
|
projectId: string | null;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const DEFAULT_API_URL = "https://gethmy.com/api";
|
|
23
|
+
const DEFAULT_API_URL = "https://app.gethmy.com/api";
|
|
24
24
|
const LOCAL_CONFIG_FILENAME = ".harmony-mcp.json";
|
|
25
25
|
|
|
26
26
|
export function getConfigDir(): string {
|
package/src/http.ts
CHANGED
package/src/prompt-builder.ts
CHANGED
|
@@ -438,6 +438,9 @@ export function generatePrompt(
|
|
|
438
438
|
roleFraming.focus.forEach((f) => {
|
|
439
439
|
sections.push(`- ${f}`);
|
|
440
440
|
});
|
|
441
|
+
sections.push(
|
|
442
|
+
`- **Memory:** When you discover important domain knowledge, architectural decisions, or infrastructure details, store them via \`harmony_remember\`. Focus on durable knowledge that future agents would benefit from — not ephemeral task details (those are auto-extracted from your session).`,
|
|
443
|
+
);
|
|
441
444
|
|
|
442
445
|
// Output suggestions
|
|
443
446
|
sections.push(`\n## Suggested Outputs`);
|
package/src/remote.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* Claude.ai → POST https://mcp.gethmy.com/mcp (Bearer: hmy_xxx)
|
|
11
11
|
*
|
|
12
12
|
* Env vars:
|
|
13
|
-
* HARMONY_API_URL - Harmony API base URL (default: https://gethmy.com/api)
|
|
13
|
+
* HARMONY_API_URL - Harmony API base URL (default: https://app.gethmy.com/api)
|
|
14
14
|
* PORT - Listen port (default: 3002)
|
|
15
15
|
*/
|
|
16
16
|
|
|
@@ -25,7 +25,7 @@ import { registerHandlers, type ToolDeps } from "./server.js";
|
|
|
25
25
|
// ---------------------------------------------------------------------------
|
|
26
26
|
// Config from env
|
|
27
27
|
// ---------------------------------------------------------------------------
|
|
28
|
-
const HARMONY_API_URL = process.env.HARMONY_API_URL || "https://gethmy.com/api";
|
|
28
|
+
const HARMONY_API_URL = process.env.HARMONY_API_URL || "https://app.gethmy.com/api";
|
|
29
29
|
const PORT = parseInt(process.env.PORT || "3002", 10);
|
|
30
30
|
|
|
31
31
|
// ---------------------------------------------------------------------------
|