conduyt-mcp 4.1.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Conduyt MCP Server
2
2
 
3
- MCP server for [Conduyt CRM](https://conduyt.app) — expose your entire CRM as AI-accessible tools.
3
+ MCP server for [Conduyt CRM](https://conduyt.app) — expose your CRM as AI-accessible tools. Covers the core CRM surface (contacts, deals, pipelines, custom fields, automations, messaging, and more); use `conduyt_api_catalog` to discover the full set of 409 REST endpoints.
4
4
 
5
- ## 107 Tools
5
+ ## 113 Tools
6
6
 
7
7
  ### Discovery
8
8
  | Tool | Description |
@@ -24,9 +24,9 @@ MCP server for [Conduyt CRM](https://conduyt.app) — expose your entire CRM as
24
24
  | Tool | Description |
25
25
  |------|-------------|
26
26
  | `conduyt_list_deals` | List deals by pipeline, stage, or assignee |
27
- | `conduyt_get_deal` | Get deal details with history |
28
- | `conduyt_create_deal` | Create a deal in a pipeline |
29
- | `conduyt_update_deal` | Move stage, change value, mark won/lost |
27
+ | `conduyt_get_deal` | Get deal details with history, including custom-field values |
28
+ | `conduyt_create_deal` | Create a deal with full attributes — currency (e.g. GBP), probability, priority, expected close date, contact/company, and structured custom-field values |
29
+ | `conduyt_update_deal` | Move stage, change value/currency, set probability or close date, reassign, mark won/lost, or write custom-field values |
30
30
 
31
31
  ### Tasks
32
32
  | Tool | Description |
@@ -38,6 +38,12 @@ MCP server for [Conduyt CRM](https://conduyt.app) — expose your entire CRM as
38
38
  | Tool | Description |
39
39
  |------|-------------|
40
40
  | `conduyt_list_pipelines` | List pipelines with stages |
41
+ | `conduyt_create_pipeline` | Create a pipeline, optionally with its full set of stages (no stage-count cap; up to 50) |
42
+ | `conduyt_update_pipeline` | Rename a pipeline, change its description, or set it as default |
43
+ | `conduyt_delete_pipeline` | Delete a pipeline (move/remove its deals first) |
44
+ | `conduyt_create_stage` | Append a stage to a pipeline (e.g. 'On Hold', 'Declined/Dead') |
45
+ | `conduyt_update_stage` | Rename, recolor, reorder, or change won/lost flags on a stage |
46
+ | `conduyt_delete_stage` | Delete an empty stage from a pipeline |
41
47
 
42
48
  ### Activities
43
49
  | Tool | Description |
@@ -238,8 +244,7 @@ Add to `claude_desktop_config.json`:
238
244
  "mcpServers": {
239
245
  "conduyt": {
240
246
  "command": "npx",
241
- "args": ["tsx", "src/index.ts"],
242
- "cwd": "/path/to/conduyt-mcp",
247
+ "args": ["-y", "conduyt-mcp"],
243
248
  "env": {
244
249
  "CONDUYT_API_URL": "https://conduyt.app",
245
250
  "CONDUYT_API_KEY": "cdy_your_key_here"
@@ -258,7 +263,7 @@ Add to `.mcp.json` or settings:
258
263
  "mcpServers": {
259
264
  "conduyt": {
260
265
  "command": "npx",
261
- "args": ["tsx", "/path/to/conduyt-mcp/src/index.ts"],
266
+ "args": ["-y", "conduyt-mcp"],
262
267
  "env": {
263
268
  "CONDUYT_API_URL": "https://conduyt.app",
264
269
  "CONDUYT_API_KEY": "cdy_your_key_here"
package/dist/index.js CHANGED
@@ -45,7 +45,7 @@ if (!apiKey.startsWith("cdy_")) {
45
45
  const client = new ConduytClient({ apiUrl, apiKey });
46
46
  const server = new McpServer({
47
47
  name: "conduyt",
48
- version: "4.1.0",
48
+ version: "4.2.0",
49
49
  });
50
50
  registerDiscoveryTools(server, client);
51
51
  registerContactTools(server, client);
@@ -28,30 +28,44 @@ export function registerDealTools(server, client) {
28
28
  const result = await client.get(`/api/v1/deals?${params}`);
29
29
  return formatResult(result);
30
30
  });
31
- server.tool("conduyt_get_deal", "Get a single deal with full details — value, stage, contact, activities, tasks, and history.", {
31
+ server.tool("conduyt_get_deal", "Get a single deal with full details — value, currency, probability, stage, contact, expected close date, custom-field values, activities, tasks, and history. Use this to read structured custom-field data back out of a deal (e.g. for a P&L or balance-sheet model).", {
32
32
  id: z.string().describe("Deal UUID"),
33
33
  }, async ({ id }) => {
34
34
  const result = await client.get(`/api/v1/deals/${id}`);
35
35
  return formatResult(result);
36
36
  });
37
- server.tool("conduyt_create_deal", "Create a new deal in a pipeline. Requires a pipeline and stage ID — use conduyt_list_pipelines to discover them.", {
37
+ server.tool("conduyt_create_deal", "Create a new deal in a pipeline with full attributes. Requires a pipeline and stage ID — use conduyt_list_pipelines to discover them. Supports currency (e.g. GBP), probability, priority, expected close date, and structured custom-field values.", {
38
38
  title: z.string().describe("Deal title (e.g. 'Acme Corp — Enterprise Plan')"),
39
39
  pipelineId: z.string().describe("Pipeline UUID"),
40
40
  stageId: z.string().describe("Stage UUID within the pipeline"),
41
41
  contactId: z.string().optional().describe("Associated contact UUID"),
42
- value: z.number().optional().describe("Deal value in dollars"),
43
- assignedTo: z.string().optional().describe("Assigned user UUID"),
42
+ companyId: z.string().optional().describe("Associated company UUID"),
43
+ value: z.number().optional().describe("Deal value (numeric, in the deal's currency)"),
44
+ currency: z.string().optional().describe("ISO 4217 currency code, e.g. 'USD', 'GBP', 'EUR'. Defaults to USD if omitted."),
45
+ status: z.enum(["open", "won", "lost"]).optional().describe("Deal status (default 'open')"),
46
+ priority: z.string().optional().describe("Deal priority, e.g. 'low', 'medium', 'high'"),
47
+ probability: z.number().min(0).max(1).optional().describe("Win probability as a 0–1 fraction (e.g. 0.75 = 75%)"),
48
+ expectedCloseDate: z.string().optional().describe("Expected close date (ISO 8601, e.g. '2026-09-30')"),
49
+ assignedTo: z.string().optional().describe("Assigned user (owner) UUID"),
50
+ customFields: z.record(z.any()).optional().describe("Structured custom-field values keyed by field key, e.g. { limit_of_indemnity: 5000000, commission_pct: 12.5 }. Define fields first with conduyt_create_custom_field."),
44
51
  }, async (params) => {
45
52
  const result = await client.post("/api/v1/deals", params);
46
53
  return formatResult(result);
47
54
  });
48
- server.tool("conduyt_update_deal", "Update a deal — move to a new stage, change value, reassign, or mark as won/lost.", {
55
+ server.tool("conduyt_update_deal", "Update a deal — move stage, change value/currency, set probability or expected close date, reassign, mark won/lost, or write structured custom-field values. customFields are merged into existing values (omit a key to leave it unchanged).", {
49
56
  id: z.string().describe("Deal UUID"),
50
57
  title: z.string().optional().describe("Updated title"),
51
58
  stageId: z.string().optional().describe("Move to a new stage UUID"),
59
+ contactId: z.string().optional().describe("Re-link to a contact UUID"),
60
+ companyId: z.string().optional().describe("Re-link to a company UUID"),
52
61
  value: z.number().optional().describe("Updated deal value"),
62
+ currency: z.string().optional().describe("ISO 4217 currency code, e.g. 'GBP'"),
53
63
  status: z.enum(["open", "won", "lost"]).optional().describe("Set deal status"),
54
- assignedTo: z.string().optional().describe("Reassign to user UUID"),
64
+ priority: z.string().optional().describe("Updated priority"),
65
+ probability: z.number().min(0).max(1).optional().describe("Win probability as a 0–1 fraction (e.g. 0.75 = 75%)"),
66
+ expectedCloseDate: z.string().optional().describe("Expected close date (ISO 8601)"),
67
+ assignedTo: z.string().optional().describe("Reassign to user (owner) UUID"),
68
+ customFields: z.record(z.any()).optional().describe("Structured custom-field values to merge, keyed by field key"),
55
69
  }, async ({ id, ...updates }) => {
56
70
  const result = await client.patch(`/api/v1/deals/${id}`, updates);
57
71
  return formatResult(result);
@@ -1,7 +1,86 @@
1
+ import { z } from "zod";
1
2
  import { formatResult } from "../client.js";
2
3
  export function registerPipelineTools(server, client) {
3
4
  server.tool("conduyt_list_pipelines", "List all sales pipelines with their stages. Use this to discover pipeline and stage UUIDs before creating or moving deals.", {}, async () => {
4
5
  const result = await client.get("/api/v1/pipelines");
5
6
  return formatResult(result);
6
7
  });
8
+ server.tool("conduyt_create_pipeline", "Create a new sales pipeline, optionally with its full set of stages in one call. If stages are omitted, default New/Won/Lost stages are created. There is no fixed limit on stage count — pass as many as your funnel needs (e.g. eight active stages plus 'On Hold' and 'Declined/Dead').", {
9
+ name: z.string().describe("Pipeline name (e.g. 'New Business Book')"),
10
+ description: z.string().optional().describe("Optional pipeline description"),
11
+ isDefault: z.boolean().optional().describe("Make this the account's default pipeline"),
12
+ stages: z
13
+ .array(z.object({
14
+ name: z.string().describe("Stage name (e.g. 'Quote Sent')"),
15
+ order: z.number().int().min(0).optional().describe("Display order (0-based). If omitted, stages are ordered as listed."),
16
+ color: z.string().optional().describe("Hex color, e.g. '#3B82F6'"),
17
+ isWon: z.boolean().optional().describe("Marks this as a won/closed-won stage"),
18
+ isLost: z.boolean().optional().describe("Marks this as a lost/dead stage"),
19
+ }))
20
+ .optional()
21
+ .describe("Ordered list of stages to create with the pipeline. A stage cannot be both isWon and isLost."),
22
+ }, async ({ name, description, isDefault, stages }) => {
23
+ const body = { name };
24
+ if (description !== undefined)
25
+ body.description = description;
26
+ if (isDefault !== undefined)
27
+ body.isDefault = isDefault;
28
+ if (stages) {
29
+ body.stages = stages.map((s, i) => ({
30
+ ...s,
31
+ order: s.order ?? i,
32
+ }));
33
+ }
34
+ const result = await client.post("/api/v1/pipelines", body);
35
+ return formatResult(result);
36
+ });
37
+ server.tool("conduyt_update_pipeline", "Update a pipeline's name, description, or default flag. To add/edit/remove stages, use the stage tools.", {
38
+ id: z.string().describe("Pipeline UUID"),
39
+ name: z.string().optional().describe("Updated pipeline name"),
40
+ description: z.string().optional().describe("Updated description"),
41
+ isDefault: z.boolean().optional().describe("Set as the account's default pipeline"),
42
+ }, async ({ id, ...updates }) => {
43
+ const result = await client.patch(`/api/v1/pipelines/${id}`, updates);
44
+ return formatResult(result);
45
+ });
46
+ server.tool("conduyt_delete_pipeline", "Delete a pipeline. Deals in the pipeline must be moved or removed first. Cannot delete the default or an archived pipeline.", {
47
+ id: z.string().describe("Pipeline UUID to delete"),
48
+ }, async ({ id }) => {
49
+ const result = await client.del(`/api/v1/pipelines/${id}`);
50
+ return formatResult(result);
51
+ });
52
+ server.tool("conduyt_create_stage", "Add a new stage to an existing pipeline. The stage is appended after the current last stage. Use this to extend a funnel (e.g. add 'On Hold' or 'Declined/Dead').", {
53
+ pipelineId: z.string().describe("Pipeline UUID to add the stage to"),
54
+ name: z.string().describe("Stage name"),
55
+ color: z.string().optional().describe("Hex color, e.g. '#3B82F6'"),
56
+ isWon: z.boolean().optional().describe("Marks this as a won stage"),
57
+ isLost: z.boolean().optional().describe("Marks this as a lost/dead stage"),
58
+ }, async ({ pipelineId, name, color, isWon, isLost }) => {
59
+ const result = await client.post(`/api/v1/pipelines/${pipelineId}/stages`, {
60
+ name,
61
+ color,
62
+ isWon,
63
+ isLost,
64
+ });
65
+ return formatResult(result);
66
+ });
67
+ server.tool("conduyt_update_stage", "Update a stage within a pipeline — rename, recolor, reorder (sortOrder), or change its won/lost flags.", {
68
+ pipelineId: z.string().describe("Pipeline UUID"),
69
+ stageId: z.string().describe("Stage UUID to update"),
70
+ name: z.string().optional().describe("Updated stage name"),
71
+ color: z.string().optional().describe("Updated hex color"),
72
+ sortOrder: z.number().int().min(0).optional().describe("Updated display order (0-based)"),
73
+ isWon: z.boolean().optional().describe("Updated won flag"),
74
+ isLost: z.boolean().optional().describe("Updated lost flag"),
75
+ }, async ({ pipelineId, stageId, ...updates }) => {
76
+ const result = await client.patch(`/api/v1/pipelines/${pipelineId}/stages/${stageId}`, updates);
77
+ return formatResult(result);
78
+ });
79
+ server.tool("conduyt_delete_stage", "Delete a stage from a pipeline. The stage must be empty (no deals) — move or reassign deals first.", {
80
+ pipelineId: z.string().describe("Pipeline UUID"),
81
+ stageId: z.string().describe("Stage UUID to delete"),
82
+ }, async ({ pipelineId, stageId }) => {
83
+ const result = await client.del(`/api/v1/pipelines/${pipelineId}/stages/${stageId}`);
84
+ return formatResult(result);
85
+ });
7
86
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conduyt-mcp",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "description": "MCP server for Conduyt CRM — expose CRM operations as AI-accessible tools",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",