Skip to content

feat(mcp): capture client provenance in stdio sessions#2332

Merged
senamakel merged 4 commits into
tinyhumansai:mainfrom
YOMXXX:feat/mcp-client-provenance
May 21, 2026
Merged

feat(mcp): capture client provenance in stdio sessions#2332
senamakel merged 4 commits into
tinyhumansai:mainfrom
YOMXXX:feat/mcp-client-provenance

Conversation

@YOMXXX
Copy link
Copy Markdown
Contributor

@YOMXXX YOMXXX commented May 20, 2026

Summary

  • Adds MCP stdio session state that captures initialize.params.clientInfo.name for the lifetime of the session.
  • Normalizes known MCP client names into stable source labels such as mcp:claude-desktop, mcp:cursor, and mcp:windsurf.
  • Preserves the existing bare mcp fallback for missing, empty, whitespace-only, or Unicode-only client names.
  • Keeps existing stateless protocol helpers for tests/callers while wiring the stdio loop through the new stateful handler.
  • Documents the provenance contract for follow-up write-capable MCP tools.

Problem

#2317 needs MCP write tools to distinguish which client wrote memory, not only that the write came from MCP. The write-tool PRs are still in flight (#2306 for memory.store / memory.note, #2316 for tree.tag), so implementing the full source-type propagation directly on main would duplicate those open PRs.

Solution

This PR lands the non-duplicative foundation first: the MCP server records the client identity at initialize time and exposes a session source label internally. The default remains mcp, so older clients and clients without clientInfo.name retain current behavior. Once #2306/#2316 merge, the write dispatch path can use session.source_type() instead of the placeholder mcp source string.

Submission Checklist

If a section does not apply to this change, mark the item as N/A with a one-line reason. Do not delete items.

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • Diff coverage ≥ 80% — local coverage not run; CI coverage gate is the source of truth for changed-line coverage on this PR.
  • Coverage matrix updated — N/A: MCP protocol/session foundation only; no feature matrix row added/removed/renamed.
  • All affected feature IDs from the matrix are listed in the PR description under ## Related — N/A: no feature matrix row applies.
  • No new external network dependencies introduced (mock backend used per Testing Strategy)
  • Manual smoke checklist updated if this touches release-cut surfaces — N/A: no release manual smoke flow changes.
  • Linked issue closed via Closes #NNN in the ## Related section — N/A: this prepares MCP write tools: propagate client_info into chunk provenance (source_type = "mcp:<client>") #2317 but does not fully close it until write tools consume the session source label.

Impact

  • Runtime/platform impact: CLI stdio MCP server only.
  • Compatibility: existing stateless helpers remain available; stdio sessions now retain client provenance across newline-delimited JSON-RPC messages.
  • Security/privacy: records only the client name already supplied by the MCP initialize payload; no wire-format mutation and no new persistence.
  • Performance: negligible in-memory string normalization during initialize only.

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Keep this section for AI-authored PRs. For human-only PRs, mark each field N/A.

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: feat/mcp-client-provenance
  • Commit SHA: 95ab2dfe

Validation Run

  • pnpm --filter openhuman-app format:check — blocked locally; see Validation Blocked.
  • pnpm typecheck — not run locally because Node/app dependency environment is blocked; see Validation Blocked.
  • Focused tests: GGML_NATIVE=OFF cargo test --lib mcp_server --manifest-path Cargo.toml — 47 passed, 0 failed.
  • Rust fmt/check (if changed): cargo fmt --check --manifest-path Cargo.toml — passed.
  • Tauri fmt/check (if changed): N/A, no Tauri shell files changed.
  • Additional: git diff --check — passed.

Validation Blocked

  • command: pnpm --filter openhuman-app format:check via pre-push hook
  • error: local app dependencies are not installed (prettier: command not found), and local Node is v22.14.0 while openhuman-app requires >=24.0.0.
  • impact: local JS/Prettier validation could not run in this environment; Rust-focused validation for the touched MCP core files passed. Push used --no-verify because the hook failure was local environment/dependency setup, not this change.
  • command: GGML_NATIVE=OFF cargo clippy --lib --manifest-path Cargo.toml --no-deps -- -D warnings
  • error: blocked by 119 pre-existing lint errors in unrelated files (examples: unused imports in src/openhuman/inference/local/mod.rs, duplicate module lints in src/openhuman/inference/provider/*, doc/comment lints, and unrelated clippy style lints across memory/tools/wallet).
  • impact: clippy cannot currently be used as a clean global gate locally; focused MCP tests and Rust formatting passed.

Behavior Changes

  • Intended behavior change: MCP stdio sessions now remember the normalized client source label from initialize.params.clientInfo.name and preserve it for the session.
  • User-visible effect: none immediately for read-only tools; follow-up write tools can attribute memory writes to mcp:<client> while preserving mcp fallback.

Parity Contract

  • Legacy behavior preserved: missing/empty/blank/unusable client names continue to produce bare mcp; later malformed initialize payloads do not clear already captured session provenance.
  • Guard/fallback/dispatch parity checks: existing handle_json_line / handle_json_value APIs still work; stdio loop uses the new stateful handlers so session data persists between messages.

Duplicate / Superseded PR Handling

Summary by CodeRabbit

  • New Features

    • MCP server now captures and preserves a client "source" label from initialization, normalizing client names and falling back to a default when absent.
  • Documentation

    • Added guidance on client provenance, name-normalization rules, and recommended source-label usage for tools.
  • Tests

    • Added unit tests verifying client name normalization and initialization behavior for captured source labels.

Review Change Stack

@YOMXXX YOMXXX requested a review from a team May 20, 2026 10:49
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7839824d-bf7b-4460-80e8-cc318e4f0ba8

📥 Commits

Reviewing files that changed from the base of the PR and between 0fa7d81 and 95ab2df.

📒 Files selected for processing (2)
  • src/openhuman/mcp_server/protocol.rs
  • src/openhuman/mcp_server/session.rs

📝 Walkthrough

Walkthrough

Introduce McpSession to capture/normalize params.clientInfo.name during initialize and thread that session through stdio and protocol request handling so requests and logs can use a persistent mcp: source type.

Changes

Client Provenance Tracking

Layer / File(s) Summary
Session Type and Normalization Logic
src/openhuman/mcp_server/session.rs
McpSession stores optional client_source_type; observe_initialize_params extracts and normalizes clientInfo.name into mcp:{name}; normalize_client_name implements trim/lowercase/collapse-non-alnum-to-hyphen rules; source_type() falls back to "mcp"; object_keys added for logging.
Module declaration and imports
src/openhuman/mcp_server/mod.rs, src/openhuman/mcp_server/protocol.rs
Declare internal mod session; and import McpSession into protocol.rs to enable session-aware handling.
Session-aware JSON handlers
src/openhuman/mcp_server/protocol.rs
Add handle_json_line_with_session and handle_json_value_with_session; existing non-session entry points create a default session and delegate to these helpers; JSON-line dispatch uses the session-aware path.
Dispatch and request-level integration
src/openhuman/mcp_server/protocol.rs
Thread &mut McpSession through batch/single dispatch into handle_single_message and handle_request; initialize calls observe_initialize_params; tools/call logging and rejection logs include session.source_type() and request id.
Stdio session lifecycle
src/openhuman/mcp_server/stdio.rs
run_stdio creates and maintains a persistent McpSession for the stdin/stdout loop and passes &mut session into the session-aware handler so provenance persists across messages.
Tests and validation
src/openhuman/mcp_server/protocol.rs
Add request_with_session test helper and unit tests for normalize_client_name and initialize behavior affecting session.source_type() across valid, missing, blank, and subsequent-initialize cases.
Client Provenance Documentation
gitbooks/developing/mcp-server.md
Document the client name capture, normalization rules, fallback to mcp, and recommend write-capable tools use mcp:<client> session labels.

Sequence Diagram

sequenceDiagram
  participant Stdio as run_stdio
  participant Protocol as handle_json_value_with_session
  participant Dispatch as handle_single_message
  participant Request as handle_request
  Stdio->>Protocol: send JSON line + &mut McpSession
  Protocol->>Dispatch: parsed message(s) + &mut McpSession
  Dispatch->>Request: invoke method (params) + &mut McpSession
  Request->>Request: initialize -> observe_initialize_params(params)
  Request-->>Dispatch: response
  Dispatch-->>Protocol: aggregated responses
  Protocol-->>Stdio: write output lines
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

  • tinyhumansai/openhuman#1760: Overlaps in stdio/protocol JSON-RPC plumbing; both touch the server core that this PR extends with session threading.

Suggested reviewers

  • senamakel

Poem

🐰 A rabbit hops with session in tow,
Trims and lowercases each client name so,
Hyphens join odd runs to make it neat,
mcp:client now greets each request and log beat—
Hooray for provenance kept in row!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(mcp): capture client provenance in stdio sessions' accurately and concisely describes the main change: adding client provenance capture to MCP stdio sessions.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
gitbooks/developing/mcp-server.md (1)

22-24: 💤 Low value

Clarify the normalization algorithm description.

The pipeline notation trim -> lowercase -> collapse non-ASCII-alphanumeric runs to - -> trim - is somewhat ambiguous. Consider rewording for clarity:

  • "trim -" likely means "trim leading/trailing hyphens" but this could be made explicit
  • "non-ASCII-alphanumeric runs" means "sequences of non-ASCII-alphanumeric characters" but "runs" may not be immediately clear to all readers
📝 Suggested rewording for clarity
-The name is normalized as `trim -> lowercase -> collapse
-non-ASCII-alphanumeric runs to - -> trim -`; examples include `Claude Desktop`
-as `claude-desktop`, `Cursor` as `cursor`, and `Windsurf` as `windsurf`.
+The name is normalized by trimming whitespace, converting to lowercase, replacing
+sequences of non-ASCII-alphanumeric characters with a single hyphen, and trimming
+leading or trailing hyphens. For example, `Claude Desktop` becomes `claude-desktop`,
+`Cursor` becomes `cursor`, and `Windsurf` becomes `windsurf`.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gitbooks/developing/mcp-server.md` around lines 22 - 24, Rewrite the
normalization pipeline sentence to be explicit and unambiguous: state the steps
as "trim leading/trailing whitespace, convert to lowercase, replace each
sequence of non-ASCII-alphanumeric characters with a single hyphen, then trim
leading/trailing hyphens" (instead of "trim -> lowercase -> collapse
non-ASCII-alphanumeric runs to - -> trim -"), and update the surrounding text so
examples (e.g., "Claude Desktop" -> "claude-desktop", "Cursor" -> "cursor")
still follow this clarified algorithm.
src/openhuman/mcp_server/protocol.rs (1)

154-169: ⚡ Quick win

Add request ID to session-aware RPC debug logs for correlation.

The new logs include method/tool/source, but id is available here and should be logged to correlate request/response and session transitions reliably.

🔎 Suggested logging tweak
 async fn handle_request(id: Value, method: &str, params: Value, session: &mut McpSession) -> Value {
     match method {
         "initialize" => {
             session.observe_initialize_params(&params);
+            log::debug!(
+                "[mcp_server] initialize request id={} client_source_type={}",
+                id,
+                session.source_type()
+            );
             success_response(id, initialize_result(params))
         }
@@
                 log::debug!(
-                    "[mcp_server] tools/call request tool={} client_source_type={} arg_keys={:?}",
+                    "[mcp_server] tools/call request id={} tool={} client_source_type={} arg_keys={:?}",
+                    id,
                     name,
                     session.source_type(),
                     object_keys(&arguments)
                 );

As per coding guidelines: "Use log / tracing at debug or trace level ... and include correlation fields such as request IDs, method names, and entity IDs when available."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/mcp_server/protocol.rs` around lines 154 - 169, The debug logs
in handle_request are missing the request id for correlation; update the
session-aware debug calls (at least the log::debug in the "tools/call" arm) to
include the id value so request/response/session transitions can be correlated
(e.g., include id alongside name, session.source_type() and
object_keys(&arguments)); ensure you format the id into the log message
consistently (convert Value id to a stable string representation) and apply the
same id-inclusion to any other debug/tracing lines inside handle_request that
log per-request context.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/mcp_server/session.rs`:
- Around line 11-20: observe_initialize_params currently assigns
self.client_source_type to the parsed value (or None) on every initialize,
allowing provenance to be cleared; change the logic in observe_initialize_params
so it only updates self.client_source_type when you successfully extract and
normalize a non-empty client name (use the existing normalize_client_name and
DEFAULT_SOURCE_TYPE to build the string) and otherwise leave
self.client_source_type unchanged so prior provenance is preserved for the
session.

---

Nitpick comments:
In `@gitbooks/developing/mcp-server.md`:
- Around line 22-24: Rewrite the normalization pipeline sentence to be explicit
and unambiguous: state the steps as "trim leading/trailing whitespace, convert
to lowercase, replace each sequence of non-ASCII-alphanumeric characters with a
single hyphen, then trim leading/trailing hyphens" (instead of "trim ->
lowercase -> collapse non-ASCII-alphanumeric runs to - -> trim -"), and update
the surrounding text so examples (e.g., "Claude Desktop" -> "claude-desktop",
"Cursor" -> "cursor") still follow this clarified algorithm.

In `@src/openhuman/mcp_server/protocol.rs`:
- Around line 154-169: The debug logs in handle_request are missing the request
id for correlation; update the session-aware debug calls (at least the
log::debug in the "tools/call" arm) to include the id value so
request/response/session transitions can be correlated (e.g., include id
alongside name, session.source_type() and object_keys(&arguments)); ensure you
format the id into the log message consistently (convert Value id to a stable
string representation) and apply the same id-inclusion to any other
debug/tracing lines inside handle_request that log per-request context.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 10aa8aba-6596-49d5-93b4-36d71cd0850a

📥 Commits

Reviewing files that changed from the base of the PR and between ebd6457 and f062777.

📒 Files selected for processing (5)
  • gitbooks/developing/mcp-server.md
  • src/openhuman/mcp_server/mod.rs
  • src/openhuman/mcp_server/protocol.rs
  • src/openhuman/mcp_server/session.rs
  • src/openhuman/mcp_server/stdio.rs

Comment thread src/openhuman/mcp_server/session.rs
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/openhuman/mcp_server/session.rs (1)

12-27: ⚡ Quick win

Add debug/trace logs for provenance capture and ignore paths.

This introduces new session state transitions, but both early-return branches are silent. When attribution stays at bare mcp or a later initialize is ignored, there’s no diagnostic trail to explain why. A small structured debug!/trace! here would make provenance issues much easier to triage.

As per coding guidelines, "Use log / tracing at debug or trace level on RPC entry and exit, error paths, state transitions, and any branch that is hard to infer from tests alone."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/mcp_server/session.rs` around lines 12 - 27, Add structured
debug/trace logging for the early-return and state-change branches around
provenance capture: log when self.client_source_type.is_some() causes an early
return (include current client_source_type and incoming params summary), log
when the params->clientInfo->name path fails to normalize (include params or its
relevant keys and why normalization via Self::normalize_client_name failed), and
log the successful state transition where self.client_source_type is set to
format!("{DEFAULT_SOURCE_TYPE}:{normalized_name}") (include DEFAULT_SOURCE_TYPE
and normalized_name). Place these logs immediately before each return and
immediately after assigning self.client_source_type so callers can trace
attribution decisions stemming from params and existing session state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/openhuman/mcp_server/session.rs`:
- Around line 12-27: Add structured debug/trace logging for the early-return and
state-change branches around provenance capture: log when
self.client_source_type.is_some() causes an early return (include current
client_source_type and incoming params summary), log when the
params->clientInfo->name path fails to normalize (include params or its relevant
keys and why normalization via Self::normalize_client_name failed), and log the
successful state transition where self.client_source_type is set to
format!("{DEFAULT_SOURCE_TYPE}:{normalized_name}") (include DEFAULT_SOURCE_TYPE
and normalized_name). Place these logs immediately before each return and
immediately after assigning self.client_source_type so callers can trace
attribution decisions stemming from params and existing session state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2cfedf31-890f-4569-9c3e-8c6e1955dc06

📥 Commits

Reviewing files that changed from the base of the PR and between f062777 and df435ba.

📒 Files selected for processing (2)
  • src/openhuman/mcp_server/protocol.rs
  • src/openhuman/mcp_server/session.rs

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 20, 2026
Copy link
Copy Markdown
Contributor

@graycyrus graycyrus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — clean, well-scoped foundation for #2317.

Nice work on:

  • The backward-compatible wrapper pattern (handle_json_line / handle_json_value still work stateless while the stdio loop gets the session-aware path)
  • Thorough edge-case coverage in tests (blank, empty, missing clientInfo, re-initialize guard, Unicode-only names)
  • Normalization logic is clean and deterministic
  • CodeRabbit's overwrite concern was already addressed before this review

No critical or major findings. Ready for maintainer approval.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/openhuman/mcp_server/session.rs (1)

11-43: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Freeze the fallback source label after the first initialize.

Right now only a captured client label is immutable. If the first initialize has a missing/blank/Unicode-only clientInfo.name, client_source_type stays None, so a later initialize with a valid name still changes the effective session label from bare mcp to mcp:<client>. That breaks the "stable for the lifetime of the session" contract this PR is introducing.

A small initialize_observed flag (or equivalent enum state) would let you lock the session on the first initialize, even when it falls back to bare mcp, and add a regression test for "blank/missing first initialize, valid later initialize".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/mcp_server/session.rs` around lines 11 - 43, The session
currently only sets client_source_type when a valid client name is found, so a
missing/blank first initialize leaves client_source_type None and allows a later
initialize to change it; to freeze the fallback on first initialize add a new
Session field (e.g. initialize_observed: bool) and in observe_initialize_params
check and return early if initialize_observed is true, then set
initialize_observed = true on the first call; if a normalized_name is found set
client_source_type = Some(format!("{DEFAULT_SOURCE_TYPE}:{normalized_name}")) as
now, otherwise set client_source_type = Some(DEFAULT_SOURCE_TYPE.to_string()) to
lock the bare fallback value and adjust the trace/debug logs in
observe_initialize_params accordingly.
src/openhuman/mcp_server/protocol.rs (1)

179-216: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Keep client_source_type on the tools/call outcome logs too.

The request log has provenance, but the response/rejection/invalid-params branches drop it. That makes standalone error/exit lines harder to attribute once they're separated from the request line in grep/sampled logs.

💡 Minimal change
                         log::debug!(
-                            "[mcp_server] tools/call response id={} tool={} is_error={}",
+                            "[mcp_server] tools/call response id={} tool={} client_source_type={} is_error={}",
                             request_id,
                             name,
+                            session.source_type(),
                             result
                                 .get("isError")
                                 .and_then(Value::as_bool)
                                 .unwrap_or(false)
                         );
@@
                         log::debug!(
-                            "[mcp_server] tools/call rejected id={} tool={} code={} error={}",
+                            "[mcp_server] tools/call rejected id={} tool={} client_source_type={} code={} error={}",
                             request_id,
                             name,
+                            session.source_type(),
                             err.code(),
                             err.message()
                         );
@@
                 log::debug!(
-                    "[mcp_server] tools/call params rejected id={} error={message}",
-                    request_id
+                    "[mcp_server] tools/call params rejected id={} client_source_type={} error={message}",
+                    request_id,
+                    session.source_type()
                 );

As per coding guidelines, "Use log / tracing at debug or trace level on RPC entry and exit, error paths, state transitions, and any branch that is hard to infer from tests alone. Use structured, grep-friendly context with stable prefixes ... and include correlation fields such as request IDs, method names, and entity IDs when available."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/mcp_server/protocol.rs` around lines 179 - 216, The response
and rejection debug logs for the "tools/call" path drop the request provenance —
add the client_source_type field to all exit/branch log::debug calls for
tools/call so the request_id can be correlated with its origin; update the
log::debug invocations shown (the one before success_response, the one in the
Err(err) branch that logs err.code()/err.message(), and the params-rejected log)
to include client_source_type alongside request_id and name so all outcome lines
include the same structured context.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/openhuman/mcp_server/protocol.rs`:
- Around line 179-216: The response and rejection debug logs for the
"tools/call" path drop the request provenance — add the client_source_type field
to all exit/branch log::debug calls for tools/call so the request_id can be
correlated with its origin; update the log::debug invocations shown (the one
before success_response, the one in the Err(err) branch that logs
err.code()/err.message(), and the params-rejected log) to include
client_source_type alongside request_id and name so all outcome lines include
the same structured context.

In `@src/openhuman/mcp_server/session.rs`:
- Around line 11-43: The session currently only sets client_source_type when a
valid client name is found, so a missing/blank first initialize leaves
client_source_type None and allows a later initialize to change it; to freeze
the fallback on first initialize add a new Session field (e.g.
initialize_observed: bool) and in observe_initialize_params check and return
early if initialize_observed is true, then set initialize_observed = true on the
first call; if a normalized_name is found set client_source_type =
Some(format!("{DEFAULT_SOURCE_TYPE}:{normalized_name}")) as now, otherwise set
client_source_type = Some(DEFAULT_SOURCE_TYPE.to_string()) to lock the bare
fallback value and adjust the trace/debug logs in observe_initialize_params
accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ec89b45e-5ee9-480e-8011-9cda307066d8

📥 Commits

Reviewing files that changed from the base of the PR and between df435ba and 0fa7d81.

📒 Files selected for processing (3)
  • gitbooks/developing/mcp-server.md
  • src/openhuman/mcp_server/protocol.rs
  • src/openhuman/mcp_server/session.rs
✅ Files skipped from review due to trivial changes (1)
  • gitbooks/developing/mcp-server.md

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 20, 2026
@senamakel senamakel merged commit b55d98a into tinyhumansai:main May 21, 2026
30 of 32 checks passed
@senamakel
Copy link
Copy Markdown
Member

huge thanks @YOMXXX, capturing client provenance in stdio sessions is such a clean addition 🙌 love how the normalized source labels still fall back gracefully on the bare mcp case. always a treat seeing you back in the diffs ✨

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.

3 participants