Skip to content

identifier fields (session/task/tool-use/client id) are bare String/Arc<str> with no newtype #2

Description

@bug-ops

Description

The crate models many distinct identifier concepts — session id, task id, tool-use id, elicitation id, OAuth client id, SSE event id / stream id — but represents essentially all of them as bare String or Arc<str>, or as plain type aliases over those (pub type SessionId = Arc<str>, pub type EventId = String, pub type StreamId = String). A pub type X = Y alias is fully interchangeable with Y and with any other alias of Y at the type-checker level, so it provides no protection against passing one id kind where another is expected. As the protocol surface grows (mrtr, task, request-state), the number of distinct id-shaped String parameters keeps growing, and the risk of a silent argument-order mix-up grows with it.

Reproduction Steps

  1. rg -n "_id: (String|Arc<str>)|Id\s*=\s*(String|Arc<str>)" crates/rmcp/src
  2. Observe multiple unrelated identifier fields (task_id, tool_use_id, elicitation_id, client_id, last_event_id) typed as plain String, alongside SessionId/EventId/StreamId aliases that are also structurally just Arc<str>/String.
  3. Any function taking two or more of these ids in sequence (e.g. something taking both a session_id: Arc<str> and a stream_id: String) compiles fine even if the arguments are swapped at a call site — the compiler cannot catch it.

Expected Behavior

Distinct identifier domains are represented as distinct newtypes (e.g. struct SessionId(Arc<str>), struct TaskId(String)), so swapping two id arguments of the same primitive shape is a compile error, not a runtime bug.

Actual Behavior

Identifiers are bare primitives or transparent type aliases; nothing in the type system distinguishes a TaskId from a SessionId from an EventId.

Environment

  • Version: v3.1.2 (current main, commit 02c62ae)
  • Features: N/A (affects model, task_manager, transport/auth.rs, transport/streamable_http_client.rs, transport/streamable_http_server/session/* regardless of feature set)

Locations

  • crates/rmcp/src/transport/common/server_side_http.rs:14pub type SessionId = Arc<str>;
  • crates/rmcp/src/transport/streamable_http_server/session/store.rs:10,13pub type EventId = String; / pub type StreamId = String;
  • crates/rmcp/src/model.rs:4239,4273,4310, crates/rmcp/src/model/task.rs:50, crates/rmcp/src/task_manager.rs:54task_id: String (repeated, no shared type)
  • crates/rmcp/src/model/content.rs:207tool_use_id: String
  • crates/rmcp/src/model.rs:3596,3705elicitation_id: String
  • crates/rmcp/src/transport/auth.rs:210,238,670,922,930,1055client_id: String

Upstream

None found — searched modelcontextprotocol/rust-sdk issues and PRs (all states) for "newtype session id task id" and "newtype id" with no matches.

Logs / Evidence

N/A — static analysis finding, no runtime reproduction needed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2High: degraded UX, incorrect non-destructive behaviorarchitectureArchitecture and structural designcode-qualityCode quality and maintainabilityenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions