@studiometa/productive-mcp 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/dist/stdio.js ADDED
@@ -0,0 +1,119 @@
1
+ import { getConfig, setConfig } from "@studiometa/productive-cli";
2
+ import { TOOLS, STDIO_ONLY_TOOLS } from "./tools.js";
3
+ import { executeToolWithCredentials } from "./handlers.js";
4
+ function getAvailableTools() {
5
+ return [...TOOLS, ...STDIO_ONLY_TOOLS];
6
+ }
7
+ function getAvailablePrompts() {
8
+ return [
9
+ {
10
+ name: "setup_productive",
11
+ description: "Interactive setup for Productive.io credentials",
12
+ arguments: []
13
+ }
14
+ ];
15
+ }
16
+ async function handleSetupPrompt() {
17
+ const config = await getConfig();
18
+ const hasConfig = !!(config.organizationId && config.apiToken);
19
+ return {
20
+ messages: [
21
+ {
22
+ role: "user",
23
+ content: {
24
+ type: "text",
25
+ text: hasConfig ? "I have already configured Productive.io credentials. Would you like to update them?" : "I need to configure my Productive.io credentials. Please help me set up:\n1. Organization ID\n2. API Token\n3. User ID (optional)"
26
+ }
27
+ }
28
+ ]
29
+ };
30
+ }
31
+ async function handleConfigureTool(args) {
32
+ const { organizationId, apiToken, userId } = args;
33
+ await setConfig("organizationId", organizationId);
34
+ await setConfig("apiToken", apiToken);
35
+ if (userId) {
36
+ await setConfig("userId", userId);
37
+ }
38
+ return {
39
+ content: [
40
+ {
41
+ type: "text",
42
+ text: JSON.stringify(
43
+ {
44
+ success: true,
45
+ message: "Productive.io credentials configured successfully",
46
+ configured: {
47
+ organizationId,
48
+ userId: userId || "not set",
49
+ apiToken: "***" + apiToken.slice(-4)
50
+ }
51
+ },
52
+ null,
53
+ 2
54
+ )
55
+ }
56
+ ]
57
+ };
58
+ }
59
+ async function handleGetConfigTool() {
60
+ const currentConfig = await getConfig();
61
+ return {
62
+ content: [
63
+ {
64
+ type: "text",
65
+ text: JSON.stringify(
66
+ {
67
+ organizationId: currentConfig.organizationId || "not configured",
68
+ userId: currentConfig.userId || "not configured",
69
+ apiToken: currentConfig.apiToken ? "***" + currentConfig.apiToken.slice(-4) : "not configured",
70
+ configured: !!(currentConfig.organizationId && currentConfig.apiToken)
71
+ },
72
+ null,
73
+ 2
74
+ )
75
+ }
76
+ ]
77
+ };
78
+ }
79
+ async function handleToolCall(name, args) {
80
+ if (name === "productive_configure") {
81
+ return handleConfigureTool(args);
82
+ }
83
+ if (name === "productive_get_config") {
84
+ return handleGetConfigTool();
85
+ }
86
+ const config = await getConfig();
87
+ if (!config.organizationId || !config.apiToken) {
88
+ return {
89
+ content: [
90
+ {
91
+ type: "text",
92
+ text: 'Error: Productive.io credentials not configured. Please use the "productive_configure" tool to set your credentials, or set PRODUCTIVE_ORG_ID and PRODUCTIVE_API_TOKEN environment variables.'
93
+ }
94
+ ],
95
+ isError: true
96
+ };
97
+ }
98
+ return executeToolWithCredentials(name, args, {
99
+ organizationId: config.organizationId,
100
+ apiToken: config.apiToken,
101
+ userId: config.userId
102
+ });
103
+ }
104
+ async function handlePrompt(name) {
105
+ if (name === "setup_productive") {
106
+ return handleSetupPrompt();
107
+ }
108
+ throw new Error(`Unknown prompt: ${name}`);
109
+ }
110
+ export {
111
+ getAvailablePrompts,
112
+ getAvailableTools,
113
+ handleConfigureTool,
114
+ handleGetConfigTool,
115
+ handlePrompt,
116
+ handleSetupPrompt,
117
+ handleToolCall
118
+ };
119
+ //# sourceMappingURL=stdio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.js","sources":["../src/stdio.ts"],"sourcesContent":["/**\n * Stdio transport handlers for Productive MCP Server\n *\n * This module contains the handler logic for the stdio transport.\n * The actual server startup is in index.ts.\n */\n\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { getConfig, setConfig } from '@studiometa/productive-cli';\n\nimport { TOOLS, STDIO_ONLY_TOOLS } from './tools.js';\nimport { executeToolWithCredentials } from './handlers.js';\n\nexport type ToolResult = CallToolResult;\n\n/**\n * Get all available tools (including stdio-only configuration tools)\n */\nexport function getAvailableTools() {\n return [...TOOLS, ...STDIO_ONLY_TOOLS];\n}\n\n/**\n * Get available prompts\n */\nexport function getAvailablePrompts() {\n return [\n {\n name: 'setup_productive',\n description: 'Interactive setup for Productive.io credentials',\n arguments: [],\n },\n ];\n}\n\n/**\n * Handle the setup_productive prompt\n */\nexport async function handleSetupPrompt(): Promise<{\n messages: Array<{ role: string; content: { type: string; text: string } }>;\n}> {\n const config = await getConfig();\n const hasConfig = !!(config.organizationId && config.apiToken);\n\n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: hasConfig\n ? 'I have already configured Productive.io credentials. Would you like to update them?'\n : 'I need to configure my Productive.io credentials. Please help me set up:\\n1. Organization ID\\n2. API Token\\n3. User ID (optional)',\n },\n },\n ],\n };\n}\n\n/**\n * Handle the productive_configure tool\n */\nexport async function handleConfigureTool(args: {\n organizationId: string;\n apiToken: string;\n userId?: string;\n}): Promise<ToolResult> {\n const { organizationId, apiToken, userId } = args;\n\n await setConfig('organizationId', organizationId);\n await setConfig('apiToken', apiToken);\n if (userId) {\n await setConfig('userId', userId);\n }\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n success: true,\n message: 'Productive.io credentials configured successfully',\n configured: {\n organizationId,\n userId: userId || 'not set',\n apiToken: '***' + apiToken.slice(-4),\n },\n },\n null,\n 2\n ),\n },\n ],\n };\n}\n\n/**\n * Handle the productive_get_config tool\n */\nexport async function handleGetConfigTool(): Promise<ToolResult> {\n const currentConfig = await getConfig();\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n organizationId: currentConfig.organizationId || 'not configured',\n userId: currentConfig.userId || 'not configured',\n apiToken: currentConfig.apiToken\n ? '***' + currentConfig.apiToken.slice(-4)\n : 'not configured',\n configured: !!(currentConfig.organizationId && currentConfig.apiToken),\n },\n null,\n 2\n ),\n },\n ],\n };\n}\n\n/**\n * Handle a tool call request\n */\nexport async function handleToolCall(\n name: string,\n args: Record<string, unknown>\n): Promise<ToolResult> {\n // Handle stdio-only configuration tools\n if (name === 'productive_configure') {\n return handleConfigureTool(args as Parameters<typeof handleConfigureTool>[0]);\n }\n\n if (name === 'productive_get_config') {\n return handleGetConfigTool();\n }\n\n // Get config for API tools\n const config = await getConfig();\n if (!config.organizationId || !config.apiToken) {\n return {\n content: [\n {\n type: 'text',\n text: 'Error: Productive.io credentials not configured. Please use the \"productive_configure\" tool to set your credentials, or set PRODUCTIVE_ORG_ID and PRODUCTIVE_API_TOKEN environment variables.',\n },\n ],\n isError: true,\n };\n }\n\n // Execute tool with credentials from config\n return executeToolWithCredentials(name, args, {\n organizationId: config.organizationId,\n apiToken: config.apiToken,\n userId: config.userId,\n });\n}\n\n/**\n * Handle a prompt request\n */\nexport async function handlePrompt(name: string): Promise<{\n messages: Array<{ role: string; content: { type: string; text: string } }>;\n}> {\n if (name === 'setup_productive') {\n return handleSetupPrompt();\n }\n\n throw new Error(`Unknown prompt: ${name}`);\n}\n"],"names":[],"mappings":";;;AAkBO,SAAS,oBAAoB;AAClC,SAAO,CAAC,GAAG,OAAO,GAAG,gBAAgB;AACvC;AAKO,SAAS,sBAAsB;AACpC,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,WAAW,CAAA;AAAA,IAAC;AAAA,EACd;AAEJ;AAKA,eAAsB,oBAEnB;AACD,QAAM,SAAS,MAAM,UAAA;AACrB,QAAM,YAAY,CAAC,EAAE,OAAO,kBAAkB,OAAO;AAErD,SAAO;AAAA,IACL,UAAU;AAAA,MACR;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM;AAAA,UACN,MAAM,YACF,wFACA;AAAA,QAAA;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAEJ;AAKA,eAAsB,oBAAoB,MAIlB;AACtB,QAAM,EAAE,gBAAgB,UAAU,OAAA,IAAW;AAE7C,QAAM,UAAU,kBAAkB,cAAc;AAChD,QAAM,UAAU,YAAY,QAAQ;AACpC,MAAI,QAAQ;AACV,UAAM,UAAU,UAAU,MAAM;AAAA,EAClC;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,MAAM,KAAK;AAAA,UACT;AAAA,YACE,SAAS;AAAA,YACT,SAAS;AAAA,YACT,YAAY;AAAA,cACV;AAAA,cACA,QAAQ,UAAU;AAAA,cAClB,UAAU,QAAQ,SAAS,MAAM,EAAE;AAAA,YAAA;AAAA,UACrC;AAAA,UAEF;AAAA,UACA;AAAA,QAAA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEJ;AAKA,eAAsB,sBAA2C;AAC/D,QAAM,gBAAgB,MAAM,UAAA;AAC5B,SAAO;AAAA,IACL,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,MAAM,KAAK;AAAA,UACT;AAAA,YACE,gBAAgB,cAAc,kBAAkB;AAAA,YAChD,QAAQ,cAAc,UAAU;AAAA,YAChC,UAAU,cAAc,WACpB,QAAQ,cAAc,SAAS,MAAM,EAAE,IACvC;AAAA,YACJ,YAAY,CAAC,EAAE,cAAc,kBAAkB,cAAc;AAAA,UAAA;AAAA,UAE/D;AAAA,UACA;AAAA,QAAA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEJ;AAKA,eAAsB,eACpB,MACA,MACqB;AAErB,MAAI,SAAS,wBAAwB;AACnC,WAAO,oBAAoB,IAAiD;AAAA,EAC9E;AAEA,MAAI,SAAS,yBAAyB;AACpC,WAAO,oBAAA;AAAA,EACT;AAGA,QAAM,SAAS,MAAM,UAAA;AACrB,MAAI,CAAC,OAAO,kBAAkB,CAAC,OAAO,UAAU;AAC9C,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,QAAA;AAAA,MACR;AAAA,MAEF,SAAS;AAAA,IAAA;AAAA,EAEb;AAGA,SAAO,2BAA2B,MAAM,MAAM;AAAA,IAC5C,gBAAgB,OAAO;AAAA,IACvB,UAAU,OAAO;AAAA,IACjB,QAAQ,OAAO;AAAA,EAAA,CAChB;AACH;AAKA,eAAsB,aAAa,MAEhC;AACD,MAAI,SAAS,oBAAoB;AAC/B,WAAO,kBAAA;AAAA,EACT;AAEA,QAAM,IAAI,MAAM,mBAAmB,IAAI,EAAE;AAC3C;"}
@@ -0,0 +1,12 @@
1
+ import type { Tool } from '@modelcontextprotocol/sdk/types.js';
2
+ /**
3
+ * Tool definitions for Productive.io MCP server
4
+ * These are shared between stdio and HTTP transports
5
+ */
6
+ export declare const TOOLS: Tool[];
7
+ /**
8
+ * Additional tools only available in stdio mode (local execution)
9
+ * These tools manage persistent configuration
10
+ */
11
+ export declare const STDIO_ONLY_TOOLS: Tool[];
12
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAE/D;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAE,IAAI,EAsMvB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,IAAI,EAsBlC,CAAC"}
package/dist/tools.js ADDED
@@ -0,0 +1,227 @@
1
+ const TOOLS = [
2
+ {
3
+ name: "productive_list_projects",
4
+ description: "List projects from Productive.io with optional filters",
5
+ inputSchema: {
6
+ type: "object",
7
+ properties: {
8
+ filter: {
9
+ type: "object",
10
+ description: "Filters to apply",
11
+ properties: {
12
+ board_id: { type: "string", description: "Filter by board ID" },
13
+ company_id: { type: "string", description: "Filter by company ID" },
14
+ project_manager_id: { type: "string", description: "Filter by project manager ID" },
15
+ workflow_status: { type: "string", description: "Filter by workflow status" }
16
+ }
17
+ },
18
+ page: { type: "number", description: "Page number (default: 1)" },
19
+ per_page: { type: "number", description: "Items per page (default: 50, max: 200)" }
20
+ }
21
+ }
22
+ },
23
+ {
24
+ name: "productive_get_project",
25
+ description: "Get details for a specific project by ID",
26
+ inputSchema: {
27
+ type: "object",
28
+ properties: {
29
+ id: { type: "string", description: "Project ID" }
30
+ },
31
+ required: ["id"]
32
+ }
33
+ },
34
+ {
35
+ name: "productive_list_time_entries",
36
+ description: "List time entries with optional filters",
37
+ inputSchema: {
38
+ type: "object",
39
+ properties: {
40
+ filter: {
41
+ type: "object",
42
+ description: "Filters to apply",
43
+ properties: {
44
+ person_id: { type: "string", description: "Filter by person ID" },
45
+ project_id: { type: "string", description: "Filter by project ID" },
46
+ service_id: { type: "string", description: "Filter by service ID" },
47
+ task_id: { type: "string", description: "Filter by task ID" },
48
+ after: { type: "string", description: "After date (YYYY-MM-DD)" },
49
+ before: { type: "string", description: "Before date (YYYY-MM-DD)" }
50
+ }
51
+ },
52
+ page: { type: "number", description: "Page number (default: 1)" },
53
+ per_page: { type: "number", description: "Items per page (default: 50, max: 200)" }
54
+ }
55
+ }
56
+ },
57
+ {
58
+ name: "productive_get_time_entry",
59
+ description: "Get details for a specific time entry by ID",
60
+ inputSchema: {
61
+ type: "object",
62
+ properties: {
63
+ id: { type: "string", description: "Time entry ID" }
64
+ },
65
+ required: ["id"]
66
+ }
67
+ },
68
+ {
69
+ name: "productive_create_time_entry",
70
+ description: "Create a new time entry",
71
+ inputSchema: {
72
+ type: "object",
73
+ properties: {
74
+ person_id: { type: "string", description: "Person ID" },
75
+ service_id: { type: "string", description: "Service ID" },
76
+ time: { type: "number", description: "Time in minutes" },
77
+ date: { type: "string", description: "Date (YYYY-MM-DD)" },
78
+ note: { type: "string", description: "Note/description" },
79
+ task_id: { type: "string", description: "Task ID (optional)" }
80
+ },
81
+ required: ["person_id", "service_id", "time", "date"]
82
+ }
83
+ },
84
+ {
85
+ name: "productive_update_time_entry",
86
+ description: "Update an existing time entry",
87
+ inputSchema: {
88
+ type: "object",
89
+ properties: {
90
+ id: { type: "string", description: "Time entry ID" },
91
+ time: { type: "number", description: "Time in minutes" },
92
+ date: { type: "string", description: "Date (YYYY-MM-DD)" },
93
+ note: { type: "string", description: "Note/description" },
94
+ service_id: { type: "string", description: "Service ID" },
95
+ task_id: { type: "string", description: "Task ID" }
96
+ },
97
+ required: ["id"]
98
+ }
99
+ },
100
+ {
101
+ name: "productive_delete_time_entry",
102
+ description: "Delete a time entry",
103
+ inputSchema: {
104
+ type: "object",
105
+ properties: {
106
+ id: { type: "string", description: "Time entry ID" }
107
+ },
108
+ required: ["id"]
109
+ }
110
+ },
111
+ {
112
+ name: "productive_list_tasks",
113
+ description: "List tasks with optional filters",
114
+ inputSchema: {
115
+ type: "object",
116
+ properties: {
117
+ filter: {
118
+ type: "object",
119
+ description: "Filters to apply",
120
+ properties: {
121
+ project_id: { type: "string", description: "Filter by project ID" },
122
+ assignee_id: { type: "string", description: "Filter by assignee ID" },
123
+ task_list_id: { type: "string", description: "Filter by task list ID" },
124
+ workflow_status_id: { type: "string", description: "Filter by workflow status ID" }
125
+ }
126
+ },
127
+ page: { type: "number", description: "Page number (default: 1)" },
128
+ per_page: { type: "number", description: "Items per page (default: 50, max: 200)" }
129
+ }
130
+ }
131
+ },
132
+ {
133
+ name: "productive_get_task",
134
+ description: "Get details for a specific task by ID",
135
+ inputSchema: {
136
+ type: "object",
137
+ properties: {
138
+ id: { type: "string", description: "Task ID" }
139
+ },
140
+ required: ["id"]
141
+ }
142
+ },
143
+ {
144
+ name: "productive_list_services",
145
+ description: "List services (budget line items) with optional filters",
146
+ inputSchema: {
147
+ type: "object",
148
+ properties: {
149
+ filter: {
150
+ type: "object",
151
+ description: "Filters to apply",
152
+ properties: {
153
+ project_id: { type: "string", description: "Filter by project ID" },
154
+ deal_id: { type: "string", description: "Filter by deal ID" }
155
+ }
156
+ },
157
+ page: { type: "number", description: "Page number (default: 1)" },
158
+ per_page: { type: "number", description: "Items per page (default: 50, max: 200)" }
159
+ }
160
+ }
161
+ },
162
+ {
163
+ name: "productive_list_people",
164
+ description: "List people from the organization",
165
+ inputSchema: {
166
+ type: "object",
167
+ properties: {
168
+ filter: {
169
+ type: "object",
170
+ description: "Filters to apply",
171
+ properties: {
172
+ archived: { type: "boolean", description: "Filter by archived status" }
173
+ }
174
+ },
175
+ page: { type: "number", description: "Page number (default: 1)" },
176
+ per_page: { type: "number", description: "Items per page (default: 50, max: 200)" }
177
+ }
178
+ }
179
+ },
180
+ {
181
+ name: "productive_get_person",
182
+ description: "Get details for a specific person by ID",
183
+ inputSchema: {
184
+ type: "object",
185
+ properties: {
186
+ id: { type: "string", description: "Person ID" }
187
+ },
188
+ required: ["id"]
189
+ }
190
+ },
191
+ {
192
+ name: "productive_get_current_user",
193
+ description: "Get the current authenticated user information",
194
+ inputSchema: {
195
+ type: "object",
196
+ properties: {}
197
+ }
198
+ }
199
+ ];
200
+ const STDIO_ONLY_TOOLS = [
201
+ {
202
+ name: "productive_configure",
203
+ description: "Configure Productive.io credentials (organization ID, API token, and optionally user ID)",
204
+ inputSchema: {
205
+ type: "object",
206
+ properties: {
207
+ organizationId: { type: "string", description: "Your Productive.io organization ID" },
208
+ apiToken: { type: "string", description: "Your Productive.io API token" },
209
+ userId: { type: "string", description: "Your Productive.io user ID (optional, for time entries)" }
210
+ },
211
+ required: ["organizationId", "apiToken"]
212
+ }
213
+ },
214
+ {
215
+ name: "productive_get_config",
216
+ description: "Get current Productive.io configuration (without exposing the API token)",
217
+ inputSchema: {
218
+ type: "object",
219
+ properties: {}
220
+ }
221
+ }
222
+ ];
223
+ export {
224
+ STDIO_ONLY_TOOLS,
225
+ TOOLS
226
+ };
227
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sources":["../src/tools.ts"],"sourcesContent":["import type { Tool } from '@modelcontextprotocol/sdk/types.js';\n\n/**\n * Tool definitions for Productive.io MCP server\n * These are shared between stdio and HTTP transports\n */\nexport const TOOLS: Tool[] = [\n {\n name: 'productive_list_projects',\n description: 'List projects from Productive.io with optional filters',\n inputSchema: {\n type: 'object',\n properties: {\n filter: {\n type: 'object',\n description: 'Filters to apply',\n properties: {\n board_id: { type: 'string', description: 'Filter by board ID' },\n company_id: { type: 'string', description: 'Filter by company ID' },\n project_manager_id: { type: 'string', description: 'Filter by project manager ID' },\n workflow_status: { type: 'string', description: 'Filter by workflow status' },\n },\n },\n page: { type: 'number', description: 'Page number (default: 1)' },\n per_page: { type: 'number', description: 'Items per page (default: 50, max: 200)' },\n },\n },\n },\n {\n name: 'productive_get_project',\n description: 'Get details for a specific project by ID',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'string', description: 'Project ID' },\n },\n required: ['id'],\n },\n },\n {\n name: 'productive_list_time_entries',\n description: 'List time entries with optional filters',\n inputSchema: {\n type: 'object',\n properties: {\n filter: {\n type: 'object',\n description: 'Filters to apply',\n properties: {\n person_id: { type: 'string', description: 'Filter by person ID' },\n project_id: { type: 'string', description: 'Filter by project ID' },\n service_id: { type: 'string', description: 'Filter by service ID' },\n task_id: { type: 'string', description: 'Filter by task ID' },\n after: { type: 'string', description: 'After date (YYYY-MM-DD)' },\n before: { type: 'string', description: 'Before date (YYYY-MM-DD)' },\n },\n },\n page: { type: 'number', description: 'Page number (default: 1)' },\n per_page: { type: 'number', description: 'Items per page (default: 50, max: 200)' },\n },\n },\n },\n {\n name: 'productive_get_time_entry',\n description: 'Get details for a specific time entry by ID',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'string', description: 'Time entry ID' },\n },\n required: ['id'],\n },\n },\n {\n name: 'productive_create_time_entry',\n description: 'Create a new time entry',\n inputSchema: {\n type: 'object',\n properties: {\n person_id: { type: 'string', description: 'Person ID' },\n service_id: { type: 'string', description: 'Service ID' },\n time: { type: 'number', description: 'Time in minutes' },\n date: { type: 'string', description: 'Date (YYYY-MM-DD)' },\n note: { type: 'string', description: 'Note/description' },\n task_id: { type: 'string', description: 'Task ID (optional)' },\n },\n required: ['person_id', 'service_id', 'time', 'date'],\n },\n },\n {\n name: 'productive_update_time_entry',\n description: 'Update an existing time entry',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'string', description: 'Time entry ID' },\n time: { type: 'number', description: 'Time in minutes' },\n date: { type: 'string', description: 'Date (YYYY-MM-DD)' },\n note: { type: 'string', description: 'Note/description' },\n service_id: { type: 'string', description: 'Service ID' },\n task_id: { type: 'string', description: 'Task ID' },\n },\n required: ['id'],\n },\n },\n {\n name: 'productive_delete_time_entry',\n description: 'Delete a time entry',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'string', description: 'Time entry ID' },\n },\n required: ['id'],\n },\n },\n {\n name: 'productive_list_tasks',\n description: 'List tasks with optional filters',\n inputSchema: {\n type: 'object',\n properties: {\n filter: {\n type: 'object',\n description: 'Filters to apply',\n properties: {\n project_id: { type: 'string', description: 'Filter by project ID' },\n assignee_id: { type: 'string', description: 'Filter by assignee ID' },\n task_list_id: { type: 'string', description: 'Filter by task list ID' },\n workflow_status_id: { type: 'string', description: 'Filter by workflow status ID' },\n },\n },\n page: { type: 'number', description: 'Page number (default: 1)' },\n per_page: { type: 'number', description: 'Items per page (default: 50, max: 200)' },\n },\n },\n },\n {\n name: 'productive_get_task',\n description: 'Get details for a specific task by ID',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'string', description: 'Task ID' },\n },\n required: ['id'],\n },\n },\n {\n name: 'productive_list_services',\n description: 'List services (budget line items) with optional filters',\n inputSchema: {\n type: 'object',\n properties: {\n filter: {\n type: 'object',\n description: 'Filters to apply',\n properties: {\n project_id: { type: 'string', description: 'Filter by project ID' },\n deal_id: { type: 'string', description: 'Filter by deal ID' },\n },\n },\n page: { type: 'number', description: 'Page number (default: 1)' },\n per_page: { type: 'number', description: 'Items per page (default: 50, max: 200)' },\n },\n },\n },\n {\n name: 'productive_list_people',\n description: 'List people from the organization',\n inputSchema: {\n type: 'object',\n properties: {\n filter: {\n type: 'object',\n description: 'Filters to apply',\n properties: {\n archived: { type: 'boolean', description: 'Filter by archived status' },\n },\n },\n page: { type: 'number', description: 'Page number (default: 1)' },\n per_page: { type: 'number', description: 'Items per page (default: 50, max: 200)' },\n },\n },\n },\n {\n name: 'productive_get_person',\n description: 'Get details for a specific person by ID',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'string', description: 'Person ID' },\n },\n required: ['id'],\n },\n },\n {\n name: 'productive_get_current_user',\n description: 'Get the current authenticated user information',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n];\n\n/**\n * Additional tools only available in stdio mode (local execution)\n * These tools manage persistent configuration\n */\nexport const STDIO_ONLY_TOOLS: Tool[] = [\n {\n name: 'productive_configure',\n description: 'Configure Productive.io credentials (organization ID, API token, and optionally user ID)',\n inputSchema: {\n type: 'object',\n properties: {\n organizationId: { type: 'string', description: 'Your Productive.io organization ID' },\n apiToken: { type: 'string', description: 'Your Productive.io API token' },\n userId: { type: 'string', description: 'Your Productive.io user ID (optional, for time entries)' },\n },\n required: ['organizationId', 'apiToken'],\n },\n },\n {\n name: 'productive_get_config',\n description: 'Get current Productive.io configuration (without exposing the API token)',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n];\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,87 @@
1
+ {
2
+ "name": "@studiometa/productive-mcp",
3
+ "version": "0.3.0",
4
+ "description": "MCP server for Productive.io API - Model Context Protocol integration for Claude Desktop",
5
+ "type": "module",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "bin": {
10
+ "productive-mcp": "./dist/index.js",
11
+ "productive-mcp-server": "./dist/server.js"
12
+ },
13
+ "main": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "import": "./dist/index.js",
18
+ "types": "./dist/index.d.ts"
19
+ },
20
+ "./server": {
21
+ "import": "./dist/server.js",
22
+ "types": "./dist/server.d.ts"
23
+ },
24
+ "./auth": {
25
+ "import": "./dist/auth.js",
26
+ "types": "./dist/auth.d.ts"
27
+ },
28
+ "./tools": {
29
+ "import": "./dist/tools.js",
30
+ "types": "./dist/tools.d.ts"
31
+ },
32
+ "./handlers": {
33
+ "import": "./dist/handlers.js",
34
+ "types": "./dist/handlers.d.ts"
35
+ }
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "Dockerfile"
40
+ ],
41
+ "scripts": {
42
+ "dev": "vite build --watch",
43
+ "dev:server": "node --watch dist/server.js",
44
+ "build": "vite build && tsc --emitDeclarationOnly && node scripts/postbuild.js",
45
+ "start": "node dist/server.js",
46
+ "test": "vitest run",
47
+ "test:watch": "vitest",
48
+ "test:ci": "vitest run --coverage",
49
+ "lint": "oxlint src",
50
+ "format": "oxlint --fix src",
51
+ "format:check": "oxlint src",
52
+ "typecheck": "tsc --noEmit"
53
+ },
54
+ "keywords": [
55
+ "mcp",
56
+ "model-context-protocol",
57
+ "productive",
58
+ "claude",
59
+ "ai",
60
+ "project-management",
61
+ "http",
62
+ "remote"
63
+ ],
64
+ "author": "Studio Meta",
65
+ "license": "MIT",
66
+ "repository": {
67
+ "type": "git",
68
+ "url": "https://github.com/studiometa/productive-cli",
69
+ "directory": "packages/productive-mcp"
70
+ },
71
+ "engines": {
72
+ "node": ">=20.0.0"
73
+ },
74
+ "dependencies": {
75
+ "@modelcontextprotocol/sdk": "^1.0.4",
76
+ "@studiometa/productive-cli": "*",
77
+ "h3": "^1.15.1"
78
+ },
79
+ "devDependencies": {
80
+ "@types/node": "^22.10.5",
81
+ "@vitest/coverage-v8": "2.1.9",
82
+ "oxlint": "^0.16.1",
83
+ "typescript": "^5.7.3",
84
+ "vite": "^6.0.7",
85
+ "vitest": "^2.1.8"
86
+ }
87
+ }