Uh oh!
There was an error while loading. Please reload this page.
Remote query attach via kernel-intrinsic MCP (LLP 0033/0034) - #135
Conversation
Implements the client/kernel half of remote attach: a verb surface that projects one typed declaration into both a CLI command and an MCP tool, a stdio MCP host, and the --remote MCP client + credential store. - Verb surface: ctx.verbs registry, argv<->schema codec, verb->command/tool projection. query_sql (intrinsic) and graph_neighbors migrate to verbs. - hyp mcp: hand-rolled JSON-RPC stdio host (no SDK dep); tools from verbs, dataset schemas as resources; per-verb exposure + read/operator auth class. - Consumer side: --remote routes a verb to the remote MCP tool with the same render; query.remotes targets; 0600 credential store with env->file resolution; hyp remote add/login/list/remove; hyp mcp --remote proxy. --remote+--refresh is a hard error; two-line truncation surfacing. Remote path is E2E-blocked on the server's MCP route + scoped credential (out of tree); the client is unit-tested via an injectable fetch. Adds traditional tests + an mcp_stdio_tools hermetic smoke; full suite green, typecheck clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
philcunliffe
commented
Jun 23, 2026
Dual-agent review — |
| Source | Finding (severity, evidence) | Intersects |
|---|---|---|
| Claude | remote_commands.js untested (major, remote_commands.js) | Risk #3 (untested command surface) + Targets |
| Claude | default_remote dead config (minor, verb_codec.js:114 / schema.js:541) | Risk #5 + Config field chain |
| Claude | inline import() type (minor, verb_command.js:90; verbs.js:62,71) | Targets (style, no risk surface) |
| Claude | --port parsed but ignored (nit, core_commands.js) | Targets (hyp mcp arg parsing) |
| Claude | -o=<path> not recognized (nit, verb_codec.js:62) | Targets (codec) |
Recommended scope
Minimal: add
test/core/remote-commands.test.js(resolves the major); decidedefault_remote(wire it or drop it + the type-doc claim); fix the two inline-import()style violations.Expanded (optional): a
mcp-client.test.jscovering the SSE/array/401 branches and arunMcpProxyforwarding test with a fakefetchImpl; aserveStdioordering test (interleaved slow/fast tool calls).Out of scope: the server-side MCP route + scoped credential (separate repo, explicitly E2E-blocking the remote path);
graph_projectoperator-verb migration and local HTTP MCP (declared follow-ups).Codex review: (errored — no output)
Claude review
Claude review
Codex produced no output (auth/model error — gpt-5.5 unreachable via the local proxy); verdict rests on this Claude review. Five parallel review subagents ran: guidance-compliance, shallow-bug-scan, historical-context, contract-&-callers, comments-&-tests. Historical-context and contract-&-callers found nothing (the migration is behavior-preserving and every verbs touchpoint is wired). Findings below survived a ≥80 confidence filter.
remote_commands.js (add/login/list/remove) has no automated test
- Severity: major
- Confidence: 85
- Evidence: src/core/cli/remote_commands.js:1 (whole module, ~300 lines, not imported by any test or smoke)
- Why it matters: CLAUDE.md says to add traditional tests for deterministic logic incl. "config parsing and validation" and "similar local contracts". The create-or-augment local-config writer (
mutateLocalConfig), theloginTTY-without-token guard (the "never a hang" promise), token-from-stdin vs--token-file, andremote removedroppingdefault_remotewhen it names the removed target are all deterministic and untested;remote-credentials.test.jscovers the store but not these command wrappers. - Suggested fix: add
test/core/remote-commands.test.jsdriving the fourrunRemote*functions with a fake ctx/stdin over a tmpHYP_HOME(add→login-via-stdin→list→remove, the TTY guard, and the default_remote cleanup).
default_remote is dead config — bare --remote is unimplemented
- Severity: minor
- Confidence: 90
- Evidence: src/core/cli/verb_codec.js:114 (
--remotehard-errors when its value is missing); src/core/config/schema.js:541 (validates + storesdefault_remote); collectivus-plugin-kernel-types.d.ts (default_remotedoc: "Default target used by--remotewith no argument") - Why it matters: the config field is validated, stored, and cleaned up on
remote remove, and the type doc + LLP 0033 promise that bare--remoteresolves todefault_remote, but no code path ever reads it — sodefault_remotehas zero runtime effect and a bare--remoteerrors instead of using the default. - Suggested fix: either resolve
default_remotewhen--remoteis given no target, or (given the deliberate argv-ambiguity reason for deferring it) removedefault_remotevalidation/storage and the type-doc claim so it isn't misleading dead config.
Inline import('...') type in verb_command.js instead of a bare @import name
- Severity: minor
- Confidence: 90
- Evidence: src/core/cli/verb_command.js:90 (
/** @type {import('../../../collectivus-plugin-kernel-types.d.ts').VerbRenderResult} */) - Why it matters: CLAUDE.md Code Style: "Never use inline
import('...')types. Declare type imports at the top of the file with@importJSDoc comments, then reference the bare names." The file already has an@importblock, so this is internally inconsistent. - Suggested fix: add
VerbRenderResultto the top-of-file@importand use/** @type {VerbRenderResult} */.
Inline import('...') types in registry/verbs.js@returns
- Severity: minor
- Confidence: 90
- Evidence: src/core/registry/verbs.js:62 and src/core/registry/verbs.js:71 (
@returns {import('...').VerbExposure}/VerbAuthClass) - Why it matters: same CLAUDE.md rule; the file already imports other kernel types via
@importat the top. - Suggested fix: add
VerbExposure, VerbAuthClassto the@importand use bare names in both@returns.
hyp mcp --port is parsed but silently ignored
- Severity: nit
- Confidence: 80
- Evidence: src/core/cli/core_commands.js (parseMcpArgv returns
port;runMcponly branches onparsed.httpand never readsparsed.port) - Why it matters:
hyp mcp --port 8080(without--http) is accepted and boots the stdio host as if no flag were passed — a silent no-op; the--httpfollow-up error only fires when--httpis present. - Suggested fix: reject a stray
--port(or roll it into the--httpfollow-up error) so it isn't silently dropped.
-o=<path> inline short form is not recognized as --output
- Severity: nit
- Confidence: 85
- Evidence: src/core/cli/verb_codec.js:62 (
isFlag = token.startsWith('--') || token === '-o'—-o=filematches neither, so it falls through to the verb tail) - Why it matters:
--output=fileand-o fileboth work, but-o=fileis silently treated as a positional — inconsistent and surprising. - Suggested fix: treat a
-o=prefix as the output flag (e.g.token.startsWith('-o')).
Reports: /Users/phil/workspace/hypaware/.git/worktrees/remote-query-plugin/dual-review/pr-135
philcunliffe
commented
Jun 23, 2026
Codex review now available — verdict reaffirmed |
Uh oh!
There was an error while loading. Please reload this page.
Implements the client/kernel half of remote attach (LLP 0033/0034): a verb surface that projects one typed declaration into both a CLI command and an MCP tool, a stdio MCP host, and the
--remoteMCP client + credential store. The producer-side design folds the old@hypaware/remoteREST plugin into core.What's in here
Verb surface (new kernel contribution surface)
ctx.verbs.register({ name, tool, inputSchema, operation, render, exposure?, authClass? })—src/core/registry/verbs.js, wired intoKernelRuntime, the activation context, and the command run context.src/core/cli/verb_codec.js) — the single place CLI parsing for the query family lives; also emits the clean JSON Schema the MCP tool advertises, so the flag set and the tool schema can't drift.verb_command.js) — one declaration → CLI command + MCP tool.MCP host —
hyp mcpover stdio (src/core/mcp/{jsonrpc,server,stdio}.js)initialize/tools/list/tools/call/resources/*.Migrated to verbs:
query_sql(core, intrinsic, read-class) andgraph_neighbors(@hypaware/context-graph, read-class), reusing their existing pure cores + render machinery.Consumer side (
--remote) —mcp/{client,remote_verb,proxy}.js--remoteroutes a verb to the remote MCP tool with the same render;query.remotes/default_remoteconfig (validated, local-only per LLP 0031);0600credential store with env→file resolution;hyp remote add/login/list/remove;hyp mcp --remotestdio proxy fallback.--remote+--refreshis a hard error; two-line truncation surfacing (server cap + client display budget).Tests
6 new
test/core/*suites (codec, verb registry, MCP server, credentials, config validation, the--remotepath with a stubbed server) + themcp_stdio_toolshermetic smoke (bootshyp mcpagainst a seeded cache, asserts protocol-clean stdout + themcp.serve_startlifecycle log). Full suite 1331 pass / 0 fail, typecheck clean, lint clean.@ref LLP 0033/0034annotations attached throughout.Scope notes
fetch; the local stdio path is fully working now.graph_project/github_backfillas operator-class verbs (machinery + gating in place, not yet migrated);hyp mcp attachAI-client sugar; local HTTP MCP (hyp mcp --httprejected today); OS keychain for the cred store.context_graph_projects_rowssmoke fails on this branch and on the clean baseline — pre-existing, unrelated to this change.🤖 Generated with Claude Code