groovehq-mcp 0.2.0 → 0.4.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 +29 -2
- package/dist/groove-client.d.ts.map +1 -1
- package/dist/groove-client.js +6 -0
- package/dist/groove-client.js.map +1 -1
- package/dist/index.js +8 -905
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +12 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +980 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/conversations.d.ts +18 -0
- package/dist/tools/conversations.d.ts.map +1 -1
- package/dist/tools/conversations.js +53 -1
- package/dist/tools/conversations.js.map +1 -1
- package/dist/tools/drafts.d.ts +1 -1
- package/dist/tools/drafts.d.ts.map +1 -1
- package/dist/tools/drafts.js +7 -2
- package/dist/tools/drafts.js.map +1 -1
- package/dist/utils/graphql-queries.d.ts +4 -0
- package/dist/utils/graphql-queries.d.ts.map +1 -1
- package/dist/utils/graphql-queries.js +46 -0
- package/dist/utils/graphql-queries.js.map +1 -1
- package/package.json +11 -1
package/README.md
CHANGED
|
@@ -15,8 +15,9 @@ Both repos use Groove's REST API for conversations. This one runs on GraphQL onl
|
|
|
15
15
|
- `listConversations`: search and filter by keyword, state, agent, team, contact, channel, or tag
|
|
16
16
|
- `getConversation`: get one ticket
|
|
17
17
|
- `createConversation`: start a new ticket by sending an email
|
|
18
|
-
- `updateConversation`: change the state, assign someone, or add tags
|
|
18
|
+
- `updateConversation`: change the state, assign or unassign someone, or add or remove tags
|
|
19
19
|
- `closeConversation`: the most satisfying one
|
|
20
|
+
- `mergeConversations`: merge one ticket into another. This can't be undone
|
|
20
21
|
|
|
21
22
|
**Messages**
|
|
22
23
|
|
|
@@ -60,6 +61,18 @@ Using a different MCP client? Have it run `npx -y groovehq-mcp` and set `GROOVE_
|
|
|
60
61
|
|
|
61
62
|
> **Heads up:** the package is `groovehq-mcp`, with the `hq`. `groove-mcp` doesn't work.
|
|
62
63
|
|
|
64
|
+
## Use as a library
|
|
65
|
+
|
|
66
|
+
You can run the same tools over your own transport, for example in a Cloudflare Worker. `createGrooveServer` returns a new MCP `Server` and connects nothing itself:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { createGrooveServer } from 'groovehq-mcp/server';
|
|
70
|
+
|
|
71
|
+
const server = createGrooveServer({ token: 'your_token_here', readOnly: true });
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`allowSend`, `allowMerge`, and `apiUrl` are optional too. Sending stays off unless you set `allowSend: true`, merging stays on unless you set `allowMerge: false`, and `readOnly` always wins.
|
|
75
|
+
|
|
63
76
|
## Handle with care
|
|
64
77
|
|
|
65
78
|
This server can send real email to real customers. A few things keep that honest:
|
|
@@ -67,6 +80,7 @@ This server can send real email to real customers. A few things keep that honest
|
|
|
67
80
|
- **Sending is off by default.** `sendMessage` and `createConversation` only appear when you set `GROOVE_ALLOW_SEND=1`.
|
|
68
81
|
- **Read-only mode.** Set `GROOVE_READ_ONLY=1` to leave out every tool that writes, including drafts.
|
|
69
82
|
- **Recipients are always explicit.** `createConversation` and `sendMessage` require a `to` address, and nothing is sent to a default.
|
|
83
|
+
- **Merging is permanent.** Only the target ticket stays, with its own contact, subject, and assignee. Replies and notes move over, tags are combined, and an open ticket reopens the target. `mergeConversations` is marked as destructive, and it refuses tickets with different contacts or your own drafts on the merged ticket unless told otherwise. Set `GROOVE_ALLOW_MERGE=0` to turn merging off.
|
|
70
84
|
- **Failed updates tell you what happened.** Groove has no all-or-nothing update, so `updateConversation` can succeed halfway. When it does, the error says which steps already went through.
|
|
71
85
|
|
|
72
86
|
Sending a draft from Groove may close the ticket, depending on your Groove settings.
|
|
@@ -78,7 +92,8 @@ Your MCP client will usually ask before a tool runs. For sending mail, it's a go
|
|
|
78
92
|
- **Some of this API is undocumented.** Sending mail and adding notes are in the official docs. The read queries (`conversations` and `events`) aren't, but Groove's own web app uses them.
|
|
79
93
|
- **Not tested with everything.** Our account only has email tickets and no knowledge base articles, so chat, widget, knowledge base search haven't been tried with real data.
|
|
80
94
|
- **Drafts are personal.** They belong to the agent who owns the API token, and they only work on existing tickets.
|
|
81
|
-
- **
|
|
95
|
+
- **Merged messages don't get sorted.** Groove adds them to the end of the ticket with their original dates, while `listMessages` always sorts by date.
|
|
96
|
+
- **Some things aren't in here yet.** You can't send attachments, use cc and bcc when sending directly, or set a contact's company.
|
|
82
97
|
|
|
83
98
|
## Development
|
|
84
99
|
|
|
@@ -114,6 +129,18 @@ To test drafts, add `--drafts` and set `GROOVE_TEST_TICKET` to a ticket you own.
|
|
|
114
129
|
GROOVE_API_TOKEN=your_token_here GROOVE_TEST_TICKET=12345 npm run test:live -- --drafts
|
|
115
130
|
```
|
|
116
131
|
|
|
132
|
+
To test changes to a ticket, add `--update`. It finds a ticket whose subject starts with `[TEST]`, changes its tags and assignee, and puts them back. If you don't have one yet, run `--write` once:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
GROOVE_API_TOKEN=your_token_here npm run test:live -- --update
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
To test merging, add `--merge`. It asks first, then sends 3 real mails to `GROOVE_TEST_TO` and a plus address of it, and merges those tickets into one that it closes again:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
GROOVE_API_TOKEN=your_token_here GROOVE_TEST_TO=you@example.com GROOVE_TEST_CHANNEL=ch_123 npm run test:live -- --merge
|
|
142
|
+
```
|
|
143
|
+
|
|
117
144
|
## License
|
|
118
145
|
|
|
119
146
|
MIT. Original work by [Christian Genco](https://github.com/christiangenco). Thanks for the head start!
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groove-client.d.ts","sourceRoot":"","sources":["../src/groove-client.ts"],"names":[],"mappings":"AAIA,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAgB;gBAElB,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAE,MAA8C;IAa9E,OAAO,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"groove-client.d.ts","sourceRoot":"","sources":["../src/groove-client.ts"],"names":[],"mappings":"AAIA,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAgB;gBAElB,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAE,MAA8C;IAa9E,OAAO,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;IAqB5D,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkBtD,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;IAaxE,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC;CAkB7C"}
|
package/dist/groove-client.js
CHANGED
|
@@ -20,6 +20,10 @@ export class GrooveClient {
|
|
|
20
20
|
catch (error) {
|
|
21
21
|
if (error.response?.errors) {
|
|
22
22
|
const graphqlError = error.response.errors[0];
|
|
23
|
+
if (graphqlError.extensions?.code === 'RESOURCE_MERGED') {
|
|
24
|
+
const target = String(graphqlError.extensions.new_conversation_id).replace(/^cnv_/, '#');
|
|
25
|
+
throw new Error(`Ticket was merged into ${target}`);
|
|
26
|
+
}
|
|
23
27
|
// Groove reports an ID that never existed as deleted too
|
|
24
28
|
if (graphqlError.message.includes('object of type Conversation is deleted')) {
|
|
25
29
|
throw new Error('Ticket not found or deleted');
|
|
@@ -36,6 +40,8 @@ export class GrooveClient {
|
|
|
36
40
|
return ticket;
|
|
37
41
|
const response = await this.request(queries.getConversationId, { number: Number(number) });
|
|
38
42
|
if (!response.conversation) {
|
|
43
|
+
// Groove finds no merged ticket by number, but its ID says where it went
|
|
44
|
+
await this.request(queries.getTicketNode, { id: `cnv_${number}` });
|
|
39
45
|
throw new Error(`Ticket not found: ${ticket}`);
|
|
40
46
|
}
|
|
41
47
|
return response.conversation.id;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groove-client.js","sourceRoot":"","sources":["../src/groove-client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"groove-client.js","sourceRoot":"","sources":["../src/groove-client.ts"],"names":[],"mappings":"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"}
|