@echomem/mcp 1.4.24 → 1.4.25
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/hud/server.js +1 -1
- package/dist/hud/web.js +1 -1
- package/dist/index.js +73 -13
- package/dist/package-metadata.js +2 -0
- package/dist/setup-page/client-extraction.js +1 -1
- package/dist/setup-preview.js +1 -1
- package/dist/setup.js +5 -3
- package/dist/v1-contract.js +58 -4
- package/package.json +1 -1
package/dist/hud/server.js
CHANGED
|
@@ -13,7 +13,7 @@ import { assembleCodex, assembleClaude } from "../migrate.js";
|
|
|
13
13
|
import { readBillingAlert } from "../billing-alert.js";
|
|
14
14
|
import { readSessionWorkingDirectory, } from "./session-launcher.js";
|
|
15
15
|
const API_BASE = (process.env.ECHO_API_BASE_URL || "https://echo-mem-chrome.vercel.app").replace(/\/$/, "");
|
|
16
|
-
const PRICING_URL = (process.env.ECHO_PRICING_URL || "https://echoknows.com/
|
|
16
|
+
const PRICING_URL = (process.env.ECHO_PRICING_URL || "https://echoknows.com/account").replace(/\/$/, "");
|
|
17
17
|
export async function createHudServer(opts = {}) {
|
|
18
18
|
const mode = opts.mode || "auto";
|
|
19
19
|
const port = opts.port ?? 17377;
|
package/dist/hud/web.js
CHANGED
|
@@ -1729,7 +1729,7 @@ export const HUD_HTML = String.raw `<!doctype html>
|
|
|
1729
1729
|
state: "ok",
|
|
1730
1730
|
plan: "pro",
|
|
1731
1731
|
paid: true,
|
|
1732
|
-
pricingUrl: "https://
|
|
1732
|
+
pricingUrl: "https://echoknows.com/account?source=hud_preview",
|
|
1733
1733
|
memoryProcessingQuota: { used: previewProcessingUsed, limit: 200000, remaining: 200000 - previewProcessingUsed, resetAt: new Date(Date.now() + 31 * 60 * 60 * 1000).toISOString() },
|
|
1734
1734
|
memorySearchQuota: { used: previewSearchUsed, limit: 500, remaining: 500 - previewSearchUsed, resetAt: new Date(Date.now() + 31 * 60 * 60 * 1000).toISOString() },
|
|
1735
1735
|
historicalConversationQuota: { used: 191, limit: 500, remaining: 309 },
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
4
4
|
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
5
|
import axios from "axios";
|
|
6
6
|
import { ZodError } from "zod";
|
|
7
|
-
import { canonicalToolNames, completeGroupPublicationSchema, createGroupInviteSchema, createGroupSchema, deleteMemorySchema, getByContextSchema, groupContextSchema, joinGroupSchema, keywordsSchema, listFriendsSchema, listToolSpecs, othersSchema, publishBatchToGroupSchema, publishToGroupSchema, prepareGroupPublicationSchema, publicMemorySchema, resolveCanonicalToolName, saveConversationSchema, searchMemoriesSchema, searchUsersSchema, sendFriendRequestSchema, timeRangeSchema, updateGroupProfileSchema, } from "./v1-contract.js";
|
|
7
|
+
import { canonicalToolNames, completeGroupPublicationSchema, createGroupInviteSchema, createGroupSchema, deleteMemorySchema, flagPublicationAttentionSchema, getByContextSchema, groupContextSchema, joinGroupSchema, keywordsSchema, listFriendsSchema, listToolSpecs, othersSchema, publishBatchToGroupSchema, publishToGroupSchema, prepareGroupPublicationSchema, publicMemorySchema, resolveCanonicalToolName, saveConversationSchema, searchMemoriesSchema, searchUsersSchema, sendFriendRequestSchema, timeRangeSchema, updateGroupProfileSchema, } from "./v1-contract.js";
|
|
8
8
|
import { KeyStore } from "./keystore.js";
|
|
9
9
|
import { EventLogger, hashText } from "./events.js";
|
|
10
10
|
import { buildReportText } from "./report.js";
|
|
@@ -16,7 +16,11 @@ import { MCP_PACKAGE_VERSION, MCP_SERVER_INSTRUCTIONS } from "./package-metadata
|
|
|
16
16
|
import { clearBillingAlert, writeBillingAlert } from "./billing-alert.js";
|
|
17
17
|
import { checkLatestUpdateStatus, formatUpdateNotice, formatUpdateStatusText, startBackgroundUpdateCheck, } from "./update-check.js";
|
|
18
18
|
const ECHO_API_BASE_URL = process.env.ECHO_API_BASE_URL || "https://echo-mem-chrome.vercel.app";
|
|
19
|
-
const ECHO_PRICING_URL = process.env.ECHO_PRICING_URL || "https://echoknows.com/
|
|
19
|
+
const ECHO_PRICING_URL = process.env.ECHO_PRICING_URL || "https://echoknows.com/account";
|
|
20
|
+
const ECHO_MEMORY_WEB_URL = (process.env.ECHO_MEMORY_WEB_URL || "https://echoknows.com/company/memories").replace(/\/$/, "");
|
|
21
|
+
function memoryWebUrl(memoryId) {
|
|
22
|
+
return `${ECHO_MEMORY_WEB_URL}?memoryId=${encodeURIComponent(memoryId)}`;
|
|
23
|
+
}
|
|
20
24
|
/** Thrown when no API token is present yet — the model gets a "run login" nudge, not a hard error. */
|
|
21
25
|
class NoTokenError extends Error {
|
|
22
26
|
}
|
|
@@ -495,6 +499,14 @@ function inputAnalyticsForTool(canonicalName, args) {
|
|
|
495
499
|
memory_id_hash: memoryId ? hashText(memoryId) : undefined,
|
|
496
500
|
};
|
|
497
501
|
}
|
|
502
|
+
case canonicalToolNames.flagPublicationAttention: {
|
|
503
|
+
const memoryIds = Array.isArray(a.memoryIds) ? a.memoryIds.filter((id) => typeof id === "string") : [];
|
|
504
|
+
return {
|
|
505
|
+
memory_count: memoryIds.length,
|
|
506
|
+
has_label: !!readString(a, "label"),
|
|
507
|
+
confirmed: a.confirmed === true,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
498
510
|
case canonicalToolNames.publishBatchToGroup: {
|
|
499
511
|
const memoryIds = Array.isArray(a.memoryIds) ? a.memoryIds.filter((id) => typeof id === "string") : [];
|
|
500
512
|
return {
|
|
@@ -983,6 +995,11 @@ class EchoMemApiClient {
|
|
|
983
995
|
const response = await this.axios.post("/api/extension/social/groups/current/publications/prepare", parsed, { headers: enc.enabled && enc.key ? { "X-Encryption-Key": enc.key } : undefined });
|
|
984
996
|
return response.data;
|
|
985
997
|
}
|
|
998
|
+
async flagMemoriesForPublicationAttention(args) {
|
|
999
|
+
const parsed = flagPublicationAttentionSchema.parse(args ?? {});
|
|
1000
|
+
const response = await this.axios.post("/api/extension/memories/publication-attention", parsed);
|
|
1001
|
+
return response.data;
|
|
1002
|
+
}
|
|
986
1003
|
async updateGroupProfile(args) {
|
|
987
1004
|
const parsed = updateGroupProfileSchema.parse(args ?? {});
|
|
988
1005
|
const response = await this.axios.patch("/api/extension/social/groups/current/profile", parsed);
|
|
@@ -998,7 +1015,9 @@ class EchoMemApiClient {
|
|
|
998
1015
|
const parsed = publishToGroupSchema.parse(args ?? {});
|
|
999
1016
|
const enc = await this.encState();
|
|
1000
1017
|
try {
|
|
1001
|
-
const response = await this.axios.post(`/api/extension/social/groups/current/memories/${encodeURIComponent(parsed.memoryId)}/publish`, {
|
|
1018
|
+
const response = await this.axios.post(`/api/extension/social/groups/current/memories/${encodeURIComponent(parsed.memoryId)}/publish`, {
|
|
1019
|
+
acknowledgedFlaggedMemoryIds: parsed.acknowledgedFlaggedMemoryIds,
|
|
1020
|
+
}, {
|
|
1002
1021
|
headers: enc.enabled && enc.key ? { "X-Encryption-Key": enc.key } : undefined,
|
|
1003
1022
|
});
|
|
1004
1023
|
return response.data;
|
|
@@ -1014,6 +1033,8 @@ class EchoMemApiClient {
|
|
|
1014
1033
|
const response = await this.axios.post("/api/extension/social/groups/current/memories/publish-batch", {
|
|
1015
1034
|
memoryIds: parsed.memoryIds,
|
|
1016
1035
|
contextId: parsed.contextId,
|
|
1036
|
+
selectionReason: parsed.selectionReason,
|
|
1037
|
+
acknowledgedFlaggedMemoryIds: parsed.acknowledgedFlaggedMemoryIds,
|
|
1017
1038
|
}, {
|
|
1018
1039
|
headers: enc.enabled && enc.key ? { "X-Encryption-Key": enc.key } : undefined,
|
|
1019
1040
|
});
|
|
@@ -1210,6 +1231,8 @@ class EchoMemMCPServer {
|
|
|
1210
1231
|
return await this.handleJoinGroup(request.params.arguments);
|
|
1211
1232
|
case canonicalToolNames.prepareGroupPublication:
|
|
1212
1233
|
return await this.handlePrepareGroupPublication(request.params.arguments);
|
|
1234
|
+
case canonicalToolNames.flagPublicationAttention:
|
|
1235
|
+
return await this.handleFlagPublicationAttention(request.params.arguments);
|
|
1213
1236
|
case canonicalToolNames.updateGroupProfile:
|
|
1214
1237
|
return await this.handleUpdateGroupProfile(request.params.arguments);
|
|
1215
1238
|
case canonicalToolNames.completeGroupPublication:
|
|
@@ -1634,6 +1657,7 @@ Details: ${m.details || "N/A"}`)
|
|
|
1634
1657
|
? m.similarity_score
|
|
1635
1658
|
: undefined;
|
|
1636
1659
|
return `[${idx + 1}] Memory ID: ${m.id || "unknown"}
|
|
1660
|
+
Open memory: ${memoryWebUrl(String(m.id || "unknown"))}
|
|
1637
1661
|
User ID: ${m.user_id || "unknown"}
|
|
1638
1662
|
User Name: ${m.username || m.user_name || m.name || "Anonymous"}
|
|
1639
1663
|
Time: ${m.time} | Location: ${m.location}
|
|
@@ -1759,6 +1783,7 @@ Details: ${m.details || "N/A"}`;
|
|
|
1759
1783
|
}
|
|
1760
1784
|
const text = [
|
|
1761
1785
|
`Memory ID: ${memory.id || parsed.memoryId}`,
|
|
1786
|
+
`Open memory: ${memoryWebUrl(String(memory.id || parsed.memoryId))}`,
|
|
1762
1787
|
`Owner User ID: ${memory.owner_user_id || memory.user_id || "Unknown"}`,
|
|
1763
1788
|
memory.time ? `Time: ${memory.time}` : "",
|
|
1764
1789
|
memory.location ? `Location: ${memory.location}` : "",
|
|
@@ -1880,15 +1905,26 @@ Details: ${m.details || "N/A"}`;
|
|
|
1880
1905
|
const participantProfile = isRecord(payload?.participantProfile)
|
|
1881
1906
|
? payload.participantProfile
|
|
1882
1907
|
: {};
|
|
1883
|
-
const formatted = candidates.map((candidate, index) =>
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1908
|
+
const formatted = candidates.map((candidate, index) => {
|
|
1909
|
+
const attention = isRecord(candidate.publicationAttention)
|
|
1910
|
+
? candidate.publicationAttention
|
|
1911
|
+
: null;
|
|
1912
|
+
return [
|
|
1913
|
+
`[${index + 1}] Memory ID: ${readString(candidate, "memoryId") ?? "unknown"}`,
|
|
1914
|
+
`Open memory: ${memoryWebUrl(readString(candidate, "memoryId") ?? "unknown")}`,
|
|
1915
|
+
`Created: ${readString(candidate, "createdAt") ?? "unknown"}`,
|
|
1916
|
+
`Category: ${readString(candidate, "category") ?? "unknown"}`,
|
|
1917
|
+
`Description: ${readString(candidate, "description") ?? ""}`,
|
|
1918
|
+
readString(candidate, "details") ? `Details: ${readString(candidate, "details")}` : "",
|
|
1919
|
+
`Already published: ${candidate.alreadyPublished === true ? "yes" : "no"}`,
|
|
1920
|
+
`Exact content duplicate: ${candidate.exactContentDuplicate === true ? "yes" : "no"}`,
|
|
1921
|
+
attention ? `PUBLICATION ATTENTION: ${readString(attention, "label") ?? "flagged"}` : "",
|
|
1922
|
+
].filter(Boolean).join("\n");
|
|
1923
|
+
}).join("\n\n");
|
|
1924
|
+
const flaggedIds = candidates
|
|
1925
|
+
.filter((candidate) => isRecord(candidate.publicationAttention))
|
|
1926
|
+
.map((candidate) => readString(candidate, "memoryId"))
|
|
1927
|
+
.filter(Boolean);
|
|
1892
1928
|
return {
|
|
1893
1929
|
content: [{
|
|
1894
1930
|
type: "text",
|
|
@@ -1901,11 +1937,35 @@ Details: ${m.details || "N/A"}`;
|
|
|
1901
1937
|
"",
|
|
1902
1938
|
formatted,
|
|
1903
1939
|
"",
|
|
1904
|
-
|
|
1940
|
+
flaggedIds.length
|
|
1941
|
+
? `Extra attention required: ${flaggedIds.length} candidate(s) are flagged (${flaggedIds.join(", ")}). Show them in a separate warning and require a separate explicit acknowledgement before including their exact IDs in acknowledgedFlaggedMemoryIds.`
|
|
1942
|
+
: "",
|
|
1943
|
+
"Select exact memory IDs matching the user's instruction. From memory evidence, draft a concise title and responsibility summary. Show the profile proposal and memory preview together, then ask for explicit confirmation. After confirmation, call update_group_profile and complete_group_publication.",
|
|
1905
1944
|
].join("\n"),
|
|
1906
1945
|
}],
|
|
1907
1946
|
};
|
|
1908
1947
|
}
|
|
1948
|
+
async handleFlagPublicationAttention(args) {
|
|
1949
|
+
const parsed = flagPublicationAttentionSchema.parse(args ?? {});
|
|
1950
|
+
const payload = await this.client.flagMemoriesForPublicationAttention(parsed);
|
|
1951
|
+
const alreadyPublished = typeof payload?.alreadyPublishedGroupCount === "number"
|
|
1952
|
+
? payload.alreadyPublishedGroupCount
|
|
1953
|
+
: 0;
|
|
1954
|
+
return {
|
|
1955
|
+
content: [{
|
|
1956
|
+
type: "text",
|
|
1957
|
+
text: [
|
|
1958
|
+
`Flagged ${payload?.flaggedCount ?? parsed.memoryIds.length} memories for publication attention.`,
|
|
1959
|
+
`Label: ${parsed.label}`,
|
|
1960
|
+
`Memory IDs: ${parsed.memoryIds.join(", ")}`,
|
|
1961
|
+
"No memory was published, decrypted, or made globally public.",
|
|
1962
|
+
alreadyPublished > 0
|
|
1963
|
+
? `Attention: ${alreadyPublished} flagged memories already have group snapshots. This flag does not retract those existing snapshots.`
|
|
1964
|
+
: "",
|
|
1965
|
+
].filter(Boolean).join("\n"),
|
|
1966
|
+
}],
|
|
1967
|
+
};
|
|
1968
|
+
}
|
|
1909
1969
|
async handleUpdateGroupProfile(args) {
|
|
1910
1970
|
const parsed = updateGroupProfileSchema.parse(args ?? {});
|
|
1911
1971
|
const payload = await this.client.updateGroupProfile(parsed);
|
package/dist/package-metadata.js
CHANGED
|
@@ -30,6 +30,8 @@ export const MCP_SERVER_INSTRUCTIONS = [
|
|
|
30
30
|
"Do not auto-update on every MCP startup; this bridge is intentionally stable between explicit updates.",
|
|
31
31
|
"For company-group sharing, use get_group_context for orientation; create_memory_group/create_group_invite/join_memory_group for membership; and prepare_group_publication as a no-publication preview.",
|
|
32
32
|
"After joining or when profile fields are missing, use candidate memory evidence to propose a title and responsibility summary. Ask the user to confirm that proposal together with the publication preview, then call update_group_profile and complete_group_publication.",
|
|
33
|
+
"Each group-search result is one memory: preserve its Memory ID and direct echoknows.com link when citing it.",
|
|
34
|
+
"For sensitive-topic flags, search and preview exact owned memories before confirmed flag_memories_for_publication_attention. During publication, separate flagged candidates and require exact-ID acknowledgement.",
|
|
33
35
|
"Never save an inferred group profile or complete a group publication without explicit confirmation, and never store or log an echo_grp_ invite code.",
|
|
34
36
|
].join(" ");
|
|
35
37
|
export function withMcpVersion(description) {
|
|
@@ -900,7 +900,7 @@ export const SETUP_PAGE_CLIENT_EXTRACTION = String.raw ` /* ---------- dash
|
|
|
900
900
|
var paidPlan = plan === "power" ? "power" : "pro";
|
|
901
901
|
return (billingStatus && billingStatus.pricingUrl)
|
|
902
902
|
? billingStatus.pricingUrl + (startTrial ? "&start=" + paidPlan + "&trial=" + (billingStatus.trialAvailable === false ? "0" : "1") : "")
|
|
903
|
-
: "https://echoknows.com/
|
|
903
|
+
: "https://echoknows.com/account?source=mcp_onboarding" + (startTrial ? "&start=" + paidPlan + "&trial=1" : "");
|
|
904
904
|
}
|
|
905
905
|
function setupPlanConfirmed() {
|
|
906
906
|
return setupPlanChoice === "free" || paidRecallPlan(billingStatus && billingStatus.plan);
|
package/dist/setup-preview.js
CHANGED
|
@@ -234,7 +234,7 @@ function extractionPreviewBootstrap(options) {
|
|
|
234
234
|
trialUsed: options.trialUsed,
|
|
235
235
|
subscriptionStatus: options.subscriptionStatus ?? null,
|
|
236
236
|
trialEndedAt: options.trialEndedAt ?? null,
|
|
237
|
-
pricingUrl: "https://echoknows.com/
|
|
237
|
+
pricingUrl: "https://echoknows.com/account?source=mcp_onboarding",
|
|
238
238
|
account: {
|
|
239
239
|
displayName: "Preview User",
|
|
240
240
|
email: "preview@example.com",
|
package/dist/setup.js
CHANGED
|
@@ -37,7 +37,7 @@ import { checkLatestUpdateStatus, compareSemver, readCachedUpdateStatus } from "
|
|
|
37
37
|
// The setup dashboard, account login, and encryption passphrase entry are all served by this
|
|
38
38
|
// localhost bridge. The hosted API only sends OTP email, verifies the code, and mints a device token.
|
|
39
39
|
const API_BASE_URL = (process.env.ECHO_API_BASE_URL || "https://echo-mem-chrome.vercel.app").replace(/\/$/, "");
|
|
40
|
-
const PRICING_URL = (process.env.ECHO_PRICING_URL || "https://echoknows.com/
|
|
40
|
+
const PRICING_URL = (process.env.ECHO_PRICING_URL || "https://echoknows.com/account").replace(/\/$/, "");
|
|
41
41
|
function hostedBillingEndpoint(pathname) {
|
|
42
42
|
const url = new URL(PRICING_URL);
|
|
43
43
|
url.pathname = pathname;
|
|
@@ -399,8 +399,10 @@ function echomemGuidanceBlock() {
|
|
|
399
399
|
"- If a user supplies an `echo_grp_...` code and explicitly asks to join, call `join_memory_group`. Joining never authorizes publishing by itself and must not move a user out of another group. After joining, continue into the profile-and-publication preview instead of leaving title or responsibility blank.",
|
|
400
400
|
"- For requests such as “prepare my recent work memories,” “upload work from this ticket,” or “publish work since my last sync,” call `prepare_group_publication` first. This is a no-publication preview. For encrypted accounts, tell the user to run `echomem-mcp unlock` locally if the tool reports that the key is required.",
|
|
401
401
|
"- After preparing, select only exact candidate memory IDs that match the user's stated scope and exclude already-published or exact-content duplicates. Use the candidate evidence to draft a concise title and responsibility summary for the current member, but label both as proposals rather than facts.",
|
|
402
|
-
"-
|
|
403
|
-
"-
|
|
402
|
+
"- Each returned group-search result is one memory. When citing it in a bullet, preserve its Memory ID and include its `https://echoknows.com/company/memories?memoryId=...` link so the user can open the evidence directly.",
|
|
403
|
+
"- If the user asks to flag memories about a sensitive topic, search their own memories first, show the exact matches, and ask them to confirm. Only then call `flag_memories_for_publication_attention`; flagging does not publish, decrypt, change visibility, or retract an existing group snapshot.",
|
|
404
|
+
"- Present the proposed title/responsibility and the memory publication preview together and ask for explicit confirmation. Never save an inferred profile or publish memories before confirmation. Show flagged candidates in a separate warning.",
|
|
405
|
+
"- On confirmation, call `update_group_profile` with the confirmed title, responsibility summary, and `confirmed: true`, then call `complete_group_publication` with the exact `scanId`, selected memory IDs, and `confirmed: true`. If a flagged memory is selected, require separate explicit acknowledgement and pass its exact ID in `acknowledgedFlaggedMemoryIds`. If the user edits either proposal, use their wording. An explicit request to join and upload still requires this preview and confirmation.",
|
|
404
406
|
"- If the user asks to show, reopen, restart, or bring back the EchoMem HUD (the context-health overlay), run the shell command `echomem-hud app --client auto`.",
|
|
405
407
|
"- If the user wants the HUD to come back after a computer restart, run the shell command `echomem-hud autostart on --client auto`.",
|
|
406
408
|
AGENTS_MD_END,
|
package/dist/v1-contract.js
CHANGED
|
@@ -15,6 +15,7 @@ export const canonicalToolNames = {
|
|
|
15
15
|
createGroupInvite: "create_group_invite",
|
|
16
16
|
joinGroup: "join_memory_group",
|
|
17
17
|
prepareGroupPublication: "prepare_group_publication",
|
|
18
|
+
flagPublicationAttention: "flag_memories_for_publication_attention",
|
|
18
19
|
updateGroupProfile: "update_group_profile",
|
|
19
20
|
completeGroupPublication: "complete_group_publication",
|
|
20
21
|
publishToGroup: "publish_memory_to_group",
|
|
@@ -144,6 +145,12 @@ export const prepareGroupPublicationSchema = z.object({
|
|
|
144
145
|
limit: z.number().int().min(1).max(50).optional(),
|
|
145
146
|
instruction: z.string().max(500).optional(),
|
|
146
147
|
});
|
|
148
|
+
export const flagPublicationAttentionSchema = z.object({
|
|
149
|
+
...triggerMetadataSchema,
|
|
150
|
+
memoryIds: z.array(z.string().min(1)).min(1).max(50),
|
|
151
|
+
label: z.string().min(1).max(120),
|
|
152
|
+
confirmed: z.literal(true),
|
|
153
|
+
});
|
|
147
154
|
export const updateGroupProfileSchema = z.object({
|
|
148
155
|
...triggerMetadataSchema,
|
|
149
156
|
displayName: z.string().min(1).max(120).optional(),
|
|
@@ -157,16 +164,19 @@ export const completeGroupPublicationSchema = z.object({
|
|
|
157
164
|
memoryIds: z.array(z.string().min(1)).max(50),
|
|
158
165
|
confirmed: z.literal(true),
|
|
159
166
|
selectionReason: z.string().max(500).optional(),
|
|
167
|
+
acknowledgedFlaggedMemoryIds: z.array(z.string().min(1)).max(50).optional(),
|
|
160
168
|
});
|
|
161
169
|
export const publishToGroupSchema = z.object({
|
|
162
170
|
...triggerMetadataSchema,
|
|
163
171
|
memoryId: z.string().min(1),
|
|
172
|
+
acknowledgedFlaggedMemoryIds: z.array(z.string().min(1)).max(1).optional(),
|
|
164
173
|
});
|
|
165
174
|
export const publishBatchToGroupSchema = z.object({
|
|
166
175
|
...triggerMetadataSchema,
|
|
167
176
|
memoryIds: z.array(z.string().min(1)).min(1).max(50),
|
|
168
177
|
contextId: z.string().min(1).optional(),
|
|
169
178
|
selectionReason: z.string().max(500).optional(),
|
|
179
|
+
acknowledgedFlaggedMemoryIds: z.array(z.string().min(1)).max(50).optional(),
|
|
170
180
|
});
|
|
171
181
|
export const deleteMemorySchema = z.object({
|
|
172
182
|
memoryId: z.string().min(1),
|
|
@@ -482,7 +492,7 @@ export function listToolSpecs(opts = {}) {
|
|
|
482
492
|
},
|
|
483
493
|
{
|
|
484
494
|
name: canonicalToolNames.prepareGroupPublication,
|
|
485
|
-
description: "Prepare a no-publication preview of up to 50 owned memories for group publication. For encrypted accounts the local bridge must be unlocked. The host agent selects exact work-related memory ids, drafts a concise title and responsibility summary from memory evidence, and asks the user to confirm both the profile and publication selection together. This tool never publishes.",
|
|
495
|
+
description: "Prepare a no-publication preview of up to 50 owned memories for group publication. For encrypted accounts the local bridge must be unlocked. The host agent selects exact work-related memory ids, drafts a concise title and responsibility summary from memory evidence, and asks the user to confirm both the profile and publication selection together. Flagged memories are identified separately and require extra attention before publication. This tool never publishes.",
|
|
486
496
|
inputSchema: {
|
|
487
497
|
type: "object",
|
|
488
498
|
properties: {
|
|
@@ -496,6 +506,32 @@ export function listToolSpecs(opts = {}) {
|
|
|
496
506
|
},
|
|
497
507
|
},
|
|
498
508
|
},
|
|
509
|
+
{
|
|
510
|
+
name: canonicalToolNames.flagPublicationAttention,
|
|
511
|
+
description: "Mark exact owned memories for extra attention during future group publication. First search the user's own memories, show the matching memory IDs and summaries, and obtain explicit confirmation. This only records a safety flag; it does not publish, decrypt, change visibility, or retract an existing group snapshot.",
|
|
512
|
+
inputSchema: {
|
|
513
|
+
type: "object",
|
|
514
|
+
properties: {
|
|
515
|
+
memoryIds: {
|
|
516
|
+
type: "array",
|
|
517
|
+
minItems: 1,
|
|
518
|
+
maxItems: 50,
|
|
519
|
+
items: { type: "string" },
|
|
520
|
+
description: "Exact owned memory IDs the user reviewed and confirmed.",
|
|
521
|
+
},
|
|
522
|
+
label: {
|
|
523
|
+
type: "string",
|
|
524
|
+
description: "A short user-supplied attention label, such as investment or customer-confidential.",
|
|
525
|
+
},
|
|
526
|
+
confirmed: {
|
|
527
|
+
type: "boolean",
|
|
528
|
+
const: true,
|
|
529
|
+
description: "Set true only after the user confirms the exact memories.",
|
|
530
|
+
},
|
|
531
|
+
},
|
|
532
|
+
required: ["memoryIds", "label", "confirmed"],
|
|
533
|
+
},
|
|
534
|
+
},
|
|
499
535
|
{
|
|
500
536
|
name: canonicalToolNames.updateGroupProfile,
|
|
501
537
|
description: "Save the current member's declared group title and responsibility summary only after the user explicitly confirms the agent's proposal. These become directory facts visible to group members; never save an unconfirmed inference.",
|
|
@@ -512,7 +548,7 @@ export function listToolSpecs(opts = {}) {
|
|
|
512
548
|
},
|
|
513
549
|
{
|
|
514
550
|
name: canonicalToolNames.completeGroupPublication,
|
|
515
|
-
description: "Publish only the exact memory ids from a prepared scan after the user explicitly confirms the preview. confirmed must be true. Completing an empty selection safely advances the scan cursor without publishing.",
|
|
551
|
+
description: "Publish only the exact memory ids from a prepared scan after the user explicitly confirms the preview. confirmed must be true. Any flagged memories must be called out separately and their exact IDs supplied in acknowledgedFlaggedMemoryIds after extra user acknowledgement. Completing an empty selection safely advances the scan cursor without publishing.",
|
|
516
552
|
inputSchema: {
|
|
517
553
|
type: "object",
|
|
518
554
|
properties: {
|
|
@@ -520,13 +556,19 @@ export function listToolSpecs(opts = {}) {
|
|
|
520
556
|
memoryIds: { type: "array", maxItems: 50, items: { type: "string" } },
|
|
521
557
|
confirmed: { type: "boolean", const: true },
|
|
522
558
|
selectionReason: { type: "string" },
|
|
559
|
+
acknowledgedFlaggedMemoryIds: {
|
|
560
|
+
type: "array",
|
|
561
|
+
maxItems: 50,
|
|
562
|
+
items: { type: "string" },
|
|
563
|
+
description: "Exact flagged IDs the user separately acknowledged for this publication.",
|
|
564
|
+
},
|
|
523
565
|
},
|
|
524
566
|
required: ["scanId", "memoryIds", "confirmed"],
|
|
525
567
|
},
|
|
526
568
|
},
|
|
527
569
|
{
|
|
528
570
|
name: canonicalToolNames.publishToGroup,
|
|
529
|
-
description: "Publish one exact memory snapshot to your current company group without changing the memory's global is_public or encryption state. Call only after the user explicitly asks to publish or push that memory. The operation is idempotent.",
|
|
571
|
+
description: "Publish one exact memory snapshot to your current company group without changing the memory's global is_public or encryption state. Call only after the user explicitly asks to publish or push that memory. If it is flagged, call it out and pass its ID in acknowledgedFlaggedMemoryIds only after extra user acknowledgement. The operation is idempotent.",
|
|
530
572
|
inputSchema: {
|
|
531
573
|
type: "object",
|
|
532
574
|
properties: {
|
|
@@ -539,13 +581,19 @@ export function listToolSpecs(opts = {}) {
|
|
|
539
581
|
description: "Optional user message that explicitly requested publication.",
|
|
540
582
|
},
|
|
541
583
|
triggerMessageRole: { type: "string", default: "user" },
|
|
584
|
+
acknowledgedFlaggedMemoryIds: {
|
|
585
|
+
type: "array",
|
|
586
|
+
maxItems: 1,
|
|
587
|
+
items: { type: "string" },
|
|
588
|
+
description: "Include the memory ID only after separate acknowledgement if the memory is flagged.",
|
|
589
|
+
},
|
|
542
590
|
},
|
|
543
591
|
required: ["memoryId"],
|
|
544
592
|
},
|
|
545
593
|
},
|
|
546
594
|
{
|
|
547
595
|
name: canonicalToolNames.publishBatchToGroup,
|
|
548
|
-
description: "Publish up to 50 exact memory snapshots to your current company group without changing global is_public or the encrypted originals. For a session request, first call get_memories_by_context, select the exact ids that match the user's instruction, then pass those ids with the same contextId. Call only after explicit group-publication intent; report what was selected when the user delegates work-related filtering.",
|
|
596
|
+
description: "Publish up to 50 exact memory snapshots to your current company group without changing global is_public or the encrypted originals. For a session request, first call get_memories_by_context, select the exact ids that match the user's instruction, then pass those ids with the same contextId. Call only after explicit group-publication intent; report what was selected when the user delegates work-related filtering. Flagged memories must be called out separately and acknowledged by exact ID.",
|
|
549
597
|
inputSchema: {
|
|
550
598
|
type: "object",
|
|
551
599
|
properties: {
|
|
@@ -569,6 +617,12 @@ export function listToolSpecs(opts = {}) {
|
|
|
569
617
|
description: "Optional user message that explicitly requested publication.",
|
|
570
618
|
},
|
|
571
619
|
triggerMessageRole: { type: "string", default: "user" },
|
|
620
|
+
acknowledgedFlaggedMemoryIds: {
|
|
621
|
+
type: "array",
|
|
622
|
+
maxItems: 50,
|
|
623
|
+
items: { type: "string" },
|
|
624
|
+
description: "Exact flagged IDs the user separately acknowledged for this publication.",
|
|
625
|
+
},
|
|
572
626
|
},
|
|
573
627
|
required: ["memoryIds"],
|
|
574
628
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@echomem/mcp",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.25",
|
|
4
4
|
"description": "EchoMem MCP bridge: cloud-first memory tools, local context HUD, and the Agent Doctor workspace forensics report (cost ledger + 3D repo city)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|