# adapter-1c-mcp Thin MCP proxy for the 1C REST adapter. Target host: ```text docker.cin.su ``` Runtime URL: ```text http://docker.cin.su:8021 ``` MCP endpoint for Codex: ```text http://docker.cin.su:8021/mcp ``` The server responds with MCP protocol `2025-06-18` and returns `Mcp-Session-Id` during `initialize`. Legacy SSE endpoint: ```text http://docker.cin.su:8021/sse ``` Direct JSON-RPC endpoint for smoke tests: ```text http://docker.cin.su:8021/mcp ``` Codex config: ```toml [mcp_servers.adapter-1c-mcp] enabled = true url = "http://docker.cin.su:8021/mcp" ``` Already running Codex Desktop windows can keep the MCP tool list from their startup time. Restart Codex Desktop, or start a fresh session, after changing MCP server configuration. ## How The Adapter URL Is Passed The MCP proxy does not hard-code the 1C adapter address. Pass it with: ```text ONEC_ADAPTER_URL=http://docker-gpu.cin.su:8011 ``` Optional adapter bearer token: ```text ONEC_ADAPTER_TOKEN= ``` Timeout for adapter HTTP calls: ```text ONEC_ADAPTER_TIMEOUT_SECONDS=4 ``` These variables are configured in: ```text core/deploy/docker/adapter-1c-mcp/.env.example ``` For real deployment, create a non-committed `.env` next to the compose file and set the actual adapter URL/token there. ## Deploy Deploy both REST adapter and MCP proxy, then run live verification when a test base is available: ```powershell powershell -NoProfile -ExecutionPolicy Bypass ` -File scripts\deploy_1c_adapter_stack.ps1 ` -BaseId ``` Multiple test bases can be verified in one deploy: ```powershell powershell -NoProfile -ExecutionPolicy Bypass ` -File scripts\deploy_1c_adapter_stack.ps1 ` -BaseId , ``` Duplicate base ids are rejected before verification starts, so persisted reports are not overwritten by an accidental repeated base value. To make post-deploy checks deterministic, pass an explicit metadata object selector. This is optional; without it the smoke discovers a module-capable object automatically. ```powershell powershell -NoProfile -ExecutionPolicy Bypass ` -File scripts\deploy_1c_adapter_stack.ps1 ` -BaseId ` -ObjectGuid ` -ObjectKind ``` Saved-state preparation defaults to `ConfigSave` for the base configuration save layer. Use `-SavedStateTable ConfigCASSave` when the strict smoke should target an extension/CAS save layer instead: ```powershell powershell -NoProfile -ExecutionPolicy Bypass ` -File scripts\deploy_1c_adapter_stack.ps1 ` -BaseId ` -SavedStateTable ConfigCASSave ``` The deploy script prints Docker container summaries for both services, then the verify script prints `/health` status and `contract_version` before running the REST and MCP selector-chain smoke tests. The selector-chain smoke also checks, when a routine name is available from module metadata, that `metadata.resolve_overrides` returns `write_plan_evidence.next_resolution` for `metadata.saved_state.modules.search` with the same `base_id` and routine query, plus a public object `ref`/`kind`/`name` and semantic `layer=base_saved_state|extension_saved_state`; public follow-ups never require `ConfigSave`, `ConfigCASSave`, or `owner_guid`. The smoke then follows that resolver. If a saved-state stream exposes `write_plan_target`, the smoke composes it with `write_plan_evidence.target` and checks the resulting read-only `metadata.write.plan`; when the test base has no saved-state stream, that last composition step records `skipped_no_saved_state_target`. These selector-chain reports are written under `reports/1c-sql//selector-chain-rest-smoke.json` and `reports/1c-sql//selector-chain-mcp-smoke.json`. Each report includes a top-level `coverage` block summarizing whether override evidence was found, whether the saved-state resolver ran, whether a `write_plan_target` was available, and which steps were skipped. The verify script validates that both selector-chain report files are written, parse as JSON, pass, and include the expected `coverage` sections. Use `-RequireSelectorChainWritePlanComposition` when the test base is expected to contain a matching saved-state stream and the selector-chain smoke must fail instead of accepting `skipped_no_saved_state_target`. Verification also runs the read-only write-plan safety smoke through both REST and MCP `onec_request`; the MCP smoke also checks that live methods without `payload.base_id` are stopped by `adapter_1c_mcp_policy.v1` with `base_id_required`, and that low-level `storage.*`/`query.*` fallback calls are blocked as `diagnostic_method` unless diagnostics are explicitly requested. The verify script validates the written write-plan safety reports after each smoke. Then verification runs REST saved-state form/module write-loop smoke tests through `metadata.write`; if the test base has no pending `ConfigSave`/`ConfigCASSave` rows, those saved-state checks record `skipped_no_saved_state` and pass by default. The saved-state report files are also parsed and checked after the smoke commands. Before those smoke tests, verification generates read-only `saved-state-strict-readiness.json` and `saved-state-copy-plan.json` reports for the selected `-SavedStateTable`. The copy plan is generated through `scripts/plan_1c_saved_state_copy.py` using the same object selector arguments, so the later persisted-report check has fresh copy-preparation evidence. At the end, verification runs `scripts/check_1c_verify_reports.py` against the persisted report set, so the same report validation can be repeated offline without calling the adapter. The offline validator checks that selector-chain coverage includes `metadata.resolve_overrides` evidence, the expected `metadata.saved_state.modules.search` next step, saved-state resolution, and attempted `metadata.write.plan` composition. It also verifies write-plan safety outcomes: effective form writes must route to `metadata.write.plan`, uncontrolled replacement must be blocked, controlled replacement must be planned through `metadata.module.write_apply`, drift must be blocked, and MCP policy checks must block missing `base_id` and diagnostic fallback. Saved-state write smoke reports are checked in both modes: empty-state skips must include successful preflight counts and `skipped=true`; real write-and-rollback runs must include allowed write plans, expected apply methods, and rollback evidence. The same persisted report validator also checks `saved-state-strict-readiness.json` and `saved-state-copy-plan.json` when saved-state write smoke reports are enabled. Readiness must match the requested `base_id` and selected save-layer table; in strict mode it must be `ready=true`. The copy plan must match the requested `base_id`, resolve a concrete object, list active source rows from the matching storage family, be `plan_ready`, and show clear target collision status for `ConfigSave`/`ConfigCASSave`. The family must match the target save layer: `Config -> ConfigSave` for base changes and `ConfigCAS -> ConfigCASSave` for extension/CAS changes. The validator also checks that readiness, copy-plan target table, saved-state form smoke table, and saved-state module smoke `module_ref` table are the same. `scripts/check_powershell_scripts.py` also guards the verify/deploy wiring for these strict flags and asserts that `check_1c_verify_reports.py --self-test` covers selector-chain, safety, saved-state, and copy-plan failure classes. Persisted report validation also pins the expected JSON `schema` value for each report type, so stale or unrelated report files fail before their contents are trusted. The same validator checks report identity: each persisted JSON must match the requested `base_id`, and REST/MCP reports must match their expected `transport`. When verification provides expected endpoints, REST/MCP reports must also match the configured `endpoint_url`. To require an actual saved-state write-and-rollback instead of allowing the empty-state skip: ```powershell python scripts\check_1c_saved_state_strict_readiness.py ` --base-id ` --saved-state-table ConfigSave ` --report reports\1c-sql\\saved-state-strict-readiness.json ` --json ``` This readiness check is read-only. It checks REST adapter health, row counts in the selected save-layer table, and saved-state form/module discovery. Use `--saved-state-table ConfigSave` for the base save layer or `--saved-state-table ConfigCASSave` for the CAS/extension save layer. If it reports `blocked_no_saved_state_rows`, there are no unactivated Configurator changes in the selected save layer. To prepare a strict write test, copy the target object from the main configuration storage (`Config`/`ConfigCAS`) into the selected save layer through the approved saved-state workflow, then rerun readiness before enabling strict mode. To produce a read-only copy preparation plan for a concrete object: ```powershell python scripts\plan_1c_saved_state_copy.py ` --base-id ` --kind ` --name ` --target-table ConfigSave ` --report reports\1c-sql\\saved-state-copy-plan.json ` --json ``` The copy plan does not write SQL. It lists active storage rows for the selected object only from the matching source family, checks whether the intended `ConfigSave`/`ConfigCASSave` target already contains the same `FileName` values, and records the intended save-layer target. `--target-table ConfigSave` plans from `Config`; `--target-table ConfigCASSave` plans from `ConfigCAS`. Normal verification regenerates this file automatically before saved-state smoke tests and uses `-SavedStateTable` to pick the same target table for the copy plan, form smoke, and module smoke. Run the command manually when choosing a target object for strict readiness or when preparing evidence without the full deploy/verify flow. The offline persisted-report validator checks this file by default, so regenerate the plan whenever the chosen object, target table, or base changes. To generate the reviewed SQL preparation script from that plan without executing SQL: ```powershell python scripts\prepare_1c_saved_state_copy_sql.py ` --plan reports\1c-sql\\saved-state-copy-plan.json ` --expected-base-id ` --expected-target-table ConfigSave ` --sql-out reports\1c-sql\\prepare-saved-state-copy.sql ` --report reports\1c-sql\\prepare-saved-state-copy-sql.json ` --json ``` This generator does not call the adapter and does not write SQL. It refuses plans that are not `plan_ready`, have target collisions, or mix storage families. The generated SQL is a manual review artifact: it starts a transaction, rechecks that the save-layer target has no planned `FileName` values, copies only the planned rows with `INSERT ... SELECT`, verifies the copied row count, and commits only if those guards pass. To execute the reviewed preparation SQL, use the explicit SQL-write gate. This is not run by deploy/verify: ```powershell powershell -NoProfile -ExecutionPolicy Bypass ` -File scripts\execute_1c_saved_state_copy_sql.ps1 ` -Server ` -Database ` -User ` -Password ` -ExpectedBaseId ` -ExpectedTargetTable ConfigSave ` -IUnderstandThisWritesToSql ``` The executor validates the generated SQL report, checks that the SQL file still looks like the reviewed saved-state copy artifact, records the SQL SHA1, runs the SQL through `System.Data.SqlClient`, and immediately calls the read-only post-copy verifier. Credentials can also be supplied with `ONEC_SQL_SERVER`, `ONEC_SQL_DATABASE`, `ONEC_SQL_USER`, and `ONEC_SQL_PASSWORD`. Do not commit credentials or execution reports containing environment-specific connection details. After the SQL preparation has been executed, verify the saved-state copy read-only before enabling strict write smoke: ```powershell python scripts\verify_1c_saved_state_copy.py ` --plan reports\1c-sql\\saved-state-copy-plan.json ` --expected-base-id ` --expected-target-table ConfigSave ` --report reports\1c-sql\\saved-state-copy-verify.json ` --require-ready ` --json ``` Before the SQL preparation is executed, this verifier is expected to report `blocked_missing_target_rows`. After preparation it must report `ready=true` by comparing the save-layer `FileName`, `PartNo`, byte sizes, and `BinarySHA1` values against the reviewed active-source rows from the copy plan. Also generate the guarded cleanup script before executing the preparation SQL, so there is a reviewed way to remove the prepared working-copy rows later: ```powershell python scripts\prepare_1c_saved_state_cleanup_sql.py ` --plan reports\1c-sql\\saved-state-copy-plan.json ` --expected-base-id ` --expected-target-table ConfigSave ` --sql-out reports\1c-sql\\cleanup-saved-state-copy.sql ` --report reports\1c-sql\\cleanup-saved-state-copy-sql.json ` --json ``` The cleanup SQL deletes only the planned `FileName`/`PartNo` rows from the selected save layer, and only when their current `BinarySHA1` still matches the reviewed copy plan. It rolls back if the rows are missing, extra/mismatched, or if the deleted row count differs from the plan. ```powershell powershell -NoProfile -ExecutionPolicy Bypass ` -File scripts\deploy_1c_adapter_stack.ps1 ` -BaseId ` -RequireSavedStateWriteSmoke ``` To require selector-chain evidence to resolve all the way to a concrete read-only `metadata.write.plan` composition: ```powershell powershell -NoProfile -ExecutionPolicy Bypass ` -File scripts\deploy_1c_adapter_stack.ps1 ` -BaseId ` -RequireSelectorChainWritePlanComposition ``` To skip saved-state write-loop checks entirely: ```powershell powershell -NoProfile -ExecutionPolicy Bypass ` -File scripts\deploy_1c_adapter_stack.ps1 ` -BaseId ` -SkipSavedStateWriteSmoke ``` To skip only the read-only write-plan safety smoke: ```powershell powershell -NoProfile -ExecutionPolicy Bypass ` -File scripts\deploy_1c_adapter_stack.ps1 ` -BaseId ` -SkipWritePlanSafetySmoke ``` To validate the latest persisted reports without contacting REST or MCP: ```powershell python scripts\check_1c_verify_reports.py --base-id ``` Add `--rest-adapter-url --mcp-url ` when the persisted REST/MCP reports should be pinned to specific endpoints. Add `--saved-state-table ConfigSave` or `--saved-state-table ConfigCASSave` when the persisted saved-state reports must be pinned to a specific save-layer table. Add `--max-report-age-seconds ` when the persisted reports must also be fresh enough for a deployment gate. Use `--skip-saved-state-copy-plan` only when intentionally validating an older report bundle that does not include `saved-state-copy-plan.json`. To run the offline validator's synthetic soft/strict self-test: ```powershell python scripts\check_1c_verify_reports.py --self-test ``` To run the whole offline/static verification-stack preflight: ```powershell python scripts\check_1c_adapter_verification_stack.py --base-id ``` The verification-stack preflight passes the default REST/MCP endpoint URLs to the persisted report validator. Override them with `--rest-adapter-url` and `--mcp-url` for non-default deployments. It also passes `--saved-state-table`, defaulting to `ConfigSave`, so persisted copy-plan/form/module reports must match the intended save-layer table. Pass multiple base ids after `--base-id` to validate several persisted report directories in one run. Use `--max-report-age-seconds` to reject stale report files during the verification-stack preflight. To save a machine-readable verification-stack summary: ```powershell python scripts\check_1c_adapter_verification_stack.py ` --base-id ` --json ` --report reports\1c-sql\\adapter-verification-stack-check.json ``` The saved stack report keeps per-command return codes, compact parsed summaries for JSON-producing checks, and truncated stdout/stderr tails for diagnostics. For persisted verify-report checks, the parsed summary also includes per-base REST/MCP selector-chain composition status, write-plan safety check counts, and saved-state write smoke status, including the saved-state copy-plan target, source-row count, and target collision status. To deploy without live verification: ```powershell powershell -NoProfile -ExecutionPolicy Bypass ` -File scripts\deploy_1c_adapter_stack.ps1 ` -SkipVerify ``` Low-level MCP-only deploy: ```powershell docker --host ssh://docker.cin.su compose ` --env-file core\deploy\docker\adapter-1c-mcp\.env.example ` -f core\deploy\docker\adapter-1c-mcp\compose.yaml ` up -d --build ``` Container name: ```text adapter-1c-mcp ``` ## Health ```powershell Invoke-RestMethod http://docker.cin.su:8021/health docker --host ssh://docker.cin.su ps --filter name=adapter-1c-mcp docker --host ssh://docker.cin.su logs --tail 80 adapter-1c-mcp ``` Smoke test MCP initialize: ```powershell $body = @{ jsonrpc = "2.0" id = 1 method = "initialize" params = @{ protocolVersion = "2025-06-18" capabilities = @{} clientInfo = @{ name = "smoke"; version = "1" } } } | ConvertTo-Json -Depth 10 Invoke-WebRequest ` -Uri "http://docker.cin.su:8021/mcp" ` -Method Post ` -ContentType "application/json" ` -Headers @{ Accept = "application/json, text/event-stream" } ` -Body $body ``` ## Tools The MCP proxy exposes a small stable tool surface: ```text onec_health onec_help onec_request onec_job_get onec_job_cancel access_role_users access_role_profiles access_role_audit_export access_role_audit_analyze access_user_explain access_users_search access_object_explain access_keys_query access_object_keys_resolve access_object_roles access_object_subjects access_rls_discover ``` Use `onec_request(method, payload)` for uncommon or newly added adapter methods until a dedicated alias is useful enough to keep stable. The `access_*` tools are lightweight aliases for common access-audit workflows; they only forward to REST adapter methods such as `access.role.users` and keep all BSP/access-rights logic in the REST adapter. For object access checks, pass object names/public refs first; the REST adapter resolves GUIDs, SQL numbers, BSP identifiers, synonyms, and readable role-rights names internally. Example: ```powershell python scripts\smoke_1c_access_object.py ` --base-id upo_test ` --ref "РегистрСведений.УОП_АктуальныеСпецификации" ` --action write ``` Use `access_object_roles` or `access_object_subjects` for the question "which roles/users can read or write this metadata object". Do not depend on `metadata.objects.list kind=Role`: some live bases do not expose roles as regular metadata objects through that route. For BSP data-access keys, keep the metadata object and concrete data record separate: ```json { "base_id": "upo_test", "kind": "object", "object_ref": "Справочники.Номенклатура", "record_ref": "00112233445566778899AABBCCDDEEFF" } ``` Here `kind=object` is the `access_keys_query` area, not the metadata kind. `object_ref` is resolved to the internal BSP SQL number and `record_ref` to the record id. The same public pair works with `access_object_keys_resolve` and `access_object_explain`; do not invent `object_sql_number` in MCP code. For BSP role-right checks, `action=write` means add or modify rights. Read-only roles must not be returned for `write`; query `action=read` separately when you need visibility roles. Returned permissions keep `source_fields` from `ПраваРолей` so suspicious mappings can be verified against the live base. `access.snapshot.extract` also supports this access graph and defaults to the BSP extractor preset when `queries` are not supplied. Passing `preset=bsp` explicitly is still fine, but the old "No extractor queries were provided" discovery response should not appear for a normal BSP base. When `access_object_subjects` is called with `include_access_key_scope=true`, the regular `limit` only trims returned roles/profiles/groups/users. Scope diagnostics use separate controls: `access_key_scope_subject_limit` limits how many matched groups/users are checked, and `access_key_scope_limit` limits rows read from each BSP access-key extractor. Check `access_key_scope.coverage` and `access_key_scope.truncated` before treating the scope sample as complete. For local audit artifacts, use the workspace script: ```powershell python scripts\export_1c_access_role_audit.py ` --base-id upo_test ` --role "запись изменение номенклатура поставщиков" ` --user-threshold 30 ``` It writes CSV, JSON export, analysis JSON, and a summary file under `reports/1c-access//`. By default it also writes a self-contained HTML report with findings, counters, artifact links, and a filterable user table; pass `--no-html` to skip it. Architecture contract: - The REST adapter owns 1C behavior, payload validation, decoding, owner resolution, RAG/tool-facing data shape, and method documentation through `help.methods`. - MCP is a transport proxy: JSON-RPC/MCP framing, adapter URL/token handling, generic `onec_request`, job polling/cancellation helpers, and lightweight agent-safety checks such as requiring `base_id` for live database methods. - Do not add method-specific 1C business logic to MCP. Put it in the adapter, expose it through `/rpc`, and make it discoverable via `help.methods`. - Do not register an MCP unified/composite handler with the same name as an adapter method; `onec_request(method=...)` must call the adapter method, not shadow it inside MCP. - When adding a new adapter method, verify it through MCP with `onec_request({"method": "...", "payload": {...}})`. MCP should not require a schema edit for ordinary adapter growth. - Run `python scripts/check_1c_mcp_adapter_contract.py` before release; it verifies that `onec_request` stays generic and that every method listed by the REST adapter is forwarded through `/rpc`. Example: ```json { "method": "metadata.object.get", "payload": { "base_id": "", "kind": "document", "name": "ПриходнаяНакладная", "view": "merged" } } ``` Do not copy placeholder or sample `base_id` values from documentation into real requests. For live database methods, get `base_id` from the current project, user request, environment, or another authoritative context. ## Agent Request Policy The MCP proxy blocks live database methods without `payload.base_id` before calling the REST adapter. This is intentional: agents must not probe metadata, modules, extensions, queries, storage, or code without a concrete target base. Affected method families include: ```text metadata.* modules.* code.* templates.* diagnostics.* extensions.* query.* storage.* schema.* codec.* ``` Allowed without `base_id`: ```text onec_help / help.methods onec_health without a base for generic service health adapter.job.get / adapter.job.cancel ``` Agent rules: - If `base_id` is unknown, ask for it or obtain it from project context. - For object-scoped calls, use one of the public selector shapes supported by the adapter: `ref`, `kind` + `name`, `guid`, or MCP-friendly `object_type`/`object_name`/`object_guid`. Do not add MCP-side conditions for concrete object names. - If a prior result contains `module_ref`, `module_id`, GUID, or read selector, use direct read methods before global search. - If a search result contains `read_selector.method`, call that method with the selector payload. `code.search` selectors point to `code.read`; `modules.search` selectors point to `modules.read`. - If a result contains `related_selectors`, prefer those payloads for the next object-scoped call. They preserve `kind`/`name`/`guid` and include `ref` when the adapter knows the canonical object kind and name. - When `modules.search` or `code.search` resolves a module owner, keep both the public owner selector (`ref`, `kind`, `name`, `guid`) and the opaque `module_ref` in the next read payload. `module_ref` is the direct read handle; `ref` makes the owner clear to the agent and later calls. - When narrowing `code.search` to one module, pass `module_ordinal` together with the object selector. The adapter response should remain a public `onec_code_search.v1` object with `item.read_selector`, not a low-level tuple or storage result. - For BSL edits, prefer high-level `metadata.write` with a 1C canonical path, `routine_text`, and `routine_operation`. Do not ask the user for SQL/save gates: the adapter prepares saved-state when needed, writes only to the saved-state working layer, and does not activate changes. Use `metadata.form.command_button.write` for the complete form command + visible button + handler workflow. `code.write` remains a compatibility shortcut for simple module edits. - For a metadata object's standard `synonym` or `comment`, call generic `onec_request` with `method=metadata.object.property.write`, a public `ref`/`kind` + `name`, and `allow_saved_state_write=true`. Prefer `execution_mode=plan` first. The adapter resolves GUIDs and serialized paths; MCP callers must not pass SQL tables or file names. Object rename and adding a new synonym locale are intentionally unsupported. - For an existing requisite, tabular section, dimension, or resource, add a public `member_ref` such as `Catalog.Номенклатура.Attribute.Артикул`. When only `member_kind` + `member_name` is used and several identities match, preserve the adapter's `ambiguous` result and retry with the full member path. - To add a requisite, call `metadata.object.member.add` through `onec_request` with a full `template_member_ref` from the same object and the new public name/synonym. Never invent a GUID, Config table, collection path, or type descriptor in MCP code; the new requisite inherits type/settings from the named template. - The same method adds a tabular-section column when `template_member_ref` contains the full `...TabularSection..Attribute.` path. Keep the complete path so duplicate checks and generated identity remain scoped to that table part. - For unresolved module owners, inspect `diagnostics.owner_resolution` and `counts.owner_scan_limit_hit`; narrow by `kind`/`name`/`guid` or increase `owner_scan_limit` before falling back to broader searches. - Do not treat `not_found` from `metadata.definition.find` or scoped search as proof that code is absent in extensions or ConfigCAS. - Treat `partial`, `truncated=true`, scan limits, and timeouts as incomplete evidence. Offline selector-chain smoke: ```powershell python scripts\smoke_1c_mcp_selector_chain.py --json --no-report ``` Saved-state BSL write smoke: ```powershell python scripts\smoke_1c_code_write_saved_state.py ` --adapter-url http://docker-gpu.cin.su:8011 ` --base-id ` --extension ` --object-type CommonForm ` --object-name ` --routine-name ` --json ``` This smoke performs idempotent `code.write mode=apply` checks with the current routine text, a unique `old`/`new` fragment, and the current full `module_text`. It then verifies `code.read state=working`, `code.read state=both`, marker-hiding for saved form modules, and saved-state form indexing. Every write step must report `write_mode.target=saved_state` and `activation_state=not_activated`. Agent working-view report: ```powershell python scripts\report_1c_agent_working_view.py ` --adapter-url http://docker-gpu.cin.su:8011 ` --base-id ` --extension ` --object-type CommonForm ` --object-name ` --routine-name ` --json ``` This read-only report shows the form names that an agent sees in the working/save layer and verifies that `code.read state=working` and `state=both` prefer `saved_state` when saved code exists. The concise agent-facing coding rules are kept in `docs/runbooks/1c-agent-coding-contract.md`. Run this with the contract checks before release. It validates generic agent routes through `onec_request` and rejects concrete object names in selector examples. Optional live selector-chain smoke against a real adapter/base: ```powershell python scripts\smoke_1c_mcp_selector_chain.py ` --live ` --transport rest ` --adapter-url http://docker-gpu.cin.su:8011 ` --base-id ` --json ` --no-report ``` To verify both deployed layers with one command: ```powershell powershell -NoProfile -ExecutionPolicy Bypass ` -File scripts\verify_1c_adapter_deployment.ps1 ` -BaseId ``` By default this also writes `reports/1c-sql//code-write-saved-state-rest-smoke.json` and `reports/1c-sql//code-write-saved-state-mcp-smoke.json` when the default saved-state code-write target exists. The REST verification also writes `reports/1c-sql//agent-working-view.json` to pin the save-first working view that agents should use for coding. Use `-RequireCodeWriteSavedStateSmoke` to make that smoke mandatory, or `-SkipCodeWriteSavedStateSmoke` to skip it for bases where the scenario is not available. Pass multiple base ids to run the same REST and MCP checks against each base: ```powershell powershell -NoProfile -ExecutionPolicy Bypass ` -File scripts\verify_1c_adapter_deployment.ps1 ` -BaseId , ``` Use `-ObjectRef`, or `-ObjectKind` with `-ObjectName`/`-ObjectGuid`, to verify a specific module-capable metadata object instead of auto-discovery. Use `-SavedStateTable ConfigSave` or `-SavedStateTable ConfigCASSave` to choose which save-layer table is used by the copy plan and saved-state write smokes. Add `-RequireSelectorChainWritePlanComposition` when the selected base/object must have a saved-state stream that lets the selector-chain smoke compose a concrete read-only `metadata.write.plan`. The same strict mode also requires the write-preflight smoke to discover both an extension form and an extension module by public names (`extension/ref/form/member` and `extension/ref/form/module/stream_ordinal`), compose allowed plans, and prove that the repository and support gates use the same resolved `extension:` layer. Module search restores the public extension name from `ConfigCASSave`; it never returns the storage GUID as the caller-facing selector. The smoke then submits each public selector with a deliberately different GUID and requires a read-only `blocked / extension_selector_conflict` result, so a legacy permissive repository profile cannot authorize a mismatched layer. Run both checks directly with `scripts/smoke_1c_write_preflight.py --require-name-first-extension-form --require-name-first-extension-module`. To exercise the MCP proxy itself, switch transport and URL: ```powershell python scripts\smoke_1c_mcp_selector_chain.py ` --live ` --transport mcp ` --mcp-url http://docker.cin.su:8021 ` --base-id ` --json ` --no-report ``` Live mode discovers a module-capable object from metadata lists and then checks `adapter.help.methods -> metadata.definition.find -> related_selectors.modules -> metadata.object.modules -> modules.read -> code.search -> item.read_selector -> code.read` using the returned selector and a token derived from module text or routine metadata. The `adapter.help.methods` step verifies live REST `contract_version` and `selector_capabilities`, so stale REST adapter images fail before the longer chain. MCP transport also performs `initialize`, checks `tools/list` for the same `contract_version` and the generic `onec_request` selector schema, keeps `Mcp-Session-Id`, and sends adapter calls through `tools/call` + `onec_request`. This catches stale MCP proxy images where REST works but agents still see old tool descriptions. Do not commit real base ids or captured reports from live runs. - Avoid increasing global search limits when a direct selector is already available. - Do not request `include_storage=true` merely to read a module found by search; use the public `read_selector` first. The request is proxied to the REST adapter through `POST /rpc`: ```json { "method": "metadata.object.get", "payload": {} } ``` The MCP proxy intentionally does not know adapter-specific 1C methods. Add new methods in the REST adapter and expose them through `help.methods`; MCP stays unchanged unless the MCP transport itself changes.