meguro-mcp 0.2.7 → 0.2.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.
- package/CHANGELOG.md +9 -0
- package/README.md +5 -4
- package/package.json +1 -1
- package/src/docs.mjs +65 -4
- package/src/server.mjs +1 -1
- package/src/tools.mjs +159 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `meguro-mcp` are recorded here. Versions follow Semantic Versioning.
|
|
4
4
|
|
|
5
|
+
## 0.2.8 — 2026-08-09
|
|
6
|
+
|
|
7
|
+
- Adds `practice_runs_list` so a cold MCP-only evaluator can discover existing practice attempts
|
|
8
|
+
without guessing a store or run identifier.
|
|
9
|
+
- Exposes `admin_schema` through the hosted-safe registry, corrects hosted OAuth connection
|
|
10
|
+
guidance, and adds immutable documentation currency/index metadata.
|
|
11
|
+
- Changes no earlier immutable documentation byte stream and carries no unrelated tool or protocol
|
|
12
|
+
behavior beyond the landed MEG-768 cold-walk corrections.
|
|
13
|
+
|
|
5
14
|
## 0.2.7 — 2026-08-08
|
|
6
15
|
|
|
7
16
|
- Adds the optional `storeId` selector to `gate_evaluate` and `gate_verdict`, preserving every
|
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ Console provides fast trusted proof and evidence inspection; the agency agent no
|
|
|
43
43
|
|
|
44
44
|
<!-- BEGIN GENERATED MCP TOOL TABLE -->
|
|
45
45
|
<!-- 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 (
|
|
46
|
+
This table is generated from the server's live `tools/list` response (47 tools).
|
|
47
47
|
|
|
48
48
|
| Tool | Title | Behavior annotations |
|
|
49
49
|
|---|---|---|
|
|
@@ -84,6 +84,7 @@ This table is generated from the server's live `tools/list` response (46 tools).
|
|
|
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 |
|
|
87
|
+
| `practice_runs_list` | List practice runs | read-only · non-destructive · idempotent · closed-world |
|
|
87
88
|
| `practice_run_status` | Read practice-run status | read-only · non-destructive · idempotent · closed-world |
|
|
88
89
|
| `practice_run_checkpoint` | Capture a practice-run checkpoint | read-write · non-destructive · non-idempotent · closed-world |
|
|
89
90
|
| `practice_run_advance` | Advance store time | read-write · non-destructive · non-idempotent · closed-world |
|
|
@@ -185,7 +186,7 @@ OAuth support. It requires a workspace-bound `meg_sk_…` API key and exposes th
|
|
|
185
186
|
surface. Pin the exact public version in client configuration so a quickstart stays reproducible:
|
|
186
187
|
|
|
187
188
|
```bash
|
|
188
|
-
npx -y meguro-mcp@0.2.
|
|
189
|
+
npx -y meguro-mcp@0.2.8
|
|
189
190
|
```
|
|
190
191
|
|
|
191
192
|
### Environment
|
|
@@ -203,7 +204,7 @@ claude mcp add meguro \
|
|
|
203
204
|
-e MEGURO_API_BASE_URL=https://api-dev.meguro.io \
|
|
204
205
|
-e MEGURO_API_TOKEN=meg_sk_... \
|
|
205
206
|
-e MEGURO_DASHBOARD_URL=https://... \
|
|
206
|
-
-- npx -y meguro-mcp@0.2.
|
|
207
|
+
-- npx -y meguro-mcp@0.2.8
|
|
207
208
|
```
|
|
208
209
|
|
|
209
210
|
### Register — Cursor (`.cursor/mcp.json`)
|
|
@@ -213,7 +214,7 @@ claude mcp add meguro \
|
|
|
213
214
|
"mcpServers": {
|
|
214
215
|
"meguro": {
|
|
215
216
|
"command": "npx",
|
|
216
|
-
"args": ["-y", "meguro-mcp@0.2.
|
|
217
|
+
"args": ["-y", "meguro-mcp@0.2.8"],
|
|
217
218
|
"env": {
|
|
218
219
|
"MEGURO_API_BASE_URL": "https://api-dev.meguro.io",
|
|
219
220
|
"MEGURO_API_TOKEN": "meg_sk_...",
|
package/package.json
CHANGED
package/src/docs.mjs
CHANGED
|
@@ -41,8 +41,45 @@ const GETTING_STARTED_V6_URI = `meguro://docs/getting-started/v${GETTING_STARTED
|
|
|
41
41
|
const PRODUCT_GUIDE_URI = `meguro://docs/product-guide/v${PRODUCT_GUIDE_VERSION}`;
|
|
42
42
|
const PRODUCT_GUIDE_V2_URI = `meguro://docs/product-guide/v${PRODUCT_GUIDE_V2_VERSION}`;
|
|
43
43
|
const PRODUCT_GUIDE_V3_URI = `meguro://docs/product-guide/v${PRODUCT_GUIDE_V3_VERSION}`;
|
|
44
|
+
export const DOCUMENTATION_INDEX_URI = 'meguro://docs/index/v1';
|
|
45
|
+
|
|
46
|
+
const DOCUMENTATION_CURRENCY_V1 = deepFreeze({
|
|
47
|
+
indexVersion: 1,
|
|
48
|
+
currentUriByTopic: {
|
|
49
|
+
'gate-policy': GATE_POLICY_V2_URI,
|
|
50
|
+
'getting-started': GETTING_STARTED_V6_URI,
|
|
51
|
+
index: DOCUMENTATION_INDEX_URI,
|
|
52
|
+
'product-guide': PRODUCT_GUIDE_V3_URI,
|
|
53
|
+
'receipt-guide': RECEIPT_GUIDE_V7_URI,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
const CURRENT_DOCUMENTATION_CURRENCY = DOCUMENTATION_CURRENCY_V1;
|
|
57
|
+
|
|
58
|
+
function documentationVersionFromUri(uri) {
|
|
59
|
+
const match = /\/v([1-9][0-9]*)$/u.exec(uri);
|
|
60
|
+
if (!match) throw new Error(`Documentation URI has no immutable version: ${uri}`);
|
|
61
|
+
return Number(match[1]);
|
|
62
|
+
}
|
|
44
63
|
|
|
45
|
-
|
|
64
|
+
function documentationIndexText(currency) {
|
|
65
|
+
const rows = Object.entries(currency.currentUriByTopic).sort(([left], [right]) => codepointCompare(left, right));
|
|
66
|
+
return [
|
|
67
|
+
`# Meguro documentation index v${currency.indexVersion}`,
|
|
68
|
+
'',
|
|
69
|
+
`Published URI: \`${DOCUMENTATION_INDEX_URI}\``,
|
|
70
|
+
'',
|
|
71
|
+
'This immutable index records the current published version of every documentation family at issuance.',
|
|
72
|
+
'Use the `meguro/status` annotations from `resources/list` for live currency; cited versioned resources never change.',
|
|
73
|
+
'',
|
|
74
|
+
'| Family | Current version | Current resource |',
|
|
75
|
+
'| --- | ---: | --- |',
|
|
76
|
+
...rows.map(([topic, uri]) => `| ${topic} | v${documentationVersionFromUri(uri)} | ${uri} |`),
|
|
77
|
+
].join('\n');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const CURRENT_GETTING_STARTED_URI = CURRENT_DOCUMENTATION_CURRENCY.currentUriByTopic['getting-started'];
|
|
81
|
+
const CURRENT_PRODUCT_GUIDE_URI = CURRENT_DOCUMENTATION_CURRENCY.currentUriByTopic['product-guide'];
|
|
82
|
+
export const MCP_INITIALIZE_INSTRUCTIONS = `Start with \`${CURRENT_GETTING_STARTED_URI}\` or call \`docs_read({ topic: "getting-started", version: ${documentationVersionFromUri(CURRENT_GETTING_STARTED_URI)} })\`; for general Meguro questions, read \`${CURRENT_PRODUCT_GUIDE_URI}\` or call \`docs_read({ topic: "product-guide", version: ${documentationVersionFromUri(CURRENT_PRODUCT_GUIDE_URI)} })\`.`;
|
|
46
83
|
export const PRODUCT_GUIDE_SHA256 = 'e5450c1b4181cec4d6ed0a498dbff1cb25d2e223ff2228928aecbbce9674f074';
|
|
47
84
|
|
|
48
85
|
function deepFreeze(value) {
|
|
@@ -1262,13 +1299,13 @@ function entry(input) {
|
|
|
1262
1299
|
name: input.name,
|
|
1263
1300
|
title: input.title,
|
|
1264
1301
|
description: input.description,
|
|
1265
|
-
mimeType: 'text/markdown',
|
|
1302
|
+
mimeType: input.mimeType ?? 'text/markdown',
|
|
1266
1303
|
text,
|
|
1267
1304
|
sha256: digest,
|
|
1268
1305
|
});
|
|
1269
1306
|
}
|
|
1270
1307
|
|
|
1271
|
-
export function buildDocumentationCatalog(inputs) {
|
|
1308
|
+
export function buildDocumentationCatalog(inputs, currency) {
|
|
1272
1309
|
const rows = inputs.map(entry).sort((left, right) => codepointCompare(left.uri, right.uri));
|
|
1273
1310
|
const byUri = new Map();
|
|
1274
1311
|
const byTopicVersion = new Map();
|
|
@@ -1279,6 +1316,19 @@ export function buildDocumentationCatalog(inputs) {
|
|
|
1279
1316
|
byUri.set(row.uri, row);
|
|
1280
1317
|
byTopicVersion.set(key, row);
|
|
1281
1318
|
}
|
|
1319
|
+
const currentUriByTopic = currency?.currentUriByTopic ?? Object.fromEntries(
|
|
1320
|
+
[...new Set(rows.map((row) => row.topic))].map((topic) => {
|
|
1321
|
+
const current = rows.filter((row) => row.topic === topic).sort((left, right) => left.version - right.version).at(-1);
|
|
1322
|
+
return [topic, current.uri];
|
|
1323
|
+
}),
|
|
1324
|
+
);
|
|
1325
|
+
for (const topic of new Set(rows.map((row) => row.topic))) {
|
|
1326
|
+
const currentUri = currentUriByTopic[topic];
|
|
1327
|
+
const current = byUri.get(currentUri);
|
|
1328
|
+
if (!current || current.topic !== topic) {
|
|
1329
|
+
throw new Error(`Documentation currency has no valid current resource for ${topic}`);
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1282
1332
|
return deepFreeze({
|
|
1283
1333
|
list() {
|
|
1284
1334
|
return rows.map((row) => deepFreeze({
|
|
@@ -1292,6 +1342,8 @@ export function buildDocumentationCatalog(inputs) {
|
|
|
1292
1342
|
'meguro/topic': row.topic,
|
|
1293
1343
|
'meguro/version': row.version,
|
|
1294
1344
|
'meguro/sha256': row.sha256,
|
|
1345
|
+
'meguro/status': row.uri === currentUriByTopic[row.topic] ? 'current' : 'superseded',
|
|
1346
|
+
'meguro/current-uri': currentUriByTopic[row.topic],
|
|
1295
1347
|
},
|
|
1296
1348
|
}));
|
|
1297
1349
|
},
|
|
@@ -1391,6 +1443,15 @@ const CATALOG = buildDocumentationCatalog([
|
|
|
1391
1443
|
description: 'World-first product concepts, evidence boundaries, surface responsibilities, and question-to-source routing.',
|
|
1392
1444
|
text: PRODUCT_GUIDE_V3_TEXT,
|
|
1393
1445
|
},
|
|
1446
|
+
{
|
|
1447
|
+
topic: 'index',
|
|
1448
|
+
version: DOCUMENTATION_CURRENCY_V1.indexVersion,
|
|
1449
|
+
uri: DOCUMENTATION_INDEX_URI,
|
|
1450
|
+
name: 'Meguro documentation index v1',
|
|
1451
|
+
title: 'Meguro documentation index v1',
|
|
1452
|
+
description: 'Immutable current-version pointers for every published Meguro documentation family.',
|
|
1453
|
+
text: documentationIndexText(DOCUMENTATION_CURRENCY_V1),
|
|
1454
|
+
},
|
|
1394
1455
|
{
|
|
1395
1456
|
topic: 'receipt-guide',
|
|
1396
1457
|
version: RECEIPT_GUIDE_VERSION,
|
|
@@ -1472,7 +1533,7 @@ const CATALOG = buildDocumentationCatalog([
|
|
|
1472
1533
|
description: 'Immutable named checks and flip conditions republished with the simulation-run vocabulary.',
|
|
1473
1534
|
text: GATE_POLICY_V2_TEXT,
|
|
1474
1535
|
},
|
|
1475
|
-
]);
|
|
1536
|
+
], CURRENT_DOCUMENTATION_CURRENCY);
|
|
1476
1537
|
|
|
1477
1538
|
export function documentationResources() {
|
|
1478
1539
|
return CATALOG.list();
|
package/src/server.mjs
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from './protocol.mjs';
|
|
15
15
|
import { createTools, redactSecrets } from './tools.mjs';
|
|
16
16
|
|
|
17
|
-
const SERVER_INFO = { name: 'meguro', version: '0.2.
|
|
17
|
+
const SERVER_INFO = { name: 'meguro', version: '0.2.8' };
|
|
18
18
|
const PROTOCOL_VERSION = '2025-03-26';
|
|
19
19
|
|
|
20
20
|
const tools = createTools({
|
package/src/tools.mjs
CHANGED
|
@@ -26,6 +26,7 @@ const DOCUMENTATION_TOOL_CONTRACT = documentationToolContract();
|
|
|
26
26
|
const DOCUMENTATION_TOPICS = new Set(DOCUMENTATION_TOOL_CONTRACT.topics);
|
|
27
27
|
const FLEET_TOOL_NAMES = new Set([
|
|
28
28
|
'templates_list', 'stores_list', 'store_create', 'store_delete', 'store_passport',
|
|
29
|
+
'practice_runs_list',
|
|
29
30
|
'workspaces_list', 'workspace_create', 'workspace_archive', 'workspace_unarchive',
|
|
30
31
|
'share_create', 'shares_list', 'share_status', 'share_publish', 'share_revoke',
|
|
31
32
|
'catalog_slice_read', 'catalog_slice_snapshot', 'catalog_slices_saved',
|
|
@@ -69,6 +70,7 @@ const TOOL_PRESENTATION = Object.freeze({
|
|
|
69
70
|
exam_status: { title: 'Read Shopify Exam status', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
70
71
|
exam_report: { title: 'Read a Shopify Exam receipt', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
71
72
|
practice_run_start: { title: 'Start a practice run', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
73
|
+
practice_runs_list: { title: 'List practice runs', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
72
74
|
practice_run_status: { title: 'Read practice-run status', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
73
75
|
practice_run_checkpoint: { title: 'Capture a practice-run checkpoint', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
74
76
|
practice_run_advance: { title: 'Advance store time', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
@@ -832,13 +834,94 @@ function runsListProjection(value, lifecycle) {
|
|
|
832
834
|
...(visible.length === 0 ? {
|
|
833
835
|
emptyState: {
|
|
834
836
|
message: `No ${lifecycle ?? 'matching'} Shopify dev-store history runs were found. This says nothing about practice simulation attempts.`,
|
|
835
|
-
practiceAttemptRecovery: '
|
|
837
|
+
practiceAttemptRecovery: 'Call practice_runs_list to discover practice simulation attempts, then pass one exact attemptId to practice_run_report or practice_run_impact.',
|
|
836
838
|
},
|
|
837
839
|
} : {}),
|
|
838
840
|
clockDiscipline: 'runClock names lifecycle timestamps; worldClock names scenario coordinates and does not invent an unreported Store-time.',
|
|
839
841
|
});
|
|
840
842
|
}
|
|
841
843
|
|
|
844
|
+
function practiceRunsSelectionError(storeIds) {
|
|
845
|
+
const multiple = storeIds.length > 1;
|
|
846
|
+
const meaning = multiple
|
|
847
|
+
? `This workspace has more than one practice store (${storeIds.length}), so Meguro cannot infer which store's practice runs to list`
|
|
848
|
+
: 'This workspace has no practice store, so there are no store-owned practice runs to list';
|
|
849
|
+
const nextStep = multiple
|
|
850
|
+
? 'Call stores_list({}), choose one exact storeId, then call practice_runs_list({ storeId: "<exact storeId>" }). You may instead provide a known receiptId so Meguro can derive its owning store.'
|
|
851
|
+
: 'Create a practice store first, then call practice_runs_list with its storeId or with a receiptId from one of its runs.';
|
|
852
|
+
return {
|
|
853
|
+
content: [{
|
|
854
|
+
type: 'text',
|
|
855
|
+
text: JSON.stringify({
|
|
856
|
+
code: 'store-selection-required',
|
|
857
|
+
storeIds,
|
|
858
|
+
errors: [{ code: 'store-selection-required', message: `Store selection required. ${meaning}. ${nextStep}`, meaning, nextStep }],
|
|
859
|
+
}, null, 2),
|
|
860
|
+
}],
|
|
861
|
+
isError: true,
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
function practiceRunReceiptSelectionError(receiptId) {
|
|
866
|
+
return {
|
|
867
|
+
content: [{
|
|
868
|
+
type: 'text',
|
|
869
|
+
text: JSON.stringify({
|
|
870
|
+
code: 'receipt-unavailable',
|
|
871
|
+
errors: [{
|
|
872
|
+
code: 'receipt-unavailable',
|
|
873
|
+
message: `Practice receipt ${receiptId} is not available in this workspace.`,
|
|
874
|
+
meaning: 'The receipt does not identify a retained practice run owned by this workspace.',
|
|
875
|
+
nextStep: 'Call practice_runs_list with an exact current storeId, or use a receiptId returned by a prior practice_runs_list or practice_run_report response.',
|
|
876
|
+
}],
|
|
877
|
+
}, null, 2),
|
|
878
|
+
}],
|
|
879
|
+
isError: true,
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
function practiceRunReceiptStoreMismatch(receiptId, receiptStoreId, requestedStoreId) {
|
|
884
|
+
return {
|
|
885
|
+
content: [{
|
|
886
|
+
type: 'text',
|
|
887
|
+
text: JSON.stringify({
|
|
888
|
+
code: 'receipt-store-mismatch',
|
|
889
|
+
errors: [{
|
|
890
|
+
code: 'receipt-store-mismatch',
|
|
891
|
+
message: `Receipt and storeId identify different practice stores. Receipt ${receiptId} belongs to ${receiptStoreId}, not ${requestedStoreId}.`,
|
|
892
|
+
meaning: `Receipt ${receiptId} belongs to store ${receiptStoreId}, not ${requestedStoreId}.`,
|
|
893
|
+
nextStep: `Retry with storeId ${receiptStoreId}, or omit storeId and let Meguro derive it from receiptId ${receiptId}.`,
|
|
894
|
+
}],
|
|
895
|
+
}, null, 2),
|
|
896
|
+
}],
|
|
897
|
+
isError: true,
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
function practiceRunsProjection(value, storeId, storeSelection) {
|
|
902
|
+
const attempts = Array.isArray(value?.playbacks) ? value.playbacks : [];
|
|
903
|
+
return secretSafe({
|
|
904
|
+
schemaVersion: 'meguro.practice-run-list.v1',
|
|
905
|
+
storeId,
|
|
906
|
+
storeSelection,
|
|
907
|
+
attempts: attempts
|
|
908
|
+
.filter((attempt) => attempt?.storeId === storeId || attempt?.worldId === storeId)
|
|
909
|
+
.map((attempt) => ({
|
|
910
|
+
attemptId: attempt.attemptId,
|
|
911
|
+
state: attempt.status,
|
|
912
|
+
clock: {
|
|
913
|
+
mode: attempt.clock?.mode ?? null,
|
|
914
|
+
baselineDay: attempt.baselineDay ?? null,
|
|
915
|
+
watermarkDay: attempt.watermarkDay ?? null,
|
|
916
|
+
simulationDays: attempt.simulationDays ?? attempt.clock?.simulationDays ?? null,
|
|
917
|
+
elapsedSimulationDays: attempt.elapsedSimulationDays ?? null,
|
|
918
|
+
remainingSimulationDays: attempt.remainingSimulationDays ?? null,
|
|
919
|
+
},
|
|
920
|
+
receiptRef: { attemptId: attempt.attemptId },
|
|
921
|
+
})),
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
|
|
842
925
|
function practiceAttemptComparisonGuidanceFor(toolName, a, b) {
|
|
843
926
|
const attemptIds = [a, b].filter((id) => PRACTICE_ATTEMPT_ID.test(id));
|
|
844
927
|
const calls = attemptIds.flatMap((attemptId) => [
|
|
@@ -900,6 +983,21 @@ function practiceStoreConnectionNotFoundGuidance(storeId) {
|
|
|
900
983
|
};
|
|
901
984
|
}
|
|
902
985
|
|
|
986
|
+
function practiceRunsStoreNotFoundGuidance(storeId) {
|
|
987
|
+
return {
|
|
988
|
+
content: [{
|
|
989
|
+
type: 'text',
|
|
990
|
+
text: JSON.stringify({
|
|
991
|
+
code: 'practice-store-not-found',
|
|
992
|
+
message: `practice_runs_list could not find practice store ${storeId} in this account or the store is no longer active.`,
|
|
993
|
+
nextAction: 'Call stores_list({}) and use an exact current storeId from the returned stores array.',
|
|
994
|
+
stopCondition: `If stores_list({}) returns no current stores, stop: there is no practice store whose attempts can be listed. Do not retry ${JSON.stringify(storeId)}.`,
|
|
995
|
+
}, null, 2),
|
|
996
|
+
}],
|
|
997
|
+
isError: true,
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
|
|
903
1001
|
function legacyGateArtifactNotFoundGuidance(runId) {
|
|
904
1002
|
return {
|
|
905
1003
|
content: [{
|
|
@@ -1881,7 +1979,7 @@ export function createTools(config) {
|
|
|
1881
1979
|
},
|
|
1882
1980
|
{
|
|
1883
1981
|
name: 'runs_list',
|
|
1884
|
-
description: 'List Shopify dev-store history runs created by run_start so an agent can re-find that family of prior work. It does not list practice simulation attempts returned by practice_run_start; those
|
|
1982
|
+
description: 'List Shopify dev-store history runs created by run_start so an agent can re-find that family of prior work. It does not list practice simulation attempts returned by practice_run_start; call practice_runs_list for those pa-* ids, then use practice_run_report or practice_run_impact. Optional history-run lifecycle filtering supports running, paused, completed, failed, or cleaning. An empty result explicitly says it is only about history runs. The payload names run-clock lifecycle timestamps separately from world-clock scenario coordinates and returns no filter counts.',
|
|
1885
1983
|
inputSchema: {
|
|
1886
1984
|
type: 'object',
|
|
1887
1985
|
additionalProperties: false,
|
|
@@ -1992,6 +2090,20 @@ export function createTools(config) {
|
|
|
1992
2090
|
anyOf: [{ required: ['storeId'] }, { required: ['worldId'] }],
|
|
1993
2091
|
},
|
|
1994
2092
|
},
|
|
2093
|
+
{
|
|
2094
|
+
name: 'practice_runs_list',
|
|
2095
|
+
description: 'List bounded practice simulation attempt facts for one exact practice store: attemptId, lifecycle state, Store-clock summary, and a receiptRef that can be passed unchanged to practice_run_report. Store selection follows one fail-closed ladder: receiptId derives its owning store; otherwise an explicit storeId wins; omission is allowed only when the workspace has exactly one current store; zero or multiple stores return a structured store-selection-required error and never choose silently. An OAuth grant may select an owned workspace; an account API key remains bound to its own workspace.',
|
|
2096
|
+
inputSchema: {
|
|
2097
|
+
type: 'object',
|
|
2098
|
+
additionalProperties: false,
|
|
2099
|
+
properties: {
|
|
2100
|
+
workspaceId: { type: 'string', minLength: 1, description: 'Optional OAuth selector for an account-owned non-default workspace. An account API key can name only its bound workspace.' },
|
|
2101
|
+
storeId: { ...PRACTICE_STORE_ID_INPUT_SCHEMA, description: 'Optional exact practice-store id from stores_list. Omit only with receiptId or when the workspace has exactly one current store.' },
|
|
2102
|
+
receiptId: { type: 'string', minLength: 4, maxLength: 128, pattern: '^pa-[a-z0-9][a-z0-9-]{0,124}$', description: 'Optional known pa-* practice receipt identity. Meguro derives its owning store and refuses a conflicting storeId.' },
|
|
2103
|
+
},
|
|
2104
|
+
required: [],
|
|
2105
|
+
},
|
|
2106
|
+
},
|
|
1995
2107
|
{
|
|
1996
2108
|
name: 'practice_run_status',
|
|
1997
2109
|
description: 'Read the server-authoritative state of an external-agent practice simulation run, including its announced simulation-run deadlines and immutable simulation run receipt after any exit. Use Console for quick proof; the tested agent remains in the caller\'s environment.',
|
|
@@ -2059,7 +2171,7 @@ export function createTools(config) {
|
|
|
2059
2171
|
},
|
|
2060
2172
|
{
|
|
2061
2173
|
name: 'get_connection_details',
|
|
2062
|
-
description: `Fetch connection material for supported Shopify Admin GraphQL versions ${ADMIN_API_SUPPORTED_VERSION_LABEL}; the default is ${ADMIN_API_DEFAULT_VERSION}. Returns adminApiVersion (default), adminApiVersions (supported set), adminVersions (exact versioned URLs), the default URL, access token, and shop domain for an existing Meguro practice store so an assistant can configure a user agent without opening the dashboard. Inspect the selected version with admin_schema before the first Admin call; an agent targeting a newer Shopify release outside the supported set must treat that behavior as not established. Takes the canonical practice-store id (storeId) and returns it back, so the result passes directly into practice_run_start({ storeId }) — no identifier translation. The practice-store id is not an attemptId (run identity).
|
|
2174
|
+
description: `Fetch connection material for supported Shopify Admin GraphQL versions ${ADMIN_API_SUPPORTED_VERSION_LABEL}; the default is ${ADMIN_API_DEFAULT_VERSION}. Returns adminApiVersion (default), adminApiVersions (supported set), adminVersions (exact versioned URLs), the default URL, access token, and shop domain for an existing Meguro practice store so an assistant can configure a user agent without opening the dashboard. Inspect the selected version with admin_schema before the first Admin call; an agent targeting a newer Shopify release outside the supported set must treat that behavior as not established. Takes the canonical practice-store id (storeId) and returns it back, so the result passes directly into practice_run_start({ storeId }) — no identifier translation. The practice-store id is not an attemptId (run identity). The hosted MCP path uses the caller's OAuth grant; the public STDIO path uses its workspace-bound account API key.`,
|
|
2063
2175
|
inputSchema: {
|
|
2064
2176
|
type: 'object',
|
|
2065
2177
|
additionalProperties: false,
|
|
@@ -2630,6 +2742,50 @@ export function createTools(config) {
|
|
|
2630
2742
|
...consoleUrlFields(started.consoleRef, started.consoleRefExpiresAt),
|
|
2631
2743
|
}));
|
|
2632
2744
|
}
|
|
2745
|
+
case 'practice_runs_list': {
|
|
2746
|
+
const workspaceId = optionalWorkspaceId(args);
|
|
2747
|
+
const requestedStoreId = args.storeId === undefined
|
|
2748
|
+
? undefined
|
|
2749
|
+
: validatedStoreId(requiredString(args, 'storeId'), 'storeId');
|
|
2750
|
+
const receiptId = args.receiptId === undefined
|
|
2751
|
+
? undefined
|
|
2752
|
+
: requiredPracticeAttemptId(args, 'receiptId');
|
|
2753
|
+
if (receiptId) {
|
|
2754
|
+
const listed = await fleetRequest(name, 'GET', '/practice/playbacks', undefined, { workspaceId });
|
|
2755
|
+
if ('error' in listed) return listed.error;
|
|
2756
|
+
const playbacks = Array.isArray(listed.value?.playbacks) ? listed.value.playbacks : [];
|
|
2757
|
+
const referenced = playbacks.find((attempt) => attempt?.attemptId === receiptId);
|
|
2758
|
+
if (!referenced) return practiceRunReceiptSelectionError(receiptId);
|
|
2759
|
+
const receiptStoreId = String(referenced.storeId ?? referenced.worldId ?? '');
|
|
2760
|
+
if (requestedStoreId && requestedStoreId !== receiptStoreId) {
|
|
2761
|
+
return practiceRunReceiptStoreMismatch(receiptId, receiptStoreId, requestedStoreId);
|
|
2762
|
+
}
|
|
2763
|
+
return textResult(practiceRunsProjection(listed.value, receiptStoreId, 'receipt-derived'));
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2766
|
+
const fleet = await fleetRequest(name, 'GET', '/practice/stores', undefined, { workspaceId });
|
|
2767
|
+
if ('error' in fleet) return fleet.error;
|
|
2768
|
+
const storeIds = [...new Set((Array.isArray(fleet.value?.stores) ? fleet.value.stores : [])
|
|
2769
|
+
.map((store) => String(store?.storeId ?? store?.worldId ?? '').trim())
|
|
2770
|
+
.filter((storeId) => /^[a-z0-9-]+$/u.test(storeId)))].sort();
|
|
2771
|
+
|
|
2772
|
+
if (requestedStoreId && !storeIds.includes(requestedStoreId)) {
|
|
2773
|
+
return practiceRunsStoreNotFoundGuidance(requestedStoreId);
|
|
2774
|
+
}
|
|
2775
|
+
if (!requestedStoreId && storeIds.length !== 1) {
|
|
2776
|
+
return practiceRunsSelectionError(storeIds);
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2779
|
+
const listPath = queryPath('/practice/playbacks', { worldId: requestedStoreId ?? storeIds[0] });
|
|
2780
|
+
const listed = await fleetRequest(name, 'GET', listPath, undefined, { workspaceId });
|
|
2781
|
+
if ('error' in listed) return listed.error;
|
|
2782
|
+
const selectedStoreId = requestedStoreId ?? storeIds[0];
|
|
2783
|
+
return textResult(practiceRunsProjection(
|
|
2784
|
+
listed.value,
|
|
2785
|
+
selectedStoreId,
|
|
2786
|
+
requestedStoreId ? 'explicit-store-id' : 'single-store',
|
|
2787
|
+
));
|
|
2788
|
+
}
|
|
2633
2789
|
case 'practice_run_status': {
|
|
2634
2790
|
const attemptId = requiredPracticeAttemptId(args);
|
|
2635
2791
|
const response = await practiceApi('GET', `/practice/playbacks/${encodeURIComponent(attemptId)}/state`);
|