@verygoodplugins/mcp-freescout 1.1.1 → 1.1.2

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.
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "permissions": {
3
3
  "allow": [
4
- "Bash(npx @verygoodplugins/mcp-freescout@1.0.1:*)"
4
+ "Bash(npx @verygoodplugins/mcp-freescout@1.0.1:*)",
5
+ "Bash(node:*)"
5
6
  ],
6
7
  "deny": []
7
8
  }
package/README.md CHANGED
@@ -143,7 +143,9 @@ Fetch a FreeScout ticket with all its details and conversation threads.
143
143
  }
144
144
  ```
145
145
 
146
- <img width="575" height="751" alt="image" src="https://github.com/user-attachments/assets/0144056d-f6d6-4275-9f55-dade0be3ba8c" />
146
+ **Example: Fetching a FreeScout ticket with conversation threads**
147
+
148
+ ![FreeScout ticket details and conversation threads displayed in Cursor chat interface](https://github.com/user-attachments/assets/0144056d-f6d6-4275-9f55-dade0be3ba8c)
147
149
 
148
150
 
149
151
  #### `freescout_analyze_ticket`
@@ -160,7 +162,9 @@ Analyze a ticket to determine issue type, root cause, and suggested solutions.
160
162
  - Root cause analysis
161
163
  - Bug vs feature request vs third-party issue determination
162
164
 
163
- <img width="570" height="691" alt="image" src="https://github.com/user-attachments/assets/19080021-1f29-45a4-8601-556b55d379c3" />
165
+ **Example: Intelligent ticket analysis with issue classification**
166
+
167
+ ![Ticket analysis showing issue type, root cause, and implementation recommendations](https://github.com/user-attachments/assets/19080021-1f29-45a4-8601-556b55d379c3)
164
168
 
165
169
  #### `freescout_add_note`
166
170
  Add an internal note to a ticket for team communication.
@@ -200,7 +204,9 @@ Create a draft reply in FreeScout that can be edited before sending. This tool l
200
204
  3. Use `freescout_create_draft_reply` to save the draft in FreeScout (Markdown automatically converted to HTML)
201
205
  4. Review and edit the draft in FreeScout before sending
202
206
 
203
- <img width="572" height="522" alt="image" src="https://github.com/user-attachments/assets/a4f9eb6c-3204-4744-8aed-8d16d7c7641c" />
207
+ **Example: Draft reply workflow with personalized customer response**
208
+
209
+ ![Draft reply generation showing personalized customer message with ticket context](https://github.com/user-attachments/assets/a4f9eb6c-3204-4744-8aed-8d16d7c7641c)
204
210
 
205
211
  #### `freescout_get_ticket_context`
206
212
  Get ticket context and customer information to help craft personalized replies.
@@ -1 +1 @@
1
- {"version":3,"file":"freescout-api.d.ts","sourceRoot":"","sources":["../src/freescout-api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAK3C;;OAEG;IACH,OAAO,CAAC,cAAc;YAqFR,OAAO;IA6Bf,eAAe,CACnB,QAAQ,EAAE,MAAM,EAChB,cAAc,GAAE,OAAc,GAC7B,OAAO,CAAC,qBAAqB,CAAC;IAO3B,SAAS,CACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,EACrC,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW,GAC5B,OAAO,CAAC,eAAe,CAAC;IAqBrB,gBAAgB,CACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,eAAe,CAAC;IAMrB,kBAAkB,CACtB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;QACP,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;QAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GACA,OAAO,CAAC,qBAAqB,CAAC;IAQ3B,mBAAmB,CACvB,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,CAAC,qBAAqB,CAAC,CAAC;IAUvD,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAQlD,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAoBxC"}
1
+ {"version":3,"file":"freescout-api.d.ts","sourceRoot":"","sources":["../src/freescout-api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAK3C;;OAEG;IACH,OAAO,CAAC,cAAc;YAgIR,OAAO;IA6Bf,eAAe,CACnB,QAAQ,EAAE,MAAM,EAChB,cAAc,GAAE,OAAc,GAC7B,OAAO,CAAC,qBAAqB,CAAC;IAO3B,SAAS,CACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,EACrC,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW,GAC5B,OAAO,CAAC,eAAe,CAAC;IAqBrB,gBAAgB,CACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,eAAe,CAAC;IAMrB,kBAAkB,CACtB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;QACP,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;QAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GACA,OAAO,CAAC,qBAAqB,CAAC;IAQ3B,mBAAmB,CACvB,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,CAAC,qBAAqB,CAAC,CAAC;IAUvD,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAQlD,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAoBxC"}
@@ -10,24 +10,61 @@ export class FreeScoutAPI {
10
10
  * Convert Markdown formatting to HTML for FreeScout
11
11
  */
12
12
  markdownToHtml(text) {
13
- let html = text;
14
13
  // Convert bold text: **text** or __text__ -> <strong>text</strong>
15
- html = html.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
16
- html = html.replace(/__(.*?)__/g, '<strong>$1</strong>');
17
- // Convert italic text: *text* or _text_ -> <em>text</em> (but not if already in bold)
14
+ let html = text
15
+ .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
16
+ .replace(/__(.*?)__/g, '<strong>$1</strong>');
17
+ // Convert italic text: *text* or _text_ -> <em>text</em> (avoid conflicts with bold)
18
18
  html = html.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, '<em>$1</em>');
19
19
  html = html.replace(/(?<!_)_([^_]+)_(?!_)/g, '<em>$1</em>');
20
20
  // Convert code: `text` -> <code>text</code>
21
21
  html = html.replace(/`(.*?)`/g, '<code>$1</code>');
22
- // Handle numbered lists
22
+ // Process the entire text to handle lists that span paragraph breaks
23
23
  const lines = html.split('\n');
24
24
  const processedLines = [];
25
25
  let inOrderedList = false;
26
26
  let inUnorderedList = false;
27
+ let currentParagraph = [];
27
28
  for (let i = 0; i < lines.length; i++) {
28
- const line = lines[i].trim();
29
+ const line = lines[i];
30
+ const trimmedLine = line.trim();
31
+ // Check for empty lines (paragraph breaks)
32
+ if (!trimmedLine) {
33
+ // Check if the next non-empty line is also a list item
34
+ const nextListItemIndex = lines.slice(i + 1).findIndex(nextLine => {
35
+ const nextTrimmed = nextLine.trim();
36
+ return nextTrimmed && (/^\d+\.\s+/.test(nextTrimmed) || /^[-*]\s+/.test(nextTrimmed));
37
+ });
38
+ // If we're in a list and the next item is also a list item, continue the list
39
+ if ((inOrderedList || inUnorderedList) && nextListItemIndex !== -1) {
40
+ continue; // Skip this empty line but keep the list open
41
+ }
42
+ // Close any current lists before starting new paragraph
43
+ if (inOrderedList) {
44
+ processedLines.push('</ol>');
45
+ inOrderedList = false;
46
+ }
47
+ if (inUnorderedList) {
48
+ processedLines.push('</ul>');
49
+ inUnorderedList = false;
50
+ }
51
+ // Process accumulated paragraph
52
+ if (currentParagraph.length > 0) {
53
+ const paragraphContent = currentParagraph.join('<br>');
54
+ processedLines.push(`<p>${paragraphContent}</p>`);
55
+ currentParagraph = [];
56
+ }
57
+ // Skip extra empty lines
58
+ continue;
59
+ }
29
60
  // Check for numbered list items
30
- if (/^\d+\.\s+/.test(line)) {
61
+ if (/^\d+\.\s+/.test(trimmedLine)) {
62
+ // Finish any current paragraph
63
+ if (currentParagraph.length > 0) {
64
+ const paragraphContent = currentParagraph.join('<br>');
65
+ processedLines.push(`<p>${paragraphContent}</p>`);
66
+ currentParagraph = [];
67
+ }
31
68
  if (!inOrderedList) {
32
69
  if (inUnorderedList) {
33
70
  processedLines.push('</ul>');
@@ -36,11 +73,17 @@ export class FreeScoutAPI {
36
73
  processedLines.push('<ol>');
37
74
  inOrderedList = true;
38
75
  }
39
- const content = line.replace(/^\d+\.\s+/, '');
76
+ const content = trimmedLine.replace(/^\d+\.\s+/, '');
40
77
  processedLines.push(`<li>${content}</li>`);
41
78
  }
42
79
  // Check for bullet list items
43
- else if (/^[-*]\s+/.test(line)) {
80
+ else if (/^[-*]\s+/.test(trimmedLine)) {
81
+ // Finish any current paragraph
82
+ if (currentParagraph.length > 0) {
83
+ const paragraphContent = currentParagraph.join('<br>');
84
+ processedLines.push(`<p>${paragraphContent}</p>`);
85
+ currentParagraph = [];
86
+ }
44
87
  if (!inUnorderedList) {
45
88
  if (inOrderedList) {
46
89
  processedLines.push('</ol>');
@@ -49,11 +92,12 @@ export class FreeScoutAPI {
49
92
  processedLines.push('<ul>');
50
93
  inUnorderedList = true;
51
94
  }
52
- const content = line.replace(/^[-*]\s+/, '');
95
+ const content = trimmedLine.replace(/^[-*]\s+/, '');
53
96
  processedLines.push(`<li>${content}</li>`);
54
97
  }
55
98
  // Regular line
56
99
  else {
100
+ // Close any lists
57
101
  if (inOrderedList) {
58
102
  processedLines.push('</ol>');
59
103
  inOrderedList = false;
@@ -62,7 +106,8 @@ export class FreeScoutAPI {
62
106
  processedLines.push('</ul>');
63
107
  inUnorderedList = false;
64
108
  }
65
- processedLines.push(line);
109
+ // Add to current paragraph
110
+ currentParagraph.push(trimmedLine);
66
111
  }
67
112
  }
68
113
  // Close any remaining lists
@@ -70,18 +115,12 @@ export class FreeScoutAPI {
70
115
  processedLines.push('</ol>');
71
116
  if (inUnorderedList)
72
117
  processedLines.push('</ul>');
73
- html = processedLines.join('\n');
74
- // Convert line breaks: double newlines -> paragraph breaks, single newlines -> <br>
75
- html = html.replace(/\n\n+/g, '</p>\n\n<p>');
76
- html = html.replace(/\n/g, '<br>\n');
77
- // Wrap content in paragraphs, but don't wrap lists
78
- html = html.replace(/^(?!<[uo]l>|<\/[uo]l>|<li>)/gm, '<p>')
79
- .replace(/(?<!<\/li>)$/gm, '</p>');
80
- // Clean up paragraph tags around lists
81
- html = html.replace(/<p>(<[uo]l>)/g, '$1');
82
- html = html.replace(/(<\/[uo]l>)<\/p>/g, '$1');
83
- html = html.replace(/<p><\/p>/g, '');
84
- return html;
118
+ // Process any remaining paragraph
119
+ if (currentParagraph.length > 0) {
120
+ const paragraphContent = currentParagraph.join('<br>');
121
+ processedLines.push(`<p>${paragraphContent}</p>`);
122
+ }
123
+ return processedLines.join('\n\n');
85
124
  }
86
125
  async request(path, method = 'GET', body) {
87
126
  const url = `${this.baseUrl}/api${path}`;
@@ -1 +1 @@
1
- {"version":3,"file":"freescout-api.js","sourceRoot":"","sources":["../src/freescout-api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"freescout-api.js","sourceRoot":"","sources":["../src/freescout-api.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verygoodplugins/mcp-freescout",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "MCP server for FreeScout ticket management and workflow automation",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -0,0 +1,150 @@
1
+ // Quick test of the markdown converter
2
+ const testInput = `Hi Victor,
3
+
4
+ Thanks for helping us identify this issue! Based on your experience with the EngageBay LiveChat plugin conflict, we've implemented a solution to prevent this confusion for future users.
5
+
6
+ **What we've added:**
7
+
8
+ 1. **Proactive Warning System** - When users have conflicting plugins installed (like EngageBay LiveChat, LeadConnector, or GHL Connect), WP Fusion will now display a warning message before they attempt OAuth authorization, letting them know these plugins may interfere with the connection process.
9
+
10
+ 2. **Enhanced Error Messages** - If the \`invalid_grant\` error does occur, users will now receive specific guidance about potential plugin conflicts rather than the cryptic error message you experienced.
11
+
12
+ This improvement will be included in the next WP Fusion update and should help other users avoid the frustration you encountered. The system will specifically detect the EngageBay LiveChat plugin (and others we discover) and provide clear guidance on temporarily disabling them during the OAuth setup process.
13
+
14
+ Thanks again for your patience in working through this issue and helping us identify the root cause. Your feedback directly led to this improvement that will benefit all WP Fusion users integrating with HighLevel!
15
+
16
+ Best regards,
17
+ Jack`;
18
+
19
+ function markdownToHtml(text) {
20
+ // Convert bold text: **text** or __text__ -> <strong>text</strong>
21
+ let html = text
22
+ .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
23
+ .replace(/__(.*?)__/g, '<strong>$1</strong>');
24
+
25
+ // Convert italic text: *text* or _text_ -> <em>text</em> (avoid conflicts with bold)
26
+ html = html.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, '<em>$1</em>');
27
+ html = html.replace(/(?<!_)_([^_]+)_(?!_)/g, '<em>$1</em>');
28
+
29
+ // Convert code: `text` -> <code>text</code>
30
+ html = html.replace(/`(.*?)`/g, '<code>$1</code>');
31
+
32
+ // Process the entire text to handle lists that span paragraph breaks
33
+ const lines = html.split('\n');
34
+ const processedLines = [];
35
+ let inOrderedList = false;
36
+ let inUnorderedList = false;
37
+ let currentParagraph = [];
38
+
39
+ for (let i = 0; i < lines.length; i++) {
40
+ const line = lines[i];
41
+ const trimmedLine = line.trim();
42
+
43
+ // Check for empty lines (paragraph breaks)
44
+ if (!trimmedLine) {
45
+ // Check if the next non-empty line is also a list item
46
+ const nextListItemIndex = lines.slice(i + 1).findIndex(nextLine => {
47
+ const nextTrimmed = nextLine.trim();
48
+ return nextTrimmed && (/^\d+\.\s+/.test(nextTrimmed) || /^[-*]\s+/.test(nextTrimmed));
49
+ });
50
+
51
+ // If we're in a list and the next item is also a list item, continue the list
52
+ if ((inOrderedList || inUnorderedList) && nextListItemIndex !== -1) {
53
+ continue; // Skip this empty line but keep the list open
54
+ }
55
+
56
+ // Close any current lists before starting new paragraph
57
+ if (inOrderedList) {
58
+ processedLines.push('</ol>');
59
+ inOrderedList = false;
60
+ }
61
+ if (inUnorderedList) {
62
+ processedLines.push('</ul>');
63
+ inUnorderedList = false;
64
+ }
65
+
66
+ // Process accumulated paragraph
67
+ if (currentParagraph.length > 0) {
68
+ const paragraphContent = currentParagraph.join('<br>');
69
+ processedLines.push(`<p>${paragraphContent}</p>`);
70
+ currentParagraph = [];
71
+ }
72
+
73
+ // Skip extra empty lines
74
+ continue;
75
+ }
76
+
77
+ // Check for numbered list items
78
+ if (/^\d+\.\s+/.test(trimmedLine)) {
79
+ // Finish any current paragraph
80
+ if (currentParagraph.length > 0) {
81
+ const paragraphContent = currentParagraph.join('<br>');
82
+ processedLines.push(`<p>${paragraphContent}</p>`);
83
+ currentParagraph = [];
84
+ }
85
+
86
+ if (!inOrderedList) {
87
+ if (inUnorderedList) {
88
+ processedLines.push('</ul>');
89
+ inUnorderedList = false;
90
+ }
91
+ processedLines.push('<ol>');
92
+ inOrderedList = true;
93
+ }
94
+ const content = trimmedLine.replace(/^\d+\.\s+/, '');
95
+ processedLines.push(`<li>${content}</li>`);
96
+ }
97
+ // Check for bullet list items
98
+ else if (/^[-*]\s+/.test(trimmedLine)) {
99
+ // Finish any current paragraph
100
+ if (currentParagraph.length > 0) {
101
+ const paragraphContent = currentParagraph.join('<br>');
102
+ processedLines.push(`<p>${paragraphContent}</p>`);
103
+ currentParagraph = [];
104
+ }
105
+
106
+ if (!inUnorderedList) {
107
+ if (inOrderedList) {
108
+ processedLines.push('</ol>');
109
+ inOrderedList = false;
110
+ }
111
+ processedLines.push('<ul>');
112
+ inUnorderedList = true;
113
+ }
114
+ const content = trimmedLine.replace(/^[-*]\s+/, '');
115
+ processedLines.push(`<li>${content}</li>`);
116
+ }
117
+ // Regular line
118
+ else {
119
+ // Close any lists
120
+ if (inOrderedList) {
121
+ processedLines.push('</ol>');
122
+ inOrderedList = false;
123
+ }
124
+ if (inUnorderedList) {
125
+ processedLines.push('</ul>');
126
+ inUnorderedList = false;
127
+ }
128
+
129
+ // Add to current paragraph
130
+ currentParagraph.push(trimmedLine);
131
+ }
132
+ }
133
+
134
+ // Close any remaining lists
135
+ if (inOrderedList) processedLines.push('</ol>');
136
+ if (inUnorderedList) processedLines.push('</ul>');
137
+
138
+ // Process any remaining paragraph
139
+ if (currentParagraph.length > 0) {
140
+ const paragraphContent = currentParagraph.join('<br>');
141
+ processedLines.push(`<p>${paragraphContent}</p>`);
142
+ }
143
+
144
+ return processedLines.join('\n\n');
145
+ }
146
+
147
+ console.log('=== INPUT ===');
148
+ console.log(testInput);
149
+ console.log('\n=== OUTPUT ===');
150
+ console.log(markdownToHtml(testInput));