@opencx/mcp 1.15.38 → 1.15.40

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=contact-segments.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact-segments.spec.d.ts","sourceRoot":"","sources":["../src/contact-segments.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,137 @@
1
+ import { beforeEach, afterEach, describe, expect, it, vi } from 'vitest';
2
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
3
+ import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
4
+ import { createServer } from './server.js';
5
+ const segmentId = '31f84a1a-ae40-4d8f-9f1c-457fed95832a';
6
+ describe('Contact segment mutation tools', () => {
7
+ let client;
8
+ let close;
9
+ let requests;
10
+ let response;
11
+ beforeEach(async () => {
12
+ requests = [];
13
+ response = Response.json({ id: segmentId });
14
+ vi.stubGlobal('fetch', vi.fn(async (request) => {
15
+ requests.push(request);
16
+ return response;
17
+ }));
18
+ const server = createServer('test', 'https://example.test');
19
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
20
+ client = new Client({ name: 'segment-tools-test', version: '1.0.0' });
21
+ await server.connect(serverTransport);
22
+ await client.connect(clientTransport);
23
+ close = async () => {
24
+ await client.close();
25
+ await server.close();
26
+ };
27
+ });
28
+ afterEach(async () => {
29
+ await close();
30
+ vi.unstubAllGlobals();
31
+ });
32
+ it('creates with complete filter rules and a default null description', async () => {
33
+ const definition = {
34
+ or: [
35
+ {
36
+ and: [
37
+ { type: 'contact_belongs_to_segment', segment_id: segmentId, belongs: false },
38
+ { type: 'contacts_custom_data', conditions: [{ key: 'plan', op: 'eq', value: 'pro' }] },
39
+ { type: 'contacts_created_at_between', after: '2026-01-01T00:00:00Z' },
40
+ ],
41
+ },
42
+ ],
43
+ };
44
+ const result = await client.callTool({
45
+ name: 'create_contact_segment',
46
+ arguments: { name: 'Pro', definition },
47
+ });
48
+ expect(result.isError).not.toBe(true);
49
+ const request = requests[0];
50
+ expect(request?.method).toBe('POST');
51
+ expect(request?.url).toBe('https://example.test/contacts/segments');
52
+ expect(await request?.json()).toEqual({ name: 'Pro', description: null, definition });
53
+ });
54
+ it('patches only supplied fields and retains explicit null', async () => {
55
+ await client.callTool({
56
+ name: 'update_contact_segment',
57
+ arguments: { segment_id: segmentId, description: null },
58
+ });
59
+ const request = requests[0];
60
+ expect(request?.method).toBe('PATCH');
61
+ expect(request?.url).toBe(`https://example.test/contacts/segments/${segmentId}`);
62
+ expect(await request?.json()).toEqual({ description: null });
63
+ });
64
+ it('rejects empty updates locally while allowing explicit null', async () => {
65
+ const empty = await client.callTool({
66
+ name: 'update_contact_segment',
67
+ arguments: { segment_id: segmentId },
68
+ });
69
+ expect(empty.isError).toBe(true);
70
+ expect(requests).toHaveLength(0);
71
+ const valid = await client.callTool({
72
+ name: 'update_contact_segment',
73
+ arguments: { segment_id: segmentId, definition: null },
74
+ });
75
+ expect(valid.isError).not.toBe(true);
76
+ expect(requests).toHaveLength(1);
77
+ });
78
+ it.each([
79
+ 'contacts_created_at_between',
80
+ 'last_contacted_at_between',
81
+ 'last_contacted_at_with_handoff_between',
82
+ ])('validates date bounds locally for %s and preserves valid strings', async (type) => {
83
+ for (const tool of ['create_contact_segment', 'update_contact_segment']) {
84
+ for (const bound of ['after', 'before']) {
85
+ requests = [];
86
+ const invalid = await client.callTool({
87
+ name: tool,
88
+ arguments: {
89
+ segment_id: segmentId,
90
+ name: 'Dates',
91
+ definition: { or: [{ and: [{ type, [bound]: 'not-a-date' }] }] },
92
+ },
93
+ });
94
+ expect(invalid.isError).toBe(true);
95
+ expect(requests).toHaveLength(0);
96
+ response = Response.json({ id: segmentId });
97
+ const value = bound === 'after' ? '2026-01-01' : '2026-01-31T12:30:00+03:00';
98
+ const definition = { or: [{ and: [{ type, [bound]: value }] }] };
99
+ const valid = await client.callTool({
100
+ name: tool,
101
+ arguments: { segment_id: segmentId, name: 'Dates', definition },
102
+ });
103
+ expect(valid.isError).not.toBe(true);
104
+ expect(requests).toHaveLength(1);
105
+ expect(await requests[0]?.json()).toMatchObject({ definition });
106
+ }
107
+ }
108
+ });
109
+ it('returns explicit success for a 204 deletion', async () => {
110
+ response = new Response(null, { status: 204 });
111
+ const result = await client.callTool({
112
+ name: 'delete_contact_segment',
113
+ arguments: { segment_id: segmentId },
114
+ });
115
+ expect(requests[0]?.method).toBe('DELETE');
116
+ expect(requests[0]?.url).toBe(`https://example.test/contacts/segments/${segmentId}`);
117
+ expect(result.content).toEqual([{ type: 'text', text: '{"success":true}' }]);
118
+ });
119
+ it.each([400, 403, 404])('propagates HTTP %s failures', async (status) => {
120
+ response = Response.json({ message: 'Rejected' }, { status });
121
+ const result = await client.callTool({
122
+ name: 'update_contact_segment',
123
+ arguments: { segment_id: segmentId, name: 'Rejected' },
124
+ });
125
+ expect(result.isError).toBe(true);
126
+ expect(JSON.stringify(result.content)).toContain(String(status));
127
+ });
128
+ it('rejects malformed filter rules before sending a request', async () => {
129
+ const result = await client.callTool({
130
+ name: 'create_contact_segment',
131
+ arguments: { name: 'Invalid', definition: { or: [] } },
132
+ });
133
+ expect(result.isError).toBe(true);
134
+ expect(requests).toHaveLength(0);
135
+ });
136
+ });
137
+ //# sourceMappingURL=contact-segments.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact-segments.spec.js","sourceRoot":"","sources":["../src/contact-segments.spec.ts"],"names":[],"mappings":"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"}