Skip to content

feat(v0.1): protocol layer, transports, session state machine, CLI — TDD#29

Merged
ksek87 merged 5 commits into
mainfrom
claude/plan-fuzzd-project-88AMD
May 9, 2026
Merged

feat(v0.1): protocol layer, transports, session state machine, CLI — TDD#29
ksek87 merged 5 commits into
mainfrom
claude/plan-fuzzd-project-88AMD

Conversation

@ksek87
Copy link
Copy Markdown
Owner

@ksek87 ksek87 commented May 9, 2026

Summary

Phase v0.1 — Protocol Foundation. Closes #1, #2, #3, #4, #5, #23.

  • MCP JSON-RPC type definitions (src/protocol/mcp.rs) — full serde-annotated type set: request/response envelope, all MCP lifecycle types (InitializeParams, ToolDefinition, CallToolResult, ToolContent, etc.), JSON-RPC error constructors
  • stdio transport (src/protocol/transport/stdio.rs) — spawns child process, newline-delimited JSON over stdin/stdout, async response correlation by request id
  • HTTP+SSE transport (src/protocol/transport/http.rs) — POST to /mcp, SSE subscription on /sse, event parsing and response correlation
  • Session state machine (src/protocol/session.rs) — Unconnected → Initializing → Ready → Closed, drives initialize handshake, list_tools, call_tool, enforces valid state transitions
  • Test harness (src/runner/harness.rs) — high-level wrapper used by fuzzer modules; caches tool list
  • CLI scaffolding (src/cli/mod.rs) — fuzzd audit / scan / corpus subcommands via clap derive; all flags wired
  • CI/CD (.github/workflows/ci.yml) — cargo fmt --check, cargo clippy -D warnings, cargo test, cargo build --release on every push/PR

Tests

37 tests, all passing. Every public type and state machine path has a unit test. Mock transport pattern used throughout — no network or real MCP server required for unit tests.

test result: ok. 37 passed; 0 failed

Test plan

  • cargo test passes locally
  • cargo clippy -- -D warnings clean
  • cargo fmt --check clean
  • CI workflow passes on this PR
  • fuzzd --help, fuzzd audit --help, fuzzd scan --help, fuzzd corpus --help all display correctly

https://claude.ai/code/session_014T1x8ZiDbJcVvkZBfP91nk


Generated by Claude Code

claude added 5 commits May 9, 2026 00:53
TDD implementation of Phase v0.1:
- MCP JSON-RPC 2.0 type definitions with serde roundtrip tests
- stdio transport (newline-delimited JSON, response correlation by id)
- HTTP+SSE transport (POST + SSE stream, response correlation)
- Session state machine (Unconnected → Initializing → Ready → Closed)
- Test harness wrapping session for fuzzer module use
- CLI scaffolding: audit, scan, corpus subcommands via clap
- GitHub Actions CI: fmt, clippy (-D warnings), test, release build

Closes #1, #2, #3, #4, #5, #23

https://claude.ai/code/session_014T1x8ZiDbJcVvkZBfP91nk
…rop cleanup

Bug fixes:
- Session initialized notification was routed through send() which registers
  an id and blocks waiting for a response that never arrives. Now uses the
  dedicated notify() path (fire-and-forget write, no pending map entry).
  New test `initialize_sends_notification` verifies the path is correct.
- Global REQUEST_COUNTER shared across all sessions caused id collisions under
  concurrent use. Replaced with per-session AtomicI64; two_sessions_have_
  independent_counters test confirms isolation.

Performance:
- HttpTransport pre-computes /mcp and /sse endpoint URLs once at construction
  instead of formatting strings on every send() call.
- HttpTransport uses Arc<Client> shared between SSE listener task and send path,
  eliminating a Client clone per connection.
- StdioTransport Drop impl calls start_kill() to prevent zombie child processes.
- Harness::tools() returns &[ToolDefinition] (zero-copy slice) for read access;
  enumerate_tools() still returns Vec for callers that need ownership.

Code quality:
- Extracted shared MockTransport into src/testutil.rs — no more duplication
  between session.rs and harness.rs test modules.
- Removed local IntoResult trait; replaced with module-level outcome_result()
  function (two-line match, no trait machinery needed).
- Removed parse_cmd() test helper from production transport code.
- Transport trait gains notify() as a first-class method, making the
  request/notification distinction explicit at every call site.

41 tests passing (up from 37).

https://claude.ai/code/session_014T1x8ZiDbJcVvkZBfP91nk
- Extract id_key() and PendingMap to transport/mod.rs — were copy-pasted
  identically in both stdio.rs and http.rs
- Add src/utils.rs with drain_sse_events() and sse_data() — SSE parsing
  logic extracted from http.rs into tested, reusable helpers; HTTP transport
  now acquires the pending map lock once per chunk instead of per response
- Add Session::ready() test constructor — replaces direct session.state
  mutation across all test bodies
- Add ok_response(), init_response(), tools_response() to testutil.rs —
  shared response builders used by both session and harness test modules
- Delete local init_response/tools_response from session.rs tests
- Simplify harness test module: local ready() helper eliminates repeated
  transport + state setup; test bodies now 2-3 lines each
- Add src/utils.rs to module tree in main.rs

43 tests passing (was 41 before simplify pass, was 37 originally).

https://claude.ai/code/session_014T1x8ZiDbJcVvkZBfP91nk
…n close

- StdioTransport: store reader_task JoinHandle, abort in Drop, clear
  pending map in close() so waiting callers get RecvError immediately
- HttpTransport: store sse_task JoinHandle, abort in Drop and close(),
  clear pending map in close(); replace from_utf8_lossy with str::from_utf8
  to skip malformed chunks rather than silently corrupting the SSE buffer
- session.rs list_tools(): move tools into self.tools directly, return
  a clone of the cached copy (single unambiguous ownership path)

https://claude.ai/code/session_014T1x8ZiDbJcVvkZBfP91nk
Captures non-negotiable rules: no unsafe, no repeated code, mandatory
JoinHandle/PendingMap resource management, UTF-8 handling policy, and
performance guidelines. Includes full annotated source tree and key
design invariants so the structure is always recoverable from context.

https://claude.ai/code/session_014T1x8ZiDbJcVvkZBfP91nk
@ksek87 ksek87 merged commit f8481f5 into main May 9, 2026
8 checks passed
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.

[v0.1] CLI scaffolding — clap with audit, scan, corpus subcommands

2 participants