Skip to content

feat(mcp/spark): canonical MCP inventory, OpenClaw scopes, and SPARK node matrix - #2126

Merged
POWERFULMOVES merged 6 commits into
mainfrom
feat/kilocode-phase5
Jul 15, 2026
Merged

POWERFULMOVES merged 6 commits into
mainfrom
feat/kilocode-phase5

Conversation

@POWERFULMOVES

@POWERFULMOVES POWERFULMOVES commented Jul 14, 2026 •

Copy link
Copy Markdown
Owner

Summary

Bootstraps a canonical MCP inventory and generator, rolls the canonical PMOVES MCP set into OpenClaw scopes and OpenCode node configs, adds the SPARK (NVIDIA DGX) node to the matrix, and fixes a TensorZero TOML duplicate-key issue discovered during bring-up.

Commits

  • 3ce7fad76 feat(mcp): canonical MCP inventory + generator + full agent-stack bootstrap
  • 0cb095371 feat(mcp): bootstrap canonical PMOVES MCPs into OpenClaw scopes
  • cd6616bf8 fix(mcp): promote kvm2 OpenClaw scope to full tier
  • 7d13e2690 feat(spark): add SPARK node to OpenClaw/OpenCode MCP matrix and fix TensorZero TOML duplicates

Key changes

  • pmoves/config/mcp_inventory.json: canonical inventory with endpoint prefixes (local/fleet) and defaults for Cipher / Agent Zero URLs.
  • pmoves/tools/mcp_config_generator.py: renders client-native configs for Claude, Kimi, KiloCode, Crush, Hermes, and OpenClaw scopes.
  • pmoves/tools/bootstrap_openclaw_scopes.py: idempotently updates per-node OpenClaw scopes using tier + endpoint policy.
  • pmoves/tools/bootstrap_opencode.py: updates OpenCode node configs while preserving non-PMOVES MCPs.
  • OpenClaw scopes for 4090, 5090, z890, kvm2, kvm4-1, kvm4-2, nemotron-claw, nemoclaw, and spark.
  • OpenCode configs for the same nodes, including new opencode-spark.json.
  • Fixed duplicate [models.chat_zai_glm52] and [functions.coding_kilocode] keys in pmoves/tensorzero/config/tensorzero.toml.

Verification

make -C pmoves openclaw-scope-check   # 9 scopes canonical
make -C pmoves mcp-bootstrap-check    # 17 passed
python3 -m pytest pmoves/tests/test_mcp_config_generator.py  # 17 passed
make -C pmoves flight-check-retro     # ALL SYSTEMS READY on SPARK

Notes

  • SPARK uses full-tier fleet endpoints (Cipher / Agent Zero resolved via ${TS_Z890}).
  • Generated .pre-mcp-bootstrap.bak files and pmoves/docs/evidence/ artifacts are left unstaged.

Summary by CodeRabbit

  • New Features
    • Added centralized MCP server configuration across supported agent and coding tools.
    • Added integrations for orchestration, messaging, databases, search, network administration, and Docker tooling.
    • Added automated setup for local and fleet endpoints, including profile-specific configurations.
    • Added backup-safe configuration generation and preservation of existing custom server settings.
  • Bug Fixes
    • Improved MCP availability checks and environment-based server activation.
  • Documentation
    • Expanded MCP Toolkit setup guidance and available bootstrap commands.
  • Tests
    • Added coverage for configuration generation, merging, validation, and endpoint selection.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a canonical MCP inventory and generator, bootstraps MCP configurations across clients and node scopes, introduces validation and backup behavior, expands runtime MCP registrations, and adds a KiloCode TensorZero variant while removing a duplicate legacy declaration.

Changes

MCP inventory and generation

Layer / File(s) Summary
Canonical inventory and client renderers
pmoves/config/mcp_inventory.json, pmoves/tools/mcp_config_generator.py, pmoves/tests/test_mcp_config_generator.py
Defines MCP servers, endpoint resolution, environment expansion, client-specific rendering, merging, backups, and coverage tests.
OpenCode and OpenClaw bootstrap
pmoves/tools/bootstrap_opencode.py, pmoves/tools/bootstrap_openclaw_scopes.py, pmoves/tests/test_mcp_config_generator.py
Generates canonical MCP blocks, preserves non-PMOVES entries, writes backups, and supports dry-run and validation modes.
Client and profile registrations
.claude/mcp.json, .kimi/mcp.json, kilo.json, pmoves/configs/claws/*, pmoves/config/profiles/hermes/*, pmoves/tools/crush_configurator.py
Adds NATS, Supabase, HuggingFace, Tailscale, Agent Zero, cipher, and Docker gateway registrations with transport, authentication, environment, permission, and enablement settings.
Bootstrap orchestration and validation
pmoves/mk/mcp-toolkit.mk, pmoves/Makefile, pmoves/scripts/*, pmoves/mk/kilo.mk, pmoves/docs/operations/MCP_TOOLKIT.md
Adds MCP bootstrap targets, startup integration, Hermes/Crush refresh, parity checks, validation commands, and related documentation.
TensorZero coding variant
pmoves/tensorzero/config/tensorzero.toml
Adds the cloud_zai_glm51 KiloCode variant and removes a duplicate legacy coding-function block.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Bootstrap as mcp-bootstrap
  participant Toolkit as MCP Toolkit
  participant Generator as mcp_config_generator
  participant Configs as Client and scope configs
  Bootstrap->>Toolkit: bootstrap toolkit profile
  Bootstrap->>Generator: generate canonical MCP configurations
  Generator->>Configs: merge MCP servers and create backups
  Bootstrap->>Configs: run configuration checks
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.42% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the main MCP inventory, scope, and SPARK matrix changes.
Description check ✅ Passed It covers the main summary and verification, but omits the template's Required Checks and Review Coordination sections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/kilocode-phase5

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7d13e26903

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread pmoves/scripts/bootstrap-hermes-crush.sh Outdated
Comment thread .kimi/mcp.json Outdated
Comment thread pmoves/tools/mcp_config_generator.py
@POWERFULMOVES
POWERFULMOVES enabled auto-merge (squash) July 15, 2026 09:41
@github-actions github-actions Bot added docs Documentation config pmoves/config(s)/ changes labels Jul 15, 2026
Agent Zero and others added 6 commits July 15, 2026 10:39
…tstrap

- Add pmoves/config/mcp_inventory.json as single source of truth
- Add pmoves/tools/mcp_config_generator.py to render client-native configs
- Wire MCP bootstrap into pmoves/scripts/bootstrap-node.sh and Makefile
- Add hermes-crush bootstrap script and make targets
- Update Claude, Kimi, KiloCode, Hermes, Crush, and OpenCode configs
- Add pytest suite for the generator
- Add kilo parity check tooling
- Docs updated in MCP_TOOLKIT.md
- Extend mcp_inventory.json with endpoint_prefix so fleet/local URLs resolve cleanly
- Fix mcp_config_generator.py endpoint lookup to honor caller endpoint preference
- Add pmoves/tools/bootstrap_openclaw_scopes.py with full/edge tier policy
- Update all 8 pmoves/configs/claws/scopes/*.json configs
  - full nodes (4090, 5090, z890, kvm4-1, kvm4-2, nemotron-claw): full PMOVES MCP set
  - edge nodes (nemoclaw, kvm2): cipher + agent-zero + tailscale
  - preserve scope-specific MCPs (gpu-mesh, docker, zai-*, etc.)
- Add openclaw-scope-bootstrap and openclaw-scope-check make targets
- Extend test_mcp_config_generator.py with endpoint + scope tests (17 passing)
KVMs act as Tailscale exit nodes and connect to GPU-bearing nodes, so
every KVM gets the full PMOVES MCP set per operator clarification.

- Move kvm2 from edge to full tier in bootstrap_openclaw_scopes.py
- Regenerate pmoves/configs/claws/scopes/kvm2.json with full PMOVES MCP set
… fallback

1. DEFAULT_OUTPUTS: add opencode entry (was missing — KeyError on --client all)
2. bootstrap-hermes-crush.sh: add export PYTHONPATH for python3 -m pmoves.tools.*
3. .kimi/mcp.json: SUPABASE_SERVICE_KEY -> canonical with fallback
   (same fixes as PR #2124, applied to this branch)
Addresses Codex P1, Codex P2, CodeRabbit Critical + Major findings:

P1 (security): mcp_config_generator._expand() now accepts
allow_os_environ flag. Tracked configs (repo-relative claude/kimi/
kilocode/opencode) generate with allow_os_environ=False, preserving
${VAR} placeholders instead of expanding real secret values from
os.environ. Only --set values and local configs (crush/hermes in
~/.config or ~/.hermes) expand from os.environ.

Critical (hermes): --client hermes now writes to a .mcp_snippet.json
sidecar instead of overwriting the real config.yaml. The bootstrap
script merges the snippet into config.yaml surgically via PyYAML.

Major (--client all): --client all with --output is now rejected
(exit 2) with a message requiring --output-dir.

P2 (PYTHONPATH): bootstrap-hermes-crush.sh already exports
PYTHONPATH at line 33 (was added in a prior commit).

Major (bootstrap fail): script now exits 1 on Crush generator failure
or missing PyYAML, instead of silently succeeding.

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
@POWERFULMOVES
POWERFULMOVES force-pushed the feat/kilocode-phase5 branch from 2644966 to 2073863 Compare July 15, 2026 14:40

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 18

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@kilo.json`:
- Around line 146-158: Update the pmoves-supabase configuration’s --apiKey value
to support the SUPABASE_SERVICE_ROLE_KEY fallback used by the corresponding Kimi
configuration, while retaining SUPABASE_SERVICE_KEY as the primary variable.
Preserve the existing PostgREST command and other arguments unchanged.

In `@pmoves/config/mcp_inventory.json`:
- Around line 78-88: Update the supabase-db configuration in mcp_inventory.json
and the corresponding generation logic in crush_configurator.py to use
--access-mode=restricted by default. Ensure generated client configurations
remain read-only, and only retain unrestricted access where it is explicitly
scoped to trusted clients.

In `@pmoves/docs/operations/MCP_TOOLKIT.md`:
- Line 236: Correct the target location statement in the MCP toolkit
documentation to identify pmoves/mk/mcp-toolkit.mk as the file defining the
targets and pmoves/Makefile as the file that includes it; leave the script
locations unchanged.

In `@pmoves/mk/kilo.mk`:
- Around line 100-107: Update the MCP parity check invocation in the Make target
to capture the exit status returned by pmoves.tools.kilo_parity_mcp_check rather
than assigning command-substitution stdout to mcp_gaps. Preserve the existing
gaps accumulation, blocked-item reporting, and final exit behavior.

In `@pmoves/mk/mcp-toolkit.mk`:
- Around line 6-8: Update the mutation warning comment near mcp-toolkit-connect
to include mcp-config-bootstrap, OpenCode/OpenClaw bootstrap, and Hermes/Crush
bootstrap as targets that modify client configuration files, and remove the
claim that mcp-toolkit-connect is the only mutating target while preserving the
explicit-authorization guidance.
- Around line 107-109: Update mcp-bootstrap in pmoves/mk/mcp-toolkit.mk to
preflight Toolkit availability, skip only when Toolkit is absent, and propagate
failures from profile import, network, or bootstrap scripts when it is
installed; do not use unconditional || true. In pmoves/Makefile lines 897-898,
call the corrected mcp-bootstrap umbrella target or apply the same
selective-skip behavior.
- Around line 123-153: Update the configuration validation recipe around the
existing file and grep checks to invoke openclaw-scope-check for generated
OpenClaw files and the repository’s canonical JSON validators for every
generated MCP configuration. Ensure validation fails on malformed JSON and
unresolved placeholders such as ${...} or your_*_here, while retaining
exhaustive checks for all generated scopes and canonical MCP entries.

In `@pmoves/scripts/bootstrap-hermes-crush.sh`:
- Line 79: Update the configuration merge in the mcp_servers setup to remove
previously managed PMOVES/Hermes entries before applying the current mcp_servers
inventory. Preserve unrelated user-defined entries, while replacing all
canonical inventory keys so renamed or removed servers do not remain.

In `@pmoves/scripts/bootstrap-node.sh`:
- Around line 243-248: Update the MCP bootstrap block in the node setup flow so
a nonzero result from the mcp-bootstrap target propagates as a failure instead
of allowing setup to continue successfully. Preserve the existing success
message, but replace the current warning-only else path with the script’s
established failure/exit behavior; only retain best-effort continuation if it is
explicitly enabled by an existing configuration option.

In `@pmoves/scripts/mcp-toolkit-bootstrap.sh`:
- Around line 70-74: Update the mcp-config-bootstrap invocation in the PMOVES
bootstrap flow to fail immediately when make returns a nonzero status. Remove
the warning-and-continue branch so canonical MCP generation errors propagate as
a bootstrap failure instead of reporting success with stale configurations.

In `@pmoves/tests/test_mcp_config_generator.py`:
- Around line 325-332: Update the scope test setup around scopes.main([]) to
restore both scopes.SCOPES_DIR and scopes.INVENTORY_PATH after each test,
including the additional affected test blocks. Prefer monkeypatch for both
module globals, or save their original values and restore them in the existing
finally cleanup.

In `@pmoves/tools/bootstrap_openclaw_scopes.py`:
- Around line 79-84: Disable OS-environment expansion in both tracked bootstrap
generator calls: update generate_for_client in
pmoves/tools/bootstrap_openclaw_scopes.py lines 79-84 and
pmoves/tools/bootstrap_opencode.py lines 37-43 to pass allow_os_environ=False,
preserving the existing inventory, endpoint, and context arguments.
- Around line 138-151: Update pmoves/tools/bootstrap_openclaw_scopes.py lines
138-151 to validate each PMOVES MCP entry’s complete definition against
canonical_scope_mcp_servers(), not just key presence; retain missing and
unexpected-entry reporting while detecting incorrect values. Update
pmoves/tools/kilo_parity_mcp_check.py lines 15-31 to compare generated KiloCode
MCP entries and their permissions against kilo.json, including configuration
values rather than only keys.

In `@pmoves/tools/crush_configurator.py`:
- Around line 196-223: Add TS_Z890 to the required_env declarations for the
remote pmoves-cipher and agent-zero MCPSpec entries, while leaving
pmoves-cipher-local dependent only on CIPHER_API_TOKEN. Ensure configurations
with missing TS_Z890 are not generated.
- Around line 242-260: Update the pmoves-supabase MCPSpec to use the MCPSpec
any-of environment requirement, requiring SUPABASE_SERVICE_ROLE_KEY or
SUPABASE_SERVICE_KEY before enabling the spec. Preserve the existing command,
arguments, timeout, and required_commands configuration.
- Around line 174-182: Update missing_envs to treat known placeholder-pattern
values, including your_*_here, as missing in addition to empty or absent values.
Add exhaustive placeholder validation within the existing _lookup_env-based
check, and return each affected key so configuration cannot pass with unresolved
placeholders.

In `@pmoves/tools/mcp_config_generator.py`:
- Around line 113-120: The recursive default expansion in `_expand` must
preserve the caller’s `allow_os_environ` value instead of re-enabling
process-environment lookups. Pass that policy through nested expansion so
tracked generation cannot resolve nested fallbacks from `os.environ` when
environment access is disabled.
- Around line 278-283: Update the stdio branch in render_crush() to include
spec.env in the generated entry, preserving the existing command and argument
rendering while ensuring environment variables are passed through to Crush stdio
servers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 73ea5a99-dc07-4053-be4f-24cb5079546b

📥 Commits

Reviewing files that changed from the base of the PR and between 288e90c and 2073863.

📒 Files selected for processing (43)
  • .claude/mcp.json
  • .gitignore
  • .kimi/mcp.json
  • kilo.json
  • pmoves/Makefile
  • pmoves/config/mcp_inventory.json
  • pmoves/config/profiles/hermes/4090.yaml
  • pmoves/config/profiles/hermes/5090.yaml
  • pmoves/config/profiles/hermes/b850.yaml
  • pmoves/config/profiles/hermes/elder-melchor.yaml
  • pmoves/config/profiles/hermes/kvm4-1.yaml
  • pmoves/config/profiles/hermes/spark.yaml
  • pmoves/config/profiles/hermes/z890.yaml
  • pmoves/configs/claws/opencode-4090.json
  • pmoves/configs/claws/opencode-5090.json
  • pmoves/configs/claws/opencode-kvm2.json
  • pmoves/configs/claws/opencode-kvm4-1.json
  • pmoves/configs/claws/opencode-kvm4-2.json
  • pmoves/configs/claws/opencode-nemoclaw.json
  • pmoves/configs/claws/opencode-nemotron-claw.json
  • pmoves/configs/claws/opencode-spark.json
  • pmoves/configs/claws/scopes/4090.json
  • pmoves/configs/claws/scopes/5090.json
  • pmoves/configs/claws/scopes/kvm2.json
  • pmoves/configs/claws/scopes/kvm4-1.json
  • pmoves/configs/claws/scopes/kvm4-2.json
  • pmoves/configs/claws/scopes/nemoclaw.json
  • pmoves/configs/claws/scopes/nemotron-claw.json
  • pmoves/configs/claws/scopes/spark.json
  • pmoves/configs/claws/scopes/z890.json
  • pmoves/docs/operations/MCP_TOOLKIT.md
  • pmoves/mk/kilo.mk
  • pmoves/mk/mcp-toolkit.mk
  • pmoves/scripts/bootstrap-hermes-crush.sh
  • pmoves/scripts/bootstrap-node.sh
  • pmoves/scripts/mcp-toolkit-bootstrap.sh
  • pmoves/tensorzero/config/tensorzero.toml
  • pmoves/tests/test_mcp_config_generator.py
  • pmoves/tools/bootstrap_openclaw_scopes.py
  • pmoves/tools/bootstrap_opencode.py
  • pmoves/tools/crush_configurator.py
  • pmoves/tools/kilo_parity_mcp_check.py
  • pmoves/tools/mcp_config_generator.py

Comment thread kilo.json
Comment on lines +146 to +158
"pmoves-supabase": {
"type": "local",
"command": [
"npx",
"-y",
"@supabase/mcp-server-postgrest@0.1.1",
"--apiUrl",
"http://localhost:8000/rest/v1",
"--apiKey",
"${SUPABASE_SERVICE_KEY}",
"--schema",
"public"
]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve the Supabase service-role-key fallback.

Line 155 accepts only SUPABASE_SERVICE_KEY, unlike the corresponding Kimi configuration. Environments exposing only SUPABASE_SERVICE_ROLE_KEY will fail authentication.

Proposed fix
-        "${SUPABASE_SERVICE_KEY}",
+        "${SUPABASE_SERVICE_ROLE_KEY:-${SUPABASE_SERVICE_KEY}}",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"pmoves-supabase": {
"type": "local",
"command": [
"npx",
"-y",
"@supabase/mcp-server-postgrest@0.1.1",
"--apiUrl",
"http://localhost:8000/rest/v1",
"--apiKey",
"${SUPABASE_SERVICE_KEY}",
"--schema",
"public"
]
"pmoves-supabase": {
"type": "local",
"command": [
"npx",
"-y",
"`@supabase/mcp-server-postgrest`@0.1.1",
"--apiUrl",
"http://localhost:8000/rest/v1",
"--apiKey",
"${SUPABASE_SERVICE_ROLE_KEY:-${SUPABASE_SERVICE_KEY}}",
"--schema",
"public"
]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kilo.json` around lines 146 - 158, Update the pmoves-supabase configuration’s
--apiKey value to support the SUPABASE_SERVICE_ROLE_KEY fallback used by the
corresponding Kimi configuration, while retaining SUPABASE_SERVICE_KEY as the
primary variable. Preserve the existing PostgREST command and other arguments
unchanged.

Comment on lines +78 to +88
"key": "supabase-db",
"description": "Supabase Postgres database",
"transport": "stdio",
"command": "uvx",
"args": [
"postgres-mcp@0.3.0",
"--access-mode=unrestricted"
],
"env": {
"DATABASE_URI": "${SUPABASE_DB_URI}"
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C3 -- '--access-mode=(unrestricted|restricted)' .

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 9458


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== mcp_inventory context =="
ast-grep outline pmoves/config/mcp_inventory.json || true
echo
echo "== related references =="
rg -n -C 2 -- 'mcp_inventory\.json|supabase-db|postgres-mcp@0\.3\.0|--access-mode=' pmoves .github README.md 2>/dev/null || true
echo
echo "== file sizes =="
wc -l pmoves/config/mcp_inventory.json pmoves/tools/crush_configurator.py 2>/dev/null || true

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 50380


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== where mcp_inventory.json is consumed =="
rg -n -C 2 -- 'mcp_inventory\.json|mcp_inventory|inventory' pmoves .github README.md 2>/dev/null | head -n 200

echo
echo "== inspect the inventory file around the target entry =="
sed -n '60,100p' pmoves/config/mcp_inventory.json

echo
echo "== inspect crush_configurator around postgres-mcp entry =="
sed -n '240,290p' pmoves/tools/crush_configurator.py

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 21640


Make the shared MCP DB default read-only pmoves/config/mcp_inventory.json and pmoves/tools/crush_configurator.py both pin supabase-db to --access-mode=unrestricted, so generated client configs still get write access. Switch the shared default to restricted, or scope the writable variant to trusted clients only.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/config/mcp_inventory.json` around lines 78 - 88, Update the
supabase-db configuration in mcp_inventory.json and the corresponding generation
logic in crush_configurator.py to use --access-mode=restricted by default.
Ensure generated client configurations remain read-only, and only retain
unrestricted access where it is explicitly scoped to trusted clients.

| `make hermes-crush-bootstrap` | Updates Hermes Agent `~/.hermes/profiles/pmoves-hermes/config.yaml` and Crush CLI `~/.config/crush/crush.json` MCP sections from the inventory. |
| `make opencode-bootstrap` | Updates all `pmoves/configs/claws/opencode-*.json` node configs with canonical PMOVES MCPs (preserves existing zai/docker entries). |

Targets live in `pmoves/Makefile` (included from `pmoves/mk/mcp-toolkit.mk`). Scripts live in `pmoves/scripts/mcp-toolkit-*.sh` and `pmoves/scripts/bootstrap-hermes-crush.sh`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the target source location.

These targets are defined in pmoves/mk/mcp-toolkit.mk, which is included by pmoves/Makefile, not the reverse.

Proposed correction
-Targets live in `pmoves/Makefile` (included from `pmoves/mk/mcp-toolkit.mk`).
+Targets are defined in `pmoves/mk/mcp-toolkit.mk` and included by `pmoves/Makefile`.

As per path instructions, “Check docs for operational accuracy.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Targets live in `pmoves/Makefile` (included from `pmoves/mk/mcp-toolkit.mk`). Scripts live in `pmoves/scripts/mcp-toolkit-*.sh` and `pmoves/scripts/bootstrap-hermes-crush.sh`.
Targets are defined in `pmoves/mk/mcp-toolkit.mk` and included by `pmoves/Makefile`. Scripts live in `pmoves/scripts/mcp-toolkit-*.sh` and `pmoves/scripts/bootstrap-hermes-crush.sh`.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/docs/operations/MCP_TOOLKIT.md` at line 236, Correct the target
location statement in the MCP toolkit documentation to identify
pmoves/mk/mcp-toolkit.mk as the file defining the targets and pmoves/Makefile as
the file that includes it; leave the script locations unchanged.

Source: Path instructions

Comment thread pmoves/mk/kilo.mk
Comment on lines +100 to +107
mcp_gaps=$$(PYTHONPATH="$(CURDIR)/.." $(PYTHON) -m pmoves.tools.kilo_parity_mcp_check); \
gaps=$$((gaps + mcp_gaps)); \
if [ $$blocked -gt 0 ]; then \
echo "[*] Results: $$gaps gap(s) found, $$blocked item(s) blocked by platform (expected)"; \
else \
echo "[*] Results: $$gaps gap(s) found"; \
fi; \
if [ $$blocked -gt 0 ]; then \
echo "[!] Hook implementation blocked — see .kilo/hooks/damage-control/README.md for activation plan"; \
fi; \
exit $$gaps

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Capture the checker’s exit status, not its stdout.

kilo_parity_mcp_check.main() returns the missing count as its exit status and prints only to stderr. Command substitution therefore leaves mcp_gaps empty, so MCP gaps are never counted.

Proposed fix
-	mcp_gaps=$$(PYTHONPATH="$(CURDIR)/.." $(PYTHON) -m pmoves.tools.kilo_parity_mcp_check); \
+	PYTHONPATH="$(CURDIR)/.." $(PYTHON) -m pmoves.tools.kilo_parity_mcp_check; \
+	mcp_gaps=$$?; \
 	gaps=$$((gaps + mcp_gaps)); \
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
mcp_gaps=$$(PYTHONPATH="$(CURDIR)/.." $(PYTHON) -m pmoves.tools.kilo_parity_mcp_check); \
gaps=$$((gaps + mcp_gaps)); \
if [ $$blocked -gt 0 ]; then \
echo "[*] Results: $$gaps gap(s) found, $$blocked item(s) blocked by platform (expected)"; \
else \
echo "[*] Results: $$gaps gap(s) found"; \
fi; \
if [ $$blocked -gt 0 ]; then \
echo "[!] Hook implementation blocked — see .kilo/hooks/damage-control/README.md for activation plan"; \
fi; \
exit $$gaps
mcp_gaps=$$(PYTHONPATH="$(CURDIR)/.." $(PYTHON) -m pmoves.tools.kilo_parity_mcp_check); \
gaps=$$((gaps + mcp_gaps)); \
if [ $$blocked -gt 0 ]; then \
echo "[*] Results: $$gaps gap(s) found, $$blocked item(s) blocked by platform (expected)"; \
else \
echo "[*] Results: $$gaps gap(s) found"; \
fi; \
exit $$gaps
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/mk/kilo.mk` around lines 100 - 107, Update the MCP parity check
invocation in the Make target to capture the exit status returned by
pmoves.tools.kilo_parity_mcp_check rather than assigning command-substitution
stdout to mcp_gaps. Preserve the existing gaps accumulation, blocked-item
reporting, and final exit behavior.

Comment thread pmoves/mk/mcp-toolkit.mk
Comment on lines 6 to 8
# mcp-toolkit-connect is the only target that MUTATES a client's MCP config
# (writes .mcp.json at the repo root). It is gated on operator authorization —
# call explicitly, not as part of a wider chain.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update the mutation warning for the new bootstrap targets.

mcp-config-bootstrap, OpenCode/OpenClaw bootstrap, and Hermes/Crush bootstrap also mutate client configuration files. The “only target” claim is no longer true.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/mk/mcp-toolkit.mk` around lines 6 - 8, Update the mutation warning
comment near mcp-toolkit-connect to include mcp-config-bootstrap,
OpenCode/OpenClaw bootstrap, and Hermes/Crush bootstrap as targets that modify
client configuration files, and remove the claim that mcp-toolkit-connect is the
only mutating target while preserving the explicit-authorization guidance.

Comment on lines +174 to +182
def missing_envs(self, env_cache: Dict[Path, Dict[str, str]]) -> List[str]:
keys = list(self.required_envs)
if self.required_env:
keys.append(self.required_env)
return [
key
for key in keys
if not _lookup_env(key, env_cache)
]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Reject placeholder values as missing configuration.

missing_envs() only checks truthiness, so values such as your_*_here enable the MCP and produce a green configuration that cannot connect. Validate known placeholder patterns here and return those keys as missing.

As per path instructions, checks must be exhaustive and fail loudly on placeholders such as your_*_here. <path_instructions>

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/tools/crush_configurator.py` around lines 174 - 182, Update
missing_envs to treat known placeholder-pattern values, including your_*_here,
as missing in addition to empty or absent values. Add exhaustive placeholder
validation within the existing _lookup_env-based check, and return each affected
key so configuration cannot pass with unresolved placeholders.

Source: Path instructions

Comment on lines +196 to +223
MCPSpec(
key="pmoves-cipher",
config={
"type": "sse",
"url": "http://${TS_Z890}:8105/mcp/sse",
"headers": {"Authorization": "Bearer ${CIPHER_API_TOKEN}"},
"timeout": 30,
},
required_env="CIPHER_API_TOKEN",
),
MCPSpec(
key="pmoves-cipher-local",
config={
"type": "sse",
"url": "http://localhost:8105/mcp/sse",
"headers": {"Authorization": "Bearer ${CIPHER_API_TOKEN}"},
"timeout": 30,
},
required_env="CIPHER_API_TOKEN",
),
MCPSpec(
key="agent-zero",
config={
"type": "http",
"url": "http://${TS_Z890}:8080/mcp",
"timeout": 30,
},
),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Declare TS_Z890 as required for remote MCP endpoints.

Both URLs retain an unresolved ${TS_Z890} when the variable is absent, but Cipher only checks its token and Agent Zero checks nothing. Add TS_Z890 to their requirements so these servers are disabled instead of generated as unusable.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 199-199: Do not make http calls without encryption
Context: "http://${TS_Z890}:8105/mcp/sse"
Note: [CWE-319] Cleartext Transmission of Sensitive Information.

(requests-http)


[warning] 219-219: Do not make http calls without encryption
Context: "http://${TS_Z890}:8080/mcp"
Note: [CWE-319] Cleartext Transmission of Sensitive Information.

(requests-http)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/tools/crush_configurator.py` around lines 196 - 223, Add TS_Z890 to
the required_env declarations for the remote pmoves-cipher and agent-zero
MCPSpec entries, while leaving pmoves-cipher-local dependent only on
CIPHER_API_TOKEN. Ensure configurations with missing TS_Z890 are not generated.

Source: Path instructions

Comment on lines +242 to +260
MCPSpec(
key="pmoves-supabase",
config={
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@supabase/mcp-server-postgrest@0.1.1",
"--apiUrl",
"${SUPABASE_REST_URL:-http://localhost:8000/rest/v1}",
"--apiKey",
"${SUPABASE_SERVICE_ROLE_KEY:-${SUPABASE_SERVICE_KEY}}",
"--schema",
"public",
],
"timeout": 60,
},
required_commands=["npx"],
),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Disable Supabase unless either supported API key exists.

This spec remains enabled when both SUPABASE_SERVICE_ROLE_KEY and SUPABASE_SERVICE_KEY are missing. Extend MCPSpec with an “any-of” environment requirement and require at least one key.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/tools/crush_configurator.py` around lines 242 - 260, Update the
pmoves-supabase MCPSpec to use the MCPSpec any-of environment requirement,
requiring SUPABASE_SERVICE_ROLE_KEY or SUPABASE_SERVICE_KEY before enabling the
spec. Preserve the existing command, arguments, timeout, and required_commands
configuration.

Source: Path instructions

Comment on lines +113 to +120
val = env.get(var)
if not val and allow_os_environ:
val = os.environ.get(var)
if val:
result.append(val)
elif default:
# Recursively expand default so nested fallbacks resolve.
result.append(_expand(default, env))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

Preserve the no-environment policy during nested expansion.

The recursive call resets allow_os_environ=True. Thus tracked generation of ${SUPABASE_SERVICE_ROLE_KEY:-${SUPABASE_SERVICE_KEY}} can resolve the nested fallback from the process environment and commit the secret.

Proposed fix
-            result.append(_expand(default, env))
+            result.append(
+                _expand(default, env, allow_os_environ=allow_os_environ)
+            )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
val = env.get(var)
if not val and allow_os_environ:
val = os.environ.get(var)
if val:
result.append(val)
elif default:
# Recursively expand default so nested fallbacks resolve.
result.append(_expand(default, env))
val = env.get(var)
if not val and allow_os_environ:
val = os.environ.get(var)
if val:
result.append(val)
elif default:
# Recursively expand default so nested fallbacks resolve.
result.append(
_expand(default, env, allow_os_environ=allow_os_environ)
)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/tools/mcp_config_generator.py` around lines 113 - 120, The recursive
default expansion in `_expand` must preserve the caller’s `allow_os_environ`
value instead of re-enabling process-environment lookups. Pass that policy
through nested expansion so tracked generation cannot resolve nested fallbacks
from `os.environ` when environment access is disabled.

Source: Path instructions

Comment on lines +278 to +283
elif spec.transport == "stdio":
command, args = _split_command_args(spec.command or "", spec.args)
entry["type"] = "stdio"
entry["command"] = command
entry["args"] = _render_args(args, context, **kw)
else:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate relevant files =="
git ls-files | rg '(^|/)pmoves/tools/mcp_config_generator\.py$|(^|/)pmoves/.*(spec|mcp|config).*\.py$|(^|/)README\.md$'

echo "== outline generator =="
ast-grep outline pmoves/tools/mcp_config_generator.py --view expanded || true

echo "== relevant lines around target =="
sed -n '220,330p' pmoves/tools/mcp_config_generator.py | cat -n

echo "== search for env handling =="
rg -n "spec\.env|_render_env|\"env\"" pmoves/tools/mcp_config_generator.py pmoves -g '*.py' || true

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 22946


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import pathlib, re, json
path = pathlib.Path('pmoves/tools/mcp_config_generator.py')
print(path.exists(), path.stat().st_size if path.exists() else None)
PY

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 172


🌐 Web query:

Crush schema stdio env object official schema.json mcp env stdio server

💡 Result:

In the Model Context Protocol (MCP), the env field is a standard component within the configuration object for stdio servers [1][2][3]. It is used to define environment variables that the client should inject into the subprocess when spawning the MCP server [1][4][3]. Configuration Schema The schema for an MCP stdio server configuration generally includes the following fields [1][5][4]: - type: Must be set to "stdio" [1]. - command: The executable or path to the server command (e.g., "node", "python", "npx") [1][5][4]. - args: An optional array of strings representing command-line arguments [1][5][4]. - env: An optional object (dictionary) of key-value pairs representing custom environment variables [1][5][4]. Example Configuration A typical configuration in a client's settings (such as VS Code or Claude Desktop) looks like this [1][3]: { "servers": { "my-server": { "type": "stdio", "command": "npx", "args": ["-y", "my-mcp-server"], "env": { "API_KEY": "your-api-key-here" } } } } Important Implementation Details 1. Environment Merging: MCP SDK implementations (such as the Python SDK) do not always pass the entire host environment to the child process [6][4]. Instead, they often use a helper function (e.g., get_default_environment()) to merge a "safe" set of inherited variables (like PATH) with the custom variables provided in your env object [5][4][7]. 2. Security: By design, many implementations filter out potentially sensitive or dangerous environment variables by default to ensure the security of the subprocess execution [5][4]. 3. Client Responsibility: The env field is processed by the MCP client (the application launching the server), not the MCP protocol itself at the wire level [8][3]. Therefore, the specific schema and validation for env may vary slightly depending on the client application you are using [1][2][9]. While there is no single monolithic "official schema.json" that covers every client's implementation, the structure described above follows the established pattern used across major MCP SDKs and client configurations [1][5][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== generator target section =="
sed -n '1,220p' pmoves/tools/mcp_config_generator.py | cat -n

echo "== crush renderer section =="
sed -n '240,290p' pmoves/tools/mcp_config_generator.py | cat -n

echo "== related tests =="
sed -n '1,360p' pmoves/tests/test_mcp_config_generator.py | cat -n | sed -n '1,340p'

echo "== inventory entries with stdio/env =="
python3 - <<'PY'
import json, pathlib
p = pathlib.Path('pmoves/config/mcp_inventory.json')
data = json.loads(p.read_text())
for server in data.get('servers', []):
    if server.get('transport') == 'stdio' and server.get('env'):
        print(server.get('key'), server.get('env'))
PY

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 29081


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path('pmoves/config/mcp_inventory.json')
print("exists", p.exists())
if p.exists():
    import json
    data = json.loads(p.read_text())
    print("servers", len(data.get("servers", [])))
    for s in data.get("servers", []):
        if s.get("transport") == "stdio":
            print(s.get("key"), "env_keys=", sorted((s.get("env") or {}).keys()))
PY

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 183


Pass spec.env into Crush stdio entries.
render_crush() drops spec.env, so any stdio server that needs credentials or connection settings will be generated without them.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/tools/mcp_config_generator.py` around lines 278 - 283, Update the
stdio branch in render_crush() to include spec.env in the generated entry,
preserving the existing command and argument rendering while ensuring
environment variables are passed through to Crush stdio servers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

config pmoves/config(s)/ changes docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants