@studiometa/productive-mcp 0.10.4 → 0.10.6

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.
@@ -0,0 +1,256 @@
1
+ const PROMPT_DEFINITIONS = [
2
+ {
3
+ name: "end-of-day",
4
+ description: "Compose an end-of-day standup message based on your activity today",
5
+ arguments: [{
6
+ name: "format",
7
+ description: "Output format: slack, email, or plain (default: plain)",
8
+ required: false
9
+ }]
10
+ },
11
+ {
12
+ name: "project-review",
13
+ description: "Analyze project health and status with budget, tasks, and timeline overview",
14
+ arguments: [{
15
+ name: "project",
16
+ description: "Project ID or project number (e.g. PRJ-123)",
17
+ required: true
18
+ }]
19
+ },
20
+ {
21
+ name: "plan-sprint",
22
+ description: "Help prioritize tasks for the next sprint based on open tasks and budget",
23
+ arguments: [{
24
+ name: "project",
25
+ description: "Project ID or project number (e.g. PRJ-123)",
26
+ required: true
27
+ }]
28
+ },
29
+ {
30
+ name: "weekly-report",
31
+ description: "Generate a polished weekly progress report",
32
+ arguments: [{
33
+ name: "person",
34
+ description: "Person email or ID to report on (default: current user)",
35
+ required: false
36
+ }, {
37
+ name: "format",
38
+ description: "Output format: slack, email, or plain (default: plain)",
39
+ required: false
40
+ }]
41
+ },
42
+ {
43
+ name: "invoice-prep",
44
+ description: "Prepare a billing summary for a project within a date range",
45
+ arguments: [
46
+ {
47
+ name: "project",
48
+ description: "Project ID or project number (e.g. PRJ-123)",
49
+ required: true
50
+ },
51
+ {
52
+ name: "from",
53
+ description: "Start date in YYYY-MM-DD format",
54
+ required: true
55
+ },
56
+ {
57
+ name: "to",
58
+ description: "End date in YYYY-MM-DD format",
59
+ required: true
60
+ }
61
+ ]
62
+ }
63
+ ];
64
+ /**
65
+ * Build the end-of-day standup prompt messages
66
+ */
67
+ function endOfDay(args) {
68
+ const format = args?.format ?? "plain";
69
+ return { messages: [{
70
+ role: "user",
71
+ content: {
72
+ type: "text",
73
+ text: `Please compose my end-of-day standup message.
74
+
75
+ First, call the productive tool to gather today's activity:
76
+ \`\`\`json
77
+ { "resource": "summaries", "action": "my_day" }
78
+ \`\`\`
79
+
80
+ Then compose a standup message with these sections:
81
+ - **What I did today**: Summarize completed tasks and logged time by project
82
+ - **What I'm working on tomorrow**: Any open/in-progress tasks from today
83
+ - **Blockers**: Note any overdue tasks or items needing attention
84
+
85
+ ${format === "slack" ? "Format the output as a Slack message using emoji bullets and bold text with *asterisks*." : format === "email" ? "Format the output as a professional email with a subject line and proper greeting/closing." : "Format the output as a plain-text standup message with clear sections."}
86
+
87
+ Keep it concise — this is for a standup, not a novel.`
88
+ }
89
+ }] };
90
+ }
91
+ /**
92
+ * Build the project-review prompt messages
93
+ */
94
+ function projectReview(args) {
95
+ const project = args?.project ?? "";
96
+ return { messages: [{
97
+ role: "user",
98
+ content: {
99
+ type: "text",
100
+ text: `Please analyze the health and status of project ${project ? `"${project}"` : "(project not specified)"}.
101
+
102
+ Fetch all project context in one call:
103
+ \`\`\`json
104
+ { "resource": "projects", "action": "context", "id": "${project}" }
105
+ \`\`\`
106
+
107
+ Also check the project's tasks for a fuller picture:
108
+ \`\`\`json
109
+ { "resource": "tasks", "action": "list", "filter": { "project_id": "${project}", "status": 1 }, "per_page": 50 }
110
+ \`\`\`
111
+
112
+ Then provide a structured project health review covering:
113
+ 1. **Overview**: Project name, client, current status
114
+ 2. **Budget**: Budget used vs total, burn rate, projected overage risk
115
+ 3. **Tasks**: Open vs completed task counts, overdue tasks, upcoming deadlines
116
+ 4. **Recent activity**: What has been worked on recently
117
+ 5. **Health assessment**: Overall RAG status (🟢 On track / 🟡 At risk / 🔴 Critical) with reasoning
118
+ 6. **Recommendations**: Concrete next steps or concerns to address`
119
+ }
120
+ }] };
121
+ }
122
+ /**
123
+ * Build the plan-sprint prompt messages
124
+ */
125
+ function planSprint(args) {
126
+ const project = args?.project ?? "";
127
+ return { messages: [{
128
+ role: "user",
129
+ content: {
130
+ type: "text",
131
+ text: `Please help me plan the next sprint for project ${project ? `"${project}"` : "(project not specified)"}.
132
+
133
+ Fetch all open tasks for the project:
134
+ \`\`\`json
135
+ { "resource": "tasks", "action": "list", "filter": { "project_id": "${project}", "status": 1 }, "per_page": 100 }
136
+ \`\`\`
137
+
138
+ Fetch the project's budget services to understand available capacity:
139
+ \`\`\`json
140
+ { "resource": "services", "action": "list", "filter": { "project_id": "${project}" }, "per_page": 50 }
141
+ \`\`\`
142
+
143
+ Then provide sprint planning recommendations:
144
+ 1. **Backlog summary**: Total open tasks, categories/task-lists breakdown
145
+ 2. **Priority candidates**: Top tasks to tackle next sprint based on:
146
+ - Due dates and overdue items
147
+ - Task dependencies (if visible)
148
+ - Effort estimates
149
+ 3. **Budget check**: Remaining budget per service — flag if any service is near its limit
150
+ 4. **Suggested sprint scope**: A realistic list of tasks for a 1-2 week sprint
151
+ 5. **Risks**: Tasks that are blocked, unassigned, or missing estimates`
152
+ }
153
+ }] };
154
+ }
155
+ /**
156
+ * Build the weekly-report prompt messages
157
+ */
158
+ function weeklyReport(args) {
159
+ const person = args?.person;
160
+ const format = args?.format ?? "plain";
161
+ const personInstruction = person ? `Focus on person "${person}". Resolve the person ID if needed using: { "resource": "people", "action": "resolve", "query": "${person}" } first.` : "Focus on the current authenticated user (use the default person from summaries).";
162
+ const formatInstruction = format === "slack" ? "Format as a Slack message with emoji bullets, bold project names, and a summary header." : format === "email" ? "Format as a professional email with subject line, greeting, bulleted highlights per project, and a closing." : "Format as a clean plain-text weekly report with clear section headers.";
163
+ return { messages: [{
164
+ role: "user",
165
+ content: {
166
+ type: "text",
167
+ text: `Please generate a weekly progress report.
168
+
169
+ ${personInstruction}
170
+
171
+ ${person ? `First resolve the person ID, then fetch weekly standup data:
172
+ \`\`\`json
173
+ { "resource": "people", "action": "resolve", "query": "${person}" }
174
+ \`\`\`
175
+ \`\`\`json
176
+ { "resource": "workflows", "action": "weekly_standup", "person_id": "<resolved_person_id>" }
177
+ \`\`\`` : `Fetch weekly standup data:
178
+ \`\`\`json
179
+ { "resource": "workflows", "action": "weekly_standup" }
180
+ \`\`\``}
181
+
182
+ Then compose a polished weekly report with:
183
+ 1. **This week's accomplishments**: Completed tasks grouped by project
184
+ 2. **Time logged**: Hours per project this week, total hours
185
+ 3. **In progress**: Tasks still open that were worked on
186
+ 4. **Upcoming**: Any tasks with deadlines in the next 7 days
187
+ 5. **Highlights**: Notable wins or milestones reached
188
+
189
+ ${formatInstruction}`
190
+ }
191
+ }] };
192
+ }
193
+ /**
194
+ * Build the invoice-prep prompt messages
195
+ */
196
+ function invoicePrep(args) {
197
+ const project = args?.project ?? "";
198
+ const from = args?.from ?? "";
199
+ const to = args?.to ?? "";
200
+ return { messages: [{
201
+ role: "user",
202
+ content: {
203
+ type: "text",
204
+ text: `Please prepare a billing summary for project ${project ? `"${project}"` : "(project not specified)"} from ${from || "(start date not specified)"} to ${to || "(end date not specified)"}.
205
+
206
+ Fetch time entries for the date range:
207
+ \`\`\`json
208
+ {
209
+ "resource": "time",
210
+ "action": "list",
211
+ "filter": {
212
+ "project_id": "${project}",
213
+ "after": "${from}",
214
+ "before": "${to}"
215
+ },
216
+ "include": ["person", "service"],
217
+ "per_page": 200
218
+ }
219
+ \`\`\`
220
+
221
+ Fetch project services/budget lines:
222
+ \`\`\`json
223
+ { "resource": "services", "action": "list", "filter": { "project_id": "${project}" }, "per_page": 50 }
224
+ \`\`\`
225
+
226
+ Fetch the project deal/budget details:
227
+ \`\`\`json
228
+ { "resource": "deals", "action": "list", "filter": { "project_id": "${project}", "type": 2 }, "per_page": 10 }
229
+ \`\`\`
230
+
231
+ Then produce a billing summary:
232
+ 1. **Period**: ${from} → ${to}
233
+ 2. **Time entries by service**: Hours logged per service/budget line with team member breakdown
234
+ 3. **Billable totals**: If rates are available, calculate amounts per service
235
+ 4. **Budget consumed**: Planned vs actual hours per service
236
+ 5. **Invoice line items**: Suggested line items ready to copy into an invoice
237
+ 6. **Notes**: Any unbilled items, write-offs, or adjustments to flag`
238
+ }
239
+ }] };
240
+ }
241
+ /**
242
+ * Get messages for a named prompt template
243
+ */
244
+ function getPromptMessages(name, args) {
245
+ switch (name) {
246
+ case "end-of-day": return endOfDay(args);
247
+ case "project-review": return projectReview(args);
248
+ case "plan-sprint": return planSprint(args);
249
+ case "weekly-report": return weeklyReport(args);
250
+ case "invoice-prep": return invoicePrep(args);
251
+ default: throw new Error(`Unknown prompt: ${name}`);
252
+ }
253
+ }
254
+ export { PROMPT_DEFINITIONS as n, getPromptMessages as t };
255
+
256
+ //# sourceMappingURL=handlers-Cha6_ulB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers-Cha6_ulB.js","names":[],"sources":["../src/prompts/definitions.ts","../src/prompts/handlers.ts"],"sourcesContent":["/**\n * MCP Prompt Template Definitions\n *\n * Prompt templates serve as guided conversation starters that instruct the LLM\n * which productive tool calls to make and how to format the output.\n */\n\nexport interface PromptArgument {\n name: string;\n description: string;\n required: boolean;\n}\n\nexport interface PromptDefinition {\n name: string;\n description: string;\n arguments: PromptArgument[];\n}\n\nexport const PROMPT_DEFINITIONS: PromptDefinition[] = [\n {\n name: 'end-of-day',\n description: 'Compose an end-of-day standup message based on your activity today',\n arguments: [\n {\n name: 'format',\n description: 'Output format: slack, email, or plain (default: plain)',\n required: false,\n },\n ],\n },\n {\n name: 'project-review',\n description: 'Analyze project health and status with budget, tasks, and timeline overview',\n arguments: [\n {\n name: 'project',\n description: 'Project ID or project number (e.g. PRJ-123)',\n required: true,\n },\n ],\n },\n {\n name: 'plan-sprint',\n description: 'Help prioritize tasks for the next sprint based on open tasks and budget',\n arguments: [\n {\n name: 'project',\n description: 'Project ID or project number (e.g. PRJ-123)',\n required: true,\n },\n ],\n },\n {\n name: 'weekly-report',\n description: 'Generate a polished weekly progress report',\n arguments: [\n {\n name: 'person',\n description: 'Person email or ID to report on (default: current user)',\n required: false,\n },\n {\n name: 'format',\n description: 'Output format: slack, email, or plain (default: plain)',\n required: false,\n },\n ],\n },\n {\n name: 'invoice-prep',\n description: 'Prepare a billing summary for a project within a date range',\n arguments: [\n {\n name: 'project',\n description: 'Project ID or project number (e.g. PRJ-123)',\n required: true,\n },\n {\n name: 'from',\n description: 'Start date in YYYY-MM-DD format',\n required: true,\n },\n {\n name: 'to',\n description: 'End date in YYYY-MM-DD format',\n required: true,\n },\n ],\n },\n];\n","/**\n * MCP Prompt Template Handlers\n *\n * Returns messages arrays that instruct the LLM which productive tool calls to\n * make and how to format and present the output to the user.\n */\n\ntype PromptMessage = {\n role: string;\n content: { type: string; text: string };\n};\n\ntype PromptResult = {\n messages: PromptMessage[];\n};\n\n/**\n * Build the end-of-day standup prompt messages\n */\nfunction endOfDay(args?: Record<string, string>): PromptResult {\n const format = args?.format ?? 'plain';\n\n const formatInstruction =\n format === 'slack'\n ? 'Format the output as a Slack message using emoji bullets and bold text with *asterisks*.'\n : format === 'email'\n ? 'Format the output as a professional email with a subject line and proper greeting/closing.'\n : 'Format the output as a plain-text standup message with clear sections.';\n\n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Please compose my end-of-day standup message.\n\nFirst, call the productive tool to gather today's activity:\n\\`\\`\\`json\n{ \"resource\": \"summaries\", \"action\": \"my_day\" }\n\\`\\`\\`\n\nThen compose a standup message with these sections:\n- **What I did today**: Summarize completed tasks and logged time by project\n- **What I'm working on tomorrow**: Any open/in-progress tasks from today\n- **Blockers**: Note any overdue tasks or items needing attention\n\n${formatInstruction}\n\nKeep it concise — this is for a standup, not a novel.`,\n },\n },\n ],\n };\n}\n\n/**\n * Build the project-review prompt messages\n */\nfunction projectReview(args?: Record<string, string>): PromptResult {\n const project = args?.project ?? '';\n\n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Please analyze the health and status of project ${project ? `\"${project}\"` : '(project not specified)'}.\n\nFetch all project context in one call:\n\\`\\`\\`json\n{ \"resource\": \"projects\", \"action\": \"context\", \"id\": \"${project}\" }\n\\`\\`\\`\n\nAlso check the project's tasks for a fuller picture:\n\\`\\`\\`json\n{ \"resource\": \"tasks\", \"action\": \"list\", \"filter\": { \"project_id\": \"${project}\", \"status\": 1 }, \"per_page\": 50 }\n\\`\\`\\`\n\nThen provide a structured project health review covering:\n1. **Overview**: Project name, client, current status\n2. **Budget**: Budget used vs total, burn rate, projected overage risk\n3. **Tasks**: Open vs completed task counts, overdue tasks, upcoming deadlines\n4. **Recent activity**: What has been worked on recently\n5. **Health assessment**: Overall RAG status (🟢 On track / 🟡 At risk / 🔴 Critical) with reasoning\n6. **Recommendations**: Concrete next steps or concerns to address`,\n },\n },\n ],\n };\n}\n\n/**\n * Build the plan-sprint prompt messages\n */\nfunction planSprint(args?: Record<string, string>): PromptResult {\n const project = args?.project ?? '';\n\n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Please help me plan the next sprint for project ${project ? `\"${project}\"` : '(project not specified)'}.\n\nFetch all open tasks for the project:\n\\`\\`\\`json\n{ \"resource\": \"tasks\", \"action\": \"list\", \"filter\": { \"project_id\": \"${project}\", \"status\": 1 }, \"per_page\": 100 }\n\\`\\`\\`\n\nFetch the project's budget services to understand available capacity:\n\\`\\`\\`json\n{ \"resource\": \"services\", \"action\": \"list\", \"filter\": { \"project_id\": \"${project}\" }, \"per_page\": 50 }\n\\`\\`\\`\n\nThen provide sprint planning recommendations:\n1. **Backlog summary**: Total open tasks, categories/task-lists breakdown\n2. **Priority candidates**: Top tasks to tackle next sprint based on:\n - Due dates and overdue items\n - Task dependencies (if visible)\n - Effort estimates\n3. **Budget check**: Remaining budget per service — flag if any service is near its limit\n4. **Suggested sprint scope**: A realistic list of tasks for a 1-2 week sprint\n5. **Risks**: Tasks that are blocked, unassigned, or missing estimates`,\n },\n },\n ],\n };\n}\n\n/**\n * Build the weekly-report prompt messages\n */\nfunction weeklyReport(args?: Record<string, string>): PromptResult {\n const person = args?.person;\n const format = args?.format ?? 'plain';\n\n const personInstruction = person\n ? `Focus on person \"${person}\". Resolve the person ID if needed using: { \"resource\": \"people\", \"action\": \"resolve\", \"query\": \"${person}\" } first.`\n : 'Focus on the current authenticated user (use the default person from summaries).';\n\n const formatInstruction =\n format === 'slack'\n ? 'Format as a Slack message with emoji bullets, bold project names, and a summary header.'\n : format === 'email'\n ? 'Format as a professional email with subject line, greeting, bulleted highlights per project, and a closing.'\n : 'Format as a clean plain-text weekly report with clear section headers.';\n\n const standupCall = person\n ? `First resolve the person ID, then fetch weekly standup data:\n\\`\\`\\`json\n{ \"resource\": \"people\", \"action\": \"resolve\", \"query\": \"${person}\" }\n\\`\\`\\`\n\\`\\`\\`json\n{ \"resource\": \"workflows\", \"action\": \"weekly_standup\", \"person_id\": \"<resolved_person_id>\" }\n\\`\\`\\``\n : `Fetch weekly standup data:\n\\`\\`\\`json\n{ \"resource\": \"workflows\", \"action\": \"weekly_standup\" }\n\\`\\`\\``;\n\n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Please generate a weekly progress report.\n\n${personInstruction}\n\n${standupCall}\n\nThen compose a polished weekly report with:\n1. **This week's accomplishments**: Completed tasks grouped by project\n2. **Time logged**: Hours per project this week, total hours\n3. **In progress**: Tasks still open that were worked on\n4. **Upcoming**: Any tasks with deadlines in the next 7 days\n5. **Highlights**: Notable wins or milestones reached\n\n${formatInstruction}`,\n },\n },\n ],\n };\n}\n\n/**\n * Build the invoice-prep prompt messages\n */\nfunction invoicePrep(args?: Record<string, string>): PromptResult {\n const project = args?.project ?? '';\n const from = args?.from ?? '';\n const to = args?.to ?? '';\n\n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Please prepare a billing summary for project ${project ? `\"${project}\"` : '(project not specified)'} from ${from || '(start date not specified)'} to ${to || '(end date not specified)'}.\n\nFetch time entries for the date range:\n\\`\\`\\`json\n{\n \"resource\": \"time\",\n \"action\": \"list\",\n \"filter\": {\n \"project_id\": \"${project}\",\n \"after\": \"${from}\",\n \"before\": \"${to}\"\n },\n \"include\": [\"person\", \"service\"],\n \"per_page\": 200\n}\n\\`\\`\\`\n\nFetch project services/budget lines:\n\\`\\`\\`json\n{ \"resource\": \"services\", \"action\": \"list\", \"filter\": { \"project_id\": \"${project}\" }, \"per_page\": 50 }\n\\`\\`\\`\n\nFetch the project deal/budget details:\n\\`\\`\\`json\n{ \"resource\": \"deals\", \"action\": \"list\", \"filter\": { \"project_id\": \"${project}\", \"type\": 2 }, \"per_page\": 10 }\n\\`\\`\\`\n\nThen produce a billing summary:\n1. **Period**: ${from} → ${to}\n2. **Time entries by service**: Hours logged per service/budget line with team member breakdown\n3. **Billable totals**: If rates are available, calculate amounts per service\n4. **Budget consumed**: Planned vs actual hours per service\n5. **Invoice line items**: Suggested line items ready to copy into an invoice\n6. **Notes**: Any unbilled items, write-offs, or adjustments to flag`,\n },\n },\n ],\n };\n}\n\n/**\n * Get messages for a named prompt template\n */\nexport function getPromptMessages(name: string, args?: Record<string, string>): PromptResult {\n switch (name) {\n case 'end-of-day':\n return endOfDay(args);\n case 'project-review':\n return projectReview(args);\n case 'plan-sprint':\n return planSprint(args);\n case 'weekly-report':\n return weeklyReport(args);\n case 'invoice-prep':\n return invoicePrep(args);\n default:\n throw new Error(`Unknown prompt: ${name}`);\n }\n}\n"],"mappings":"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"}
package/dist/handlers.js CHANGED
@@ -1,2 +1,2 @@
1
- import { t as executeToolWithCredentials } from "./handlers-CaOBYauF.js";
1
+ import { t as executeToolWithCredentials } from "./handlers-BvwBrRHp.js";
2
2
  export { executeToolWithCredentials };
package/dist/http.js CHANGED
@@ -1,5 +1,5 @@
1
- import { n as INSTRUCTIONS, t as VERSION } from "./version-C4It3BAM.js";
2
- import { t as executeToolWithCredentials } from "./handlers-CaOBYauF.js";
1
+ import { n as INSTRUCTIONS, t as VERSION } from "./version-KdH6s_ty.js";
2
+ import { t as executeToolWithCredentials } from "./handlers-BvwBrRHp.js";
3
3
  import "./handlers.js";
4
4
  import { TOOLS } from "./tools.js";
5
5
  import { parseAuthHeader } from "./auth.js";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { n as INSTRUCTIONS, t as VERSION } from "./version-C4It3BAM.js";
3
- import "./handlers-CaOBYauF.js";
2
+ import { n as INSTRUCTIONS, t as VERSION } from "./version-KdH6s_ty.js";
3
+ import "./handlers-BvwBrRHp.js";
4
4
  import { getAvailablePrompts, getAvailableTools, handlePrompt, handleToolCall } from "./stdio.js";
5
5
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
6
6
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -45,7 +45,7 @@ function createStdioServer() {
45
45
  return { prompts: getAvailablePrompts() };
46
46
  });
47
47
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
48
- return handlePrompt(request.params.name);
48
+ return handlePrompt(request.params.name, request.params.arguments);
49
49
  });
50
50
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
51
51
  const { name, arguments: args } = request.params;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * Productive MCP Server - Stdio Transport\n *\n * This is the local execution mode using stdio transport.\n * For remote HTTP deployment, use server.ts instead.\n *\n * Usage:\n * npx @studiometa/productive-mcp\n *\n * Or in Claude Desktop config:\n * {\n * \"mcpServers\": {\n * \"productive\": {\n * \"command\": \"npx\",\n * \"args\": [\"@studiometa/productive-mcp\"]\n * }\n * }\n * }\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n ListPromptsRequestSchema,\n GetPromptRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\n\nimport { INSTRUCTIONS } from './instructions.js';\nimport { getAvailableTools, getAvailablePrompts, handleToolCall, handlePrompt } from './stdio.js';\nimport { VERSION } from './version.js';\n\n/**\n * Create and configure the MCP server\n */\nexport function createStdioServer(): Server {\n const server = new Server(\n {\n name: 'productive-mcp',\n version: VERSION,\n },\n {\n capabilities: {\n tools: {},\n prompts: {},\n },\n instructions: INSTRUCTIONS,\n },\n );\n\n // List available tools (including stdio-only configuration tools)\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return { tools: getAvailableTools() };\n });\n\n // List available prompts\n server.setRequestHandler(ListPromptsRequestSchema, async () => {\n return { prompts: getAvailablePrompts() };\n });\n\n // Get prompt\n server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n return handlePrompt(request.params.name);\n });\n\n // Handle tool calls\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n return await handleToolCall(name, (args as Record<string, unknown>) || {});\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: 'text', text: `Error: ${message}` }],\n isError: true,\n };\n }\n });\n\n return server;\n}\n\n/**\n * Start the stdio server\n */\nexport async function startStdioServer(): Promise<void> {\n const server = createStdioServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error(`Productive MCP server v${VERSION} running on stdio`);\n}\n\n// Start server when run directly\nconst isMainModule =\n import.meta.url === `file://${process.argv[1]}` ||\n process.argv[1]?.endsWith('/productive-mcp') ||\n process.argv[1]?.endsWith('\\\\productive-mcp');\n\nif (isMainModule) {\n startStdioServer().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,oBAA4B;CAC1C,MAAM,SAAS,IAAI,OACjB;EACE,MAAM;EACN,SAAS;EACV,EACD;EACE,cAAc;GACZ,OAAO,EAAE;GACT,SAAS,EAAE;GACZ;EACD,cAAc;EACf,CACF;AAGD,QAAO,kBAAkB,wBAAwB,YAAY;AAC3D,SAAO,EAAE,OAAO,mBAAmB,EAAE;GACrC;AAGF,QAAO,kBAAkB,0BAA0B,YAAY;AAC7D,SAAO,EAAE,SAAS,qBAAqB,EAAE;GACzC;AAGF,QAAO,kBAAkB,wBAAwB,OAAO,YAAY;AAClE,SAAO,aAAa,QAAQ,OAAO,KAAK;GACxC;AAGF,QAAO,kBAAkB,uBAAuB,OAAO,YAAY;EACjE,MAAM,EAAE,MAAM,WAAW,SAAS,QAAQ;AAE1C,MAAI;AACF,UAAO,MAAM,eAAe,MAAO,QAAoC,EAAE,CAAC;WACnE,OAAO;AAEd,UAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAQ,MAAM,UAFlB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;KAEf,CAAC;IACtD,SAAS;IACV;;GAEH;AAEF,QAAO;;;;;AAMT,eAAsB,mBAAkC;CACtD,MAAM,SAAS,mBAAmB;CAClC,MAAM,YAAY,IAAI,sBAAsB;AAC5C,OAAM,OAAO,QAAQ,UAAU;AAC/B,SAAQ,MAAM,0BAA0B,QAAQ,mBAAmB;;AASrE,IAJE,OAAO,KAAK,QAAQ,UAAU,QAAQ,KAAK,QAC3C,QAAQ,KAAK,IAAI,SAAS,kBAAkB,IAC5C,QAAQ,KAAK,IAAI,SAAS,mBAAmB,CAG7C,mBAAkB,CAAC,OAAO,UAAU;AAClC,SAAQ,MAAM,gBAAgB,MAAM;AACpC,SAAQ,KAAK,EAAE;EACf"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * Productive MCP Server - Stdio Transport\n *\n * This is the local execution mode using stdio transport.\n * For remote HTTP deployment, use server.ts instead.\n *\n * Usage:\n * npx @studiometa/productive-mcp\n *\n * Or in Claude Desktop config:\n * {\n * \"mcpServers\": {\n * \"productive\": {\n * \"command\": \"npx\",\n * \"args\": [\"@studiometa/productive-mcp\"]\n * }\n * }\n * }\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n ListPromptsRequestSchema,\n GetPromptRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\n\nimport { INSTRUCTIONS } from './instructions.js';\nimport { getAvailableTools, getAvailablePrompts, handleToolCall, handlePrompt } from './stdio.js';\nimport { VERSION } from './version.js';\n\n/**\n * Create and configure the MCP server\n */\nexport function createStdioServer(): Server {\n const server = new Server(\n {\n name: 'productive-mcp',\n version: VERSION,\n },\n {\n capabilities: {\n tools: {},\n prompts: {},\n },\n instructions: INSTRUCTIONS,\n },\n );\n\n // List available tools (including stdio-only configuration tools)\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return { tools: getAvailableTools() };\n });\n\n // List available prompts\n server.setRequestHandler(ListPromptsRequestSchema, async () => {\n return { prompts: getAvailablePrompts() };\n });\n\n // Get prompt\n server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n return handlePrompt(request.params.name, request.params.arguments as Record<string, string>);\n });\n\n // Handle tool calls\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n return await handleToolCall(name, (args as Record<string, unknown>) || {});\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: 'text', text: `Error: ${message}` }],\n isError: true,\n };\n }\n });\n\n return server;\n}\n\n/**\n * Start the stdio server\n */\nexport async function startStdioServer(): Promise<void> {\n const server = createStdioServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error(`Productive MCP server v${VERSION} running on stdio`);\n}\n\n// Start server when run directly\nconst isMainModule =\n import.meta.url === `file://${process.argv[1]}` ||\n process.argv[1]?.endsWith('/productive-mcp') ||\n process.argv[1]?.endsWith('\\\\productive-mcp');\n\nif (isMainModule) {\n startStdioServer().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,oBAA4B;CAC1C,MAAM,SAAS,IAAI,OACjB;EACE,MAAM;EACN,SAAS;EACV,EACD;EACE,cAAc;GACZ,OAAO,EAAE;GACT,SAAS,EAAE;GACZ;EACD,cAAc;EACf,CACF;AAGD,QAAO,kBAAkB,wBAAwB,YAAY;AAC3D,SAAO,EAAE,OAAO,mBAAmB,EAAE;GACrC;AAGF,QAAO,kBAAkB,0BAA0B,YAAY;AAC7D,SAAO,EAAE,SAAS,qBAAqB,EAAE;GACzC;AAGF,QAAO,kBAAkB,wBAAwB,OAAO,YAAY;AAClE,SAAO,aAAa,QAAQ,OAAO,MAAM,QAAQ,OAAO,UAAoC;GAC5F;AAGF,QAAO,kBAAkB,uBAAuB,OAAO,YAAY;EACjE,MAAM,EAAE,MAAM,WAAW,SAAS,QAAQ;AAE1C,MAAI;AACF,UAAO,MAAM,eAAe,MAAO,QAAoC,EAAE,CAAC;WACnE,OAAO;AAEd,UAAO;IACL,SAAS,CAAC;KAAE,MAAM;KAAQ,MAAM,UAFlB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;KAEf,CAAC;IACtD,SAAS;IACV;;GAEH;AAEF,QAAO;;;;;AAMT,eAAsB,mBAAkC;CACtD,MAAM,SAAS,mBAAmB;CAClC,MAAM,YAAY,IAAI,sBAAsB;AAC5C,OAAM,OAAO,QAAQ,UAAU;AAC/B,SAAQ,MAAM,0BAA0B,QAAQ,mBAAmB;;AASrE,IAJE,OAAO,KAAK,QAAQ,UAAU,QAAQ,KAAK,QAC3C,QAAQ,KAAK,IAAI,SAAS,kBAAkB,IAC5C,QAAQ,KAAK,IAAI,SAAS,mBAAmB,CAG7C,mBAAkB,CAAC,OAAO,UAAU;AAClC,SAAQ,MAAM,gBAAgB,MAAM;AACpC,SAAQ,KAAK,EAAE;EACf"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * MCP Prompt Template Definitions
3
+ *
4
+ * Prompt templates serve as guided conversation starters that instruct the LLM
5
+ * which productive tool calls to make and how to format the output.
6
+ */
7
+ export interface PromptArgument {
8
+ name: string;
9
+ description: string;
10
+ required: boolean;
11
+ }
12
+ export interface PromptDefinition {
13
+ name: string;
14
+ description: string;
15
+ arguments: PromptArgument[];
16
+ }
17
+ export declare const PROMPT_DEFINITIONS: PromptDefinition[];
18
+ //# sourceMappingURL=definitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/prompts/definitions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAuEhD,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * MCP Prompt Template Handlers
3
+ *
4
+ * Returns messages arrays that instruct the LLM which productive tool calls to
5
+ * make and how to format and present the output to the user.
6
+ */
7
+ type PromptMessage = {
8
+ role: string;
9
+ content: {
10
+ type: string;
11
+ text: string;
12
+ };
13
+ };
14
+ type PromptResult = {
15
+ messages: PromptMessage[];
16
+ };
17
+ /**
18
+ * Get messages for a named prompt template
19
+ */
20
+ export declare function getPromptMessages(name: string, args?: Record<string, string>): PromptResult;
21
+ export {};
22
+ //# sourceMappingURL=handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/prompts/handlers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B,CAAC;AAqOF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,YAAY,CAe3F"}
@@ -0,0 +1,3 @@
1
+ export * from './definitions.js';
2
+ export * from './handlers.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC"}
package/dist/server.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { t as VERSION } from "./version-C4It3BAM.js";
3
- import "./handlers-CaOBYauF.js";
2
+ import { t as VERSION } from "./version-KdH6s_ty.js";
3
+ import "./handlers-BvwBrRHp.js";
4
4
  import { createHttpApp } from "./http.js";
5
5
  import { toNodeListener } from "h3";
6
6
  import { createServer } from "node:http";
package/dist/stdio.d.ts CHANGED
@@ -52,11 +52,7 @@ export declare function getAvailableTools(): {
52
52
  /**
53
53
  * Get available prompts
54
54
  */
55
- export declare function getAvailablePrompts(): {
56
- name: string;
57
- description: string;
58
- arguments: never[];
59
- }[];
55
+ export declare function getAvailablePrompts(): import("./prompts/definitions.js").PromptDefinition[];
60
56
  /**
61
57
  * Handle the setup_productive prompt
62
58
  */
@@ -88,7 +84,7 @@ export declare function handleToolCall(name: string, args: Record<string, unknow
88
84
  /**
89
85
  * Handle a prompt request
90
86
  */
91
- export declare function handlePrompt(name: string): Promise<{
87
+ export declare function handlePrompt(name: string, args?: Record<string, string>): Promise<{
92
88
  messages: Array<{
93
89
  role: string;
94
90
  content: {
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAOzE,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC;AAExC;;GAEG;AACH,wBAAgB,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAEhC;AAED;;GAEG;AACH,wBAAgB,mBAAmB;;;;IAQlC;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC;IACjD,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;CAC5E,CAAC,CAiBD;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,UAAU,CAAC,CA6BtB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,UAAU,CAAC,CAqB/D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,UAAU,CAAC,CA8BrB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACxD,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;CAC5E,CAAC,CAMD"}
1
+ {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAQzE,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC;AAExC;;GAEG;AACH,wBAAgB,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAEhC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,0DASlC;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC;IACjD,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;CAC5E,CAAC,CAiBD;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,UAAU,CAAC,CA6BtB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,UAAU,CAAC,CAqB/D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,UAAU,CAAC,CA8BrB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,OAAO,CAAC;IACT,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;CAC5E,CAAC,CAMD"}
package/dist/stdio.js CHANGED
@@ -1,5 +1,6 @@
1
- import { t as executeToolWithCredentials } from "./handlers-CaOBYauF.js";
1
+ import { t as executeToolWithCredentials } from "./handlers-BvwBrRHp.js";
2
2
  import "./handlers.js";
3
+ import { n as PROMPT_DEFINITIONS, t as getPromptMessages } from "./handlers-Cha6_ulB.js";
3
4
  import { STDIO_ONLY_TOOLS, TOOLS } from "./tools.js";
4
5
  import { getConfig, setConfig } from "@studiometa/productive-api";
5
6
  /**
@@ -16,7 +17,7 @@ function getAvailablePrompts() {
16
17
  name: "setup_productive",
17
18
  description: "Interactive setup for Productive.io credentials",
18
19
  arguments: []
19
- }];
20
+ }, ...PROMPT_DEFINITIONS];
20
21
  }
21
22
  /**
22
23
  * Handle the setup_productive prompt
@@ -90,9 +91,9 @@ async function handleToolCall(name, args) {
90
91
  /**
91
92
  * Handle a prompt request
92
93
  */
93
- async function handlePrompt(name) {
94
+ async function handlePrompt(name, args) {
94
95
  if (name === "setup_productive") return handleSetupPrompt();
95
- throw new Error(`Unknown prompt: ${name}`);
96
+ return getPromptMessages(name, args);
96
97
  }
97
98
  export { getAvailablePrompts, getAvailableTools, handleConfigureTool, handleGetConfigTool, handlePrompt, handleSetupPrompt, handleToolCall };
98
99
 
package/dist/stdio.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.js","names":[],"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';\n\nimport { getConfig, setConfig } from '@studiometa/productive-api';\n\nimport { executeToolWithCredentials } from './handlers.js';\nimport { TOOLS, STDIO_ONLY_TOOLS } from './tools.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"],"mappings":";;;;;;;AAmBA,SAAgB,oBAAoB;AAClC,QAAO,CAAC,GAAG,OAAO,GAAG,iBAAiB;;;;;AAMxC,SAAgB,sBAAsB;AACpC,QAAO,CACL;EACE,MAAM;EACN,aAAa;EACb,WAAW,EAAE;EACd,CACF;;;;;AAMH,eAAsB,oBAEnB;CACD,MAAM,SAAS,MAAM,WAAW;AAGhC,QAAO,EACL,UAAU,CACR;EACE,MAAM;EACN,SAAS;GACP,MAAM;GACN,MARU,CAAC,EAAE,OAAO,kBAAkB,OAAO,YASzC,wFACA;GACL;EACF,CACF,EACF;;;;;AAMH,eAAsB,oBAAoB,MAIlB;CACtB,MAAM,EAAE,gBAAgB,UAAU,WAAW;AAE7C,OAAM,UAAU,kBAAkB,eAAe;AACjD,OAAM,UAAU,YAAY,SAAS;AACrC,KAAI,OACF,OAAM,UAAU,UAAU,OAAO;AAGnC,QAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE,SAAS;GACT,SAAS;GACT,YAAY;IACV;IACA,QAAQ,UAAU;IAClB,UAAU,QAAQ,SAAS,MAAM,GAAG;IACrC;GACF,EACD,MACA,EACD;EACF,CACF,EACF;;;;;AAMH,eAAsB,sBAA2C;CAC/D,MAAM,gBAAgB,MAAM,WAAW;AACvC,QAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE,gBAAgB,cAAc,kBAAkB;GAChD,QAAQ,cAAc,UAAU;GAChC,UAAU,cAAc,WACpB,QAAQ,cAAc,SAAS,MAAM,GAAG,GACxC;GACJ,YAAY,CAAC,EAAE,cAAc,kBAAkB,cAAc;GAC9D,EACD,MACA,EACD;EACF,CACF,EACF;;;;;AAMH,eAAsB,eACpB,MACA,MACqB;AAErB,KAAI,SAAS,uBACX,QAAO,oBAAoB,KAAkD;AAG/E,KAAI,SAAS,wBACX,QAAO,qBAAqB;CAI9B,MAAM,SAAS,MAAM,WAAW;AAChC,KAAI,CAAC,OAAO,kBAAkB,CAAC,OAAO,SACpC,QAAO;EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM;GACP,CACF;EACD,SAAS;EACV;AAIH,QAAO,2BAA2B,MAAM,MAAM;EAC5C,gBAAgB,OAAO;EACvB,UAAU,OAAO;EACjB,QAAQ,OAAO;EAChB,CAAC;;;;;AAMJ,eAAsB,aAAa,MAEhC;AACD,KAAI,SAAS,mBACX,QAAO,mBAAmB;AAG5B,OAAM,IAAI,MAAM,mBAAmB,OAAO"}
1
+ {"version":3,"file":"stdio.js","names":[],"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';\n\nimport { getConfig, setConfig } from '@studiometa/productive-api';\n\nimport { executeToolWithCredentials } from './handlers.js';\nimport { PROMPT_DEFINITIONS, getPromptMessages } from './prompts/index.js';\nimport { TOOLS, STDIO_ONLY_TOOLS } from './tools.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 ...PROMPT_DEFINITIONS,\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(\n name: string,\n args?: Record<string, string>,\n): Promise<{\n messages: Array<{ role: string; content: { type: string; text: string } }>;\n}> {\n if (name === 'setup_productive') {\n return handleSetupPrompt();\n }\n\n return getPromptMessages(name, args);\n}\n"],"mappings":";;;;;;;;AAoBA,SAAgB,oBAAoB;AAClC,QAAO,CAAC,GAAG,OAAO,GAAG,iBAAiB;;;;;AAMxC,SAAgB,sBAAsB;AACpC,QAAO,CACL;EACE,MAAM;EACN,aAAa;EACb,WAAW,EAAE;EACd,EACD,GAAG,mBACJ;;;;;AAMH,eAAsB,oBAEnB;CACD,MAAM,SAAS,MAAM,WAAW;AAGhC,QAAO,EACL,UAAU,CACR;EACE,MAAM;EACN,SAAS;GACP,MAAM;GACN,MARU,CAAC,EAAE,OAAO,kBAAkB,OAAO,YASzC,wFACA;GACL;EACF,CACF,EACF;;;;;AAMH,eAAsB,oBAAoB,MAIlB;CACtB,MAAM,EAAE,gBAAgB,UAAU,WAAW;AAE7C,OAAM,UAAU,kBAAkB,eAAe;AACjD,OAAM,UAAU,YAAY,SAAS;AACrC,KAAI,OACF,OAAM,UAAU,UAAU,OAAO;AAGnC,QAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE,SAAS;GACT,SAAS;GACT,YAAY;IACV;IACA,QAAQ,UAAU;IAClB,UAAU,QAAQ,SAAS,MAAM,GAAG;IACrC;GACF,EACD,MACA,EACD;EACF,CACF,EACF;;;;;AAMH,eAAsB,sBAA2C;CAC/D,MAAM,gBAAgB,MAAM,WAAW;AACvC,QAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE,gBAAgB,cAAc,kBAAkB;GAChD,QAAQ,cAAc,UAAU;GAChC,UAAU,cAAc,WACpB,QAAQ,cAAc,SAAS,MAAM,GAAG,GACxC;GACJ,YAAY,CAAC,EAAE,cAAc,kBAAkB,cAAc;GAC9D,EACD,MACA,EACD;EACF,CACF,EACF;;;;;AAMH,eAAsB,eACpB,MACA,MACqB;AAErB,KAAI,SAAS,uBACX,QAAO,oBAAoB,KAAkD;AAG/E,KAAI,SAAS,wBACX,QAAO,qBAAqB;CAI9B,MAAM,SAAS,MAAM,WAAW;AAChC,KAAI,CAAC,OAAO,kBAAkB,CAAC,OAAO,SACpC,QAAO;EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM;GACP,CACF;EACD,SAAS;EACV;AAIH,QAAO,2BAA2B,MAAM,MAAM;EAC5C,gBAAgB,OAAO;EACvB,UAAU,OAAO;EACjB,QAAQ,OAAO;EAChB,CAAC;;;;;AAMJ,eAAsB,aACpB,MACA,MAGC;AACD,KAAI,SAAS,mBACX,QAAO,mBAAmB;AAG5B,QAAO,kBAAkB,MAAM,KAAK"}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAwB/D;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,KAAK,EAAE,IAAI,EAsGvB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,IAAI,EAoClC,CAAC"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAwB/D;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,KAAK,EAAE,IAAI,EA0GvB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,IAAI,EAoClC,CAAC"}
package/dist/tools.js CHANGED
@@ -102,6 +102,10 @@ const TOOLS = [{
102
102
  type: "string",
103
103
  description: "Comment/page body content"
104
104
  },
105
+ hidden: {
106
+ type: "boolean",
107
+ description: "Set to true to hide comment from client (comments only)"
108
+ },
105
109
  deal_id: { type: "string" },
106
110
  comment_id: {
107
111
  type: "string",
package/dist/tools.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tools.js","names":[],"sources":["../src/tools.ts"],"sourcesContent":["import type { Tool } from '@modelcontextprotocol/sdk/types.js';\n\nimport { RESOURCES, ACTIONS, REPORT_TYPES } from '@studiometa/productive-core';\n\n/**\n * Generate the tool description dynamically from the constants.\n * Adding a resource or action to constants.ts automatically updates this description.\n */\nfunction generateDescription(): string {\n return [\n 'Productive.io API.',\n `Resources: ${RESOURCES.join(', ')}.`,\n `Actions: ${ACTIONS.join(', ')} (varies by resource).`,\n 'Discovery: action=help with any resource for filters, fields, examples. action=schema for compact machine-readable spec.',\n 'Filters: filter:{key:value}. Common: project_id, person_id, after/before (YYYY-MM-DD).',\n 'Includes: include:[...] for related data (e.g. [\"project\",\"assignee\"]).',\n 'Output: compact=false for full detail (default for get; list defaults true).',\n 'Search: query for text search on list actions. Cross-resource: resource=search action=run with query searches projects, companies, people, tasks simultaneously.',\n 'Reports: resource=reports action=get with report_type, from, to.',\n 'Batch: resource=batch action=run with operations=[{resource,action,...}] executes up to 10 ops in parallel.',\n 'Rich context: action=context on tasks/projects/deals for full context in one call.',\n ].join('\\n');\n}\n\n/**\n * Single consolidated tool for Productive.io MCP server\n *\n * The resource/action/report_type enums and description are derived from\n * the shared constants in constants.ts — the single source of truth for both\n * the MCP tool definition and the Zod validation schemas.\n * Adding a new resource, action, or report type there automatically updates\n * both the tool exposed to clients and the validation layer.\n *\n * MCP Annotations (for MCP directory compliance):\n * - readOnlyHint: false - Tool can create/update data\n * - destructiveHint: false - Tool does not permanently delete data\n * - idempotentHint: false - Create actions are not idempotent\n * - openWorldHint: true - Tool interacts with external Productive.io API\n */\nexport const TOOLS: Tool[] = [\n {\n name: 'productive',\n description: generateDescription(),\n annotations: {\n title: 'Productive.io',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n resource: {\n type: 'string',\n enum: [...RESOURCES],\n },\n action: {\n type: 'string',\n enum: [...ACTIONS],\n description: 'Use \"help\" for resource documentation',\n },\n id: { type: 'string' },\n filter: { type: 'object' },\n page: { type: 'number' },\n per_page: { type: 'number' },\n compact: {\n type: 'boolean',\n description: 'Compact output (default: true for list, false for get)',\n },\n include: {\n type: 'array',\n items: { type: 'string' },\n description: 'Related data to include (e.g. [\"project\",\"assignee\"])',\n },\n query: { type: 'string', description: 'Text search for list actions' },\n resources: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Resource types to search (for resource=search). Defaults to [projects, companies, people, tasks]. Valid values: projects, companies, people, tasks, deals.',\n },\n // Common fields\n person_id: { type: 'string' },\n service_id: { type: 'string' },\n task_id: { type: 'string' },\n company_id: { type: 'string' },\n time: { type: 'number' },\n date: { type: 'string' },\n note: { type: 'string' },\n // Task fields\n title: { type: 'string' },\n project_id: { type: 'string' },\n task_list_id: { type: 'string' },\n description: { type: 'string' },\n assignee_id: { type: 'string' },\n // Company fields\n name: { type: 'string' },\n // Page fields\n page_id: { type: 'string', description: 'Page ID (list pages to find)' },\n parent_page_id: { type: 'string', description: 'Parent page ID for sub-pages' },\n // Comment fields\n body: { type: 'string', description: 'Comment/page body content' },\n deal_id: { type: 'string' },\n // Attachment fields\n comment_id: { type: 'string', description: 'Comment ID (for attachments)' },\n // Timer fields\n time_entry_id: { type: 'string' },\n // Booking fields\n started_on: { type: 'string', description: 'Booking date (YYYY-MM-DD)' },\n ended_on: { type: 'string', description: 'Booking end date (YYYY-MM-DD)' },\n event_id: { type: 'string' },\n // Report fields\n report_type: {\n type: 'string',\n enum: [...REPORT_TYPES],\n description: 'Required for resource=reports action=get',\n },\n group: { type: 'string', description: 'Report grouping: person, project, service' },\n from: { type: 'string', description: 'Report start (YYYY-MM-DD); filter.after for time' },\n to: { type: 'string', description: 'Report end (YYYY-MM-DD); filter.before for time' },\n status: { type: 'string' },\n // Batch fields\n operations: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n resource: { type: 'string' },\n action: { type: 'string' },\n },\n required: ['resource', 'action'],\n },\n maxItems: 10,\n description:\n 'Array of operations for batch execution (max 10). Each operation needs resource, action, and any additional params.',\n },\n },\n required: ['resource', 'action'],\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',\n annotations: {\n title: 'Configure Productive',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n inputSchema: {\n type: 'object',\n properties: {\n organizationId: { type: 'string' },\n apiToken: { type: 'string' },\n userId: { type: 'string' },\n },\n required: ['organizationId', 'apiToken'],\n },\n },\n {\n name: 'productive_get_config',\n description: 'Get current configuration',\n annotations: {\n title: 'Get Productive Config',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n];\n"],"mappings":"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"}
1
+ {"version":3,"file":"tools.js","names":[],"sources":["../src/tools.ts"],"sourcesContent":["import type { Tool } from '@modelcontextprotocol/sdk/types.js';\n\nimport { RESOURCES, ACTIONS, REPORT_TYPES } from '@studiometa/productive-core';\n\n/**\n * Generate the tool description dynamically from the constants.\n * Adding a resource or action to constants.ts automatically updates this description.\n */\nfunction generateDescription(): string {\n return [\n 'Productive.io API.',\n `Resources: ${RESOURCES.join(', ')}.`,\n `Actions: ${ACTIONS.join(', ')} (varies by resource).`,\n 'Discovery: action=help with any resource for filters, fields, examples. action=schema for compact machine-readable spec.',\n 'Filters: filter:{key:value}. Common: project_id, person_id, after/before (YYYY-MM-DD).',\n 'Includes: include:[...] for related data (e.g. [\"project\",\"assignee\"]).',\n 'Output: compact=false for full detail (default for get; list defaults true).',\n 'Search: query for text search on list actions. Cross-resource: resource=search action=run with query searches projects, companies, people, tasks simultaneously.',\n 'Reports: resource=reports action=get with report_type, from, to.',\n 'Batch: resource=batch action=run with operations=[{resource,action,...}] executes up to 10 ops in parallel.',\n 'Rich context: action=context on tasks/projects/deals for full context in one call.',\n ].join('\\n');\n}\n\n/**\n * Single consolidated tool for Productive.io MCP server\n *\n * The resource/action/report_type enums and description are derived from\n * the shared constants in constants.ts — the single source of truth for both\n * the MCP tool definition and the Zod validation schemas.\n * Adding a new resource, action, or report type there automatically updates\n * both the tool exposed to clients and the validation layer.\n *\n * MCP Annotations (for MCP directory compliance):\n * - readOnlyHint: false - Tool can create/update data\n * - destructiveHint: false - Tool does not permanently delete data\n * - idempotentHint: false - Create actions are not idempotent\n * - openWorldHint: true - Tool interacts with external Productive.io API\n */\nexport const TOOLS: Tool[] = [\n {\n name: 'productive',\n description: generateDescription(),\n annotations: {\n title: 'Productive.io',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n resource: {\n type: 'string',\n enum: [...RESOURCES],\n },\n action: {\n type: 'string',\n enum: [...ACTIONS],\n description: 'Use \"help\" for resource documentation',\n },\n id: { type: 'string' },\n filter: { type: 'object' },\n page: { type: 'number' },\n per_page: { type: 'number' },\n compact: {\n type: 'boolean',\n description: 'Compact output (default: true for list, false for get)',\n },\n include: {\n type: 'array',\n items: { type: 'string' },\n description: 'Related data to include (e.g. [\"project\",\"assignee\"])',\n },\n query: { type: 'string', description: 'Text search for list actions' },\n resources: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Resource types to search (for resource=search). Defaults to [projects, companies, people, tasks]. Valid values: projects, companies, people, tasks, deals.',\n },\n // Common fields\n person_id: { type: 'string' },\n service_id: { type: 'string' },\n task_id: { type: 'string' },\n company_id: { type: 'string' },\n time: { type: 'number' },\n date: { type: 'string' },\n note: { type: 'string' },\n // Task fields\n title: { type: 'string' },\n project_id: { type: 'string' },\n task_list_id: { type: 'string' },\n description: { type: 'string' },\n assignee_id: { type: 'string' },\n // Company fields\n name: { type: 'string' },\n // Page fields\n page_id: { type: 'string', description: 'Page ID (list pages to find)' },\n parent_page_id: { type: 'string', description: 'Parent page ID for sub-pages' },\n // Comment fields\n body: { type: 'string', description: 'Comment/page body content' },\n hidden: {\n type: 'boolean',\n description: 'Set to true to hide comment from client (comments only)',\n },\n deal_id: { type: 'string' },\n // Attachment fields\n comment_id: { type: 'string', description: 'Comment ID (for attachments)' },\n // Timer fields\n time_entry_id: { type: 'string' },\n // Booking fields\n started_on: { type: 'string', description: 'Booking date (YYYY-MM-DD)' },\n ended_on: { type: 'string', description: 'Booking end date (YYYY-MM-DD)' },\n event_id: { type: 'string' },\n // Report fields\n report_type: {\n type: 'string',\n enum: [...REPORT_TYPES],\n description: 'Required for resource=reports action=get',\n },\n group: { type: 'string', description: 'Report grouping: person, project, service' },\n from: { type: 'string', description: 'Report start (YYYY-MM-DD); filter.after for time' },\n to: { type: 'string', description: 'Report end (YYYY-MM-DD); filter.before for time' },\n status: { type: 'string' },\n // Batch fields\n operations: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n resource: { type: 'string' },\n action: { type: 'string' },\n },\n required: ['resource', 'action'],\n },\n maxItems: 10,\n description:\n 'Array of operations for batch execution (max 10). Each operation needs resource, action, and any additional params.',\n },\n },\n required: ['resource', 'action'],\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',\n annotations: {\n title: 'Configure Productive',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n inputSchema: {\n type: 'object',\n properties: {\n organizationId: { type: 'string' },\n apiToken: { type: 'string' },\n userId: { type: 'string' },\n },\n required: ['organizationId', 'apiToken'],\n },\n },\n {\n name: 'productive_get_config',\n description: 'Get current configuration',\n annotations: {\n title: 'Get Productive Config',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n];\n"],"mappings":";;;;;AAQA,SAAS,sBAA8B;AACrC,QAAO;EACL;EACA,cAAc,UAAU,KAAK,KAAK,CAAC;EACnC,YAAY,QAAQ,KAAK,KAAK,CAAC;EAC/B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,KAAK,KAAK;;;;;;;;;;;;;;;;;AAkBd,MAAa,QAAgB,CAC3B;CACE,MAAM;CACN,aAAa,qBAAqB;CAClC,aAAa;EACX,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EAChB,eAAe;EAChB;CACD,aAAa;EACX,MAAM;EACN,YAAY;GACV,UAAU;IACR,MAAM;IACN,MAAM,CAAC,GAAG,UAAU;IACrB;GACD,QAAQ;IACN,MAAM;IACN,MAAM,CAAC,GAAG,QAAQ;IAClB,aAAa;IACd;GACD,IAAI,EAAE,MAAM,UAAU;GACtB,QAAQ,EAAE,MAAM,UAAU;GAC1B,MAAM,EAAE,MAAM,UAAU;GACxB,UAAU,EAAE,MAAM,UAAU;GAC5B,SAAS;IACP,MAAM;IACN,aAAa;IACd;GACD,SAAS;IACP,MAAM;IACN,OAAO,EAAE,MAAM,UAAU;IACzB,aAAa;IACd;GACD,OAAO;IAAE,MAAM;IAAU,aAAa;IAAgC;GACtE,WAAW;IACT,MAAM;IACN,OAAO,EAAE,MAAM,UAAU;IACzB,aACE;IACH;GAED,WAAW,EAAE,MAAM,UAAU;GAC7B,YAAY,EAAE,MAAM,UAAU;GAC9B,SAAS,EAAE,MAAM,UAAU;GAC3B,YAAY,EAAE,MAAM,UAAU;GAC9B,MAAM,EAAE,MAAM,UAAU;GACxB,MAAM,EAAE,MAAM,UAAU;GACxB,MAAM,EAAE,MAAM,UAAU;GAExB,OAAO,EAAE,MAAM,UAAU;GACzB,YAAY,EAAE,MAAM,UAAU;GAC9B,cAAc,EAAE,MAAM,UAAU;GAChC,aAAa,EAAE,MAAM,UAAU;GAC/B,aAAa,EAAE,MAAM,UAAU;GAE/B,MAAM,EAAE,MAAM,UAAU;GAExB,SAAS;IAAE,MAAM;IAAU,aAAa;IAAgC;GACxE,gBAAgB;IAAE,MAAM;IAAU,aAAa;IAAgC;GAE/E,MAAM;IAAE,MAAM;IAAU,aAAa;IAA6B;GAClE,QAAQ;IACN,MAAM;IACN,aAAa;IACd;GACD,SAAS,EAAE,MAAM,UAAU;GAE3B,YAAY;IAAE,MAAM;IAAU,aAAa;IAAgC;GAE3E,eAAe,EAAE,MAAM,UAAU;GAEjC,YAAY;IAAE,MAAM;IAAU,aAAa;IAA6B;GACxE,UAAU;IAAE,MAAM;IAAU,aAAa;IAAiC;GAC1E,UAAU,EAAE,MAAM,UAAU;GAE5B,aAAa;IACX,MAAM;IACN,MAAM,CAAC,GAAG,aAAa;IACvB,aAAa;IACd;GACD,OAAO;IAAE,MAAM;IAAU,aAAa;IAA6C;GACnF,MAAM;IAAE,MAAM;IAAU,aAAa;IAAoD;GACzF,IAAI;IAAE,MAAM;IAAU,aAAa;IAAmD;GACtF,QAAQ,EAAE,MAAM,UAAU;GAE1B,YAAY;IACV,MAAM;IACN,OAAO;KACL,MAAM;KACN,YAAY;MACV,UAAU,EAAE,MAAM,UAAU;MAC5B,QAAQ,EAAE,MAAM,UAAU;MAC3B;KACD,UAAU,CAAC,YAAY,SAAS;KACjC;IACD,UAAU;IACV,aACE;IACH;GACF;EACD,UAAU,CAAC,YAAY,SAAS;EACjC;CACF,CACF;;;;;AAMD,MAAa,mBAA2B,CACtC;CACE,MAAM;CACN,aAAa;CACb,aAAa;EACX,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EAChB,eAAe;EAChB;CACD,aAAa;EACX,MAAM;EACN,YAAY;GACV,gBAAgB,EAAE,MAAM,UAAU;GAClC,UAAU,EAAE,MAAM,UAAU;GAC5B,QAAQ,EAAE,MAAM,UAAU;GAC3B;EACD,UAAU,CAAC,kBAAkB,WAAW;EACzC;CACF,EACD;CACE,MAAM;CACN,aAAa;CACb,aAAa;EACX,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EAChB,eAAe;EAChB;CACD,aAAa;EACX,MAAM;EACN,YAAY,EAAE;EACf;CACF,CACF"}
@@ -23,7 +23,7 @@ function loadInstructions() {
23
23
  }
24
24
  }
25
25
  const INSTRUCTIONS = loadInstructions();
26
- const VERSION = "0.10.4";
26
+ const VERSION = "0.10.6";
27
27
  export { INSTRUCTIONS as n, VERSION as t };
28
28
 
29
- //# sourceMappingURL=version-C4It3BAM.js.map
29
+ //# sourceMappingURL=version-KdH6s_ty.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version-C4It3BAM.js","names":[],"sources":["../src/instructions.ts","../src/version.ts"],"sourcesContent":["/**\n * MCP Server Instructions\n *\n * These instructions are sent to Claude Desktop during initialization\n * and used as context/hints for the LLM. This ensures the AI agent\n * knows how to properly use the Productive.io MCP server.\n *\n * The content is derived from skills/SKILL.md (without YAML frontmatter).\n */\n\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Load instructions from SKILL.md file\n * Removes YAML frontmatter (content between --- markers)\n */\nfunction loadInstructions(): string {\n try {\n // In dist/, go up to package root, then to skills/\n const skillPath = join(__dirname, '..', 'skills', 'SKILL.md');\n const content = readFileSync(skillPath, 'utf-8');\n\n // Remove YAML frontmatter (between --- markers at start of file)\n const withoutFrontmatter = content.replace(/^---\\n[\\s\\S]*?\\n---\\n+/, '');\n\n return withoutFrontmatter.trim();\n } catch {\n // Fallback if file not found (shouldn't happen in production)\n return 'Productive.io MCP Server - Use the productive tool with resource and action parameters.';\n }\n}\n\nexport const INSTRUCTIONS = loadInstructions();\n","/**\n * Package version - injected from package.json at build time\n */\ndeclare const __VERSION__: string;\nexport const VERSION = __VERSION__;\n"],"mappings":";;;;;;;;;;;;AAcA,IAAM,YAAY,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;;;;;AAMzD,SAAS,mBAA2B;AAClC,KAAI;AAQF,SALgB,aADE,KAAK,WAAW,MAAM,UAAU,WAAW,EACrB,QAAQ,CAGb,QAAQ,0BAA0B,GAAG,CAE9C,MAAM;SAC1B;AAEN,SAAO;;;AAIX,MAAa,eAAe,kBAAkB;AChC9C,MAAa,UAAA"}
1
+ {"version":3,"file":"version-KdH6s_ty.js","names":[],"sources":["../src/instructions.ts","../src/version.ts"],"sourcesContent":["/**\n * MCP Server Instructions\n *\n * These instructions are sent to Claude Desktop during initialization\n * and used as context/hints for the LLM. This ensures the AI agent\n * knows how to properly use the Productive.io MCP server.\n *\n * The content is derived from skills/SKILL.md (without YAML frontmatter).\n */\n\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Load instructions from SKILL.md file\n * Removes YAML frontmatter (content between --- markers)\n */\nfunction loadInstructions(): string {\n try {\n // In dist/, go up to package root, then to skills/\n const skillPath = join(__dirname, '..', 'skills', 'SKILL.md');\n const content = readFileSync(skillPath, 'utf-8');\n\n // Remove YAML frontmatter (between --- markers at start of file)\n const withoutFrontmatter = content.replace(/^---\\n[\\s\\S]*?\\n---\\n+/, '');\n\n return withoutFrontmatter.trim();\n } catch {\n // Fallback if file not found (shouldn't happen in production)\n return 'Productive.io MCP Server - Use the productive tool with resource and action parameters.';\n }\n}\n\nexport const INSTRUCTIONS = loadInstructions();\n","/**\n * Package version - injected from package.json at build time\n */\ndeclare const __VERSION__: string;\nexport const VERSION = __VERSION__;\n"],"mappings":";;;;;;;;;;;;AAcA,IAAM,YAAY,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;;;;;AAMzD,SAAS,mBAA2B;AAClC,KAAI;AAQF,SALgB,aADE,KAAK,WAAW,MAAM,UAAU,WAAW,EACrB,QAAQ,CAGb,QAAQ,0BAA0B,GAAG,CAE9C,MAAM;SAC1B;AAEN,SAAO;;;AAIX,MAAa,eAAe,kBAAkB;AChC9C,MAAa,UAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studiometa/productive-mcp",
3
- "version": "0.10.4",
3
+ "version": "0.10.6",
4
4
  "description": "MCP server for Productive.io API - Model Context Protocol integration for Claude Desktop",
5
5
  "keywords": [
6
6
  "ai",
@@ -87,8 +87,8 @@
87
87
  },
88
88
  "dependencies": {
89
89
  "@modelcontextprotocol/sdk": "^1.26.0",
90
- "@studiometa/productive-api": "0.10.4",
91
- "@studiometa/productive-core": "0.10.4",
90
+ "@studiometa/productive-api": "0.10.6",
91
+ "@studiometa/productive-core": "0.10.6",
92
92
  "h3": "^1.15.1",
93
93
  "zod": "4.3.6"
94
94
  },