@stratta/mcp 0.13.1 → 0.15.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 +47 -28
- package/dist/confirm.d.ts +10 -1
- package/dist/confirm.js +46 -24
- package/dist/errors.js +40 -0
- package/dist/tools/catalog.gen.js +380 -2
- package/dist/tools/dossier.d.ts +136 -0
- package/dist/tools/dossier.js +282 -0
- package/dist/tools/ingest.d.ts +4 -0
- package/dist/tools/ingest.js +12 -3
- package/dist/tools/site.d.ts +46 -0
- package/dist/tools/site.js +121 -1
- package/package.json +1 -1
- package/skills/consult-stratta/SKILL.md +1 -1
package/dist/tools/dossier.js
CHANGED
|
@@ -358,6 +358,276 @@ export const applyTemplate = defineTool({
|
|
|
358
358
|
templateId: args.templateId,
|
|
359
359
|
}),
|
|
360
360
|
});
|
|
361
|
+
/* ------------------------------------------------- questions (0.14.0) */
|
|
362
|
+
//
|
|
363
|
+
// Everything the dossier page can read and do to a question (ADR 36). The
|
|
364
|
+
// reads paginate with `cursor`; the two deletions go through the same
|
|
365
|
+
// confirmation gate as `record_decision` (`confirm.ts`), and `confirmed` is
|
|
366
|
+
// read there, never sent.
|
|
367
|
+
const questionStatus = z.enum(['open', 'decided', 'closed']);
|
|
368
|
+
const cursor = (tool) => z.string().min(1).optional().describe(param(tool, 'cursor'));
|
|
369
|
+
const pageLimit = (tool) => z.number().int().min(1).max(200).optional().describe(param(tool, 'limit'));
|
|
370
|
+
export const listQuestions = defineTool({
|
|
371
|
+
...headOf('list_questions'),
|
|
372
|
+
inputSchema: {
|
|
373
|
+
dossierId: dossierId('list_questions'),
|
|
374
|
+
status: questionStatus
|
|
375
|
+
.optional()
|
|
376
|
+
.describe(param('list_questions', 'status')),
|
|
377
|
+
limit: pageLimit('list_questions'),
|
|
378
|
+
cursor: cursor('list_questions'),
|
|
379
|
+
},
|
|
380
|
+
run: (client, args) => client.action(api.dossiersApi.listQuestions, {
|
|
381
|
+
apiKey: requireApiKey(),
|
|
382
|
+
dossierId: args.dossierId,
|
|
383
|
+
status: args.status,
|
|
384
|
+
limit: args.limit,
|
|
385
|
+
cursor: args.cursor,
|
|
386
|
+
}),
|
|
387
|
+
});
|
|
388
|
+
export const getQuestion = defineTool({
|
|
389
|
+
...headOf('get_question'),
|
|
390
|
+
inputSchema: {
|
|
391
|
+
questionId: questionId('get_question'),
|
|
392
|
+
limit: pageLimit('get_question'),
|
|
393
|
+
cursor: cursor('get_question'),
|
|
394
|
+
},
|
|
395
|
+
run: (client, args) => client.action(api.dossiersApi.getQuestion, {
|
|
396
|
+
apiKey: requireApiKey(),
|
|
397
|
+
questionId: args.questionId,
|
|
398
|
+
limit: args.limit,
|
|
399
|
+
cursor: args.cursor,
|
|
400
|
+
}),
|
|
401
|
+
});
|
|
402
|
+
export const getDossierActivity = defineTool({
|
|
403
|
+
...headOf('get_dossier_activity'),
|
|
404
|
+
inputSchema: {
|
|
405
|
+
dossierId: dossierId('get_dossier_activity'),
|
|
406
|
+
limit: pageLimit('get_dossier_activity'),
|
|
407
|
+
cursor: cursor('get_dossier_activity'),
|
|
408
|
+
},
|
|
409
|
+
run: (client, args) => client.action(api.dossiersApi.getDossierActivity, {
|
|
410
|
+
apiKey: requireApiKey(),
|
|
411
|
+
dossierId: args.dossierId,
|
|
412
|
+
limit: args.limit,
|
|
413
|
+
cursor: args.cursor,
|
|
414
|
+
}),
|
|
415
|
+
});
|
|
416
|
+
export const listExports = defineTool({
|
|
417
|
+
...headOf('list_exports'),
|
|
418
|
+
inputSchema: { dossierId: dossierId('list_exports') },
|
|
419
|
+
run: (client, args) => client.action(api.dossiersApi.listExports, {
|
|
420
|
+
apiKey: requireApiKey(),
|
|
421
|
+
dossierId: args.dossierId,
|
|
422
|
+
}),
|
|
423
|
+
});
|
|
424
|
+
export const updateQuestion = defineTool({
|
|
425
|
+
...headOf('update_question'),
|
|
426
|
+
inputSchema: {
|
|
427
|
+
questionId: questionId('update_question'),
|
|
428
|
+
title: z
|
|
429
|
+
.string()
|
|
430
|
+
.min(1)
|
|
431
|
+
.max(200)
|
|
432
|
+
.optional()
|
|
433
|
+
.describe(param('update_question', 'title')),
|
|
434
|
+
body: z
|
|
435
|
+
.string()
|
|
436
|
+
.max(4000)
|
|
437
|
+
.optional()
|
|
438
|
+
.describe(param('update_question', 'body')),
|
|
439
|
+
assigneeEmail: z
|
|
440
|
+
.email()
|
|
441
|
+
.nullable()
|
|
442
|
+
.optional()
|
|
443
|
+
.describe(param('update_question', 'assigneeEmail')),
|
|
444
|
+
dueAt: z
|
|
445
|
+
.string()
|
|
446
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
447
|
+
.nullable()
|
|
448
|
+
.optional()
|
|
449
|
+
.describe(param('update_question', 'dueAt')),
|
|
450
|
+
},
|
|
451
|
+
run: (client, args) => client.action(api.dossiersApi.updateQuestion, {
|
|
452
|
+
apiKey: requireApiKey(),
|
|
453
|
+
questionId: args.questionId,
|
|
454
|
+
title: args.title,
|
|
455
|
+
body: args.body,
|
|
456
|
+
assigneeEmail: args.assigneeEmail,
|
|
457
|
+
dueAt: args.dueAt,
|
|
458
|
+
}),
|
|
459
|
+
});
|
|
460
|
+
export const addOption = defineTool({
|
|
461
|
+
...headOf('add_option'),
|
|
462
|
+
inputSchema: {
|
|
463
|
+
questionId: questionId('add_option'),
|
|
464
|
+
name: z.string().min(1).max(120).describe(param('add_option', 'name')),
|
|
465
|
+
description: z
|
|
466
|
+
.string()
|
|
467
|
+
.max(2000)
|
|
468
|
+
.optional()
|
|
469
|
+
.describe(param('add_option', 'description')),
|
|
470
|
+
},
|
|
471
|
+
run: (client, args) => client.action(api.dossiersApi.addOption, {
|
|
472
|
+
apiKey: requireApiKey(),
|
|
473
|
+
questionId: args.questionId,
|
|
474
|
+
name: args.name,
|
|
475
|
+
description: args.description,
|
|
476
|
+
}),
|
|
477
|
+
});
|
|
478
|
+
const optionId = (tool) => z.string().min(1).describe(param(tool, 'optionId'));
|
|
479
|
+
export const updateOption = defineTool({
|
|
480
|
+
...headOf('update_option'),
|
|
481
|
+
inputSchema: {
|
|
482
|
+
optionId: optionId('update_option'),
|
|
483
|
+
name: z
|
|
484
|
+
.string()
|
|
485
|
+
.min(1)
|
|
486
|
+
.max(120)
|
|
487
|
+
.optional()
|
|
488
|
+
.describe(param('update_option', 'name')),
|
|
489
|
+
description: z
|
|
490
|
+
.string()
|
|
491
|
+
.max(2000)
|
|
492
|
+
.optional()
|
|
493
|
+
.describe(param('update_option', 'description')),
|
|
494
|
+
retained: z
|
|
495
|
+
.boolean()
|
|
496
|
+
.optional()
|
|
497
|
+
.describe(param('update_option', 'retained')),
|
|
498
|
+
},
|
|
499
|
+
run: (client, args) => client.action(api.dossiersApi.updateOption, {
|
|
500
|
+
apiKey: requireApiKey(),
|
|
501
|
+
optionId: args.optionId,
|
|
502
|
+
name: args.name,
|
|
503
|
+
description: args.description,
|
|
504
|
+
retained: args.retained,
|
|
505
|
+
}),
|
|
506
|
+
});
|
|
507
|
+
export const deleteOption = defineTool({
|
|
508
|
+
...headOf('delete_option'),
|
|
509
|
+
inputSchema: {
|
|
510
|
+
optionId: optionId('delete_option'),
|
|
511
|
+
confirmed: z
|
|
512
|
+
.boolean()
|
|
513
|
+
.optional()
|
|
514
|
+
.describe(param('delete_option', 'confirmed')),
|
|
515
|
+
},
|
|
516
|
+
run: (client, { confirmed: _confirmed, ...args }) => client.action(api.dossiersApi.deleteOption, {
|
|
517
|
+
apiKey: requireApiKey(),
|
|
518
|
+
optionId: args.optionId,
|
|
519
|
+
}),
|
|
520
|
+
});
|
|
521
|
+
export const deleteQuestion = defineTool({
|
|
522
|
+
...headOf('delete_question'),
|
|
523
|
+
inputSchema: {
|
|
524
|
+
questionId: questionId('delete_question'),
|
|
525
|
+
confirmed: z
|
|
526
|
+
.boolean()
|
|
527
|
+
.optional()
|
|
528
|
+
.describe(param('delete_question', 'confirmed')),
|
|
529
|
+
},
|
|
530
|
+
run: (client, { confirmed: _confirmed, ...args }) => client.action(api.dossiersApi.deleteQuestion, {
|
|
531
|
+
apiKey: requireApiKey(),
|
|
532
|
+
questionId: args.questionId,
|
|
533
|
+
}),
|
|
534
|
+
});
|
|
535
|
+
export const addComment = defineTool({
|
|
536
|
+
...headOf('add_comment'),
|
|
537
|
+
inputSchema: {
|
|
538
|
+
dossierId: dossierId('add_comment'),
|
|
539
|
+
body: z.string().min(1).max(4000).describe(param('add_comment', 'body')),
|
|
540
|
+
questionId: questionId('add_comment').optional(),
|
|
541
|
+
entryId: z
|
|
542
|
+
.string()
|
|
543
|
+
.min(1)
|
|
544
|
+
.optional()
|
|
545
|
+
.describe(param('add_comment', 'entryId')),
|
|
546
|
+
},
|
|
547
|
+
run: (client, args) => client.action(api.dossiersApi.addComment, {
|
|
548
|
+
apiKey: requireApiKey(),
|
|
549
|
+
dossierId: args.dossierId,
|
|
550
|
+
body: args.body,
|
|
551
|
+
questionId: args.questionId,
|
|
552
|
+
entryId: args.entryId,
|
|
553
|
+
}),
|
|
554
|
+
});
|
|
555
|
+
export const updateEntry = defineTool({
|
|
556
|
+
...headOf('update_entry'),
|
|
557
|
+
inputSchema: {
|
|
558
|
+
entryId: z.string().min(1).describe(param('update_entry', 'entryId')),
|
|
559
|
+
title: z
|
|
560
|
+
.string()
|
|
561
|
+
.min(1)
|
|
562
|
+
.max(200)
|
|
563
|
+
.optional()
|
|
564
|
+
.describe(param('update_entry', 'title')),
|
|
565
|
+
detail: z
|
|
566
|
+
.string()
|
|
567
|
+
.max(4000)
|
|
568
|
+
.optional()
|
|
569
|
+
.describe(param('update_entry', 'detail')),
|
|
570
|
+
value: z
|
|
571
|
+
.string()
|
|
572
|
+
.max(120)
|
|
573
|
+
.optional()
|
|
574
|
+
.describe(param('update_entry', 'value')),
|
|
575
|
+
confidence: z
|
|
576
|
+
.enum(['established', 'judgement', 'to_confirm'])
|
|
577
|
+
.optional()
|
|
578
|
+
.describe(param('update_entry', 'confidence')),
|
|
579
|
+
normCode: z
|
|
580
|
+
.string()
|
|
581
|
+
.max(40)
|
|
582
|
+
.optional()
|
|
583
|
+
.describe(param('update_entry', 'normCode')),
|
|
584
|
+
sectionPath: z
|
|
585
|
+
.string()
|
|
586
|
+
.max(60)
|
|
587
|
+
.optional()
|
|
588
|
+
.describe(param('update_entry', 'sectionPath')),
|
|
589
|
+
page: z
|
|
590
|
+
.number()
|
|
591
|
+
.int()
|
|
592
|
+
.positive()
|
|
593
|
+
.nullable()
|
|
594
|
+
.optional()
|
|
595
|
+
.describe(param('update_entry', 'page')),
|
|
596
|
+
normEdition: z
|
|
597
|
+
.string()
|
|
598
|
+
.max(40)
|
|
599
|
+
.optional()
|
|
600
|
+
.describe(param('update_entry', 'normEdition')),
|
|
601
|
+
},
|
|
602
|
+
run: (client, args) => client.action(api.dossiersApi.updateEntry, {
|
|
603
|
+
apiKey: requireApiKey(),
|
|
604
|
+
...args,
|
|
605
|
+
entryId: args.entryId,
|
|
606
|
+
}),
|
|
607
|
+
});
|
|
608
|
+
export const attachEntry = defineTool({
|
|
609
|
+
...headOf('attach_entry'),
|
|
610
|
+
inputSchema: {
|
|
611
|
+
entryId: z.string().min(1).describe(param('attach_entry', 'entryId')),
|
|
612
|
+
questionId: z
|
|
613
|
+
.string()
|
|
614
|
+
.min(1)
|
|
615
|
+
.nullable()
|
|
616
|
+
.describe(param('attach_entry', 'questionId')),
|
|
617
|
+
optionId: z
|
|
618
|
+
.string()
|
|
619
|
+
.min(1)
|
|
620
|
+
.nullable()
|
|
621
|
+
.optional()
|
|
622
|
+
.describe(param('attach_entry', 'optionId')),
|
|
623
|
+
},
|
|
624
|
+
run: (client, args) => client.action(api.dossiersApi.attachEntry, {
|
|
625
|
+
apiKey: requireApiKey(),
|
|
626
|
+
entryId: args.entryId,
|
|
627
|
+
questionId: args.questionId,
|
|
628
|
+
optionId: args.optionId,
|
|
629
|
+
}),
|
|
630
|
+
});
|
|
361
631
|
export const dossierTools = [
|
|
362
632
|
listDossiers,
|
|
363
633
|
openDossier,
|
|
@@ -372,4 +642,16 @@ export const dossierTools = [
|
|
|
372
642
|
addAttachment,
|
|
373
643
|
listTemplates,
|
|
374
644
|
applyTemplate,
|
|
645
|
+
listQuestions,
|
|
646
|
+
getQuestion,
|
|
647
|
+
getDossierActivity,
|
|
648
|
+
listExports,
|
|
649
|
+
updateQuestion,
|
|
650
|
+
addOption,
|
|
651
|
+
updateOption,
|
|
652
|
+
deleteOption,
|
|
653
|
+
deleteQuestion,
|
|
654
|
+
addComment,
|
|
655
|
+
updateEntry,
|
|
656
|
+
attachEntry,
|
|
375
657
|
];
|
package/dist/tools/ingest.d.ts
CHANGED
|
@@ -77,6 +77,7 @@ export declare const ingestPublish: import("./define.js").ToolDef<{
|
|
|
77
77
|
}>;
|
|
78
78
|
export declare const ingestDelete: import("./define.js").ToolDef<{
|
|
79
79
|
documentId: z.ZodString;
|
|
80
|
+
confirmed: z.ZodOptional<z.ZodBoolean>;
|
|
80
81
|
}>;
|
|
81
82
|
export declare const ingestTools: (import("./define.js").ToolDef<{
|
|
82
83
|
code: z.ZodString;
|
|
@@ -145,4 +146,7 @@ export declare const ingestTools: (import("./define.js").ToolDef<{
|
|
|
145
146
|
}> | import("./define.js").ToolDef<{
|
|
146
147
|
documentId: z.ZodString;
|
|
147
148
|
force: z.ZodOptional<z.ZodBoolean>;
|
|
149
|
+
}> | import("./define.js").ToolDef<{
|
|
150
|
+
documentId: z.ZodString;
|
|
151
|
+
confirmed: z.ZodOptional<z.ZodBoolean>;
|
|
148
152
|
}>)[];
|
package/dist/tools/ingest.js
CHANGED
|
@@ -8,8 +8,10 @@ import { defineTool } from './define.js';
|
|
|
8
8
|
* its Stratta workspace, from the user's own agent. Every call is
|
|
9
9
|
* authenticated by the user's API key and scoped server-side to their
|
|
10
10
|
* organisation (see convex/ingestionApi.ts). Driven by the `ingest-norm`
|
|
11
|
-
* skill.
|
|
12
|
-
*
|
|
11
|
+
* skill. ⚠️ They are served on the remote connector too since 2026-09-05
|
|
12
|
+
* (`convex/mcpIngestRegistrations.ts`): the pre-pass still reads a PDF on the
|
|
13
|
+
* caller's disk, which rules out a browser client but not Claude Code, Codex,
|
|
14
|
+
* Cursor or Gemini CLI.
|
|
13
15
|
*
|
|
14
16
|
* Names, descriptions and annotations come from the generated catalogue. The
|
|
15
17
|
* Zod shapes below are enforced by the SDK before a handler runs, so a bad
|
|
@@ -232,7 +234,14 @@ export const ingestPublish = defineTool({
|
|
|
232
234
|
});
|
|
233
235
|
export const ingestDelete = defineTool({
|
|
234
236
|
...headOf('ingest_delete'),
|
|
235
|
-
inputSchema: {
|
|
237
|
+
inputSchema: {
|
|
238
|
+
documentId: documentId('ingest_delete'),
|
|
239
|
+
// Read by the confirmation gate in `confirm.ts`, never sent on.
|
|
240
|
+
confirmed: z
|
|
241
|
+
.boolean()
|
|
242
|
+
.optional()
|
|
243
|
+
.describe(param('ingest_delete', 'confirmed')),
|
|
244
|
+
},
|
|
236
245
|
run: async (client, args) => {
|
|
237
246
|
await client.action(api.ingestionApi.deleteDocument, {
|
|
238
247
|
apiKey: requireApiKey(),
|
package/dist/tools/site.d.ts
CHANGED
|
@@ -30,6 +30,41 @@ export declare const getBoreholes: import("./define.js").ToolDef<{
|
|
|
30
30
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
31
31
|
withStrataOnly: z.ZodOptional<z.ZodBoolean>;
|
|
32
32
|
}>;
|
|
33
|
+
/**
|
|
34
|
+
* The Site tab of a dossier, read by an agent (0.14.0, ADR 36).
|
|
35
|
+
*
|
|
36
|
+
* `get_site_context` is the summary shaped for an answer; these are the
|
|
37
|
+
* record: every fact with its key and notice, the section along the axis,
|
|
38
|
+
* the map areas, the piezometric contours, the photos, the neighbouring
|
|
39
|
+
* projects, and the list of sheets. Geometry is left out unless asked for:
|
|
40
|
+
* a water protection sector runs to hundreds of vertices, and an agent
|
|
41
|
+
* reads distances, not polygons.
|
|
42
|
+
*/
|
|
43
|
+
export declare const listSites: import("./define.js").ToolDef<{
|
|
44
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
45
|
+
}>;
|
|
46
|
+
export declare const getSite: import("./define.js").ToolDef<{
|
|
47
|
+
siteId: z.ZodString;
|
|
48
|
+
}>;
|
|
49
|
+
export declare const getSiteSection: import("./define.js").ToolDef<{
|
|
50
|
+
siteId: z.ZodString;
|
|
51
|
+
maxPoints: z.ZodOptional<z.ZodNumber>;
|
|
52
|
+
}>;
|
|
53
|
+
export declare const listSiteOverlays: import("./define.js").ToolDef<{
|
|
54
|
+
siteId: z.ZodString;
|
|
55
|
+
includeGeometry: z.ZodOptional<z.ZodBoolean>;
|
|
56
|
+
}>;
|
|
57
|
+
export declare const getGroundwaterContours: import("./define.js").ToolDef<{
|
|
58
|
+
siteId: z.ZodString;
|
|
59
|
+
includeGeometry: z.ZodOptional<z.ZodBoolean>;
|
|
60
|
+
}>;
|
|
61
|
+
export declare const listSitePhotos: import("./define.js").ToolDef<{
|
|
62
|
+
siteId: z.ZodString;
|
|
63
|
+
}>;
|
|
64
|
+
export declare const listSiteNeighbours: import("./define.js").ToolDef<{
|
|
65
|
+
siteId: z.ZodString;
|
|
66
|
+
radius: z.ZodOptional<z.ZodNumber>;
|
|
67
|
+
}>;
|
|
33
68
|
export declare const siteTools: (import("./define.js").ToolDef<{
|
|
34
69
|
dossierId: z.ZodString;
|
|
35
70
|
address: z.ZodString;
|
|
@@ -50,4 +85,15 @@ export declare const siteTools: (import("./define.js").ToolDef<{
|
|
|
50
85
|
*/
|
|
51
86
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
52
87
|
withStrataOnly: z.ZodOptional<z.ZodBoolean>;
|
|
88
|
+
}> | import("./define.js").ToolDef<{
|
|
89
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
90
|
+
}> | import("./define.js").ToolDef<{
|
|
91
|
+
siteId: z.ZodString;
|
|
92
|
+
maxPoints: z.ZodOptional<z.ZodNumber>;
|
|
93
|
+
}> | import("./define.js").ToolDef<{
|
|
94
|
+
siteId: z.ZodString;
|
|
95
|
+
includeGeometry: z.ZodOptional<z.ZodBoolean>;
|
|
96
|
+
}> | import("./define.js").ToolDef<{
|
|
97
|
+
siteId: z.ZodString;
|
|
98
|
+
radius: z.ZodOptional<z.ZodNumber>;
|
|
53
99
|
}>)[];
|
package/dist/tools/site.js
CHANGED
|
@@ -97,4 +97,124 @@ export const getBoreholes = defineTool({
|
|
|
97
97
|
withStrataOnly: args.withStrataOnly,
|
|
98
98
|
}),
|
|
99
99
|
});
|
|
100
|
-
|
|
100
|
+
const siteId = (tool) => z.string().min(1).describe(param(tool, 'siteId'));
|
|
101
|
+
/**
|
|
102
|
+
* The Site tab of a dossier, read by an agent (0.14.0, ADR 36).
|
|
103
|
+
*
|
|
104
|
+
* `get_site_context` is the summary shaped for an answer; these are the
|
|
105
|
+
* record: every fact with its key and notice, the section along the axis,
|
|
106
|
+
* the map areas, the piezometric contours, the photos, the neighbouring
|
|
107
|
+
* projects, and the list of sheets. Geometry is left out unless asked for:
|
|
108
|
+
* a water protection sector runs to hundreds of vertices, and an agent
|
|
109
|
+
* reads distances, not polygons.
|
|
110
|
+
*/
|
|
111
|
+
export const listSites = defineTool({
|
|
112
|
+
...headOf('list_sites'),
|
|
113
|
+
inputSchema: {
|
|
114
|
+
limit: z
|
|
115
|
+
.number()
|
|
116
|
+
.int()
|
|
117
|
+
.min(1)
|
|
118
|
+
.max(200)
|
|
119
|
+
.optional()
|
|
120
|
+
.describe(param('list_sites', 'limit')),
|
|
121
|
+
},
|
|
122
|
+
run: (client, args) => client.action(api.sitesApi.listSites, {
|
|
123
|
+
apiKey: requireApiKey(),
|
|
124
|
+
limit: args.limit,
|
|
125
|
+
}),
|
|
126
|
+
});
|
|
127
|
+
export const getSite = defineTool({
|
|
128
|
+
...headOf('get_site'),
|
|
129
|
+
inputSchema: { siteId: siteId('get_site') },
|
|
130
|
+
run: (client, args) => client.action(api.sitesApi.getSite, {
|
|
131
|
+
apiKey: requireApiKey(),
|
|
132
|
+
siteId: args.siteId,
|
|
133
|
+
}),
|
|
134
|
+
});
|
|
135
|
+
export const getSiteSection = defineTool({
|
|
136
|
+
...headOf('get_site_section'),
|
|
137
|
+
inputSchema: {
|
|
138
|
+
siteId: siteId('get_site_section'),
|
|
139
|
+
maxPoints: z
|
|
140
|
+
.number()
|
|
141
|
+
.int()
|
|
142
|
+
.min(2)
|
|
143
|
+
.max(200)
|
|
144
|
+
.optional()
|
|
145
|
+
.describe(param('get_site_section', 'maxPoints')),
|
|
146
|
+
},
|
|
147
|
+
run: (client, args) => client.action(api.sitesApi.getSiteSection, {
|
|
148
|
+
apiKey: requireApiKey(),
|
|
149
|
+
siteId: args.siteId,
|
|
150
|
+
maxPoints: args.maxPoints,
|
|
151
|
+
}),
|
|
152
|
+
});
|
|
153
|
+
export const listSiteOverlays = defineTool({
|
|
154
|
+
...headOf('list_site_overlays'),
|
|
155
|
+
inputSchema: {
|
|
156
|
+
siteId: siteId('list_site_overlays'),
|
|
157
|
+
includeGeometry: z
|
|
158
|
+
.boolean()
|
|
159
|
+
.optional()
|
|
160
|
+
.describe(param('list_site_overlays', 'includeGeometry')),
|
|
161
|
+
},
|
|
162
|
+
run: (client, args) => client.action(api.sitesApi.listSiteOverlays, {
|
|
163
|
+
apiKey: requireApiKey(),
|
|
164
|
+
siteId: args.siteId,
|
|
165
|
+
includeGeometry: args.includeGeometry,
|
|
166
|
+
}),
|
|
167
|
+
});
|
|
168
|
+
export const getGroundwaterContours = defineTool({
|
|
169
|
+
...headOf('get_groundwater_contours'),
|
|
170
|
+
inputSchema: {
|
|
171
|
+
siteId: siteId('get_groundwater_contours'),
|
|
172
|
+
includeGeometry: z
|
|
173
|
+
.boolean()
|
|
174
|
+
.optional()
|
|
175
|
+
.describe(param('get_groundwater_contours', 'includeGeometry')),
|
|
176
|
+
},
|
|
177
|
+
run: (client, args) => client.action(api.sitesApi.getGroundwaterContours, {
|
|
178
|
+
apiKey: requireApiKey(),
|
|
179
|
+
siteId: args.siteId,
|
|
180
|
+
includeGeometry: args.includeGeometry,
|
|
181
|
+
}),
|
|
182
|
+
});
|
|
183
|
+
export const listSitePhotos = defineTool({
|
|
184
|
+
...headOf('list_site_photos'),
|
|
185
|
+
inputSchema: { siteId: siteId('list_site_photos') },
|
|
186
|
+
run: (client, args) => client.action(api.sitesApi.listSitePhotos, {
|
|
187
|
+
apiKey: requireApiKey(),
|
|
188
|
+
siteId: args.siteId,
|
|
189
|
+
}),
|
|
190
|
+
});
|
|
191
|
+
export const listSiteNeighbours = defineTool({
|
|
192
|
+
...headOf('list_site_neighbours'),
|
|
193
|
+
inputSchema: {
|
|
194
|
+
siteId: siteId('list_site_neighbours'),
|
|
195
|
+
radius: z
|
|
196
|
+
.number()
|
|
197
|
+
.int()
|
|
198
|
+
.min(50)
|
|
199
|
+
.max(5000)
|
|
200
|
+
.optional()
|
|
201
|
+
.describe(param('list_site_neighbours', 'radius')),
|
|
202
|
+
},
|
|
203
|
+
run: (client, args) => client.action(api.sitesApi.listSiteNeighbours, {
|
|
204
|
+
apiKey: requireApiKey(),
|
|
205
|
+
siteId: args.siteId,
|
|
206
|
+
radius: args.radius,
|
|
207
|
+
}),
|
|
208
|
+
});
|
|
209
|
+
export const siteTools = [
|
|
210
|
+
scanSite,
|
|
211
|
+
getSiteContext,
|
|
212
|
+
getBoreholes,
|
|
213
|
+
listSites,
|
|
214
|
+
getSite,
|
|
215
|
+
getSiteSection,
|
|
216
|
+
listSiteOverlays,
|
|
217
|
+
getGroundwaterContours,
|
|
218
|
+
listSitePhotos,
|
|
219
|
+
listSiteNeighbours,
|
|
220
|
+
];
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratta/mcp",
|
|
3
3
|
"mcpName": "ch.stratta/mcp",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.15.0",
|
|
5
5
|
"description": "MCP server exposing the engineering norms your firm is licensed for (SIA / Eurocodes) to any MCP client, via Stratta TreeRAG.",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"author": "SmartFlow <hello@stratta.ch>",
|
|
@@ -46,7 +46,7 @@ A conversation disappears, a project lasts months. The dossier is what remains:
|
|
|
46
46
|
|
|
47
47
|
**Open one** (`open_dossier`) when the user names a project, a structure, a site or a mandate, when a value is retained for a design rather than looked up, when a hypothesis is set, when a site observation is reported, or when a question is left open. Do not open a dossier for a one-off lookup with no project behind it.
|
|
48
48
|
|
|
49
|
-
**Reload it first** (`list_dossiers`, `load_dossier`) BEFORE answering, as soon as the user returns to a project already named ("pick up dossier X", "where were we on Y"): reloading is what stops a decision already taken from being taken again. Read its entries and its open questions before answering anything about that project.
|
|
49
|
+
**Reload it first** (`list_dossiers`, `load_dossier`) BEFORE answering, as soon as the user returns to a project already named ("pick up dossier X", "where were we on Y"): reloading is what stops a decision already taken from being taken again. Read its entries and its open questions before answering anything about that project. To work on one question, `get_question` reads it in full (options, evidence with every citation field, comments); `attach_entry` files what `load_dossier` lists as unclassified. A question is edited with `update_question`, never deleted unless the user says so.
|
|
50
50
|
|
|
51
51
|
**Read its attachments.** A dossier carries the project's own documents (site reports, borehole logs, meeting minutes): `list_attachments`, then `read_attachment` on what bears on the question, or `search_in_dossier` when the dossier holds many. A fact from a piece is evidence like a clause: cite it as [name, p. N] and file it with `attachmentId` and `attachmentPage`.
|
|
52
52
|
|