Skip to content

feat(adr-010): Phase 1 — Commonly MCP server + /room dual-auth - #243

Closed
lilyshen0722 wants to merge 2 commits into
mainfrom
feat/adr-010-phase-1-mcp-server
Closed

feat(adr-010): Phase 1 — Commonly MCP server + /room dual-auth#243
lilyshen0722 wants to merge 2 commits into
mainfrom
feat/adr-010-phase-1-mcp-server

Conversation

@lilyshen0722

Copy link
Copy Markdown
Contributor

Summary

ADR-010 Phase 1 (companion PR #242 for the ADR itself):

  • commonly-mcp/ new top-level package (@commonly/mcp@0.1.0) — stdio MCP server exposing CAP plus the dual-auth task surface as 14 standard commonly_* tools. Any MCP-capable runtime (codex CLI, Claude Code, future-N) loads one config entry and gets the kernel surface. Replaces the openclaw extension's hand-rolled commonly_* block as the long-term path.
  • Backend POST /api/agents/runtime/room → dual-auth via the established tasksApi.ts:34-36 pattern. The route's own header comment had named the agent-side gap; this closes it. The commonly_dm_agent MCP tool calls this path.
  • CI: commonly-mcp tests added to .github/workflows/tests.yml.

Tests

  • backend/__tests__/service/agentsRuntime.room.test.js — 8 tests (auth gating, both paths, 1:1 invariant, symmetry, self-DM 400, missing-arg 400). All pass locally.
  • commonly-mcp/__tests__/client.test.mjs + tools.test.mjs — 28 tests (env validation, request shape, error surfacing, per-tool wire shape). All pass locally.
  • Full-suite verification rides on this PR's CI run (laptop is too underpowered to run the full backend suite — exits 144 / OOM).

Reviewer fixes baked in (from a self-review pass)

  • replyToMessageId field rename — backend expects replyToMessageId; the first draft sent replyToId. Replies would have silently dropped.
  • Removed sinceId from commonly_get_messages — backend doesn't support it; advertising it would mislead the model.
  • req.agentUser fallback from installationagentRuntimeAuth only stamps req.agentUser for User-row tokens, not the legacy installation-token path. Without the fallback, legacy-token agents would 401 on /room.
  • dualAuth accepts x-commonly-agent-token as well as Authorization: Bearer so the alternate-header path doesn't silently route to the human handler.
  • CI step for commonly-mcp tests so the 28 unit tests are visible to the pipeline.
  • Smoke recipe in docs corrected (the original node -e 'require + import' form doesn't work in Node 20).
  • Removed unused _testHelpers export and the dead OPTIONAL_STRING alias.

Live smoke (post-deploy)

The dual-auth /room path needs to be deployed before the smoke runs. Once commonly-dev ships this commit, run:

```bash
TOKEN_FILE=~/.commonly/tokens/sam-local-codex.json
export COMMONLY_API_URL=$(node -e "console.log(require('$TOKEN_FILE').instanceUrl)")
export COMMONLY_AGENT_TOKEN=$(node -e "console.log(require('$TOKEN_FILE').runtimeToken)")
export SMOKE_POD_ID=69ef02b036b742e2e2c0c4af
export SMOKE_DM_TARGET=nova
node commonly-mcp/tests/smoke.live.mjs
```

Confirms: read memory (read-only), read pod context (read-only), and open an agent-room with nova (idempotent upsert) — all via the new commonly_* MCP surface against api-dev.

Sequencing

Test plan

  • CI green on `tests.yml` (backend + frontend + commonly-mcp + service-test + chart-lint)
  • Live smoke against api-dev post-deploy (commands above)
  • Wire sam-local-codex's environment spec to point at `commonly-mcp`; verify the agent's codex sees the new tool list

🤖 Generated with Claude Code

ADR-010 Phase 1: ship `@commonly/mcp` and refactor `POST /api/agents/runtime/room`
from human-auth-only to dual-auth so agents can open agent↔agent 1:1 rooms via
the new `commonly_dm_agent` MCP tool.

## What ships

- **`commonly-mcp/`** — new top-level package (`@commonly/mcp@0.1.0`). Stdio
  MCP server wrapping CAP (`/api/agents/runtime/*` per ADR-004) plus the
  dual-auth task surface (`/api/v1/tasks/*`) as 14 standard MCP tools matching
  the openclaw extension's `commonly_*` naming convention. Single-tenant per
  process, reads `COMMONLY_API_URL` and `COMMONLY_AGENT_TOKEN` from env at
  startup, fails fast if either is missing. 28 unit tests covering env
  loading, request shape, error surfacing, and per-tool wire shape.

- **Backend `POST /room` dual-auth** — refactored to dispatch via the
  established `tasksApi.ts:34-36` pattern (`cm_agent_*` prefix → agent path,
  else → human path). Agent path resolves caller via `req.agentUser` (with
  installation-token fallback for legacy tokens), refuses self-DM, calls
  existing `DMService.getOrCreateAgentRoom`. Human path unchanged below the
  new branch. 8 integration tests covering both paths + 1:1 invariant +
  symmetry.

- **CI step for commonly-mcp tests** in `.github/workflows/tests.yml` so the
  package is verified on every PR.

- **`docs/agents/COMMONLY_MCP.md`** — install + env-var contract + tool
  reference, copyable into a host runtime's `mcp_servers` config.

## Out of scope for this PR

- Phase 2 (OpenClaw migration) — separate PR after the openclaw-MCP support
  investigation.
- Phase 3 (Task #5 nova HEARTBEAT cutover) — mechanical once Phase 1 lands.
- Live smoke against api-dev — runnable post-deploy via
  `commonly-mcp/__tests__/smoke.live.mjs` (excluded from `npm test`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread backend/routes/agentsRuntime.ts Fixed
…limiting)

CodeQL flagged the refactored agent path on /room as missing rate-limiting.
The file already defines `phase4RateLimit` (120/60s) for the ADR-003 cross-agent
surface; applying it to /room matches the pattern, tightens the route uniformly
for both auth paths, and closes the CodeQL alert without a dismissal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread backend/routes/agentsRuntime.ts Dismissed
lilyshen0722 added a commit that referenced this pull request Apr 27, 2026
ADR-010 Phase 1: ship `@commonly/mcp` and refactor `POST /api/agents/runtime/room`
from human-auth-only to dual-auth so agents can open agent↔agent 1:1 rooms via
the new `commonly_dm_agent` MCP tool.

## What ships

- **`commonly-mcp/`** — new top-level package (`@commonly/mcp@0.1.0`). Stdio
  MCP server wrapping CAP (`/api/agents/runtime/*` per ADR-004) plus the
  dual-auth task surface (`/api/v1/tasks/*`) as 14 standard MCP tools matching
  the openclaw extension's `commonly_*` naming convention. Single-tenant per
  process, reads `COMMONLY_API_URL` and `COMMONLY_AGENT_TOKEN` from env at
  startup, fails fast if either is missing. 28 unit tests.

- **Backend `POST /room` dual-auth** — refactored to dispatch via the
  established `tasksApi.ts:34-36` pattern (`cm_agent_*` prefix → agent path,
  else → human path). Agent path resolves caller via `req.agentUser` (with
  installation-token fallback), refuses self-DM, calls existing
  `DMService.getOrCreateAgentRoom`. Human path unchanged below the new
  branch. 8 integration tests covering both paths + 1:1 invariant + symmetry.
  Rate-limited via `phase4RateLimit` (120/60s).

- **CI step for commonly-mcp tests** in `.github/workflows/tests.yml`.

- **`docs/agents/COMMONLY_MCP.md`** — install + env-var contract + tool
  reference, copyable into a host runtime's `mcp_servers` config.

## Out of scope

- Phase 2 (OpenClaw migration) — separate PR after openclaw-MCP investigation.
- Phase 3 (Task #5 nova HEARTBEAT cutover) — mechanical once Phase 1 lands.
- Live smoke against api-dev — runnable post-deploy via
  `commonly-mcp/__tests__/smoke.live.mjs` (excluded from `npm test`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@lilyshen0722

Copy link
Copy Markdown
Contributor Author

Squashed and merged manually as f4c76d4 (per local-squash convention to preserve authorship).

samxu01 added a commit that referenced this pull request Apr 28, 2026
…local-codex (#247)

Task #5 of ADR-005 Stage 3 / ADR-010 Phase 3. Nova's heartbeat retires
acpx_run as the codex implementation path and replaces it with DM-based
delegation to sam-local-codex.

Heartbeat is a separate model invocation per tick — nova posts a self-
contained task spec into her 1:1 agent-room with sam (podId hardcoded as
SamCodexDmPodId, pre-created via the dual-auth /room endpoint shipped in
PR #243), writes ## PendingDelegation to memory, and reads sam's reply
on the next tick. Five-branch decision tree (A: reply received, B: still
waiting, C: 90-min timeout → block, D: fresh task → delegate, E: idle).

Includes regression test asserting acpx_run is only in negative-instruction
lines, PendingDelegation + SamCodexDmPodId present, all five Branch labels.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants