@stratta/mcp 1.21.0 → 1.22.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 CHANGED
@@ -49,8 +49,8 @@ This package is what you want when:
49
49
 
50
50
  ## Lighter setup: `--simple`
51
51
 
52
- By default the server announces all 59 tools (about 67,000 characters of
53
- schemas). `--simple` announces only the 10 norm-reading tools (about 11,000),
52
+ By default the server announces all 60 tools (about 67,000 characters of
53
+ schemas). `--simple` announces only the 11 norm-reading tools (about 11,000),
54
54
  which is enough for an agent that just reads norms:
55
55
 
56
56
  ```bash
@@ -193,23 +193,24 @@ named `E2E dossier <timestamp>` and does not delete it.
193
193
  ## Tools exposed
194
194
 
195
195
  62 tools, generated from one catalogue shared with the remote connector. This
196
- package announces 59 of them; the remote connector serves 61: everything minus
197
- `add_attachment`, plus the three tools a host calls for the person, listed last.
196
+ package announces 60 of them; the remote connector serves 61: everything minus
197
+ `add_attachment`, plus the two tools a host calls for the person, listed last.
198
198
 
199
199
  **Read** (10 tools — query the norms of your workspace):
200
200
 
201
- | Tool | Purpose |
202
- | ----------------- | ------------------------------------------------------------------------------------------------ |
203
- | `get_methodology` | Behavioural contract: persona, workflow, meta-routing hints, answer rules. Call first. |
204
- | `whoami` | Which organisation, role and plan this connection reads as, and how many norms it sees. |
205
- | `list_norms` | List the norms of your workspace, filtered by `query` (code or title words), bounded by `limit`. |
206
- | `get_toc` | Hierarchical TOC for a norm (default `maxDepth=1` = chapters). |
207
- | `get_subtree` | Drill into a chapter/section subtree (`path` + `maxDepth`). |
208
- | `get_section` | Full enriched content of a section (formulas, tables, figures, cross-refs). |
209
- | `search_in_norm` | Keyword search inside a norm. |
210
- | `search_corpus` | Keyword search across every norm of the workspace, grouped by norm. |
211
- | `get_figure` | Retrieve a figure inline (base64 ImageContent). |
212
- | `get_cross_refs` | Outgoing cross-refs from a section to other norms. |
201
+ | Tool | Purpose |
202
+ | ----------------- | ------------------------------------------------------------------------------------------------------------------- |
203
+ | `get_methodology` | Behavioural contract: persona, workflow, meta-routing hints, answer rules. Call first. |
204
+ | `whoami` | Which organisation, role and plan this connection reads as, and how many norms it sees. |
205
+ | `list_norms` | List the norms of your workspace, filtered by `query` (code or title words), bounded by `limit`. |
206
+ | `get_toc` | Hierarchical TOC for a norm (default `maxDepth=1` = chapters). |
207
+ | `get_subtree` | Drill into a chapter/section subtree (`path` + `maxDepth`). |
208
+ | `get_section` | Full enriched content of a section (formulas, tables, figures, cross-refs). |
209
+ | `search_in_norm` | Keyword search inside a norm. |
210
+ | `search_corpus` | Keyword search across every norm of the workspace, grouped by norm. |
211
+ | `get_figure` | Retrieve a figure inline (base64 ImageContent). |
212
+ | `get_cross_refs` | Outgoing cross-refs from a section to other norms. |
213
+ | `verify_citation` | Check that a sentence is printed word for word in a clause before quoting it; returns the passage and the citation. |
213
214
 
214
215
  **Site** (10 tools — what public Swiss registers know about a plot, and the site sheet as the app shows it):
215
216
 
@@ -293,13 +294,12 @@ too, and its file is the layout the Word export is rendered into.
293
294
  | `ingest_publish` | Score the document and flip it to published; refuses below 30/100 unless forced. |
294
295
  | `ingest_delete` | Delete a document and all its children. |
295
296
 
296
- **Remote only** (3 tools, served by `https://stratta.ch/mcp` and not by this package, which draws no interface):
297
+ **Remote only** (2 tools, served by `https://stratta.ch/mcp` and not by this package, which draws no interface):
297
298
 
298
- | Tool | Purpose |
299
- | ------------------ | ------------------------------------------------------------------------------------------------------------ |
300
- | `show_citations` | Show the clauses an answer cites as cards (an MCP App), each quote checked word for word against the clause. |
301
- | `open_norm_reader` | The norm reader, opened by the person from the host's side panel or sidebar; hidden from the model. |
302
- | `get_profile` | An opaque id and the organization of the connection, so a host tells two connected accounts apart. |
299
+ | Tool | Purpose |
300
+ | ---------------- | ------------------------------------------------------------------------------------------------------------ |
301
+ | `show_citations` | Show the clauses an answer cites as cards (an MCP App), each quote checked word for word against the clause. |
302
+ | `get_profile` | An opaque id and the organization of the connection, so a host tells two connected accounts apart. |
303
303
 
304
304
  ## How agents should use it
305
305
 
@@ -178,9 +178,9 @@ export const CATALOG = [
178
178
  }
179
179
  },
180
180
  {
181
- "name": "get_figure",
182
- "title": "Figure",
183
- "description": "Return one figure of a norm as an image: diagrams, charts, standard cross-sections. Call it when the figure carries the rule and describing it in words would lose the content. The figure identifier comes from the figures array of get_section.",
181
+ "name": "verify_citation",
182
+ "title": "Verify a quote",
183
+ "description": "Use this before quoting a clause word for word: checks that the sentence is printed in the clause, whatever its case, accents and line breaks. Returns verified, the passage as the norm prints it and the citation to write after it. When the sentence is not in the clause, verified is false and passage is the closest sentence of the clause, to quote from instead; a changed number makes a quote fail.",
184
184
  "annotations": {
185
185
  "readOnlyHint": true,
186
186
  "destructiveHint": false,
@@ -194,13 +194,14 @@ export const CATALOG = [
194
194
  "params": {
195
195
  "code": "Norm code exactly as list_norms returns it, e.g. \"SIA 261\", \"EN 1997-1\", \"CO\", \"IFRS 15\".",
196
196
  "edition": "Edition of the norm when the organization holds several (\"2013\", \"2020\"). Default: the most recent published edition; list_norms names them.",
197
- "figureId": "Figure identifier from the figures array of get_section."
197
+ "path": "Section path as it appears in the table of contents, e.g. \"4.2.1\" or \"Annexe A\".",
198
+ "quote": "The sentence as it will be quoted, at least 8 characters and one sentence or two at most."
198
199
  }
199
200
  },
200
201
  {
201
- "name": "show_citations",
202
- "title": "Show cited clauses",
203
- "description": "Use this when an answer rests on clauses read with get_section and the person should be able to check them: shows those clauses as cards they can open against the norm, once per answer, in the order they were cited. It reads nothing new and does not replace get_section; only clauses actually read belong in it.",
202
+ "name": "get_figure",
203
+ "title": "Figure",
204
+ "description": "Return one figure of a norm as an image: diagrams, charts, standard cross-sections. Call it when the figure carries the rule and describing it in words would lose the content. The figure identifier comes from the figures array of get_section.",
204
205
  "annotations": {
205
206
  "readOnlyHint": true,
206
207
  "destructiveHint": false,
@@ -208,16 +209,19 @@ export const CATALOG = [
208
209
  "openWorldHint": false
209
210
  },
210
211
  "transports": [
212
+ "stdio",
211
213
  "remote"
212
214
  ],
213
215
  "params": {
214
- "citations": "The cited clauses, one to eight: code and path as get_section took them, the edition when the norm has several, and optionally the exact sentence quoted from the clause."
216
+ "code": "Norm code exactly as list_norms returns it, e.g. \"SIA 261\", \"EN 1997-1\", \"CO\", \"IFRS 15\".",
217
+ "edition": "Edition of the norm when the organization holds several (\"2013\", \"2020\"). Default: the most recent published edition; list_norms names them.",
218
+ "figureId": "Figure identifier from the figures array of get_section."
215
219
  }
216
220
  },
217
221
  {
218
- "name": "open_norm_reader",
219
- "title": "Norm reader",
220
- "description": "Open the norm reader: the norms of the signed-in organization, each with its table of contents and its clauses, browsed by the person. Opened by the person from the side panel or the sidebar, never by the model.",
222
+ "name": "show_citations",
223
+ "title": "Show cited clauses",
224
+ "description": "Use this when an answer rests on clauses read with get_section and the person should be able to check them: shows those clauses as cards they can open against the norm, once per answer, in the order they were cited. It reads nothing new and does not replace get_section; only clauses actually read belong in it.",
221
225
  "annotations": {
222
226
  "readOnlyHint": true,
223
227
  "destructiveHint": false,
@@ -227,7 +231,9 @@ export const CATALOG = [
227
231
  "transports": [
228
232
  "remote"
229
233
  ],
230
- "params": {}
234
+ "params": {
235
+ "citations": "The cited clauses, one to eight: code and path as get_section took them, the edition when the norm has several, and optionally the exact sentence quoted from the clause."
236
+ }
231
237
  },
232
238
  {
233
239
  "name": "get_profile",
@@ -44,6 +44,12 @@ export declare const getFigure: import("./define.js").ToolDef<{
44
44
  edition: z.ZodOptional<z.ZodString>;
45
45
  figureId: z.ZodString;
46
46
  }>;
47
+ export declare const verifyCitation: import("./define.js").ToolDef<{
48
+ code: z.ZodString;
49
+ edition: z.ZodOptional<z.ZodString>;
50
+ path: z.ZodString;
51
+ quote: z.ZodString;
52
+ }>;
47
53
  export declare const readTools: (import("./define.js").ToolDef<{}> | import("./define.js").ToolDef<{
48
54
  query: z.ZodOptional<z.ZodString>;
49
55
  limit: z.ZodOptional<z.ZodNumber>;
@@ -79,4 +85,9 @@ export declare const readTools: (import("./define.js").ToolDef<{}> | import("./d
79
85
  code: z.ZodString;
80
86
  edition: z.ZodOptional<z.ZodString>;
81
87
  figureId: z.ZodString;
88
+ }> | import("./define.js").ToolDef<{
89
+ code: z.ZodString;
90
+ edition: z.ZodOptional<z.ZodString>;
91
+ path: z.ZodString;
92
+ quote: z.ZodString;
82
93
  }>)[];
@@ -327,6 +327,22 @@ export const getFigure = defineTool({
327
327
  };
328
328
  },
329
329
  });
330
+ export const verifyCitation = defineTool({
331
+ ...headOf('verify_citation'),
332
+ inputSchema: {
333
+ code: code('verify_citation'),
334
+ edition: edition('verify_citation'),
335
+ path: path('verify_citation'),
336
+ quote: z.string().min(8).describe(param('verify_citation', 'quote')),
337
+ },
338
+ run: (client, args) => client.action(api._mcp.verifyCitation, {
339
+ apiKey: requireApiKey(),
340
+ code: args.code,
341
+ edition: args.edition,
342
+ path: args.path,
343
+ quote: args.quote,
344
+ }),
345
+ });
330
346
  export const readTools = [
331
347
  getMethodology,
332
348
  whoami,
@@ -337,5 +353,6 @@ export const readTools = [
337
353
  searchInNorm,
338
354
  searchCorpus,
339
355
  getCrossRefs,
356
+ verifyCitation,
340
357
  getFigure,
341
358
  ];
@@ -22,10 +22,10 @@ export const TOOLSET_OF = {
22
22
  search_in_norm: 'norms',
23
23
  search_corpus: 'norms',
24
24
  get_cross_refs: 'norms',
25
+ verify_citation: 'norms',
25
26
  get_figure: 'norms',
26
27
  // Shown to the person rather than read by the model (ADR 59): remote only.
27
28
  show_citations: 'norms',
28
- open_norm_reader: 'norms',
29
29
  get_profile: 'norms',
30
30
  list_dossiers: 'dossiers',
31
31
  open_dossier: 'dossiers',
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stratta/mcp",
3
3
  "mcpName": "ch.stratta/mcp",
4
- "version": "1.21.0",
4
+ "version": "1.22.0",
5
5
  "description": "MCP server exposing your organization’s norms and reference documents (standards, laws, regulations) to any MCP client, with exact citations, via Stratta TreeRAG.",
6
6
  "license": "UNLICENSED",
7
7
  "author": "SmartFlow <hello@stratta.ch>",
@@ -27,6 +27,7 @@ When the question names a norm absent from the corpus but a norm you hold refers
27
27
  ## Answer contract
28
28
 
29
29
  - Every technical statement rests on a section you read in this conversation and cites it as `[CODE § path, p. N]`, for example `[SIA 267 § 9.5.2.1, p. 63]`. A value with no clause is not an answer.
30
+ - A sentence quoted word for word is checked with `verify_citation` before it is written; when it is refused, quote the passage it returns.
30
31
  - A calculation shows its inputs, each with its citation, its formula in LaTeX (`$$...$$`) with every symbol defined and its unit (kN, MPa, CHF, %).
31
32
  - Before answering, check: each value has its clause; each clause was read, not remembered from a summary; the resolvable references were followed; what the corpus does not cover is named, with the norm or clause where it is likely to be found.
32
33
  - When several norms are cited, group by norm under headings: principle, then method, then conditions of use.