@verygoodplugins/mcp-freescout 1.0.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/.claude/commands/implement-freescout-ticket.md +422 -0
- package/.claude/mcp-freescout.code-workspace +7 -0
- package/.claude/settings.json +60 -0
- package/.gitattributes +2 -0
- package/LICENSE +674 -0
- package/README.md +477 -0
- package/dist/freescout-api.d.ts +18 -0
- package/dist/freescout-api.d.ts.map +1 -0
- package/dist/freescout-api.js +79 -0
- package/dist/freescout-api.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +604 -0
- package/dist/index.js.map +1 -0
- package/dist/ticket-analyzer.d.ts +15 -0
- package/dist/ticket-analyzer.d.ts.map +1 -0
- package/dist/ticket-analyzer.js +257 -0
- package/dist/ticket-analyzer.js.map +1 -0
- package/dist/types.d.ts +77 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
# MCP FreeScout Server
|
|
2
|
+
|
|
3
|
+
An MCP (Model Context Protocol) server for FreeScout helpdesk ticket management and workflow automation. This server provides tools to interact with FreeScout tickets, analyze issues, manage responses, and integrate with Git workflows.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎫 **Ticket Management**: Fetch, analyze, and update FreeScout tickets
|
|
8
|
+
- 🔍 **Intelligent Analysis**: Automatically analyze tickets to determine issue type, root cause, and solutions
|
|
9
|
+
- 💬 **Draft Responses**: Generate customer replies based on ticket analysis
|
|
10
|
+
- 🌳 **Git Integration**: Create and manage Git worktrees for ticket implementations
|
|
11
|
+
- 🔄 **Full Workflow Support**: Complete ticket-to-PR workflow automation
|
|
12
|
+
- 📊 **Search Capabilities**: Search and filter tickets across your FreeScout instance
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
### Prerequisites
|
|
17
|
+
|
|
18
|
+
- Node.js 18 or higher
|
|
19
|
+
- FreeScout instance with API access enabled
|
|
20
|
+
- Git (for worktree management features)
|
|
21
|
+
|
|
22
|
+
## Quick Start (Recommended)
|
|
23
|
+
|
|
24
|
+
The easiest way to use this MCP server is with `npx`:
|
|
25
|
+
|
|
26
|
+
### With Claude Desktop
|
|
27
|
+
|
|
28
|
+
Add this to your Claude Desktop settings (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"mcpServers": {
|
|
33
|
+
"freescout": {
|
|
34
|
+
"command": "npx",
|
|
35
|
+
"args": ["@verygoodplugins/mcp-freescout@latest"],
|
|
36
|
+
"env": {
|
|
37
|
+
"FREESCOUT_URL": "https://your-freescout-domain.com",
|
|
38
|
+
"FREESCOUT_API_KEY": "your-api-key-here"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### With Cursor IDE
|
|
46
|
+
|
|
47
|
+
Add this to your Cursor settings.json:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"mcp.servers": {
|
|
52
|
+
"freescout": {
|
|
53
|
+
"command": "npx",
|
|
54
|
+
"args": ["@verygoodplugins/mcp-freescout@latest"],
|
|
55
|
+
"env": {
|
|
56
|
+
"FREESCOUT_URL": "https://your-freescout-domain.com",
|
|
57
|
+
"FREESCOUT_API_KEY": "your-api-key-here"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
That's it! The server will automatically use your current workspace directory for Git operations.
|
|
65
|
+
|
|
66
|
+
## Manual Installation (Alternative)
|
|
67
|
+
|
|
68
|
+
If you prefer to install and run the server locally:
|
|
69
|
+
|
|
70
|
+
1. Clone this repository:
|
|
71
|
+
```bash
|
|
72
|
+
git clone https://github.com/verygoodplugins/mcp-freescout.git
|
|
73
|
+
cd mcp-freescout
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
2. Install dependencies:
|
|
77
|
+
```bash
|
|
78
|
+
npm install
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
3. Build the TypeScript code:
|
|
82
|
+
```bash
|
|
83
|
+
npm run build
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
4. Configure your MCP client to use the local installation:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"mcpServers": {
|
|
91
|
+
"freescout": {
|
|
92
|
+
"command": "node",
|
|
93
|
+
"args": ["/path/to/mcp-freescout/dist/index.js"],
|
|
94
|
+
"env": {
|
|
95
|
+
"FREESCOUT_URL": "https://your-freescout-domain.com",
|
|
96
|
+
"FREESCOUT_API_KEY": "your-api-key-here"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Usage with Other MCP Clients
|
|
104
|
+
|
|
105
|
+
Run the server directly:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
npm start
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Or in development mode with auto-reload:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npm run dev
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Available Tools
|
|
118
|
+
|
|
119
|
+
### Core Ticket Operations
|
|
120
|
+
|
|
121
|
+
#### `freescout_get_ticket`
|
|
122
|
+
Fetch a FreeScout ticket with all its details and conversation threads.
|
|
123
|
+
|
|
124
|
+
**Parameters:**
|
|
125
|
+
- `ticket` (required): Ticket ID, number, or FreeScout URL
|
|
126
|
+
- `includeThreads` (optional): Include conversation threads (default: true)
|
|
127
|
+
|
|
128
|
+
**Example:**
|
|
129
|
+
```javascript
|
|
130
|
+
{
|
|
131
|
+
"ticket": "12345",
|
|
132
|
+
"includeThreads": true
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### `freescout_analyze_ticket`
|
|
137
|
+
Analyze a ticket to determine issue type, root cause, and suggested solutions.
|
|
138
|
+
|
|
139
|
+
**Parameters:**
|
|
140
|
+
- `ticket` (required): Ticket ID, number, or FreeScout URL
|
|
141
|
+
|
|
142
|
+
**Returns:**
|
|
143
|
+
- Customer information
|
|
144
|
+
- Issue description and classification
|
|
145
|
+
- Code snippets and error messages
|
|
146
|
+
- Reproducibility status
|
|
147
|
+
- Root cause analysis
|
|
148
|
+
- Bug vs feature request vs third-party issue determination
|
|
149
|
+
|
|
150
|
+
#### `freescout_add_note`
|
|
151
|
+
Add an internal note to a ticket for team communication.
|
|
152
|
+
|
|
153
|
+
**Parameters:**
|
|
154
|
+
- `ticket` (required): Ticket ID, number, or FreeScout URL
|
|
155
|
+
- `note` (required): The note content
|
|
156
|
+
- `userId` (optional): User ID for the note (defaults to env setting)
|
|
157
|
+
|
|
158
|
+
#### `freescout_update_ticket`
|
|
159
|
+
Update ticket status and/or assignment.
|
|
160
|
+
|
|
161
|
+
**Parameters:**
|
|
162
|
+
- `ticket` (required): Ticket ID, number, or FreeScout URL
|
|
163
|
+
- `status` (optional): New status ('active', 'pending', 'closed', 'spam')
|
|
164
|
+
- `assignTo` (optional): User ID to assign the ticket to
|
|
165
|
+
|
|
166
|
+
#### `freescout_draft_reply`
|
|
167
|
+
Generate a customer reply based on ticket analysis and fix description.
|
|
168
|
+
|
|
169
|
+
**Parameters:**
|
|
170
|
+
- `ticket` (required): Ticket ID, number, or FreeScout URL
|
|
171
|
+
- `fixDescription` (optional): Description of the implemented fix
|
|
172
|
+
- `isExplanatory` (optional): Whether this is an explanatory reply (no code changes)
|
|
173
|
+
|
|
174
|
+
#### `freescout_search_tickets`
|
|
175
|
+
Search for tickets across your FreeScout instance.
|
|
176
|
+
|
|
177
|
+
**Parameters:**
|
|
178
|
+
- `query` (required): Search query
|
|
179
|
+
- `status` (optional): Filter by status ('active', 'pending', 'closed', 'spam', 'all')
|
|
180
|
+
|
|
181
|
+
### Git Workflow Tools
|
|
182
|
+
|
|
183
|
+
#### `git_create_worktree`
|
|
184
|
+
Create a Git worktree for isolated ticket implementation.
|
|
185
|
+
|
|
186
|
+
**Parameters:**
|
|
187
|
+
- `ticketId` (required): Ticket ID for the worktree
|
|
188
|
+
- `branchName` (optional): Custom branch name (default: fix/freescout-{ticketId})
|
|
189
|
+
- `baseBranch` (optional): Base branch to create from (default: master)
|
|
190
|
+
|
|
191
|
+
#### `git_remove_worktree`
|
|
192
|
+
Remove a Git worktree after work is complete.
|
|
193
|
+
|
|
194
|
+
**Parameters:**
|
|
195
|
+
- `ticketId` (required): Ticket ID of the worktree to remove
|
|
196
|
+
|
|
197
|
+
#### `github_create_pr`
|
|
198
|
+
Create a GitHub pull request for the current branch. Automatically detects the repository from git remote.
|
|
199
|
+
|
|
200
|
+
**Parameters:**
|
|
201
|
+
- `title` (required): PR title
|
|
202
|
+
- `body` (required): PR description/body
|
|
203
|
+
- `ticketId` (optional): FreeScout ticket ID for reference (adds link to PR body)
|
|
204
|
+
- `branch` (optional): Branch name (defaults to current branch)
|
|
205
|
+
- `baseBranch` (optional): Base branch (default: master)
|
|
206
|
+
- `draft` (optional): Create as draft PR (default: false)
|
|
207
|
+
|
|
208
|
+
**Features:**
|
|
209
|
+
- Auto-detects GitHub repository from git remote (no configuration needed!)
|
|
210
|
+
- Adds FreeScout ticket link to PR body when ticketId is provided
|
|
211
|
+
- Supports draft PRs for work in progress
|
|
212
|
+
- Uses GitHub CLI (gh) for authentication
|
|
213
|
+
|
|
214
|
+
### Workflow Automation
|
|
215
|
+
|
|
216
|
+
#### `freescout_implement_ticket`
|
|
217
|
+
Complete workflow automation: analyze ticket, create worktree, and prepare implementation plan.
|
|
218
|
+
|
|
219
|
+
**Parameters:**
|
|
220
|
+
- `ticket` (required): Ticket ID, number, or FreeScout URL
|
|
221
|
+
- `additionalContext` (optional): Additional context or implementation suggestions
|
|
222
|
+
- `autoCreateWorktree` (optional): Automatically create Git worktree (default: true)
|
|
223
|
+
|
|
224
|
+
**Returns:**
|
|
225
|
+
- Complete ticket analysis
|
|
226
|
+
- Customer information
|
|
227
|
+
- Issue classification (bug/feature/third-party)
|
|
228
|
+
- Implementation plan
|
|
229
|
+
- Git worktree details
|
|
230
|
+
- Next steps guidance
|
|
231
|
+
|
|
232
|
+
## Workflow Examples
|
|
233
|
+
|
|
234
|
+
### Basic Ticket Analysis
|
|
235
|
+
```javascript
|
|
236
|
+
// Analyze a ticket to understand the issue
|
|
237
|
+
await mcp.callTool('freescout_analyze_ticket', {
|
|
238
|
+
ticket: '12345'
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Complete Implementation Workflow
|
|
243
|
+
```javascript
|
|
244
|
+
// 1. Start the implementation workflow
|
|
245
|
+
const plan = await mcp.callTool('freescout_implement_ticket', {
|
|
246
|
+
ticket: 'https://support.example.com/conversation/12345',
|
|
247
|
+
additionalContext: 'Consider backward compatibility'
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// 2. After implementing the fix, create a GitHub PR
|
|
251
|
+
await mcp.callTool('github_create_pr', {
|
|
252
|
+
title: 'Fix: Validation error in checkout (FreeScout #12345)',
|
|
253
|
+
body: `## Summary
|
|
254
|
+
Fixes the validation error reported in the checkout process.
|
|
255
|
+
|
|
256
|
+
## Changes
|
|
257
|
+
- Fixed validation logic in checkout.js
|
|
258
|
+
- Added error handling for edge cases
|
|
259
|
+
|
|
260
|
+
## Testing
|
|
261
|
+
- Tested with various input combinations
|
|
262
|
+
- All existing tests pass`,
|
|
263
|
+
ticketId: '12345' // Automatically adds FreeScout link to PR
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
// 3. Draft a customer reply
|
|
267
|
+
const reply = await mcp.callTool('freescout_draft_reply', {
|
|
268
|
+
ticket: '12345',
|
|
269
|
+
fixDescription: 'Fixed the validation error in the checkout process'
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
// 4. Add the draft as an internal note for review
|
|
273
|
+
await mcp.callTool('freescout_add_note', {
|
|
274
|
+
ticket: '12345',
|
|
275
|
+
note: `Draft reply for customer:\n\n${reply}`
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// 5. Update ticket status and assignment
|
|
279
|
+
await mcp.callTool('freescout_update_ticket', {
|
|
280
|
+
ticket: '12345',
|
|
281
|
+
status: 'active',
|
|
282
|
+
assignTo: 1
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// 6. Clean up the worktree after PR is created
|
|
286
|
+
await mcp.callTool('git_remove_worktree', {
|
|
287
|
+
ticketId: '12345'
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Handling Non-Bug Issues
|
|
292
|
+
```javascript
|
|
293
|
+
// For third-party issues or feature requests
|
|
294
|
+
const reply = await mcp.callTool('freescout_draft_reply', {
|
|
295
|
+
ticket: '12345',
|
|
296
|
+
fixDescription: 'This is a limitation of the Elementor plugin that we cannot override.',
|
|
297
|
+
isExplanatory: true
|
|
298
|
+
});
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Architecture
|
|
302
|
+
|
|
303
|
+
### Components
|
|
304
|
+
|
|
305
|
+
1. **FreeScout API Client** (`freescout-api.ts`)
|
|
306
|
+
- Handles all API communication with FreeScout
|
|
307
|
+
- Manages authentication and request formatting
|
|
308
|
+
- Provides ticket parsing utilities
|
|
309
|
+
|
|
310
|
+
2. **Ticket Analyzer** (`ticket-analyzer.ts`)
|
|
311
|
+
- Intelligent ticket content analysis
|
|
312
|
+
- Issue classification (bug vs feature vs configuration)
|
|
313
|
+
- Code snippet and error extraction
|
|
314
|
+
- Root cause determination
|
|
315
|
+
|
|
316
|
+
3. **MCP Server** (`index.ts`)
|
|
317
|
+
- Tool registration and request handling
|
|
318
|
+
- Integration with Git for worktree management
|
|
319
|
+
- Response formatting and error handling
|
|
320
|
+
|
|
321
|
+
### Data Flow
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
User Request → MCP Server → FreeScout API → Ticket Analyzer
|
|
325
|
+
↓ ↓
|
|
326
|
+
Git Operations Analysis Results
|
|
327
|
+
↓ ↓
|
|
328
|
+
Worktree Management Customer Reply
|
|
329
|
+
↓ ↓
|
|
330
|
+
Response → User
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Development
|
|
334
|
+
|
|
335
|
+
### Running in Development Mode
|
|
336
|
+
```bash
|
|
337
|
+
npm run dev
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Running Tests
|
|
341
|
+
```bash
|
|
342
|
+
npm test
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Linting
|
|
346
|
+
```bash
|
|
347
|
+
npm run lint
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Building for Production
|
|
351
|
+
```bash
|
|
352
|
+
npm run build
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## Configuration
|
|
356
|
+
|
|
357
|
+
### Required Environment Variables
|
|
358
|
+
|
|
359
|
+
| Variable | Description | Example |
|
|
360
|
+
|----------|-------------|---------|
|
|
361
|
+
| `FREESCOUT_URL` | Your FreeScout instance URL | `https://support.example.com` |
|
|
362
|
+
| `FREESCOUT_API_KEY` | FreeScout API key | `your-api-key-here` |
|
|
363
|
+
|
|
364
|
+
### Optional Environment Variables
|
|
365
|
+
|
|
366
|
+
| Variable | Description | Default |
|
|
367
|
+
|----------|-------------|---------|
|
|
368
|
+
| `FREESCOUT_DEFAULT_USER_ID` | Default user ID for assignments | `1` |
|
|
369
|
+
| `WORKING_DIRECTORY` | Base directory for Git operations | Current working directory¹ |
|
|
370
|
+
| `GITHUB_TOKEN` | GitHub token for PR creation | - |
|
|
371
|
+
| `GITHUB_REPO` | GitHub repository (owner/repo) | Auto-detected from git remote² |
|
|
372
|
+
|
|
373
|
+
¹ **Note**: Automatically uses the current project/workspace directory. Only set this if you need to work on a different directory.
|
|
374
|
+
|
|
375
|
+
² **Note**: The server automatically detects the GitHub repository from your git remote. Only set `GITHUB_REPO` if you need to override the auto-detection or if your project doesn't have a GitHub remote configured.
|
|
376
|
+
|
|
377
|
+
### Advanced Configuration Example
|
|
378
|
+
|
|
379
|
+
For more control, you can specify additional environment variables:
|
|
380
|
+
|
|
381
|
+
```json
|
|
382
|
+
{
|
|
383
|
+
"mcpServers": {
|
|
384
|
+
"freescout": {
|
|
385
|
+
"command": "npx",
|
|
386
|
+
"args": ["@verygoodplugins/mcp-freescout@latest"],
|
|
387
|
+
"env": {
|
|
388
|
+
"FREESCOUT_URL": "https://support.example.com",
|
|
389
|
+
"FREESCOUT_API_KEY": "your-api-key",
|
|
390
|
+
"FREESCOUT_DEFAULT_USER_ID": "2",
|
|
391
|
+
"WORKING_DIRECTORY": "/path/to/specific/project",
|
|
392
|
+
"GITHUB_TOKEN": "ghp_yourtoken",
|
|
393
|
+
"GITHUB_REPO": "owner/repo"
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### FreeScout API Setup
|
|
401
|
+
|
|
402
|
+
1. Log into your FreeScout instance as an administrator
|
|
403
|
+
2. Navigate to Manage → API Keys
|
|
404
|
+
3. Create a new API key with appropriate permissions:
|
|
405
|
+
- View conversations
|
|
406
|
+
- Update conversations
|
|
407
|
+
- Create threads (for notes)
|
|
408
|
+
|
|
409
|
+
## Best Practices
|
|
410
|
+
|
|
411
|
+
### Ticket Analysis
|
|
412
|
+
- Always analyze tickets before implementing fixes
|
|
413
|
+
- Check for third-party limitations before attempting fixes
|
|
414
|
+
- Verify reproducibility with team notes
|
|
415
|
+
|
|
416
|
+
### Git Workflow
|
|
417
|
+
- Use worktrees for parallel development
|
|
418
|
+
- Clean up worktrees after PR creation
|
|
419
|
+
- Keep branch names descriptive
|
|
420
|
+
|
|
421
|
+
### Customer Communication
|
|
422
|
+
- Generate draft replies for review
|
|
423
|
+
- Include fix descriptions in customer communications
|
|
424
|
+
- Use explanatory replies for non-bug issues
|
|
425
|
+
|
|
426
|
+
## Troubleshooting
|
|
427
|
+
|
|
428
|
+
### Common Issues
|
|
429
|
+
|
|
430
|
+
#### API Connection Errors
|
|
431
|
+
- Verify your FreeScout URL includes the protocol (https://)
|
|
432
|
+
- Check API key permissions in FreeScout
|
|
433
|
+
- Ensure your FreeScout instance has API access enabled
|
|
434
|
+
|
|
435
|
+
#### Git Worktree Errors
|
|
436
|
+
- Ensure Git is installed and accessible
|
|
437
|
+
- Verify the working directory is a Git repository (defaults to current directory)
|
|
438
|
+
- Check that the base branch exists
|
|
439
|
+
- If needed, explicitly set WORKING_DIRECTORY to your Git repository path
|
|
440
|
+
|
|
441
|
+
#### Ticket Parsing Issues
|
|
442
|
+
- The server accepts ticket IDs, numbers, and full URLs
|
|
443
|
+
- URLs are automatically parsed to extract ticket IDs
|
|
444
|
+
- Numeric inputs are treated as ticket IDs
|
|
445
|
+
|
|
446
|
+
## Contributing
|
|
447
|
+
|
|
448
|
+
Contributions are welcome! Please:
|
|
449
|
+
|
|
450
|
+
1. Fork the repository
|
|
451
|
+
2. Create a feature branch
|
|
452
|
+
3. Make your changes with tests
|
|
453
|
+
4. Submit a pull request
|
|
454
|
+
|
|
455
|
+
## License
|
|
456
|
+
|
|
457
|
+
GPL-3.0 License - see LICENSE file for details
|
|
458
|
+
|
|
459
|
+
## Support
|
|
460
|
+
|
|
461
|
+
For issues, questions, or suggestions:
|
|
462
|
+
- [Open an issue on GitHub](https://github.com/verygoodplugins/mcp-freescout/issues)
|
|
463
|
+
- [Contact the maintainers](https://verygoodplugins.com/contact)
|
|
464
|
+
- Check the documentation
|
|
465
|
+
|
|
466
|
+
## Roadmap
|
|
467
|
+
|
|
468
|
+
- [ ] Batch ticket operations
|
|
469
|
+
- [ ] Webhook support for real-time updates
|
|
470
|
+
- [ ] Template system for common replies
|
|
471
|
+
- [ ] Integration with CI/CD pipelines
|
|
472
|
+
- [ ] Advanced search filters
|
|
473
|
+
- [ ] Ticket metrics and analytics
|
|
474
|
+
- [ ] Multi-language support for customer replies
|
|
475
|
+
- [ ] Attachment handling
|
|
476
|
+
- [ ] Custom field support
|
|
477
|
+
- [ ] Automated testing integration
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FreeScoutConversation, FreeScoutApiResponse, FreeScoutThread } from './types.js';
|
|
2
|
+
export declare class FreeScoutAPI {
|
|
3
|
+
private baseUrl;
|
|
4
|
+
private apiKey;
|
|
5
|
+
constructor(baseUrl: string, apiKey: string);
|
|
6
|
+
private request;
|
|
7
|
+
getConversation(ticketId: string, includeThreads?: boolean): Promise<FreeScoutConversation>;
|
|
8
|
+
addThread(ticketId: string, type: 'note' | 'message' | 'customer', text: string, userId?: number): Promise<FreeScoutThread>;
|
|
9
|
+
updateConversation(ticketId: string, updates: {
|
|
10
|
+
status?: 'active' | 'pending' | 'closed' | 'spam';
|
|
11
|
+
assignTo?: number;
|
|
12
|
+
byUser?: number;
|
|
13
|
+
}): Promise<FreeScoutConversation>;
|
|
14
|
+
searchConversations(query: string, status?: string): Promise<FreeScoutApiResponse<FreeScoutConversation>>;
|
|
15
|
+
extractTicketIdFromUrl(url: string): string | null;
|
|
16
|
+
parseTicketInput(input: string): string;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=freescout-api.d.ts.map
|
|
@@ -0,0 +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;YAK7B,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,GACd,OAAO,CAAC,eAAe,CAAC;IAiBrB,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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import fetch from 'node-fetch';
|
|
2
|
+
export class FreeScoutAPI {
|
|
3
|
+
baseUrl;
|
|
4
|
+
apiKey;
|
|
5
|
+
constructor(baseUrl, apiKey) {
|
|
6
|
+
this.baseUrl = baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
7
|
+
this.apiKey = apiKey;
|
|
8
|
+
}
|
|
9
|
+
async request(path, method = 'GET', body) {
|
|
10
|
+
const url = `${this.baseUrl}/api${path}`;
|
|
11
|
+
const headers = {
|
|
12
|
+
'X-FreeScout-API-Key': this.apiKey,
|
|
13
|
+
};
|
|
14
|
+
if (body) {
|
|
15
|
+
headers['Content-Type'] = 'application/json';
|
|
16
|
+
}
|
|
17
|
+
const response = await fetch(url, {
|
|
18
|
+
method,
|
|
19
|
+
headers,
|
|
20
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
21
|
+
});
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
const errorText = await response.text();
|
|
24
|
+
throw new Error(`FreeScout API error: ${response.status} - ${errorText}`);
|
|
25
|
+
}
|
|
26
|
+
return response.json();
|
|
27
|
+
}
|
|
28
|
+
async getConversation(ticketId, includeThreads = true) {
|
|
29
|
+
const embed = includeThreads ? '?embed=threads' : '';
|
|
30
|
+
return this.request(`/conversations/${ticketId}${embed}`);
|
|
31
|
+
}
|
|
32
|
+
async addThread(ticketId, type, text, userId) {
|
|
33
|
+
const body = {
|
|
34
|
+
type,
|
|
35
|
+
text,
|
|
36
|
+
};
|
|
37
|
+
if (userId) {
|
|
38
|
+
body.user = userId;
|
|
39
|
+
}
|
|
40
|
+
return this.request(`/conversations/${ticketId}/threads`, 'POST', body);
|
|
41
|
+
}
|
|
42
|
+
async updateConversation(ticketId, updates) {
|
|
43
|
+
return this.request(`/conversations/${ticketId}`, 'PUT', updates);
|
|
44
|
+
}
|
|
45
|
+
async searchConversations(query, status) {
|
|
46
|
+
const params = new URLSearchParams();
|
|
47
|
+
if (query)
|
|
48
|
+
params.append('query', query);
|
|
49
|
+
if (status)
|
|
50
|
+
params.append('status', status);
|
|
51
|
+
return this.request(`/conversations?${params.toString()}`);
|
|
52
|
+
}
|
|
53
|
+
extractTicketIdFromUrl(url) {
|
|
54
|
+
// Match patterns like:
|
|
55
|
+
// https://domain.com/conversation/12345
|
|
56
|
+
// https://domain.com/conversations/12345
|
|
57
|
+
const match = url.match(/conversations?\/(\d+)/);
|
|
58
|
+
return match ? match[1] : null;
|
|
59
|
+
}
|
|
60
|
+
parseTicketInput(input) {
|
|
61
|
+
// Check if input is a URL
|
|
62
|
+
if (input.includes('http')) {
|
|
63
|
+
const ticketId = this.extractTicketIdFromUrl(input);
|
|
64
|
+
if (ticketId)
|
|
65
|
+
return ticketId;
|
|
66
|
+
}
|
|
67
|
+
// Check if input is numeric (ticket ID)
|
|
68
|
+
if (/^\d+$/.test(input.trim())) {
|
|
69
|
+
return input.trim();
|
|
70
|
+
}
|
|
71
|
+
// Try to extract ticket ID from text like "ticket #12345"
|
|
72
|
+
const match = input.match(/#?(\d+)/);
|
|
73
|
+
if (match) {
|
|
74
|
+
return match[1];
|
|
75
|
+
}
|
|
76
|
+
throw new Error(`Could not extract ticket ID from input: ${input}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=freescout-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"freescout-api.js","sourceRoot":"","sources":["../src/freescout-api.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|