@abraca/mcp 1.6.0 → 1.8.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/abracadabra-mcp.cjs +1165 -190
- package/dist/abracadabra-mcp.cjs.map +1 -1
- package/dist/abracadabra-mcp.esm.js +1165 -190
- package/dist/abracadabra-mcp.esm.js.map +1 -1
- package/dist/index.d.ts +32 -1
- package/package.json +1 -1
- package/src/converters/page-types.ts +408 -0
- package/src/converters/types.ts +15 -11
- package/src/hook-bridge.ts +18 -8
- package/src/index.ts +29 -2
- package/src/mentions.ts +42 -0
- package/src/resources/agent-guide.ts +151 -29
- package/src/server.ts +139 -14
- package/src/tools/awareness.ts +3 -0
- package/src/tools/channel.ts +18 -8
- package/src/tools/content.ts +0 -5
- package/src/tools/files.ts +8 -0
- package/src/tools/meta.ts +1 -7
- package/src/tools/svg.ts +0 -3
- package/src/tools/tree.ts +28 -22
|
@@ -3757,7 +3757,7 @@ const propertyKeyTypes = new Set([
|
|
|
3757
3757
|
"number",
|
|
3758
3758
|
"symbol"
|
|
3759
3759
|
]);
|
|
3760
|
-
function escapeRegex(str) {
|
|
3760
|
+
function escapeRegex$1(str) {
|
|
3761
3761
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3762
3762
|
}
|
|
3763
3763
|
function clone(inst, def, params) {
|
|
@@ -4468,7 +4468,7 @@ const $ZodCheckUpperCase = /* @__PURE__ */ $constructor("$ZodCheckUpperCase", (i
|
|
|
4468
4468
|
});
|
|
4469
4469
|
const $ZodCheckIncludes = /* @__PURE__ */ $constructor("$ZodCheckIncludes", (inst, def) => {
|
|
4470
4470
|
$ZodCheck.init(inst, def);
|
|
4471
|
-
const escapedRegex = escapeRegex(def.includes);
|
|
4471
|
+
const escapedRegex = escapeRegex$1(def.includes);
|
|
4472
4472
|
const pattern = new RegExp(typeof def.position === "number" ? `^.{${def.position}}${escapedRegex}` : escapedRegex);
|
|
4473
4473
|
def.pattern = pattern;
|
|
4474
4474
|
inst._zod.onattach.push((inst) => {
|
|
@@ -4491,7 +4491,7 @@ const $ZodCheckIncludes = /* @__PURE__ */ $constructor("$ZodCheckIncludes", (ins
|
|
|
4491
4491
|
});
|
|
4492
4492
|
const $ZodCheckStartsWith = /* @__PURE__ */ $constructor("$ZodCheckStartsWith", (inst, def) => {
|
|
4493
4493
|
$ZodCheck.init(inst, def);
|
|
4494
|
-
const pattern = new RegExp(`^${escapeRegex(def.prefix)}.*`);
|
|
4494
|
+
const pattern = new RegExp(`^${escapeRegex$1(def.prefix)}.*`);
|
|
4495
4495
|
def.pattern ?? (def.pattern = pattern);
|
|
4496
4496
|
inst._zod.onattach.push((inst) => {
|
|
4497
4497
|
const bag = inst._zod.bag;
|
|
@@ -4513,7 +4513,7 @@ const $ZodCheckStartsWith = /* @__PURE__ */ $constructor("$ZodCheckStartsWith",
|
|
|
4513
4513
|
});
|
|
4514
4514
|
const $ZodCheckEndsWith = /* @__PURE__ */ $constructor("$ZodCheckEndsWith", (inst, def) => {
|
|
4515
4515
|
$ZodCheck.init(inst, def);
|
|
4516
|
-
const pattern = new RegExp(`.*${escapeRegex(def.suffix)}$`);
|
|
4516
|
+
const pattern = new RegExp(`.*${escapeRegex$1(def.suffix)}$`);
|
|
4517
4517
|
def.pattern ?? (def.pattern = pattern);
|
|
4518
4518
|
inst._zod.onattach.push((inst) => {
|
|
4519
4519
|
const bag = inst._zod.bag;
|
|
@@ -5545,7 +5545,7 @@ const $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
|
|
|
5545
5545
|
const values = getEnumValues(def.entries);
|
|
5546
5546
|
const valuesSet = new Set(values);
|
|
5547
5547
|
inst._zod.values = valuesSet;
|
|
5548
|
-
inst._zod.pattern = new RegExp(`^(${values.filter((k) => propertyKeyTypes.has(typeof k)).map((o) => typeof o === "string" ? escapeRegex(o) : o.toString()).join("|")})$`);
|
|
5548
|
+
inst._zod.pattern = new RegExp(`^(${values.filter((k) => propertyKeyTypes.has(typeof k)).map((o) => typeof o === "string" ? escapeRegex$1(o) : o.toString()).join("|")})$`);
|
|
5549
5549
|
inst._zod.parse = (payload, _ctx) => {
|
|
5550
5550
|
const input = payload.value;
|
|
5551
5551
|
if (valuesSet.has(input)) return payload;
|
|
@@ -5563,7 +5563,7 @@ const $ZodLiteral = /* @__PURE__ */ $constructor("$ZodLiteral", (inst, def) => {
|
|
|
5563
5563
|
if (def.values.length === 0) throw new Error("Cannot create literal schema with no valid values");
|
|
5564
5564
|
const values = new Set(def.values);
|
|
5565
5565
|
inst._zod.values = values;
|
|
5566
|
-
inst._zod.pattern = new RegExp(`^(${def.values.map((o) => typeof o === "string" ? escapeRegex(o) : o ? escapeRegex(o.toString()) : String(o)).join("|")})$`);
|
|
5566
|
+
inst._zod.pattern = new RegExp(`^(${def.values.map((o) => typeof o === "string" ? escapeRegex$1(o) : o ? escapeRegex$1(o.toString()) : String(o)).join("|")})$`);
|
|
5567
5567
|
inst._zod.parse = (payload, _ctx) => {
|
|
5568
5568
|
const input = payload.value;
|
|
5569
5569
|
if (values.has(input)) return payload;
|
|
@@ -19965,6 +19965,47 @@ function signChallenge(challengeB64, privateKey) {
|
|
|
19965
19965
|
return toBase64url(sign(challenge, privateKey));
|
|
19966
19966
|
}
|
|
19967
19967
|
|
|
19968
|
+
//#endregion
|
|
19969
|
+
//#region packages/mcp/src/mentions.ts
|
|
19970
|
+
/**
|
|
19971
|
+
* Mention parsing for chat messages.
|
|
19972
|
+
*
|
|
19973
|
+
* Recognizes `@alias` tokens (case-insensitive, word-boundary) so the agent
|
|
19974
|
+
* can decide whether a group-chat message is directed at it.
|
|
19975
|
+
*/
|
|
19976
|
+
/** Escape regex metacharacters in an alias string. */
|
|
19977
|
+
function escapeRegex(s) {
|
|
19978
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
19979
|
+
}
|
|
19980
|
+
/**
|
|
19981
|
+
* Build a regex that matches `@<alias>` for any of the given aliases.
|
|
19982
|
+
* Requires a non-word char (or start) before `@` and a word boundary after the alias
|
|
19983
|
+
* so `@Claude` matches but `email@claudesomething` does not.
|
|
19984
|
+
*/
|
|
19985
|
+
function buildMentionRegex(aliases) {
|
|
19986
|
+
const cleaned = aliases.map((a) => a.trim()).filter((a) => a.length > 0);
|
|
19987
|
+
if (cleaned.length === 0) return null;
|
|
19988
|
+
const alt = cleaned.map(escapeRegex).join("|");
|
|
19989
|
+
return new RegExp(`(?:^|[^\\w@])@(?:${alt})\\b`, "i");
|
|
19990
|
+
}
|
|
19991
|
+
/** Returns true if `text` contains `@alias` for any alias (case-insensitive). */
|
|
19992
|
+
function containsMention(text, aliases) {
|
|
19993
|
+
const re = buildMentionRegex(aliases);
|
|
19994
|
+
if (!re) return false;
|
|
19995
|
+
return re.test(text);
|
|
19996
|
+
}
|
|
19997
|
+
/**
|
|
19998
|
+
* Remove `@alias` tokens from the text. Leaves surrounding whitespace tidy so
|
|
19999
|
+
* the cleaned prompt reads naturally (e.g. `"@Claude help"` → `"help"`).
|
|
20000
|
+
*/
|
|
20001
|
+
function stripMention(text, aliases) {
|
|
20002
|
+
const cleaned = aliases.map((a) => a.trim()).filter((a) => a.length > 0);
|
|
20003
|
+
if (cleaned.length === 0) return text;
|
|
20004
|
+
const alt = cleaned.map(escapeRegex).join("|");
|
|
20005
|
+
const re = new RegExp(`(^|\\s)@(?:${alt})\\b[,:]?\\s*`, "gi");
|
|
20006
|
+
return text.replace(re, (_m, lead) => lead ? " " : "").replace(/\s{2,}/g, " ").trim();
|
|
20007
|
+
}
|
|
20008
|
+
|
|
19968
20009
|
//#endregion
|
|
19969
20010
|
//#region packages/mcp/src/server.ts
|
|
19970
20011
|
/**
|
|
@@ -19975,7 +20016,10 @@ function signChallenge(challengeB64, privateKey) {
|
|
|
19975
20016
|
* Use switchSpace(docId) to change the active space.
|
|
19976
20017
|
*/
|
|
19977
20018
|
const IDLE_TIMEOUT_MS = 300 * 1e3;
|
|
19978
|
-
var AbracadabraMCPServer = class {
|
|
20019
|
+
var AbracadabraMCPServer = class AbracadabraMCPServer {
|
|
20020
|
+
static {
|
|
20021
|
+
this.TOOL_HISTORY_MAX = 20;
|
|
20022
|
+
}
|
|
19979
20023
|
constructor(config) {
|
|
19980
20024
|
this._serverInfo = null;
|
|
19981
20025
|
this._rootDocId = null;
|
|
@@ -19992,6 +20036,7 @@ var AbracadabraMCPServer = class {
|
|
|
19992
20036
|
this._typingInterval = null;
|
|
19993
20037
|
this._lastChatChannel = null;
|
|
19994
20038
|
this._signFn = null;
|
|
20039
|
+
this._toolHistory = [];
|
|
19995
20040
|
this.config = config;
|
|
19996
20041
|
this.client = new AbracadabraClient({
|
|
19997
20042
|
url: config.url,
|
|
@@ -20004,6 +20049,14 @@ var AbracadabraMCPServer = class {
|
|
|
20004
20049
|
get agentColor() {
|
|
20005
20050
|
return this.config.agentColor || "hsl(270, 80%, 60%)";
|
|
20006
20051
|
}
|
|
20052
|
+
get triggerMode() {
|
|
20053
|
+
return this.config.triggerMode ?? "mention+task";
|
|
20054
|
+
}
|
|
20055
|
+
get mentionAliases() {
|
|
20056
|
+
const explicit = this.config.mentionAliases?.filter((a) => a.trim().length > 0);
|
|
20057
|
+
if (explicit && explicit.length > 0) return explicit;
|
|
20058
|
+
return [this.agentName];
|
|
20059
|
+
}
|
|
20007
20060
|
get serverInfo() {
|
|
20008
20061
|
return this._serverInfo;
|
|
20009
20062
|
}
|
|
@@ -20044,7 +20097,7 @@ var AbracadabraMCPServer = class {
|
|
|
20044
20097
|
await this.client.loginWithKey(keypair.publicKeyB64, signFn);
|
|
20045
20098
|
} else throw err;
|
|
20046
20099
|
}
|
|
20047
|
-
console.error(`[abracadabra-mcp] Authenticated as ${this.agentName} (
|
|
20100
|
+
console.error(`[abracadabra-mcp] Authenticated as ${this.agentName} (pubkey=${keypair.publicKeyB64})`);
|
|
20048
20101
|
this._serverInfo = await this.client.serverInfo();
|
|
20049
20102
|
let initialDocId = this._serverInfo.index_doc_id ?? null;
|
|
20050
20103
|
try {
|
|
@@ -20111,6 +20164,8 @@ var AbracadabraMCPServer = class {
|
|
|
20111
20164
|
provider.awareness.setLocalStateField("status", null);
|
|
20112
20165
|
provider.awareness.setLocalStateField("activeToolCall", null);
|
|
20113
20166
|
provider.awareness.setLocalStateField("statusContext", null);
|
|
20167
|
+
provider.awareness.setLocalStateField("turnId", null);
|
|
20168
|
+
provider.awareness.setLocalStateField("toolHistory", []);
|
|
20114
20169
|
const conn = {
|
|
20115
20170
|
doc,
|
|
20116
20171
|
provider,
|
|
@@ -20145,6 +20200,17 @@ var AbracadabraMCPServer = class {
|
|
|
20145
20200
|
getTrashMap() {
|
|
20146
20201
|
return this._activeConnection?.doc.getMap("doc-trash") ?? null;
|
|
20147
20202
|
}
|
|
20203
|
+
/** Get plugin names enabled in the active space via space-plugins Y.Map. */
|
|
20204
|
+
getEnabledPluginNames() {
|
|
20205
|
+
const doc = this._activeConnection?.doc;
|
|
20206
|
+
if (!doc) return [];
|
|
20207
|
+
const pluginsMap = doc.getMap("space-plugins");
|
|
20208
|
+
const names = [];
|
|
20209
|
+
pluginsMap.forEach((value, key) => {
|
|
20210
|
+
if ((value?.toJSON ? value.toJSON() : value)?.enabled) names.push(key);
|
|
20211
|
+
});
|
|
20212
|
+
return names;
|
|
20213
|
+
}
|
|
20148
20214
|
/**
|
|
20149
20215
|
* Get or create a child provider for a given document ID.
|
|
20150
20216
|
* Caches providers and waits for sync before returning.
|
|
@@ -20223,6 +20289,7 @@ var AbracadabraMCPServer = class {
|
|
|
20223
20289
|
_observeRootAwareness(provider) {
|
|
20224
20290
|
const selfId = provider.awareness.clientID;
|
|
20225
20291
|
provider.awareness.on("change", () => {
|
|
20292
|
+
if (this.triggerMode === "mention") return;
|
|
20226
20293
|
const states = provider.awareness.getStates();
|
|
20227
20294
|
for (const [clientId, state] of states) {
|
|
20228
20295
|
if (clientId === selfId) continue;
|
|
@@ -20235,6 +20302,7 @@ var AbracadabraMCPServer = class {
|
|
|
20235
20302
|
const user = state["user"];
|
|
20236
20303
|
const senderName = user && typeof user === "object" && typeof user.name === "string" ? user.name : "Unknown";
|
|
20237
20304
|
console.error(`[abracadabra-mcp] Handling ai:task id=${id} from ${senderName}: ${text.slice(0, 80)}`);
|
|
20305
|
+
this._beginTurn();
|
|
20238
20306
|
this.setAutoStatus("thinking");
|
|
20239
20307
|
this._dispatchAiTask({
|
|
20240
20308
|
id,
|
|
@@ -20297,9 +20365,28 @@ var AbracadabraMCPServer = class {
|
|
|
20297
20365
|
if (data.sender_id && data.sender_id === this._userId) return;
|
|
20298
20366
|
const channel = data.channel;
|
|
20299
20367
|
const docId = channel?.startsWith("group:") ? channel.slice(6) : "";
|
|
20300
|
-
|
|
20368
|
+
const isDM = channel?.startsWith("dm:") ?? false;
|
|
20369
|
+
const isGroup = channel?.startsWith("group:") ?? false;
|
|
20370
|
+
if (isDM) {
|
|
20301
20371
|
const parts = channel.split(":");
|
|
20302
|
-
if (parts.length === 3 && parts[1] !== this._userId && parts[2] !== this._userId)
|
|
20372
|
+
if (parts.length === 3 && parts[1] !== this._userId && parts[2] !== this._userId) {
|
|
20373
|
+
console.error(`[abracadabra-mcp] Dropping DM: agent _userId=${this._userId} not in channel parts=[${parts[1]}, ${parts[2]}] — channel='${channel}'. The dashboard's awareness likely points at a stale Claude identity.`);
|
|
20374
|
+
return;
|
|
20375
|
+
}
|
|
20376
|
+
}
|
|
20377
|
+
const mode = this.triggerMode;
|
|
20378
|
+
const content = typeof data.content === "string" ? data.content : "";
|
|
20379
|
+
let dispatchContent = content;
|
|
20380
|
+
if (isGroup) {
|
|
20381
|
+
if (mode === "task") return;
|
|
20382
|
+
if (mode === "mention" || mode === "mention+task") {
|
|
20383
|
+
const aliases = this.mentionAliases;
|
|
20384
|
+
if (!containsMention(content, aliases)) {
|
|
20385
|
+
console.error(`[abracadabra-mcp] skipped message on ${channel} — no @mention for ${aliases.join("|")}`);
|
|
20386
|
+
return;
|
|
20387
|
+
}
|
|
20388
|
+
dispatchContent = stripMention(content, aliases) || content;
|
|
20389
|
+
}
|
|
20303
20390
|
}
|
|
20304
20391
|
if (channel) {
|
|
20305
20392
|
const rootProvider = this._activeConnection?.provider;
|
|
@@ -20309,14 +20396,13 @@ var AbracadabraMCPServer = class {
|
|
|
20309
20396
|
timestamp: Math.floor(Date.now() / 1e3)
|
|
20310
20397
|
}));
|
|
20311
20398
|
this._lastChatChannel = channel;
|
|
20312
|
-
this.sendTypingIndicator(channel);
|
|
20313
|
-
this._startTypingInterval(channel);
|
|
20314
20399
|
}
|
|
20400
|
+
this._beginTurn();
|
|
20315
20401
|
this.setAutoStatus("thinking");
|
|
20316
20402
|
await this._serverRef.notification({
|
|
20317
20403
|
method: "notifications/claude/channel",
|
|
20318
20404
|
params: {
|
|
20319
|
-
content:
|
|
20405
|
+
content: dispatchContent,
|
|
20320
20406
|
instructions: `You MUST use send_chat_message with channel="${channel ?? ""}" for ALL responses — both progress updates and final answers. The user CANNOT see plain text output; they only see messages sent via send_chat_message. When doing multi-step work, send brief status updates via send_chat_message (e.g. "Looking into that..." or "Found it, writing up results...") so the user knows you're working. Never output plain text as a substitute for send_chat_message.`,
|
|
20321
20407
|
meta: {
|
|
20322
20408
|
source: "abracadabra",
|
|
@@ -20347,13 +20433,35 @@ var AbracadabraMCPServer = class {
|
|
|
20347
20433
|
if (docId !== void 0) provider.awareness.setLocalStateField("docId", docId);
|
|
20348
20434
|
const context = status ? statusContext !== void 0 ? statusContext : this._lastChatChannel : null;
|
|
20349
20435
|
provider.awareness.setLocalStateField("statusContext", context ?? null);
|
|
20350
|
-
if (!status)
|
|
20436
|
+
if (!status) {
|
|
20437
|
+
this._stopTypingInterval();
|
|
20438
|
+
provider.awareness.setLocalStateField("activeToolCall", null);
|
|
20439
|
+
provider.awareness.setLocalStateField("turnId", null);
|
|
20440
|
+
this._toolHistory = [];
|
|
20441
|
+
provider.awareness.setLocalStateField("toolHistory", []);
|
|
20442
|
+
}
|
|
20351
20443
|
if (status) this._statusClearTimer = setTimeout(() => {
|
|
20352
20444
|
provider.awareness.setLocalStateField("status", null);
|
|
20353
20445
|
provider.awareness.setLocalStateField("activeToolCall", null);
|
|
20354
20446
|
provider.awareness.setLocalStateField("statusContext", null);
|
|
20447
|
+
provider.awareness.setLocalStateField("turnId", null);
|
|
20448
|
+
this._toolHistory = [];
|
|
20449
|
+
provider.awareness.setLocalStateField("toolHistory", []);
|
|
20355
20450
|
this._stopTypingInterval();
|
|
20356
|
-
},
|
|
20451
|
+
}, 1e4);
|
|
20452
|
+
}
|
|
20453
|
+
/**
|
|
20454
|
+
* Start a new agent turn. Mints a fresh UUID and writes it to awareness so
|
|
20455
|
+
* the dashboard can gate the incantation on "there is an active turn",
|
|
20456
|
+
* decoupled from the (racier) status field. Called from chat arrival and
|
|
20457
|
+
* ai:task dispatch right before `setAutoStatus('thinking')`.
|
|
20458
|
+
*/
|
|
20459
|
+
_beginTurn() {
|
|
20460
|
+
const provider = this._activeConnection?.provider;
|
|
20461
|
+
if (!provider) return;
|
|
20462
|
+
this._toolHistory = [];
|
|
20463
|
+
provider.awareness.setLocalStateField("toolHistory", []);
|
|
20464
|
+
provider.awareness.setLocalStateField("turnId", crypto.randomUUID());
|
|
20357
20465
|
}
|
|
20358
20466
|
/** Re-send typing indicator every 2s so dashboard keeps showing it (expires at 3s). */
|
|
20359
20467
|
_startTypingInterval(channel) {
|
|
@@ -20371,10 +20479,28 @@ var AbracadabraMCPServer = class {
|
|
|
20371
20479
|
}
|
|
20372
20480
|
/**
|
|
20373
20481
|
* Broadcast which tool the agent is currently executing.
|
|
20374
|
-
*
|
|
20482
|
+
*
|
|
20483
|
+
* Renders as a ChatTool pill on the dashboard. On non-null calls, the tool
|
|
20484
|
+
* is also appended to `toolHistory` (capped at TOOL_HISTORY_MAX) and written
|
|
20485
|
+
* to awareness so the dashboard's inline trace can show the turn's recent
|
|
20486
|
+
* activity. Tools do NOT clear (`setActiveToolCall(null)`) on completion —
|
|
20487
|
+
* the pill stays until the next tool replaces it or `setAutoStatus(null)`
|
|
20488
|
+
* flushes the turn. This keeps pills visible long enough to see.
|
|
20375
20489
|
*/
|
|
20376
20490
|
setActiveToolCall(toolCall) {
|
|
20377
|
-
this._activeConnection?.provider
|
|
20491
|
+
const provider = this._activeConnection?.provider;
|
|
20492
|
+
if (!provider) return;
|
|
20493
|
+
provider.awareness.setLocalStateField("activeToolCall", toolCall);
|
|
20494
|
+
if (toolCall) {
|
|
20495
|
+
this._toolHistory.push({
|
|
20496
|
+
tool: toolCall.name,
|
|
20497
|
+
target: toolCall.target,
|
|
20498
|
+
ts: Date.now(),
|
|
20499
|
+
channel: this._lastChatChannel
|
|
20500
|
+
});
|
|
20501
|
+
if (this._toolHistory.length > AbracadabraMCPServer.TOOL_HISTORY_MAX) this._toolHistory.splice(0, this._toolHistory.length - AbracadabraMCPServer.TOOL_HISTORY_MAX);
|
|
20502
|
+
provider.awareness.setLocalStateField("toolHistory", [...this._toolHistory]);
|
|
20503
|
+
}
|
|
20378
20504
|
}
|
|
20379
20505
|
/**
|
|
20380
20506
|
* Send a typing indicator to a chat channel.
|
|
@@ -20405,8 +20531,11 @@ var AbracadabraMCPServer = class {
|
|
|
20405
20531
|
conn.provider.awareness.setLocalStateField("status", null);
|
|
20406
20532
|
conn.provider.awareness.setLocalStateField("activeToolCall", null);
|
|
20407
20533
|
conn.provider.awareness.setLocalStateField("statusContext", null);
|
|
20534
|
+
conn.provider.awareness.setLocalStateField("turnId", null);
|
|
20535
|
+
conn.provider.awareness.setLocalStateField("toolHistory", []);
|
|
20408
20536
|
conn.provider.destroy();
|
|
20409
20537
|
}
|
|
20538
|
+
this._toolHistory = [];
|
|
20410
20539
|
this._spaceConnections.clear();
|
|
20411
20540
|
this._activeConnection = null;
|
|
20412
20541
|
console.error("[abracadabra-mcp] Shutdown complete");
|
|
@@ -20431,6 +20560,724 @@ function docToSpaceMeta(doc) {
|
|
|
20431
20560
|
};
|
|
20432
20561
|
}
|
|
20433
20562
|
|
|
20563
|
+
//#endregion
|
|
20564
|
+
//#region packages/mcp/src/converters/page-types.ts
|
|
20565
|
+
const PAGE_TYPES = {
|
|
20566
|
+
doc: {
|
|
20567
|
+
key: "doc",
|
|
20568
|
+
label: "Document",
|
|
20569
|
+
icon: "file-text",
|
|
20570
|
+
description: "Rich text document with real-time collaboration",
|
|
20571
|
+
core: true,
|
|
20572
|
+
supportsChildren: true
|
|
20573
|
+
},
|
|
20574
|
+
kanban: {
|
|
20575
|
+
key: "kanban",
|
|
20576
|
+
label: "Kanban",
|
|
20577
|
+
icon: "kanban",
|
|
20578
|
+
description: "Drag-and-drop task board with columns and cards",
|
|
20579
|
+
core: true,
|
|
20580
|
+
supportsChildren: true,
|
|
20581
|
+
childLabel: "Column",
|
|
20582
|
+
grandchildLabel: "Card",
|
|
20583
|
+
defaultMetaFields: [{
|
|
20584
|
+
type: "select",
|
|
20585
|
+
key: "kanbanColumnWidth",
|
|
20586
|
+
options: [
|
|
20587
|
+
"narrow",
|
|
20588
|
+
"default",
|
|
20589
|
+
"wide"
|
|
20590
|
+
],
|
|
20591
|
+
label: "Column Width"
|
|
20592
|
+
}]
|
|
20593
|
+
},
|
|
20594
|
+
gallery: {
|
|
20595
|
+
key: "gallery",
|
|
20596
|
+
label: "Gallery",
|
|
20597
|
+
icon: "images",
|
|
20598
|
+
description: "Visual grid of items with rich content",
|
|
20599
|
+
core: true,
|
|
20600
|
+
supportsChildren: true,
|
|
20601
|
+
childLabel: "Item",
|
|
20602
|
+
metaSchema: [
|
|
20603
|
+
{
|
|
20604
|
+
type: "location",
|
|
20605
|
+
latKey: "geoLat",
|
|
20606
|
+
lngKey: "geoLng",
|
|
20607
|
+
label: "Location"
|
|
20608
|
+
},
|
|
20609
|
+
{
|
|
20610
|
+
type: "datetime",
|
|
20611
|
+
key: "datetimeStart",
|
|
20612
|
+
label: "Date"
|
|
20613
|
+
},
|
|
20614
|
+
{
|
|
20615
|
+
type: "tags",
|
|
20616
|
+
key: "tags",
|
|
20617
|
+
label: "Tags"
|
|
20618
|
+
},
|
|
20619
|
+
{
|
|
20620
|
+
type: "rating",
|
|
20621
|
+
key: "rating",
|
|
20622
|
+
max: 5,
|
|
20623
|
+
label: "Rating"
|
|
20624
|
+
},
|
|
20625
|
+
{
|
|
20626
|
+
type: "icon",
|
|
20627
|
+
key: "icon",
|
|
20628
|
+
label: "Icon"
|
|
20629
|
+
},
|
|
20630
|
+
{
|
|
20631
|
+
type: "colorPreset",
|
|
20632
|
+
key: "color",
|
|
20633
|
+
presets: [
|
|
20634
|
+
"#6366f1",
|
|
20635
|
+
"#ec4899",
|
|
20636
|
+
"#f97316",
|
|
20637
|
+
"#22c55e",
|
|
20638
|
+
"#3b82f6",
|
|
20639
|
+
"#a855f7"
|
|
20640
|
+
],
|
|
20641
|
+
label: "Color"
|
|
20642
|
+
}
|
|
20643
|
+
],
|
|
20644
|
+
defaultMetaFields: [
|
|
20645
|
+
{
|
|
20646
|
+
type: "number",
|
|
20647
|
+
key: "galleryColumns",
|
|
20648
|
+
min: 1,
|
|
20649
|
+
max: 6,
|
|
20650
|
+
step: 1,
|
|
20651
|
+
label: "Columns"
|
|
20652
|
+
},
|
|
20653
|
+
{
|
|
20654
|
+
type: "select",
|
|
20655
|
+
key: "galleryAspect",
|
|
20656
|
+
options: [
|
|
20657
|
+
"square",
|
|
20658
|
+
"4:3",
|
|
20659
|
+
"3:2",
|
|
20660
|
+
"16:9",
|
|
20661
|
+
"free"
|
|
20662
|
+
],
|
|
20663
|
+
label: "Aspect Ratio"
|
|
20664
|
+
},
|
|
20665
|
+
{
|
|
20666
|
+
type: "select",
|
|
20667
|
+
key: "galleryCardStyle",
|
|
20668
|
+
options: [
|
|
20669
|
+
"default",
|
|
20670
|
+
"compact",
|
|
20671
|
+
"detailed"
|
|
20672
|
+
],
|
|
20673
|
+
label: "Card Style"
|
|
20674
|
+
},
|
|
20675
|
+
{
|
|
20676
|
+
type: "toggle",
|
|
20677
|
+
key: "galleryShowLabels",
|
|
20678
|
+
label: "Show Labels"
|
|
20679
|
+
},
|
|
20680
|
+
{
|
|
20681
|
+
type: "select",
|
|
20682
|
+
key: "gallerySortBy",
|
|
20683
|
+
options: [
|
|
20684
|
+
"manual",
|
|
20685
|
+
"date",
|
|
20686
|
+
"name",
|
|
20687
|
+
"rating"
|
|
20688
|
+
],
|
|
20689
|
+
label: "Sort"
|
|
20690
|
+
}
|
|
20691
|
+
]
|
|
20692
|
+
},
|
|
20693
|
+
table: {
|
|
20694
|
+
key: "table",
|
|
20695
|
+
label: "Table",
|
|
20696
|
+
icon: "table",
|
|
20697
|
+
description: "Collaborative spreadsheet with custom fields",
|
|
20698
|
+
core: true,
|
|
20699
|
+
supportsChildren: true,
|
|
20700
|
+
childLabel: "Column",
|
|
20701
|
+
grandchildLabel: "Row",
|
|
20702
|
+
defaultMetaFields: [{
|
|
20703
|
+
type: "select",
|
|
20704
|
+
key: "tableMode",
|
|
20705
|
+
options: ["hierarchy", "flat"],
|
|
20706
|
+
label: "Mode"
|
|
20707
|
+
}, {
|
|
20708
|
+
type: "select",
|
|
20709
|
+
key: "tableSortDir",
|
|
20710
|
+
options: ["asc", "desc"],
|
|
20711
|
+
label: "Sort Direction"
|
|
20712
|
+
}]
|
|
20713
|
+
},
|
|
20714
|
+
outline: {
|
|
20715
|
+
key: "outline",
|
|
20716
|
+
label: "Outline",
|
|
20717
|
+
icon: "list-tree",
|
|
20718
|
+
description: "Hierarchical outline with keyboard navigation",
|
|
20719
|
+
core: true,
|
|
20720
|
+
supportsChildren: true,
|
|
20721
|
+
childLabel: "Item",
|
|
20722
|
+
defaultDepth: -1
|
|
20723
|
+
},
|
|
20724
|
+
checklist: {
|
|
20725
|
+
key: "checklist",
|
|
20726
|
+
label: "Checklist",
|
|
20727
|
+
icon: "check-square",
|
|
20728
|
+
description: "Collaborative checklist with sub-tasks, drag-and-drop, and due dates",
|
|
20729
|
+
core: true,
|
|
20730
|
+
supportsChildren: true,
|
|
20731
|
+
childLabel: "Task",
|
|
20732
|
+
defaultDepth: -1,
|
|
20733
|
+
metaSchema: [
|
|
20734
|
+
{
|
|
20735
|
+
type: "toggle",
|
|
20736
|
+
key: "checked",
|
|
20737
|
+
label: "Done"
|
|
20738
|
+
},
|
|
20739
|
+
{
|
|
20740
|
+
type: "select",
|
|
20741
|
+
key: "priority",
|
|
20742
|
+
options: [
|
|
20743
|
+
"none",
|
|
20744
|
+
"low",
|
|
20745
|
+
"medium",
|
|
20746
|
+
"high"
|
|
20747
|
+
],
|
|
20748
|
+
label: "Priority"
|
|
20749
|
+
},
|
|
20750
|
+
{
|
|
20751
|
+
type: "date",
|
|
20752
|
+
key: "dateEnd",
|
|
20753
|
+
label: "Due date"
|
|
20754
|
+
}
|
|
20755
|
+
],
|
|
20756
|
+
defaultMetaFields: [{
|
|
20757
|
+
type: "select",
|
|
20758
|
+
key: "checklistFilter",
|
|
20759
|
+
options: [
|
|
20760
|
+
"all",
|
|
20761
|
+
"active",
|
|
20762
|
+
"completed"
|
|
20763
|
+
],
|
|
20764
|
+
label: "Filter"
|
|
20765
|
+
}, {
|
|
20766
|
+
type: "select",
|
|
20767
|
+
key: "checklistSort",
|
|
20768
|
+
options: [
|
|
20769
|
+
"manual",
|
|
20770
|
+
"priority",
|
|
20771
|
+
"due"
|
|
20772
|
+
],
|
|
20773
|
+
label: "Sort"
|
|
20774
|
+
}]
|
|
20775
|
+
},
|
|
20776
|
+
graph: {
|
|
20777
|
+
key: "graph",
|
|
20778
|
+
label: "Graph",
|
|
20779
|
+
icon: "git-fork",
|
|
20780
|
+
description: "Force-directed knowledge graph — full document tree as nodes & edges",
|
|
20781
|
+
core: true,
|
|
20782
|
+
supportsChildren: true,
|
|
20783
|
+
childLabel: "Node",
|
|
20784
|
+
defaultMetaFields: [{
|
|
20785
|
+
type: "toggle",
|
|
20786
|
+
key: "showRefEdges",
|
|
20787
|
+
label: "Show Ref Edges",
|
|
20788
|
+
default: true
|
|
20789
|
+
}]
|
|
20790
|
+
},
|
|
20791
|
+
timeline: {
|
|
20792
|
+
key: "timeline",
|
|
20793
|
+
label: "Timeline",
|
|
20794
|
+
icon: "gantt-chart",
|
|
20795
|
+
description: "Gantt-style project timeline with epics and tasks",
|
|
20796
|
+
core: true,
|
|
20797
|
+
supportsChildren: true,
|
|
20798
|
+
childLabel: "Epic",
|
|
20799
|
+
grandchildLabel: "Task",
|
|
20800
|
+
metaSchema: [
|
|
20801
|
+
{
|
|
20802
|
+
type: "daterange",
|
|
20803
|
+
startKey: "dateStart",
|
|
20804
|
+
endKey: "dateEnd"
|
|
20805
|
+
},
|
|
20806
|
+
{
|
|
20807
|
+
type: "slider",
|
|
20808
|
+
key: "taskProgress",
|
|
20809
|
+
min: 0,
|
|
20810
|
+
max: 100,
|
|
20811
|
+
label: "Progress"
|
|
20812
|
+
},
|
|
20813
|
+
{
|
|
20814
|
+
type: "colorPreset",
|
|
20815
|
+
key: "color",
|
|
20816
|
+
presets: [
|
|
20817
|
+
"#6366f1",
|
|
20818
|
+
"#818cf8",
|
|
20819
|
+
"#f97316",
|
|
20820
|
+
"#22c55e",
|
|
20821
|
+
"#3b82f6",
|
|
20822
|
+
"#a855f7"
|
|
20823
|
+
],
|
|
20824
|
+
label: "Color"
|
|
20825
|
+
}
|
|
20826
|
+
]
|
|
20827
|
+
},
|
|
20828
|
+
calendar: {
|
|
20829
|
+
key: "calendar",
|
|
20830
|
+
label: "Calendar",
|
|
20831
|
+
icon: "calendar",
|
|
20832
|
+
description: "Event calendar with month, week, and day views",
|
|
20833
|
+
core: true,
|
|
20834
|
+
supportsChildren: true,
|
|
20835
|
+
childLabel: "Event",
|
|
20836
|
+
metaSchema: [
|
|
20837
|
+
{
|
|
20838
|
+
type: "datetimerange",
|
|
20839
|
+
startKey: "datetimeStart",
|
|
20840
|
+
endKey: "datetimeEnd",
|
|
20841
|
+
allDayKey: "allDay"
|
|
20842
|
+
},
|
|
20843
|
+
{
|
|
20844
|
+
type: "colorPreset",
|
|
20845
|
+
key: "color",
|
|
20846
|
+
presets: [
|
|
20847
|
+
"#6366f1",
|
|
20848
|
+
"#ec4899",
|
|
20849
|
+
"#f97316",
|
|
20850
|
+
"#22c55e",
|
|
20851
|
+
"#3b82f6",
|
|
20852
|
+
"#a855f7"
|
|
20853
|
+
],
|
|
20854
|
+
label: "Color"
|
|
20855
|
+
},
|
|
20856
|
+
{
|
|
20857
|
+
type: "icon",
|
|
20858
|
+
key: "icon",
|
|
20859
|
+
label: "Icon"
|
|
20860
|
+
}
|
|
20861
|
+
],
|
|
20862
|
+
defaultMetaFields: [
|
|
20863
|
+
{
|
|
20864
|
+
type: "select",
|
|
20865
|
+
key: "calendarWeekStart",
|
|
20866
|
+
options: ["sun", "mon"],
|
|
20867
|
+
label: "Week Starts"
|
|
20868
|
+
},
|
|
20869
|
+
{
|
|
20870
|
+
type: "select",
|
|
20871
|
+
key: "calendarView",
|
|
20872
|
+
options: [
|
|
20873
|
+
"month",
|
|
20874
|
+
"week",
|
|
20875
|
+
"day"
|
|
20876
|
+
],
|
|
20877
|
+
label: "Default View"
|
|
20878
|
+
},
|
|
20879
|
+
{
|
|
20880
|
+
type: "toggle",
|
|
20881
|
+
key: "calendarShowWeekNumbers",
|
|
20882
|
+
label: "Show Week Numbers"
|
|
20883
|
+
}
|
|
20884
|
+
]
|
|
20885
|
+
},
|
|
20886
|
+
map: {
|
|
20887
|
+
key: "map",
|
|
20888
|
+
label: "Map",
|
|
20889
|
+
icon: "map",
|
|
20890
|
+
description: "Collaborative world map with shared markers",
|
|
20891
|
+
core: true,
|
|
20892
|
+
supportsChildren: true,
|
|
20893
|
+
childLabel: "Location",
|
|
20894
|
+
defaultMetaFields: [{
|
|
20895
|
+
type: "toggle",
|
|
20896
|
+
key: "mapShowLabels",
|
|
20897
|
+
label: "Show Labels",
|
|
20898
|
+
default: true
|
|
20899
|
+
}]
|
|
20900
|
+
},
|
|
20901
|
+
dashboard: {
|
|
20902
|
+
key: "dashboard",
|
|
20903
|
+
label: "Dashboard",
|
|
20904
|
+
icon: "layout-dashboard",
|
|
20905
|
+
description: "Arrange documents as draggable icons with optional widget views",
|
|
20906
|
+
core: true,
|
|
20907
|
+
supportsChildren: true,
|
|
20908
|
+
childLabel: "Item"
|
|
20909
|
+
},
|
|
20910
|
+
call: {
|
|
20911
|
+
key: "call",
|
|
20912
|
+
label: "Call",
|
|
20913
|
+
icon: "phone",
|
|
20914
|
+
description: "Video call room with live audio and screen sharing",
|
|
20915
|
+
core: true,
|
|
20916
|
+
supportsChildren: false
|
|
20917
|
+
},
|
|
20918
|
+
chart: {
|
|
20919
|
+
key: "chart",
|
|
20920
|
+
label: "Chart",
|
|
20921
|
+
icon: "bar-chart-3",
|
|
20922
|
+
description: "Charts — manual data points or aggregation over document trees",
|
|
20923
|
+
core: true,
|
|
20924
|
+
supportsChildren: true,
|
|
20925
|
+
childLabel: "Data Point",
|
|
20926
|
+
grandchildLabel: "Data Point",
|
|
20927
|
+
metaSchema: [
|
|
20928
|
+
{
|
|
20929
|
+
type: "number",
|
|
20930
|
+
key: "number",
|
|
20931
|
+
step: .01,
|
|
20932
|
+
label: "Value"
|
|
20933
|
+
},
|
|
20934
|
+
{
|
|
20935
|
+
type: "colorPreset",
|
|
20936
|
+
key: "color",
|
|
20937
|
+
presets: [
|
|
20938
|
+
"#6366f1",
|
|
20939
|
+
"#ec4899",
|
|
20940
|
+
"#f97316",
|
|
20941
|
+
"#22c55e",
|
|
20942
|
+
"#3b82f6",
|
|
20943
|
+
"#a855f7",
|
|
20944
|
+
"#14b8a6",
|
|
20945
|
+
"#eab308"
|
|
20946
|
+
],
|
|
20947
|
+
label: "Color"
|
|
20948
|
+
},
|
|
20949
|
+
{
|
|
20950
|
+
type: "tags",
|
|
20951
|
+
key: "tags",
|
|
20952
|
+
label: "Tags"
|
|
20953
|
+
}
|
|
20954
|
+
],
|
|
20955
|
+
defaultMetaFields: [
|
|
20956
|
+
{
|
|
20957
|
+
type: "select",
|
|
20958
|
+
key: "chartType",
|
|
20959
|
+
options: [
|
|
20960
|
+
"bar",
|
|
20961
|
+
"stacked bar",
|
|
20962
|
+
"line",
|
|
20963
|
+
"donut",
|
|
20964
|
+
"treemap"
|
|
20965
|
+
],
|
|
20966
|
+
label: "Chart Type"
|
|
20967
|
+
},
|
|
20968
|
+
{
|
|
20969
|
+
type: "select",
|
|
20970
|
+
key: "chartMetric",
|
|
20971
|
+
options: [
|
|
20972
|
+
"value",
|
|
20973
|
+
"type",
|
|
20974
|
+
"tag",
|
|
20975
|
+
"status",
|
|
20976
|
+
"priority",
|
|
20977
|
+
"activity",
|
|
20978
|
+
"completion"
|
|
20979
|
+
],
|
|
20980
|
+
label: "Metric"
|
|
20981
|
+
},
|
|
20982
|
+
{
|
|
20983
|
+
type: "select",
|
|
20984
|
+
key: "chartColorScheme",
|
|
20985
|
+
options: [
|
|
20986
|
+
"default",
|
|
20987
|
+
"warm",
|
|
20988
|
+
"cool",
|
|
20989
|
+
"mono"
|
|
20990
|
+
],
|
|
20991
|
+
label: "Colors"
|
|
20992
|
+
},
|
|
20993
|
+
{
|
|
20994
|
+
type: "number",
|
|
20995
|
+
key: "chartLimit",
|
|
20996
|
+
min: 3,
|
|
20997
|
+
max: 30,
|
|
20998
|
+
step: 1,
|
|
20999
|
+
label: "Max Items"
|
|
21000
|
+
},
|
|
21001
|
+
{
|
|
21002
|
+
type: "toggle",
|
|
21003
|
+
key: "chartShowLegend",
|
|
21004
|
+
label: "Show Legend",
|
|
21005
|
+
default: true
|
|
21006
|
+
},
|
|
21007
|
+
{
|
|
21008
|
+
type: "toggle",
|
|
21009
|
+
key: "chartShowValues",
|
|
21010
|
+
label: "Show Values"
|
|
21011
|
+
}
|
|
21012
|
+
]
|
|
21013
|
+
},
|
|
21014
|
+
sheets: {
|
|
21015
|
+
key: "sheets",
|
|
21016
|
+
label: "Sheets",
|
|
21017
|
+
icon: "grid-3x3",
|
|
21018
|
+
description: "Spreadsheet — cells, formulas, and formatting in a collaborative grid",
|
|
21019
|
+
core: true,
|
|
21020
|
+
supportsChildren: true,
|
|
21021
|
+
childLabel: "Column",
|
|
21022
|
+
grandchildLabel: "Cell",
|
|
21023
|
+
defaultMetaFields: [
|
|
21024
|
+
{
|
|
21025
|
+
type: "number",
|
|
21026
|
+
key: "sheetsDefaultColWidth",
|
|
21027
|
+
min: 40,
|
|
21028
|
+
max: 500,
|
|
21029
|
+
step: 10,
|
|
21030
|
+
label: "Column Width"
|
|
21031
|
+
},
|
|
21032
|
+
{
|
|
21033
|
+
type: "number",
|
|
21034
|
+
key: "sheetsDefaultRowHeight",
|
|
21035
|
+
min: 20,
|
|
21036
|
+
max: 100,
|
|
21037
|
+
step: 2,
|
|
21038
|
+
label: "Row Height"
|
|
21039
|
+
},
|
|
21040
|
+
{
|
|
21041
|
+
type: "toggle",
|
|
21042
|
+
key: "sheetsShowGridlines",
|
|
21043
|
+
label: "Gridlines"
|
|
21044
|
+
}
|
|
21045
|
+
]
|
|
21046
|
+
},
|
|
21047
|
+
slides: {
|
|
21048
|
+
key: "slides",
|
|
21049
|
+
label: "Slides",
|
|
21050
|
+
icon: "presentation",
|
|
21051
|
+
description: "Presentation slides with two-axis navigation",
|
|
21052
|
+
core: true,
|
|
21053
|
+
supportsChildren: true,
|
|
21054
|
+
childLabel: "Slide",
|
|
21055
|
+
grandchildLabel: "Sub-slide",
|
|
21056
|
+
metaSchema: [{
|
|
21057
|
+
type: "select",
|
|
21058
|
+
key: "slidesTransition",
|
|
21059
|
+
options: [
|
|
21060
|
+
"none",
|
|
21061
|
+
"fade",
|
|
21062
|
+
"slide"
|
|
21063
|
+
],
|
|
21064
|
+
label: "Transition"
|
|
21065
|
+
}, {
|
|
21066
|
+
type: "colorPreset",
|
|
21067
|
+
key: "color",
|
|
21068
|
+
presets: [
|
|
21069
|
+
"#6366f1",
|
|
21070
|
+
"#ec4899",
|
|
21071
|
+
"#f97316",
|
|
21072
|
+
"#22c55e",
|
|
21073
|
+
"#3b82f6",
|
|
21074
|
+
"#a855f7"
|
|
21075
|
+
],
|
|
21076
|
+
label: "Accent"
|
|
21077
|
+
}],
|
|
21078
|
+
defaultMetaFields: [{
|
|
21079
|
+
type: "select",
|
|
21080
|
+
key: "slidesTheme",
|
|
21081
|
+
options: ["dark", "light"],
|
|
21082
|
+
label: "Theme"
|
|
21083
|
+
}]
|
|
21084
|
+
},
|
|
21085
|
+
overview: {
|
|
21086
|
+
key: "overview",
|
|
21087
|
+
label: "Overview",
|
|
21088
|
+
icon: "radar",
|
|
21089
|
+
description: "Space home — activity, people, stats, and health at a glance",
|
|
21090
|
+
core: true,
|
|
21091
|
+
supportsChildren: true,
|
|
21092
|
+
childLabel: "Page"
|
|
21093
|
+
},
|
|
21094
|
+
spatial: {
|
|
21095
|
+
key: "spatial",
|
|
21096
|
+
label: "Spatial",
|
|
21097
|
+
icon: "box",
|
|
21098
|
+
description: "3D scene with collaborative objects and real-time presence",
|
|
21099
|
+
core: false,
|
|
21100
|
+
plugin: "spatial",
|
|
21101
|
+
supportsChildren: true,
|
|
21102
|
+
childLabel: "Object",
|
|
21103
|
+
grandchildLabel: "Part",
|
|
21104
|
+
defaultDepth: -1,
|
|
21105
|
+
metaSchema: [
|
|
21106
|
+
{
|
|
21107
|
+
type: "select",
|
|
21108
|
+
key: "spShape",
|
|
21109
|
+
options: [
|
|
21110
|
+
"box",
|
|
21111
|
+
"sphere",
|
|
21112
|
+
"cylinder",
|
|
21113
|
+
"cone",
|
|
21114
|
+
"plane",
|
|
21115
|
+
"torus",
|
|
21116
|
+
"glb"
|
|
21117
|
+
],
|
|
21118
|
+
label: "Shape"
|
|
21119
|
+
},
|
|
21120
|
+
{
|
|
21121
|
+
type: "colorPreset",
|
|
21122
|
+
key: "color",
|
|
21123
|
+
presets: [
|
|
21124
|
+
"#6366f1",
|
|
21125
|
+
"#ef4444",
|
|
21126
|
+
"#22c55e",
|
|
21127
|
+
"#3b82f6",
|
|
21128
|
+
"#f97316",
|
|
21129
|
+
"#a855f7",
|
|
21130
|
+
"#ec4899",
|
|
21131
|
+
"#14b8a6"
|
|
21132
|
+
],
|
|
21133
|
+
label: "Color"
|
|
21134
|
+
},
|
|
21135
|
+
{
|
|
21136
|
+
type: "slider",
|
|
21137
|
+
key: "spOpacity",
|
|
21138
|
+
min: 0,
|
|
21139
|
+
max: 100,
|
|
21140
|
+
label: "Opacity"
|
|
21141
|
+
},
|
|
21142
|
+
{
|
|
21143
|
+
type: "number",
|
|
21144
|
+
key: "spX",
|
|
21145
|
+
step: .1,
|
|
21146
|
+
label: "X"
|
|
21147
|
+
},
|
|
21148
|
+
{
|
|
21149
|
+
type: "number",
|
|
21150
|
+
key: "spY",
|
|
21151
|
+
step: .1,
|
|
21152
|
+
label: "Y"
|
|
21153
|
+
},
|
|
21154
|
+
{
|
|
21155
|
+
type: "number",
|
|
21156
|
+
key: "spZ",
|
|
21157
|
+
step: .1,
|
|
21158
|
+
label: "Z"
|
|
21159
|
+
},
|
|
21160
|
+
{
|
|
21161
|
+
type: "number",
|
|
21162
|
+
key: "spRX",
|
|
21163
|
+
min: -180,
|
|
21164
|
+
max: 180,
|
|
21165
|
+
step: 1,
|
|
21166
|
+
label: "Rot X"
|
|
21167
|
+
},
|
|
21168
|
+
{
|
|
21169
|
+
type: "number",
|
|
21170
|
+
key: "spRY",
|
|
21171
|
+
min: -180,
|
|
21172
|
+
max: 180,
|
|
21173
|
+
step: 1,
|
|
21174
|
+
label: "Rot Y"
|
|
21175
|
+
},
|
|
21176
|
+
{
|
|
21177
|
+
type: "number",
|
|
21178
|
+
key: "spRZ",
|
|
21179
|
+
min: -180,
|
|
21180
|
+
max: 180,
|
|
21181
|
+
step: 1,
|
|
21182
|
+
label: "Rot Z"
|
|
21183
|
+
},
|
|
21184
|
+
{
|
|
21185
|
+
type: "number",
|
|
21186
|
+
key: "spSX",
|
|
21187
|
+
min: .01,
|
|
21188
|
+
max: 100,
|
|
21189
|
+
step: .1,
|
|
21190
|
+
label: "Scale X"
|
|
21191
|
+
},
|
|
21192
|
+
{
|
|
21193
|
+
type: "number",
|
|
21194
|
+
key: "spSY",
|
|
21195
|
+
min: .01,
|
|
21196
|
+
max: 100,
|
|
21197
|
+
step: .1,
|
|
21198
|
+
label: "Scale Y"
|
|
21199
|
+
},
|
|
21200
|
+
{
|
|
21201
|
+
type: "number",
|
|
21202
|
+
key: "spSZ",
|
|
21203
|
+
min: .01,
|
|
21204
|
+
max: 100,
|
|
21205
|
+
step: .1,
|
|
21206
|
+
label: "Scale Z"
|
|
21207
|
+
}
|
|
21208
|
+
],
|
|
21209
|
+
defaultMetaFields: [{
|
|
21210
|
+
type: "toggle",
|
|
21211
|
+
key: "spatialGridVisible",
|
|
21212
|
+
label: "Show Grid",
|
|
21213
|
+
default: true
|
|
21214
|
+
}]
|
|
21215
|
+
},
|
|
21216
|
+
media: {
|
|
21217
|
+
key: "media",
|
|
21218
|
+
label: "Media",
|
|
21219
|
+
icon: "disc-3",
|
|
21220
|
+
description: "Media player with synced listening and playlists",
|
|
21221
|
+
core: false,
|
|
21222
|
+
plugin: "media",
|
|
21223
|
+
supportsChildren: true,
|
|
21224
|
+
childLabel: "Track",
|
|
21225
|
+
defaultDepth: -1,
|
|
21226
|
+
metaSchema: [{
|
|
21227
|
+
type: "tags",
|
|
21228
|
+
key: "tags",
|
|
21229
|
+
label: "Tags"
|
|
21230
|
+
}],
|
|
21231
|
+
defaultMetaFields: [{
|
|
21232
|
+
type: "select",
|
|
21233
|
+
key: "mediaRepeat",
|
|
21234
|
+
options: [
|
|
21235
|
+
"off",
|
|
21236
|
+
"all",
|
|
21237
|
+
"one"
|
|
21238
|
+
],
|
|
21239
|
+
label: "Repeat"
|
|
21240
|
+
}, {
|
|
21241
|
+
type: "toggle",
|
|
21242
|
+
key: "mediaShuffle",
|
|
21243
|
+
label: "Shuffle"
|
|
21244
|
+
}]
|
|
21245
|
+
},
|
|
21246
|
+
coder: {
|
|
21247
|
+
key: "coder",
|
|
21248
|
+
label: "Coder",
|
|
21249
|
+
icon: "code-2",
|
|
21250
|
+
description: "Collaborative multi-file coding environment",
|
|
21251
|
+
core: false,
|
|
21252
|
+
plugin: "coder",
|
|
21253
|
+
supportsChildren: true,
|
|
21254
|
+
childLabel: "File",
|
|
21255
|
+
defaultDepth: -1,
|
|
21256
|
+
metaSchema: [{
|
|
21257
|
+
type: "select",
|
|
21258
|
+
key: "fileType",
|
|
21259
|
+
options: [
|
|
21260
|
+
"vue",
|
|
21261
|
+
"ts",
|
|
21262
|
+
"js",
|
|
21263
|
+
"css",
|
|
21264
|
+
"json",
|
|
21265
|
+
"folder"
|
|
21266
|
+
],
|
|
21267
|
+
label: "Type"
|
|
21268
|
+
}, {
|
|
21269
|
+
type: "toggle",
|
|
21270
|
+
key: "entry",
|
|
21271
|
+
label: "Entry Point"
|
|
21272
|
+
}]
|
|
21273
|
+
}
|
|
21274
|
+
};
|
|
21275
|
+
const TYPE_ALIASES = { desktop: "dashboard" };
|
|
21276
|
+
function resolvePageType(key) {
|
|
21277
|
+
if (!key) return void 0;
|
|
21278
|
+
return PAGE_TYPES[TYPE_ALIASES[key] ?? key];
|
|
21279
|
+
}
|
|
21280
|
+
|
|
20434
21281
|
//#endregion
|
|
20435
21282
|
//#region packages/mcp/src/tools/tree.ts
|
|
20436
21283
|
/**
|
|
@@ -20504,16 +21351,12 @@ function registerTreeTools(mcp, server) {
|
|
|
20504
21351
|
server.setAutoStatus("reading");
|
|
20505
21352
|
server.setActiveToolCall({ name: "list_documents" });
|
|
20506
21353
|
const treeMap = server.getTreeMap();
|
|
20507
|
-
if (!treeMap) {
|
|
20508
|
-
|
|
20509
|
-
|
|
20510
|
-
|
|
20511
|
-
text: "Not connected"
|
|
20512
|
-
}] };
|
|
20513
|
-
}
|
|
21354
|
+
if (!treeMap) return { content: [{
|
|
21355
|
+
type: "text",
|
|
21356
|
+
text: "Not connected"
|
|
21357
|
+
}] };
|
|
20514
21358
|
const targetId = normalizeRootId(parentId, server);
|
|
20515
21359
|
const children = childrenOf$1(readEntries$1(treeMap), targetId);
|
|
20516
|
-
server.setActiveToolCall(null);
|
|
20517
21360
|
return { content: [{
|
|
20518
21361
|
type: "text",
|
|
20519
21362
|
text: JSON.stringify(children, null, 2)
|
|
@@ -20526,17 +21369,13 @@ function registerTreeTools(mcp, server) {
|
|
|
20526
21369
|
server.setAutoStatus("reading");
|
|
20527
21370
|
server.setActiveToolCall({ name: "get_document_tree" });
|
|
20528
21371
|
const treeMap = server.getTreeMap();
|
|
20529
|
-
if (!treeMap) {
|
|
20530
|
-
|
|
20531
|
-
|
|
20532
|
-
|
|
20533
|
-
text: "Not connected"
|
|
20534
|
-
}] };
|
|
20535
|
-
}
|
|
21372
|
+
if (!treeMap) return { content: [{
|
|
21373
|
+
type: "text",
|
|
21374
|
+
text: "Not connected"
|
|
21375
|
+
}] };
|
|
20536
21376
|
const targetId = normalizeRootId(rootId, server);
|
|
20537
21377
|
const maxDepth = depth ?? 3;
|
|
20538
21378
|
const tree = buildTree$1(readEntries$1(treeMap), targetId, maxDepth);
|
|
20539
|
-
server.setActiveToolCall(null);
|
|
20540
21379
|
return { content: [{
|
|
20541
21380
|
type: "text",
|
|
20542
21381
|
text: JSON.stringify(tree, null, 2)
|
|
@@ -20552,13 +21391,10 @@ function registerTreeTools(mcp, server) {
|
|
|
20552
21391
|
target: query
|
|
20553
21392
|
});
|
|
20554
21393
|
const treeMap = server.getTreeMap();
|
|
20555
|
-
if (!treeMap) {
|
|
20556
|
-
|
|
20557
|
-
|
|
20558
|
-
|
|
20559
|
-
text: "Not connected"
|
|
20560
|
-
}] };
|
|
20561
|
-
}
|
|
21394
|
+
if (!treeMap) return { content: [{
|
|
21395
|
+
type: "text",
|
|
21396
|
+
text: "Not connected"
|
|
21397
|
+
}] };
|
|
20562
21398
|
const entries = readEntries$1(treeMap);
|
|
20563
21399
|
const lowerQuery = query.toLowerCase();
|
|
20564
21400
|
const normalizedRoot = normalizeRootId(rootId, server);
|
|
@@ -20583,7 +21419,6 @@ function registerTreeTools(mcp, server) {
|
|
|
20583
21419
|
path
|
|
20584
21420
|
};
|
|
20585
21421
|
});
|
|
20586
|
-
server.setActiveToolCall(null);
|
|
20587
21422
|
if (results.length === 0) return { content: [{
|
|
20588
21423
|
type: "text",
|
|
20589
21424
|
text: `No documents found matching "${query}". Try get_document_tree to see the full hierarchy.`
|
|
@@ -20596,8 +21431,8 @@ function registerTreeTools(mcp, server) {
|
|
|
20596
21431
|
mcp.tool("create_document", "Create a new document in the tree. Returns the new document ID.", {
|
|
20597
21432
|
parentId: z.string().optional().describe("Parent document ID. Omit for top-level pages. Use a document ID for nested/child pages."),
|
|
20598
21433
|
label: z.string().describe("Display name / title for the document."),
|
|
20599
|
-
type: z.string().optional().describe("Page type — sets how this document renders. \"doc\" (rich text), \"kanban\" (columns → cards), \"table\" (columns → rows
|
|
20600
|
-
meta: z.record(z.unknown()).optional().describe("Initial metadata (PageMeta fields: color as hex string, icon as Lucide kebab-case name like \"star\"/\"code-2\"/\"users\" — never emoji, dateStart, dateEnd, priority 0-4, tags array, etc). Omit icon entirely to use page type default.")
|
|
21434
|
+
type: z.string().optional().describe("Page type — sets how this document renders. Core types (always available): \"doc\" (rich text), \"kanban\" (columns → cards), \"table\" (columns → rows, positional), \"calendar\" (events with datetimeStart/End), \"timeline\" (epics → tasks with dateStart/End + taskProgress), \"checklist\" (tasks with checked/priority, unlimited nesting), \"outline\" (nested items, unlimited depth), \"gallery\" (visual grid with covers/ratings), \"map\" (markers/lines with geoLat/geoLng), \"graph\" (force-directed knowledge graph), \"dashboard\" (positioned widgets with deskX/deskY/deskMode), \"slides\" (slides → sub-slides with transitions), \"chart\" (bar/stacked bar/line/donut/treemap from data points or aggregation), \"sheets\" (spreadsheet with formulas and formatting), \"overview\" (space home — activity and stats), \"call\" (video call room, no children). Plugin types (require plugin enabled on the server): \"spatial\" (3D scene with spShape/spX/spY/spZ + universal color, plugin: spatial), \"media\" (audio/video player with playlists, plugin: media), \"coder\" (collaborative multi-file coding env with fileType/entry, plugin: coder). Alias: \"desktop\" → \"dashboard\". Omit to inherit parent view. Only set on the parent page, NEVER on child items."),
|
|
21435
|
+
meta: z.record(z.string(), z.unknown()).optional().describe("Initial metadata (PageMeta fields: color as hex string, icon as Lucide kebab-case name like \"star\"/\"code-2\"/\"users\" — never emoji, dateStart, dateEnd, priority 0-4, tags array, etc). Omit icon entirely to use page type default.")
|
|
20601
21436
|
}, async ({ parentId, label, type, meta }) => {
|
|
20602
21437
|
server.setAutoStatus("creating");
|
|
20603
21438
|
server.setActiveToolCall({
|
|
@@ -20606,13 +21441,10 @@ function registerTreeTools(mcp, server) {
|
|
|
20606
21441
|
});
|
|
20607
21442
|
const treeMap = server.getTreeMap();
|
|
20608
21443
|
const rootDoc = server.rootDocument;
|
|
20609
|
-
if (!treeMap || !rootDoc) {
|
|
20610
|
-
|
|
20611
|
-
|
|
20612
|
-
|
|
20613
|
-
text: "Not connected"
|
|
20614
|
-
}] };
|
|
20615
|
-
}
|
|
21444
|
+
if (!treeMap || !rootDoc) return { content: [{
|
|
21445
|
+
type: "text",
|
|
21446
|
+
text: "Not connected"
|
|
21447
|
+
}] };
|
|
20616
21448
|
const id = crypto.randomUUID();
|
|
20617
21449
|
const normalizedParent = normalizeRootId(parentId, server);
|
|
20618
21450
|
const now = Date.now();
|
|
@@ -20628,7 +21460,6 @@ function registerTreeTools(mcp, server) {
|
|
|
20628
21460
|
});
|
|
20629
21461
|
});
|
|
20630
21462
|
server.setFocusedDoc(id);
|
|
20631
|
-
server.setActiveToolCall(null);
|
|
20632
21463
|
return { content: [{
|
|
20633
21464
|
type: "text",
|
|
20634
21465
|
text: JSON.stringify({
|
|
@@ -20649,28 +21480,21 @@ function registerTreeTools(mcp, server) {
|
|
|
20649
21480
|
target: id
|
|
20650
21481
|
});
|
|
20651
21482
|
const treeMap = server.getTreeMap();
|
|
20652
|
-
if (!treeMap) {
|
|
20653
|
-
|
|
20654
|
-
|
|
20655
|
-
|
|
20656
|
-
text: "Not connected"
|
|
20657
|
-
}] };
|
|
20658
|
-
}
|
|
21483
|
+
if (!treeMap) return { content: [{
|
|
21484
|
+
type: "text",
|
|
21485
|
+
text: "Not connected"
|
|
21486
|
+
}] };
|
|
20659
21487
|
const raw = treeMap.get(id);
|
|
20660
|
-
if (!raw) {
|
|
20661
|
-
|
|
20662
|
-
|
|
20663
|
-
|
|
20664
|
-
text: `Document ${id} not found`
|
|
20665
|
-
}] };
|
|
20666
|
-
}
|
|
21488
|
+
if (!raw) return { content: [{
|
|
21489
|
+
type: "text",
|
|
21490
|
+
text: `Document ${id} not found`
|
|
21491
|
+
}] };
|
|
20667
21492
|
const entry = toPlain(raw);
|
|
20668
21493
|
treeMap.set(id, {
|
|
20669
21494
|
...entry,
|
|
20670
21495
|
label,
|
|
20671
21496
|
updatedAt: Date.now()
|
|
20672
21497
|
});
|
|
20673
|
-
server.setActiveToolCall(null);
|
|
20674
21498
|
return { content: [{
|
|
20675
21499
|
type: "text",
|
|
20676
21500
|
text: `Renamed to "${label}"`
|
|
@@ -20687,21 +21511,15 @@ function registerTreeTools(mcp, server) {
|
|
|
20687
21511
|
target: id
|
|
20688
21512
|
});
|
|
20689
21513
|
const treeMap = server.getTreeMap();
|
|
20690
|
-
if (!treeMap) {
|
|
20691
|
-
|
|
20692
|
-
|
|
20693
|
-
|
|
20694
|
-
text: "Not connected"
|
|
20695
|
-
}] };
|
|
20696
|
-
}
|
|
21514
|
+
if (!treeMap) return { content: [{
|
|
21515
|
+
type: "text",
|
|
21516
|
+
text: "Not connected"
|
|
21517
|
+
}] };
|
|
20697
21518
|
const raw = treeMap.get(id);
|
|
20698
|
-
if (!raw) {
|
|
20699
|
-
|
|
20700
|
-
|
|
20701
|
-
|
|
20702
|
-
text: `Document ${id} not found`
|
|
20703
|
-
}] };
|
|
20704
|
-
}
|
|
21519
|
+
if (!raw) return { content: [{
|
|
21520
|
+
type: "text",
|
|
21521
|
+
text: `Document ${id} not found`
|
|
21522
|
+
}] };
|
|
20705
21523
|
const entry = toPlain(raw);
|
|
20706
21524
|
treeMap.set(id, {
|
|
20707
21525
|
...entry,
|
|
@@ -20709,7 +21527,6 @@ function registerTreeTools(mcp, server) {
|
|
|
20709
21527
|
order: order ?? Date.now(),
|
|
20710
21528
|
updatedAt: Date.now()
|
|
20711
21529
|
});
|
|
20712
|
-
server.setActiveToolCall(null);
|
|
20713
21530
|
return { content: [{
|
|
20714
21531
|
type: "text",
|
|
20715
21532
|
text: `Moved ${id} to parent ${newParentId}`
|
|
@@ -20724,13 +21541,10 @@ function registerTreeTools(mcp, server) {
|
|
|
20724
21541
|
const treeMap = server.getTreeMap();
|
|
20725
21542
|
const trashMap = server.getTrashMap();
|
|
20726
21543
|
const rootDoc = server.rootDocument;
|
|
20727
|
-
if (!treeMap || !trashMap || !rootDoc) {
|
|
20728
|
-
|
|
20729
|
-
|
|
20730
|
-
|
|
20731
|
-
text: "Not connected"
|
|
20732
|
-
}] };
|
|
20733
|
-
}
|
|
21544
|
+
if (!treeMap || !trashMap || !rootDoc) return { content: [{
|
|
21545
|
+
type: "text",
|
|
21546
|
+
text: "Not connected"
|
|
21547
|
+
}] };
|
|
20734
21548
|
const toDelete = [id, ...descendantsOf(readEntries$1(treeMap), id).map((e) => e.id)];
|
|
20735
21549
|
const now = Date.now();
|
|
20736
21550
|
rootDoc.transact(() => {
|
|
@@ -20749,7 +21563,6 @@ function registerTreeTools(mcp, server) {
|
|
|
20749
21563
|
treeMap.delete(nid);
|
|
20750
21564
|
}
|
|
20751
21565
|
});
|
|
20752
|
-
server.setActiveToolCall(null);
|
|
20753
21566
|
return { content: [{
|
|
20754
21567
|
type: "text",
|
|
20755
21568
|
text: `Deleted ${toDelete.length} document(s)`
|
|
@@ -20757,7 +21570,7 @@ function registerTreeTools(mcp, server) {
|
|
|
20757
21570
|
});
|
|
20758
21571
|
mcp.tool("change_document_type", "Change the page type view of a document (data is preserved).", {
|
|
20759
21572
|
id: z.string().describe("Document ID."),
|
|
20760
|
-
type: z.string().describe("New page type: \"doc\", \"kanban\", \"table\", \"calendar\", \"timeline\", \"checklist\", \"outline\", \"gallery\", \"map\", \"graph\", \"dashboard\", \"
|
|
21573
|
+
type: z.string().describe("New page type. Core: \"doc\", \"kanban\", \"table\", \"calendar\", \"timeline\", \"checklist\", \"outline\", \"gallery\", \"map\", \"graph\", \"dashboard\", \"slides\", \"chart\", \"sheets\", \"overview\", \"call\". Plugin (require plugin enabled): \"spatial\", \"media\", \"coder\". Switching preserves the tree — children, labels, and meta are all retained; only the view changes.")
|
|
20761
21574
|
}, async ({ id, type }) => {
|
|
20762
21575
|
server.setAutoStatus("writing");
|
|
20763
21576
|
server.setActiveToolCall({
|
|
@@ -20765,28 +21578,21 @@ function registerTreeTools(mcp, server) {
|
|
|
20765
21578
|
target: id
|
|
20766
21579
|
});
|
|
20767
21580
|
const treeMap = server.getTreeMap();
|
|
20768
|
-
if (!treeMap) {
|
|
20769
|
-
|
|
20770
|
-
|
|
20771
|
-
|
|
20772
|
-
text: "Not connected"
|
|
20773
|
-
}] };
|
|
20774
|
-
}
|
|
21581
|
+
if (!treeMap) return { content: [{
|
|
21582
|
+
type: "text",
|
|
21583
|
+
text: "Not connected"
|
|
21584
|
+
}] };
|
|
20775
21585
|
const raw = treeMap.get(id);
|
|
20776
|
-
if (!raw) {
|
|
20777
|
-
|
|
20778
|
-
|
|
20779
|
-
|
|
20780
|
-
text: `Document ${id} not found`
|
|
20781
|
-
}] };
|
|
20782
|
-
}
|
|
21586
|
+
if (!raw) return { content: [{
|
|
21587
|
+
type: "text",
|
|
21588
|
+
text: `Document ${id} not found`
|
|
21589
|
+
}] };
|
|
20783
21590
|
const entry = toPlain(raw);
|
|
20784
21591
|
treeMap.set(id, {
|
|
20785
21592
|
...entry,
|
|
20786
21593
|
type,
|
|
20787
21594
|
updatedAt: Date.now()
|
|
20788
21595
|
});
|
|
20789
|
-
server.setActiveToolCall(null);
|
|
20790
21596
|
return { content: [{
|
|
20791
21597
|
type: "text",
|
|
20792
21598
|
text: `Changed type to "${type}"`
|
|
@@ -20842,6 +21648,27 @@ function registerTreeTools(mcp, server) {
|
|
|
20842
21648
|
}, null, 2)
|
|
20843
21649
|
}] };
|
|
20844
21650
|
});
|
|
21651
|
+
mcp.tool("list_page_types", "Enumerate all known Abracadabra page types with their metadata schemas. Returns an array of { key, label, icon, description, core, plugin, supportsChildren, childLabel, grandchildLabel, defaultDepth, metaSchema, defaultMetaFields }. `metaSchema` describes fields that apply to DESCENDANTS (children, grandchildren, ...) of a page of this type. `defaultMetaFields` are view-config fields on the page doc itself. Plugin types (core: false) require the named plugin to be enabled on the server. Use this to discover what meta keys a given renderer supports instead of guessing.", { key: z.string().optional().describe("Filter to a single type by key (e.g. \"kanban\", \"calendar\"). Aliases are resolved (e.g. \"desktop\" → \"dashboard\"). Omit to list all types.") }, async ({ key }) => {
|
|
21652
|
+
if (key) {
|
|
21653
|
+
const resolved = resolvePageType(key);
|
|
21654
|
+
if (!resolved) return { content: [{
|
|
21655
|
+
type: "text",
|
|
21656
|
+
text: `Unknown page type "${key}". Call list_page_types with no args to see all types.`
|
|
21657
|
+
}] };
|
|
21658
|
+
return { content: [{
|
|
21659
|
+
type: "text",
|
|
21660
|
+
text: JSON.stringify(resolved, null, 2)
|
|
21661
|
+
}] };
|
|
21662
|
+
}
|
|
21663
|
+
const all = Object.values(PAGE_TYPES);
|
|
21664
|
+
return { content: [{
|
|
21665
|
+
type: "text",
|
|
21666
|
+
text: JSON.stringify({
|
|
21667
|
+
types: all,
|
|
21668
|
+
aliases: TYPE_ALIASES
|
|
21669
|
+
}, null, 2)
|
|
21670
|
+
}] };
|
|
21671
|
+
});
|
|
20845
21672
|
}
|
|
20846
21673
|
|
|
20847
21674
|
//#endregion
|
|
@@ -22018,7 +22845,6 @@ function registerContentTools(mcp, server) {
|
|
|
22018
22845
|
});
|
|
22019
22846
|
children.sort((a, b) => (treeMap.get(a.id)?.order ?? 0) - (treeMap.get(b.id)?.order ?? 0));
|
|
22020
22847
|
}
|
|
22021
|
-
server.setActiveToolCall(null);
|
|
22022
22848
|
const result = {
|
|
22023
22849
|
label,
|
|
22024
22850
|
type,
|
|
@@ -22031,7 +22857,6 @@ function registerContentTools(mcp, server) {
|
|
|
22031
22857
|
text: JSON.stringify(result, null, 2)
|
|
22032
22858
|
}] };
|
|
22033
22859
|
} catch (error) {
|
|
22034
|
-
server.setActiveToolCall(null);
|
|
22035
22860
|
return {
|
|
22036
22861
|
content: [{
|
|
22037
22862
|
type: "text",
|
|
@@ -22081,13 +22906,11 @@ function registerContentTools(mcp, server) {
|
|
|
22081
22906
|
populateYDocFromMarkdown(fragment, body || markdown, title || "Untitled");
|
|
22082
22907
|
server.setFocusedDoc(docId);
|
|
22083
22908
|
server.setDocCursor(docId, fragment.length);
|
|
22084
|
-
server.setActiveToolCall(null);
|
|
22085
22909
|
return { content: [{
|
|
22086
22910
|
type: "text",
|
|
22087
22911
|
text: `Document ${docId} updated (${writeMode} mode)`
|
|
22088
22912
|
}] };
|
|
22089
22913
|
} catch (error) {
|
|
22090
|
-
server.setActiveToolCall(null);
|
|
22091
22914
|
return {
|
|
22092
22915
|
content: [{
|
|
22093
22916
|
type: "text",
|
|
@@ -22109,22 +22932,15 @@ function registerMetaTools(mcp, server) {
|
|
|
22109
22932
|
target: docId
|
|
22110
22933
|
});
|
|
22111
22934
|
const treeMap = server.getTreeMap();
|
|
22112
|
-
if (!treeMap) {
|
|
22113
|
-
|
|
22114
|
-
|
|
22115
|
-
|
|
22116
|
-
text: "Not connected"
|
|
22117
|
-
}] };
|
|
22118
|
-
}
|
|
22935
|
+
if (!treeMap) return { content: [{
|
|
22936
|
+
type: "text",
|
|
22937
|
+
text: "Not connected"
|
|
22938
|
+
}] };
|
|
22119
22939
|
const entry = treeMap.get(docId);
|
|
22120
|
-
if (!entry) {
|
|
22121
|
-
|
|
22122
|
-
|
|
22123
|
-
|
|
22124
|
-
text: `Document ${docId} not found`
|
|
22125
|
-
}] };
|
|
22126
|
-
}
|
|
22127
|
-
server.setActiveToolCall(null);
|
|
22940
|
+
if (!entry) return { content: [{
|
|
22941
|
+
type: "text",
|
|
22942
|
+
text: `Document ${docId} not found`
|
|
22943
|
+
}] };
|
|
22128
22944
|
return { content: [{
|
|
22129
22945
|
type: "text",
|
|
22130
22946
|
text: JSON.stringify({
|
|
@@ -22137,7 +22953,7 @@ function registerMetaTools(mcp, server) {
|
|
|
22137
22953
|
});
|
|
22138
22954
|
mcp.tool("update_metadata", "Update metadata fields on a document. Merges the provided fields into existing metadata.", {
|
|
22139
22955
|
docId: z.string().describe("Document ID."),
|
|
22140
|
-
meta: z.record(z.unknown()).describe("Metadata fields to update (merged with existing). Universal keys: color (hex), icon (Lucide kebab-case — NEVER emoji), dateStart/dateEnd, datetimeStart/datetimeEnd, allDay, tags (string[]), checked (bool), priority (0=none,1=low,2=med,3=high,4=urgent), status, rating (0-5), url, email, phone, number, unit, subtitle, note, taskProgress (0-100), members ({id,label}[]), coverUploadId. Geo/Map: geoType (\"marker\"|\"line\"|\"measure\"), geoLat, geoLng, geoDescription. Spatial 3D: spShape (\"box\"|\"sphere\"|\"cylinder\"|\"cone\"|\"plane\"|\"torus\"|\"glb\"), spX/spY/spZ, spRX/spRY/spRZ, spSX/spSY/spSZ
|
|
22956
|
+
meta: z.record(z.string(), z.unknown()).describe("Metadata fields to update (merged with existing). Universal keys: color (hex), icon (Lucide kebab-case — NEVER emoji), dateStart/dateEnd, datetimeStart/datetimeEnd, allDay, timeStart/timeEnd, tags (string[]), checked (bool), priority (0=none,1=low,2=med,3=high,4=urgent), status, rating (0-5), url, email, phone, number, unit, subtitle, note, taskProgress (0-100), members ({id,label}[]), coverUploadId, coverDocId, dateTaken. Geo/Map (children): geoType (\"marker\"|\"line\"|\"measure\"), geoLat, geoLng, geoDescription. Spatial 3D (children, plugin: spatial): spShape (\"box\"|\"sphere\"|\"cylinder\"|\"cone\"|\"plane\"|\"torus\"|\"glb\"), spX/spY/spZ, spRX/spRY/spRZ (deg), spSX/spSY/spSZ (scale), spOpacity (0-100), spModelUploadId, spModelDocId — spatial uses the universal `color` key, NOT spColor. Dashboard (children): deskX, deskY, deskZ, deskMode (\"icon\"|\"widget-sm\"|\"widget-lg\"). Mindmap-layout (children): mmX, mmY. Graph-layout (children): graphX, graphY, graphPinned. Slides (children): slidesTransition (\"none\"|\"fade\"|\"slide\"). Coder (children, plugin: coder): fileType (\"vue\"|\"ts\"|\"js\"|\"css\"|\"json\"|\"folder\"), entry (bool). Cell formatting (sheets cells): bold, italic, textColor, bgColor, align (\"left\"|\"center\"|\"right\"), formula. Renderer config (on the PAGE doc itself, not children): kanbanColumnWidth (\"narrow\"|\"default\"|\"wide\"), galleryColumns (1-6), galleryAspect (\"square\"|\"4:3\"|\"3:2\"|\"16:9\"|\"free\"), galleryCardStyle (\"default\"|\"compact\"|\"detailed\"), galleryShowLabels, gallerySortBy (\"manual\"|\"date\"|\"name\"|\"rating\"), calendarView (\"month\"|\"week\"|\"day\"), calendarWeekStart (\"sun\"|\"mon\"), calendarShowWeekNumbers, tableMode (\"hierarchy\"|\"flat\"), tableSortKey, tableSortDir (\"asc\"|\"desc\"), timelineZoom (\"week\"|\"month\"|\"quarter\"), timelinePixelsPerDay, timelineCenterDate (ISO date), checklistFilter (\"all\"|\"active\"|\"completed\"), checklistSort (\"manual\"|\"priority\"|\"due\"), mapShowLabels, graphSpacing (\"compact\"|\"default\"|\"spacious\"), graphShowLabels, graphEdgeThickness (\"thin\"|\"normal\"|\"thick\"), showRefEdges, mmSpacing, spatialGridVisible, slidesTheme (\"dark\"|\"light\"), chartType (\"bar\"|\"stacked bar\"|\"line\"|\"donut\"|\"treemap\"), chartMetric (\"value\"|\"type\"|\"tag\"|\"status\"|\"priority\"|\"activity\"|\"completion\"), chartColorScheme (\"default\"|\"warm\"|\"cool\"|\"mono\"), chartLimit (3-30), chartShowLegend, chartShowValues, sheetsDefaultColWidth (40-500), sheetsDefaultRowHeight (20-100), sheetsShowGridlines, sheetsFreezeRows, sheetsFreezeCols, mediaRepeat (\"off\"|\"all\"|\"one\"), mediaShuffle. Set a key to null to clear it.")
|
|
22141
22957
|
}, async ({ docId, meta }) => {
|
|
22142
22958
|
server.setAutoStatus("writing", docId);
|
|
22143
22959
|
server.setActiveToolCall({
|
|
@@ -22145,21 +22961,15 @@ function registerMetaTools(mcp, server) {
|
|
|
22145
22961
|
target: docId
|
|
22146
22962
|
});
|
|
22147
22963
|
const treeMap = server.getTreeMap();
|
|
22148
|
-
if (!treeMap) {
|
|
22149
|
-
|
|
22150
|
-
|
|
22151
|
-
|
|
22152
|
-
text: "Not connected"
|
|
22153
|
-
}] };
|
|
22154
|
-
}
|
|
22964
|
+
if (!treeMap) return { content: [{
|
|
22965
|
+
type: "text",
|
|
22966
|
+
text: "Not connected"
|
|
22967
|
+
}] };
|
|
22155
22968
|
const entry = treeMap.get(docId);
|
|
22156
|
-
if (!entry) {
|
|
22157
|
-
|
|
22158
|
-
|
|
22159
|
-
|
|
22160
|
-
text: `Document ${docId} not found`
|
|
22161
|
-
}] };
|
|
22162
|
-
}
|
|
22969
|
+
if (!entry) return { content: [{
|
|
22970
|
+
type: "text",
|
|
22971
|
+
text: `Document ${docId} not found`
|
|
22972
|
+
}] };
|
|
22163
22973
|
treeMap.set(docId, {
|
|
22164
22974
|
...entry,
|
|
22165
22975
|
meta: {
|
|
@@ -22168,7 +22978,6 @@ function registerMetaTools(mcp, server) {
|
|
|
22168
22978
|
},
|
|
22169
22979
|
updatedAt: Date.now()
|
|
22170
22980
|
});
|
|
22171
|
-
server.setActiveToolCall(null);
|
|
22172
22981
|
return { content: [{
|
|
22173
22982
|
type: "text",
|
|
22174
22983
|
text: `Metadata updated for ${docId}`
|
|
@@ -22183,6 +22992,11 @@ function registerMetaTools(mcp, server) {
|
|
|
22183
22992
|
*/
|
|
22184
22993
|
function registerFileTools(mcp, server) {
|
|
22185
22994
|
mcp.tool("list_uploads", "List file attachments for a document.", { docId: z.string().describe("Document ID.") }, async ({ docId }) => {
|
|
22995
|
+
server.setAutoStatus("reading", docId);
|
|
22996
|
+
server.setActiveToolCall({
|
|
22997
|
+
name: "list_uploads",
|
|
22998
|
+
target: docId
|
|
22999
|
+
});
|
|
22186
23000
|
try {
|
|
22187
23001
|
const uploads = await server.client.listUploads(docId);
|
|
22188
23002
|
return { content: [{
|
|
@@ -22204,6 +23018,11 @@ function registerFileTools(mcp, server) {
|
|
|
22204
23018
|
filePath: z.string().describe("Absolute path to the local file to upload."),
|
|
22205
23019
|
filename: z.string().optional().describe("Override filename (defaults to basename of filePath).")
|
|
22206
23020
|
}, async ({ docId, filePath, filename }) => {
|
|
23021
|
+
server.setAutoStatus("uploading", docId);
|
|
23022
|
+
server.setActiveToolCall({
|
|
23023
|
+
name: "upload_file",
|
|
23024
|
+
target: path.basename(filePath)
|
|
23025
|
+
});
|
|
22207
23026
|
try {
|
|
22208
23027
|
const resolvedPath = path.resolve(filePath);
|
|
22209
23028
|
const data = fs.readFileSync(resolvedPath);
|
|
@@ -22229,6 +23048,11 @@ function registerFileTools(mcp, server) {
|
|
|
22229
23048
|
uploadId: z.string().describe("Upload ID to download."),
|
|
22230
23049
|
saveTo: z.string().describe("Absolute local file path to save the download.")
|
|
22231
23050
|
}, async ({ docId, uploadId, saveTo }) => {
|
|
23051
|
+
server.setAutoStatus("reading", docId);
|
|
23052
|
+
server.setActiveToolCall({
|
|
23053
|
+
name: "download_file",
|
|
23054
|
+
target: path.basename(saveTo)
|
|
23055
|
+
});
|
|
22232
23056
|
try {
|
|
22233
23057
|
const blob = await server.client.getUpload(docId, uploadId);
|
|
22234
23058
|
const buffer = Buffer.from(await blob.arrayBuffer());
|
|
@@ -22252,6 +23076,11 @@ function registerFileTools(mcp, server) {
|
|
|
22252
23076
|
docId: z.string().describe("Document ID."),
|
|
22253
23077
|
uploadId: z.string().describe("Upload ID to delete.")
|
|
22254
23078
|
}, async ({ docId, uploadId }) => {
|
|
23079
|
+
server.setAutoStatus("writing", docId);
|
|
23080
|
+
server.setActiveToolCall({
|
|
23081
|
+
name: "delete_file",
|
|
23082
|
+
target: uploadId
|
|
23083
|
+
});
|
|
22255
23084
|
try {
|
|
22256
23085
|
await server.client.deleteUpload(docId, uploadId);
|
|
22257
23086
|
return { content: [{
|
|
@@ -22293,6 +23122,10 @@ function registerAwarenessTools(mcp, server) {
|
|
|
22293
23122
|
docId: z.string().describe("Document ID to set awareness on."),
|
|
22294
23123
|
fields: z.record(z.string(), z.unknown()).describe("Key-value pairs to set on the child document's awareness state. Use namespaced keys like \"kanban:hovering\", \"table:editing\", \"slides:viewing\", \"outline:editing\", \"calendar:focused\", \"gallery:focused\", \"timeline:focused\", \"graph:focused\", \"map:focused\", \"doc:scroll\". Set a key to null to clear it.")
|
|
22295
23124
|
}, async ({ docId, fields }) => {
|
|
23125
|
+
server.setActiveToolCall({
|
|
23126
|
+
name: "set_doc_awareness",
|
|
23127
|
+
target: docId
|
|
23128
|
+
});
|
|
22296
23129
|
try {
|
|
22297
23130
|
const provider = await server.getChildProvider(docId);
|
|
22298
23131
|
for (const [key, value] of Object.entries(fields)) provider.awareness.setLocalStateField(key, value ?? null);
|
|
@@ -22311,6 +23144,7 @@ function registerAwarenessTools(mcp, server) {
|
|
|
22311
23144
|
}
|
|
22312
23145
|
});
|
|
22313
23146
|
mcp.tool("poll_inbox", "Check the \"AI Inbox\" document for pending instructions from humans. Returns the inbox content and any pending task sub-documents. Create the inbox as a doc called \"AI Inbox\" under the hub doc if it does not exist yet. Note: channel-based watching via watch_chat is preferred for real-time use.", {}, async () => {
|
|
23147
|
+
server.setActiveToolCall({ name: "poll_inbox" });
|
|
22314
23148
|
try {
|
|
22315
23149
|
const treeMap = server.getTreeMap();
|
|
22316
23150
|
const rootDocId = server.rootDocId;
|
|
@@ -22357,6 +23191,10 @@ function registerAwarenessTools(mcp, server) {
|
|
|
22357
23191
|
}
|
|
22358
23192
|
});
|
|
22359
23193
|
mcp.tool("list_connected_users", "List all connected users and their awareness state. Shows who is online and what they are doing.", { docId: z.string().optional().describe("If provided, list users connected to this specific document. Otherwise lists users from root awareness.") }, async ({ docId }) => {
|
|
23194
|
+
server.setActiveToolCall({
|
|
23195
|
+
name: "list_connected_users",
|
|
23196
|
+
target: docId
|
|
23197
|
+
});
|
|
22360
23198
|
try {
|
|
22361
23199
|
let awareness;
|
|
22362
23200
|
if (docId) awareness = (await server.getChildProvider(docId)).awareness;
|
|
@@ -22401,16 +23239,13 @@ function registerChannelTools(mcp, server) {
|
|
|
22401
23239
|
});
|
|
22402
23240
|
const treeMap = server.getTreeMap();
|
|
22403
23241
|
const rootDoc = server.rootDocument;
|
|
22404
|
-
if (!treeMap || !rootDoc) {
|
|
22405
|
-
|
|
22406
|
-
|
|
22407
|
-
|
|
22408
|
-
|
|
22409
|
-
|
|
22410
|
-
|
|
22411
|
-
isError: true
|
|
22412
|
-
};
|
|
22413
|
-
}
|
|
23242
|
+
if (!treeMap || !rootDoc) return {
|
|
23243
|
+
content: [{
|
|
23244
|
+
type: "text",
|
|
23245
|
+
text: "Not connected"
|
|
23246
|
+
}],
|
|
23247
|
+
isError: true
|
|
23248
|
+
};
|
|
22414
23249
|
const label = `AI Reply — ${(/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19)}: ${text.slice(0, 40).replace(/\n/g, " ")}`;
|
|
22415
23250
|
const replyId = crypto.randomUUID();
|
|
22416
23251
|
const now = Date.now();
|
|
@@ -22426,7 +23261,6 @@ function registerChannelTools(mcp, server) {
|
|
|
22426
23261
|
});
|
|
22427
23262
|
populateYDocFromMarkdown((await server.getChildProvider(replyId)).document, text);
|
|
22428
23263
|
if (task_id) server.clearAiTask(task_id);
|
|
22429
|
-
server.setActiveToolCall(null);
|
|
22430
23264
|
return { content: [{
|
|
22431
23265
|
type: "text",
|
|
22432
23266
|
text: JSON.stringify({
|
|
@@ -22435,7 +23269,6 @@ function registerChannelTools(mcp, server) {
|
|
|
22435
23269
|
})
|
|
22436
23270
|
}] };
|
|
22437
23271
|
} catch (error) {
|
|
22438
|
-
server.setActiveToolCall(null);
|
|
22439
23272
|
return {
|
|
22440
23273
|
content: [{
|
|
22441
23274
|
type: "text",
|
|
@@ -22458,14 +23291,15 @@ function registerChannelTools(mcp, server) {
|
|
|
22458
23291
|
}],
|
|
22459
23292
|
isError: true
|
|
22460
23293
|
};
|
|
23294
|
+
const normalized = text.replace(/\\r\\n/g, "\n").replace(/\\n/g, "\n").replace(/\\t/g, " ").replace(/\\r/g, "\n");
|
|
23295
|
+
server.setAutoStatus(null);
|
|
23296
|
+
server.sendTypingIndicator(channel);
|
|
22461
23297
|
rootProvider.sendStateless(JSON.stringify({
|
|
22462
23298
|
type: "chat:send",
|
|
22463
23299
|
channel,
|
|
22464
|
-
content:
|
|
23300
|
+
content: normalized,
|
|
22465
23301
|
sender_name: server.agentName
|
|
22466
23302
|
}));
|
|
22467
|
-
server.setAutoStatus(null);
|
|
22468
|
-
server.setActiveToolCall(null);
|
|
22469
23303
|
return { content: [{
|
|
22470
23304
|
type: "text",
|
|
22471
23305
|
text: `Sent to ${channel}`
|
|
@@ -22620,16 +23454,13 @@ function registerSvgTools(mcp, server) {
|
|
|
22620
23454
|
target: docId
|
|
22621
23455
|
});
|
|
22622
23456
|
const cleanSvg = sanitizeSvg(svg);
|
|
22623
|
-
if (!cleanSvg) {
|
|
22624
|
-
|
|
22625
|
-
|
|
22626
|
-
|
|
22627
|
-
|
|
22628
|
-
|
|
22629
|
-
|
|
22630
|
-
isError: true
|
|
22631
|
-
};
|
|
22632
|
-
}
|
|
23457
|
+
if (!cleanSvg) return {
|
|
23458
|
+
content: [{
|
|
23459
|
+
type: "text",
|
|
23460
|
+
text: "Error: SVG markup was empty or entirely stripped by sanitizer."
|
|
23461
|
+
}],
|
|
23462
|
+
isError: true
|
|
23463
|
+
};
|
|
22633
23464
|
const doc = (await server.getChildProvider(docId)).document;
|
|
22634
23465
|
const fragment = doc.getXmlFragment("default");
|
|
22635
23466
|
doc.transact(() => {
|
|
@@ -22640,13 +23471,11 @@ function registerSvgTools(mcp, server) {
|
|
|
22640
23471
|
fragment.insert(insertPos, [el]);
|
|
22641
23472
|
});
|
|
22642
23473
|
server.setFocusedDoc(docId);
|
|
22643
|
-
server.setActiveToolCall(null);
|
|
22644
23474
|
return { content: [{
|
|
22645
23475
|
type: "text",
|
|
22646
23476
|
text: `SVG inserted into document ${docId}${title ? ` ("${title}")` : ""}`
|
|
22647
23477
|
}] };
|
|
22648
23478
|
} catch (error) {
|
|
22649
|
-
server.setActiveToolCall(null);
|
|
22650
23479
|
return {
|
|
22651
23480
|
content: [{
|
|
22652
23481
|
type: "text",
|
|
@@ -22704,24 +23533,38 @@ If you are adding content to an existing space, call \`get_document_tree(rootId:
|
|
|
22704
23533
|
|
|
22705
23534
|
## Page Types Reference
|
|
22706
23535
|
|
|
23536
|
+
### Core Types (always available)
|
|
23537
|
+
|
|
22707
23538
|
| Type | Children Are | Grandchildren Are | Depth | Key Meta on Children |
|
|
22708
23539
|
|------|-------------|-------------------|-------|---------------------|
|
|
22709
23540
|
| **doc** | Sub-documents | Sub-sub-documents | ∞ | — |
|
|
22710
23541
|
| **kanban** | Columns | Cards | 2 | color, icon on cards |
|
|
22711
23542
|
| **table** | Columns | Cells (positional rows) | 2 | — |
|
|
22712
|
-
| **calendar** | Events | — | 1 | datetimeStart, datetimeEnd, allDay, color |
|
|
23543
|
+
| **calendar** | Events | — | 1 | datetimeStart, datetimeEnd, allDay, color, icon |
|
|
22713
23544
|
| **timeline** | Epics | Tasks | 2 | dateStart, dateEnd, taskProgress, color |
|
|
22714
23545
|
| **checklist** | Tasks | Sub-tasks | ∞ | checked, priority, dateEnd |
|
|
22715
23546
|
| **outline** | Items | Sub-items | ∞ | — |
|
|
22716
|
-
| **mindmap** | Central nodes | Branches | ∞ | mmX, mmY |
|
|
22717
23547
|
| **graph** | Nodes | — | 1 | graphX, graphY, graphPinned, color |
|
|
22718
|
-
| **gallery** | Items | — | 1 | geoLat, geoLng, datetimeStart, tags |
|
|
23548
|
+
| **gallery** | Items | — | 1 | geoLat, geoLng, datetimeStart, tags, rating, icon, color |
|
|
22719
23549
|
| **map** | Markers/Lines | Points (for lines) | 2 | geoType, geoLat, geoLng, icon, color |
|
|
22720
|
-
| **
|
|
22721
|
-
| **
|
|
22722
|
-
| **
|
|
22723
|
-
| **
|
|
22724
|
-
| **
|
|
23550
|
+
| **slides** | Slides | Sub-slides | 2 | slidesTransition, color |
|
|
23551
|
+
| **dashboard** | Items | — | 1 | deskX, deskY, deskZ, deskMode |
|
|
23552
|
+
| **chart** | Data points | Data points | 2 | number (value), color, tags |
|
|
23553
|
+
| **sheets** | Columns | Cells | 2 | formula, bold, italic, textColor, bgColor, align |
|
|
23554
|
+
| **overview** | Pages | — | 1 | — |
|
|
23555
|
+
| **call** | — (no children) | — | 0 | — |
|
|
23556
|
+
|
|
23557
|
+
Alias: \`desktop\` → \`dashboard\`.
|
|
23558
|
+
|
|
23559
|
+
### Plugin Types (require plugin enabled on the server)
|
|
23560
|
+
|
|
23561
|
+
| Type | Plugin | Children Are | Grandchildren Are | Depth | Key Meta on Children |
|
|
23562
|
+
|------|--------|-------------|-------------------|-------|---------------------|
|
|
23563
|
+
| **spatial** | spatial | Objects | Sub-parts | ∞ | spShape, spX/Y/Z, spRX/RY/RZ, spSX/SY/SZ, color, spOpacity |
|
|
23564
|
+
| **media** | media | Tracks | — | ∞ | tags |
|
|
23565
|
+
| **coder** | coder | Files/Folders | — | ∞ | fileType, entry |
|
|
23566
|
+
|
|
23567
|
+
> Spatial uses the universal \`color\` key for object color — there is no \`spColor\`.
|
|
22725
23568
|
|
|
22726
23569
|
---
|
|
22727
23570
|
|
|
@@ -22794,18 +23637,65 @@ If you are adding content to an existing space, call \`get_document_tree(rootId:
|
|
|
22794
23637
|
4. Modes: \`"icon"\` (small), \`"widget-sm"\` (240×180), \`"widget-lg"\` (400×320)
|
|
22795
23638
|
5. Grid uses 80px cells
|
|
22796
23639
|
|
|
22797
|
-
**Spatial (3D scene)
|
|
23640
|
+
**Spatial (3D scene)** *(requires spatial plugin):*
|
|
22798
23641
|
1. \`create_document(parentId, "3D Scene", "spatial")\`
|
|
22799
23642
|
2. Create objects: \`create_document(sceneId, "Red Cube")\`
|
|
22800
|
-
3. Set 3D properties: \`update_metadata(objId, { spShape: "box",
|
|
22801
|
-
4. Shapes: \`"box"\`, \`"sphere"\`, \`"cylinder"\`, \`"cone"\`, \`"plane"\`, \`"torus"\`, \`"glb"\` (uploaded 3D model)
|
|
23643
|
+
3. Set 3D properties: \`update_metadata(objId, { spShape: "box", color: "#ef4444", spX: 0, spY: 1, spZ: 0, spSX: 2, spSY: 2, spSZ: 2 })\`
|
|
23644
|
+
4. Shapes: \`"box"\`, \`"sphere"\`, \`"cylinder"\`, \`"cone"\`, \`"plane"\`, \`"torus"\`, \`"glb"\` (uploaded 3D model — set \`spModelUploadId\` and \`spModelDocId\`)
|
|
22802
23645
|
5. Rotation (degrees): \`spRX\`, \`spRY\`, \`spRZ\`. Scale: \`spSX\`, \`spSY\`, \`spSZ\` (default 1). Opacity: \`spOpacity\` (0–100)
|
|
23646
|
+
6. Use the universal \`color\` key — **never \`spColor\`**
|
|
22803
23647
|
|
|
22804
23648
|
**Outline (nested items):**
|
|
22805
23649
|
1. \`create_document(parentId, "Meeting Notes", "outline")\`
|
|
22806
23650
|
2. Create items: \`create_document(outlineId, "Agenda Item 1")\`
|
|
22807
23651
|
3. Create sub-items (unlimited depth): \`create_document(itemId, "Sub-point")\`
|
|
22808
23652
|
|
|
23653
|
+
**Slides (presentation with two-axis nav):**
|
|
23654
|
+
1. \`create_document(parentId, "Q1 Review", "slides")\`
|
|
23655
|
+
2. Create slides as direct children: \`create_document(deckId, "Intro")\`
|
|
23656
|
+
3. Create sub-slides (vertical navigation) as grandchildren: \`create_document(slideId, "Deep dive")\`
|
|
23657
|
+
4. Per-slide transition: \`update_metadata(slideId, { slidesTransition: "fade", color: "#6366f1" })\`
|
|
23658
|
+
5. Deck-level theme: \`update_metadata(deckId, { slidesTheme: "dark" })\`
|
|
23659
|
+
|
|
23660
|
+
**Chart (data viz — manual or aggregation):**
|
|
23661
|
+
1. \`create_document(parentId, "Sales", "chart")\`
|
|
23662
|
+
2. Configure: \`update_metadata(chartId, { chartType: "bar", chartMetric: "value", chartShowLegend: true, chartLimit: 10 })\`
|
|
23663
|
+
3. Modes:
|
|
23664
|
+
- **Manual data points**: create children with \`number\` (value) and optional \`tags\`/\`color\`
|
|
23665
|
+
\`create_document(chartId, "Q1")\` then \`update_metadata(dpId, { number: 42500, color: "#6366f1" })\`
|
|
23666
|
+
- **Aggregation**: set \`chartMetric\` to \`"type"\`/\`"tag"\`/\`"status"\`/\`"priority"\`/\`"activity"\`/\`"completion"\` and point the chart at a subtree — it aggregates the descendants' meta automatically
|
|
23667
|
+
4. Chart types: \`"bar"\`, \`"stacked bar"\`, \`"line"\`, \`"donut"\`, \`"treemap"\`
|
|
23668
|
+
5. Color schemes: \`"default"\`, \`"warm"\`, \`"cool"\`, \`"mono"\`
|
|
23669
|
+
|
|
23670
|
+
**Sheets (spreadsheet with formulas):**
|
|
23671
|
+
1. \`create_document(parentId, "Budget", "sheets")\`
|
|
23672
|
+
2. Create columns: \`create_document(sheetId, "A")\`, \`create_document(sheetId, "B")\`
|
|
23673
|
+
3. Create cells under columns (positional rows, like \`table\`)
|
|
23674
|
+
4. Formulas on cells: \`update_metadata(cellId, { formula: "=A1+B1" })\`
|
|
23675
|
+
5. Cell formatting: \`update_metadata(cellId, { bold: true, bgColor: "#fef3c7", align: "right" })\`
|
|
23676
|
+
6. Deck config: \`update_metadata(sheetId, { sheetsDefaultColWidth: 120, sheetsDefaultRowHeight: 28, sheetsShowGridlines: true, sheetsFreezeRows: 1, sheetsFreezeCols: 1 })\`
|
|
23677
|
+
|
|
23678
|
+
**Overview (space home):**
|
|
23679
|
+
1. \`create_document(parentId, "Home", "overview")\`
|
|
23680
|
+
2. No children required — renders activity, people, stats from the surrounding space
|
|
23681
|
+
3. Children (if any) show as linked pages
|
|
23682
|
+
|
|
23683
|
+
**Call (video room):**
|
|
23684
|
+
1. \`create_document(parentId, "Daily Standup", "call")\`
|
|
23685
|
+
2. Video rooms have **no children** — do not add documents underneath
|
|
23686
|
+
|
|
23687
|
+
**Coder (multi-file collaborative editor)** *(requires coder plugin):*
|
|
23688
|
+
1. \`create_document(parentId, "My App", "coder")\`
|
|
23689
|
+
2. Create files/folders: \`create_document(projectId, "App.vue")\`, \`create_document(projectId, "src")\`
|
|
23690
|
+
3. Set file type: \`update_metadata(fileId, { fileType: "vue", entry: true })\`
|
|
23691
|
+
4. \`fileType\` options: \`"vue"\`, \`"ts"\`, \`"js"\`, \`"css"\`, \`"json"\`, \`"folder"\`
|
|
23692
|
+
5. Mark the entry file with \`entry: true\` — the renderer uses it as the preview root
|
|
23693
|
+
|
|
23694
|
+
**Media (audio/video playlist)** *(requires media plugin):*
|
|
23695
|
+
1. \`create_document(parentId, "Focus Mix", "media")\`
|
|
23696
|
+
2. Create tracks: \`create_document(playlistId, "Track 1")\` — attach audio/video file via upload tool
|
|
23697
|
+
3. Playlist config: \`update_metadata(playlistId, { mediaRepeat: "all", mediaShuffle: false })\`
|
|
23698
|
+
|
|
22809
23699
|
---
|
|
22810
23700
|
|
|
22811
23701
|
## Document References
|
|
@@ -22880,22 +23770,55 @@ In the **graph** page type, document references (embeds and links) create visibl
|
|
|
22880
23770
|
|-----|------|-----------|--------|
|
|
22881
23771
|
| \`kanbanColumnWidth\` | string | kanban | "narrow", "default", "wide" |
|
|
22882
23772
|
| \`galleryColumns\` | number | gallery | 1–6 |
|
|
22883
|
-
| \`galleryAspect\` | string | gallery | "square", "4:3", "16:9" |
|
|
23773
|
+
| \`galleryAspect\` | string | gallery | "square", "4:3", "3:2", "16:9", "free" |
|
|
23774
|
+
| \`galleryCardStyle\` | string | gallery | "default", "compact", "detailed" |
|
|
23775
|
+
| \`galleryShowLabels\` | boolean | gallery | show item labels |
|
|
23776
|
+
| \`gallerySortBy\` | string | gallery | "manual", "date", "name", "rating" |
|
|
22884
23777
|
| \`calendarView\` | string | calendar | "month", "week", "day" |
|
|
22885
23778
|
| \`calendarWeekStart\` | string | calendar | "sun", "mon" |
|
|
23779
|
+
| \`calendarShowWeekNumbers\` | boolean | calendar | — |
|
|
22886
23780
|
| \`tableMode\` | string | table | "hierarchy", "flat" |
|
|
23781
|
+
| \`tableSortKey\` | string | table | meta key to sort by |
|
|
23782
|
+
| \`tableSortDir\` | string | table | "asc", "desc" |
|
|
23783
|
+
| \`timelineZoom\` | string | timeline | "week", "month", "quarter" |
|
|
23784
|
+
| \`timelinePixelsPerDay\` | number | timeline | zoom granularity |
|
|
23785
|
+
| \`timelineCenterDate\` | string | timeline | ISO date to center view |
|
|
23786
|
+
| \`checklistFilter\` | string | checklist | "all", "active", "completed" |
|
|
23787
|
+
| \`checklistSort\` | string | checklist | "manual", "priority", "due" |
|
|
23788
|
+
| \`mapShowLabels\` | boolean | map | — |
|
|
23789
|
+
| \`graphSpacing\` | string | graph | "compact", "default", "spacious" |
|
|
23790
|
+
| \`graphShowLabels\` | boolean | graph | — |
|
|
23791
|
+
| \`graphEdgeThickness\` | string | graph | "thin", "normal", "thick" |
|
|
22887
23792
|
| \`showRefEdges\` | boolean | graph | show doc-reference edges |
|
|
22888
|
-
|
|
22889
|
-
|
|
23793
|
+
| \`mmSpacing\` | string | mindmap-layout | spacing between branches |
|
|
23794
|
+
| \`spatialGridVisible\` | boolean | spatial | show ground grid |
|
|
23795
|
+
| \`slidesTheme\` | string | slides | "dark", "light" |
|
|
23796
|
+
| \`chartType\` | string | chart | "bar", "stacked bar", "line", "donut", "treemap" |
|
|
23797
|
+
| \`chartMetric\` | string | chart | "value", "type", "tag", "status", "priority", "activity", "completion" |
|
|
23798
|
+
| \`chartColorScheme\` | string | chart | "default", "warm", "cool", "mono" |
|
|
23799
|
+
| \`chartLimit\` | number | chart | 3–30 (max items) |
|
|
23800
|
+
| \`chartShowLegend\` | boolean | chart | — |
|
|
23801
|
+
| \`chartShowValues\` | boolean | chart | — |
|
|
23802
|
+
| \`sheetsDefaultColWidth\` | number | sheets | 40–500 |
|
|
23803
|
+
| \`sheetsDefaultRowHeight\` | number | sheets | 20–100 |
|
|
23804
|
+
| \`sheetsShowGridlines\` | boolean | sheets | — |
|
|
23805
|
+
| \`sheetsFreezeRows\` | number | sheets | frozen rows count |
|
|
23806
|
+
| \`sheetsFreezeCols\` | number | sheets | frozen cols count |
|
|
23807
|
+
| \`mediaRepeat\` | string | media | "off", "all", "one" (plugin) |
|
|
23808
|
+
| \`mediaShuffle\` | boolean | media | plugin |
|
|
23809
|
+
|
|
23810
|
+
### Spatial 3D Keys (for spatial children — requires spatial plugin)
|
|
22890
23811
|
|
|
22891
23812
|
| Key | Type | Default | Meaning |
|
|
22892
23813
|
|-----|------|---------|---------|
|
|
22893
23814
|
| \`spShape\` | string | — | "box", "sphere", "cylinder", "cone", "plane", "torus", "glb" |
|
|
22894
|
-
| \`
|
|
23815
|
+
| \`color\` | string | — | CSS color — universal key, **not** \`spColor\` |
|
|
22895
23816
|
| \`spOpacity\` | number | 100 | 0–100 |
|
|
22896
23817
|
| \`spX\`, \`spY\`, \`spZ\` | number | 0 | Position |
|
|
22897
23818
|
| \`spRX\`, \`spRY\`, \`spRZ\` | number | 0 | Rotation (degrees) |
|
|
22898
23819
|
| \`spSX\`, \`spSY\`, \`spSZ\` | number | 1 | Scale |
|
|
23820
|
+
| \`spModelUploadId\` | string | — | GLB upload ID (when \`spShape: "glb"\`) |
|
|
23821
|
+
| \`spModelDocId\` | string | — | Doc ID that owns the GLB upload |
|
|
22899
23822
|
|
|
22900
23823
|
### Dashboard Keys (for dashboard children)
|
|
22901
23824
|
|
|
@@ -22905,6 +23828,28 @@ In the **graph** page type, document references (embeds and links) create visibl
|
|
|
22905
23828
|
| \`deskZ\` | number | Z-index (layering) |
|
|
22906
23829
|
| \`deskMode\` | string | "icon", "widget-sm" (240×180), "widget-lg" (400×320) |
|
|
22907
23830
|
|
|
23831
|
+
### Sheets Cell Formatting (per-cell meta)
|
|
23832
|
+
|
|
23833
|
+
| Key | Type | Meaning |
|
|
23834
|
+
|-----|------|---------|
|
|
23835
|
+
| \`formula\` | string | Cell formula (e.g. "=A1+B1") |
|
|
23836
|
+
| \`bold\` | boolean | — |
|
|
23837
|
+
| \`italic\` | boolean | — |
|
|
23838
|
+
| \`textColor\` | string | CSS color |
|
|
23839
|
+
| \`bgColor\` | string | CSS color |
|
|
23840
|
+
| \`align\` | string | "left", "center", "right" |
|
|
23841
|
+
|
|
23842
|
+
### Coder Keys (for coder children — plugin)
|
|
23843
|
+
|
|
23844
|
+
| Key | Type | Meaning |
|
|
23845
|
+
|-----|------|---------|
|
|
23846
|
+
| \`fileType\` | string | "vue", "ts", "js", "css", "json", "folder" |
|
|
23847
|
+
| \`entry\` | boolean | Mark this file as the preview entry point |
|
|
23848
|
+
|
|
23849
|
+
### Discovering What Metadata Applies
|
|
23850
|
+
|
|
23851
|
+
Use the \`list_page_types\` tool to enumerate all known page types and their declared \`metaSchema\` (fields that apply to children/descendants) and \`defaultMetaFields\` (renderer config fields on the page itself). It's the authoritative list of what meta keys make sense for any given page type.
|
|
23852
|
+
|
|
22908
23853
|
---
|
|
22909
23854
|
|
|
22910
23855
|
## Content Structure
|
|
@@ -22987,8 +23932,11 @@ Always clear fields when done by setting them to \`null\`.
|
|
|
22987
23932
|
| **Outline** | \`outline:editing\` | nodeId | Editing an outline node |
|
|
22988
23933
|
| **Gallery** | \`gallery:focused\` | itemId | Item hovered/selected |
|
|
22989
23934
|
| **Timeline** | \`timeline:focused\` | taskId | Task selected |
|
|
22990
|
-
| **Mindmap** | \`mindmap:focused\` | nodeId | Node selected/edited |
|
|
22991
23935
|
| **Graph** | \`graph:focused\` | nodeId | Node hovered/selected |
|
|
23936
|
+
| **Slides** | \`slides:current\` | slideId | Slide being presented |
|
|
23937
|
+
| **Spatial** | \`spatial:selected\`, \`spatial:camera\` | objectId / camera state | plugin |
|
|
23938
|
+
| **Media** | \`media:playing\`, \`media:position\` | trackId / 0–1 | plugin |
|
|
23939
|
+
| **Coder** | \`coder:activeFile\` | fileId | plugin |
|
|
22992
23940
|
| **Map** | \`map:focused\` | markerId | Marker hovered/selected |
|
|
22993
23941
|
| **Doc** | \`doc:scroll\` | 0–1 number | Scroll position in document |
|
|
22994
23942
|
|
|
@@ -23331,6 +24279,9 @@ var HookBridge = class {
|
|
|
23331
24279
|
}
|
|
23332
24280
|
routeEvent(payload) {
|
|
23333
24281
|
switch (payload.hook_event_name) {
|
|
24282
|
+
case "UserPromptSubmit":
|
|
24283
|
+
this.onUserPromptSubmit();
|
|
24284
|
+
break;
|
|
23334
24285
|
case "PreToolUse":
|
|
23335
24286
|
this.onPreToolUse(payload);
|
|
23336
24287
|
break;
|
|
@@ -23341,13 +24292,18 @@ var HookBridge = class {
|
|
|
23341
24292
|
this.onSubagentStart(payload);
|
|
23342
24293
|
break;
|
|
23343
24294
|
case "SubagentStop":
|
|
23344
|
-
this.onSubagentStop(
|
|
24295
|
+
this.onSubagentStop();
|
|
23345
24296
|
break;
|
|
23346
24297
|
case "Stop":
|
|
23347
24298
|
this.onStop();
|
|
23348
24299
|
break;
|
|
23349
24300
|
}
|
|
23350
24301
|
}
|
|
24302
|
+
/** New user turn — reset any lingering status/tool state from the previous turn. */
|
|
24303
|
+
onUserPromptSubmit() {
|
|
24304
|
+
this.server.setAutoStatus(null);
|
|
24305
|
+
this.server.setActiveToolCall(null);
|
|
24306
|
+
}
|
|
23351
24307
|
onPreToolUse(payload) {
|
|
23352
24308
|
const toolName = payload.tool_name ?? "";
|
|
23353
24309
|
if (toolName.startsWith("mcp__abracadabra__")) return;
|
|
@@ -23359,7 +24315,6 @@ var HookBridge = class {
|
|
|
23359
24315
|
}
|
|
23360
24316
|
onPostToolUse(payload) {
|
|
23361
24317
|
if ((payload.tool_name ?? "").startsWith("mcp__abracadabra__")) return;
|
|
23362
|
-
this.server.setAutoStatus("thinking");
|
|
23363
24318
|
}
|
|
23364
24319
|
onSubagentStart(payload) {
|
|
23365
24320
|
const agentType = payload.agent_type ?? "agent";
|
|
@@ -23369,9 +24324,7 @@ var HookBridge = class {
|
|
|
23369
24324
|
});
|
|
23370
24325
|
this.server.setAutoStatus("thinking");
|
|
23371
24326
|
}
|
|
23372
|
-
onSubagentStop(
|
|
23373
|
-
this.server.setAutoStatus("thinking");
|
|
23374
|
-
}
|
|
24327
|
+
onSubagentStop() {}
|
|
23375
24328
|
onStop() {
|
|
23376
24329
|
this.server.setAutoStatus(null);
|
|
23377
24330
|
this.server.setActiveToolCall(null);
|
|
@@ -23384,11 +24337,19 @@ var HookBridge = class {
|
|
|
23384
24337
|
* Abracadabra MCP Server — entry point.
|
|
23385
24338
|
*
|
|
23386
24339
|
* Environment variables:
|
|
23387
|
-
* ABRA_URL
|
|
24340
|
+
* ABRA_URL (required) — Server URL (e.g. http://localhost:1234)
|
|
23388
24341
|
* ABRA_AGENT_NAME — Display name (default: "AI Assistant")
|
|
23389
24342
|
* ABRA_AGENT_COLOR — HSL color for presence (default: "hsl(270, 80%, 60%)")
|
|
23390
24343
|
* ABRA_INVITE_CODE — Invite code for first-run registration (grants role)
|
|
23391
24344
|
* ABRA_KEY_FILE — Path to Ed25519 key file (default: ~/.abracadabra/agent.key)
|
|
24345
|
+
* ABRA_AGENT_TRIGGER_MODE — When to respond in group chats:
|
|
24346
|
+
* all → every message (legacy)
|
|
24347
|
+
* mention → only when @<alias> is used
|
|
24348
|
+
* task → only ai:task awareness events
|
|
24349
|
+
* mention+task → mention OR ai:task (default)
|
|
24350
|
+
* DMs always trigger regardless of mode.
|
|
24351
|
+
* ABRA_AGENT_MENTION_ALIASES — Comma-separated aliases for @mentions
|
|
24352
|
+
* (default: [ABRA_AGENT_NAME])
|
|
23392
24353
|
*/
|
|
23393
24354
|
async function main() {
|
|
23394
24355
|
const url = process.env.ABRA_URL;
|
|
@@ -23396,13 +24357,27 @@ async function main() {
|
|
|
23396
24357
|
console.error("Missing required environment variable: ABRA_URL");
|
|
23397
24358
|
process.exit(1);
|
|
23398
24359
|
}
|
|
24360
|
+
const rawMode = (process.env.ABRA_AGENT_TRIGGER_MODE ?? "mention+task").trim().toLowerCase();
|
|
24361
|
+
const validModes = [
|
|
24362
|
+
"all",
|
|
24363
|
+
"mention",
|
|
24364
|
+
"task",
|
|
24365
|
+
"mention+task"
|
|
24366
|
+
];
|
|
24367
|
+
const triggerMode = validModes.includes(rawMode) ? rawMode : "mention+task";
|
|
24368
|
+
if (rawMode && !validModes.includes(rawMode)) console.error(`[abracadabra-mcp] Invalid ABRA_AGENT_TRIGGER_MODE="${rawMode}", falling back to "mention+task"`);
|
|
24369
|
+
const aliasEnv = process.env.ABRA_AGENT_MENTION_ALIASES;
|
|
24370
|
+
const mentionAliases = aliasEnv ? aliasEnv.split(",").map((a) => a.trim()).filter((a) => a.length > 0) : void 0;
|
|
23399
24371
|
const server = new AbracadabraMCPServer({
|
|
23400
24372
|
url,
|
|
23401
24373
|
agentName: process.env.ABRA_AGENT_NAME,
|
|
23402
24374
|
agentColor: process.env.ABRA_AGENT_COLOR,
|
|
23403
24375
|
inviteCode: process.env.ABRA_INVITE_CODE,
|
|
23404
|
-
keyFile: process.env.ABRA_KEY_FILE
|
|
24376
|
+
keyFile: process.env.ABRA_KEY_FILE,
|
|
24377
|
+
triggerMode,
|
|
24378
|
+
mentionAliases
|
|
23405
24379
|
});
|
|
24380
|
+
console.error(`[abracadabra-mcp] Trigger mode: ${triggerMode}; aliases: ${server.mentionAliases.join(", ")}`);
|
|
23406
24381
|
const mcp = new McpServer({
|
|
23407
24382
|
name: "abracadabra",
|
|
23408
24383
|
version: "1.0.0"
|