@studiometa/productive-mcp 0.6.4 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/errors.d.ts +41 -0
  2. package/dist/errors.d.ts.map +1 -0
  3. package/dist/handlers/bookings.d.ts +1 -1
  4. package/dist/handlers/bookings.d.ts.map +1 -1
  5. package/dist/handlers/comments.d.ts +1 -1
  6. package/dist/handlers/comments.d.ts.map +1 -1
  7. package/dist/handlers/companies.d.ts +1 -1
  8. package/dist/handlers/companies.d.ts.map +1 -1
  9. package/dist/handlers/deals.d.ts +1 -1
  10. package/dist/handlers/deals.d.ts.map +1 -1
  11. package/dist/handlers/help.d.ts +13 -0
  12. package/dist/handlers/help.d.ts.map +1 -0
  13. package/dist/handlers/index.d.ts.map +1 -1
  14. package/dist/handlers/people.d.ts +1 -1
  15. package/dist/handlers/people.d.ts.map +1 -1
  16. package/dist/handlers/projects.d.ts +1 -1
  17. package/dist/handlers/projects.d.ts.map +1 -1
  18. package/dist/handlers/reports.d.ts +21 -0
  19. package/dist/handlers/reports.d.ts.map +1 -0
  20. package/dist/handlers/services.d.ts +1 -1
  21. package/dist/handlers/services.d.ts.map +1 -1
  22. package/dist/handlers/tasks.d.ts.map +1 -1
  23. package/dist/handlers/time.d.ts +1 -1
  24. package/dist/handlers/time.d.ts.map +1 -1
  25. package/dist/handlers/timers.d.ts.map +1 -1
  26. package/dist/handlers/types.d.ts +1 -0
  27. package/dist/handlers/types.d.ts.map +1 -1
  28. package/dist/handlers/utils.d.ts +12 -1
  29. package/dist/handlers/utils.d.ts.map +1 -1
  30. package/dist/handlers.js +1 -1
  31. package/dist/http.d.ts +1 -0
  32. package/dist/http.d.ts.map +1 -1
  33. package/dist/http.js +4 -3
  34. package/dist/http.js.map +1 -1
  35. package/dist/index-D743zTS1.js +1177 -0
  36. package/dist/index-D743zTS1.js.map +1 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +3 -2
  39. package/dist/index.js.map +1 -1
  40. package/dist/instructions.d.ts +11 -0
  41. package/dist/instructions.d.ts.map +1 -0
  42. package/dist/schema.d.ts +218 -0
  43. package/dist/schema.d.ts.map +1 -0
  44. package/dist/server.js +1 -1
  45. package/dist/stdio.js +1 -1
  46. package/dist/tools.d.ts +6 -0
  47. package/dist/tools.d.ts.map +1 -1
  48. package/dist/tools.js +61 -5
  49. package/dist/tools.js.map +1 -1
  50. package/dist/version-i2-GF6d1.js +21 -0
  51. package/dist/version-i2-GF6d1.js.map +1 -0
  52. package/package.json +13 -3
  53. package/skills/SKILL.md +330 -0
  54. package/dist/index-CmTDkz-y.js +0 -480
  55. package/dist/index-CmTDkz-y.js.map +0 -1
  56. package/dist/version-BRw90xAB.js +0 -5
  57. package/dist/version-BRw90xAB.js.map +0 -1
package/dist/tools.js CHANGED
@@ -1,7 +1,14 @@
1
1
  const TOOLS = [
2
2
  {
3
3
  name: "productive",
4
- description: "Productive.io API. Resources: projects, time, tasks, services, people, companies, comments, timers, deals, bookings. Actions: list, get, create, update (varies by resource), start/stop (timers), me (people). Filters: project_id, person_id, service_id, company_id, after/before (dates).",
4
+ description: "Productive.io API. Resources: projects, time, tasks, services, people, companies, comments, timers, deals, bookings, reports. Actions: list, get, create, update (varies by resource), start/stop (timers), me (people), help (documentation). Use query for text search on list actions. Reports: use resource=reports, action=get with report_type. Filters: project_id, person_id, service_id, company_id, after/before (dates). Use include to fetch related data. Use compact=false for full details (default for get, true for list). Use action=help with a resource for detailed documentation.",
5
+ annotations: {
6
+ title: "Productive.io",
7
+ readOnlyHint: false,
8
+ destructiveHint: false,
9
+ idempotentHint: false,
10
+ openWorldHint: true
11
+ },
5
12
  inputSchema: {
6
13
  type: "object",
7
14
  properties: {
@@ -17,18 +24,32 @@ const TOOLS = [
17
24
  "comments",
18
25
  "timers",
19
26
  "deals",
20
- "bookings"
27
+ "bookings",
28
+ "reports"
21
29
  ]
22
30
  },
23
31
  action: {
24
32
  type: "string",
25
- enum: ["list", "get", "create", "update", "me", "start", "stop"]
33
+ enum: ["list", "get", "create", "update", "me", "start", "stop", "help"],
34
+ description: 'Action to perform. Use "help" for detailed documentation on a resource.'
26
35
  },
27
36
  id: { type: "string" },
28
37
  filter: { type: "object" },
29
38
  page: { type: "number" },
30
39
  per_page: { type: "number" },
31
- compact: { type: "boolean" },
40
+ compact: {
41
+ type: "boolean",
42
+ description: "Compact output (default: true for list, false for get)"
43
+ },
44
+ include: {
45
+ type: "array",
46
+ items: { type: "string" },
47
+ description: 'Related resources to include (e.g., ["project", "assignee", "comments"])'
48
+ },
49
+ query: {
50
+ type: "string",
51
+ description: "Text search query for list actions (searches name/title fields)"
52
+ },
32
53
  // Common fields
33
54
  person_id: { type: "string" },
34
55
  service_id: { type: "string" },
@@ -53,7 +74,28 @@ const TOOLS = [
53
74
  // Booking fields
54
75
  started_on: { type: "string" },
55
76
  ended_on: { type: "string" },
56
- event_id: { type: "string" }
77
+ event_id: { type: "string" },
78
+ // Report fields
79
+ report_type: {
80
+ type: "string",
81
+ enum: [
82
+ "time_reports",
83
+ "project_reports",
84
+ "budget_reports",
85
+ "person_reports",
86
+ "invoice_reports",
87
+ "payment_reports",
88
+ "service_reports",
89
+ "task_reports",
90
+ "company_reports",
91
+ "deal_reports",
92
+ "timesheet_reports"
93
+ ]
94
+ },
95
+ group: { type: "string" },
96
+ from: { type: "string" },
97
+ to: { type: "string" },
98
+ status: { type: "string" }
57
99
  },
58
100
  required: ["resource", "action"]
59
101
  }
@@ -63,6 +105,13 @@ const STDIO_ONLY_TOOLS = [
63
105
  {
64
106
  name: "productive_configure",
65
107
  description: "Configure Productive.io credentials",
108
+ annotations: {
109
+ title: "Configure Productive",
110
+ readOnlyHint: false,
111
+ destructiveHint: false,
112
+ idempotentHint: true,
113
+ openWorldHint: false
114
+ },
66
115
  inputSchema: {
67
116
  type: "object",
68
117
  properties: {
@@ -76,6 +125,13 @@ const STDIO_ONLY_TOOLS = [
76
125
  {
77
126
  name: "productive_get_config",
78
127
  description: "Get current configuration",
128
+ annotations: {
129
+ title: "Get Productive Config",
130
+ readOnlyHint: true,
131
+ destructiveHint: false,
132
+ idempotentHint: true,
133
+ openWorldHint: false
134
+ },
79
135
  inputSchema: {
80
136
  type: "object",
81
137
  properties: {}
package/dist/tools.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tools.js","sources":["../src/tools.ts"],"sourcesContent":["import type { Tool } from '@modelcontextprotocol/sdk/types.js';\n\n/**\n * Single consolidated tool for Productive.io MCP server\n *\n * Optimized for minimal token overhead (~170 tokens vs ~1300 for individual tools)\n */\nexport const TOOLS: Tool[] = [\n {\n name: 'productive',\n description:\n 'Productive.io API. Resources: projects, time, tasks, services, people, companies, comments, timers, deals, bookings. Actions: list, get, create, update (varies by resource), start/stop (timers), me (people). Filters: project_id, person_id, service_id, company_id, after/before (dates).',\n inputSchema: {\n type: 'object',\n properties: {\n resource: {\n type: 'string',\n enum: [\n 'projects',\n 'time',\n 'tasks',\n 'services',\n 'people',\n 'companies',\n 'comments',\n 'timers',\n 'deals',\n 'bookings',\n ],\n },\n action: {\n type: 'string',\n enum: ['list', 'get', 'create', 'update', 'me', 'start', 'stop'],\n },\n id: { type: 'string' },\n filter: { type: 'object' },\n page: { type: 'number' },\n per_page: { type: 'number' },\n compact: { type: 'boolean' },\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 // Comment fields\n body: { type: 'string' },\n deal_id: { type: 'string' },\n // Timer fields\n time_entry_id: { type: 'string' },\n // Booking fields\n started_on: { type: 'string' },\n ended_on: { type: 'string' },\n event_id: { type: 'string' },\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 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 inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n];\n"],"names":[],"mappings":"AAOO,MAAM,QAAgB;AAAA,EAC3B;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,UAAU;AAAA,UACR,MAAM;AAAA,UACN,MAAM;AAAA,YACJ;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UAAA;AAAA,QACF;AAAA,QAEF,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,MAAM,CAAC,QAAQ,OAAO,UAAU,UAAU,MAAM,SAAS,MAAM;AAAA,QAAA;AAAA,QAEjE,IAAI,EAAE,MAAM,SAAA;AAAA,QACZ,QAAQ,EAAE,MAAM,SAAA;AAAA,QAChB,MAAM,EAAE,MAAM,SAAA;AAAA,QACd,UAAU,EAAE,MAAM,SAAA;AAAA,QAClB,SAAS,EAAE,MAAM,UAAA;AAAA;AAAA,QAEjB,WAAW,EAAE,MAAM,SAAA;AAAA,QACnB,YAAY,EAAE,MAAM,SAAA;AAAA,QACpB,SAAS,EAAE,MAAM,SAAA;AAAA,QACjB,YAAY,EAAE,MAAM,SAAA;AAAA,QACpB,MAAM,EAAE,MAAM,SAAA;AAAA,QACd,MAAM,EAAE,MAAM,SAAA;AAAA,QACd,MAAM,EAAE,MAAM,SAAA;AAAA;AAAA,QAEd,OAAO,EAAE,MAAM,SAAA;AAAA,QACf,YAAY,EAAE,MAAM,SAAA;AAAA,QACpB,cAAc,EAAE,MAAM,SAAA;AAAA,QACtB,aAAa,EAAE,MAAM,SAAA;AAAA,QACrB,aAAa,EAAE,MAAM,SAAA;AAAA;AAAA,QAErB,MAAM,EAAE,MAAM,SAAA;AAAA;AAAA,QAEd,MAAM,EAAE,MAAM,SAAA;AAAA,QACd,SAAS,EAAE,MAAM,SAAA;AAAA;AAAA,QAEjB,eAAe,EAAE,MAAM,SAAA;AAAA;AAAA,QAEvB,YAAY,EAAE,MAAM,SAAA;AAAA,QACpB,UAAU,EAAE,MAAM,SAAA;AAAA,QAClB,UAAU,EAAE,MAAM,SAAA;AAAA,MAAS;AAAA,MAE7B,UAAU,CAAC,YAAY,QAAQ;AAAA,IAAA;AAAA,EACjC;AAEJ;AAMO,MAAM,mBAA2B;AAAA,EACtC;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,gBAAgB,EAAE,MAAM,SAAA;AAAA,QACxB,UAAU,EAAE,MAAM,SAAA;AAAA,QAClB,QAAQ,EAAE,MAAM,SAAA;AAAA,MAAS;AAAA,MAE3B,UAAU,CAAC,kBAAkB,UAAU;AAAA,IAAA;AAAA,EACzC;AAAA,EAEF;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY,CAAA;AAAA,IAAC;AAAA,EACf;AAEJ;"}
1
+ {"version":3,"file":"tools.js","sources":["../src/tools.ts"],"sourcesContent":["import type { Tool } from '@modelcontextprotocol/sdk/types.js';\n\n/**\n * Single consolidated tool for Productive.io MCP server\n *\n * Optimized for minimal token overhead (~170 tokens vs ~1300 for individual tools)\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:\n 'Productive.io API. Resources: projects, time, tasks, services, people, companies, comments, timers, deals, bookings, reports. Actions: list, get, create, update (varies by resource), start/stop (timers), me (people), help (documentation). Use query for text search on list actions. Reports: use resource=reports, action=get with report_type. Filters: project_id, person_id, service_id, company_id, after/before (dates). Use include to fetch related data. Use compact=false for full details (default for get, true for list). Use action=help with a resource for detailed documentation.',\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: [\n 'projects',\n 'time',\n 'tasks',\n 'services',\n 'people',\n 'companies',\n 'comments',\n 'timers',\n 'deals',\n 'bookings',\n 'reports',\n ],\n },\n action: {\n type: 'string',\n enum: ['list', 'get', 'create', 'update', 'me', 'start', 'stop', 'help'],\n description: 'Action to perform. Use \"help\" for detailed documentation on a resource.',\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 resources to include (e.g., [\"project\", \"assignee\", \"comments\"])',\n },\n query: {\n type: 'string',\n description: 'Text search query for list actions (searches name/title fields)',\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 // Comment fields\n body: { type: 'string' },\n deal_id: { type: 'string' },\n // Timer fields\n time_entry_id: { type: 'string' },\n // Booking fields\n started_on: { type: 'string' },\n ended_on: { type: 'string' },\n event_id: { type: 'string' },\n // Report fields\n report_type: {\n type: 'string',\n enum: [\n 'time_reports',\n 'project_reports',\n 'budget_reports',\n 'person_reports',\n 'invoice_reports',\n 'payment_reports',\n 'service_reports',\n 'task_reports',\n 'company_reports',\n 'deal_reports',\n 'timesheet_reports',\n ],\n },\n group: { type: 'string' },\n from: { type: 'string' },\n to: { type: 'string' },\n status: { type: 'string' },\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"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ const __dirname$1 = dirname(fileURLToPath(import.meta.url));
5
+ function loadInstructions() {
6
+ try {
7
+ const skillPath = join(__dirname$1, "..", "skills", "SKILL.md");
8
+ const content = readFileSync(skillPath, "utf-8");
9
+ const withoutFrontmatter = content.replace(/^---\n[\s\S]*?\n---\n+/, "");
10
+ return withoutFrontmatter.trim();
11
+ } catch {
12
+ return "Productive.io MCP Server - Use the productive tool with resource and action parameters.";
13
+ }
14
+ }
15
+ const INSTRUCTIONS = loadInstructions();
16
+ const VERSION = "0.8.0";
17
+ export {
18
+ INSTRUCTIONS as I,
19
+ VERSION as V
20
+ };
21
+ //# sourceMappingURL=version-i2-GF6d1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-i2-GF6d1.js","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"],"names":["__dirname"],"mappings":";;;AAcA,MAAMA,cAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAMxD,SAAS,mBAA2B;AAClC,MAAI;AAEF,UAAM,YAAY,KAAKA,aAAW,MAAM,UAAU,UAAU;AAC5D,UAAM,UAAU,aAAa,WAAW,OAAO;AAG/C,UAAM,qBAAqB,QAAQ,QAAQ,0BAA0B,EAAE;AAEvE,WAAO,mBAAmB,KAAA;AAAA,EAC5B,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AAEO,MAAM,eAAe,iBAAA;AChCrB,MAAM,UAAU;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studiometa/productive-mcp",
3
- "version": "0.6.4",
3
+ "version": "0.8.0",
4
4
  "description": "MCP server for Productive.io API - Model Context Protocol integration for Claude Desktop",
5
5
  "keywords": [
6
6
  "ai",
@@ -25,6 +25,7 @@
25
25
  },
26
26
  "files": [
27
27
  "dist",
28
+ "skills",
28
29
  "Dockerfile"
29
30
  ],
30
31
  "type": "module",
@@ -58,6 +59,14 @@
58
59
  "./handlers": {
59
60
  "types": "./dist/handlers.d.ts",
60
61
  "import": "./dist/handlers.js"
62
+ },
63
+ "./errors": {
64
+ "types": "./dist/errors.d.ts",
65
+ "import": "./dist/errors.js"
66
+ },
67
+ "./schema": {
68
+ "types": "./dist/schema.d.ts",
69
+ "import": "./dist/schema.js"
61
70
  }
62
71
  },
63
72
  "publishConfig": {
@@ -79,8 +88,9 @@
79
88
  },
80
89
  "dependencies": {
81
90
  "@modelcontextprotocol/sdk": "^1.0.4",
82
- "@studiometa/productive-cli": "0.6.4",
83
- "h3": "^1.15.1"
91
+ "@studiometa/productive-cli": "0.8.0",
92
+ "h3": "^1.15.1",
93
+ "zod": "4.3.6"
84
94
  },
85
95
  "devDependencies": {
86
96
  "@types/node": "^22.10.5",
@@ -0,0 +1,330 @@
1
+ ---
2
+ name: productive-mcp
3
+ description: MCP server for Productive.io - use with Claude Desktop or MCP-compatible clients for time tracking, projects, and tasks
4
+ ---
5
+
6
+ # Productive MCP Server
7
+
8
+ MCP (Model Context Protocol) server for Productive.io. Provides a single unified tool for all operations.
9
+
10
+ ## The `productive` Tool
11
+
12
+ Single unified tool with this signature:
13
+
14
+ ```
15
+ productive(resource, action, [parameters...])
16
+ ```
17
+
18
+ ### Resources & Actions
19
+
20
+ | Resource | Actions | Description |
21
+ | ----------- | ----------------------------------------- | ----------------------- |
22
+ | `projects` | `list`, `get`, `help` | Project management |
23
+ | `time` | `list`, `get`, `create`, `update`, `help` | Time tracking |
24
+ | `tasks` | `list`, `get`, `create`, `update`, `help` | Task management |
25
+ | `services` | `list`, `get`, `help` | Budget line items |
26
+ | `people` | `list`, `get`, `me`, `help` | Team members |
27
+ | `companies` | `list`, `get`, `create`, `update`, `help` | Client companies |
28
+ | `comments` | `list`, `get`, `create`, `update`, `help` | Comments on tasks/deals |
29
+ | `timers` | `list`, `get`, `start`, `stop`, `help` | Active timers |
30
+ | `deals` | `list`, `get`, `create`, `update`, `help` | Sales deals |
31
+ | `bookings` | `list`, `get`, `create`, `update`, `help` | Resource scheduling |
32
+ | `reports` | `get`, `help` | Generate reports |
33
+
34
+ ### Getting Help
35
+
36
+ Use `action: "help"` to get detailed documentation for any resource:
37
+
38
+ ```json
39
+ {
40
+ "resource": "time",
41
+ "action": "help"
42
+ }
43
+ ```
44
+
45
+ Returns filters, fields, includes, and examples for that resource.
46
+
47
+ ## Common Parameters
48
+
49
+ | Parameter | Type | Description |
50
+ | ---------- | ------- | ------------------------------------------------------ |
51
+ | `resource` | string | **Required**. Resource type (see table above) |
52
+ | `action` | string | **Required**. Action to perform |
53
+ | `id` | string | Resource ID (for `get`, `update`, `stop`) |
54
+ | `filter` | object | Filter criteria for `list` actions |
55
+ | `page` | number | Page number (default: 1) |
56
+ | `per_page` | number | Items per page (default: 20, max: 200) |
57
+ | `compact` | boolean | Compact output (default: true for list, false for get) |
58
+ | `include` | array | Related resources to include |
59
+ | `query` | string | Text search on name/title fields |
60
+
61
+ ## Examples by Resource
62
+
63
+ ### Projects
64
+
65
+ ```json
66
+ // List projects
67
+ { "resource": "projects", "action": "list" }
68
+
69
+ // Search projects
70
+ { "resource": "projects", "action": "list", "query": "website" }
71
+
72
+ // Get project details
73
+ { "resource": "projects", "action": "get", "id": "12345" }
74
+
75
+ // Filter active projects
76
+ { "resource": "projects", "action": "list", "filter": { "archived": "false" } }
77
+ ```
78
+
79
+ ### Time Entries
80
+
81
+ ```json
82
+ // List my time entries for a date range
83
+ {
84
+ "resource": "time",
85
+ "action": "list",
86
+ "filter": {
87
+ "person_id": "me",
88
+ "after": "2024-01-15",
89
+ "before": "2024-01-21"
90
+ }
91
+ }
92
+
93
+ // Create time entry (time in MINUTES)
94
+ {
95
+ "resource": "time",
96
+ "action": "create",
97
+ "service_id": "12345",
98
+ "date": "2024-01-16",
99
+ "time": 480,
100
+ "note": "Development work"
101
+ }
102
+
103
+ // Update time entry
104
+ {
105
+ "resource": "time",
106
+ "action": "update",
107
+ "id": "67890",
108
+ "time": 240,
109
+ "note": "Updated note"
110
+ }
111
+ ```
112
+
113
+ ### Tasks
114
+
115
+ ```json
116
+ // List open tasks for a project
117
+ {
118
+ "resource": "tasks",
119
+ "action": "list",
120
+ "filter": { "project_id": "12345", "status": "open" }
121
+ }
122
+
123
+ // Get task with comments
124
+ {
125
+ "resource": "tasks",
126
+ "action": "get",
127
+ "id": "67890",
128
+ "include": ["comments", "assignee"]
129
+ }
130
+
131
+ // Search tasks
132
+ { "resource": "tasks", "action": "list", "query": "bug fix" }
133
+
134
+ // Create task
135
+ {
136
+ "resource": "tasks",
137
+ "action": "create",
138
+ "title": "New task",
139
+ "project_id": "12345",
140
+ "task_list_id": "111"
141
+ }
142
+ ```
143
+
144
+ ### People
145
+
146
+ ```json
147
+ // Get current user
148
+ { "resource": "people", "action": "me" }
149
+
150
+ // List people
151
+ { "resource": "people", "action": "list" }
152
+
153
+ // Search by name
154
+ { "resource": "people", "action": "list", "query": "john" }
155
+ ```
156
+
157
+ ### Services
158
+
159
+ ```json
160
+ // List services for a project
161
+ {
162
+ "resource": "services",
163
+ "action": "list",
164
+ "filter": { "project_id": "12345" }
165
+ }
166
+ ```
167
+
168
+ ### Comments
169
+
170
+ ```json
171
+ // List comments on a task
172
+ {
173
+ "resource": "comments",
174
+ "action": "list",
175
+ "filter": { "task_id": "12345" }
176
+ }
177
+
178
+ // Add comment
179
+ {
180
+ "resource": "comments",
181
+ "action": "create",
182
+ "task_id": "12345",
183
+ "body": "Looking good!"
184
+ }
185
+ ```
186
+
187
+ ### Timers
188
+
189
+ ```json
190
+ // List active timers
191
+ { "resource": "timers", "action": "list" }
192
+
193
+ // Start timer on a service
194
+ { "resource": "timers", "action": "start", "service_id": "12345" }
195
+
196
+ // Stop timer
197
+ { "resource": "timers", "action": "stop", "id": "67890" }
198
+ ```
199
+
200
+ ### Reports
201
+
202
+ ```json
203
+ // Time report by person
204
+ {
205
+ "resource": "reports",
206
+ "action": "get",
207
+ "report_type": "time_reports",
208
+ "group": "person",
209
+ "from": "2024-01-01",
210
+ "to": "2024-01-31"
211
+ }
212
+
213
+ // Budget report for a project
214
+ {
215
+ "resource": "reports",
216
+ "action": "get",
217
+ "report_type": "budget_reports",
218
+ "filter": { "project_id": "12345" }
219
+ }
220
+ ```
221
+
222
+ ## Filters Reference
223
+
224
+ ### Time Entries
225
+
226
+ - `person_id` - Filter by person (use "me" for current user)
227
+ - `project_id` - Filter by project
228
+ - `service_id` - Filter by service
229
+ - `after` - After date (YYYY-MM-DD)
230
+ - `before` - Before date (YYYY-MM-DD)
231
+
232
+ ### Tasks
233
+
234
+ - `project_id` - Filter by project
235
+ - `assignee_id` - Filter by assigned person
236
+ - `status` - Filter by status: `open`, `closed`, `all`
237
+ - `task_list_id` - Filter by task list
238
+
239
+ ### Projects
240
+
241
+ - `company_id` - Filter by company
242
+ - `archived` - Include archived: `true`, `false`
243
+
244
+ ### Services
245
+
246
+ - `project_id` - Filter by project
247
+ - `deal_id` - Filter by deal
248
+
249
+ ### Bookings
250
+
251
+ - `person_id` - Filter by person
252
+ - `service_id` - Filter by service
253
+ - `after` / `before` - Date range
254
+
255
+ ## Include (Related Resources)
256
+
257
+ Fetch related data in a single request:
258
+
259
+ ```json
260
+ {
261
+ "resource": "tasks",
262
+ "action": "get",
263
+ "id": "12345",
264
+ "include": ["project", "project.company", "assignee", "comments"]
265
+ }
266
+ ```
267
+
268
+ Common includes:
269
+
270
+ - Tasks: `project`, `assignee`, `workflow_status`, `comments`, `subtasks`
271
+ - Time entries: `person`, `service`, `project`
272
+ - Deals: `company`, `deal_status`, `responsible`
273
+
274
+ ## Compact Mode
275
+
276
+ - `compact: true` (default for `list`) - Returns minimal fields
277
+ - `compact: false` (default for `get`) - Returns full details
278
+
279
+ Force full details on list:
280
+
281
+ ```json
282
+ { "resource": "projects", "action": "list", "compact": false }
283
+ ```
284
+
285
+ ## Time Values
286
+
287
+ **Time is always in MINUTES:**
288
+
289
+ - 60 = 1 hour
290
+ - 480 = 8 hours (full day)
291
+ - 240 = 4 hours (half day)
292
+
293
+ ## Configuration Tools (stdio mode only)
294
+
295
+ In local/stdio mode, additional configuration tools are available:
296
+
297
+ ```json
298
+ // Configure credentials
299
+ productive_configure({
300
+ "organizationId": "...",
301
+ "apiToken": "...",
302
+ "userId": "..."
303
+ })
304
+
305
+ // View current config (token masked)
306
+ productive_get_config()
307
+ ```
308
+
309
+ ---
310
+
311
+ ## Best Practices for AI Agents
312
+
313
+ **For data handling best practices, confirmation workflows, and error handling patterns, see the CLI skill documentation:**
314
+
315
+ → `@studiometa/productive-cli/skills/SKILL.md`
316
+
317
+ Key points:
318
+
319
+ 1. **Never modify text content** - Use exact titles, descriptions, notes from API
320
+ 2. **Never invent IDs** - Always fetch first to get valid IDs
321
+ 3. **Always confirm before mutations** - Ask user before create/update/delete
322
+ 4. **Time is in minutes** - 480 = 8 hours
323
+
324
+ ### MCP-Specific Tips
325
+
326
+ 1. **Use `action: "help"`** - Get resource documentation before using unfamiliar resources
327
+ 2. **Use `compact: false`** for detailed single-item views
328
+ 3. **Use `include`** to reduce round-trips when you need related data
329
+ 4. **Use `query`** for text search instead of fetching all and filtering
330
+ 5. **Check `people.me`** first to get the current user's ID for filters