01How it works
Daubert exposes one Model Context Protocol endpoint over Streamable HTTP: a single POST /mcp. It is stateless. There is no session id to hold, no socket to keep open, and no server side conversation to resume. Each request authenticates, builds the tool surface for that session, answers, and tears down.
The intelligence is your agent. Daubert runs no model of its own on this path. It holds the case file, the graph, the chain access, and the roles. Your agent decides what to call, and Daubert decides whether it may.
Any client that speaks remote MCP over HTTP can connect: the Claude apps, Claude Code, and ChatGPT in developer mode. Nothing in the tool surface is client specific.
A connected agent is a session, not an account. It sees what you can see and changes what you can change. Connecting one does not widen the door.
02Connect an agent
Paste one address, sign in, choose the organization. Dynamic client registration is supported, so there is no client id to generate and no secret to store, and nothing runs locally.
https://api.dauberts.ai/mcpOne thing to check first: you need a Daubert account holding admin or member on at least one organization. A guest cannot connect an agent. The same address is shown inside Daubert under Account · Connected Agents.
Claude
- 1Open Settings · Customize · Connectors.
- 2Scroll past the partner directory and click +, then Add custom connector.
- 3Name it "Daubert" and paste the address above.
- 4Leave Advanced settings empty. No client id is needed.
- 5Click Add. A browser tab opens where you sign in, choose the organization, and approve access.
One connector covers every Claude surface. Claude Desktop, claude.ai, Cowork, and Claude Code all read the same catalog once it is added to your account.
On a Team or Enterprise plan, your workspace admin registers Daubert once under Organization settings · Connectors. Everyone else then sees a Connect button on that entry.
ChatGPT
- 1Turn on developer mode first, under Settings · Plugins · Advanced. Custom MCP connectors do not appear until it is on. This is the step people miss.
- 2Click Create, name it "Daubert", and paste the address above. Keep the
/mcppath on the end. - 3Sign in when the browser opens, choose the organization, and approve access.
Two differences worth knowing. ChatGPT has no installable skill files, so ask your agent to call get_skill for the procedure it needs, or paste the daubert-overview text into Settings · Personalization · Custom instructions once. And without a way to pre-approve tools it may ask before each call. Approve once and it settles down.
What you are approving
The consent screen names the client asking for access, shows the address it will be redirected back to, and asks which organization the session is for. That choice is the whole scope of the session, and it cannot be changed afterwards. Connect a second agent, or a second organization, and you get a second session.
- Only admins and members can grant a session. A guest is refused at consent.
- The organization list is built from your own memberships on the server. A client cannot supply one.
- PKCE with
S256is the only accepted method. Clients are public, so no secret is ever issued. - Codes, tokens, and sessions have the lifetimes in Limits and lifetimes.
On the first call after connecting, the session label is enriched with the client's own name and version and the operating system it reported, so Claude Desktop becomes something like Claude Desktop 1.4.2 · macOS in your account. That is cosmetic. It is how you tell two sessions apart when you go to revoke one.
04Roles, and what they gate
There are two role systems, and MCP uses both. Your organization role decides whether you can connect an agent at all. Your case role decides what that agent can do on a given matter.
| Organization role | Can connect an agent | Implicit case role |
|---|---|---|
| admin | Yes | owner on every case in the organization |
| member | Yes | editor on every case in the organization |
| guest | No | None. A guest reaches a case only through an explicit membership on it |
Case roles are ranked viewer below editor below owner. A tool gated at viewer accepts all three. A tool gated at editor accepts editor and owner. An explicit case membership always wins over the implicit one, so a case can grant access more narrowly than the organization does.
The four gates on the tool catalog
| Gate | Meaning |
|---|---|
| viewer on the case | The case must belong to this session's organization, and you must hold viewer or higher on it. |
| editor on the case | The same organization gate, plus editor or higher. Every one of these writes an audit row. |
| organization | No case id involved. Scoped to the one organization the session is bound to. |
| any connected agent | No case scope. Bounded by the session gate and the per-session rate limit only. Chain lookups and skill reads sit here. |
Guests are refused at consent rather than at the tool. There is no version of this where a guest connects an agent and finds out later that nothing works.
05The words the tools use
These are the same words the app uses. When your agent reports what it did, this is what it means.
- organization
- The tenant. Every case, production, and connected session belongs to exactly one.
- case
- The matter. It carries members, investigations, productions, and a data room.
- investigation
- One line of inquiry inside a case. A case can run several.
- trace
- The graph itself, stored under an investigation. An investigation can hold more than one.
- node / edge
- An address on the graph, and a transfer between two of them. Tools hand edges to the agent denormalized, carrying the from and to addresses rather than internal ids.
- group / bundle
- Collapsed sets of nodes and of edges. They travel with the graph on reads.
- production
- Work product on the record: a
report, achart, achronology, adeclaration, or aredline. - declaration
- A production in one of five jurisdiction formats. The server renders the oath, the caption chrome, and the numbering. The agent supplies the content.
- redline
- A review of a draft someone else wrote. Creating one snapshots the draft's text into an immutable baseline, so the edits stay anchored to what was actually reviewed.
- data room
- The case's documents. Agents read them by id, and get extracted text back rather than raw bytes.
- declarant
- A saved expert witness profile: title, firm, qualifications, prior testimony, CV exhibit, rate, and disclosures.
- declaration library
- Reusable boilerplate blocks held across the organization, such as chain primers and authentication language.
- labeled entity
- A known address in the shared catalog: an exchange, a contract, a mixer, a service wallet.
- session
- One connected agent, bound to one user and one organization, revocable on its own.
- agent action
- One audit row. A write a session performed, with its target and its outcome.
- skill
- A workflow document. Seven are registered as prompts on connect, and any of them can be pulled mid task with
get_skill.
06Tool reference
Nineteen tools in four groups. You never call these yourself. Your agent does, in the course of working the matter, and the names are here so that when it tells you what it did, the sentence means something.
Find the matter
Where an agent starts. Nothing here reaches outside the organization the session is bound to.
list_casesorganizationList the cases you can see inside this session's organization.
None. The user and organization come from the session.
An array of { id, name, role }. The role is your effective role on that case.
- Takes no input. The user and organization come from the session, so a prompt cannot point it at a different organization.
get_caseviewer on the caseRead one case by id, including its investigations.
caseIduuidrequired
The case record with its investigations.
- The member list is hidden from viewers, the same way it is hidden in the app.
list_investigationsviewer on the caseList the investigations under a case.
caseIduuidrequired
The investigation rows for that case.
Read the case
The graph, the productions, the entity catalog, the declaration library, and the data room.
get_case_dataviewer on the caseOne aggregated overview of a case: investigations, productions, and the data room manifest.
caseIduuidrequired
{ investigations: [{ id, name, traceCount, totalNodes, totalEdges }], productions: [{ id, name, type }], dataRoom: { available, fileCount, truncated, files } }
- Production payloads are omitted. Use read_production for the contents of one.
- The embedded manifest stops at 25 files. Use list_data_room_files for the rest.
get_investigationviewer on the caseRead an investigation's graph, or a summary of every investigation in the case.
caseIduuidrequiredinvestigationIduuidoptional · omit for summaries across the whole caseaddressstringoptional · narrow to nodes and edges touching this addresstokenstringoptional · narrow to edges carrying this token symbol
Without investigationId: [{ id, name, notes, traces: [{ id, name, nodeCount, edgeCount }] }]. With it: the graph per trace, with nodes, edges denormalized to carry from and to addresses, groups, and bundles.
- Visual metadata such as node positions is stripped before the graph is handed to the agent.
- Exempt from the 8 KB result cap. A slimmed graph routinely exceeds it.
- An investigation id that does not belong to the case comes back as a normal result carrying { error }, not as a tool error.
read_productionviewer on the caseRead one production in full, or list every production on a case.
caseIduuidrequiredproductionIduuidoptional · omit to list instead of readtypereport | chart | chronology | declaration | redlineoptional · filters the list form
With productionId: the production including its data payload. Without: the summaries for the case.
query_labeled_entitiesorganizationLook up exchanges, contracts, and known wallets by address, or search the catalog by name and category.
addressstringoptional · exact lookup, takes precedencesearchstringoptionalcategoryentity categoryoptional
The matching entity for an address lookup, or the filtered list for a search.
- No case scope. The catalog is shared across the organization.
list_data_room_filesviewer on the caseThe data room manifest: id, name, mimeType, size, and folder path.
caseIduuidrequired
{ files, total, truncated } for up to 500 files. Check truncated before assuming the list is complete.
- Exempt from the 8 KB result cap.
read_data_room_fileviewer on the caseRead one data room file's contents.
caseIduuidrequiredfileIduuidrequired · from list_data_room_files or the get_case_data manifest
docx, pdf, xlsx, csv, and txt come back as extracted text. Images come back as an image block. A file over the limit comes back as a note stating its size.
- PDFs are read up to 32 MB. Every other type stops at 5 MB.
- Exempt from the 8 KB result cap.
get_declarantsorganizationThe organization's saved expert witness profiles, for filling a declaration's qualifications.
None. The user and organization come from the session.
{ declarants: [{ id, displayName, title, firm, qualifications, cvExhibit, priorTestimony, hourlyRate, nonContingencyDisclosure, dateOfBirth, address, userId }] }
get_declaration_libraryorganizationThe organization's reusable boilerplate blocks: technical chain primers and authentication language.
kind"boilerplate"optional
{ blocks: [{ id, kind, name, category, content }] }
get_skillany connected agentPull a workflow document by name when the agent needs the procedure mid-task.
namestringrequired · the tool description lists every valid name
The skill's markdown, frontmatter stripped. An unknown name returns { error } listing the valid names.
Pull from the chain
Seven chains on Daubert's server side API keys. There are no keys of your own to manage and no case scope on these calls.
blockchain_fetch_historyany connected agentTransaction history for an address: native transactions and token transfers, merged and sorted newest first.
addressstringrequiredchainethereum | polygon | arbitrum | base | tron | bitcoin | solanarequiredstartDateYYYY-MM-DDoptionalendDateYYYY-MM-DDoptionalmaxTotalintegeroptional · caps how many rows the server fetches
{ transactions, chain, address } and, when the payload had to be cut, truncated: true with totalCount so the agent knows how many rows exist.
- Bitcoin input and output arrays are collapsed to counts before the result is sized, so a large consolidation does not consume the whole budget.
- The array is trimmed to fit 8 KB rather than sliced mid object, so the agent always receives well formed JSON.
blockchain_get_transactionany connected agentOne transaction by hash.
txHashstringrequiredchainchain idrequired
From, to, amount, token transfers, and error status. Bitcoin rows carry the full input and output detail.
- Past 100 combined inputs and outputs the utxo block is collapsed to counts, the same way history rows are.
blockchain_get_address_infoany connected agentBalance, wallet or contract, and a known label if there is one.
addressstringrequiredchainchain idrequired
{ address, addressType, balance, label? }
Put work back in the case
Editor on the case is required. Every call, successful or refused, writes an audit row naming the session.
create_investigationeditor on the caseOpen a new investigation under a case.
caseIduuidrequirednamestringrequirednotesstringoptional
The created investigation.
- Audited as create_investigation against case:<caseId>.
import_transactionseditor on the caseWrite transactions into a trace.
traceIduuidrequiredtransactionsarrayrequired · from, to, txHash, chain, timestamp, amount, token, and optional blockNumber, fromLabel, toLabel, utxo, solana
A count of what was added, plus the nodes that were created.
- Addresses that are not yet on the graph become nodes automatically.
- Rows are deduplicated by transaction hash, sender, and recipient.
- The utxo and solana provenance blocks are strict. An invented or misspelled field inside them is refused rather than dropped, because a silently missing field there is a silently wrong exhibit.
- Audited as import_transactions against trace:<traceId>.
create_productioneditor on the caseStart a report, chart, chronology, declaration, or redline on a case.
caseIduuidrequirednamestringrequiredtypereport | chart | chronology | declaration | redlinerequireddataobjectrequired · declarations take formatId and caption. redlines take sourceFileId
The created production.
- Declaration formats: ca-declaration, ny-affirmation, federal-1746, tx-declaration, fl-declaration. The server seeds the section skeleton and renders the oath, caption, and numbering.
- tx-declaration additionally requires declarantDateOfBirth and declarantAddress.
- A redline snapshots the text of the source file into an immutable baseline at creation, so the review cannot drift from the draft it reviewed.
- Audited as create_production against case:<caseId>.
update_productioneditor on the caseRename a production, replace its payload, or apply atomic operations to it.
productionIduuidrequirednamestringoptionaldataobjectoptional · mutually exclusive with opsopsarrayoptional · mutually exclusive with data
The updated production.
- Chronology and chart operations are documented in the productions skill. Declaration operations are in the declarations skill. Redline operations are in the redlining skill.
- Redline anchors must be quoted verbatim, at least eight characters, and contained in one paragraph.
- Audited as update_production against production:<productionId>, recording which fields were touched.
07Prompts and skills
Tool names alone do not teach an agent how a declaration is structured or what a valid redline anchor looks like. Daubert registers seven workflow documents as MCP prompts, so the method arrives with the connection rather than having to be pasted into a system prompt.
| Prompt | What it covers |
|---|---|
| daubert-overview | Orientation. How Daubert is organized, the tool surface, the fetch to import workflow, the access model, and the execution constraints. The one an agent reads first. |
| graph-mutations | Adding, editing, and deleting nodes, edges, and groups inside a trace. |
| etherscan-apis | Etherscan V2 reference for EVM chain queries. |
| tronscan-apis | Tronscan and TronGrid reference for TRON queries. |
| productions | Building reports, charts, and chronologies for a case. |
| declarations | Drafting court ready declarations across the five jurisdiction formats, with the structured operations and exhibit conventions. |
| redlining | Reviewing a draft against the case record and proposing tracked changes anchored to the text. |
get_skill reads more than the seven registered prompts. Three further documents are available by name and are worth pulling when the work calls for them: bitcoin-apis for Esplora UTXO queries, solana-apis for the Helius parsed transaction API, and product-knowledge for answering questions about Daubert itself.
A missing skill file is skipped rather than fatal. A session with a document unavailable still connects, minus that prompt.
08Results, truncation, and errors
Tool results come back as JSON text. Most are capped at 8192 bytes. Past that the payload is cut and a suffix is appended saying how many bytes were dropped, so the agent is told explicitly that it is looking at part of something rather than treating a fragment as the whole.
What is exempt from the cap
get_investigationreturns the full graph. A slimmed trace routinely exceeds 8 KB and cutting it would produce a graph missing edges without saying so.list_data_room_filesreturns the manifest up to 500 entries, with atruncatedflag of its own.read_data_room_filereturns the document. Text extraction is the point of the call.
blockchain_fetch_history handles the cap differently again. Rather than slicing raw bytes and handing back broken JSON, it trims the transaction array to the number of rows that fit and sets truncated: true with totalCount, so the agent knows how much history exists beyond what it received. Bitcoin input and output arrays are collapsed to counts first, so one large consolidation cannot consume the entire budget.
Errors do not end the conversation
A refused or failed tool call comes back as a normal result marked isError, carrying the message. It does not throw through the transport and it does not close the session. The agent reads the message, corrects itself, and carries on. That is why an agent that asks for a case in the wrong organization can recover in the same turn instead of dropping the connection.
09Limits and lifetimes
| Limit | Value | Where it applies |
|---|---|---|
| Requests per address | 20 per minute | Before authentication runs. Refused with 429 and a Retry-After header. |
| Calls per session | 60 per minute | After the membership check, so a revoked session does not consume a bucket it no longer owns. |
| Tool result payload | 8192 bytes | Every tool except the three graph and document reads listed above. |
| Data room manifest | 25 files | Inside get_case_data. Use list_data_room_files for the full list. |
| Data room listing | 500 files | list_data_room_files. Check the truncated flag. |
| File read | 5 MB · 32 MB | Most types stop at 5 MB. PDFs are read up to 32 MB. |
| Access token | 1 hour | Refreshed automatically by the client, without a new consent screen. |
| Refresh token | 30 days | Sliding. Every exchange resets it, so an agent in regular use stays connected. |
| Authorization code | 60 seconds | Single use, between the consent screen and the token exchange. |
| Agent actions in the app | 50 rows | The most recent 50 agent writes shown under your account. |
Token lifetimes are the deployment defaults and can be tightened per environment. The rate limits are enforced per server instance.
10Chains
Chain access runs on Daubert's server side API keys. There is nothing for you to provision and no key to rotate.
| Chain | Id | Native | Address shape |
|---|---|---|---|
| Ethereum | ethereum | ETH | 0x followed by 40 hex characters |
| Polygon | polygon | MATIC | 0x followed by 40 hex characters |
| Arbitrum | arbitrum | ETH | 0x followed by 40 hex characters |
| Base | base | ETH | 0x followed by 40 hex characters |
| TRON | tron | TRX | T followed by 33 base58 characters |
| Bitcoin | bitcoin | BTC | bc1…, or a legacy 1… or 3… |
| Solana | solana | SOL | bare base58, 32 to 44 characters |
A legacy Bitcoin address starting 1 or 3 is also a valid base58 string, which makes it shape-ambiguous with Solana. Daubert resolves that in Bitcoin's favor, and the tool descriptions say so, so an agent picking a chain from an address alone does not silently query the wrong network.
Bitcoin transfers carry their UTXO provenance: inputs, outputs, fee, change evidence, and confirmation state. Solana transfers carry a transfer index, fee payer, and mint detail. Both survive import_transactions intact, and both are validated strictly on the way in, because a dropped field there is a wrong exhibit rather than a cosmetic loss.
11Audit and revocation
The case file records what the agent did the same way it records what you did.
- Every write is audited. The session, the user, the organization, the action, the target, and the outcome. Successes and refusals both.
- Failures are audited too. A write the role gate refused leaves a row saying so. An agent cannot probe for access quietly.
- Reads are not audited. They are bounded by role, not by paperwork.
- Audit rows outlive sessions. Revoke a session and its history stays, still labeled with the agent that did the work.
| Action | Target |
|---|---|
| create_investigation | case:<caseId> |
| import_transactions | trace:<traceId> |
| create_production | case:<caseId> |
| update_production | production:<productionId> |
Under Account · Connected Agents you see every session you have granted, with its label, when it was created, and when it was last used, alongside the most recent agent actions. Revoking one is immediate and affects only that session. Your other agents keep working.
Revocation is not the only kill switch. Removing someone from the organization stops all of their agents on the next call, without anyone having to find the sessions first.
12When something is wrong
- The sign-in loop repeats
- The client did not keep the token. Remove the connector and add it again. Registration is dynamic, so re-adding costs nothing and issues a fresh session.
- Everything stopped mid conversation
- Usually
membership_revoked. Your organization membership was removed or downgraded to guest. That check runs per call, so it takes effect immediately rather than when the token expires. - The agent says a case does not exist
- The id is not in this session's organization. Have it call
list_casesand work from those ids. A session is bound to one organization and cannot reach another. - Writes fail but reads work
- You hold viewer on that case. Reads are gated at viewer and writes at editor.
- Results arrive incomplete
- The 8 KB cap. Narrow the call: pass an
addressortokenfilter toget_investigation, a date range toblockchain_fetch_history, or read one production instead of listing them all. - Calls start failing in bursts
- A rate limit. Sixty calls a minute per session, twenty a minute per address before authentication. Both windows slide, so they clear on their own.
- The agent invents a workflow
- It has not read the procedure. Ask it to pull the relevant skill first, or invoke the matching prompt.
declarationsandredliningin particular carry rules that cannot be guessed from tool names.
Still stuck? Request access or get in touch and a person will read it. Tell us what the agent was doing and what came back instead.