feat(mcp): MCP client foundation (Phase 4.2) - #6
Merged
Merged
Conversation
…ry (Phase 4.2)
Adds the symbiote layer that complements the in-house Skills package
from PR 4.1. Where Skills are organelles the cell synthesises, MCP
servers are external symbionts the cell admits through a governed
membrane (allowed_mcps whitelist). This PR wires the client surface;
PR 4.3 grafts it onto RoleDefinitionConfig and CognitiveCore.
acc/mcp/ — new package
* manifest.py: MCPManifest pydantic model. Transport enum
(http | stdio), per-transport field-set validation (http demands
url, stdio demands command), tool allow/deny lists with manifest-
side gating via is_tool_allowed(), risk_level + requires_actions
governance hooks, lowercase-snake_case server_id validator.
* errors.py: MCPError → {ManifestError, ServerNotFound, ToolNotFound,
Connection, Protocol, Transport}. Shape mirrors acc.skills error
tree so contributors learn one pattern.
* client.py: MCPClient — JSON-RPC 2.0 envelope with monotonic id
allocator, MCP `initialize` + `tools/list` + `tools/call` methods,
cached tool advertisement (refreshable), bearer auth via
api_key_env, lazy connection on first call, idempotent
initialize(). Stdio transport is wired for future PR — the
manifest enum accepts the value, the client raises
NotImplementedError if used.
* registry.py: MCPRegistry — same load_from() / manifest() / list
surface as SkillRegistry, plus client(server_id) lazy
instantiation with HTTP-connection caching across hot-reloads
when the manifest is unchanged. close_all() releases
connections during agent shutdown.
mcps/ — directory convention
* mcps/_base/{mcp.yaml,README.md}: defaults document + minimum-
manifest walkthrough + transport status table + tool sandbox
rules + risk-level mapping + governance-hook reference.
* mcps/echo_server/mcp.yaml: stub diagnostic manifest pointing at a
hypothetical local echo server (acc-mcp-echo:8080). No server
process is shipped here; the manifest exists so the loader has
one row to validate against, and so the TUI Ecosystem screen
(Phase 4.4) is never empty on a fresh checkout.
Round-trip smoke tests (run locally, all green):
* Loader discovery + deep-merge: 1 server loaded as expected.
* Tool allow/deny gating: blocks forbidden names client-side.
* Manifest validation: http transport without url raises
ValidationError; stdio without command raises ValidationError.
* JSON-RPC envelope: against a mocked httpx, initialize →
tools/list → tools/call returns expected payload, manifest-
filtered tools are not advertised, manifest-blocked invocations
raise MCPToolNotFoundError.
Unblocks PR 4.3 (RoleDefinitionConfig.allowed_skills /
allowed_mcps + Cat-A A-017/A-018 + CognitiveCore wiring) and PR 4.4
(TUI Ecosystem live tables + how-to docs).
4 tasks
2 tasks
flg77
added a commit
that referenced
this pull request
May 9, 2026
Closes the deferral from the extension repo's v0.1 PR #6 (the documentation closer). Both INDEX docs now point operators living in Podman Desktop at the sibling extension that surfaces the same wire format as a webview. * `INDEX_subagent_clustering.md` — see-also entry for the cluster topology panel + extension docs. * `AUTORESEARCHER_index.md` — companion section enumerating the PD panels (Stack, Examples, Cluster, Compliance, Performance) that exercise the autoresearcher demo end-to-end inside PD. No code changes. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
flg77
added a commit
that referenced
this pull request
May 31, 2026
…ible state (v0.3.40) (#6) Closes follow-up #51. PR-MEM2 shipped in v0.3.1 but `acc/agent.py::_reflection_loop` is gated on `ACC_REFLECTION_INTERVAL_S > 0` and the baseline production compose never set it. Reflection loop returned immediately; the entire memory consolidation chain (episodes → reflection → memory_notes → Redis hot-cache → PR-I retrieval) has been silently disabled on every default deploy since v0.3.1. It only surfaced now because v0.3.37 unblocked the episode-persist producer side — episodes finally flow (verified `episodes` rows = 5 on lighthouse) but memory_notes stays 0. Three coupled changes: 1. `container/production/podman-compose.yml` — adds `ACC_REFLECTION_INTERVAL_S: ${ACC_REFLECTION_INTERVAL_S:-600}` to every agent service's `environment:` block (baseline + coding-split profile). 10-min default with operator override. 2. `acc/agent.py::_reflection_loop` — boot-time INFO log lines so the on/off state is operator-visible. Pre-v0.3.40 the loop was silent when disabled, hiding the fact that `memory_notes` was empty by configuration rather than failure. Now logs either: memory_reflection: disabled (ACC_REFLECTION_INTERVAL_S=0) or: memory_reflection: enabled interval=600s role=assistant agent_id=assistant-1 3. `tests/test_reflection_loop.py` — 4 new env-gating regression tests: - skipped when env unset (with disabled log line) - skipped when env="0" (with disabled log line) - enabled logs interval + role + agent_id - silent skip when cognitive_core is None (dormant worker contract preserved) Downstream consumers unblocked: - PR-I memory retrieval (queries memory_notes) - ACC-6a/11 centroid drift (uses memory_notes as priors) - SIP-P3 contextual prior (last_eval_reward + memory-informed) - Dreamer Phase 2 (M1 dedup, M2 prune) — operates on memory_notes Tests: 11 passing in tests/test_reflection_loop.py; 278 passing across the broader memory/agent/reflection sweep. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the symbiote layer that complements the in-house Skills package from PR 4.1. Where Skills are organelles the cell synthesises, MCP servers are external symbionts the cell admits through a governed membrane (
allowed_mcpswhitelist).This PR wires the client surface only. PR 4.3 grafts it onto
RoleDefinitionConfigandCognitiveCore; PR 4.4 surfaces it in the TUI Ecosystem screen.What's in the box
acc/mcp/— new packagemanifest.pyMCPManifestpydantic model. Transport enum (http/stdio), per-transport field-set validation (http demandsurl, stdio demandscommand), tool allow/deny lists withis_tool_allowed(),risk_level+requires_actionsgovernance hooks, lowercase-snake_caseserver_idvalidator.errors.pyMCPError→{ManifestError, ServerNotFound, ToolNotFound, Connection, Protocol, Transport}. Shape mirrors theacc.skillserror tree so contributors learn one pattern.client.pyMCPClient— JSON-RPC 2.0 envelope (monotonic id allocator), MCPinitialize+tools/list+tools/callmethods, cached tool advertisement (refreshable), bearer auth viaapi_key_env, lazy connection on first call, idempotentinitialize().registry.pyMCPRegistry— sameload_from()/manifest()/list_server_ids()surface asSkillRegistry, plusclient(server_id)lazy instantiation with HTTP-connection caching across hot-reloads when the manifest is unchanged.close_all()releases connections during agent shutdown.mcps/— directory conventionmcps/_base/{mcp.yaml, README.md}: defaults document + minimum-manifest walkthrough + transport status table + tool sandbox rules + risk-level mapping + governance-hook reference.mcps/echo_server/mcp.yaml: stub diagnostic manifest pointing at a hypothetical local echo server (acc-mcp-echo:8080). No server process is shipped here; the manifest exists so the loader has one row to validate against, and so the TUI Ecosystem screen (PR 4.4) is never empty on a fresh checkout.Transport status
httpstdioNotImplementedErrorif used. Subprocess-pipe transport will land in a follow-up PR.Round-trip smoke tests (run locally — all green)
urlraisesValidationError; stdio withoutcommandraisesValidationError.httpx,initialize→tools/list→tools/callreturns expected payload, manifest-filtered tools are not advertised, manifest-blocked invocations raiseMCPToolNotFoundError.Test plan
Out of scope for this PR
RoleDefinitionConfigfields (allowed_mcps) — comes in PR 4.3.CognitiveCoreinvocation surface — comes in PR 4.3.