@critical-path/mcp 0.11.7 → 0.11.8

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,274 +0,0 @@
1
- import { describe, it, expect, beforeEach } from 'vitest';
2
- import { CriticalPathEngine, InMemoryStore } from '@critical-path/core';
3
- import { Client } from '@modelcontextprotocol/sdk/client/index.js';
4
- import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
5
- import { ALL_TOOLS, TOOL_MAP, createCriticalPathMcpServer, registerWebMcpTools, ensureModelContextShim } from './index.js';
6
- describe('@critical-path/mcp', () => {
7
- let engine;
8
- beforeEach(() => {
9
- engine = new CriticalPathEngine({ store: new InMemoryStore() });
10
- });
11
- describe('Tool Definitions', () => {
12
- it('registers all core project management tools', () => {
13
- const toolNames = ALL_TOOLS.map((t) => t.name);
14
- expect(toolNames).toContain('list_projects');
15
- expect(toolNames).toContain('get_project');
16
- expect(toolNames).toContain('create_project');
17
- expect(toolNames).toContain('list_tasks');
18
- expect(toolNames).toContain('get_task');
19
- expect(toolNames).toContain('create_task');
20
- expect(toolNames).toContain('update_task');
21
- expect(toolNames).toContain('delete_task');
22
- expect(toolNames).toContain('list_deliverables');
23
- expect(toolNames).toContain('create_deliverable');
24
- expect(toolNames).toContain('list_comments');
25
- expect(toolNames).toContain('add_comment');
26
- expect(toolNames).toContain('calculate_critical_path');
27
- expect(toolNames).toContain('get_timeline_ladder');
28
- expect(toolNames).toContain('get_task_ladder');
29
- expect(toolNames).toContain('get_workload_distribution');
30
- });
31
- it('executes project and task workflows through tool definitions', async () => {
32
- // 1. Create project
33
- const createProjTool = TOOL_MAP.get('create_project');
34
- const project = await createProjTool.execute({ name: 'Core Engine Dev', key: 'CED' }, engine);
35
- expect(project.id).toBeDefined();
36
- expect(project.name).toBe('Core Engine Dev');
37
- // 2. List projects
38
- const listProjTool = TOOL_MAP.get('list_projects');
39
- const projects = await listProjTool.execute({}, engine);
40
- expect(projects).toHaveLength(1);
41
- expect(projects[0].id).toBe(project.id);
42
- // 3. Create task
43
- const createTaskTool = TOOL_MAP.get('create_task');
44
- const task = await createTaskTool.execute({
45
- projectId: project.id,
46
- title: 'Implement WebMCP Spec',
47
- priority: 'urgent',
48
- tags: ['agent', 'mcp']
49
- }, engine);
50
- expect(task.id).toBeDefined();
51
- expect(task.title).toBe('Implement WebMCP Spec');
52
- expect(task.priority).toBe('urgent');
53
- // 4. Update task
54
- const updateTaskTool = TOOL_MAP.get('update_task');
55
- const updated = await updateTaskTool.execute({
56
- id: task.id,
57
- status: 'in_progress',
58
- estimatedHours: 5
59
- }, engine);
60
- expect(updated.status).toBe('in_progress');
61
- expect(updated.estimatedHours).toBe(5);
62
- // 5. Add comment
63
- const addCommentTool = TOOL_MAP.get('add_comment');
64
- const comment = await addCommentTool.execute({
65
- taskId: task.id,
66
- content: 'Started drafting the WebMCP handler',
67
- authorId: 'agent-1'
68
- }, engine);
69
- expect(comment.content).toBe('Started drafting the WebMCP handler');
70
- // 6. List tasks with filter
71
- const listTasksTool = TOOL_MAP.get('list_tasks');
72
- const filtered = await listTasksTool.execute({ projectId: project.id, status: 'in_progress' }, engine);
73
- expect(filtered.tasks).toHaveLength(1);
74
- expect(filtered.nextCursor).toBeUndefined();
75
- // 7. Delete task
76
- const deleteTaskTool = TOOL_MAP.get('delete_task');
77
- const delRes = await deleteTaskTool.execute({ id: task.id }, engine);
78
- expect(delRes.success).toBe(true);
79
- const afterDelete = await listTasksTool.execute({ projectId: project.id }, engine);
80
- expect(afterDelete.tasks).toHaveLength(0);
81
- });
82
- it('calculates critical path and returns timeline ladder via MCP tools', async () => {
83
- const createProjTool = TOOL_MAP.get('create_project');
84
- const project = await createProjTool.execute({ name: 'Timeline Ladder MCP', key: 'TLM' }, engine);
85
- const createTaskTool = TOOL_MAP.get('create_task');
86
- const t1 = await createTaskTool.execute({
87
- projectId: project.id,
88
- title: 'Step 1: Prototype',
89
- status: 'done',
90
- estimatedHours: 4
91
- }, engine);
92
- const t2 = await createTaskTool.execute({
93
- projectId: project.id,
94
- title: 'Step 2: Polish',
95
- status: 'in_progress',
96
- estimatedHours: 6
97
- }, engine);
98
- await engine.addDependency({
99
- taskId: t2.id,
100
- dependsOnTaskId: t1.id,
101
- type: 'blocking'
102
- });
103
- // 1. calculate_critical_path tool
104
- const cpmTool = TOOL_MAP.get('calculate_critical_path');
105
- const cpmResult = await cpmTool.execute({ projectId: project.id }, engine);
106
- expect(cpmResult.totalDurationHours).toBe(10);
107
- expect(cpmResult.criticalTaskIds).toEqual([t1.id, t2.id]);
108
- // 2. get_timeline_ladder tool
109
- const ladderTool = TOOL_MAP.get('get_timeline_ladder');
110
- const ladderResult = await ladderTool.execute({ projectId: project.id, level: 'all' }, engine);
111
- expect(ladderResult.macro).toBeDefined();
112
- expect(ladderResult.macro.criticalPathDurationHours).toBe(10);
113
- expect(ladderResult.standard.tasks).toHaveLength(2);
114
- // 3. get_task_ladder tool
115
- const taskLadderTool = TOOL_MAP.get('get_task_ladder');
116
- const taskLadderResult = await taskLadderTool.execute({ taskId: t2.id }, engine);
117
- expect(taskLadderResult.taskId).toBe(t2.id);
118
- expect(taskLadderResult.standard.title).toBe('Step 2: Polish');
119
- expect(taskLadderResult.metrics).toBeDefined();
120
- // 4. get_task_metrics tool
121
- const taskMetricsTool = TOOL_MAP.get('get_task_metrics');
122
- const taskMetricsResult = await taskMetricsTool.execute({ taskId: t2.id }, engine);
123
- expect(taskMetricsResult.taskId).toBe(t2.id);
124
- expect(taskMetricsResult.realityDelta.estimatedHours).toBe(6);
125
- expect(taskMetricsResult.progress).toBeDefined();
126
- expect(taskMetricsResult.evm).toBeDefined();
127
- // 5. get_task_progress_history tool
128
- const taskHistoryTool = TOOL_MAP.get('get_task_progress_history');
129
- const taskHistoryResult = await taskHistoryTool.execute({ taskId: t2.id }, engine);
130
- expect(taskHistoryResult.taskId).toBe(t2.id);
131
- expect(taskHistoryResult.points.length).toBeGreaterThanOrEqual(1);
132
- // 6. get_workload_distribution tool
133
- const workloadTool = TOOL_MAP.get('get_workload_distribution');
134
- const workloadResult = await workloadTool.execute({ projectId: project.id, interval: 'week' }, engine);
135
- expect(workloadResult.projectId).toBe(project.id);
136
- expect(workloadResult.buckets.length).toBeGreaterThan(0);
137
- expect(workloadResult.totalHours).toBeGreaterThan(0);
138
- });
139
- });
140
- describe('Standard MCP Server Creation', () => {
141
- it('creates an MCP Server instance with capabilities', () => {
142
- const server = createCriticalPathMcpServer({
143
- engine,
144
- name: 'test-mcp-server',
145
- version: '1.0.0'
146
- });
147
- expect(server).toBeDefined();
148
- });
149
- it('throws if neither engine nor client is provided', () => {
150
- expect(() => createCriticalPathMcpServer({})).toThrow('Either engine or client must be provided');
151
- });
152
- async function connect(options) {
153
- const server = createCriticalPathMcpServer(options);
154
- const client = new Client({ name: 'test-client', version: '1.0.0' });
155
- const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
156
- await Promise.all([server.connect(serverTransport), client.connect(clientTransport)]);
157
- return client;
158
- }
159
- it('refuses to call tools excluded by the tools option', async () => {
160
- const project = await engine.createProject({ name: 'Guarded', key: 'GRD' });
161
- const task = await engine.createTask({ projectId: project.id, title: 'Keep me' });
162
- const client = await connect({ engine, tools: ['list_tasks'] });
163
- const { tools } = await client.listTools();
164
- expect(tools.map((t) => t.name)).toEqual(['list_tasks']);
165
- await expect(client.callTool({ name: 'delete_task', arguments: { id: task.id } })).rejects.toThrow(/not registered/);
166
- expect(await engine.getTask(task.id)).not.toBeNull();
167
- });
168
- it('validates tool arguments and rejects undeclared fields', async () => {
169
- const source = await engine.createProject({ name: 'Source', key: 'SRC' });
170
- const other = await engine.createProject({ name: 'Other', key: 'OTH' });
171
- const task = await engine.createTask({ projectId: source.id, title: 'Stay put' });
172
- const client = await connect({ engine });
173
- const invalid = await client.callTool({ name: 'get_task', arguments: { id: 42 } });
174
- expect(invalid.isError).toBe(true);
175
- expect(invalid.content[0].text).toContain('Invalid arguments');
176
- const undeclared = await client.callTool({
177
- name: 'update_task',
178
- arguments: { id: task.id, title: 'Renamed', projectId: other.id }
179
- });
180
- expect(undeclared.isError).toBe(true);
181
- expect(undeclared.content[0].text).toContain('projectId');
182
- const unchanged = await engine.getTask(task.id);
183
- expect(unchanged?.title).toBe('Stay put');
184
- expect(unchanged?.projectId).toBe(source.id);
185
- });
186
- it('attributes engine writes to the configured actor', async () => {
187
- const project = await engine.createProject({ name: 'Actors', key: 'ACT' });
188
- const task = await engine.createTask({ projectId: project.id, title: 'T' });
189
- const defaultClient = await connect({ engine });
190
- const first = await defaultClient.callTool({ name: 'add_comment', arguments: { taskId: task.id, content: 'hi' } });
191
- expect(JSON.parse(first.content[0].text).authorId).toBe('mcp-agent');
192
- const namedClient = await connect({ engine, actor: { userId: 'claude', actorType: 'agent' } });
193
- const second = await namedClient.callTool({ name: 'add_comment', arguments: { taskId: task.id, content: 'hi' } });
194
- expect(JSON.parse(second.content[0].text).authorId).toBe('claude');
195
- });
196
- it('marks destructive tools with MCP annotations', async () => {
197
- const client = await connect({ engine });
198
- const { tools } = await client.listTools();
199
- expect(tools.find((t) => t.name === 'delete_task')?.annotations?.destructiveHint).toBe(true);
200
- expect(tools.find((t) => t.name === 'list_tasks')?.annotations?.readOnlyHint).toBe(true);
201
- });
202
- });
203
- describe('WebMCP Client Layer', () => {
204
- let mockDoc;
205
- let mockWin;
206
- beforeEach(() => {
207
- mockDoc = {};
208
- mockWin = {};
209
- });
210
- it('creates a modelContext shim if document.modelContext is not natively present', () => {
211
- const shim = ensureModelContextShim(mockDoc);
212
- expect(shim).toBeDefined();
213
- expect(mockDoc.modelContext).toBe(shim);
214
- expect(typeof shim.registerTool).toBe('function');
215
- });
216
- it('registers tools into modelContext and allows execution', async () => {
217
- const project = await engine.createProject({ name: 'WebMCP Test Project' });
218
- // Mock client that delegates to engine
219
- const mockClient = {
220
- getProjects: () => engine.getProjects(),
221
- getProject: (id) => engine.getProject(id),
222
- createProject: (d) => engine.createProject(d),
223
- getTasks: (pId) => engine.getTasks(pId),
224
- getTask: (id) => engine.getTask(id),
225
- createTask: (d) => engine.createTask(d),
226
- updateTask: (id, u) => engine.updateTask(id, u),
227
- deleteTask: (id) => engine.deleteTask(id)
228
- };
229
- const handle = registerWebMcpTools({
230
- client: mockClient,
231
- projectId: project.id,
232
- document: mockDoc,
233
- window: mockWin
234
- });
235
- expect(handle.getRegisteredTools().length).toBeGreaterThan(0);
236
- expect(mockDoc.modelContext).toBeDefined();
237
- const registered = await mockDoc.modelContext.getTools();
238
- expect(registered.length).toBe(handle.getRegisteredTools().length);
239
- // Execute create_task via WebMCP modelContext, inheriting ambient projectId
240
- const createdTask = await mockDoc.modelContext.executeTool('create_task', {
241
- title: 'Task Created via WebMCP'
242
- });
243
- expect(createdTask.id).toBeDefined();
244
- expect(createdTask.projectId).toBe(project.id);
245
- expect(createdTask.title).toBe('Task Created via WebMCP');
246
- // Verify window fallback
247
- expect(mockWin.__CRITICAL_PATH_WEBMCP__).toBeDefined();
248
- expect(mockWin.__CRITICAL_PATH_WEBMCP__.projectId).toBe(project.id);
249
- // Cleanup
250
- handle.unregister();
251
- const afterUnregister = await mockDoc.modelContext.getTools();
252
- expect(afterUnregister).toHaveLength(0);
253
- expect(mockWin.__CRITICAL_PATH_WEBMCP__).toBeUndefined();
254
- });
255
- it('supports AbortSignal unregistration lifecycle', async () => {
256
- const controller = new AbortController();
257
- const mockClient = {
258
- getTasks: () => Promise.resolve([])
259
- };
260
- registerWebMcpTools({
261
- client: mockClient,
262
- signal: controller.signal,
263
- document: mockDoc,
264
- window: mockWin
265
- });
266
- let tools = await mockDoc.modelContext.getTools();
267
- expect(tools.length).toBeGreaterThan(0);
268
- controller.abort();
269
- tools = await mockDoc.modelContext.getTools();
270
- expect(tools).toHaveLength(0);
271
- });
272
- });
273
- });
274
- //# sourceMappingURL=index.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EACL,SAAS,EACT,QAAQ,EACR,2BAA2B,EAC3B,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAEpB,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,IAAI,MAA0B,CAAC;IAE/B,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,IAAI,aAAa,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACrD,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC/C,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;YAC7C,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YAC3C,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;YAC9C,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YAC1C,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACxC,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YAC3C,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YAC3C,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YAC3C,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;YACjD,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;YAClD,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;YAC7C,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YAC3C,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;YACvD,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;YACnD,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;YAC/C,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;YAC5E,oBAAoB;YACpB,MAAM,cAAc,GAAG,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAE,CAAC;YACvD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,OAAO,CAC1C,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,KAAK,EAAE,EACvC,MAAM,CACP,CAAC;YACF,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAE7C,mBAAmB;YACnB,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAE,CAAC;YACpD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YACxD,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACjC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAExC,iBAAiB;YACjB,MAAM,cAAc,GAAG,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAE,CAAC;YACpD,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,OAAO,CACvC;gBACE,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,KAAK,EAAE,uBAAuB;gBAC9B,QAAQ,EAAE,QAAQ;gBAClB,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC;aACvB,EACD,MAAM,CACP,CAAC;YACF,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;YACjD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAErC,iBAAiB;YACjB,MAAM,cAAc,GAAG,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAE,CAAC;YACpD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,OAAO,CAC1C;gBACE,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,MAAM,EAAE,aAAa;gBACrB,cAAc,EAAE,CAAC;aAClB,EACD,MAAM,CACP,CAAC;YACF,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAEvC,iBAAiB;YACjB,MAAM,cAAc,GAAG,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAE,CAAC;YACpD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,OAAO,CAC1C;gBACE,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,OAAO,EAAE,qCAAqC;gBAC9C,QAAQ,EAAE,SAAS;aACpB,EACD,MAAM,CACP,CAAC;YACF,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;YAEpE,4BAA4B;YAC5B,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAE,CAAC;YAClD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,OAAO,CAC1C,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,EAChD,MAAM,CACP,CAAC;YACF,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACvC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,aAAa,EAAE,CAAC;YAE5C,iBAAiB;YACjB,MAAM,cAAc,GAAG,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAE,CAAC;YACpD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;YACrE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAElC,MAAM,WAAW,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;YACnF,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;YAClF,MAAM,cAAc,GAAG,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAE,CAAC;YACvD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,MAAM,CAAC,CAAC;YAElG,MAAM,cAAc,GAAG,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAE,CAAC;YACpD,MAAM,EAAE,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC;gBACtC,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,KAAK,EAAE,mBAAmB;gBAC1B,MAAM,EAAE,MAAM;gBACd,cAAc,EAAE,CAAC;aAClB,EAAE,MAAM,CAAC,CAAC;YAEX,MAAM,EAAE,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC;gBACtC,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,KAAK,EAAE,gBAAgB;gBACvB,MAAM,EAAE,aAAa;gBACrB,cAAc,EAAE,CAAC;aAClB,EAAE,MAAM,CAAC,CAAC;YAEX,MAAM,MAAM,CAAC,aAAa,CAAC;gBACzB,MAAM,EAAE,EAAE,CAAC,EAAE;gBACb,eAAe,EAAE,EAAE,CAAC,EAAE;gBACtB,IAAI,EAAE,UAAU;aACjB,CAAC,CAAC;YAEH,kCAAkC;YAClC,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,yBAAyB,CAAE,CAAC;YACzD,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;YAC3E,MAAM,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAE1D,8BAA8B;YAC9B,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,qBAAqB,CAAE,CAAC;YACxD,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,MAAM,CAAC,CAAC;YAC/F,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;YACzC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC9D,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAEpD,0BAA0B;YAC1B,MAAM,cAAc,GAAG,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAE,CAAC;YACxD,MAAM,gBAAgB,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;YACjF,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC5C,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAC/D,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;YAE/C,2BAA2B;YAC3B,MAAM,eAAe,GAAG,QAAQ,CAAC,GAAG,CAAC,kBAAkB,CAAE,CAAC;YAC1D,MAAM,iBAAiB,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;YACnF,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7C,MAAM,CAAC,iBAAiB,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC9D,MAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;YACjD,MAAM,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YAE5C,oCAAoC;YACpC,MAAM,eAAe,GAAG,QAAQ,CAAC,GAAG,CAAC,2BAA2B,CAAE,CAAC;YACnE,MAAM,iBAAiB,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;YACnF,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7C,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;YAElE,oCAAoC;YACpC,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,2BAA2B,CAAE,CAAC;YAChE,MAAM,cAAc,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC;YACvG,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAClD,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YACzD,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC5C,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YAC1D,MAAM,MAAM,GAAG,2BAA2B,CAAC;gBACzC,MAAM;gBACN,IAAI,EAAE,iBAAiB;gBACvB,OAAO,EAAE,OAAO;aACjB,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACzD,MAAM,CAAC,GAAG,EAAE,CAAC,2BAA2B,CAAC,EAAS,CAAC,CAAC,CAAC,OAAO,CAC1D,0CAA0C,CAC3C,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,KAAK,UAAU,OAAO,CAAC,OAA0D;YAC/E,MAAM,MAAM,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAC;YACpD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;YACrE,MAAM,CAAC,eAAe,EAAE,eAAe,CAAC,GAAG,iBAAiB,CAAC,gBAAgB,EAAE,CAAC;YAChF,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YACtF,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;YAC5E,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YAClF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAEhE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;YAC3C,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;YAEzD,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAChG,gBAAgB,CACjB,CAAC;YACF,MAAM,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;YACtE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1E,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;YACxE,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;YAClF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAEzC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YACnF,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM,CAAE,OAAO,CAAC,OAAmC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;YAE5F,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC;gBACvC,IAAI,EAAE,aAAa;gBACnB,SAAS,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,EAAE;aAClE,CAAC,CAAC;YACH,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAE,UAAU,CAAC,OAAmC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;YACvF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChD,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC1C,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3E,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAE5E,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAChD,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;YACnH,MAAM,CAAC,IAAI,CAAC,KAAK,CAAE,KAAK,CAAC,OAAmC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAElG,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;YAC/F,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;YAClH,MAAM,CAAC,IAAI,CAAC,KAAK,CAAE,MAAM,CAAC,OAAmC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClG,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;YAC5D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YACzC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;YAC3C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7F,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3F,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;QACnC,IAAI,OAAY,CAAC;QACjB,IAAI,OAAY,CAAC;QAEjB,UAAU,CAAC,GAAG,EAAE;YACd,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,GAAG,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;YACtF,MAAM,IAAI,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAC3B,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxC,MAAM,CAAC,OAAO,IAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;YACtE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC,CAAC;YAE5E,uCAAuC;YACvC,MAAM,UAAU,GAAQ;gBACtB,WAAW,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE;gBACvC,UAAU,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;gBACjD,aAAa,EAAE,CAAC,CAAM,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;gBAClD,QAAQ,EAAE,CAAC,GAAY,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAChD,OAAO,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3C,UAAU,EAAE,CAAC,CAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;gBAC5C,UAAU,EAAE,CAAC,EAAU,EAAE,CAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC5D,UAAU,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;aAClD,CAAC;YAEF,MAAM,MAAM,GAAG,mBAAmB,CAAC;gBACjC,MAAM,EAAE,UAAU;gBAClB,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,QAAQ,EAAE,OAAO;gBACjB,MAAM,EAAE,OAAO;aAChB,CAAC,CAAC;YAEH,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YAC9D,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;YAE3C,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;YACzD,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,MAAM,CAAC,CAAC;YAEnE,4EAA4E;YAC5E,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,aAAa,EAAE;gBACxE,KAAK,EAAE,yBAAyB;aACjC,CAAC,CAAC;YACH,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;YACrC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;YAE1D,yBAAyB;YACzB,MAAM,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC,WAAW,EAAE,CAAC;YACvD,MAAM,CAAC,OAAO,CAAC,wBAAwB,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAEpE,UAAU;YACV,MAAM,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;YAC9D,MAAM,CAAC,eAAe,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACxC,MAAM,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC,aAAa,EAAE,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,UAAU,GAAQ;gBACtB,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;aACpC,CAAC;YAEF,mBAAmB,CAAC;gBAClB,MAAM,EAAE,UAAU;gBAClB,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,QAAQ,EAAE,OAAO;gBACjB,MAAM,EAAE,OAAO;aAChB,CAAC,CAAC;YAEH,IAAI,KAAK,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;YAClD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YAExC,UAAU,CAAC,KAAK,EAAE,CAAC;YAEnB,KAAK,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;YAC9C,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=definitions.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"definitions.test.d.ts","sourceRoot":"","sources":["../../src/tools/definitions.test.ts"],"names":[],"mappings":""}
@@ -1,24 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { ALL_TOOLS } from './definitions.js';
3
- describe('MCP tool definitions', () => {
4
- // inputSchema is generated from zodSchema by defineTool; this guards the generation itself
5
- // (e.g. a zod feature that zod-to-json-schema cannot express would drop fields here).
6
- it.each(ALL_TOOLS.map((t) => [t.name, t]))('%s: zodSchema and inputSchema agree', (_name, tool) => {
7
- const json = tool.inputSchema;
8
- const shape = tool.zodSchema.shape;
9
- expect(Object.keys(shape).sort()).toEqual(Object.keys(json.properties ?? {}).sort());
10
- expect(Object.entries(shape)
11
- .filter(([, schema]) => !schema.isOptional())
12
- .map(([key]) => key)
13
- .sort()).toEqual([...(json.required ?? [])].sort());
14
- });
15
- it('generates closed object schemas with descriptions for every tool', () => {
16
- for (const tool of ALL_TOOLS) {
17
- expect(tool.inputSchema).toMatchObject({ type: 'object', additionalProperties: false });
18
- expect(tool.inputSchema).not.toHaveProperty('$schema');
19
- }
20
- const updateTask = ALL_TOOLS.find((t) => t.name === 'update_task');
21
- expect(updateTask.inputSchema.properties.isBlocked.description).toBe('Whether the task is blocked');
22
- });
23
- });
24
- //# sourceMappingURL=definitions.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"definitions.test.js","sourceRoot":"","sources":["../../src/tools/definitions.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,2FAA2F;IAC3F,sFAAsF;IACtF,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAU,CAAC,CAAC,CAAC,qCAAqC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACzG,MAAM,IAAI,GAAG,IAAI,CAAC,WAA4E,CAAC;QAC/F,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,KAAkD,CAAC;QAEhF,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACrF,MAAM,CACJ,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;aAClB,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;aAC5C,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC;aACnB,IAAI,EAAE,CACV,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC,CAAC;YACxF,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAE,CAAC;QACpE,MAAM,CAAE,UAAU,CAAC,WAAmB,CAAC,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC/G,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,28 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { parseArgs, buildApiHeaders, isInsecureRemote } from './args.js';
3
-
4
- describe('MCP CLI arguments', () => {
5
- it('collects repeated --header flags', () => {
6
- const options = parseArgs(['--api', 'https://x.test/api', '--header', 'X-Tenant: acme', '--header', 'X-Trace: 1']);
7
- expect(options.api).toBe('https://x.test/api');
8
- expect(options.headers).toEqual(['X-Tenant: acme', 'X-Trace: 1']);
9
- });
10
-
11
- it('builds headers from the token env var and flags, with flags taking precedence', () => {
12
- expect(buildApiHeaders(['X-Tenant: acme'], { CRITICAL_PATH_API_TOKEN: 'secret' })).toEqual({
13
- Authorization: 'Bearer secret',
14
- 'X-Tenant': 'acme'
15
- });
16
- expect(buildApiHeaders(['Authorization: Basic abc'], { CRITICAL_PATH_API_TOKEN: 'secret' }).Authorization).toBe(
17
- 'Basic abc'
18
- );
19
- expect(() => buildApiHeaders(['no-colon'], {})).toThrow(/Expected "Name: value"/);
20
- });
21
-
22
- it('flags plain http to remote hosts only', () => {
23
- expect(isInsecureRemote('http://api.example.com')).toBe(true);
24
- expect(isInsecureRemote('https://api.example.com')).toBe(false);
25
- expect(isInsecureRemote('http://localhost:3000/api')).toBe(false);
26
- expect(isInsecureRemote('http://127.0.0.1:3000')).toBe(false);
27
- });
28
- });
package/src/bin/args.ts DELETED
@@ -1,50 +0,0 @@
1
- export interface CliOptions {
2
- db?: string;
3
- api?: string;
4
- headers: string[];
5
- help?: boolean;
6
- }
7
-
8
- export function parseArgs(args: string[]): CliOptions {
9
- const options: CliOptions = { headers: [] };
10
- for (let i = 0; i < args.length; i++) {
11
- const arg = args[i];
12
- if (arg === '--help' || arg === '-h') {
13
- options.help = true;
14
- } else if (arg === '--db' && args[i + 1]) {
15
- options.db = args[++i];
16
- } else if (arg === '--api' && args[i + 1]) {
17
- options.api = args[++i];
18
- } else if (arg === '--header' && args[i + 1]) {
19
- options.headers.push(args[++i]);
20
- }
21
- }
22
- return options;
23
- }
24
-
25
- /**
26
- * Builds request headers for `--api` mode from repeated `--header "Name: value"` flags and the
27
- * `CRITICAL_PATH_API_TOKEN` environment variable (sent as `Authorization: Bearer <token>`).
28
- * Prefer the environment variable for secrets: command-line flags are visible in process lists.
29
- */
30
- export function buildApiHeaders(headerFlags: string[], env: Record<string, string | undefined>): Record<string, string> {
31
- const headers: Record<string, string> = {};
32
- if (env.CRITICAL_PATH_API_TOKEN) {
33
- headers['Authorization'] = `Bearer ${env.CRITICAL_PATH_API_TOKEN}`;
34
- }
35
- for (const flag of headerFlags) {
36
- const separator = flag.indexOf(':');
37
- if (separator <= 0) {
38
- throw new Error(`Invalid --header "${flag}". Expected "Name: value".`);
39
- }
40
- headers[flag.slice(0, separator).trim()] = flag.slice(separator + 1).trim();
41
- }
42
- return headers;
43
- }
44
-
45
- /** True when credentials would be sent in cleartext to a host other than this machine. */
46
- export function isInsecureRemote(apiUrl: string): boolean {
47
- const url = new URL(apiUrl);
48
- const localHosts = ['localhost', '127.0.0.1', '[::1]'];
49
- return url.protocol === 'http:' && !localHosts.includes(url.hostname) && !url.hostname.endsWith('.localhost');
50
- }
package/src/bin/cli.ts DELETED
@@ -1,75 +0,0 @@
1
- #!/usr/bin/env node
2
- import { CriticalPathEngine, SQLiteStore, InMemoryStore } from '@critical-path/core';
3
- import { CriticalPathClient } from '@critical-path/client';
4
- import { createCriticalPathMcpServer, startStdioServer } from '../server/index.js';
5
- import { parseArgs, buildApiHeaders, isInsecureRemote } from './args.js';
6
-
7
- function showHelp() {
8
- console.log(`
9
- Critical Path MCP Server (Stdio)
10
-
11
- Usage:
12
- npx @critical-path/mcp [options]
13
-
14
- Environment:
15
- CRITICAL_PATH_API_TOKEN Sent as "Authorization: Bearer <token>" in --api mode
16
-
17
- Options:
18
- --db <path> Path to SQLite database file (uses SQLiteStore)
19
- --api <url> Base URL of remote Critical Path server (uses CriticalPathClient)
20
- --header <h> Extra request header for --api, as "Name: value" (repeatable)
21
- --help, -h Display this help message
22
-
23
- Examples:
24
- # Run against local SQLite database
25
- npx @critical-path/mcp --db ./critical-path.db
26
-
27
- # Run against remote Next.js or SvelteKit route handler
28
- npx @critical-path/mcp --api http://localhost:3000/api/critical-path
29
-
30
- # Authenticate against a protected API (token read from the environment)
31
- CRITICAL_PATH_API_TOKEN=secret npx @critical-path/mcp --api https://app.example.com/api/critical-path
32
-
33
- # Run with in-memory store (for testing)
34
- npx @critical-path/mcp
35
- `);
36
- }
37
-
38
- async function main() {
39
- const args = process.argv.slice(2);
40
- const options = parseArgs(args);
41
-
42
- if (options.help) {
43
- showHelp();
44
- process.exit(0);
45
- }
46
-
47
- let server;
48
-
49
- if (options.api) {
50
- const headers = buildApiHeaders(options.headers, process.env);
51
- if (Object.keys(headers).length > 0 && isInsecureRemote(options.api)) {
52
- console.error('[Critical Path MCP] Warning: sending credentials over plain http to a remote host.');
53
- }
54
- const client = new CriticalPathClient({ baseUrl: options.api, headers });
55
- server = createCriticalPathMcpServer({ client, name: 'critical-path-api-mcp' });
56
- console.error(`[Critical Path MCP] Connecting to remote API at ${options.api} over stdio...`);
57
- } else if (options.db) {
58
- const store = new SQLiteStore({ filename: options.db });
59
- const engine = new CriticalPathEngine({ store });
60
- server = createCriticalPathMcpServer({ engine, name: 'critical-path-sqlite-mcp' });
61
- console.error(`[Critical Path MCP] Loaded SQLite database from "${options.db}" over stdio...`);
62
- } else {
63
- const store = new InMemoryStore();
64
- const engine = new CriticalPathEngine({ store });
65
- server = createCriticalPathMcpServer({ engine, name: 'critical-path-inmemory-mcp' });
66
- console.error('[Critical Path MCP] Initialized in-memory store over stdio...');
67
- }
68
-
69
- await startStdioServer(server);
70
- }
71
-
72
- main().catch((err) => {
73
- console.error('[Critical Path MCP] Fatal error:', err);
74
- process.exit(1);
75
- });