@abraca/mcp 1.0.12 → 1.0.18
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 +632 -113
- package/dist/abracadabra-mcp.cjs.map +1 -1
- package/dist/abracadabra-mcp.esm.js +631 -113
- package/dist/abracadabra-mcp.esm.js.map +1 -1
- package/dist/index.d.ts +24 -0
- package/package.json +1 -1
- package/src/converters/markdownToYjs.ts +52 -2
- package/src/converters/types.ts +54 -4
- package/src/converters/yjsToMarkdown.ts +5 -0
- package/src/hook-bridge.ts +204 -0
- package/src/index.ts +17 -1
- package/src/resources/agent-guide.ts +203 -92
- package/src/server.ts +114 -0
- package/src/tools/channel.ts +11 -0
- package/src/tools/content.ts +13 -1
- package/src/tools/hooks.ts +42 -0
- package/src/tools/meta.ts +1 -1
- package/src/tools/tree.ts +13 -2
package/src/tools/content.ts
CHANGED
|
@@ -17,6 +17,9 @@ export function registerContentTools(mcp: McpServer, server: AbracadabraMCPServe
|
|
|
17
17
|
},
|
|
18
18
|
async ({ docId }) => {
|
|
19
19
|
try {
|
|
20
|
+
server.setAutoStatus('reading', docId)
|
|
21
|
+
server.setActiveToolCall({ name: 'read_document', target: docId })
|
|
22
|
+
|
|
20
23
|
const provider = await server.getChildProvider(docId)
|
|
21
24
|
const fragment = provider.document.getXmlFragment('default')
|
|
22
25
|
|
|
@@ -48,6 +51,8 @@ export function registerContentTools(mcp: McpServer, server: AbracadabraMCPServe
|
|
|
48
51
|
children.sort((a: any, b: any) => ((treeMap.get(a.id)?.order ?? 0) - (treeMap.get(b.id)?.order ?? 0)))
|
|
49
52
|
}
|
|
50
53
|
|
|
54
|
+
server.setActiveToolCall(null)
|
|
55
|
+
|
|
51
56
|
const result: Record<string, unknown> = { label, type, meta, markdown, children }
|
|
52
57
|
return {
|
|
53
58
|
content: [{
|
|
@@ -56,6 +61,7 @@ export function registerContentTools(mcp: McpServer, server: AbracadabraMCPServe
|
|
|
56
61
|
}],
|
|
57
62
|
}
|
|
58
63
|
} catch (error: any) {
|
|
64
|
+
server.setActiveToolCall(null)
|
|
59
65
|
return {
|
|
60
66
|
content: [{ type: 'text', text: `Error reading document: ${error.message}` }],
|
|
61
67
|
isError: true,
|
|
@@ -66,7 +72,7 @@ export function registerContentTools(mcp: McpServer, server: AbracadabraMCPServe
|
|
|
66
72
|
|
|
67
73
|
mcp.tool(
|
|
68
74
|
'write_document',
|
|
69
|
-
'Write markdown content to a document. Parses the markdown and writes it to the Y.js CRDT document, which syncs in real-time to all connected clients. Supports optional YAML frontmatter for title and metadata.',
|
|
75
|
+
'Write markdown content to a document. Parses the markdown and writes it to the Y.js CRDT document, which syncs in real-time to all connected clients. Supports optional YAML frontmatter for title and metadata. Use ![[docId]] to embed another document as a block, or [[docId|label]] for inline doc links.',
|
|
70
76
|
{
|
|
71
77
|
docId: z.string().describe('Document ID to write to.'),
|
|
72
78
|
markdown: z.string().describe('Markdown content to write. Can include YAML frontmatter with title and metadata fields.'),
|
|
@@ -74,6 +80,9 @@ export function registerContentTools(mcp: McpServer, server: AbracadabraMCPServe
|
|
|
74
80
|
},
|
|
75
81
|
async ({ docId, markdown, mode }) => {
|
|
76
82
|
try {
|
|
83
|
+
server.setAutoStatus('writing', docId)
|
|
84
|
+
server.setActiveToolCall({ name: 'write_document', target: docId })
|
|
85
|
+
|
|
77
86
|
const writeMode = mode ?? 'replace'
|
|
78
87
|
const provider = await server.getChildProvider(docId)
|
|
79
88
|
const doc = provider.document
|
|
@@ -119,10 +128,13 @@ export function registerContentTools(mcp: McpServer, server: AbracadabraMCPServe
|
|
|
119
128
|
server.setFocusedDoc(docId)
|
|
120
129
|
server.setDocCursor(docId, fragment.length)
|
|
121
130
|
|
|
131
|
+
server.setActiveToolCall(null)
|
|
132
|
+
|
|
122
133
|
return {
|
|
123
134
|
content: [{ type: 'text', text: `Document ${docId} updated (${writeMode} mode)` }],
|
|
124
135
|
}
|
|
125
136
|
} catch (error: any) {
|
|
137
|
+
server.setActiveToolCall(null)
|
|
126
138
|
return {
|
|
127
139
|
content: [{ type: 'text', text: `Error writing document: ${error.message}` }],
|
|
128
140
|
isError: true,
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook tools — provides Claude Code hook configuration for activity bridging.
|
|
3
|
+
*/
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
5
|
+
import type { HookBridge } from '../hook-bridge.ts'
|
|
6
|
+
|
|
7
|
+
export function registerHookTools(mcp: McpServer, hookBridge: HookBridge) {
|
|
8
|
+
mcp.tool(
|
|
9
|
+
'get_hook_config',
|
|
10
|
+
'Returns Claude Code hook configuration JSON for bridging activity to the Abracadabra dashboard. Copy the "hooks" object into your .claude/settings.local.json to enable real-time activity indicators (tool calls, subagents, etc.) visible to all connected users.',
|
|
11
|
+
{},
|
|
12
|
+
async () => {
|
|
13
|
+
const port = hookBridge.port
|
|
14
|
+
if (!port) {
|
|
15
|
+
return {
|
|
16
|
+
content: [{ type: 'text', text: 'Hook bridge is not running.' }],
|
|
17
|
+
isError: true,
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const url = `http://127.0.0.1:${port}/hook`
|
|
22
|
+
const hookEntry = { type: 'http', url, timeout: 3 }
|
|
23
|
+
|
|
24
|
+
const config = {
|
|
25
|
+
hooks: {
|
|
26
|
+
PreToolUse: [{ hooks: [hookEntry] }],
|
|
27
|
+
PostToolUse: [{ hooks: [hookEntry] }],
|
|
28
|
+
SubagentStart: [{ hooks: [hookEntry] }],
|
|
29
|
+
SubagentStop: [{ hooks: [hookEntry] }],
|
|
30
|
+
Stop: [{ hooks: [hookEntry] }],
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
content: [{
|
|
36
|
+
type: 'text',
|
|
37
|
+
text: JSON.stringify(config, null, 2),
|
|
38
|
+
}],
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
)
|
|
42
|
+
}
|
package/src/tools/meta.ts
CHANGED
|
@@ -38,7 +38,7 @@ export function registerMetaTools(mcp: McpServer, server: AbracadabraMCPServer)
|
|
|
38
38
|
'Update metadata fields on a document. Merges the provided fields into existing metadata.',
|
|
39
39
|
{
|
|
40
40
|
docId: z.string().describe('Document ID.'),
|
|
41
|
-
meta: z.record(z.unknown()).describe('Metadata fields to update (merged with existing).
|
|
41
|
+
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, spColor, spOpacity (0-100). Dashboard: deskX, deskY, deskZ, deskMode ("icon"|"widget-sm"|"widget-lg"). Renderer config (on the page doc itself): kanbanColumnWidth, galleryColumns, galleryAspect, calendarView, calendarWeekStart, tableMode, showRefEdges. Set a key to null to clear it.'),
|
|
42
42
|
},
|
|
43
43
|
async ({ docId, meta }) => {
|
|
44
44
|
const treeMap = server.getTreeMap()
|
package/src/tools/tree.ts
CHANGED
|
@@ -182,13 +182,19 @@ export function registerTreeTools(mcp: McpServer, server: AbracadabraMCPServer)
|
|
|
182
182
|
{
|
|
183
183
|
parentId: z.string().optional().describe('Parent document ID. Omit for top-level pages. Use a document ID for nested/child pages.'),
|
|
184
184
|
label: z.string().describe('Display name / title for the document.'),
|
|
185
|
-
type: z.string().optional().describe('Page type
|
|
185
|
+
type: z.string().optional().describe('Page type — sets how this document renders. "doc" (rich text), "kanban" (columns → cards), "table" (columns → cells, positional rows), "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" (image/media items), "map" (markers/lines with geoLat/geoLng), "graph" (knowledge graph nodes), "dashboard" (positioned widgets with deskX/deskY/deskMode), "mindmap" (connected nodes), "spatial" (3D objects with spShape/spX/spY/spZ), "media" (audio/video tracks), "slides" (slide deck), "whiteboard" (freeform canvas). Omit to inherit parent view. Only set on the parent page, NEVER on child items.'),
|
|
186
186
|
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.'),
|
|
187
187
|
},
|
|
188
188
|
async ({ parentId, label, type, meta }) => {
|
|
189
|
+
server.setAutoStatus('creating')
|
|
190
|
+
server.setActiveToolCall({ name: 'create_document', target: label })
|
|
191
|
+
|
|
189
192
|
const treeMap = server.getTreeMap()
|
|
190
193
|
const rootDoc = server.rootDocument
|
|
191
|
-
if (!treeMap || !rootDoc)
|
|
194
|
+
if (!treeMap || !rootDoc) {
|
|
195
|
+
server.setActiveToolCall(null)
|
|
196
|
+
return { content: [{ type: 'text', text: 'Not connected' }] }
|
|
197
|
+
}
|
|
192
198
|
|
|
193
199
|
const id = crypto.randomUUID()
|
|
194
200
|
const normalizedParent = normalizeRootId(parentId, server)
|
|
@@ -205,6 +211,9 @@ export function registerTreeTools(mcp: McpServer, server: AbracadabraMCPServer)
|
|
|
205
211
|
})
|
|
206
212
|
})
|
|
207
213
|
|
|
214
|
+
server.setFocusedDoc(id)
|
|
215
|
+
server.setActiveToolCall(null)
|
|
216
|
+
|
|
208
217
|
return {
|
|
209
218
|
content: [{
|
|
210
219
|
type: 'text',
|
|
@@ -360,6 +369,8 @@ export function registerTreeTools(mcp: McpServer, server: AbracadabraMCPServer)
|
|
|
360
369
|
order: Date.now(),
|
|
361
370
|
})
|
|
362
371
|
|
|
372
|
+
server.setFocusedDoc(newId)
|
|
373
|
+
|
|
363
374
|
return {
|
|
364
375
|
content: [{
|
|
365
376
|
type: 'text',
|