pub enum Harness {
ClaudeCode,
Codex,
Cursor,
Cline,
Continue,
Aider,
Goose,
ClaudeDesktop,
Generic(String),
}Expand description
MCP harness detected from the initialize.clientInfo.name field.
The variants cover the harnesses called out in
docs/v0.7/compatibility-matrix.html (Track D2). Unknown harnesses
fall through to Generic(String) carrying the original
clientInfo.name so downstream logging / metrics can attribute
behaviour to the unrecognised client without losing the name.
serde uses snake_case so the wire shape matches the rest of the
v3 capabilities document. Generic carries an inner string and
serialises as {"generic": "<name>"} per serde’s default
externally-tagged enum representation.
Variants§
ClaudeCode
Anthropic Claude Code — supports deferred-tool registration via
ToolSearch. The only first-class harness today where B1’s
memory_load_family actually surfaces new tools mid-session.
Codex
OpenAI Codex CLI — eager-load only.
Cursor
Anysphere Cursor — MCP via stdio, eager-load only.
Cline
VS Code Cline extension — MCP via stdio, eager-load only.
Continue
Continue.dev (VS Code / JetBrains) — MCP via stdio, eager-load only.
Aider
Aider CLI pair-programmer — MCP via stdio, eager-load only.
Goose
Block / Square Goose — MCP via stdio, eager-load only.
ClaudeDesktop
Anthropic Claude Desktop — eager-load only.
Generic(String)
Unknown harness; carries the original clientInfo.name so the
operator can grep logs for “this is the harness I forgot to
register” without losing the identifying string.
Implementations§
Source§impl Harness
impl Harness
Sourcepub fn detect(client_name: &str) -> Self
pub fn detect(client_name: &str) -> Self
Detect a harness from the clientInfo.name field of the MCP
initialize request.
Matching is case-insensitive and fuzzy substring — the
raw name is normalised by lower-casing and stripping the
punctuation harnesses use as separators (-, _, ,
.) before comparison. So "claude-code", "Claude Code",
"claude_code", and "CLAUDE.CODE" all detect as
Harness::ClaudeCode.
Unknown names round-trip into Generic(<original>) preserving
the input verbatim so logging / metrics keep a useful label.
Sourcepub fn supports_deferred_registration(&self) -> bool
pub fn supports_deferred_registration(&self) -> bool
Whether this harness exposes tools registered after the
initial tools/list to the LLM mid-session.
true only for harnesses with documented deferred-tool
registration support. Today that’s just Claude Code via its
ToolSearch mechanism. Every other known harness eager-loads
the manifest at session start and won’t surface a tool added
later — so B1’s memory_load_family falls back to a
“restart with --profile <family>” hint on those harnesses.
Default for unknown harnesses (Generic): false
(conservative). It’s better to under-promise than to claim a
tool will appear and have the conversation strand on a stale
cached manifest.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Harness
impl<'de> Deserialize<'de> for Harness
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Harness
impl StructuralPartialEq for Harness
Auto Trait Implementations§
impl Freeze for Harness
impl RefUnwindSafe for Harness
impl Send for Harness
impl Sync for Harness
impl Unpin for Harness
impl UnsafeUnpin for Harness
impl UnwindSafe for Harness
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more