# Smedc MCP

> 上传和查询企业数据中枢（SMEDC）中的文件与资料：当员工要求把文件/文档/表格上传到 企业数据中枢、企业资料中枢、企业知识库或企业数据库，或想基于已上传的企业资料提问业务问题时使用。 用户要求更新 smedc-mcp 或 smedc-mcp-skill 这个 skill 时也使用本技能。 用户询问 SMEDC 的配套分析、报表或扩展 skill 时也使用本技能。 Also use when users ask about optional SMEDC analysis, reporting, or extension skills. Also covers updating this skill from its official GitHub source and installing, configuring, and authenticating the official SMEDC remote MCP launcher (api.smedatacenter.xyz); accesses SMEDC through the launcher only and never exposes employee credentials or service infrastructure.

- Skill: `yinxiaoyu-1998/smedc-mcp` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add yinxiaoyu-1998/smedc-mcp`
- Raw SKILL.md: https://api.skillmd.com/api/skills/yinxiaoyu-1998/smedc-mcp/raw
- Safety review: pending (external: skill-scanner PASS, skillspector FAIL)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: YinXiaoyu-1998 (https://skillmd.com/u/yinxiaoyu-1998)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/yinxiaoyu-1998/smedc-mcp

---


# SMEDC MCP

Use SMEDC only through its official remote MCP launcher. This skill is the
current-user installation and recovery runbook for an employee-owned agent; it is not a
service-operations runbook.

The approved service origin is `https://api.smedatacenter.xyz`. The approved launcher is
the exact npm package `smedc-mcp-launcher@0.5.0`. Do not substitute another
origin, package, tag, or version. In particular, never install npm `latest` and never let
the launcher update itself. This pin governs launcher installation, not fetching a newer official
copy of this skill; after a skill refresh, read the newly verified copy for its current pin.

## Update This Skill

The canonical skill name is `smedc-mcp`; `smedc-mcp-skill` is its repository
name and a recognized user-facing alias. “帮我更新 smedc-mcp-skill 这个 skill” means
refresh this skill's files from its official source. The request authorizes that local update;
do not ask which kind of update the employee means when they explicitly name the skill.

Official source: [YinXiaoyu-1998/smedc-mcp-skill](https://github.com/YinXiaoyu-1998/smedc-mcp-skill),
directory `skills/smedc-mcp/`, latest commit on the repository's default branch
(currently `main`). A marketplace listing, SMEDC login, MCP connection, and an approved
new launcher pin in the old installed skill are not prerequisites for refreshing the skill.
Use ordinary Git/HTTPS and local file tools for this maintenance task.

Follow [the skill update procedure](references/update-skill.md) for source retrieval, backup,
complete-directory replacement, verification, and host reload. A skill-only update does not
authorize a launcher upgrade. For an authorized launcher update, first refresh this skill if its
pin is older than the server recommendation, then follow Official Install Or Update using the
newly verified exact pin. Never derive a new approved pin from server metadata alone.

## Optional Companion Skills

Companion skills are independently maintained workflows that use SMEDC MCP data. They
are not bundled with this core skill and are not required for ordinary SMEDC work. This
skill continues to own launcher installation, authentication, uploads, and authorization-safe data
access; a companion owns its business-specific analysis and deliverables.

- [`smedc-business-analysis`](https://github.com/YinXiaoyu-1998/smedc-companion-skills)
  generates organization-backed operating diagnoses, weekly reports, and monthly reports. When the
  employee asks for one of those deliverables and the companion is installed, use it together with
  this skill instead of creating the report here.
- [`smedc-delivery-ledger`](https://github.com/YinXiaoyu-1998/smedc-companion-skills)
  renders the standard delivery-ledger table, exports the approved CSV, and guides receipt-linked
  quarantine-certificate photo operations. When the employee asks for those ledger deliverables and
  the companion is installed, use it together with this skill instead of recreating ledger-specific
  presentation logic here.
- If the matching companion is not installed, explain that it is optional, identify its official
  source, and offer to install it. Install it only when the employee explicitly authorizes its
  installation or has already requested that named companion or all recommended companions.
  Never install it silently during a core-skill install, update, login, upload, or query request.
- Updating this skill does not update a companion, and updating a companion does not change this
  skill or the launcher pin. Follow each repository's own update guidance.

Do not copy companion-specific report logic, dataset transformations, or business conclusions into
this base skill. Keep the core boundary below and route only the matching employee request.

## Hard Boundaries

- The employee enters an account password only in the SMEDC browser page. Never ask
  for, accept, read, store, paste, or transmit an email/password, access token, durable
  credential, authorization code, raw `Authorization` header, or credential-store record.
- For SMEDC service access, use only launcher configuration and tools. Do not call
  SMEDC API endpoints directly and do not operate its API, database, Qdrant, storage,
  Docker, worker, cloud resources, or deployment.
- Do not create reports, dashboards, or final business conclusions. Return only tool-visible
  records, statuses, and evidence within the employee's backend-authorized scope.
- Do not provide an organization ID. The service derives organization and confidentiality access
  from the authenticated Employee Account; never infer hidden data from a forbidden/not-found result.
- The launcher stores its durable credential only in the operating-system secure store. Never
  put credentials in configuration, environment variables, arguments, ordinary files, logs, or
  chat.

## Tool Discovery

The launcher is a standard stdio MCP server. When the invoking host is configured correctly,
its SMEDC tools appear in the host's native MCP tool list; the agent does not need to
discover them by hand.

- Never hand-craft JSON-RPC (`initialize`, `ping`, `tools/list`, `tools/call`) against the
  launcher process. Use the host's MCP integration and its tool list.
- The launcher registers the complete MCP tool contracts bundled into its published package.
  It does not safely invent contracts for service tools added later. Discover the available tools
  from the connected host; if the server requires a tool absent from that list, update to the exact
  launcher version approved by this skill before retrying.
- Call `list_structured_datasets` before using any structured dataset; use `dish_catalog`,
  `delivery_ledger`, or `supplier_catalog` only when discovery advertises it and its fields.
- In structured dataset discovery, `canonicalName` is the queryable field name. `sourceColumn` and
  `aliases` are not accepted directly by `query_structured_dataset`; use them to map the user's
  wording or source-table headers to `canonicalName`, and to choose friendly table headers when
  presenting results.
- Discovery also advertises each field's operators and capabilities. A field can be present
  without supporting every structured-query role; use only fields whose registry capabilities allow
  the intended filtering, sorting, grouping, or aggregation.
- Use `describe_structured_dataset_coverage` when the employee needs to know which uploaded
  structured sources are currently readable for a dataset before deciding whether a query is scoped
  enough. Treat coverage as source facts only, not a service-side completeness judgment.
- Discovery metadata is not an upload template. Do not rewrite, reshape, normalize, rename
  headers, duplicate receipt metadata into item rows, or generate a replacement CSV/XLSX to make a
  file match registry fields unless the employee explicitly asks for a separate local conversion
  task.
- If SMEDC tools are not visible: run the pinned launcher's credential-free self-check
  (see Official Install Or Update), verify the invoking agent's MCP entry (`codex mcp list` /
  `codex mcp get smedc` or the host equivalent), reload or restart the host, then
  recheck its tool list. Only if the entry is missing or the self-check fails, follow the focused
  recovery below. Do not debug the launcher protocol or service internals.
- If a self-check reports `recommendedUpdateAvailable: true` (the server recommends a launcher
  version newer than the installed one), tell the employee a newer launcher is recommended and
  offer to update. If that update is already requested, proceed without asking again. Refresh
  stale skill guidance through Update This Skill before choosing the approved exact launcher
  version. Follow Official Install Or Update; never update silently in the background.

## Request Limits

Keep tool input within the public service contract:

- ordinary upload content is at most 50 MiB after Base64 decoding. `business` and `dishes` are the
  exception: path-mode multipart upload streams one original CSV/XLSX up to the current 2 GiB
  service limit without placing file bytes in the MCP argument. A basename-only filename is at
  most 255 characters;
- an evidence title is at most 512 characters and `sourceSystem` is at most 255 characters;
- structured `enterpriseName` and `idempotencyKey` are each at most 255 characters;
- receipt IDs and quarantine-certificate `idempotencyKey` values are each at most 255 characters;
- `confidentialityLevel`, when supplied, is an integer from `0` through `3`; omit it to use the
  service default of `0`;
- an evidence question is at most 4,000 characters; each evidence filter ID is at most 64
  characters, with at most 100 IDs in each filter group;
- an opaque cursor is at most 4,096 characters, and each structured-query string filter value is
  at most 32,767 characters.
- a structured query returns at most 200 rows or aggregate groups per page, with up to 50 selected
  fields, 2 sort fields, 4 group-by fields, 12 explicit aggregates, 20 filter conditions, 100 `in`
  values, and boolean nesting depth 3.

If a tool rejects an input at one of these boundaries, report the validation error and ask the
employee to shorten the text, reduce filters, or provide a corrected source. Never manually split
`business` or `dishes`; the service validates and partitions the original file atomically. Never
split `dish_catalog`: keep one complete snapshot and ask the employee to remove unrelated
sheets/columns outside the catalog schema, use a service-supported larger limit, or seek operator
help. Never silently truncate a title, key,
query, cursor, filter value, or file.

Prefer `file.encoding:"path"` uploads with the file's absolute local path so the launcher reads the
file locally and the model never emits payload bytes. Inline `file.encoding:"base64"` remains
subject to the ordinary 50 MiB service ceiling and much smaller host tool-argument caps. For
`business` and `dishes`, path mode is required for the multipart flow described below.

## Upload Completion And Status Polling

Treat every text/evidence or row-query structured-table upload response with HTTP `202` as accepted
for background processing, not as a completed upload. Keep the returned `documentId`; for a
row-query structured upload also keep `importBatchId`. Poll `get_evidence_document_status` or
`get_import_status` after
**2 seconds, then 5 seconds, then 10 seconds, then every 15 seconds**, for at most **10 minutes**.

- Tell the employee an upload succeeded only after its terminal success state: evidence is
  `active/ready`; a structured import is `importBatch.status=applied` (with the returned document
  and processing views complete). Never call a queued/pending response successful.
- On terminal `rejected` or `failed`, summarize only safe tool-returned errors and give correction
  advice, usually by asking the employee for a corrected source file or metadata. Do not silently
  rewrite and re-upload the file yourself. Never expose internal exceptions, stacks, credentials,
  or infrastructure details.
- At 10 minutes with no terminal state, report **still processing**, include the Document and
  ImportBatch IDs when present, and say the employee can check later with the corresponding status
  tool. This is not a failure.
- Do not re-upload instead of polling. Upload retries must follow idempotency rules: reuse a
  structured idempotency key only for the exact same file bytes and metadata; use a new key only
  after the employee intentionally corrects or changes the upload.

For `business` and `dishes`, keep `partitionImportJobId` and poll
`get_partition_import_status`. For a source file larger than 50 MiB, check first after 2 minutes,
then every 2 minutes, for at most 20 minutes; this replaces the ordinary polling schedule above.
Tell the employee once that large-file processing may take 10–20 minutes, then use a passive wait
when the host provides one. Do not narrate unchanged `queued` or `processing` states between
checks. For a source file at or below 50 MiB, use the ordinary polling schedule above.
`published` is the only success state;
`rejected`, `failed`, `cancelled`, and `expired` are terminal non-success states. A `queued` or
`processing` response is not complete. Exact-repeat uploads may return the existing published job;
same-key requests with different bytes or metadata are conflicts, not retries.

## Business And Dishes Partition Uploads

`business` and `dishes` use an atomic source-to-partitions workflow. Upload the employee's original
CSV/XLSX exactly once with `upload_structured_dataset`; do not inspect row count to decide whether
to split, rewrite, convert, or Base64-encode it.

- Use `file.encoding:"path"` with an absolute path, `dataset`, `enterpriseName`, inclusive
  `startDate` and `endDate` in `YYYYMMDD`, and a stable `idempotencyKey`. Optionally supply
  `confidentialityLevel`; otherwise the service uses `0`.
- The launcher streams the file through bounded multipart upload. The source may be up to the
  service's current 2 GiB limit; the model and MCP request never contain the file bytes or storage
  upload URLs.
- The service validates the complete source and publishes all daily store partitions atomically.
  If any row or partition fails, nothing from that source replaces live data. On success, matching
  organization + enterprise + dataset + store + date partitions replace prior content, including
  its confidentiality level.
- Keep `partitionImportJobId` and follow the partition status polling rules above. Do not query or
  download from a job until its status is `published`.
- `query_structured_dataset` is not available for these datasets and returns
  `DATASET_REQUIRES_PARTITION_EXTRACT`. Use `describe_structured_dataset_coverage`, then call
  `download_structured_partitions` with `dataset`, the exact coverage `enterpriseName`, inclusive
  `startDate`/`endDate` in `YYYYMMDD`, and optional merchant IDs in `storeIds`.
- The launcher consumes presigned links internally, verifies each CSV, and returns
  `localDirectory`, dataset/window metadata, counts, and local file names. Never expose or request
  presigned links. The calling analysis workflow owns the returned scratch directory and must
  delete that exact directory in `finally`; it must not delete broader temp or report directories.

## Dish Catalog Snapshot Uploads

Use this path only when `list_structured_datasets` reports `dish_catalog` as available. It is a
complete, append-only menu snapshot rather than a sales/business date-window dataset.

- Call `upload_structured_dataset` with `dataset: "dish_catalog"`, `snapshotDate: "YYYYMMDD"`,
  `enterpriseName`, a stable `idempotencyKey`, and the CSV/XLSX file. Optionally include an
  explicit `confidentialityLevel`; otherwise it is `0`. Do not include `startDate` or `endDate`.
- Treat the uploaded file as the full directory for that date. Do not split it into CSV parts,
  upload only changed rows, use the service to merge it with another file, or describe a partial
  file as a complete catalog.
- The service validates catalog headers, sheets, and row values after upload. If validation rejects
  the upload, summarize the safe returned errors and ask for a corrected source file or explicit
  local-conversion instruction; do not pre-normalize or regenerate the catalog file from registry
  metadata.
- The organization can upload historical snapshots out of date order, but only one non-archived
  snapshot may occupy a date. For a same-date correction with different content, the existing
  snapshot must be archived through the authorized maintenance path before a new upload. Uploading
  a newer snapshot does not archive or replace older history.
- After `importBatch.status=applied`, query catalog rows through the discovery-reported
  `snapshot_date` field. Do not infer a current/latest menu, a diff, or added, removed,
  discontinued, or other cross-snapshot status.

## Delivery Ledgers And Supplier Catalogs

For `delivery_ledger` and `supplier_catalog`, call `upload_structured_dataset` with `file`,
`enterpriseName` and `idempotencyKey`. Optionally include an explicit `confidentialityLevel`.
Do not send `startDate`, `endDate`,
or `snapshotDate`.

- `delivery_ledger` accepts one complete CSV/XLSX delivery receipt per file. The receipt ID
  and date are extracted by the service, and each item row becomes one ledger row. Upload the
  original receipt file as provided, even when receipt-level fields appear in header rows rather
  than in the item table. Do not generate a normalized CSV with repeated receipt metadata. The
  normalized receipt ID is the organization-scoped natural idempotency key, so different content
  for the same receipt is a conflict rather than an overwrite.
- For delivery-ledger queries, use the `list_structured_datasets` registry's `canonicalName`,
  `sourceColumn`, and `aliases` instead of guessing English field names. Paper-ledger terms such as
  `进货数量`, `进货金额`, and `供货单位名称` are aliases for the matching fields; resolve them to
  `purchase_quantity`, `purchase_amount`, and `supplier_name` before querying.
- `supplier_catalog` is the current supplier snapshot used for delivery-ledger enrichment. Upload
  the provided supplier catalog file as-is; do not rewrite it locally to match registry metadata.
  The service validates required and optional columns after upload. The latest successfully applied
  snapshot is current; older history is not a fallback, and an in-progress, failed, or rejected
  upload cannot replace it.
- Keep the returned `importBatchId` and poll `get_import_status` until
  `importBatch.status=applied` before querying. A queued or pending response is not success.
- In delivery detail queries, `supplier_contact_phone` and `supplier_unit_address` are selectable
  dynamic fields only; they cannot filter, sort, group, or aggregate. They may be `null` when no
  current catalog is available or visible, no exact match exists, the source value is blank, or the
  supplier name is ambiguous. Enrichment never changes the authorized ledger page or falls back to
  an older catalog.
- Select `source_document_id` on detail-row structured queries when the employee needs the
  original uploaded receipt file. This field is not returned by default and cannot filter, sort,
  group, or aggregate.

## Quarantine Certificates And Source Downloads

Use quarantine-certificate tools only for animal quarantine certificate images that should be
linked to delivery-ledger receipt IDs. The service does not inspect whether the photo actually
looks like a certificate.

- Upload with `upload_quarantine_certificate`: provide one JPG/JPEG/PNG file, one `receiptId`, and
  one stable `idempotencyKey`. Optionally include an explicit `confidentialityLevel`; otherwise it
  is `0`. Use `file.encoding:"path"` when possible. If the employee gives several photos for the
  same receipt, call the tool once per photo.
- `receiptId` is the public business key for both delivery ledgers and certificates. The service
  trims and uppercases it. Do not call it `receiptNumber`, do not treat it as a count, and do not
  require the corresponding delivery ledger to already exist.
- Query with `query_quarantine_certificates` using explicit `receiptIds` only. It returns one group
  per requested receipt ID, each with zero or more certificates. An empty group means no visible
  matching certificate; do not infer whether a hidden one exists.
- Archive with `archive_quarantine_certificates`. Use `sourceDocumentId` for a single visible
  certificate. Only admins may archive by `receiptId`, which archives all visible certificates
  under that receipt ID.
- For downloading originals, call `get_source_document_download_url` with a visible
  `sourceDocumentId`. The result is a 24-hour attachment link; return the link to the employee
  rather than fetching or proxying the file bytes yourself.

## Official Install Or Update

An employee may ask in natural language to install, update, or repair SMEDC. The
employee does not need to run these commands personally. Agents should also offer an update when
a self-check reports `recommendedUpdateAvailable: true` (see Tool Discovery). Work only for the
current OS user and only on the invoking agent's configuration.

1. Confirm the host is macOS or Windows and that the user authorizes this current-user install.
   Run `node --version` and `npm --version`. Require Node.js major version **22 or newer** and a
   working npm. If Node.js is missing or older than 22, install or upgrade Node.js/npm for the
   current user before continuing; do not use administrator privileges or alter unrelated tools.
2. Use the fixed platform directory:

   | Platform | Launcher directory                                             |
   | -------- | -------------------------------------------------------------- |
   | macOS    | `~/Library/Application Support/SMEDC/launcher/versions/0.5.0/` |
   | Windows  | `%LOCALAPPDATA%\\SMEDC\\launcher\\versions\\0.5.0\\`           |

3. Install or repair the exact package idempotently. Substitute only the platform directory
   above; do not add credentials or a global install:

   ```sh
   npm install --prefix "<launcher-directory>" --save-exact smedc-mcp-launcher@0.5.0
   ```

4. Preserve the existing installation if the same pinned package is already present. For an
   approved update, install the newly approved exact version into its own versioned directory,
   update the one launcher path in the invoking agent's MCP entry, then run the self-check.
   Updating does not delete the secure-store session or unrelated MCP servers.
5. Run the installed launcher's credential-free self-check before changing or declaring an MCP
   configuration healthy:

   ```sh
   SMEDC_BASE_URL=https://api.smedatacenter.xyz \
     "$HOME/Library/Application Support/SMEDC/launcher/versions/0.5.0/node_modules/.bin/smedc-mcp-launcher" self-check
   ```

   ```powershell
   $env:SMEDC_BASE_URL = "https://api.smedatacenter.xyz"
   & "$env:LOCALAPPDATA\SMEDC\launcher\versions\0.5.0\node_modules\.bin\smedc-mcp-launcher.cmd" self-check
   ```

   The stable self-check contract is safe machine-readable JSON with this shape:

   ```json
   {
     "ok": true,
     "launcherVersion": "0.5.0",
     "serviceOrigin": "https://api.smedatacenter.xyz",
     "platform": "<safe platform>",
     "secureStore": {
       "available": true,
       "durableCredentialPresent": false
     },
     "server": {
       "reachable": true,
       "metadataCompatible": true,
       "minimumLauncherVersion": "<safe version>",
       "recommendedLauncherVersion": "<safe version>",
       "recommendedUpdateAvailable": false
     },
     "mcp": {
       "handshake": "ok"
     }
   }
   ```

   `mcp.handshake` is `ok`, `not_authenticated`, or `unavailable`. Self-check never performs
   browser login and never returns credential contents. If it reports a typed failure, follow the
   focused recovery below; do not inspect secure storage or repair the remote service.

Use this exact stdio launch tuple after installation. `SMEDC_BASE_URL` is the only
launcher environment variable; do not add another environment value or any credential.

| Platform | Command                                                                                            | Arguments | Environment                                    |
| -------- | -------------------------------------------------------------------------------------------------- | --------- | ---------------------------------------------- |
| macOS    | `~/Library/Application Support/SMEDC/launcher/versions/0.5.0/node_modules/.bin/smedc-mcp-launcher` | `serve`   | `SMEDC_BASE_URL=https://api.smedatacenter.xyz` |
| Windows  | `%LOCALAPPDATA%\\SMEDC\\launcher\\versions\\0.5.0\\node_modules\\.bin\\smedc-mcp-launcher.cmd`     | `serve`   | `SMEDC_BASE_URL=https://api.smedatacenter.xyz` |

The command, its single `serve` argument, and the one URL-only environment value are the complete
stdio configuration. It must never contain a password, token, header, client secret, or OAuth
setting.

## Device-Code Login Flow

Starting with launcher 0.2.2, every login uses the OAuth Device Authorization Grant: the launcher
obtains a first-party SMEDC verification link, opens it automatically when a system
browser is available (desktop agents), or returns it for the agent to surface through the employee
channel (phone-remote-controlled and headless agents). The employee confirms the agent instance
name shown on the page, enters email/password, and the launcher completes sign-in by polling.

- The employee's only credential input remains email/password on the SMEDC page; never
  ask for, read, or relay verification codes or tokens.
- On macOS/Windows the launcher keeps the durable session in Keychain/Credential Manager exactly as
  before.
- On hosts without a secure store (headless Linux/VPS), the launcher keeps the session in memory
  only; after a launcher or host restart, run the login tool again so the employee can tap a fresh
  link.
- If a business tool reports `authentication_pending`, tell the employee to complete the sign-in
  link and retry the original request once; if it reports `authentication_required`, run
  `smedc_login` to obtain a new link.

This flow is available in launcher 0.2.2 and later; this document pins launcher 0.5.0.

## Configure The Invoking Agent

Always inspect the existing configuration first, create a timestamped backup before modifying it,
then make the smallest idempotent change: one `smedc` stdio MCP entry. Preserve every
unrelated server and setting. Do not configure a direct HTTP/OAuth SMEDC server because
the local launcher owns browser login and credential storage.

### Codex

Use the verified Codex CLI MCP registry. On macOS, prefer `codex` from `PATH`; when it is absent,
use the bundled `/Applications/ChatGPT.app/Contents/Resources/codex` fallback. On Windows, resolve
`codex.exe` from `PATH`. Stop if neither verified binary exists.

Before the first mutation, inspect with `codex mcp list --json` and
`codex mcp get smedc --json`. Back up `~/.codex/config.toml` (Windows:
`%USERPROFILE%\.codex\config.toml`) to a timestamped sibling file when it exists. If the existing
entry already matches the exact command, `serve` argument, and sole BASE_URL environment value, do
nothing.

For macOS add/repair:

```sh
CODEX_BIN="$(command -v codex 2>/dev/null || true)"
if [ -z "$CODEX_BIN" ] && [ -x "/Applications/ChatGPT.app/Contents/Resources/codex" ]; then
  CODEX_BIN="/Applications/ChatGPT.app/Contents/Resources/codex"
fi
test -n "$CODEX_BIN"
CODEX_CONFIG="$HOME/.codex/config.toml"
if [ -f "$CODEX_CONFIG" ]; then
  cp -p "$CODEX_CONFIG" "$CODEX_CONFIG.smedc.bak.$(date +%Y%m%d%H%M%S)"
fi
"$CODEX_BIN" mcp list --json
"$CODEX_BIN" mcp get smedc --json
```

If `get` reports the entry absent, add it. If it is present and exact, stop without mutation. Only
when it is present and mismatched, remove that one entry immediately before running the same add
command:

```sh
# Mismatched entry only:
"$CODEX_BIN" mcp remove smedc
# Missing or just-removed entry:
"$CODEX_BIN" mcp add \
  --env SMEDC_BASE_URL=https://api.smedatacenter.xyz \
  smedc -- \
  "$HOME/Library/Application Support/SMEDC/launcher/versions/0.5.0/node_modules/.bin/smedc-mcp-launcher" serve
"$CODEX_BIN" mcp get smedc --json
```

For Windows PowerShell, use the same `list`/`get`/`remove`/`add` sequence:

```powershell
$CodexBin = (Get-Command codex.exe -ErrorAction Stop).Source
$CodexConfig = Join-Path $env:USERPROFILE ".codex\config.toml"
if (Test-Path $CodexConfig) {
  Copy-Item $CodexConfig "$CodexConfig.smedc.bak.$(Get-Date -Format yyyyMMddHHmmss)"
}
$LauncherBin = "$env:LOCALAPPDATA\SMEDC\launcher\versions\0.5.0\node_modules\.bin\smedc-mcp-launcher.cmd"
& $CodexBin mcp list --json
& $CodexBin mcp get smedc --json
```

If `get` reports the entry absent, add it. If it is present and exact, stop without mutation. Only
for a present mismatched entry, run:

```powershell
# Mismatched entry only:
& $CodexBin mcp remove smedc
# Missing or just-removed entry:
& $CodexBin mcp add --env "SMEDC_BASE_URL=https://api.smedatacenter.xyz" smedc -- $LauncherBin serve
& $CodexBin mcp get smedc --json
```

After add/repair, run the platform self-check above, restart/reload Codex, run
`codex mcp list --json` and `codex mcp get smedc --json`, and confirm the discovered tools.
If add fails after removal, restore the timestamped backup and report the focused failure. For
per-agent removal, back up first, run `codex mcp remove smedc`, then verify
`codex mcp list --json` no longer contains it and `codex mcp get smedc --json` reports it
absent.

### OpenClaw

Use OpenClaw's MCP CLI registry for a **stdio** launcher; do not use OpenClaw's direct remote
OAuth store, `openclaw mcp login`, or `openclaw mcp logout` for SMEDC.

1. Inspect first: `openclaw mcp status --verbose` and, when present,
   `openclaw mcp show smedc --json`.
2. Back up the OpenClaw configuration using its supported current-user mechanism.
3. Add the entry with the platform-specific launcher path from the table, its single `serve`
   argument, and the sole URL-only environment value. On macOS, the verified OpenClaw CLI form is:

   ```sh
   openclaw mcp add smedc \
     --command "$HOME/Library/Application Support/SMEDC/launcher/versions/0.5.0/node_modules/.bin/smedc-mcp-launcher" \
     --arg serve \
     --env SMEDC_BASE_URL=https://api.smedatacenter.xyz
   ```

   If the entry already exists, use `openclaw mcp set smedc '<one stdio JSON object>'`
   with exactly `command`, `args: ["serve"]`, and the one `SMEDC_BASE_URL` environment
   value. Do not add an HTTP URL or `auth: oauth` configuration.

4. Verify with `openclaw mcp doctor smedc --probe`. Reload or restart the owning
   OpenClaw runtime when required by its current setup.

`openclaw mcp add/set/doctor --probe` are the supported configuration/proof path. The launcher,
not OpenClaw's OAuth store, opens the browser and manages the SMEDC secure session.

### Other Agents

Use guarded adaptive discovery. Inspect the installed client's help, current configuration, and
MCP capabilities to confirm that it can start a local stdio server. Back up its configuration,
add only the pinned SMEDC launcher entry, validate its handshake, and preserve every
unrelated server. If its supported configuration mechanism is not clear, report the narrow blocker
instead of editing guessed files or configuring direct remote OAuth.

## Browser Login And Normal Use

Call `smedc_auth_status` before beginning work when the authentication state is unknown.
If it reports `authentication_required`, call `smedc_login`. The launcher opens the
system browser; ask the employee to finish login there and never request any credential in chat.
The launcher returns only a safe outcome.

After successful login, retry the employee's original business tool call exactly once. Do not
retry repeatedly after browser cancellation or an unsuccessful login. Use
`smedc_logout` only when the employee asks to sign out. It clears the shared local
session for SMEDC under the current OS user, so all locally configured agents on that
OS user are signed out.

When the employee asks which SMEDC account is currently active, call the zero-input
`smedc_get_current_user` tool. Return its `displayName`, `email`, `role`, and `clearance`; do not infer
identity from launcher configuration or `smedc_auth_status`, and do not ask for an account
selector. The tool is self-scoped to the bearer-authenticated employee and never returns internal
IDs or credentials. Follow the normal authentication recovery above if login is required.

## SMEDC Data Questions

When the employee asks about资料、SOP、上传过的文件、公司数据、SMEDC 里的表格, or what was
“刚上传/刚传进去/这份表”, answer through SMEDC MCP tools. Do not answer those questions by
reading a local attachment, local CSV/XLSX, previous chat text, cache, or filesystem copy unless
the employee explicitly asks you to inspect a local file outside SMEDC.

Local files are upload inputs only. After uploading a file, keep the returned service metadata
needed for follow-up questions: document id, import batch id, dataset id, declared confidentiality
level, declared business
date window or `snapshotDate`, enterprise/store name, and status. In a later task, rediscover
available datasets through MCP; if the intended uploaded table/document cannot be
identified safely, ask one short natural clarification instead of querying all visible history.

For structured-table questions:

- Call `list_structured_datasets` before constructing a structured query unless you already have a
  fresh compatible registry from the same MCP session.
- Resolve field wording through the registry before every structured query: match user-facing terms
  against `sourceColumn`/`aliases`, then send only `canonicalName` values in `select`, filters,
  sorts, groups, and aggregates. Use `sourceColumn` or the matched alias as the displayed table
  header when that is clearer for the employee.
- Respect registry capabilities for every field. Detail `select` entries must be registered
  canonical fields; filter, sort, group, and aggregate only with fields whose advertised
  capabilities permit that use. Dynamic enrichment fields are selectable detail fields only unless
  discovery says otherwise.
- Use explicit mechanical aggregates only: `count`, `countDistinct`, `sum`, `avg`, `min`, `max`,
  and `weightedAvg`. Group by at most four canonical fields and request at most twelve aggregate
  outputs. Aggregate sort fields must be either a group-by field or a unique aggregate alias from
  the same request.
- For `weightedAvg`, both `field` and `weightField` must be numeric aggregatable canonical fields
  in the same dataset. It represents `SUM(field * weightField) / SUM(weightField)` with a `null`
  result when total weight is zero or missing; do not describe it as a service-generated business
  conclusion.
- Select `source_document_id` on detail-row queries when the employee needs the original uploaded
  file behind a structured row, then pass it to `get_source_document_download_url`. This field is
  not returned by default and is not for filters, sorting, grouping, or aggregates.
- Call `describe_structured_dataset_coverage` before answering whether SMEDC has enough
  readable applied data for a dataset, time window, snapshot, or source-file scope. Coverage shares
  structured-query authorization and returns readable source windows or snapshots; decide and state
  any sufficiency assumptions yourself.
- Scope follow-up questions about a recent upload to that upload's returned import metadata,
  declared business-date window, enterprise/store name, or other explicit service-returned
  metadata. Avoid broad unbounded queries for phrases like “这份表”, “刚才那张表”, or “我刚传的”.
- For `dish_catalog`, scope queries with the discovery-reported `snapshot_date` field. Do not
  infer latest/current catalog state, diffs, or row status across snapshots.
- If the employee asks about a local spreadsheet before it has been uploaded, offer to upload it
  first. Do not compute final SMEDC answers directly from the local spreadsheet unless the
  employee explicitly says they want a local-file-only inspection.
- If a query result contains historical rows outside the intended upload/window, narrow the query
  or ask for clarification before presenting totals as “这份表”的 totals.

For authorized service tools:

- Default an upload to confidentiality level `0` when the employee does not explicitly provide a
  level. Never infer or elevate the level from filenames, content, source context, or apparent
  document lineage. If the employee explicitly supplies `0`–`3`, pass it unchanged.
- Prefer `file.encoding:"path"` uploads with the file's absolute local path; the launcher reads
  exact bytes mechanically. Use `file.encoding:"base64"` only for small inline payloads. Do not
  alter business content, schema, headers, or row meaning unless the employee explicitly asks for a
  local file-conversion task before upload.
- Follow Upload Completion And Status Polling after every `202` upload; never start a worker.
- Quarantine-certificate uploads are synchronous `201` operations, not background imports. Call
  `upload_quarantine_certificate` once per JPG/PNG image with exactly one `receiptId`, one
  idempotency key, and declared confidentiality level. A receipt ID may have zero, one, or multiple
  certificates; one certificate upload request contains only one image.
- Reuse a structured-import idempotency key only for the exact same file and metadata. Treat an
  import-status 404 as "not visible or missing" and do not infer hidden metadata.
- Reuse a quarantine-certificate idempotency key only for the exact same image bytes, receipt ID,
  and declared confidentiality level. Use `query_quarantine_certificates` with explicit `receiptIds`; never try to
  query all quarantine certificates. Use `get_source_document_download_url` with a returned
  `sourceDocumentId` when the employee asks to download or view the original source file.
- Treat evidence cursors as opaque, short-lived continuations. Return `page.nextCursor` unchanged
  with the same query, filters, and limit. Restart without it on `INVALID_CURSOR`; on
  `CURSOR_EXPIRED`, explain the expiry and restart only if the employee still wants more results.
- `smedc_list_skills` exposes approved directory metadata only; do not execute an entry.

## Local File Read Errors

When a path-mode upload fails because the launcher cannot read the file, report the typed error
and ask the employee, in the employee's language, to provide an accessible file. Do not fabricate
content, do not paste file contents into chat, and do not silently retry with an inline copy.

- `MCP_LOCAL_FILE_NOT_FOUND`: the file does not exist at the given path.
- `MCP_LOCAL_FILE_PERMISSION_DENIED`: the launcher cannot read the file (file permissions, macOS
  privacy protection, sandbox, or another OS access boundary).
- `MCP_LOCAL_FILE_INVALID`: the path is relative, a directory, or not a regular file.
- `MCP_LOCAL_FILE_TOO_LARGE`: the file exceeds the applicable contract (2 GiB for path-mode
  `business`/`dishes`; 50 MiB for ordinary uploads).
- `MCP_LOCAL_FILE_READ_FAILED`: another read error.

Example employee-facing reply (Chinese):

> 您刚才提供的文件企业数据中枢没有足够权限读取，请把文件放到桌面/下载等可访问位置后重新提供，
> 或重新拖入文件。

For `MCP_LOCAL_FILE_NOT_FOUND` / `MCP_LOCAL_FILE_INVALID`, ask the employee to re-check the file
location or re-attach the file. For `MCP_LOCAL_FILE_TOO_LARGE`, do not split `business`, `dishes`,
or `dish_catalog`; ask the employee for a smaller complete export, a service-supported larger
limit, or operator help.

## Typed Recovery

| Condition                                     | Required response                                                                                                                            |
| --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `authentication_required`                     | Call `smedc_login`, wait for browser completion, then retry the original business operation once.                                            |
| Browser cancelled, timed out, or login failed | Report the safe outcome. Do not reopen the browser automatically or retry the business operation.                                            |
| `service_unavailable`                         | Report that the official service cannot be reached. Do not start, repair, or diagnose service infrastructure.                                |
| `forbidden` or not-found                      | Treat the resource as unavailable to this employee; do not infer hidden data.                                                                |
| `launcher_upgrade

…(truncated)
