aixischeck-mcp 0.1.0 → 0.3.0
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 +11 -0
- package/dist/index.js +64 -3
- package/dist/lib.js +25 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,17 @@ upload. Generate an HTML one-pager in chat, and it lands in your workspace, rend
|
|
|
10
10
|
- **`create_doc`** — `{ workspace_id, title?, content, doc_type? }`. Creates a doc and
|
|
11
11
|
returns its URL. `doc_type` defaults to `"html"` (a rendered prototype); pass
|
|
12
12
|
`"markdown"` for a markdown doc.
|
|
13
|
+
- **`list_docs`** — `{ workspace_id }`. Lists docs in a workspace you belong to
|
|
14
|
+
(`id`, `title`, `doc_type`, `doc_status`, `updated_at`, open `comment_count`).
|
|
15
|
+
- **`get_doc`** — `{ doc_id }`. Reads one doc's `content`, `doc_status`,
|
|
16
|
+
`current_version`, and section list.
|
|
17
|
+
- **`list_comments`** — `{ doc_id, filter? }`. Lists review comments; `filter:"open"`
|
|
18
|
+
returns just the active ones to address (else `{ active, archived }`).
|
|
19
|
+
- **`update_doc`** — `{ doc_id, content, request_id, comment_dispositions? }`. Saves a
|
|
20
|
+
revised version that addresses a revision request's comments. Lands as a NEW version
|
|
21
|
+
(base_version derived from the request); records what was done with each comment
|
|
22
|
+
(incorporated / partial / skipped / not_addressed). The write-back to Postgres is one
|
|
23
|
+
atomic RPC (concurrency + idempotency guaranteed).
|
|
13
24
|
|
|
14
25
|
## Setup
|
|
15
26
|
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// AIXIS_URL — Supabase project URL, e.g. https://<ref>.supabase.co
|
|
13
13
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
14
14
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
15
|
-
import { buildCreateDocBody, createDocShape, edgeErrorMessage, functionUrl } from "./lib.js";
|
|
15
|
+
import { buildCreateDocBody, createDocShape, edgeErrorMessage, functionUrl, getDocShape, listCommentsShape, listDocsShape, updateDocShape, } from "./lib.js";
|
|
16
16
|
const AIXIS_TOKEN = process.env.AIXIS_TOKEN ?? "";
|
|
17
17
|
const AIXIS_URL = process.env.AIXIS_URL ?? "";
|
|
18
18
|
if (!AIXIS_TOKEN || !AIXIS_URL) {
|
|
@@ -43,7 +43,7 @@ function errorResult(e) {
|
|
|
43
43
|
const message = e instanceof Error ? e.message : String(e);
|
|
44
44
|
return { content: [{ type: "text", text: message }], isError: true };
|
|
45
45
|
}
|
|
46
|
-
const server = new McpServer({ name: "aixischeck-mcp", version: "0.
|
|
46
|
+
const server = new McpServer({ name: "aixischeck-mcp", version: "0.3.0" });
|
|
47
47
|
server.registerTool("list_workspaces", {
|
|
48
48
|
description: "List the AIxisCheck workspaces you can write to. Returns each workspace's id, name, and your role. Call this first to get a workspace_id for create_doc.",
|
|
49
49
|
inputSchema: {},
|
|
@@ -58,16 +58,77 @@ server.registerTool("list_workspaces", {
|
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
server.registerTool("create_doc", {
|
|
61
|
-
description: "Create a document in an AIxisCheck workspace from generated content. Defaults to an HTML prototype (doc_type='html'); pass doc_type='markdown' for a markdown doc. Use list_workspaces first to get a workspace_id. Returns the URL of the new doc.",
|
|
61
|
+
description: "Create a document in an AIxisCheck workspace from generated content. Defaults to an HTML prototype (doc_type='html'); pass doc_type='markdown' for a markdown doc. Pass a short, human-readable `title` (e.g. \"Q3 Launch One-Pager\"), not a filename. Use list_workspaces first to get a workspace_id. Returns the URL of the new doc.",
|
|
62
62
|
inputSchema: createDocShape,
|
|
63
63
|
}, async (args) => {
|
|
64
64
|
try {
|
|
65
65
|
const data = await callEdge("mcp-create-doc", "POST", buildCreateDocBody(args));
|
|
66
|
+
if (!data || !data.url)
|
|
67
|
+
throw new Error("Doc creation returned an unexpected response.");
|
|
66
68
|
return { content: [{ type: "text", text: `Created. View it at ${data.url}` }] };
|
|
67
69
|
}
|
|
68
70
|
catch (e) {
|
|
69
71
|
return errorResult(e);
|
|
70
72
|
}
|
|
71
73
|
});
|
|
74
|
+
server.registerTool("list_docs", {
|
|
75
|
+
description: "List the documents in an AIxisCheck workspace you belong to. Returns each doc's id, title, doc_type, doc_status, updated_at, and open comment_count. Use list_workspaces first to get a workspace_id.",
|
|
76
|
+
inputSchema: listDocsShape,
|
|
77
|
+
}, async (args) => {
|
|
78
|
+
try {
|
|
79
|
+
const data = await callEdge("mcp-read", "POST", { action: "list_docs", workspace_id: args.workspace_id });
|
|
80
|
+
return { content: [{ type: "text", text: JSON.stringify(data?.docs ?? data, null, 2) }] };
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
return errorResult(e);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
server.registerTool("get_doc", {
|
|
87
|
+
description: "Read one AIxisCheck document: its content (HTML or markdown), doc_status, current_version, and section list. Pass the doc_id from list_docs. current_version is the value to echo as base_version when revising via update_doc.",
|
|
88
|
+
inputSchema: getDocShape,
|
|
89
|
+
}, async (args) => {
|
|
90
|
+
try {
|
|
91
|
+
const data = await callEdge("mcp-read", "POST", { action: "get_doc", doc_id: args.doc_id });
|
|
92
|
+
return { content: [{ type: "text", text: JSON.stringify(data?.doc ?? data, null, 2) }] };
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
return errorResult(e);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
server.registerTool("list_comments", {
|
|
99
|
+
description: "List the review comments on an AIxisCheck document. Pass filter:'open' for just the active (non-archived) comments to address; default returns { active, archived }. Each comment has id, selectedText, and note.",
|
|
100
|
+
inputSchema: listCommentsShape,
|
|
101
|
+
}, async (args) => {
|
|
102
|
+
try {
|
|
103
|
+
const data = await callEdge("mcp-read", "POST", { action: "list_comments", doc_id: args.doc_id, filter: args.filter });
|
|
104
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
return errorResult(e);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
server.registerTool("update_doc", {
|
|
111
|
+
description: "Save a revised version of an AIxisCheck doc that addresses a revision request's comments. Pass: doc_id; content (the FULL revised doc); request_id (from the user's 'Send to Claude' prompt); and comment_dispositions recording what you did with each comment (outcome: incorporated | partial | skipped | not_addressed, plus a short rationale). The revision lands as a NEW version (base_version is derived from the request). Returns the new version number. If you get a conflict, call get_doc again and retry.",
|
|
112
|
+
inputSchema: updateDocShape,
|
|
113
|
+
}, async (args) => {
|
|
114
|
+
try {
|
|
115
|
+
const data = await callEdge("mcp-update-doc", "POST", {
|
|
116
|
+
doc_id: args.doc_id,
|
|
117
|
+
content: args.content,
|
|
118
|
+
request_id: args.request_id,
|
|
119
|
+
comment_dispositions: args.comment_dispositions ?? [],
|
|
120
|
+
});
|
|
121
|
+
const v = data?.version_number;
|
|
122
|
+
return {
|
|
123
|
+
content: [{
|
|
124
|
+
type: "text",
|
|
125
|
+
text: v ? `Saved as v${v}.` + (data?.idempotent ? " (already applied)" : "") : `Saved. ${JSON.stringify(data)}`,
|
|
126
|
+
}],
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
return errorResult(e);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
72
133
|
const transport = new StdioServerTransport();
|
|
73
134
|
await server.connect(transport);
|
package/dist/lib.js
CHANGED
|
@@ -11,11 +11,35 @@ export function functionUrl(baseUrl, name) {
|
|
|
11
11
|
// it to 'html' (the Shaed prototype-capture flow).
|
|
12
12
|
export const createDocShape = {
|
|
13
13
|
workspace_id: z.string().min(1, "workspace_id is required"),
|
|
14
|
-
title: z.string().optional(),
|
|
14
|
+
title: z.string().optional().describe("A short, human-readable title for the doc, e.g. \"Q3 Launch One-Pager\" — NOT a filename or slug."),
|
|
15
15
|
content: z.string().min(1, "content is required"),
|
|
16
16
|
doc_type: z.enum(["html", "markdown"]).optional(),
|
|
17
17
|
};
|
|
18
18
|
export const CreateDocSchema = z.object(createDocShape);
|
|
19
|
+
// Read-tool input shapes (Phase 3a). The tools call the mcp-read edge
|
|
20
|
+
// function with an `action` discriminator; these validate the client args.
|
|
21
|
+
export const listDocsShape = {
|
|
22
|
+
workspace_id: z.string().min(1, "workspace_id is required"),
|
|
23
|
+
};
|
|
24
|
+
export const getDocShape = {
|
|
25
|
+
doc_id: z.string().min(1, "doc_id is required"),
|
|
26
|
+
};
|
|
27
|
+
export const listCommentsShape = {
|
|
28
|
+
doc_id: z.string().min(1, "doc_id is required"),
|
|
29
|
+
filter: z.enum(["open", "all"]).optional().describe("'open' returns only active (non-archived) comments; default returns { active, archived }."),
|
|
30
|
+
};
|
|
31
|
+
// update_doc (Phase 3a, slice 2): the write-back. base_version is NOT a param —
|
|
32
|
+
// it is derived from the revision request server-side (the caller can't move it).
|
|
33
|
+
export const updateDocShape = {
|
|
34
|
+
doc_id: z.string().min(1, "doc_id is required"),
|
|
35
|
+
content: z.string().min(1, "content is required (the full revised doc)"),
|
|
36
|
+
request_id: z.string().min(1, "request_id is required (from the Send-to-Claude prompt)"),
|
|
37
|
+
comment_dispositions: z.array(z.object({
|
|
38
|
+
comment_id: z.string(),
|
|
39
|
+
outcome: z.enum(["incorporated", "partial", "skipped", "not_addressed"]),
|
|
40
|
+
rationale: z.string().optional(),
|
|
41
|
+
})).optional().describe("What you did with each comment you addressed. Any requested comment you omit is recorded as not_addressed."),
|
|
42
|
+
};
|
|
19
43
|
// Shape the POST body for the mcp-create-doc edge function, applying
|
|
20
44
|
// the doc_type='html' default and normalizing an absent title to ''.
|
|
21
45
|
export function buildCreateDocBody(input) {
|