meguro-mcp 0.2.12 → 0.2.14
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/CHANGELOG.md +16 -0
- package/README.md +28 -21
- package/package.json +1 -1
- package/scripts/generate-readme-tools.mjs +67 -12
- package/src/docs.mjs +3738 -117
- package/src/protocol.mjs +6 -0
- package/src/server.mjs +1 -1
- package/src/tools.mjs +1333 -529
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `meguro-mcp` are recorded here. Versions follow Semantic Versioning.
|
|
4
4
|
|
|
5
|
+
## 0.2.14 — 2026-09-06
|
|
6
|
+
|
|
7
|
+
- Packages the current deployed source, whose documentation resources and served behavior the
|
|
8
|
+
hosted door already serves: getting-started v51, product-guide v48, receipt-guide v31,
|
|
9
|
+
gate-policy v9, and documentation-index v52 across 191 immutable resources.
|
|
10
|
+
- Carries the run, receipt, Store, workspace, and Admin-schema behavior already reachable at this
|
|
11
|
+
source revision; no tool identity, input schema, or call shape changes with this version.
|
|
12
|
+
- This is a prepared package candidate only; it is not published, tagged, or deployed.
|
|
13
|
+
|
|
14
|
+
## 0.2.13 — 2026-08-11
|
|
15
|
+
|
|
16
|
+
- Preserves server-owned structured tier-enforcement facts, same-tier remedies, and conditional
|
|
17
|
+
Plans & Billing handoffs across MCP errors without quoting or inferring plan prices.
|
|
18
|
+
- Keeps the existing tool registry and call shapes unchanged. This is a prepared package candidate
|
|
19
|
+
only; it is not published, tagged, or deployed.
|
|
20
|
+
|
|
5
21
|
## 0.2.12 — 2026-08-11
|
|
6
22
|
|
|
7
23
|
- Adds a credential-safe, state-aware `adminExecutionGuide` to `get_connection_details`, separating
|
package/README.md
CHANGED
|
@@ -21,9 +21,12 @@ The configured hosted endpoints are environment-specific: dev uses
|
|
|
21
21
|
`https://mcp-dev.meguro.io/mcp`, stage uses `https://mcp-stage.meguro.io/mcp`, and production uses
|
|
22
22
|
`https://mcp.meguro.io/mcp`. Use the URL shown by the Console for the environment you intend to access.
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
<!-- BEGIN GENERATED MCP README CURRENT DOCUMENTATION -->
|
|
25
|
+
<!-- Run `npm run docs:tools --workspace meguro-mcp` to refresh this section from documentation currency. -->
|
|
26
|
+
After connecting, read `meguro://docs/getting-started/v51` for the world-first operating sequence;
|
|
27
|
+
for general Meguro questions, read `meguro://docs/product-guide/v48`. Both are available through
|
|
26
28
|
`resources/read` or the matching `docs_read({ topic, version })` fallback.
|
|
29
|
+
<!-- END GENERATED MCP README CURRENT DOCUMENTATION -->
|
|
27
30
|
|
|
28
31
|
The hosted server exposes 39 customer-safe tools and deliberately excludes `admin_probe`. Active
|
|
29
32
|
grants are visible and revocable under Console → Settings → Connection → MCP
|
|
@@ -37,31 +40,28 @@ fallback, separate from the hosted Streamable HTTP OAuth endpoint.
|
|
|
37
40
|
|
|
38
41
|
Practice stores separately expose a Storefront shopper/data-plane MCP endpoint at `https://<worldId>.meguro.io/api/mcp`. That endpoint is not this server and cannot start runs, reveal Admin connection details, inspect schemas, or collect receipts.
|
|
39
42
|
|
|
40
|
-
Console provides fast trusted proof and evidence inspection; the agency agent normally remains in its own environment. A practice-store endpoint/token remains stable while commerce time moves through explicit run tools. Practice evidence is deterministic scenario simulation, not merchant forecasting. Console-proof actions are not credited to the agent, and Receipt Gate evidence is not public certification.
|
|
43
|
+
Console provides fast trusted proof and evidence inspection; the agency agent normally remains in its own environment. A practice-store endpoint/token remains stable while commerce time moves through explicit run tools. Practice evidence is deterministic scenario simulation, not merchant forecasting. Console-proof actions are not credited to the agent, and Configured Receipt Gate evidence is not public certification.
|
|
41
44
|
|
|
42
45
|
## Tools
|
|
43
46
|
|
|
44
47
|
<!-- BEGIN GENERATED MCP TOOL TABLE -->
|
|
45
48
|
<!-- Run `npm run docs:tools --workspace meguro-mcp` to refresh this section from `tools/list`. -->
|
|
46
|
-
This table is generated from the server's live `tools/list` response (
|
|
49
|
+
This table is generated from the server's live `tools/list` response (46 tools).
|
|
47
50
|
|
|
48
51
|
| Tool | Title | Behavior annotations |
|
|
49
52
|
|---|---|---|
|
|
50
53
|
| `docs_read` | Read Meguro product and evidence documentation | read-only · non-destructive · idempotent · closed-world |
|
|
51
54
|
| `templates_list` | List practice-store templates | read-only · non-destructive · idempotent · closed-world |
|
|
55
|
+
| `template_get` | Read one practice-store template | read-only · non-destructive · idempotent · closed-world |
|
|
52
56
|
| `stores_list` | List practice stores | read-only · non-destructive · idempotent · closed-world |
|
|
53
57
|
| `store_create` | Create a practice store | read-write · non-destructive · non-idempotent · closed-world |
|
|
54
58
|
| `store_delete` | Delete a practice store | read-write · destructive · non-idempotent · closed-world |
|
|
55
59
|
| `store_passport` | Read Store Passport | read-only · non-destructive · idempotent · closed-world |
|
|
60
|
+
| `sample_store_reset` | Repair the sample practice store | read-write · destructive · idempotent · closed-world |
|
|
56
61
|
| `workspaces_list` | List account workspaces | read-only · non-destructive · idempotent · closed-world |
|
|
57
62
|
| `workspace_create` | Create a workspace | read-write · non-destructive · non-idempotent · closed-world |
|
|
58
63
|
| `workspace_archive` | Archive a workspace | read-write · destructive · idempotent · closed-world |
|
|
59
64
|
| `workspace_unarchive` | Restore a workspace | read-write · non-destructive · idempotent · closed-world |
|
|
60
|
-
| `share_create` | Create or update a private share draft | read-write · non-destructive · non-idempotent · closed-world |
|
|
61
|
-
| `shares_list` | List evidence shares | read-only · non-destructive · idempotent · closed-world |
|
|
62
|
-
| `share_status` | Read an evidence share | read-only · non-destructive · idempotent · closed-world |
|
|
63
|
-
| `share_publish` | Publish evidence to client viewers | read-write · non-destructive · non-idempotent · open-world |
|
|
64
|
-
| `share_revoke` | Revoke client-viewer evidence access | read-write · destructive · idempotent · open-world |
|
|
65
65
|
| `catalog_slice_read` | Read a live Shopify catalog slice | read-only · non-destructive · idempotent · open-world |
|
|
66
66
|
| `catalog_slice_snapshot` | Mint a catalog slice snapshot | read-write · non-destructive · non-idempotent · open-world |
|
|
67
67
|
| `catalog_slices_saved` | Manage saved catalog slices | read-write · destructive · non-idempotent · open-world |
|
|
@@ -73,14 +73,14 @@ This table is generated from the server's live `tools/list` response (48 tools).
|
|
|
73
73
|
| `run_report` | Read run receipt | read-only · non-destructive · idempotent · closed-world |
|
|
74
74
|
| `run_resume` | Resume a Shopify dev-store run | read-write · non-destructive · non-idempotent · open-world |
|
|
75
75
|
| `runs_diff` | Compare history-run receipts | read-only · non-destructive · idempotent · closed-world |
|
|
76
|
-
| `gate_configure` | Configure
|
|
77
|
-
| `gate_evaluate` | Evaluate
|
|
78
|
-
| `gate_verdict` | Read
|
|
76
|
+
| `gate_configure` | Configure Configured Receipt Gate | read-write · non-destructive · idempotent · closed-world |
|
|
77
|
+
| `gate_evaluate` | Evaluate Configured Receipt Gate | read-write · non-destructive · non-idempotent · closed-world |
|
|
78
|
+
| `gate_verdict` | Read Configured Receipt Gate verdict | read-only · non-destructive · idempotent · closed-world |
|
|
79
79
|
| `runs_list` | List history runs | read-only · non-destructive · idempotent · closed-world |
|
|
80
80
|
| `usage_read` | Read usage headroom | read-only · non-destructive · idempotent · closed-world |
|
|
81
81
|
| `twin_diff` | Read a twin impact receipt | read-only · non-destructive · idempotent · closed-world |
|
|
82
82
|
| `exam_preflight` | Check Shopify Exam readiness | read-only · non-destructive · idempotent · open-world |
|
|
83
|
-
| `exam_start` | Start or continue a Shopify Exam | read-write · non-destructive · idempotent · open-world |
|
|
83
|
+
| `exam_start` | Start or continue a Shopify Exam | read-write · non-destructive · non-idempotent · open-world |
|
|
84
84
|
| `exam_status` | Read Shopify Exam status | read-only · non-destructive · idempotent · closed-world |
|
|
85
85
|
| `exam_report` | Read a Shopify Exam receipt | read-only · non-destructive · idempotent · closed-world |
|
|
86
86
|
| `practice_run_start` | Start a practice run | read-write · non-destructive · non-idempotent · closed-world |
|
|
@@ -89,12 +89,13 @@ This table is generated from the server's live `tools/list` response (48 tools).
|
|
|
89
89
|
| `practice_run_checkpoint` | Capture a practice-run checkpoint | read-write · non-destructive · non-idempotent · closed-world |
|
|
90
90
|
| `practice_run_advance` | Advance store time | read-write · non-destructive · non-idempotent · closed-world |
|
|
91
91
|
| `practice_run_finish` | Finish a practice run | read-write · non-destructive · non-idempotent · closed-world |
|
|
92
|
-
| `practice_run_report` | Read a
|
|
92
|
+
| `practice_run_report` | Read a practice-run receipt | read-only · non-destructive · idempotent · closed-world |
|
|
93
93
|
| `practice_run_impact` | Read a practice-run impact receipt | read-only · non-destructive · idempotent · closed-world |
|
|
94
94
|
| `get_connection_details` | Get practice-store connection details | read-only · non-destructive · idempotent · closed-world |
|
|
95
95
|
| `admin_probe` | Run an Admin API probe | read-write · non-destructive · non-idempotent · closed-world |
|
|
96
96
|
| `admin_schema` | Look up the Admin API schema | read-only · non-destructive · idempotent · closed-world |
|
|
97
97
|
| `admin_recipes_list` | List Admin API recipes | read-only · non-destructive · idempotent · closed-world |
|
|
98
|
+
| `plan_validate` | Check an intended Admin operation plan against Meguro | read-only · non-destructive · idempotent · closed-world |
|
|
98
99
|
<!-- END GENERATED MCP TOOL TABLE -->
|
|
99
100
|
|
|
100
101
|
## Documentation resources
|
|
@@ -164,8 +165,8 @@ Use these tool names in order:
|
|
|
164
165
|
3. `get_connection_details({ storeId })` through the explicit secure flow (`worldId` remains a legacy alias). Follow its structured `adminExecutionGuide`; keep returned credential values out of model/chat logs.
|
|
165
166
|
4. `practice_run_start({ storeId, clock: { mode: "harness", simulationDays: 14, stepDays: 1 } })` — the same `storeId` the previous step took and returned.
|
|
166
167
|
5. Launch the agency agent in its own environment with the stable returned `SHOPIFY_*` values.
|
|
167
|
-
6. `practice_run_status({ attemptId })`, then `practice_run_checkpoint({ attemptId })`.
|
|
168
|
-
7. `practice_run_advance({ attemptId, days: 1,
|
|
168
|
+
6. `practice_run_status({ attemptId })`, then `practice_run_checkpoint({ attemptId })`; retain the exact returned `practiceRun.advanceCursor`.
|
|
169
|
+
7. `practice_run_advance({ attemptId, days: 1, advanceCursor })`, copying that object unchanged. Supply `until` instead of `days` for a supported event stop. Legacy flat `expectedDay` and `expectedCallSeq` remain accepted together.
|
|
169
170
|
8. Inspect the aligned checkpoint evidence in Console or the run APIs.
|
|
170
171
|
9. `practice_run_finish({ attemptId })`, then `practice_run_report({ attemptId })` for the run's receipt.
|
|
171
172
|
|
|
@@ -194,12 +195,15 @@ See [the agency quickstart](../../docs/agency-practice-run-quickstart.md) and [H
|
|
|
194
195
|
|
|
195
196
|
## Advanced: CI or local STDIO
|
|
196
197
|
|
|
198
|
+
<!-- BEGIN GENERATED MCP README LOCAL TOOL COUNT -->
|
|
199
|
+
<!-- Run `npm run docs:tools --workspace meguro-mcp` to refresh this section from `tools/list`. -->
|
|
197
200
|
Use the public STDIO package for CI, local automation, or clients without hosted Streamable HTTP and
|
|
198
|
-
OAuth support. It requires a workspace-bound `meg_sk_…` API key and exposes the full
|
|
201
|
+
OAuth support. It requires a workspace-bound `meg_sk_…` API key and exposes the full 46-tool local
|
|
199
202
|
surface. Pin the exact public version in client configuration so a quickstart stays reproducible:
|
|
203
|
+
<!-- END GENERATED MCP README LOCAL TOOL COUNT -->
|
|
200
204
|
|
|
201
205
|
```bash
|
|
202
|
-
npx -y meguro-mcp@0.2.
|
|
206
|
+
npx -y meguro-mcp@0.2.14
|
|
203
207
|
```
|
|
204
208
|
|
|
205
209
|
### Environment
|
|
@@ -217,7 +221,7 @@ claude mcp add meguro \
|
|
|
217
221
|
-e MEGURO_API_BASE_URL=https://api-dev.meguro.io \
|
|
218
222
|
-e MEGURO_API_TOKEN=meg_sk_... \
|
|
219
223
|
-e MEGURO_DASHBOARD_URL=https://... \
|
|
220
|
-
-- npx -y meguro-mcp@0.2.
|
|
224
|
+
-- npx -y meguro-mcp@0.2.14
|
|
221
225
|
```
|
|
222
226
|
|
|
223
227
|
### Register — Cursor (`.cursor/mcp.json`)
|
|
@@ -227,7 +231,7 @@ claude mcp add meguro \
|
|
|
227
231
|
"mcpServers": {
|
|
228
232
|
"meguro": {
|
|
229
233
|
"command": "npx",
|
|
230
|
-
"args": ["-y", "meguro-mcp@0.2.
|
|
234
|
+
"args": ["-y", "meguro-mcp@0.2.14"],
|
|
231
235
|
"env": {
|
|
232
236
|
"MEGURO_API_BASE_URL": "https://api-dev.meguro.io",
|
|
233
237
|
"MEGURO_API_TOKEN": "meg_sk_...",
|
|
@@ -247,7 +251,10 @@ seed `bfcm-regression`, and give me the dashboard link."*
|
|
|
247
251
|
npm test --workspace meguro-mcp
|
|
248
252
|
```
|
|
249
253
|
|
|
254
|
+
<!-- BEGIN GENERATED MCP README DISTRIBUTION TOOL COUNT -->
|
|
255
|
+
<!-- Run `npm run docs:tools --workspace meguro-mcp` to refresh this section from `tools/list`. -->
|
|
250
256
|
The test suite packs the public artifact, installs it into a temporary clean-room project, starts the
|
|
251
|
-
installed binary, and requires `tools/list` to return exactly
|
|
257
|
+
installed binary, and requires `tools/list` to return exactly 46 tools without leaking supplied
|
|
252
258
|
credentials to stdout or stderr. Maintainers should follow [RELEASING.md](./RELEASING.md) for every
|
|
253
259
|
version; release notes are in [CHANGELOG.md](./CHANGELOG.md).
|
|
260
|
+
<!-- END GENERATED MCP README DISTRIBUTION TOOL COUNT -->
|
package/package.json
CHANGED
|
@@ -3,11 +3,18 @@ import { spawn } from 'node:child_process';
|
|
|
3
3
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
4
4
|
import { dirname, join } from 'node:path';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { documentationResources, documentationToolContract } from '../src/docs.mjs';
|
|
6
7
|
|
|
7
8
|
const root = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
8
9
|
const readmePath = join(root, 'README.md');
|
|
9
|
-
const
|
|
10
|
-
const
|
|
10
|
+
const toolTableStartMarker = '<!-- BEGIN GENERATED MCP TOOL TABLE -->';
|
|
11
|
+
const toolTableEndMarker = '<!-- END GENERATED MCP TOOL TABLE -->';
|
|
12
|
+
const currentDocumentationStartMarker = '<!-- BEGIN GENERATED MCP README CURRENT DOCUMENTATION -->';
|
|
13
|
+
const currentDocumentationEndMarker = '<!-- END GENERATED MCP README CURRENT DOCUMENTATION -->';
|
|
14
|
+
const localToolCountStartMarker = '<!-- BEGIN GENERATED MCP README LOCAL TOOL COUNT -->';
|
|
15
|
+
const localToolCountEndMarker = '<!-- END GENERATED MCP README LOCAL TOOL COUNT -->';
|
|
16
|
+
const distributionToolCountStartMarker = '<!-- BEGIN GENERATED MCP README DISTRIBUTION TOOL COUNT -->';
|
|
17
|
+
const distributionToolCountEndMarker = '<!-- END GENERATED MCP README DISTRIBUTION TOOL COUNT -->';
|
|
11
18
|
|
|
12
19
|
function escapeCell(value) {
|
|
13
20
|
return String(value).replaceAll('|', '\\|').replaceAll('\n', ' ');
|
|
@@ -51,6 +58,23 @@ async function toolsList() {
|
|
|
51
58
|
return response.result.tools;
|
|
52
59
|
}
|
|
53
60
|
|
|
61
|
+
function currentDocumentationUri(topic) {
|
|
62
|
+
const version = documentationToolContract().currentByTopic[topic];
|
|
63
|
+
const resource = documentationResources().find((candidate) => (
|
|
64
|
+
candidate?._meta?.['meguro/topic'] === topic
|
|
65
|
+
&& candidate?._meta?.['meguro/version'] === version
|
|
66
|
+
));
|
|
67
|
+
assert.ok(resource, `Documentation currency has no published ${topic} resource at v${version}`);
|
|
68
|
+
return resource.uri;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function replaceGeneratedSection(readme, startMarker, endMarker, generated) {
|
|
72
|
+
const start = readme.indexOf(startMarker);
|
|
73
|
+
const end = readme.indexOf(endMarker);
|
|
74
|
+
assert.ok(start >= 0 && end > start, `README generated section ${startMarker} is missing or out of order`);
|
|
75
|
+
return `${readme.slice(0, start)}${generated}${readme.slice(end + endMarker.length)}`;
|
|
76
|
+
}
|
|
77
|
+
|
|
54
78
|
const tools = await toolsList();
|
|
55
79
|
const rows = tools.map((tool) => {
|
|
56
80
|
assert.equal(typeof tool.name, 'string');
|
|
@@ -60,27 +84,58 @@ const rows = tools.map((tool) => {
|
|
|
60
84
|
], `${tool.name} is missing behavior annotations`);
|
|
61
85
|
return `| \`${escapeCell(tool.name)}\` | ${escapeCell(tool.title)} | ${behaviorLabel(tool.annotations)} |`;
|
|
62
86
|
});
|
|
63
|
-
const
|
|
64
|
-
|
|
87
|
+
const generatedToolTable = [
|
|
88
|
+
toolTableStartMarker,
|
|
65
89
|
'<!-- Run `npm run docs:tools --workspace meguro-mcp` to refresh this section from `tools/list`. -->',
|
|
66
90
|
`This table is generated from the server's live \`tools/list\` response (${tools.length} tools).`,
|
|
67
91
|
'',
|
|
68
92
|
'| Tool | Title | Behavior annotations |',
|
|
69
93
|
'|---|---|---|',
|
|
70
94
|
...rows,
|
|
71
|
-
|
|
95
|
+
toolTableEndMarker,
|
|
96
|
+
].join('\n');
|
|
97
|
+
const gettingStartedUri = currentDocumentationUri('getting-started');
|
|
98
|
+
const productGuideUri = currentDocumentationUri('product-guide');
|
|
99
|
+
const generatedCurrentDocumentation = [
|
|
100
|
+
currentDocumentationStartMarker,
|
|
101
|
+
'<!-- Run `npm run docs:tools --workspace meguro-mcp` to refresh this section from documentation currency. -->',
|
|
102
|
+
`After connecting, read \`${gettingStartedUri}\` for the world-first operating sequence;`,
|
|
103
|
+
`for general Meguro questions, read \`${productGuideUri}\`. Both are available through`,
|
|
104
|
+
'`resources/read` or the matching `docs_read({ topic, version })` fallback.',
|
|
105
|
+
currentDocumentationEndMarker,
|
|
106
|
+
].join('\n');
|
|
107
|
+
const generatedLocalToolCount = [
|
|
108
|
+
localToolCountStartMarker,
|
|
109
|
+
'<!-- Run `npm run docs:tools --workspace meguro-mcp` to refresh this section from `tools/list`. -->',
|
|
110
|
+
'Use the public STDIO package for CI, local automation, or clients without hosted Streamable HTTP and',
|
|
111
|
+
`OAuth support. It requires a workspace-bound \`meg_sk_…\` API key and exposes the full ${tools.length}-tool local`,
|
|
112
|
+
'surface. Pin the exact public version in client configuration so a quickstart stays reproducible:',
|
|
113
|
+
localToolCountEndMarker,
|
|
114
|
+
].join('\n');
|
|
115
|
+
const generatedDistributionToolCount = [
|
|
116
|
+
distributionToolCountStartMarker,
|
|
117
|
+
'<!-- Run `npm run docs:tools --workspace meguro-mcp` to refresh this section from `tools/list`. -->',
|
|
118
|
+
'The test suite packs the public artifact, installs it into a temporary clean-room project, starts the',
|
|
119
|
+
`installed binary, and requires \`tools/list\` to return exactly ${tools.length} tools without leaking supplied`,
|
|
120
|
+
'credentials to stdout or stderr. Maintainers should follow [RELEASING.md](./RELEASING.md) for every',
|
|
121
|
+
'version; release notes are in [CHANGELOG.md](./CHANGELOG.md).',
|
|
122
|
+
distributionToolCountEndMarker,
|
|
72
123
|
].join('\n');
|
|
73
124
|
|
|
74
125
|
const readme = readFileSync(readmePath, 'utf8');
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
126
|
+
const nextReadme = [
|
|
127
|
+
[toolTableStartMarker, toolTableEndMarker, generatedToolTable],
|
|
128
|
+
[currentDocumentationStartMarker, currentDocumentationEndMarker, generatedCurrentDocumentation],
|
|
129
|
+
[localToolCountStartMarker, localToolCountEndMarker, generatedLocalToolCount],
|
|
130
|
+
[distributionToolCountStartMarker, distributionToolCountEndMarker, generatedDistributionToolCount],
|
|
131
|
+
].reduce((current, [startMarker, endMarker, generated]) => (
|
|
132
|
+
replaceGeneratedSection(current, startMarker, endMarker, generated)
|
|
133
|
+
), readme);
|
|
79
134
|
|
|
80
135
|
if (process.argv.includes('--check')) {
|
|
81
|
-
assert.equal(readme, nextReadme, 'README
|
|
82
|
-
console.log(`README
|
|
136
|
+
assert.equal(readme, nextReadme, 'README generated MCP claims are stale; run npm run docs:tools --workspace meguro-mcp');
|
|
137
|
+
console.log(`README generated MCP claims are current (${tools.length} tools)`);
|
|
83
138
|
} else {
|
|
84
139
|
writeFileSync(readmePath, nextReadme);
|
|
85
|
-
console.log(`README
|
|
140
|
+
console.log(`README generated MCP claims refreshed (${tools.length} tools)`);
|
|
86
141
|
}
|