@monnet/mcp 0.1.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.
Files changed (44) hide show
  1. package/README.md +67 -0
  2. package/dist/client.d.ts +23 -0
  3. package/dist/client.js +175 -0
  4. package/dist/client.js.map +1 -0
  5. package/dist/index.d.ts +9 -0
  6. package/dist/index.js +74 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/rendering/inbox.d.ts +18 -0
  9. package/dist/rendering/inbox.js +38 -0
  10. package/dist/rendering/inbox.js.map +1 -0
  11. package/dist/rendering/motion.d.ts +46 -0
  12. package/dist/rendering/motion.js +86 -0
  13. package/dist/rendering/motion.js.map +1 -0
  14. package/dist/tools/approve.d.ts +24 -0
  15. package/dist/tools/approve.js +40 -0
  16. package/dist/tools/approve.js.map +1 -0
  17. package/dist/tools/ask-monnet.d.ts +23 -0
  18. package/dist/tools/ask-monnet.js +42 -0
  19. package/dist/tools/ask-monnet.js.map +1 -0
  20. package/dist/tools/comment.d.ts +23 -0
  21. package/dist/tools/comment.js +41 -0
  22. package/dist/tools/comment.js.map +1 -0
  23. package/dist/tools/create-motion.d.ts +19 -0
  24. package/dist/tools/create-motion.js +41 -0
  25. package/dist/tools/create-motion.js.map +1 -0
  26. package/dist/tools/get-inbox.d.ts +22 -0
  27. package/dist/tools/get-inbox.js +56 -0
  28. package/dist/tools/get-inbox.js.map +1 -0
  29. package/dist/tools/get-motion.d.ts +19 -0
  30. package/dist/tools/get-motion.js +47 -0
  31. package/dist/tools/get-motion.js.map +1 -0
  32. package/dist/tools/list-motions.d.ts +31 -0
  33. package/dist/tools/list-motions.js +69 -0
  34. package/dist/tools/list-motions.js.map +1 -0
  35. package/dist/tools/reject.d.ts +28 -0
  36. package/dist/tools/reject.js +48 -0
  37. package/dist/tools/reject.js.map +1 -0
  38. package/dist/tools/update-motion.d.ts +64 -0
  39. package/dist/tools/update-motion.js +99 -0
  40. package/dist/tools/update-motion.js.map +1 -0
  41. package/dist/tools/whoami.d.ts +15 -0
  42. package/dist/tools/whoami.js +26 -0
  43. package/dist/tools/whoami.js.map +1 -0
  44. package/package.json +33 -0
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # @monnet/mcp
2
+
3
+ Model Context Protocol (MCP) server for Monnet.
4
+
5
+ Exposes motions, plans, and approvals to MCP-compatible clients (Claude Desktop, Cursor, etc.) so you can work with your Monnet workspace from your terminal without leaving your AI assistant.
6
+
7
+ ## Install
8
+
9
+ Add this to your MCP client config (e.g. `~/Library/Application Support/Claude/claude_desktop_config.json` for Claude Desktop):
10
+
11
+ ```json
12
+ {
13
+ "mcpServers": {
14
+ "monnet": {
15
+ "command": "npx",
16
+ "args": ["-y", "@monnet/mcp"],
17
+ "env": {
18
+ "MONNET_API_KEY": "mnk_..."
19
+ }
20
+ }
21
+ }
22
+ }
23
+ ```
24
+
25
+ Generate an API key from the Monnet web app: Settings โ†’ API Keys โ†’ Generate new key.
26
+
27
+ ## Environment variables
28
+
29
+ | Variable | Required | Default | Purpose |
30
+ |---|---|---|---|
31
+ | `MONNET_API_KEY` | yes | โ€” | Bearer token (`mnk_*`), sent as `X-API-Key` header on every request |
32
+ | `MONNET_API_URL` | no | `https://api.monnet.ai` | Override for self-hosted or local dev backends |
33
+
34
+ ## Local development
35
+
36
+ ```bash
37
+ cd mcp-server
38
+ npm install
39
+ npm run build
40
+ ```
41
+
42
+ Point your MCP client at the local build:
43
+
44
+ ```json
45
+ {
46
+ "mcpServers": {
47
+ "monnet": {
48
+ "command": "node",
49
+ "args": ["/absolute/path/to/mcp-server/dist/index.js"],
50
+ "env": {
51
+ "MONNET_API_KEY": "mnk_...",
52
+ "MONNET_API_URL": "http://localhost:8000"
53
+ }
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ Restart Claude Desktop / Cursor after editing the config.
60
+
61
+ ## Tools
62
+
63
+ Current scaffold ships with one tool for end-to-end validation:
64
+
65
+ - `monnet_whoami` โ€” verifies the MCP connection and lists the API keys on your account.
66
+
67
+ Additional tools (`get_motion`, `list_motions`, `create_motion`, `update_motion`, `comment`, `ask_monnet`, `get_inbox`, `approve`, `reject`) will follow as Phase 4 and 5 of the implementation plan.
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Thin HTTP client that wraps the Monnet backend with X-API-Key auth.
3
+ *
4
+ * Both env vars come from the MCP client's config JSON, not from a shell
5
+ * .env โ€” the MCP server is spawned by Claude Desktop / Cursor with this env.
6
+ */
7
+ export declare class MonnetApiError extends Error {
8
+ status: number;
9
+ constructor(status: number, message: string);
10
+ }
11
+ export declare function apiFetch<T>(path: string, options?: RequestInit): Promise<T>;
12
+ /**
13
+ * POST that may return SSE (when Monnet is triggered by the message).
14
+ *
15
+ * If the response is a normal JSON payload, returns the message content.
16
+ * If it's an SSE stream, consumes it and returns Monnet's final response text.
17
+ */
18
+ export declare function apiPostWithSSE(path: string, body: unknown): Promise<{
19
+ message: string;
20
+ monnetResponse: string | null;
21
+ }>;
22
+ export declare function resolveWorkspaceId(slug: string): Promise<string>;
23
+ export declare function getCurrentUserId(): Promise<string>;
package/dist/client.js ADDED
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Thin HTTP client that wraps the Monnet backend with X-API-Key auth.
3
+ *
4
+ * Both env vars come from the MCP client's config JSON, not from a shell
5
+ * .env โ€” the MCP server is spawned by Claude Desktop / Cursor with this env.
6
+ */
7
+ const MONNET_API_URL = (process.env.MONNET_API_URL || "https://api.monnet.ai").replace(/\/$/, "");
8
+ const MONNET_API_KEY = process.env.MONNET_API_KEY;
9
+ if (!MONNET_API_KEY) {
10
+ process.stderr.write("Error: MONNET_API_KEY environment variable is not set.\n" +
11
+ "Generate one at https://app.monnet.ai/settings and add it to your MCP client config.\n");
12
+ process.exit(1);
13
+ }
14
+ export class MonnetApiError extends Error {
15
+ status;
16
+ constructor(status, message) {
17
+ super(message);
18
+ this.status = status;
19
+ this.name = "MonnetApiError";
20
+ }
21
+ }
22
+ function friendlyMessage(status, detail) {
23
+ // Backend-supplied detail is always preferred for client errors that carry
24
+ // actionable info (permission denials, validation errors, not-found hints).
25
+ const fallback = detail ? `: ${detail}` : "";
26
+ switch (status) {
27
+ case 401:
28
+ return ("Your Monnet API key is invalid or has been revoked. " +
29
+ "Generate a new one in the Monnet web app under Settings โ†’ API Keys.");
30
+ case 403:
31
+ return `You don't have permission to perform this action${fallback}. Ask the workspace owner to add you as a member or bump your role.`;
32
+ case 404:
33
+ return `Not found${fallback}. Double-check the workspace slug or motion id.`;
34
+ case 409:
35
+ return `Conflict${fallback}.`;
36
+ case 422:
37
+ return `Invalid input${fallback}.`;
38
+ case 429:
39
+ return "Rate limited by the Monnet backend. Wait a moment and retry.";
40
+ case 500:
41
+ case 502:
42
+ case 503:
43
+ return "The Monnet backend is unavailable right now. Please retry in a moment.";
44
+ default:
45
+ return `Monnet API ${status}${fallback}`;
46
+ }
47
+ }
48
+ export async function apiFetch(path, options = {}) {
49
+ const response = await fetch(`${MONNET_API_URL}${path}`, {
50
+ ...options,
51
+ headers: {
52
+ "X-API-Key": MONNET_API_KEY,
53
+ "Content-Type": "application/json",
54
+ ...options.headers,
55
+ },
56
+ });
57
+ if (!response.ok) {
58
+ // FastAPI returns errors as {"detail": "..."} โ€” grab it if present,
59
+ // otherwise fall back to a generic message for this status.
60
+ let detail = null;
61
+ try {
62
+ const parsed = await response.json();
63
+ if (parsed && typeof parsed.detail === "string") {
64
+ detail = parsed.detail;
65
+ }
66
+ }
67
+ catch {
68
+ // Non-JSON body โ€” ignore.
69
+ }
70
+ throw new MonnetApiError(response.status, friendlyMessage(response.status, detail));
71
+ }
72
+ if (response.status === 204)
73
+ return undefined;
74
+ return (await response.json());
75
+ }
76
+ /**
77
+ * POST that may return SSE (when Monnet is triggered by the message).
78
+ *
79
+ * If the response is a normal JSON payload, returns the message content.
80
+ * If it's an SSE stream, consumes it and returns Monnet's final response text.
81
+ */
82
+ export async function apiPostWithSSE(path, body) {
83
+ const response = await fetch(`${MONNET_API_URL}${path}`, {
84
+ method: "POST",
85
+ headers: {
86
+ "X-API-Key": MONNET_API_KEY,
87
+ "Content-Type": "application/json",
88
+ },
89
+ body: JSON.stringify(body),
90
+ });
91
+ if (!response.ok) {
92
+ let detail = null;
93
+ try {
94
+ const parsed = await response.json();
95
+ if (parsed && typeof parsed.detail === "string")
96
+ detail = parsed.detail;
97
+ }
98
+ catch { /* ignore */ }
99
+ throw new MonnetApiError(response.status, friendlyMessage(response.status, detail));
100
+ }
101
+ const contentType = response.headers.get("content-type") || "";
102
+ // Non-streaming: Monnet didn't respond โ€” return the created message as-is
103
+ if (!contentType.includes("text/event-stream")) {
104
+ const data = await response.json();
105
+ return { message: data.content || JSON.stringify(data), monnetResponse: null };
106
+ }
107
+ // SSE stream: Monnet is responding. Consume the full stream and extract
108
+ // the final AI text from the "done" event.
109
+ if (!response.body)
110
+ throw new Error("Empty SSE response body");
111
+ const reader = response.body.getReader();
112
+ const decoder = new TextDecoder();
113
+ let buffer = "";
114
+ let monnetText = "";
115
+ let userMessage = "";
116
+ while (true) {
117
+ const { done, value } = await reader.read();
118
+ if (done)
119
+ break;
120
+ buffer += decoder.decode(value, { stream: true });
121
+ const events = buffer.split("\n\n");
122
+ buffer = events.pop() || "";
123
+ for (const rawEvent of events) {
124
+ const lines = rawEvent.split("\n");
125
+ let eventType = "message";
126
+ let data = "";
127
+ for (const line of lines) {
128
+ if (line.startsWith("event:"))
129
+ eventType = line.slice(6).trim();
130
+ else if (line.startsWith("data:"))
131
+ data += line.slice(5);
132
+ }
133
+ data = data.trim();
134
+ if (eventType === "user_message_saved" && data) {
135
+ try {
136
+ userMessage = JSON.parse(data).content || "";
137
+ }
138
+ catch { /* ignore */ }
139
+ }
140
+ if (eventType === "done" && data) {
141
+ try {
142
+ monnetText = JSON.parse(data).content || "";
143
+ }
144
+ catch { /* ignore */ }
145
+ }
146
+ }
147
+ }
148
+ return { message: userMessage, monnetResponse: monnetText || null };
149
+ }
150
+ /**
151
+ * Resolve a workspace slug to its workspace_id via GET /workspaces/by-slug/{slug}.
152
+ * Cached in-memory for the process lifetime (workspaces don't change often).
153
+ */
154
+ const _slugCache = new Map();
155
+ export async function resolveWorkspaceId(slug) {
156
+ const cached = _slugCache.get(slug);
157
+ if (cached)
158
+ return cached;
159
+ const ws = await apiFetch(`/workspaces/by-slug/${encodeURIComponent(slug)}`);
160
+ _slugCache.set(slug, ws.id);
161
+ return ws.id;
162
+ }
163
+ /**
164
+ * Return the current user's Clerk user_id (sub claim). Needed to construct
165
+ * the private channel identifier for ask_monnet.
166
+ */
167
+ let _cachedUserId = null;
168
+ export async function getCurrentUserId() {
169
+ if (_cachedUserId)
170
+ return _cachedUserId;
171
+ const me = await apiFetch("/me");
172
+ _cachedUserId = me.sub;
173
+ return me.sub;
174
+ }
175
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Monnet MCP server โ€” stdio transport.
4
+ *
5
+ * Launched as a subprocess by MCP clients (Claude Desktop, Cursor, etc.).
6
+ * Reads MONNET_API_KEY and MONNET_API_URL from the client's env and proxies
7
+ * each tool call to the Monnet backend.
8
+ */
9
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Monnet MCP server โ€” stdio transport.
4
+ *
5
+ * Launched as a subprocess by MCP clients (Claude Desktop, Cursor, etc.).
6
+ * Reads MONNET_API_KEY and MONNET_API_URL from the client's env and proxies
7
+ * each tool call to the Monnet backend.
8
+ */
9
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
10
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
12
+ import { handleWhoami, WHOAMI_TOOL_DEFINITION } from "./tools/whoami.js";
13
+ import { handleGetMotion, GET_MOTION_TOOL_DEFINITION } from "./tools/get-motion.js";
14
+ import { handleListMotions, LIST_MOTIONS_TOOL_DEFINITION } from "./tools/list-motions.js";
15
+ import { handleGetInbox, GET_INBOX_TOOL_DEFINITION } from "./tools/get-inbox.js";
16
+ import { handleCreateMotion, CREATE_MOTION_TOOL_DEFINITION } from "./tools/create-motion.js";
17
+ import { handleUpdateMotion, UPDATE_MOTION_TOOL_DEFINITION } from "./tools/update-motion.js";
18
+ import { handleComment, COMMENT_TOOL_DEFINITION } from "./tools/comment.js";
19
+ import { handleApprove, APPROVE_TOOL_DEFINITION } from "./tools/approve.js";
20
+ import { handleReject, REJECT_TOOL_DEFINITION } from "./tools/reject.js";
21
+ import { handleAskMonnet, ASK_MONNET_TOOL_DEFINITION } from "./tools/ask-monnet.js";
22
+ const TOOLS = [
23
+ WHOAMI_TOOL_DEFINITION,
24
+ GET_MOTION_TOOL_DEFINITION,
25
+ LIST_MOTIONS_TOOL_DEFINITION,
26
+ GET_INBOX_TOOL_DEFINITION,
27
+ CREATE_MOTION_TOOL_DEFINITION,
28
+ UPDATE_MOTION_TOOL_DEFINITION,
29
+ COMMENT_TOOL_DEFINITION,
30
+ APPROVE_TOOL_DEFINITION,
31
+ REJECT_TOOL_DEFINITION,
32
+ ASK_MONNET_TOOL_DEFINITION,
33
+ ];
34
+ const HANDLERS = {
35
+ monnet_whoami: handleWhoami,
36
+ get_motion: handleGetMotion,
37
+ list_motions: handleListMotions,
38
+ get_inbox: handleGetInbox,
39
+ create_motion: handleCreateMotion,
40
+ update_motion: handleUpdateMotion,
41
+ comment: handleComment,
42
+ approve: handleApprove,
43
+ reject: handleReject,
44
+ ask_monnet: handleAskMonnet,
45
+ };
46
+ const server = new Server({ name: "monnet", version: "0.1.0" }, { capabilities: { tools: {} } });
47
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
48
+ tools: TOOLS,
49
+ }));
50
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
51
+ const toolName = request.params.name;
52
+ const args = request.params.arguments ?? {};
53
+ const handler = HANDLERS[toolName];
54
+ if (!handler) {
55
+ return {
56
+ content: [{ type: "text", text: `Unknown tool: ${toolName}` }],
57
+ isError: true,
58
+ };
59
+ }
60
+ try {
61
+ const text = await handler(args);
62
+ return { content: [{ type: "text", text }] };
63
+ }
64
+ catch (err) {
65
+ const message = err instanceof Error ? err.message : String(err);
66
+ return {
67
+ content: [{ type: "text", text: `Error: ${message}` }],
68
+ isError: true,
69
+ };
70
+ }
71
+ });
72
+ const transport = new StdioServerTransport();
73
+ await server.connect(transport);
74
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ interface InboxMotion {
2
+ short_id: string;
3
+ summary: string;
4
+ status: string;
5
+ priority: string | null;
6
+ workspace: string;
7
+ workspace_slug: string;
8
+ last_activity: string | null;
9
+ last_activity_at: string | null;
10
+ is_unread: boolean;
11
+ }
12
+ interface InboxData {
13
+ total: number;
14
+ page: number;
15
+ motions: InboxMotion[];
16
+ }
17
+ export declare function renderInbox(data: InboxData): string;
18
+ export {};
@@ -0,0 +1,38 @@
1
+ function timeAgo(iso) {
2
+ if (!iso)
3
+ return "";
4
+ const diff = Date.now() - new Date(iso).getTime();
5
+ const minutes = Math.floor(diff / 60_000);
6
+ if (minutes < 1)
7
+ return "just now";
8
+ if (minutes < 60)
9
+ return `${minutes}m ago`;
10
+ const hours = Math.floor(minutes / 60);
11
+ if (hours < 24)
12
+ return `${hours}h ago`;
13
+ const days = Math.floor(hours / 24);
14
+ return `${days}d ago`;
15
+ }
16
+ export function renderInbox(data) {
17
+ const lines = [];
18
+ lines.push(`## ๐Ÿ“ฅ For You โ€” ${data.total} motion(s)`);
19
+ lines.push("");
20
+ if (data.motions.length === 0) {
21
+ lines.push("Nothing needs your attention right now.");
22
+ return lines.join("\n");
23
+ }
24
+ for (const m of data.motions) {
25
+ const unread = m.is_unread ? " ๐Ÿ”ต" : "";
26
+ const activity = m.last_activity
27
+ ? `${m.last_activity} ยท ${timeAgo(m.last_activity_at)}`
28
+ : "";
29
+ lines.push(`- \`${m.short_id}\` **${m.summary}** [${m.status}]${unread}`);
30
+ lines.push(` ${m.workspace}${activity ? ` ยท ${activity}` : ""}`);
31
+ }
32
+ if (data.total > data.motions.length) {
33
+ lines.push("");
34
+ lines.push(`_Page ${data.page} of ${Math.ceil(data.total / data.motions.length)}. Pass \`page\` to see more._`);
35
+ }
36
+ return lines.join("\n");
37
+ }
38
+ //# sourceMappingURL=inbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../src/rendering/inbox.ts"],"names":[],"mappings":"AAkBA,SAAS,OAAO,CAAC,GAAkB;IACjC,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IAC1C,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,UAAU,CAAC;IACnC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,OAAO,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,GAAG,KAAK,OAAO,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IACpC,OAAO,GAAG,IAAI,OAAO,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAe;IACzC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,KAAK,YAAY,CAAC,CAAC;IACtD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;QACtD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,CAAC,CAAC,aAAa;YAC9B,CAAC,CAAC,GAAG,CAAC,CAAC,aAAa,MAAM,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,EAAE;YACvD,CAAC,CAAC,EAAE,CAAC;QAEP,KAAK,CAAC,IAAI,CACR,OAAO,CAAC,CAAC,QAAQ,QAAQ,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,IAAI,MAAM,EAAE,CAC9D,CAAC;QACF,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,CAAC,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACtD,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CACR,SAAS,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,+BAA+B,CACpG,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,46 @@
1
+ interface PlanStep {
2
+ content: string;
3
+ status: string;
4
+ assignees?: string[];
5
+ approval?: boolean;
6
+ approved_by?: string[];
7
+ }
8
+ interface MotionDetail {
9
+ id: string;
10
+ summary: string;
11
+ status: string;
12
+ priority: string | null;
13
+ body: string | null;
14
+ plan: PlanStep[] | null;
15
+ author: string;
16
+ created_at: string;
17
+ updated_at: string;
18
+ workspace: string;
19
+ members: Array<{
20
+ name?: string;
21
+ role?: string;
22
+ function?: string | null;
23
+ }>;
24
+ motion_members: Array<{
25
+ user_id: string;
26
+ role: string;
27
+ }>;
28
+ }
29
+ export declare function renderMotionDetail(data: MotionDetail): string;
30
+ interface MotionListItem {
31
+ short_id: string;
32
+ summary: string;
33
+ status: string;
34
+ priority: string | null;
35
+ author: string;
36
+ updated_at: string;
37
+ }
38
+ interface MotionListData {
39
+ workspace_slug: string;
40
+ status: string;
41
+ page: number;
42
+ total: number;
43
+ motions: MotionListItem[];
44
+ }
45
+ export declare function renderMotionList(data: MotionListData): string;
46
+ export {};
@@ -0,0 +1,86 @@
1
+ const STATUS_ICONS = {
2
+ pending: "โณ",
3
+ in_progress: "๐Ÿ”„",
4
+ done: "โœ…",
5
+ };
6
+ const PRIORITY_DOTS = {
7
+ critical: "๐Ÿ”ด",
8
+ normal: "๐ŸŸข",
9
+ low: "โšช",
10
+ };
11
+ function formatDate(iso) {
12
+ return new Date(iso).toLocaleDateString("en-US", {
13
+ year: "numeric",
14
+ month: "short",
15
+ day: "numeric",
16
+ });
17
+ }
18
+ export function renderMotionDetail(data) {
19
+ const priority = data.priority || "normal";
20
+ const dot = PRIORITY_DOTS[priority] || "โšช";
21
+ const shortId = data.id.slice(0, 8);
22
+ const lines = [];
23
+ // Header
24
+ lines.push(`# ๐Ÿ“‹ ${data.summary}`);
25
+ lines.push("");
26
+ lines.push(`**Status:** ${data.status} ยท **Priority:** ${dot} ${priority} ยท **Space:** ${data.workspace}`);
27
+ lines.push(`**Author:** ${data.author} ยท **Created:** ${formatDate(data.created_at)} ยท **ID:** ${shortId}`);
28
+ // Body
29
+ if (data.body) {
30
+ lines.push("");
31
+ lines.push("---");
32
+ lines.push("");
33
+ lines.push(data.body);
34
+ }
35
+ // Plan
36
+ if (data.plan && data.plan.length > 0) {
37
+ lines.push("");
38
+ lines.push("---");
39
+ lines.push("");
40
+ lines.push("## Plan");
41
+ lines.push("");
42
+ data.plan.forEach((step, i) => {
43
+ const icon = STATUS_ICONS[step.status] || "โณ";
44
+ const assignees = step.assignees && step.assignees.length > 0
45
+ ? ` โ†’ ${step.assignees.map((a) => `@${a}`).join(", ")}`
46
+ : "";
47
+ const lock = step.approval ? " ๐Ÿ”’" : "";
48
+ const approved = step.approved_by && step.approved_by.length > 0
49
+ ? ` (approved by ${step.approved_by.join(", ")})`
50
+ : "";
51
+ lines.push(`${i + 1}. ${icon} ${step.content}${assignees}${lock}${approved}`);
52
+ });
53
+ }
54
+ // Members
55
+ if (data.members.length > 0) {
56
+ lines.push("");
57
+ lines.push("---");
58
+ lines.push("");
59
+ lines.push("## Members");
60
+ lines.push("");
61
+ for (const m of data.members) {
62
+ const fn = m.function ? ` (${m.function})` : "";
63
+ lines.push(`- **${m.name}** โ€” ${m.role}${fn}`);
64
+ }
65
+ }
66
+ return lines.join("\n");
67
+ }
68
+ export function renderMotionList(data) {
69
+ const lines = [];
70
+ lines.push(`## ${data.workspace_slug} โ€” ${data.total} ${data.status} motion(s)`);
71
+ lines.push("");
72
+ if (data.motions.length === 0) {
73
+ lines.push("No motions found.");
74
+ return lines.join("\n");
75
+ }
76
+ for (const m of data.motions) {
77
+ const dot = PRIORITY_DOTS[m.priority || "normal"] || "โšช";
78
+ lines.push(`- \`${m.short_id}\` ${dot} **${m.summary}** โ€” ${m.author}`);
79
+ }
80
+ if (data.total > data.motions.length) {
81
+ lines.push("");
82
+ lines.push(`_Page ${data.page} of ${Math.ceil(data.total / data.motions.length)}. Pass \`page\` to see more._`);
83
+ }
84
+ return lines.join("\n");
85
+ }
86
+ //# sourceMappingURL=motion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion.js","sourceRoot":"","sources":["../../src/rendering/motion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export declare function handleApprove(args: unknown): Promise<string>;
2
+ export declare const APPROVE_TOOL_DEFINITION: {
3
+ name: string;
4
+ description: string;
5
+ inputSchema: {
6
+ type: "object";
7
+ properties: {
8
+ workspace_slug: {
9
+ type: string;
10
+ description: string;
11
+ };
12
+ motion_short_id: {
13
+ type: string;
14
+ description: string;
15
+ };
16
+ step_index: {
17
+ type: string;
18
+ description: string;
19
+ minimum: number;
20
+ };
21
+ };
22
+ required: string[];
23
+ };
24
+ };
@@ -0,0 +1,40 @@
1
+ import { z } from "zod";
2
+ import { apiFetch, resolveWorkspaceId } from "../client.js";
3
+ const ApproveArgs = z.object({
4
+ workspace_slug: z.string().min(1),
5
+ motion_short_id: z.string().min(1),
6
+ step_index: z.number().int().min(0),
7
+ });
8
+ export async function handleApprove(args) {
9
+ const { workspace_slug, motion_short_id, step_index } = ApproveArgs.parse(args);
10
+ const wsId = await resolveWorkspaceId(workspace_slug);
11
+ const result = await apiFetch(`/workspaces/${wsId}/motions/${encodeURIComponent(motion_short_id)}/plan/steps/${step_index}/approve`, { method: "POST" });
12
+ return result.ok
13
+ ? `Step ${step_index} approved. Plan now has ${result.plan.length} step(s).`
14
+ : "Approval failed.";
15
+ }
16
+ export const APPROVE_TOOL_DEFINITION = {
17
+ name: "approve",
18
+ description: "Approve a plan step on a motion. Requires editor role on the motion. " +
19
+ "Use get_motion first to see the plan and identify the step_index (0-based).",
20
+ inputSchema: {
21
+ type: "object",
22
+ properties: {
23
+ workspace_slug: {
24
+ type: "string",
25
+ description: "The workspace slug.",
26
+ },
27
+ motion_short_id: {
28
+ type: "string",
29
+ description: "The first 8 characters of the motion UUID.",
30
+ },
31
+ step_index: {
32
+ type: "integer",
33
+ description: "0-based index of the plan step to approve.",
34
+ minimum: 0,
35
+ },
36
+ },
37
+ required: ["workspace_slug", "motion_short_id", "step_index"],
38
+ },
39
+ };
40
+ //# sourceMappingURL=approve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approve.js","sourceRoot":"","sources":["../../src/tools/approve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAE5D,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAClC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACpC,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAa;IAC/C,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChF,MAAM,IAAI,GAAG,MAAM,kBAAkB,CAAC,cAAc,CAAC,CAAC;IAEtD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAC3B,eAAe,IAAI,YAAY,kBAAkB,CAAC,eAAe,CAAC,eAAe,UAAU,UAAU,EACrG,EAAE,MAAM,EAAE,MAAM,EAAE,CACnB,CAAC;IAEF,OAAO,MAAM,CAAC,EAAE;QACd,CAAC,CAAC,QAAQ,UAAU,2BAA2B,MAAM,CAAC,IAAI,CAAC,MAAM,WAAW;QAC5E,CAAC,CAAC,kBAAkB,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,IAAI,EAAE,SAAS;IACf,WAAW,EACT,uEAAuE;QACvE,6EAA6E;IAC/E,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,cAAc,EAAE;gBACd,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,qBAAqB;aACnC;YACD,eAAe,EAAE;gBACf,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,4CAA4C;aAC1D;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,SAAS;gBACf,WAAW,EAAE,4CAA4C;gBACzD,OAAO,EAAE,CAAC;aACX;SACF;QACD,QAAQ,EAAE,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,YAAY,CAAC;KAC9D;CACF,CAAC"}