@opencraw/mcp 0.1.45 → 0.1.48
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 +28 -1
- package/dist/diff-tool/diff-tool.handler.d.ts +42 -0
- package/dist/diff-tool/index.d.ts +3 -0
- package/dist/docs-tool/docs-folder.repository.d.ts +24 -0
- package/dist/docs-tool/docs-root.client.d.ts +8 -0
- package/dist/docs-tool/docs-tool.handler.d.ts +21 -0
- package/dist/docs-tool/docs-topics.algorithm.d.ts +39 -0
- package/dist/docs-tool/index.d.ts +3 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.esm.js +517 -1
- package/dist/list-tool/index.d.ts +3 -0
- package/dist/list-tool/list-recipes-tool.handler.d.ts +32 -0
- package/dist/main.d.ts +7 -0
- package/dist/probe-tool/index.d.ts +2 -0
- package/dist/probe-tool/probe-tool.handler.d.ts +27 -0
- package/dist/recipe-source/index.d.ts +3 -0
- package/dist/recipe-source/recipe-source.mapper.d.ts +21 -0
- package/dist/run-tool/index.d.ts +3 -0
- package/dist/run-tool/run-tool.handler.d.ts +51 -0
- package/dist/server/create-server.use-case.d.ts +11 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/src/docs-tool/docs-folder.repository.d.ts +24 -0
- package/dist/src/docs-tool/docs-root.client.d.ts +8 -0
- package/dist/src/docs-tool/docs-tool.handler.d.ts +21 -0
- package/dist/src/docs-tool/docs-topics.algorithm.d.ts +39 -0
- package/dist/src/docs-tool/index.d.ts +3 -0
- package/dist/src/server/create-server.use-case.d.ts +1 -1
- package/dist/src/studio-tool/index.d.ts +2 -0
- package/dist/src/studio-tool/studio-command.client.d.ts +11 -0
- package/dist/src/studio-tool/studio-instance.repository.d.ts +22 -0
- package/dist/src/studio-tool/studio-tools.handler.d.ts +68 -0
- package/dist/studio-tool/index.d.ts +2 -0
- package/dist/studio-tool/studio-command.client.d.ts +11 -0
- package/dist/studio-tool/studio-instance.repository.d.ts +22 -0
- package/dist/studio-tool/studio-tools.handler.d.ts +68 -0
- package/dist/validate-tool/index.d.ts +3 -0
- package/dist/validate-tool/validate-tool.handler.d.ts +31 -0
- package/docs/how-it-works/01-recipes.md +698 -0
- package/docs/how-it-works/02-page-steps.md +672 -0
- package/docs/how-it-works/03-data-steps.md +813 -0
- package/docs/how-it-works/04-flow-steps.md +738 -0
- package/docs/how-it-works/05-templates-and-scope.md +428 -0
- package/docs/how-it-works/06-documents.md +1413 -0
- package/docs/how-it-works/07-mapping-and-transforms.md +699 -0
- package/docs/how-it-works/08-policies.md +405 -0
- package/docs/how-it-works/09-running.md +804 -0
- package/docs/how-it-works/README.md +225 -0
- package/docs/recipes/README.md +22 -0
- package/docs/recipes/access.md +440 -0
- package/docs/recipes/authoring.md +1503 -0
- package/docs/recipes/azure-durable.md +180 -0
- package/docs/recipes/captcha.md +204 -0
- package/docs/recipes/movies-example.md +12 -0
- package/docs/recipes/programmatic-authoring.md +101 -0
- package/docs/recipes/quick-guide.md +157 -0
- package/docs/recipes/vehicles-example.md +9 -0
- package/docs/recipes/worker-mode.md +221 -0
- package/docs/studio/manual.md +314 -0
- package/docs/studio/pdf-agreements.md +150 -0
- package/package.json +29 -4
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Tutorial: one recipe for two PDFs of one layout
|
|
2
|
+
|
|
3
|
+
Two service agreements have the same fields and do not look alike: one is a single column with `DETAILS`,
|
|
4
|
+
`PRICE` and `TERMS` in capitals, the other has two columns, `Details`, `Price` and `Terms`, a different
|
|
5
|
+
header and footer, and a longer description. This tutorial builds **one** recipe in the Studio from the first
|
|
6
|
+
and shows it reading the second.
|
|
7
|
+
|
|
8
|
+
- **Video** (about 3 minutes, narrated): [pdf-agreements.mp4](../assets/studio/pdf-agreements/pdf-agreements.mp4)
|
|
9
|
+
- **The finished recipe**: [examples/pdf-agreements](../../examples/pdf-agreements)
|
|
10
|
+
- **The documents**: [agreement.pdf](../../examples/pdf-agreements/agreement.pdf) and
|
|
11
|
+
[agreement-two-columns.pdf](../../examples/pdf-agreements/agreement-two-columns.pdf)
|
|
12
|
+
|
|
13
|
+
The pictures and the video are produced by [capture/pdf-agreements.mjs](./capture/pdf-agreements.mjs), which
|
|
14
|
+
drives the Studio the way these steps do; run it again after a change to the Studio and they follow.
|
|
15
|
+
|
|
16
|
+
## The idea
|
|
17
|
+
|
|
18
|
+
A PDF has no structure of its own: the engine only knows lines of text at positions. A recipe that says "the
|
|
19
|
+
text in this box" breaks as soon as a description is longer, because everything under it moves. So the recipe
|
|
20
|
+
is anchored on what the two documents **do** share: a label before a value, a heading above a block of text,
|
|
21
|
+
a header row above a table.
|
|
22
|
+
|
|
23
|
+
| Field | What it is in both documents | What the recipe anchors on |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| reference, effective date, status | `Label: value` | the label |
|
|
26
|
+
| details | the text between the `Details` and `Price` headings | the two headings |
|
|
27
|
+
| terms | everything under `Terms`, over a page break | the heading |
|
|
28
|
+
| price tiers | a table | its header row, until the next heading |
|
|
29
|
+
|
|
30
|
+
## 1. Open the Studio and load the first document
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
opencraw studio ./agreements
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
An empty folder. **Load ▾** brings in what the recipe reads.
|
|
37
|
+
|
|
38
|
+

|
|
39
|
+
|
|
40
|
+
Choose **Document…** and pick `agreement.pdf`.
|
|
41
|
+
|
|
42
|
+

|
|
43
|
+
|
|
44
|
+
The Studio copies the file next to the recipes (the recipe refers to it by name, `file:agreement.pdf`, so the
|
|
45
|
+
folder can be moved) and starts a recipe named after it. The page is drawn with every line the engine found
|
|
46
|
+
outlined, the way the recipe will see it.
|
|
47
|
+
|
|
48
|
+

|
|
49
|
+
|
|
50
|
+
## 2. Pick the values that have a label
|
|
51
|
+
|
|
52
|
+
Click `Reference ID: REF-2026-8801`. The chip says what the step will be tied to: **Reads the value after its
|
|
53
|
+
label**. The step is a `regex` on `Reference ID:`, so it finds the value wherever the line is, and the value
|
|
54
|
+
does not carry its label.
|
|
55
|
+
|
|
56
|
+

|
|
57
|
+
|
|
58
|
+
**Add to recipe**, then do the same for the effective date and the status. The three steps are named after
|
|
59
|
+
their labels: `referenceId`, `effectiveDate`, `status`.
|
|
60
|
+
|
|
61
|
+
## 3. Pick the description: the text between two headings
|
|
62
|
+
|
|
63
|
+
Click any line under **DETAILS**. The Studio sees a heading above it and another heading of the same size
|
|
64
|
+
below (`PRICE`), and ties the selection to them: **Reads what is between “DETAILS” and “PRICE”**. The whole
|
|
65
|
+
block is highlighted, not the line you clicked.
|
|
66
|
+
|
|
67
|
+

|
|
68
|
+
|
|
69
|
+
The step is a `section` with `selector: "^DETAILS$"` and `until: "^PRICE$"`. In another document it reads
|
|
70
|
+
whatever is between those two headings, however many paragraphs, however many columns.
|
|
71
|
+
|
|
72
|
+
## 4. Pick the terms: everything below a heading
|
|
73
|
+
|
|
74
|
+
Click a line under **TERMS**. Nothing follows it, so it reads **everything below “TERMS”**, over the page
|
|
75
|
+
break. The document repeats a header and a footer on each page; the Studio notices (the same text at the same
|
|
76
|
+
height on more than one page) and writes `ignoreHeadersFooters: true`, so the footer does not end up in the
|
|
77
|
+
middle of a sentence.
|
|
78
|
+
|
|
79
|
+

|
|
80
|
+
|
|
81
|
+
## 5. Pick the table
|
|
82
|
+
|
|
83
|
+
Choose the **Header row** mode and click the table's header (`Service Tier`), then the **Last row (until)**
|
|
84
|
+
mode and click the heading that follows the table (`TERMS`). The badge above the page says what was picked:
|
|
85
|
+
`table: ^Service Tier until ^TERMS`.
|
|
86
|
+
|
|
87
|
+

|
|
88
|
+
|
|
89
|
+
## 6. The input recipe
|
|
90
|
+
|
|
91
|
+
The **Steps** tab shows the recipe so far: a request for the document, three values by label, two sections
|
|
92
|
+
and a table. There is no coordinate in it.
|
|
93
|
+
|
|
94
|
+

|
|
95
|
+
|
|
96
|
+
## 7. The output recipe
|
|
97
|
+
|
|
98
|
+
The **Record** tab is the output side: what a record of this recipe looks like. The Studio proposes one field
|
|
99
|
+
for each value the steps read, with a type guessed from what it is (a block of text is a `string` whatever
|
|
100
|
+
its name says; the table's rows are a `json` list).
|
|
101
|
+
|
|
102
|
+

|
|
103
|
+
|
|
104
|
+
A recipe with fields but no **Emit** step reads values and returns nothing, so the tab says so and offers
|
|
105
|
+
**Add Emit step**. Then **Add all** adds every proposal as a field together with its mapping. Rename the
|
|
106
|
+
table's field (`table`) to `tiers` and **Save**: this writes both files, `agreement.ocw-in.json` (the input
|
|
107
|
+
recipe, with its `mapping`) and `agreement.ocw-out.json` (the output recipe, with its `fields`).
|
|
108
|
+
|
|
109
|
+

|
|
110
|
+
|
|
111
|
+
## 8. Run it on the first document
|
|
112
|
+
|
|
113
|
+
**Run sample** runs the recipe and shows the record: the reference, the effective date as a date, the status,
|
|
114
|
+
the description in one piece, the terms numbered, and the tiers.
|
|
115
|
+
|
|
116
|
+

|
|
117
|
+
|
|
118
|
+
The **JSON** tab shows exactly what was written. Every step is anchored on a heading or a label.
|
|
119
|
+
|
|
120
|
+

|
|
121
|
+
|
|
122
|
+
## 9. Load the second document
|
|
123
|
+
|
|
124
|
+
**Load ▾ › Document…** again, with `agreement-two-columns.pdf`. Loading a document into a recipe that reads a
|
|
125
|
+
document replaces its start address and keeps every step; the notice under the toolbar says what it replaced.
|
|
126
|
+
The page now looks different: two columns, `Details` in lower case, another header, another footer, a longer
|
|
127
|
+
description.
|
|
128
|
+
|
|
129
|
+

|
|
130
|
+
|
|
131
|
+
## 10. Run it again
|
|
132
|
+
|
|
133
|
+
**Run sample.** The same recipe reads the new document: the description comes out in reading order, left
|
|
134
|
+
column and then right; the terms run over the page break, numbered, with no footer inside; the table has its
|
|
135
|
+
three tiers and not the footer row that sits right under it.
|
|
136
|
+
|
|
137
|
+

|
|
138
|
+
|
|
139
|
+
## What to do when a document does not fit
|
|
140
|
+
|
|
141
|
+
- **A value is missing.** Open **Why?** and click the missing cell: it names the step that found nothing. A
|
|
142
|
+
`section` finds nothing when its heading is not in the document (a different wording): change its
|
|
143
|
+
`selector`, or make it a pattern that accepts both (`^(Details|Description)$`).
|
|
144
|
+
- **A block ends too early or too late.** Give the `section` an `until` (the heading that follows it).
|
|
145
|
+
- **A footer is in the text.** Add `ignoreHeadersFooters: true` to the step.
|
|
146
|
+
- **A value has no label and no heading above it.** Then only a position is left: drag a box on the page.
|
|
147
|
+
The chip says **Reads a fixed position on the page: it breaks when the layout moves**, which is the
|
|
148
|
+
Studio telling you this step will not survive a document of another layout.
|
|
149
|
+
|
|
150
|
+
Reference: the [`section`, `table` and `regex` extracts of a PDF](../recipes/authoring.md#46-pdfs).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opencraw/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.48",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.esm.js",
|
|
6
6
|
"module": "./dist/index.esm.js",
|
|
@@ -19,13 +19,14 @@
|
|
|
19
19
|
"files": [
|
|
20
20
|
"dist",
|
|
21
21
|
"bin",
|
|
22
|
+
"docs",
|
|
22
23
|
"!**/*.tsbuildinfo",
|
|
23
24
|
"!**/*.d.ts.map",
|
|
24
25
|
"!**/*.js.map"
|
|
25
26
|
],
|
|
26
27
|
"dependencies": {
|
|
27
|
-
"@opencraw/core": "^0.1.
|
|
28
|
-
"@opencraw/cli": "^0.1.
|
|
28
|
+
"@opencraw/core": "^0.1.42",
|
|
29
|
+
"@opencraw/cli": "^0.1.48",
|
|
29
30
|
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
30
31
|
"playwright": "^1.63.0",
|
|
31
32
|
"zod": "^4.6.5"
|
|
@@ -78,7 +79,8 @@
|
|
|
78
79
|
"@opencraw/cli"
|
|
79
80
|
],
|
|
80
81
|
"target": "e2e"
|
|
81
|
-
}
|
|
82
|
+
},
|
|
83
|
+
"copy-docs"
|
|
82
84
|
],
|
|
83
85
|
"inputs": [
|
|
84
86
|
"default",
|
|
@@ -89,6 +91,29 @@
|
|
|
89
91
|
"command": "tsc -p tsconfig.e2e.json && jest --config jest.e2e.config.cts",
|
|
90
92
|
"cwd": "packages/mcp"
|
|
91
93
|
}
|
|
94
|
+
},
|
|
95
|
+
"copy-docs": {
|
|
96
|
+
"executor": "nx:run-commands",
|
|
97
|
+
"cache": true,
|
|
98
|
+
"inputs": [
|
|
99
|
+
"{workspaceRoot}/docs/recipes/*.md",
|
|
100
|
+
"{workspaceRoot}/docs/how-it-works/*.md",
|
|
101
|
+
"{workspaceRoot}/docs/studio/*.md",
|
|
102
|
+
"{projectRoot}/scripts/copy-docs.mjs"
|
|
103
|
+
],
|
|
104
|
+
"outputs": [
|
|
105
|
+
"{projectRoot}/docs"
|
|
106
|
+
],
|
|
107
|
+
"options": {
|
|
108
|
+
"command": "node scripts/copy-docs.mjs",
|
|
109
|
+
"cwd": "packages/mcp"
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"build": {
|
|
113
|
+
"dependsOn": [
|
|
114
|
+
"^build",
|
|
115
|
+
"copy-docs"
|
|
116
|
+
]
|
|
92
117
|
}
|
|
93
118
|
}
|
|
94
119
|
}
|