Trooth

Trooth

@trooth-engMITUpdated Today

Trooth is an infrastructure and cybersecurity company providing Machine-Readable Trust.

Server endpointStreamable HTTPNo authProbed

This is the third-party server itself — Odel doesn't run it. Hitting this URL directly talks straight to the upstream server with no auth or proxying. Connect through Odel to front it with managed auth.

trooth-mcp

The Trooth Network over the Model Context Protocol. Four read-only tools, public data, no key.

Trooth operates the Trooth Network: one public, signed, machine-readable record per company, carrying its identity, products and demos, commercial terms, domain and marketing links, people, documents, security and privacy posture, AI practices, procurement terms and relationships. It is Trooth's only product and it is free.

DNS says where a company is. A TLS certificate says the connection is authentic. The Trooth Network says who the company is and what it does with your data.

Trooth witnesses and dates facts. It does not grade, rate or rank anyone. No tool here returns a number that sums a company up, and no such number exists. An agent that wants one is being asked to invent it.

What is in this repository

A license, this README and server.json. There is no server code here, and there is nothing to install.

The server runs in the Worker behind api.trooth.co, which is a different repository. server.json is the manifest published to the official MCP Registry. What this repository is, therefore, is the registry record plus the description of a surface that lives somewhere else, and the honest thing to do is say which of the two any given fact came from.

Everything below was read from a committed file. The lines marked live were observed against the endpoint itself on 2026-09-24 by Trooth's verification script (scripts/verify-public-mcp.mjs in the site repository, not in this one), which writes its report to docs/rebuild-package/PUBLIC_MCP_VERIFICATION.md there. In that run nothing failed: the report lists 85 results that matched what was expected and 11 informational readings. That run is anonymous, from one network location, and says nothing about a later time.

The endpoint

URLhttps://api.trooth.co/public/mcp
MethodPOST only. Live: GET and DELETE both answer 405 with a JSON body saying so.
TransportStreamable HTTP, JSON-RPC 2.0, one JSON response per POST. No SSE stream, no batches. Live: a batch request is refused with -32600, malformed JSON with -32700.
SessionsNone, under any revision. Live: no Mcp-Session-Id header is ever minted.
AuthenticationNone. No key, no cookie, no account.
Protocol revision2026-07-28 is what the server leads with. 2025-06-18, 2025-03-26 and 2024-11-05 are still answered in full. Live: server/discover returned exactly those four.
Server identityLive: serverInfo is {"name":"trooth-mcp","version":"1.1.0"}.
CapabilitiesLive: {"tools":{"listChanged":false},"resources":{"listChanged":false,"subscribe":false},"prompts":{"listChanged":false}} and nothing else.
CORSLive: https://trooth.co is granted. A foreign origin is granted nothing, on the request and on the OPTIONS check before it.

2026-07-28 removed protocol-level sessions and the initialize handshake and added a required server/discover RPC. Which era a request belongs to is decided by the presence of the reserved _meta key, not by the version value, so an unknown future version is refused rather than quietly served as an old one. Live: a 2026-07-28 request that omits the MCP-Protocol-Version header is refused with -32020, and so is an Mcp-Method header that contradicts the body.

An older client is not stranded. Live: initialize asking for 2025-06-18 gets 2025-06-18 back, asking for 2024-11-05 gets 2024-11-05, and an unrecognized version falls back to 2025-06-18 rather than failing.

The four tools

Four, and there are no others. Live: tools/list returned exactly these names. Each takes one required string argument. Each answers with prose in content[0].text for a person and the same answer as a typed record in structuredContent for a machine, from a declared outputSchema. All four are annotated readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true.

trooth_public_trust_profile

Argument company: a domain or a Trooth slug.

Returns the company's published Trust Profile if it has one. A profile Trooth has witnessed comes back as witnessed_signed, with the date it was last witnessed where the record carries one; a published profile with nothing witnessed comes back as self_declared, the company's own words. A company listed in the public directory without a published profile comes back with its directory entry, labeled signed_scan (the API's name for that provenance). When Trooth holds nothing, the answer is an honest absence carrying provenance: "honest_absence" and a claim_url, which is not a guess and not a negative finding about the company.

It reads the same source as GET https://trooth.co/api/network/profile?q=, deliberately, so the machine answer and the human page are built from the same record. The Worker caches that read for up to 120 seconds, so a change can take that long to appear here.

trooth_outside_in_read

Argument domain.

A neutral read of that domain's public surface at the moment of the call: HTTPS and TLS reachability, the common security headers, security.txt. These are observations. They are not witnessed evidence, they are not a grade, and the response labels them that way. An outside-in read says what a stranger can see from the internet. It says nothing about what the company runs.

The input is hardened, and this is the one tool where that matters, because it is the only one that makes an outbound request on a caller's behalf. Live: an IPv4 literal, an IPv6 literal, localhost, the cloud metadata address 169.254.169.254, a hostname resolving into 10.0.0.0/8 and a hostname resolving to loopback are each refused as bad_input with the reason named. A URL is reduced to its host before anything is read.

trooth_verify

Argument token: a Trust Ledger Token in tlt2. or tlt. form, or its JTI.

Re-runs both signatures and answers valid, expired, revoked or invalid, the last when a signature does not match, which the answer tells you to treat as tampered. The limit travels in the answer: Trooth's signature covers the signing event and the payload at issuance, and never the truthfulness of the claims inside it. A caller that reads a valid token as proof that its claims are true has made the one mistake this product exists to prevent.

Live: an unknown token and outright garbage both come back as an honest absence. Neither is ever reported valid.

trooth_ask

Argument question.

Answers questions about Trooth itself: what the Network is, what one record carries, what it costs, how witnessing works. It is not a question-answering service about a company; a question about a company is answered by the three tools above, which cite what they read. Live: a question outside the curated corpus comes back out_of_scope rather than invented.

What comes back

structuredContent carries status, provenance, subject, summary and, where it applies, claim_url. Live: the status enum the server declares is exactly:

published  listed  unclaimed  private  observed  valid  invalid
expired  revoked  answered  out_of_scope  bad_input  unavailable

provenance is the label that keeps an observation from being read as a proof. The values the verification script holds the server to are witnessed_signed, signed_scan, live_observation, honest_absence, withheld_by_owner, knowledge_base, input_error, self_declared and read_failed. The live run exercised five of them: witnessed_signed, live_observation, honest_absence, knowledge_base and input_error, the last on every malformed argument.

Two states stay deliberately apart, and collapsing them would misrepresent a company:

  • unclaimed with honest_absence means Trooth holds no record. That is an absence of evidence, not a finding.
  • private with withheld_by_owner means a record exists and its owner chose not to publish it. That is a decision, not missing data.

Resources and prompts

Live: three of each.

Resource
trooth://methodologywhat witnessed means, how an outside-in read differs from signed evidence, and what an honest absence is
trooth://provenance-labelswhat each provenance label an agent sees here means
trooth://verify-a-vendorthe four-step reading sequence

Prompts: vendor_trust_check, verify_trust_token, before_you_trust.

Discovery

https://trooth.co/.well-known/mcp.json is Trooth's own descriptor, and that file says so in its own first line. MCP defines no .well-known path for advertising a server. The specification's answer to "what is this server" is the in-band server/discover RPC, which needs the URL you already have, and a Server Card document is an active working-group proposal (SEP-2127, Draft) whose experimental shape is GET <mcp-url>/server-card, not that path. The descriptor is published because a fixed address a person or an agent can guess is worth having, and it is named as Trooth's own so nobody cites it as a convention.

There is no OAuth metadata beside it, and that absence is written down rather than left to be discovered. The MCP specification makes an authorized HTTP server an OAuth 2.0 protected resource; none of that applies here, because this server takes no credential and the four tools read data already public to any browser. So there is no protected resource, no protected-resource metadata and no authorization server, and the descriptor's protectedResourceMetadata is null rather than a URL nobody serves.

The registry record

The current record is io.github.troothllc/trooth-network, named for the troothllc organization that owns this repository. io.github.* is the registry's GitHub-authenticated namespace, which is why no signing key and no DNS proof are needed.

It is published from this repository by .github/workflows/publish-registry.yml. The registry's GitHub OIDC sign-in grants a workflow the namespace of the repository's owner, here io.github.troothllc/*, so a publish needs no secret and no one person at a device sign-in. The workflow runs only when someone starts it. It installs a pinned mcp-publisher release, signs in with mcp-publisher login github-oidc, publishes server.json, and reads the record back from the registry.

server.json in this repository is version 1.1.4, the first version under the organization's name. Until the registry serves it, https://trooth.co/.well-known/mcp.json declares it as registry.pendingVersion, and the site's checks accept either name.

The previous record is io.github.trooth-eng/trooth-network, published under a personal GitHub account, and it is superseded. Live: the registry read back on 2026-09-25 served its 1.1.3 as the latest version, pointing at {"type":"streamable-http","url":"https://api.trooth.co/public/mcp"}, the same endpoint the current record names. The registry gives one endpoint to one record: it refuses a record whose remote URL a version of another record still uses, and only a version marked deleted releases it, deprecated or not. The first publish under the current name was refused for exactly that reason. So before the publish, every version of the previous record is marked deleted, with a message that names the current record. Deleted is a status on the registry, not an erasure: the versions are kept and can be restored, and if the publish had failed they would have been put back as they were.

The manifest version and the running server's version are two different numbers on purpose, and since 2026-09-17 they have not matched: the publish was refused with 400 cannot-publish-duplicate-version because 1.1.0 was already on the registry, so the payload went out as 1.1.1 while the Worker kept reporting 1.1.0. 1.1.2, published 2026-09-19, changed the description, 1.1.3, published 2026-09-25, wrote out its ampersand, and the Worker still reports 1.1.0. Both numbers are recorded on every verification run, so a drift shows up in its report.

What this server does not offer

No long-running work, and no task handle. 2026-07-28 changed the core lifecycle and removed sessions; it does not define a task lifecycle. Long-running work in MCP lives in a separate extension identified as io.modelcontextprotocol/tasks, published in draft beside the revision rather than inside it, and opt-in on both sides. Live: this server's capabilities are tools, resources and prompts and nothing else. There is no task capability and no task method. The Worker's code sets resultType to "complete" on every 2026-07-28 result.

Stated so nobody has to infer it: a client that supports the Tasks extension needs no special handling here and should offer none. All four tools are bounded reads that answer in the ordinary tools/call response. Trooth never returns a task handle and invents no field the revision it negotiated does not define. A client that does not support the extension is in exactly the same position, which is the point of saying so.

No authenticated surface. There is no signed-in company or buyer an agent can act as. Nothing here writes. Earlier plans listed a further ten public tools, eight buyer tools and eight company tools; none of them is built, and the reason is the same for all of them.

No unknown tool runs. Live: a call to a tool that does not exist answers -32602 and executes nothing. A call with no arguments at all degrades to bad_input rather than throwing.

Monitoring

A scheduled job in the site repository POSTs tools/list to the live endpoint every five minutes (GitHub may delay a scheduled run under load). Be clear about what that proves and what it does not: it checks the HTTP status code and that each of the four tool names appears somewhere in the body, so it catches the endpoint being down or losing a tool, and would not catch an extra tool, a changed schema or a wrong answer from a tool. The catalog and the served surface are compared properly by the verification run above, which is not continuous.

A test in the site repository holds the output contract published on trooth.co/docs/agents in two ways: against the status values the last verification run recorded, and against the Worker's provenance values when the Worker's repository is cloned beside it. Without that clone, its provenance check only confirms that the page publishes every provenance value the last run saw, and it says the fuller comparison was skipped. It is only as current as that last run.

Add it

The steps below restate each vendor's own pages as trooth.co/docs/agents read them in September 2026. That page carries the plan limits, the removal steps and the sources.

ChatGPT: Trooth Network is listed in the ChatGPT app directory. Open the listing; OpenAI says whether an app is offered to you depends on your plan, region, workspace and role. To add it by hand instead you need Developer mode, which OpenAI lists for Plus, Pro, Business, Enterprise and Education accounts on the web and not for the Free plan: Settings, then Security and login, then turn on Developer mode; then open Plugins, press +, give it a name and paste the endpoint.

Claude: Customize, then Connectors, then Add custom connector, then paste the endpoint and press Add. If the dialog asks how people sign in, choose No sign-in. On Team and Enterprise an owner adds it for the organization first.

Cursor, Cline, VS Code, or any other MCP client: add a remote MCP server pointing at https://api.trooth.co/public/mcp. There is no key to configure.

What earlier versions of this file got wrong

Named rather than quietly corrected, because a reader who acted on one of them deserves to know which line moved.

  • The status table omitted unavailable. The server declares thirteen values and the table listed twelve, so a client branching exhaustively on that table had an unhandled case.
  • The provenance table listed six values and omitted input_error, which is the label on every answer any of the four tools gives to a malformed argument. It is the one a client is most likely to meet first.
  • The last published version of this file said server.json here and the copy served at https://trooth.co/.well-known/mcp-server.json both carried version 1.1.1 with different description fields, and that the registry held 1.1.1. That was out of date: server.json here and the registry's latest record are now both 1.1.2, published 2026-09-19; the website's copy is the prepared, unpublished 1.1.3 described under The registry record.
  • The last published version of this file said server.json here was 1.1.2 and that a 1.1.3 payload was prepared and not published. That was out of date: server.json here carried 1.1.3, which was published on 2026-09-25 under the previous name. It now carries 1.1.4 under the organization's name, described under The registry record.
  • The last published version of this file said the organization profile claims every public Trooth repository is Apache 2.0. That was out of date. LICENSE in this repository is MIT, every other repository in the profile's table is Apache 2.0, and the profile now says so: every repository in its table is Apache 2.0 except trooth-mcp, which is MIT.

Security

Report a vulnerability through the Vulnerability Disclosure Policy, or read /.well-known/security.txt.

This server takes no credential, so there is none to leak through it. Every tool reads data already public to any browser. The only outbound request made on a caller's behalf is trooth_outside_in_read, and the refusals listed against that tool above are what keeps it from being pointed at a private address.

Links

License

MIT. See LICENSE.

Trooth signs what it witnessed. It never signs on a company's behalf.