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 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: { topic: topicScope },
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-server-moscow",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "type": "module",
5
5
  "description": "MCP for Moscow task management",
6
6
  "main": "dist/index.js",