dueey-mcp 1.0.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 (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +97 -0
  3. package/dist/index.js +231 -0
  4. package/package.json +31 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gregory Murphy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # Dueey MCP Server
2
+
3
+ MCP server for the [Dueey](https://dueey.com) PM Assistant public API.
4
+ Exposes boards, lists, cards, and exports as MCP tools for Claude and other AI clients.
5
+
6
+ ## Setup
7
+
8
+ ### Option A: Install from npm
9
+
10
+ ```bash
11
+ npm install -g dueey-mcp
12
+ # or use with npx: npx dueey-mcp
13
+ ```
14
+
15
+ ### Option B: Install from source
16
+
17
+ ```bash
18
+ npm install
19
+ npm run build
20
+ ```
21
+
22
+ ### 2. Get your API key
23
+
24
+ In Dueey: **Settings → API Access** → generate a token (starts with `pm_...`).
25
+
26
+ ### 3. Add to your AI client
27
+
28
+ #### Claude Desktop
29
+
30
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or
31
+ `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
32
+
33
+ ```json
34
+ {
35
+ "mcpServers": {
36
+ "dueey": {
37
+ "command": "node",
38
+ "args": ["/path/to/dueey-mcp/dist/index.js"],
39
+ "env": {
40
+ "DUEEY_API_KEY": "pm_your_token_here"
41
+ }
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ Restart Claude Desktop.
48
+
49
+ #### Cursor
50
+
51
+ Add the server in **Cursor Settings → Features → MCP** (or your project’s `.cursor/mcp.json`). Example:
52
+
53
+ ```json
54
+ {
55
+ "mcpServers": {
56
+ "dueey": {
57
+ "command": "node",
58
+ "args": ["/path/to/dueey-mcp/dist/index.js"],
59
+ "env": {
60
+ "DUEEY_API_KEY": "pm_your_token_here"
61
+ }
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ If you installed globally (`npm install -g dueey-mcp`), use the path from `npm root -g` (e.g. `"args": ["/usr/local/lib/node_modules/dueey-mcp/dist/index.js"]`) or use `npx`: `"command": "npx", "args": ["dueey-mcp"]` and keep `env` as above.
68
+
69
+ #### Other clients
70
+
71
+ Any client that supports MCP over stdio (e.g. Windsurf, Continue, custom setups) can use this server: run `node /path/to/dist/index.js` with `DUEEY_API_KEY` set in the environment and point the client at that process.
72
+
73
+ ---
74
+
75
+ ## Available Tools
76
+
77
+ | Tool | Description |
78
+ |------|-------------|
79
+ | `get_me` | Current authenticated user |
80
+ | `list_boards` | All boards (optional `workspaceId` filter) |
81
+ | `get_board` | Single board by ID or slug |
82
+ | `list_lists` | Lists/columns for a board |
83
+ | `list_cards` | Cards filtered by board or list |
84
+ | `get_card` | Single card by UUID or cardKey (e.g. `SWAT-42`) |
85
+ | `create_card` | Create a card with title, description, priority, labels, dates, checklist |
86
+ | `update_card` | Update any card field; use `listId` to move a card |
87
+ | `get_data` | Full export — all workspaces, boards, lists, cards |
88
+
89
+ ---
90
+
91
+ ## Example prompts
92
+
93
+ - *"Show me all my Dueey boards"*
94
+ - *"List the cards in my Roadmap board"*
95
+ - *"Create a high-priority card called 'Fix login bug' in my Backlog list"*
96
+ - *"Move card SWAT-12 to the Done column"*
97
+ - *"Export all my data from Dueey"*
package/dist/index.js ADDED
@@ -0,0 +1,231 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, ErrorCode, McpError, } from "@modelcontextprotocol/sdk/types.js";
5
+ const BASE_URL = "https://dueey.com/api/v1";
6
+ const API_KEY = process.env.DUEEY_API_KEY ?? "";
7
+ if (!API_KEY) {
8
+ console.error("Error: DUEEY_API_KEY environment variable is required.");
9
+ process.exit(1);
10
+ }
11
+ async function dueeyFetch(path, options = {}) {
12
+ const { params, ...fetchOptions } = options;
13
+ const url = new URL(`${BASE_URL}${path}`);
14
+ if (params) {
15
+ for (const [k, v] of Object.entries(params)) {
16
+ if (v !== undefined)
17
+ url.searchParams.set(k, String(v));
18
+ }
19
+ }
20
+ const res = await fetch(url.toString(), {
21
+ ...fetchOptions,
22
+ headers: {
23
+ Authorization: `Bearer ${API_KEY}`,
24
+ "Content-Type": "application/json",
25
+ ...(fetchOptions.headers ?? {}),
26
+ },
27
+ });
28
+ if (!res.ok) {
29
+ const text = await res.text().catch(() => "");
30
+ throw new McpError(ErrorCode.InternalError, `Dueey API error ${res.status}: ${text || res.statusText}`);
31
+ }
32
+ return res.json();
33
+ }
34
+ const server = new Server({ name: "dueey-mcp", version: "1.0.0" }, { capabilities: { tools: {} } });
35
+ // ─── Tool Definitions ────────────────────────────────────────────────────────
36
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
37
+ tools: [
38
+ // User
39
+ {
40
+ name: "get_me",
41
+ description: "Get the currently authenticated Dueey user (id, email, name).",
42
+ inputSchema: { type: "object", properties: {}, required: [] },
43
+ },
44
+ // Boards
45
+ {
46
+ name: "list_boards",
47
+ description: "List all boards the user has access to, optionally filtered by workspace.",
48
+ inputSchema: {
49
+ type: "object",
50
+ properties: {
51
+ workspaceId: { type: "string", description: "Filter by workspace ID" },
52
+ fields: { type: "string", description: "Comma-separated fields to return" },
53
+ },
54
+ },
55
+ },
56
+ {
57
+ name: "get_board",
58
+ description: "Get full details for a single board by its ID or slug.",
59
+ inputSchema: {
60
+ type: "object",
61
+ required: ["id"],
62
+ properties: {
63
+ id: { type: "string", description: "Board ID or slug" },
64
+ fields: { type: "string" },
65
+ },
66
+ },
67
+ },
68
+ // Lists
69
+ {
70
+ name: "list_lists",
71
+ description: "Get all lists (columns) for a specific board.",
72
+ inputSchema: {
73
+ type: "object",
74
+ required: ["boardId"],
75
+ properties: {
76
+ boardId: { type: "string", description: "Board ID" },
77
+ fields: { type: "string" },
78
+ },
79
+ },
80
+ },
81
+ // Cards
82
+ {
83
+ name: "list_cards",
84
+ description: "List cards, optionally filtered by board or list. Returns up to `limit` cards (default 50).",
85
+ inputSchema: {
86
+ type: "object",
87
+ properties: {
88
+ boardId: { type: "string" },
89
+ listId: { type: "string" },
90
+ limit: { type: "number", description: "Max results (default 50)" },
91
+ fields: { type: "string" },
92
+ },
93
+ },
94
+ },
95
+ {
96
+ name: "get_card",
97
+ description: "Get a single card by its UUID or cardKey (e.g. SWAT-42).",
98
+ inputSchema: {
99
+ type: "object",
100
+ required: ["id"],
101
+ properties: {
102
+ id: { type: "string", description: "Card UUID or cardKey" },
103
+ fields: { type: "string" },
104
+ },
105
+ },
106
+ },
107
+ {
108
+ name: "create_card",
109
+ description: "Create a new card in a list.",
110
+ inputSchema: {
111
+ type: "object",
112
+ required: ["listId", "title"],
113
+ properties: {
114
+ listId: { type: "string" },
115
+ title: { type: "string" },
116
+ description: { type: "string" },
117
+ priority: {
118
+ type: "string",
119
+ enum: ["critical", "high", "medium", "low", "none"],
120
+ },
121
+ labels: { type: "array", items: { type: "string" } },
122
+ dueDate: { type: "string", description: "ISO date e.g. 2025-12-31" },
123
+ startDate: { type: "string" },
124
+ checklist: {
125
+ type: "array",
126
+ items: {
127
+ type: "object",
128
+ properties: {
129
+ text: { type: "string" },
130
+ completed: { type: "boolean" },
131
+ },
132
+ },
133
+ },
134
+ },
135
+ },
136
+ },
137
+ {
138
+ name: "update_card",
139
+ description: "Update an existing card. Pass only the fields you want to change. Use `listId` to move a card to another list.",
140
+ inputSchema: {
141
+ type: "object",
142
+ required: ["id"],
143
+ properties: {
144
+ id: { type: "string", description: "Card UUID or cardKey" },
145
+ title: { type: "string" },
146
+ description: { type: "string" },
147
+ priority: {
148
+ type: "string",
149
+ enum: ["critical", "high", "medium", "low", "none"],
150
+ },
151
+ labels: { type: "array", items: { type: "string" } },
152
+ dueDate: { type: "string", nullable: true },
153
+ startDate: { type: "string", nullable: true },
154
+ checklist: { type: "array" },
155
+ listId: { type: "string", description: "Move card to this list" },
156
+ },
157
+ },
158
+ },
159
+ // Export
160
+ {
161
+ name: "get_data",
162
+ description: "Full export of all workspaces, boards, lists, and cards keyed by ID. Use `compact=true` to omit nulls and heavy fields.",
163
+ inputSchema: {
164
+ type: "object",
165
+ properties: {
166
+ compact: { type: "boolean" },
167
+ },
168
+ },
169
+ },
170
+ ],
171
+ }));
172
+ // ─── Tool Handlers ───────────────────────────────────────────────────────────
173
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
174
+ const { name, arguments: args = {} } = request.params;
175
+ const ok = (data) => ({
176
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
177
+ });
178
+ switch (name) {
179
+ case "get_me":
180
+ return ok(await dueeyFetch("/me"));
181
+ case "list_boards":
182
+ return ok(await dueeyFetch("/boards", {
183
+ params: { workspaceId: args.workspaceId, fields: args.fields },
184
+ }));
185
+ case "get_board":
186
+ return ok(await dueeyFetch(`/boards/${args.id}`, {
187
+ params: { fields: args.fields },
188
+ }));
189
+ case "list_lists":
190
+ return ok(await dueeyFetch("/lists", {
191
+ params: { boardId: args.boardId, fields: args.fields },
192
+ }));
193
+ case "list_cards":
194
+ return ok(await dueeyFetch("/cards", {
195
+ params: {
196
+ boardId: args.boardId,
197
+ listId: args.listId,
198
+ limit: args.limit,
199
+ fields: args.fields,
200
+ },
201
+ }));
202
+ case "get_card":
203
+ return ok(await dueeyFetch(`/cards/${args.id}`, {
204
+ params: { fields: args.fields },
205
+ }));
206
+ case "create_card": {
207
+ const { ...body } = args;
208
+ return ok(await dueeyFetch("/cards", {
209
+ method: "POST",
210
+ body: JSON.stringify(body),
211
+ }));
212
+ }
213
+ case "update_card": {
214
+ const { id, ...body } = args;
215
+ return ok(await dueeyFetch(`/cards/${id}`, {
216
+ method: "PATCH",
217
+ body: JSON.stringify(body),
218
+ }));
219
+ }
220
+ case "get_data":
221
+ return ok(await dueeyFetch("/data", {
222
+ params: { compact: args.compact ? "1" : undefined },
223
+ }));
224
+ default:
225
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
226
+ }
227
+ });
228
+ // ─── Start ───────────────────────────────────────────────────────────────────
229
+ const transport = new StdioServerTransport();
230
+ server.connect(transport);
231
+ console.error("Dueey MCP server running.");
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "dueey-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for the Dueey PM Assistant public API",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": { "dueey-mcp": "dist/index.js" },
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "start": "node dist/index.js",
11
+ "dev": "ts-node --esm src/index.ts",
12
+ "prepublishOnly": "npm run build"
13
+ },
14
+ "files": ["dist", "README.md"],
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/gmurph91/dueeymcp.git"
18
+ },
19
+ "keywords": ["mcp", "dueey", "model-context-protocol", "claude", "pm", "project-management"],
20
+ "license": "MIT",
21
+ "dependencies": {
22
+ "@modelcontextprotocol/sdk": "^1.0.0"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^20.0.0",
26
+ "typescript": "^5.0.0"
27
+ },
28
+ "engines": {
29
+ "node": ">=18"
30
+ }
31
+ }