@abraca/mcp 1.1.0 → 1.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abraca/mcp",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "MCP server for Abracadabra — AI agent collaboration on CRDT documents",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -184,7 +184,10 @@ export class HookBridge {
184
184
  const toolName: string = payload.tool_name ?? ''
185
185
  if (toolName.startsWith('mcp__abracadabra__')) return
186
186
 
187
- this.server.setActiveToolCall(null)
187
+ // Don't clear activeToolCall — let it persist until the next PreToolUse
188
+ // replaces it or Stop clears everything. This prevents the status from
189
+ // flashing and vanishing between consecutive tool calls.
190
+ this.server.setAutoStatus('thinking')
188
191
  }
189
192
 
190
193
  private onSubagentStart(payload: Record<string, any>): void {
@@ -194,7 +197,8 @@ export class HookBridge {
194
197
  }
195
198
 
196
199
  private onSubagentStop(_payload: Record<string, any>): void {
197
- this.server.setActiveToolCall(null)
200
+ // Don't clear — let it persist until the next action or Stop
201
+ this.server.setAutoStatus('thinking')
198
202
  }
199
203
 
200
204
  private onStop(): void {
package/src/server.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import * as Y from 'yjs'
9
9
  import { AbracadabraProvider, AbracadabraClient } from '@abraca/dabra'
10
- import type { ServerInfo, SpaceMeta } from '@abraca/dabra'
10
+ import type { ServerInfo, SpaceMeta, DocumentMeta } from '@abraca/dabra'
11
11
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
12
12
  import type { Server } from '@modelcontextprotocol/sdk/server/index.js'
13
13
  import { waitForSync } from './utils.ts'
@@ -124,20 +124,35 @@ export class AbracadabraMCPServer {
124
124
  // Step 3: Discover server info
125
125
  this._serverInfo = await this.client.serverInfo()
126
126
 
127
- // Step 4: Discover spaces (optional extension)
127
+ // Step 4: Discover root documents (try new endpoint first, fall back to /spaces)
128
128
  let initialDocId: string | null = this._serverInfo.index_doc_id ?? null
129
129
  try {
130
- this._spaces = await this.client.listSpaces()
131
- const hub = this._spaces.find(s => s.is_hub)
130
+ const roots = await this.client.listRootDocuments()
131
+ // Map to SpaceMeta shape for backwards compat with list_spaces tool
132
+ this._spaces = roots.map(docToSpaceMeta)
133
+ const hub = roots.find(d => d.is_hub)
132
134
  if (hub) {
133
- initialDocId = hub.doc_id
134
- console.error(`[abracadabra-mcp] Spaces extension active. Hub space: ${hub.name} (${hub.doc_id})`)
135
- } else if (this._spaces.length > 0) {
136
- initialDocId = this._spaces[0].doc_id
137
- console.error(`[abracadabra-mcp] Spaces active but no hub, using first space: ${this._spaces[0].name} (${this._spaces[0].doc_id})`)
135
+ initialDocId = hub.id
136
+ console.error(`[abracadabra-mcp] Root documents discovered. Hub: ${hub.label ?? hub.id} (${hub.id})`)
137
+ } else if (roots.length > 0) {
138
+ initialDocId = roots[0].id
139
+ console.error(`[abracadabra-mcp] No hub, using first root doc: ${roots[0].label ?? roots[0].id} (${roots[0].id})`)
138
140
  }
139
141
  } catch {
140
- console.error('[abracadabra-mcp] Spaces extension not available, using index_doc_id')
142
+ // Fall back to legacy /spaces endpoint for older servers
143
+ try {
144
+ this._spaces = await this.client.listSpaces()
145
+ const hub = this._spaces.find(s => s.is_hub)
146
+ if (hub) {
147
+ initialDocId = hub.doc_id
148
+ console.error(`[abracadabra-mcp] Spaces extension active. Hub space: ${hub.name} (${hub.doc_id})`)
149
+ } else if (this._spaces.length > 0) {
150
+ initialDocId = this._spaces[0].doc_id
151
+ console.error(`[abracadabra-mcp] Spaces active but no hub, using first space: ${this._spaces[0].name} (${this._spaces[0].doc_id})`)
152
+ }
153
+ } catch {
154
+ console.error('[abracadabra-mcp] Neither /docs?root=true nor /spaces available, using index_doc_id')
155
+ }
141
156
  }
142
157
 
143
158
  if (!initialDocId) {
@@ -479,14 +494,15 @@ export class AbracadabraMCPServer {
479
494
  this._stopTypingInterval()
480
495
  }
481
496
 
482
- // Auto-clear status after 10s of no updates
497
+ // Auto-clear status after 30s of no updates (generous timeout so status
498
+ // persists visibly between consecutive tool calls instead of flickering)
483
499
  if (status) {
484
500
  this._statusClearTimer = setTimeout(() => {
485
501
  provider.awareness.setLocalStateField('status', null)
486
502
  provider.awareness.setLocalStateField('activeToolCall', null)
487
503
  provider.awareness.setLocalStateField('statusContext', null)
488
504
  this._stopTypingInterval()
489
- }, 10_000)
505
+ }, 30_000)
490
506
  }
491
507
  }
492
508
 
@@ -557,3 +573,23 @@ export class AbracadabraMCPServer {
557
573
  console.error('[abracadabra-mcp] Shutdown complete')
558
574
  }
559
575
  }
576
+
577
+ /** Map a DocumentMeta (from /docs?root=true) to the SpaceMeta shape for compat. */
578
+ function docToSpaceMeta(doc: DocumentMeta): SpaceMeta {
579
+ const publicAccess = doc.public_access
580
+ let visibility: SpaceMeta['visibility'] = 'private'
581
+ if (publicAccess && publicAccess !== 'none') visibility = 'public'
582
+
583
+ return {
584
+ id: doc.id,
585
+ doc_id: doc.id,
586
+ name: doc.label ?? doc.id,
587
+ description: doc.description ?? null,
588
+ visibility,
589
+ is_hub: doc.is_hub ?? false,
590
+ owner_id: doc.owner_id ?? null,
591
+ created_at: 0,
592
+ updated_at: doc.updated_at ?? 0,
593
+ public_access: publicAccess ?? null,
594
+ }
595
+ }