Repository navigation
feat(mcp): replace stub handlers with service dispatch - #102
Merged
Merged
Conversation
couragehong
marked this pull request as draft
May 5, 2026 23:11
couragehong
force-pushed
the
wip/go-impl-runtime
branch
from
May 6, 2026 22:33
12a7b11 to
6d2a85a
Compare
Deps gains 4 fields: State (*lifecycle.Manager), Capture/Recall/Lifecycle
service pointers. Adapter clients live on the services, populated by the
boot loop after Vault success.
Adds internal/mcp/result.go with two helpers:
- errorResult(err): JSON-marshals domain.MakeError(err) into TextContent +
IsError=true. Preserves the {ok,error{code,message,retryable,recovery_hint}}
shape of Python make_error.
- okResult(payload): JSON-marshals success payload into TextContent. Marshal
failure degrades to errorResult(INTERNAL_ERROR) instead of panicking.
stubHandler is still in place; subsequent commits replace per-tool wiring.
Adds internal/mcp/handlers.go with 8 typed handler factories — one per
tool. Each handler:
1. (write tools) CheckState gate → PIPELINE_NOT_READY when not active
2. (write tools) per-tool input validator (ValidateCaptureRequest /
ValidateRecallArgs)
3. service dispatch (Capture/Recall/Lifecycle method)
4. errorResult / okResult shaping (result.go)
Write tools (capture, batch_capture, recall, delete_capture) are
state-gated. Read/diagnostic tools (capture_history, vault_status,
diagnostics) bypass the gate so users can troubleshoot pre-active.
reload_pipelines also bypasses (it IS the dormant→active unblocker).
CheckState becomes nil-safe: Deps.State == nil returns PIPELINE_NOT_READY
with an explanatory hint instead of panicking.
Renames mustAddTool → mustAdd; the handler is now passed in as a typed
ToolHandlerFor[In,Out] argument rather than synthesized via stubHandler
generics. stubHandler / stubResult are removed.
Phase A.5 smoke test (register_test.go) updates:
- newSession constructs a usable Deps (NewManager + service factories,
State wired into Capture/Lifecycle); the empty-Deps regression check
is preserved at the catalog level
- TestRegister_StubReturnsIsError → TestRegister_WriteToolsGated:
asserts PIPELINE_NOT_READY for the 4 write tools instead of a stub
marker; reload_pipelines explicitly excluded with a doc note
- TestMustAddTool_PanicsOnInvalidName → TestMustAdd_PanicsOnInvalidName
buildDeps() constructs the State manager (lifecycle.NewManager) and the 3 services (Capture/Recall/Lifecycle), sharing the same Manager pointer across services so a single SetState transition is visible everywhere the gate looks. main() spawns RunBootLoop in the background. Adapter clients are NOT wired here — RunBootLoop is the right home for Vault.GetPublicKey + bundle parsing + envector.NewClient + embedder.New once those gRPC paths are real. With the boot loop currently a no-op stub (lifecycle/boot.go), the daemon stays in StateStarting forever and write tools surface PIPELINE_NOT_READY; read-only tools (vault_status, diagnostics, capture_history) work degraded so the operator can probe. Phase A.5 smoke + cmd test still pass.
Adds 2 test functions / 4 subtest cases on top of the existing
catalog/gating suite:
- TestRegister_ReadOnlyToolsBypassGate: vault_status / diagnostics /
capture_history must respond OK (not PIPELINE_NOT_READY) even when
State == StateStarting. Asserts:
* vault_status with nil Vault → 'standard' mode marker
* diagnostics → 4 of 7 sections present (environment, vault, keys,
embedding); skips state assertion because the field reflects
config.json (not Manager) and the test host may have a real one
* capture_history → ok:true, no error
- TestRegister_ErrorResultPreservesRuneError: triggers
PIPELINE_NOT_READY via rune_capture in StateStarting and json.Unmarshal-s
the TextContent. Asserts shape matches domain.MakeError(): ok=false,
error.code, error.retryable=false, error.recovery_hint mentions
'starting'.
Total mcp suite: 8 functions / 12 subtests, ~0.5s.
go test ./... ok across all packages.
…ols-impl audit-mcp-tools-impl.md: Tool catalog parity (8 names — Go uses rune_ prefix, Python bare name — documented intentional divergence). State gate parity (CheckState atomic vs Python _ensure_pipelines Event-wait). Validation parity (Python L1240/L910 ↔ Go state.go ValidateCaptureRequest/ValidateRecallArgs; 2 Go-stricter empty-input checks). Error response shape bit-identical (domain.MakeError matches Python make_error). Agent-delegated mode v0.4 narrowing (drops Python's legacy 3-tier fallback per D14/D21/D28). 6 open follow-up gaps including the largest — boot loop body stub. audit-production-readiness.md: Cross-cuts the 3 task PRs + integration base. P0 blocker: boot loop body (lifecycle/boot.go is no-op stub → write tools never reach Active). P1: RUNEVAULT_GRPC_TARGET env, embedder socket path resolver, FHE key disk persistence. P2: request_id propagation, Tier 2 fallback hookup, vector_dim verification, runed typed errors. P3: doc consistency, integration tag tests, dormant_reason persistence. Includes recommended PR ordering and an end-to-end smoke target.
couragehong
force-pushed
the
couragehong/feat/mcp-tools-impl
branch
from
May 6, 2026 22:35
bde38a0 to
276f973
Compare
couragehong
marked this pull request as ready for review
May 6, 2026 22:40
…-102 # Conflicts: # internal/mcp/tools.go
couragehong
added a commit
that referenced
this pull request
May 8, 2026
The Go rune-mcp at internal/* + cmd/rune-mcp/ has reached parity (PR #102 + #110 + #117) and end-to-end verification (#118, #122, #124), which means the Python tree is now dead weight. Carrying both implementations is actively misleading: a fresh contributor following the in-repo install instructions would still land in mcp/ + agents/ and try to set up a venv that no longer ships, and parity audits keep re-discovering the Python source instead of treating the Go side as the source of truth. Removed ------- agents/common/ 12 files (config, embedding, llm, schemas) agents/retriever/ 4 files (query_processor, searcher, synthesizer) agents/scribe/ 12 files (detector, llm_extractor, handlers, server) agents/tests/ 16 files (pytest suite) agents/__init__.py agents/README.md (Python agents intro — gone with the impl) agents/SLACK_SETUP.md (Slack notifier setup for Python scribe) mcp/ 18 files (Python adapter + server + tests) requirements.txt (root Python dependency list) scripts/migrate_embeddings.py (one-off Python migration helper) Total: 67 files, 17,815 lines. Kept (intentional) ------------------ agents/claude/{scribe,retriever}.md referenced by .claude-plugin/ plugin.json — agent prompts that the runtime loads agents/codex/scribe.md Codex-side agent prompt agents/gemini/{scribe,retriever}.md Gemini-side agent prompts benchmark/ deferred (separate decision — rewrite in Go vs delete entirely) docs/v04/spec/python-mapping.md parity blueprint that maps Python source to Go destinations; useful as a historical record post-deletion docs/migration/*.md migration plan + audit trail — intentional history scripts/bootstrap-mcp.sh and other referenced by gemini-extension.json; Python-era shell scripts removal blocked on Gemini support decision (separate PR) Not in scope ------------ .github/workflows/pr-tests.yml + pr-comment.yml — Python pytest CI; handled by PR #125 (ci-drop-python). README.md, CLAUDE.md, SKILL.md, AGENT_INTEGRATION.md, GEMINI.md, CONTRIBUTING.md — top-level docs still describe the v0.3 install flow; rewrite scheduled separately so this commit stays focused on code deletion. Verification ------------ go build ./... passes go vet ./... passes go test ./... full suite passes (no test referenced deleted paths) grep across remaining .{go,md,json,sh,toml,yml,yaml} for the deleted paths returned zero hits — no dangling references. Co-Authored-By: Claude Opus 4.7 (1M context) <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.
v0.4 go-migration - "not yet implemented" stub 으로만 떠있던 8개 MCP 핸들러를 실제 service dispatch 로 교체하는 작업입니다.
Deps구조체에State+ 3개 service (Capture/Recall/Lifecycle) 주입하고, write tools (capture / batch_capture / recall / delete_capture) 는CheckState게이트 통과해야 호출되도록,domain.MakeErrorshape 그대로 JSON 직렬화 후TextContent로 감싸고,cmd/rune-mcp/main.go도 같이 wiring —buildDeps()가 단일 Manager 포인터를 3개 service 가 공유하게 만들어서 한 번의SetState전이가 모든 게이트에 일관되게 반영되도록 하였습니다.중요한 한계:
lifecycle/boot.go RunBootLoop본체는 여전히 TODO 스텁. 즉, 이 PR 만 머지하면state가 영원히Starting에 머물러서 write tools 는 항상PIPELINE_NOT_READY로 떨어짐. read-only tools 는 정상 동작 (degraded mode 진단용). boot loop 본체 + config env 우선순위 + FHE 키 디스크 저장은 별도 후속 PR — 자세한 P0/P1/P2 분류는docs/v04/notes/audit-production-readiness.md참조.base 는
wip/go-impl-runtime. #93/95/96 머지 후 retarget.Scope
Tasks 1 + 2 of the v0.4 Go migration runtime impl: replace the Phase-A stub MCP handlers with state-gated service dispatch and wire
Depsconstruction incmd/rune-mcp/main.go.5 commits, 6 files of source + 2 audit docs (~818 LoC):
feat(mcp): expand Deps with services + add result helpers— Deps gets State + 3 services;result.goaddserrorResult/okResultfeat(mcp): replace stub handlers with state-gated service dispatch—handlers.goadds 8 typedToolHandlerFor[In,Out]factories. Write tools state-gated; read/diagnostic + reload_pipelines bypass.mustAdd(renamed) accepts a typed handler.CheckStatebecomes nil-safe.feat(mcp): wire Deps construction + boot loop in cmd/rune-mcp/main.go—buildDeps()shares one Manager pointer across services;main()spawnslifecycle.RunBootLoopin background.test(mcp): read-only bypass + error result shape coverage— 2 fn / 4 subtest on top of existing catalog/gating suitedocs(v04): add Python parity + production-readiness audits for mcp-tools-impl— 2 audit docs (mcp-tools parity + cross-cutting production readiness)Stacked-PR base
Base =
wip/go-impl-runtime, an integration branch that local-mergesthe still-under-review #93/#95/#96. With this base, the PR diff is exactly
the mcp-tools-impl work — no noise from the prerequisite ports.
When #93/#95/#96 merge upstream, rebase wip + retarget this PR's base to
feat/go-migrationvia GitHub UI.Spec
docs/v04/spec/components/rune-mcp.md§MCP Tools + §에러 처리 + §부팅 시퀀스docs/v04/overview/architecture.md§Scope (agent-delegated only)mcp/server/server.py(with Go-specificrune_prefix per spec code samples)mcp/server/errors.pymake_errordocs/v04/notes/audit-mcp-tools-impl.md+docs/v04/notes/audit-production-readiness.mdBehavior matrix
rune_captureCapture.Handlerune_batch_captureCapture.Batchrune_recallRecall.Handlerune_delete_captureLifecycle.DeleteCapturerune_capture_historyLifecycle.CaptureHistoryrune_vault_statusLifecycle.VaultStatusrune_diagnosticsLifecycle.Diagnosticsrune_reload_pipelinesLifecycle.ReloadPipelinesProduction-readiness
audit-production-readiness.mdflags one P0 blocker:lifecycle/boot.go RunBootLoopis still a no-op stub. Until a follow-up PR implements config-load + Vault dial + adapter wiring, write tools always surfacePIPELINE_NOT_READYin production. Read-only tools work degraded.This PR ships the handler wiring; the boot-loop body is intentionally a separate concern.