@live-context/mcp 0.4.0 → 0.7.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/README.md +9 -1
- package/dist/index.js +99 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,7 +40,15 @@ For Claude Desktop, Cursor, or any other MCP client, add this to your `mcpServer
|
|
|
40
40
|
|
|
41
41
|
## Tools
|
|
42
42
|
|
|
43
|
-
`get_context`, `list_spaces`, `list_collections`, `list_notebooks`, `list_context
|
|
43
|
+
**Read** — `get_context`, `list_spaces`, `list_collections`, `list_notebooks`, `list_context`
|
|
44
|
+
|
|
45
|
+
**Write** — `write_context` (knowledge → Spaces or Notebooks). Honors `write_mode='review_required'` Spaces: writes to those queue as proposals for admin approval. Pass `trigger_message` (min 10 chars) explaining why the write should be applied when targeting such a Space.
|
|
46
|
+
|
|
47
|
+
**Propose** *(v0.4.0+)* — `propose_space`, `propose_project`, `list_my_proposals`. Use these when the user asks for a new container. Both `propose_*` tools require a `trigger_message` (min 10 chars). Auto-approves when the caller is a team admin; otherwise queues for review at `live-context.com/dashboard/proposals`.
|
|
48
|
+
|
|
49
|
+
**Health** — `health_check`
|
|
50
|
+
|
|
51
|
+
See the [Live Context docs](https://live-context.com/docs) for full schemas and examples.
|
|
44
52
|
|
|
45
53
|
## Get a key
|
|
46
54
|
|
package/dist/index.js
CHANGED
|
@@ -91,7 +91,7 @@ async function callMcpApi(tool, args, method = 'POST') {
|
|
|
91
91
|
// ---------------------------------------------------------------------------
|
|
92
92
|
const server = new McpServer({
|
|
93
93
|
name: 'live-context-mcp',
|
|
94
|
-
version: '0.
|
|
94
|
+
version: '0.7.1', // 0.7.0 added body_tiptap; 0.7.1 adds width_mode (fixed | wide)
|
|
95
95
|
});
|
|
96
96
|
server.registerTool('get_context', {
|
|
97
97
|
description: 'Retrieve relevant context entries. Returns L0 summaries (title, type, snippet) by default. Pass drawer_id to get full page body.',
|
|
@@ -204,6 +204,19 @@ Use for time-bound work (launches, fundraises, redesigns). For ongoing knowledge
|
|
|
204
204
|
trigger_message: z.string().describe('Why this Project should exist (min 10 chars). Required.'),
|
|
205
205
|
},
|
|
206
206
|
}, (args) => callMcpApi('propose-project', args));
|
|
207
|
+
server.registerTool('propose_collection', {
|
|
208
|
+
description: `Propose a new Collection inside an existing Space — a grouping layer for related drawers (e.g. "Tokens" inside "design-system"). When the caller is a team admin of the Space's owner team, the proposal auto-approves and the Collection is created immediately. Otherwise it queues for admin review.
|
|
209
|
+
|
|
210
|
+
trigger_message is REQUIRED — explain WHY this Collection should exist (min 10 chars). Cite the drawers or topic that motivated it.
|
|
211
|
+
|
|
212
|
+
Use when several drawers in a Space cluster around a sub-topic that deserves its own grouping. For new top-level containers, use propose_space instead.`,
|
|
213
|
+
inputSchema: {
|
|
214
|
+
space_id: z.string().describe('Parent Space ID. Find via list_spaces.'),
|
|
215
|
+
name: z.string().describe('Collection name (e.g. "Tokens", "Migrations")'),
|
|
216
|
+
description: z.string().optional().describe('Short description of what goes in this Collection.'),
|
|
217
|
+
trigger_message: z.string().describe('Why this Collection should exist (min 10 chars). Required.'),
|
|
218
|
+
},
|
|
219
|
+
}, (args) => callMcpApi('propose-collection', args));
|
|
207
220
|
server.registerTool('list_my_proposals', {
|
|
208
221
|
description: 'List your proposals (Spaces + Projects you proposed) plus any proposals you can see based on team_visible setting. Filter by status.',
|
|
209
222
|
inputSchema: {
|
|
@@ -213,6 +226,91 @@ server.registerTool('list_my_proposals', {
|
|
|
213
226
|
.describe('Filter by proposal status.'),
|
|
214
227
|
},
|
|
215
228
|
}, (args) => callMcpApi('list-my-proposals', args));
|
|
229
|
+
server.registerTool('write_page', {
|
|
230
|
+
description: `Compose a Page — a human-readable, evidence-backed narrative document — into a Space or Notebook. Pages are how research, decisions, and synthesis get forwarded to other humans; drawers stay atomic for retrieval, Pages are the readable artifact.
|
|
231
|
+
|
|
232
|
+
When to use:
|
|
233
|
+
- The user asks to "write up", "summarise", "synthesise", "hand off", or "share with someone" a body of team knowledge.
|
|
234
|
+
- An empty Page draft exists (created from the dashboard) — fill it by passing page_id.
|
|
235
|
+
|
|
236
|
+
Body format — pick ONE:
|
|
237
|
+
|
|
238
|
+
1) body_tiptap (preferred — full formatting). A Tiptap document JSON tree. Top shape:
|
|
239
|
+
{ "type": "doc", "content": [...nodes] }
|
|
240
|
+
|
|
241
|
+
Block node types you can emit:
|
|
242
|
+
- paragraph: { "type": "paragraph", "content": [...inline] }
|
|
243
|
+
- heading: { "type": "heading", "attrs": { "level": 1|2|3|4 }, "content": [...inline] }
|
|
244
|
+
- bulletList / orderedList: { "type": "bulletList"|"orderedList", "content": [{ "type": "listItem", "content": [...blocks] }] }
|
|
245
|
+
- taskList: { "type": "taskList", "content": [{ "type": "taskItem", "attrs": { "checked": false }, "content": [...blocks] }] }
|
|
246
|
+
- blockquote: { "type": "blockquote", "content": [...blocks] }
|
|
247
|
+
- codeBlock: { "type": "codeBlock", "attrs": { "language": "ts" }, "content": [{ "type": "text", "text": "..." }] }
|
|
248
|
+
- horizontalRule: { "type": "horizontalRule" }
|
|
249
|
+
- table: { "type": "table", "attrs": { "width": "inline"|"wide"|"full" }, "content": [{ "type": "tableRow", "content": [{ "type": "tableHeader"|"tableCell", "content": [...blocks] }] }] }
|
|
250
|
+
- details (collapsible / Confluence Expand): { "type": "details", "content": [{ "type": "detailsSummary", "content": [...inline] }, { "type": "detailsContent", "content": [...blocks] }] }
|
|
251
|
+
|
|
252
|
+
Inline node types:
|
|
253
|
+
- text: { "type": "text", "text": "string", "marks": [...] }
|
|
254
|
+
- hardBreak: { "type": "hardBreak" }
|
|
255
|
+
- drawerCitation (clickable evidence chip — use these to ground claims!): { "type": "drawerCitation", "attrs": { "drawerId": "<uuid>", "drawerTitle": "<title>", "drawerType": "decision|constraint|..." } }
|
|
256
|
+
- mention (person): { "type": "mention", "attrs": { "id": "<user_uuid>", "label": "Display Name" } }
|
|
257
|
+
|
|
258
|
+
Marks (applied to text nodes via the "marks" array):
|
|
259
|
+
- bold, italic, underline, strike, code
|
|
260
|
+
- highlight: { "type": "highlight" }
|
|
261
|
+
- subscript, superscript
|
|
262
|
+
- link: { "type": "link", "attrs": { "href": "https://..." } }
|
|
263
|
+
- textAlign: paragraphs and headings accept "attrs": { "textAlign": "left"|"center"|"right" }
|
|
264
|
+
|
|
265
|
+
Use drawerCitation inline anywhere you would cite. The server auto-extracts cited drawer_ids from your doc and snapshots each drawer's body so the Page stays interpretable even if drawers later change. You do NOT need to also pass "citations" — extraction is automatic.
|
|
266
|
+
|
|
267
|
+
2) body_markdown (legacy — limited). Markdown string. Supports headings, paragraphs, lists, blockquote, code blocks, bold/italic/strike, links, inline code, horizontal rule. Does NOT support tables, details, mentions, highlight, alignment, underline. Use \`[[drawer:<uuid>|<title>]]\` inline for citations. Prefer body_tiptap.
|
|
268
|
+
|
|
269
|
+
Always retrieve evidence with get_context first; never compose from training data when team knowledge exists.`,
|
|
270
|
+
inputSchema: {
|
|
271
|
+
title: z.string().describe('Page title — short, descriptive, sentence case.'),
|
|
272
|
+
body_tiptap: z
|
|
273
|
+
.object({
|
|
274
|
+
type: z.literal('doc'),
|
|
275
|
+
content: z.array(z.any()).optional(),
|
|
276
|
+
})
|
|
277
|
+
.passthrough()
|
|
278
|
+
.optional()
|
|
279
|
+
.describe('Preferred. Tiptap document JSON — see tool description for full node + mark schema.'),
|
|
280
|
+
body_markdown: z
|
|
281
|
+
.string()
|
|
282
|
+
.optional()
|
|
283
|
+
.describe('Legacy fallback. Markdown subset (no tables, details, mentions). Prefer body_tiptap.'),
|
|
284
|
+
scope: z.enum(['team', 'personal']).optional().describe("'team' (default — writes to a Space) or 'personal' (writes to a Notebook; requires user token)."),
|
|
285
|
+
space: z.string().optional().describe('Target Space name (required for team scope).'),
|
|
286
|
+
notebook: z.string().optional().describe('Target Notebook name (required for personal scope).'),
|
|
287
|
+
page_id: z.string().optional().describe('If filling an existing empty draft, the draft id. Else omit to create new.'),
|
|
288
|
+
citations: z
|
|
289
|
+
.array(z.object({ drawer_id: z.string() }))
|
|
290
|
+
.optional()
|
|
291
|
+
.describe('Optional. If body_tiptap is passed, citations auto-extract from drawerCitation nodes. Pass explicitly only to attribute drawers that don\'t appear inline.'),
|
|
292
|
+
width_mode: z
|
|
293
|
+
.enum(['fixed', 'wide'])
|
|
294
|
+
.optional()
|
|
295
|
+
.describe("Optional. 'fixed' (default, ~768px reading width) or 'wide' (~1024px). Use 'wide' for pages dominated by tables, wide code blocks, or side-by-side comparisons. Matches Confluence's per-page Full-width toggle."),
|
|
296
|
+
},
|
|
297
|
+
}, (args) => callMcpApi('write-page', args));
|
|
298
|
+
server.registerTool('list_pages', {
|
|
299
|
+
description: 'List Pages in the team or in a specific Space/Notebook. Returns title + container + updated_at. Use get_page for full body and citations.',
|
|
300
|
+
inputSchema: {
|
|
301
|
+
scope: z.enum(['team', 'personal', 'all']).optional().describe("Default 'all'. 'team' = Space pages; 'personal' = Notebook pages."),
|
|
302
|
+
space: z.string().optional().describe('Filter by Space name.'),
|
|
303
|
+
notebook: z.string().optional().describe('Filter by Notebook name (requires user token).'),
|
|
304
|
+
limit: z.number().int().positive().max(100).optional().describe('Page size (default 20, max 100).'),
|
|
305
|
+
offset: z.number().int().min(0).optional().describe('Pagination offset (default 0).'),
|
|
306
|
+
},
|
|
307
|
+
}, (args) => callMcpApi('list-pages', args));
|
|
308
|
+
server.registerTool('get_page', {
|
|
309
|
+
description: 'Fetch a Page by id. Returns title, body_json (Tiptap doc), container, and citations enriched with current drawer title/type. Use this before re-composing so you can show what already exists.',
|
|
310
|
+
inputSchema: {
|
|
311
|
+
page_id: z.string().describe('Page id (from list_pages or write_page result).'),
|
|
312
|
+
},
|
|
313
|
+
}, (args) => callMcpApi('get-page', args));
|
|
216
314
|
server.registerTool('health_check', {
|
|
217
315
|
description: 'Returns server health status and resolved team identity',
|
|
218
316
|
}, () => callMcpApi('health-check', undefined, 'GET'));
|
package/package.json
CHANGED