> ## Documentation Index
> Fetch the complete documentation index at: https://retrievalcontextprotocol.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SDKs overview

> Four native SDKs — C++, Python, Node.js, and Rust — that speak the identical wire and interoperate byte-for-byte.

RCP ships **four native SDKs** that speak the identical wire format. Any client
drives any server across languages — proven by each SDK's test suite and the
shared conformance runner.

<CardGroup cols={2}>
  <Card title="C++" icon="c" href="/sdks/cpp">
    Header-only, C++23, type-theoretic. Protocol invariants proved at compile
    time.
  </Card>

  <Card title="Python" icon="python" href="/sdks/python">
    Pure standard library — no compiler, no dependencies, nothing to build.
  </Card>

  <Card title="Node.js" icon="node-js" href="/sdks/node">
    Pure standard library, ESM, async. Zero dependencies.
  </Card>

  <Card title="Rust" icon="rust" href="/sdks/rust">
    Zero dependencies, synchronous, `Result`-typed. Vendors its own JSON.
  </Card>
</CardGroup>

## What every SDK gives you

* A **`Client`** that connects over stdio or HTTP, runs the `initialize`
  handshake, and exposes typed, **capability-gated** calls (`retrieve`, `embed`,
  `rerank`, `graph`, …). A gated call to an unadvertised capability fails
  *client-side* before any I/O.
* A **`Server`** that owns the JSON-RPC framing, the handshake, capability
  gating, batching, and error mapping — you write handlers.
* A **`Selector`** for registry-driven [routing](/features/federation) with lazy
  connect and priority fallback.
* A **`filter`** module — a typed [builder + server-side validator](/features/metadata-filtering#the-canonical-builder-validator)
  for metadata filters, so clients never hand-write filter JSON and servers turn
  a malformed tree into a clean `-32602` instead of a `-32603` crash.
* **Reference algorithms** as importable, tested code, byte-for-byte identical
  across all four SDKs: [Reciprocal Rank Fusion](/features/federation#the-fusion-primitive-rrf-fuse)
  (`rrf_fuse` / `weighted_fuse`) and the compact
  [`f32-base64` vector codec](/methods/embed#compact-wire-encoding-f32-base64) —
  so no adopter re-derives the spec's fusion or encoding rules.
* Uniform errors surfaced as a typed error whose message is
  `"[RCP <code>] <message>"`, exposing `.code`, `.data`, `retryable()`.

## The shared shape

The four SDKs deliberately mirror each other (idiomatic per language):

| Concept          | C++                                 | Python                                  | Node.js                                 | Rust                                      |
| ---------------- | ----------------------------------- | --------------------------------------- | --------------------------------------- | ----------------------------------------- |
| Connect (stdio)  | `Client::connect_stdio(argv)`       | `rcp.connect_stdio(argv)`               | `await rcp.connectStdio(argv)`          | `rcp::connect_stdio(&argv)?`              |
| Capability check | `c.supports(Capability::Retrieve)`  | `c.supports(rcp.Capability.Retrieve)`   | `c.supports(rcp.Capability.Retrieve)`   | `c.supports(Capability::Retrieve)`        |
| Retrieve         | `c.retrieve(q, k)`                  | `c.retrieve(q, k=…)`                    | `await c.retrieve(q, k)`                | `c.retrieve(q, k)?`                       |
| Advertise        | `Capabilities{}.with_retrieve({…})` | `s.advertise(Capability.Retrieve, {…})` | `s.advertise(Capability.Retrieve, {…})` | `s.advertise(Capability::Retrieve, meta)` |
| Handle           | concept-gated hook                  | `@s.on(Method.RETRIEVE)`                | `s.on(Method.RETRIEVE, fn)`             | `s.on(Method::RETRIEVE, \|p\| …)`         |
| Serve            | `srv.serve_stdio()`                 | `s.serve_stdio()`                       | `await s.serveStdio()`                  | `s.serve_stdio()`                         |
| Fuse (RRF)       | `fusion::rrf_fuse(engines, k)`      | `rcp.rrf_fuse(lists, k=…)`              | `rcp.rrfFuse(lists, { k })`             | `fusion::rrf_fuse(&engines, Some(k), …)`  |
| Vector codec     | `vectors::encode_f32_base64(v)`     | `rcp.encode_vectors(v, "f32-base64")`   | `rcp.encodeVectors(v, rcp.F32_BASE64)`  | `vectors::encode_f32_base64(&v)`          |

<Info>
  Cross-language interop is not aspirational: the Python and Node test suites each
  include a case where their client drives the **C++** example server, the Rust
  suite drives both the C++ and Python servers, and the conformance suite runs
  against all four servers over stdio and HTTP.
</Info>
