mandaire.com · For your life .app · For your product .dev · Architecture & trust .org

Common integration questions.

Questions from renderer LLM builders integrating with the Mandaire MCP server. If your question is not here, write to us.

Setup and auth

Do I need an SDK or library?

No. Mandaire is a standard MCP server. Add one URL to your AI client and auth runs automatically.

# Claude Desktop: add to claude_desktop_config.json { "mcpServers": { "mandaire": { "command": "mcp-remote", "args": ["https://mcp.mandaire.com/mcp"] } } } # ChatGPT: Settings → Connectors → + Add: https://mcp.mandaire.com/mcp # Claude.ai: Settings → Integrations: https://mcp.mandaire.com/mcp

No package to install. No client library to import. One URL, one permission grant, everything available.

How does auth work? Do I manage tokens?

OAuth 2.1 with Dynamic Client Registration. For Claude.ai and Claude Desktop, the OAuth flow runs automatically on first connect. You are redirected to Mandaire to authorize, then returned to your AI. No token rotation to manage yourself.

For custom clients: send a DCR POST /register to receive a client_id, exchange for a bearer token, attach to every request. The full OAuth metadata is at https://mcp.mandaire.com/.well-known/oauth-authorization-server.

One permission grant covers all routine access. You do not request per-tool or per-kind permissions separately.

How do I get a Mandaire account to build with?

Mandaire is in private beta. Request MCP access with a quick note on what you are building and which renderer you are using. We prioritize integrations with active development.

Queries

My query returned nothing. Is there a bug?

Three possible causes, in order of likelihood:

1. The fact is not in the graph yet. Check absent_knowledge_caveats in the response envelope. If Mandaire has no record for that person or event, the field will say so explicitly. This is expected for people or topics the user has never mentioned.

2. A disclosure policy hold. The query passed technically but the disclosure policy filtered the result. Check disclosure_applied. If filtered: true, the data exists but the user's policy blocked it for this caller or context. Do not retry with a different framing to circumvent this. The filter is intentional.

3. Wrong from_kind. A query for a person via from_kind="email" returns emails, not a person profile. Use from_kind="person" with depth="deep" to get the full profile including communications.

When the result is empty and the cause is (1), the envelope includes a writeback_slot_id. See writeback slots.

How do I find all available from_kinds?

Two options:

# Machine-readable spec (full catalog + verb table) get_protocol_spec() # Live catalog with current DB row counts mandaire(from_kind="server_status")

The partial read-kind list: person, email, message, event, photo, trip, note, file, topic, context, recall, open_commitments, catch_me_up, entity_state, inference_claim, open_writeback_slots.

Write kinds: ai_observation (INSERT), correction, task, state, inference_claim (UPDATE to confirm or reject).

When should I use depth=deep vs the default?

Default (depth="standard") returns the profile fields most relevant to the query. Use depth="deep" when you need the full picture for a person: all aliases, relationship history, recent communications, open commitments, inferred context. One call, no follow-up calls needed.

# ❌ Four calls to assemble one person profile mandaire(from_kind="person", from_match="Scott Hassan", fields=["name"]) mandaire(from_kind="email", from_match="Scott Hassan", ask="recent") mandaire(from_kind="message", from_match="Scott Hassan", ask="recent") mandaire(from_kind="event", from_match="Scott Hassan", filters={"days": 30}) # ✓ One call, full profile mandaire(from_kind="person", from_match="Scott Hassan", depth="deep")

The data owner's calls auto-upgrade to deep. External caller defaults remain standard unless specified.

The response has a confidence value. What do I do with it?

Phrase your output to match it. Do not present a 0.6 result as certain. A few practical rules:

confidence ≥ 0.90 State directly. "Scott's current role is..." confidence 0.70-0.89 Light hedge. "Based on recent context, Scott..." confidence 0.50-0.69 Explicit hedge. "This is my best read, but..." confidence < 0.50 Tell the user what you are uncertain about.

Also check expectedness: SUPPRESS means the user already knows this, SURFACE_NOVEL means lead with it, SURFACE_INTERESTING_IF_TRUE means surface it with the appropriate hedge.

Writebacks

When should my AI write back to the graph?

Three situations:

1. The user directly tells you something new. The user says "Scott just took the CTO role at Inflection." That is a claim_source="user_direct" INSERT with confidence ≥ 0.80.

2. A query returned a writeback slot. The SELECT returned empty and included a writeback_slot_id. Disclose the gap to the user. If they fill it in conversation, write it back with the slot ID.

3. You have inferred something with high confidence. Use claim_source="ai_inference" and keep confidence at or below 0.50. Low-confidence rows enter a 30-day review window before they influence future responses.

Do not write back information you are uncertain about at high confidence. Overstating confidence is worse than understating it.

What is a writeback slot? How long do slots stay open?

When a SELECT returns empty (count: 0 or found: false), the response envelope includes a writeback_slot_id. The slot is Mandaire saying: I do not know this yet. If the user tells you, close the loop.

# Nil result with a slot { "ok": true, "result": { "count": 0, "results": [] }, "writeback_slot_id": "wbs_7GNSA5G27X9ZH9ZYAQ64NPEZ90" } # Write back when the user fills the gap mandaire( verb = "INSERT", from_kind = "ai_observation", payload = { "claim": "Scott's new role is CTO at Inflection", "claim_source": "user_direct", "claim_tier": "factual", "confidence": 0.92, "trigger_reason": "nil_result_writeback", "entity_refs": ["[email protected]"], "writeback_slot_id": "wbs_7GNSA5G27X9ZH9ZYAQ64NPEZ90", }, )

Slots expire after 14 days if never closed. You can query open slots: mandaire(from_kind="open_writeback_slots").

What happens if I include sensitive PII in a write?

The INSERT is rejected before it reaches storage. PII pattern detection runs on every ai_observation and rejects claims containing raw credentials, payment data, SSNs, or passwords.

You do not need to pre-filter for these patterns. Write the claim as the user stated it. Mandaire rejects before storage and returns a clear error describing what was blocked.

What confidence value should I use on INSERTs?

1.0 Verbatim user quote (exact words, not paraphrased). 0.80-0.95 User paraphrase, or confirmed against a prior Mandaire record. 0.50-0.79 Strong inference; you can name the evidence chain. 0.00-0.50 Structured guess or plausible synthesis.

High-confidence rows (≥ 0.80 user-attributed) land silently and immediately influence future responses. Low-confidence rows (< 0.50) enter a 30-day review window. There is no penalty for being conservative. There is one for overstating.

Privacy and disclosure

What is disclosure_applied and do I need to handle it?

Every SELECT response includes a disclosure_applied field confirming that the user's disclosure policy ran before the response was returned:

"disclosure_applied": { "policy_version": "v0.1", "filtered": false }

If filtered: true, some fields were withheld by the policy. The response is complete as returned. Do not attempt to re-query or re-frame the request to get the withheld data. The filter is intentional and runs upstream of your call.

You do not need to implement your own disclosure logic. Mandaire handles it before your AI sees the result.

When do I need to include a purpose parameter?

Sensitive from_kind values require an explicit purpose= parameter. Without it, the call is rejected with a hint naming the required purpose.

Sensitive kinds include: correction_history, disclosure_policy, health data, personality profiles. Routine kinds like person, email, event, and recall do not require purpose by default.

If your query is rejected with a purpose_required error, the error message tells you what purpose value to include. The field is explicit by design: it creates an audit record of why the data was accessed.

How do I communicate knowledge gaps to the user?

Surface them. Do not invent answers. Two tools:

absent_knowledge_caveats in every response. These are facts Mandaire knows it does not have. "Last interaction: 3 months ago" is a fact. Tell the user.

Writeback slots when a query returns empty. Disclose the gap: "I do not have that in the graph yet." If the user provides the information, write it back. The next query finds it.

A gap surfaced honestly is more useful than a plausible answer invented from training data. Training data ages. The graph does not.

Question not answered here?

If you are blocked on something that is not covered above, write to [email protected]. We update this page as patterns emerge.

For the full verb shape and from_kind catalog, see the MCP docs. For the architecture behind the disclosure engine, see mandaire.org.