DCC-MCP Creator
Use this skill when you are creating a new DCC-MCP adapter, modernizing an existing adapter repository, or exposing a private non-DCC studio system as a standalone MCP service: server composition, host-thread dispatch, sidecar/gateway wiring, readiness, resources, project state, diagnostics, install lifecycle, or cross-DCC verification. A local folder, intranet source tree, or private monorepo is sufficient; GitHub is not a runtime requirement.
For individual skill packages (SKILL.md, tools.yaml, scripts, groups, and
skill taxonomy), load dcc-mcp-skills-creator instead.
Install and Route
Install the published
@loonghao/dcc-mcp-creator
package, then start a new agent turn:
openclaw skills install @loonghao/dcc-mcp-creator
npx --yes clawhub@0.23.1 install @loonghao/dcc-mcp-creator
Use dcc-mcp to operate an
existing DCC. Use
dcc-mcp-skills-creator
when only a DCC-specific Skill package is needed.
CLI-First Control Path
Use the dcc-mcp skill and dcc-mcp-cli for discovery, validation, and live
DCC control whenever the agent can run shell commands. If the CLI is missing,
follow the consent-gated official installation instructions in dcc-mcp.
Before long-lived validation, run dcc-mcp-cli update check; use
dcc-mcp-cli update apply to verify and stage the latest CLI for the next
launch. Apply-time verification is installation-bound and legacy unsigned
staging is quarantined. Official update manifests additionally require the
release workflow's detached Sigstore provenance. This does not replace a running server binary; update
the server from its exact target environment. Gateway Admin is check-only.
Runtime Vocabulary
- DCC startup hook: adapter code running inside the host at application startup; it prepares env/instance data and launches the service path without blocking the DCC UI/main thread.
- Per-DCC service: one registered runtime row for one concrete DCC instance; Python
DccServerBaseand Rust sidecars both participate as per-DCC services. - Sidecar: the Rust
dcc-mcp-sidecarchild launched through the stabledcc-mcp-server sidecarcommand; it bridges host RPC to MCP/REST and exits when the watched DCC dies. - Gateway daemon: the one machine-wide
dcc-mcp-server gatewayprocess that owns routing, dynamic capability search/describe/call, and Gateway Admin. - Guardian: a lightweight loop inside daemon-backed services that probes gateway
/healthand re-ensures the daemon throughgateway-launch.lock; it is not a separate process. - Service heartbeat: registry freshness for the service row only. Do not describe heartbeat as the gateway restart trigger.
- Service owner: the process that owns the registry sentinel and MCP endpoint; its
pid/sentinel prove the service itself is alive. - Bound DCC host: optional external process identified by
host_pid; both owner and host must stay alive. Standalone/headless services intentionally have no bound host.
Fast Workflow
- Classify the ownership boundary before creating files:
- Public DCC adapter: run
dcc-mcp-cli dcc-types; improve an existing adapter instead of creating a duplicate. Add a genuinely new public adapter todcc-mcp-catalog.ymland the compatibility matrix. A pip install entry requires the released universal wheel's exact HTTPS URL, catalog version, and SHA-256; omit install metadata until it is published. - Private non-DCC service: work in the supplied local or intranet project,
keep its stable custom service id private, and do not require a GitHub
repository, public catalog entry, issue, or release. Use a studio-owned
catalog only when operators need
dcc-mcp-cli installplans. - Skill package only: switch to
dcc-mcp-skills-creator.
- Public DCC adapter: run
- Classify the runtime integration:
- Embedded Python host: Blender, 3ds Max Python, Houdini, Maya, Nuke.
- External bridge host: ZBrush, Photoshop, Unity, custom tools.
- Game/editor host with mixed Python or C++ bridge: Unreal, Unity.
- Standalone internal service: no host bridge; use inline execution for ordinary service/file/API tools and keep every tool typed.
- Read the relevant reference:
- ADAPTER_WORKFLOW.md for the build path.
- INTERNAL_SERVICE_WORKFLOW.md for a private non-DCC service with no public repository requirement.
- HOST_PATTERN_MATRIX.md for host-specific wiring.
- CORE_ESCALATION_CHECKLIST.md before adding adapter-local glue.
- TESTING_AND_RELEASE.md before validating or publishing.
- Python 3.7 policy: native py37 is an LTS profile with no automatic calendar expiry. Verify the aggregate Python 3.7 gate is green and
requires-python = ">=3.7"is unchanged before any release.py37-litefallback does NOT satisfy release gates. Removal requires an accepted superseding ADR, a major release, and at least 180 days of notice. - docs/guide/gateway.md for gateway daemon lifecycle details.
- docs/guide/adapter-install-lifecycle.md for sidecar launch/readiness details.
- docs/guide/adapter-install-sop.md for the adapter-owned install, status, verify, uninstall, and upgrade contract.
- docs/guide/adapter-release-checklist.md for release train compliance.
- docs/guide/new-adapter-onboarding.md for new adapter scaffolding.
- docs/guide/adapter-compatibility-matrix.md for the per-DCC compatibility table.
- Start from
DccServerBase+DccServerOptions.from_env(...). Classify the runtime lifetime explicitly:- Embedded adapter: the service owner is the DCC process; no separate host PID is needed.
- Standard sidecar: pass
watch_pid=current_dcc_pid; core publishes the sidecar owner and bound host as separate liveness signals. - Other out-of-process adapter: pass
dcc_pid=current_dcc_pidsoMcpHttpConfig.host_pidbinds discovery to the DCC lifetime. - Standalone/headless service: pass
instance_type="standalone", leavedcc_pidunset, and do not bind it to an optional GUI process. Runtime identity is independent fromstandalone_main_thread, which controls tool execution only.
- Route host API calls through
HostExecutionBridge; do not hand-roll a second script executor. Standalone services with no host-thread boundary should keep the default inline execution path. For file-backed typedmain(**params)execution, publish mapping annotations only when their keys are strings (Dict[str, V]). Validate the requested SHA-256, derived schema, and structured params before materializing inline source; an invalid request must leave no script or sidecar file behind. - Keep service identity data-driven:
dcc_name/custom service id,server_name, env-var prefix, skill names, and gateway metadata. Leave the instance port unset so core resolvesDCC_MCP_<DCC>_PORTor asks the OS for a free port. - Use core helpers for skill discovery,
MinimalModeConfig, project tools, resources, diagnostics, context snapshots, install lifecycle, and gateway failover before writing adapter-local wrappers. PythonDccServerBase.collect_skill_search_paths()includes marketplace-installed skills under~/.dcc-mcp/marketplace/<dcc>(orDCC_MCP_MARKETPLACE_INSTALL_ROOT/<dcc>) when the directory exists, so adapters should not add a second marketplace path convention. Hermetic adapter tests should setDCC_MCP_DISABLE_DEFAULT_SKILL_PATHS=1; this excludes implicit local/platform defaults, marketplace installs, and Admin custom paths while explicit, bundled, and environment-provided skill paths remain active.DccServerBasealso ownsDiagnosticRuntimeState; do not add adapter-level recorder, sandbox, screenshot-capturer, dispatcher, server, or instance-context globals. Standalone registration code may inject one state into both diagnostic registration helpers. It also ownsfeedback_store,script_execution_context, andcheckpoint_store; inject them into core helpers instead of creating adapter-level feedback buffers, persistent exec namespaces, or default stores. Adapters that exposeexecute_pythonshould capability-gate cheap scene-state evidence by registering one host-owned callback withregister_state_digest_provider(..., context=server.script_execution_context). The callback returnsSceneStatsor its mapping shape (object_count,vertex_count,has_mesh, optionalextra). Run scripts throughexecute_with_state_digest(...); its native transaction pins that exact provider for both observations and returns publicSceneDigestSnapshotvalues. A script cannot replace the provider used by its active transaction or poison the next transaction throughScriptExecutionContext. Pass both snapshots toScriptExecutionResult.from_value(...). Core bounds and redacts the payload, computes a deterministic fingerprint, and fails closed when the provider is absent, raises, returns malformed data, or supplies a mismatched fingerprint. Digest change proves only that observed state changed; leaveverifiedomitted/false unless an adapter-owned postcondition verifies the claimed effect. Never turn contract-test evidence into a real-host success claim. The fingerprint and truncation marker detect deterministic corruption; they are not authentication, authorization, or proof of host identity. Core does not expose a Python secret, signing oracle, signed wire tag, or native factory that turns caller-supplied bytes into authenticated evidence. The adapter registers the provider before the native transaction starts, but that does not establish cryptographic authenticity; semantic verification remains adapter-owned. Pure-Python runtimes without that boundary fail closed withscene_digest_custody_unavailable. Mapping values beyond the bounded observation budget use a fixed sentinel, keeping equivalent provider mappings deterministic without unbounded reads. Core does not auto-register or advertise anexecute_pythonroute. Gate adapter discovery and route registration on successful provider registration, and exposeunavailable/provider_missingwhencapture_state_digest(...)reports no provider. If the script raisesExceptionorBaseException, the transaction performs after-state readback first. CatchSceneDigestExecutionErrorand pass itscause, snapshots, andreadback_errortoScriptExecutionResult.from_exception(...). A failed after-readback after a mutating script is explicitlyindeterminate=truewithverified=false; preserve the before snapshot and never retry it as if no side effect occurred. Core persists gateway-accepted feedback under<registry_dir>/feedback/<dcc>-<pid>.jsonlwith bounded rotation and session-end syncing. Treatfeedback_persistence_failedas a real degraded result; never add an adapter-local success fallback.- For native visual UI fallback, reuse the bundled
ui-controlskill with standalonedcc-cua0.4.0 or newer; do not add adapter-local capture, accessibility, or raw-input wrappers. Keep stateful UI calls in one long-lived adapter process so each logical session retains its persistent CUA bridge and window capability. Preservecapture_provenancewith evidence. The shared CUA Host owns platform accessibility, capture, banner/border/cursor markers, Escape interruption, input serialization, and recording.ui-controlremainsrequires_in_process: truewithaffinity: any; registerHostExecutionBridgebefore skill loading. - Keep structured DCC skills, host APIs, and adapter scripts ahead of
ui-control. Agents should make an explicit, agent-directed transition into the scopedsnapshot→ oneact→snapshotloop only when an operation is unsupported, no suitable tool exists, or semantic UI Automation cannot reach the required control. Re-observe after every action. - For native application menu bars, route an explicit
menu_paththroughui_control__act(action="invoke_menu")when semantic click or Alt-mnemonic delivery cannot prove that a Qt popup opened. Require the negotiatednative_menu_pathHost capability, honorverification_required, and re-observe the exact window before another mutation. - Raw pointer and keyboard input are enabled by default only inside the
adapter/operator-bound DCC scope. Operators may set
DCC_MCP_CUA_ALLOW_RAW_INPUT=falseto disable that runtime ceiling; the adapter must not override this choice. PopulateDccServerOptionswith the adapter's DCC PID and, when available, its current window title or handle; Core injects that trusted scope into in-processui-controlcalls. Dedicated servers may instead useDCC_MCP_UI_CONTROL_PROCESS_IDorDCC_MCP_UI_CONTROL_WINDOW_HANDLEoperator overrides. Request scope may only narrow that trusted PID/HWND, including a title constraint for one window inside a multi-window process. Require a visible unlocked desktop and matching Windows integrity level, preserve the click-through border/banner/pointer feedback, and preserveuser_interruptedwithout automatic retry,session_idchanges, or fallback. Once Esc stops an session, onlyui_control__snapshot(resume_computer_use=true)may request a resume, and the isolated host must still obtain trusted user confirmation before clearing the latch. Always callui_control__stop_computer_usewhen the workflow ends. Never transition or retry through another UI/input path after a policy, authorization, authentication, security, confirmation,desktop_unavailable, oruser_interruptedresult. Keep mutating UI Control tools annotated as destructive. The optionalintentmay only raise the native host's independent UIA/input classification. Do not introduce a model-suppliedconfirmed/approvedflag or environment bypass.
- For native visual UI fallback, reuse the bundled
- Use CLI profiles (
dcc-mcp-cli gateway ...,list/search/describe/call) as the user UX; treatdcc-mcp-servermodes as runtime plumbing. Readdocs/guide/gateway.mdbefore changing daemon, guardian, sentinel, registry, or idle-timeout behavior. Gateway discovery reuses a recent capability snapshot across adjacent queries. Route adapter catalog changes through the existing load/reload/unload contracts that force a refresh; never depend on every search polling the full backend catalog.gateway://instancesis agent-safe by default and returns only live, routable rows. Use?include_stale=true,?include_dead=true, or?view=allonly for explicit diagnosis; never route a call from those expanded operator views without re-validating live readiness. Once an instance is selected, reusegateway://instances/{instance_id}orGET /v1/instances/{instance_id}/contextfor live process/machine performance, scene/documents, loaded skills, and canonical follow-up routes. These reads fetch the backend context on demand, but scene freshness remains adapter-owned: publish changes from a host event/main-thread callback withDccServerBase.update_gateway_metadata(...), and publish rich snapshots withset_scene_resource(...). Never claim scene awareness when the adapter has not installed a publisher;scene=null/no_scene_publishedis explicit. For agent observability, readgateway://experiments/{experiment_id}for runs, Session DAG links, metrics, and Judge evidence; readgateway://governancefor the effective policy boundary. Keep Admin memory deletion controls out of agent-readable resources. - Use
dcc_mcp_core.deployment.build_sidecar_command(...)/launch_sidecar(...)for library-driven sidecar startup and readiness. Installer subprocesses should usedcc-mcp-install-lifecycle;dcc_mcp_core.install_lifecycleandpython -m dcc_mcp_core.install_lifecycleremain compatibility aliases. Readdocs/guide/adapter-install-lifecycle.mdbefore changing host RPC, dispatch readiness, launch stdio,watch_pid, orinstance_idhandling.- Adapter-owned lifecycle commands must follow
docs/guide/adapter-install-sop.md. Consumeload_install_sop_schema()andINSTALL_EXIT_CODESfromdcc_mcp_core.deployment; do not invent adapter-local result shapes or exit-code mappings. - The sidecar MCP listener is dispatch-only. A py37-lite factory can expose local skill metadata, but it cannot advertise or activate declarative skills through the gateway. Require a native py37 wheel for that path, or provide a separate discovery MCP URL; never report lite
load_skillsuccess without an executable catalog. - Wrap the outer adapter import/start block with
capture_bootstrap_errors(...); it is stdlib-only, records pre-MCP failures, and re-raises for the DCC's native error UI.DccServerBasealready captures Python error logs and uncaught exceptions into the shared log plusoutput:///events://. Forward host-native console callbacks withserver.report_host_error(...); do not replace global stdout/stderr or add an adapter-local error store. - For DCC-Link IPC upgrades, deploy readers that accept current version 1 and legacy version 0 before switching writers to the default versioned frame. Use
DccLinkFrame(..., version=0)only during that compatibility window, preserve an incoming frame's version in its reply, and treatunsupported DCC-Link protocol versionas an explicit peer-upgrade failure rather than retrying body decoding. - Preserve one caller-generated request id across every execution hop. JSON-RPC responses must echo
id; commandPort-style sidecar responses must echo top-levelrequest_id; gateway REST responses must echoX-Request-ID. Never replace an explicit response id with the current request id, because that can disguise a stale response. Treat a missing or mismatched echo astransport desync, fail closed, and regression-test a slow call followed by fast calls on the same connection. - Registry producers must write
ServiceEntry.schema_versionusingSERVICE_ENTRY_SCHEMA_VERSION; rows with no field are legacy version 0. Consumers may read legacy/current rows but must reject a higher schema version without quarantining, deleting, or rewritingservices.json. Treat that error as an explicit peer-upgrade requirement, not as corrupt JSON.
- Adapter-owned lifecycle commands must follow
- Pass
instance_idto sidecar launch helpers only when it is a real UUID for the DCC service. During early startup, omit it or passNone;build_sidecar_command()rejects cosmetic values such as"unknown"withsuccess=falseandreason="invalid_instance_id"so adapters do not spawn a child that can only fail with a CLI argument error. AfterDccServerBase.start(), useserver.instance_idwhen adapter UI or sidecar wiring needs the canonical FileRegistry identity. It is the exact registered UUID and isNonebefore start, after stop, or when gateway registration is disabled/unavailable; never inspect private handles or generate a replacement UUID. - Adapter supervisors that must stop the sidecar on plugin unload should call
launch_sidecar(..., return_process=True, detached=False)instead of reimplementingsubprocess.Popen; keepreturn_process=Falsefor CLI/JSON paths because the process handle is not serializable. - If the adapter cannot share the gateway
FileRegistry, register remotely throughPOST /v1/instances/register, refresh with/heartbeat, and deregister on shutdown; the gateway will expose the row assource: "http"ingateway://instances/GET /v1/instances, preserveinstance_shortandmcp_url, and route it through the samelive_instancescontract. Remote registrations are untrusted input: health and capability refresh only use policy-allowed, identity-matching HTTP(S) endpoints with no query credentials or URL userinfo; redirects are not followed, and private/link-local targets (including IPv4-mapped IPv6 literals) and DNS names are rejected for periodic outbound probes. Gateway health and reliability totals count only registrations accepted by that same dispatch predicate; rejected registrations are reported separately and cannot shadow a safe backend during DCC-type routing. Public literal IPv6 registrations keep an unbracketed canonical host identity; brackets belong only to serialized URLs. Adapters must not copy a bracketed URL host intoServiceEntry.hostor compare raw URL text across discovery and dispatch. - Keep the gateway's secondary listener on its default loopback host. Opt into LAN access only with an explicit
--remote-host 0.0.0.0or concrete LAN IP; for same-LAN convenience discovery, build withmdnsand pair adapter-side--advertise-mdnswith gateway-side--discover-mdns. Treat mDNS as a multicast discovery hint only, keep auth/TLS policy explicit, and prefer HTTP registration or relay for routed/subnet-crossing production deployments. - For NAT or routed-subnet deployments, run the tunnel agent with stable
instance_id,capabilities_fingerprint,adapter_version, andscenemetadata, then configure the standalone gateway with--relay-source ADMIN_URL=PUBLIC_BASE_URL; the gateway will expose active tunnels assource: "relay"rows with relay details insource_metaafter probing/v1/healthzthrough<PUBLIC_BASE_URL>/tunnel/<tunnel_id>/mcp. - Preserve gateway caller attribution when adding adapter wrappers or admin/debug routes: let legacy MCP
initialize.params.clientInfo, MCP_meta.agent_context, RESTmeta.agent_context,x-dcc-mcp-*headers, and safeUser-Agentfallbacks flow through core rather than logging raw prompts or local machine data. The opt-in MCP 2026 path usesserver/discoverand namespaced per-request metadata instead of a legacy initialize session. Consume Core's shared protocol types and routing; do not copy wire envelopes into adapters or Skills. Keep CLI+REST as the agent default. Before enabling a new protocol, follow the protocol compatibility gates against the exact installed artifact; a version label alone is insufficient. - For lifecycle/memory/telemetry policy, use
register_lifecycle_hooks(...),search_skills(..., session_id=...),dispatch_session_start(...),dispatch_before_tool_call(...),dispatch_after_tool_call(...), anddispatch_session_end(...); pairMemoryRecorder(InMemoryMemoryStore()).install(hooks)with those hooks when adapters need bounded memory summaries, failed-pattern avoidance, or session compaction. Memory injection is conservative and budgeted by default: search receives compact ranking hints, tool calls receive memory only when it matches the currenttool_name, and session-start injection is opt-in. UseSqliteMemoryStore()only when longterm patterns should be durable, operator-managed in the Admin Memory tab, and included in memory hit-rate observability; disable the recorder for privacy-sensitive deployments. Open a focused core issue/RFC only when those public hooks cannot express the adapter boundary. - Add one executable smoke path: unit tests for construction plus either headless DCC, mock dispatcher MCP calls, gateway REST replay, mDNS same-LAN discovery smoke, relay-source smoke, the open-source MCP Inspector for a loopback internal service, or
just idle-memory-smokefor standalone server idle/regression checks. - For gateway/admin observability, surface explicit state instead of silent zeroes: traffic panels should report disabled, unavailable, filtered, or genuine no-traffic states; skill panels should distinguish discovered, loaded, searched, selected, called, failed, and low-adoption skills; and admin-facing frames/paths should stay metadata-only or aliased unless an operator explicitly configures a private raw sink. Keep
ServiceEntry.versionas the DCC application version; use core-publisheddcc_mcp_server_versionanddcc_mcp_instance_type=gui|standalonemetadata for server regression and runtime-shape diagnostics instead of overloading DCC or adapter versions. - Preserve workflow observability: adapter calls should carry request, parent, trace, session, DCC, transport, and artifact/validation metadata so the Admin workflow graph can show Intent → Discovery → Skill Load → Tool Calls → Fallbacks → Artifacts → Validation → Report without raw log reading.
- Preserve bounded
agent_contexttask/session/turn metadata and artifact/validation-friendly tool names so Admin task outcomes can group workflows, calls, deliverables, and checks without reading raw payloads or local paths. - Preserve record-replay ownership boundaries: forward server-derived
agent_context.session_id, keep UI Control logical ids connection/caller scoped, and write only redacted recording projections to existingsession_events. Do not add adapter-local recorder state, a second database, or a replay authority flag. Persist calls incrementally; after a gateway restart, project unfinished recordings asinterruptedwithout restoring capture authority. Generated workflows re-resolve current tools and schemas; semantic UI replay resolves fresh control ids; raw/visual fallback requires exact-window calibration and drift guards. - Record reproducible experiment definitions, run states, Session DAG links,
metrics, and judge evidence through the gateway
/v1/experimentsAPIs. Reusesession_events, workflow/recording identifiers, and artifact references; do not add adapter-local experiment storage or treat judge output as approval authority.
Chunked Main-Thread Jobs
Read references/ASYNC_RECOVERY.md when this workflow applies.
Failure Analysis and Bug Routing
Reproduce through dcc-mcp and keep one gateway session id. Run
dcc-mcp-cli doctor, then dcc-mcp-cli stats --status failure --session-id <session-id>; preserve the failed call's request_id, trace/job ids, adapter
version, DCC version, readiness fields, and the smallest safe reproduction.
Use /v1/debug/issue-reports/<request_id> for the public-safe issue body and
review any ?mode=raw export locally before sharing it.
The bundled error report binds persisted-job diagnostics to the exact current
instance key. If that database is absent, report persistence as unavailable;
never glob a sibling instance or fall back to another process's database.
It likewise binds rolling-log diagnostics to the current DCC process PID; if
that exact log is absent, report logging as unavailable instead of selecting a
same-DCC sibling log.
Report adapter-owned dispatch, host-thread, readiness, packaging, or install
bugs in the adapter repository. Escalate shared CLI, gateway, protocol, or core
contract failures to dcc-mcp-core. Tool schema/script/workflow defects belong
to the owning Skill and dcc-mcp-skills-creator. Record runtime feedback with
the gateway-owned dcc-mcp-cli feedback command so the report remains possible
after an adapter or DCC process exits; include the last known instance,
request, and job ids. Instance-level dcc_feedback__report is the live-adapter
Finding v1 entry point. Core must register it so runtime DCC/adapter/core/host
versions, OS, instance id, fingerprint, and conservative redaction status are
auto-filled; adapters must not accept agent claims for those fields or add an
adapter-specific action/local-success fallback. Open an external issue only
with user authorization.
Core persists accepted adapter reports under the shared registry and exposes
them through dcc-mcp-cli feedback list|export / GET /admin/api/feedback.
Adapters must use DccServerBase's instance-owned FeedbackStore; do not add a
second adapter-local log, aggregation endpoint, or delete-then-copy rotation.
The gateway query is bounded, deduplicates by feedback id, and fails explicitly
when filesystem reads or scan limits prevent a complete result.
Example: New Nuke Adapter
When asked to create a Nuke MCP adapter, start by mapping the host lifecycle: how Python is loaded, how the UI/main thread must be entered, what headless mode is available, how plugins are installed, and which operations should be bundled as default skills. Then scaffold the adapter around core primitives:
DccServerBasefor MCP/HTTP and skill catalog behavior.DccServerOptions.from_env("NUKE")or an adapter-specific equivalent for env-driven configuration.HostExecutionBridgeplus a Nuke dispatcher for all Nuke API calls.- Core project, readiness, resource, diagnostics, and gateway helpers before adapter-local glue.
dcc-mcp-skills-creatorfor the firstnuke-*skill packages.
Example: Private Non-DCC Service
When asked to expose an internal asset, render-farm, review, or production
service, stay in the supplied private project and start with
examples/remote-server. It is a standalone
service despite the historical directory name: it binds to loopback for local
development, discovers a bundled example Skill, and needs no DCC process or GitHub
repository.
- Use a stable custom identifier such as
studio-assets; do not pretend it is Maya or another cataloged DCC. - Pass
instance_type="standalone", leavedcc_pidunset, and use inline execution unless a real external host boundary exists. - Validate the Skill, start the service, then exercise
tools/list,tools/call, resources, and errors with the official open-source MCP Inspector before testing gateway discovery. - Keep development on loopback. Intranet exposure requires operator-owned TLS, authentication, firewall policy, secret storage, and audit controls.
- Package through the owner's existing wheel, archive, container, Rez, or private registry workflow. Do not create or publish a public repository unless the user explicitly requests it.
Cross-DCC Asset Sync
When an adapter publishes an evolving file to another local or remote DCC, use
Core's AssetSyncRevision and FileAssetSyncStore contract. Keep absolute
paths process-local: public tools accept a relative source name, while both the
source root and consumer destination root come from operator configuration.
Validate format and size before publishing, pass expected_head_revision for
optimistic conflict detection, and materialize only beneath the consumer-owned
root. The adapter owns its native import, canvas, refresh, or watch behavior;
Core owns only the path-free revision manifest, content-addressed object, and
conflict/materialization rules. See docs/guide/asset-sync.md and ADR-021.
Non-Negotiables
- Do not touch a DCC API from a Tokio/HTTP worker thread.
- Do not parse or rewrite
SKILL.md,tools.yaml,groups.yaml, or prompt/workflow files in adapter runtime code when core exposes a typed object or catalog API. - Do not reach into
server._serverunless no public core API exists; if you must, file a core issue and keep the adapter shim small. - Do not create Maya-only abstractions in shared core or adapter templates.
- Do not expose raw script execution as the primary user workflow when a typed skill can cover the task.
- Do not require GitHub, a public catalog entry, or public issue tracking for a private internal service.
- Do not publish local paths, private machine names, or source-attribution markers in public issues or PR text.