# Using Connect from any MCP client

Every call is a single JSON-RPC 2.0 object posted to `https://connectbyjbrh.com/mcp`. Under revision 2026-07-28 no handshake is required: put the protocol version in `params._meta` and send `tools/list` or `tools/call` straight away. An older client may still send `initialize` first and will be answered.

- **Status:** Available
- **Audience:** developer
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/developers/mcp-client-generic/

## One call, end to end

```bash
curl -sS https://connectbyjbrh.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'MCP-Protocol-Version: 2026-07-28' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"search_public_docs",
                 "arguments":{"query":"call recording","limit":3},
                 "_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28"}}}'
```

No `Origin` header is sent, which is correct for anything that is not a browser. No cookie, token or session identifier is involved. The reply is one JSON object with a `result` containing both a text block and `structuredContent`.

## The methods a client may send

| Method | Params | Returns |
|---|---|---|
| `initialize` | `protocolVersion`, client info | The agreed version, the server's capabilities, `serverInfo`, and instructions telling a model to check status before claiming a capability |
| `ping` | — | An empty object |
| `tools/list` | — | Ten tool descriptors with input schemas and annotations |
| `tools/call` | `name`, `arguments` | A tool result, or a result with `isError: true` |
| `resources/list` | — | Four resource descriptors |
| `resources/read` | `uri` | The document, with its real media type |
| `resources/templates/list` | — | An empty list — there are no templated resources |
| `prompts/list` | — | Two prompt descriptors |
| `prompts/get` | `name`, `arguments` | A single user message ready to send to a model |
| `logging/setLevel` | any | An empty object; accepted and not acted on |
| `notifications/initialized` | — | Nothing; HTTP `202` |
| `notifications/cancelled` | — | Nothing; HTTP `202` |

Anything else raises method-not-found. The `initialize` result is worth reading even if you skip the handshake: its `instructions` field is the text that tells a model several Connect capabilities exist as foundation rather than as usable features, which is the single most useful correction a client can pass through to a model.

## Writing a minimal client

1. Decide whether to handshake. If your client is new, skip `initialize` and include `_meta` on every request. If it is an existing client for an older revision, send `initialize` and use the version in the reply.
   - Result: Either path is accepted; mixing them is fine too.
2. Send optional headers only if you mirror them exactly. `MCP-Protocol-Version`, `Mcp-Method` and `Mcp-Name` must match the body, or the request is rejected with `-32020`.
   - Result: Sending none of the three is the simplest correct choice.
3. Parse the body before the status line. A response can be HTTP `200` and still contain an error object — an unknown tool name arrives that way.
   - Result: Your client records failures accurately instead of counting a call to a non-existent tool as a success.
4. Handle `429` by waiting. The limit is 120 requests per minute per address and no `Retry-After` is sent.
   - Result: A widening delay clears it; an immediate retry does not.
5. Cache what you fetch, keyed on the page's `updated` date.
   - Result: The corpus changes on a deploy, not per request, so a cached page stays correct until the date moves.

## Reading a resource

```json
{"jsonrpc": "2.0", "id": 2, "method": "resources/read",
 "params": {"uri": "https://connectbyjbrh.com/docs-data/status.json"}}
```

The four resource URIs are absolute and are the same documents the website serves, so a client with an HTTP fetcher can read them directly instead — `llms.txt` for the map, `docs-manifest.json` for every page as JSON, `docs-data/status.json` for capability status, and the A2A card. Going through `resources/read` buys you the media type and one code path for everything; going direct buys you edge caching.

> **Note** A client sending an unknown resource URI gets method-not-found at HTTP `200`, not `404`, for the same reason an unknown tool does: the method was valid and the argument was not.

## Questions

### Can I keep a connection open?

There is nothing to keep open. Each request is an independent POST, no session is minted, and the standalone stream this revision removed does not exist here. Use ordinary HTTP connection reuse if you want fewer handshakes.

### What is the smallest useful call?

`get_product_status` with empty arguments. It returns the five status words, every documented capability with its status, and the corpus counts — enough to answer most capability questions without a second call.

### How do I know a tool result is bad without reading the prose?

Check `result.isError`. A successful call also carries `structuredContent`, so a program can branch on the presence of that field rather than on the wording of a sentence.

## Related

- [The Connect MCP server](https://connectbyjbrh.com/developers/mcp-server/)
- [Public MCP tools](https://connectbyjbrh.com/developers/mcp-public-tools/)
- [MCP error shapes](https://connectbyjbrh.com/developers/mcp-errors/)
- [Designing a resilient client](https://connectbyjbrh.com/developers/errors-and-retries/)
- [JSON-RPC 2.0](https://connectbyjbrh.com/docs/protocols/json-rpc/)
- [Streamable HTTP](https://connectbyjbrh.com/docs/protocols/streamable-http/)

## What this page is based on

- `backend/app/mcp_server.py` — _handle and the route handlers
- JSON-RPC 2.0 — https://www.jsonrpc.org/specification
- MCP specification 2026-07-28 — https://modelcontextprotocol.io/specification/2026-07-28
