mcp-server-moscow 0.0.2 → 0.0.3
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.dev.md +10 -4
- package/dist/index.js +60 -4
- package/package.json +1 -1
package/README.dev.md
CHANGED
|
@@ -15,6 +15,8 @@ The server requires the following environment variables. You can set them in a `
|
|
|
15
15
|
|
|
16
16
|
- `SUPABASE_URL`: The URL of your Supabase project.
|
|
17
17
|
- `MCP_TOKEN` (Optional): A custom token for authorization if your Edge Functions require it.
|
|
18
|
+
- `TOPIC` (Optional): Default topic for filtering tasks.
|
|
19
|
+
- `BOARD_ID` (Optional): Default board ID for filtering and assigning tasks.
|
|
18
20
|
|
|
19
21
|
## Usage
|
|
20
22
|
|
|
@@ -34,7 +36,8 @@ Add the following to your MCP configuration file (e.g., `claude_desktop_config.j
|
|
|
34
36
|
"env": {
|
|
35
37
|
"SUPABASE_URL": "https://your-project.supabase.co",
|
|
36
38
|
"MCP_TOKEN": "mcp_123.....",
|
|
37
|
-
"TOPIC": "mcp"
|
|
39
|
+
"TOPIC": "mcp",
|
|
40
|
+
"BOARD_ID": "your-board-uuid"
|
|
38
41
|
},
|
|
39
42
|
"disabled": false
|
|
40
43
|
}
|
|
@@ -75,7 +78,10 @@ npx -y moscow-mcp-server
|
|
|
75
78
|
|
|
76
79
|
## Tools Provided
|
|
77
80
|
|
|
78
|
-
- `list_tasks`: List tasks from the Moscow project. Can be filtered by `topic`.
|
|
79
|
-
- `create_task`: Create a new task.
|
|
80
|
-
- `update_task`: Update an existing task.
|
|
81
|
+
- `list_tasks`: List tasks from the Moscow project. Can be filtered by `topic` or `board_id`.
|
|
82
|
+
- `create_task`: Create a new task. Supports `board_id` to assign to a board.
|
|
83
|
+
- `update_task`: Update an existing task. Supports `board_id` to move between boards.
|
|
81
84
|
- `delete_task`: Delete a task.
|
|
85
|
+
- `find_task`: Find a task by ID or name. Supports `board_id` filtering.
|
|
86
|
+
- `list_boards`: List all boards for the current user.
|
|
87
|
+
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ const __dirname = path.dirname(__filename);
|
|
|
12
12
|
dotenv.config({ path: path.resolve(__dirname, '../.env') });
|
|
13
13
|
const SUPABASE_URL = process.env.SUPABASE_URL || 'https://jnxbtfiwzaxwheifuhuf.supabase.co';
|
|
14
14
|
const DEFAULT_TOPIC = process.env.TOPIC || 'default';
|
|
15
|
+
const DEFAULT_BOARD_ID = process.env.BOARD_ID || undefined;
|
|
15
16
|
if (!SUPABASE_URL) {
|
|
16
17
|
console.error('Missing SUPABASE_URL environment variable');
|
|
17
18
|
process.exit(1);
|
|
@@ -25,12 +26,13 @@ const server = new Server({
|
|
|
25
26
|
},
|
|
26
27
|
});
|
|
27
28
|
const getEdgeFunctionUrl = () => `${SUPABASE_URL}/functions/v1/tasks`;
|
|
29
|
+
const getBoardsEdgeFunctionUrl = () => `${SUPABASE_URL}/functions/v1/boards`;
|
|
28
30
|
// Tool Handlers
|
|
29
31
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
30
32
|
tools: [
|
|
31
33
|
{
|
|
32
34
|
name: 'list_tasks',
|
|
33
|
-
description: 'List tasks for the current user and optionally filter by topic.',
|
|
35
|
+
description: 'List tasks for the current user and optionally filter by topic or board.',
|
|
34
36
|
inputSchema: {
|
|
35
37
|
type: 'object',
|
|
36
38
|
properties: {
|
|
@@ -38,6 +40,10 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
38
40
|
type: 'string',
|
|
39
41
|
description: 'Optional topic to filter tasks by.',
|
|
40
42
|
},
|
|
43
|
+
board_id: {
|
|
44
|
+
type: 'string',
|
|
45
|
+
description: 'Optional board ID to filter tasks by. Only tasks belonging to this board will be returned.',
|
|
46
|
+
},
|
|
41
47
|
},
|
|
42
48
|
},
|
|
43
49
|
},
|
|
@@ -69,6 +75,10 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
69
75
|
enum: ['TODO', 'IN_PROGRESS', 'DONE'],
|
|
70
76
|
description: 'The status of the task.',
|
|
71
77
|
},
|
|
78
|
+
board_id: {
|
|
79
|
+
type: 'string',
|
|
80
|
+
description: 'Optional board ID to assign the task to.',
|
|
81
|
+
},
|
|
72
82
|
},
|
|
73
83
|
required: ['title'],
|
|
74
84
|
},
|
|
@@ -105,6 +115,10 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
105
115
|
enum: ['TODO', 'IN_PROGRESS', 'DONE'],
|
|
106
116
|
description: 'The new status.',
|
|
107
117
|
},
|
|
118
|
+
board_id: {
|
|
119
|
+
type: 'string',
|
|
120
|
+
description: 'Move the task to a different board by providing the new board ID.',
|
|
121
|
+
},
|
|
108
122
|
},
|
|
109
123
|
required: ['id'],
|
|
110
124
|
},
|
|
@@ -141,9 +155,21 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
141
155
|
type: 'string',
|
|
142
156
|
description: 'Optional topic to narrow down the search scope.',
|
|
143
157
|
},
|
|
158
|
+
board_id: {
|
|
159
|
+
type: 'string',
|
|
160
|
+
description: 'Optional board ID to narrow down the search scope.',
|
|
161
|
+
},
|
|
144
162
|
},
|
|
145
163
|
},
|
|
146
164
|
},
|
|
165
|
+
{
|
|
166
|
+
name: 'list_boards',
|
|
167
|
+
description: 'List all boards for the current user. Useful for discovering available board IDs to filter or assign tasks.',
|
|
168
|
+
inputSchema: {
|
|
169
|
+
type: 'object',
|
|
170
|
+
properties: {},
|
|
171
|
+
},
|
|
172
|
+
},
|
|
147
173
|
],
|
|
148
174
|
}));
|
|
149
175
|
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
@@ -151,12 +177,17 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
151
177
|
const env = extra?.env || {};
|
|
152
178
|
const mcpToken = env.MCP_TOKEN || process.env.MCP_TOKEN;
|
|
153
179
|
const topicScope = request.params.arguments?.topic || env.TOPIC || DEFAULT_TOPIC;
|
|
180
|
+
const boardScope = request.params.arguments?.board_id || env.BOARD_ID || DEFAULT_BOARD_ID;
|
|
154
181
|
const authValue = mcpToken;
|
|
155
182
|
switch (request.params.name) {
|
|
156
183
|
case 'list_tasks': {
|
|
157
184
|
try {
|
|
185
|
+
const params = { topic: topicScope };
|
|
186
|
+
if (boardScope) {
|
|
187
|
+
params.board_id = boardScope;
|
|
188
|
+
}
|
|
158
189
|
const response = await axios.get(getEdgeFunctionUrl(), {
|
|
159
|
-
params
|
|
190
|
+
params,
|
|
160
191
|
headers: {
|
|
161
192
|
Authorization: `Bearer ${authValue}`,
|
|
162
193
|
},
|
|
@@ -178,7 +209,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
178
209
|
}
|
|
179
210
|
}
|
|
180
211
|
case 'create_task': {
|
|
181
|
-
const { title, description, topic, priority, status } = request.params.arguments || {};
|
|
212
|
+
const { title, description, topic, priority, status, board_id } = request.params.arguments || {};
|
|
182
213
|
try {
|
|
183
214
|
const response = await axios.post(getEdgeFunctionUrl(), {
|
|
184
215
|
title,
|
|
@@ -186,6 +217,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
186
217
|
topic: topic || topicScope,
|
|
187
218
|
priority,
|
|
188
219
|
status,
|
|
220
|
+
board_id: board_id || boardScope || null,
|
|
189
221
|
}, {
|
|
190
222
|
headers: {
|
|
191
223
|
Authorization: `Bearer ${authValue}`,
|
|
@@ -270,7 +302,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
270
302
|
}
|
|
271
303
|
}
|
|
272
304
|
case 'find_task': {
|
|
273
|
-
const { id, name, topic } = request.params.arguments ||
|
|
305
|
+
const { id, name, topic, board_id } = request.params.arguments ||
|
|
274
306
|
{};
|
|
275
307
|
if (!id && !name) {
|
|
276
308
|
return {
|
|
@@ -287,6 +319,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
287
319
|
...(id && { id }),
|
|
288
320
|
...(name && { name }),
|
|
289
321
|
...(topic && { topic }),
|
|
322
|
+
...(board_id && { board_id }),
|
|
290
323
|
},
|
|
291
324
|
headers: {
|
|
292
325
|
Authorization: `Bearer ${authValue}`,
|
|
@@ -324,6 +357,29 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
324
357
|
};
|
|
325
358
|
}
|
|
326
359
|
}
|
|
360
|
+
case 'list_boards': {
|
|
361
|
+
try {
|
|
362
|
+
const response = await axios.get(getBoardsEdgeFunctionUrl(), {
|
|
363
|
+
headers: {
|
|
364
|
+
Authorization: `Bearer ${authValue}`,
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
return {
|
|
368
|
+
content: [{ type: 'text', text: JSON.stringify(response.data, null, 2) }],
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
catch (error) {
|
|
372
|
+
const errorMessage = axios.isAxiosError(error)
|
|
373
|
+
? error.response?.data?.error || error.message
|
|
374
|
+
: error instanceof Error
|
|
375
|
+
? error.message
|
|
376
|
+
: String(error);
|
|
377
|
+
return {
|
|
378
|
+
content: [{ type: 'text', text: `Error listing boards: ${errorMessage}` }],
|
|
379
|
+
isError: true,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
}
|
|
327
383
|
default:
|
|
328
384
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
|
|
329
385
|
}
|