Skip to content

Live Demo: First License

You can run the whole protocol today, from a chat window, in about five minutes. No signup fee, no contract, no card. This page walks the demo as a user sees it, and shows the protocol call sitting under each screen.

You will add the demo MCP server to Claude, get an agent identity, register with the Exchange, and fetch a licensed article — discovering the offer, executing the transaction and filing the usage report along the way. Each step shows the protocol call it makes, so you can do the same thing from code afterwards.

Claude with custom connector support, and an email address you can receive mail at. That is all.

Add a custom connector pointing at the demo MCP endpoint:

https://mcp.demo.fora-protocol.org/mcp
Claude's Add custom connector dialog, with the name FORA and the demo MCP URL filled in.

Claude probes the endpoint and discovers how to authenticate. Both settings it picks are the right ones — the server runs an OAuth flow, and registers OAuth clients dynamically as users connect.

Connector settings showing Sign in now and Register automatically, both marked Detected. Connector panel reading: You're not connected to FORA yet, with a Connect button.

Connecting sends you to the demo’s identity service. If you have no account, register one.

Login screen with a Register button. Registration form asking for given name, family name, email and password.

Confirm the address from the mail that arrives, and set your password.

Activation email from FORA Demo containing an initialisation code and a Finish initialization button. Activate User screen with the code from the email filled in.

Then approve Claude’s request to act as your agent.

Authorize access screen: the application Claude is requesting access to your agent identity agent-duci2vuk.mcp.demo.fora-protocol.org.

Read that screen carefully, because it is the interesting part. Claude is not asking for your password. It is asking to act as an agent identity that now exists on the network, at its own hostname.

Registering did not just create a login. The demo provisioned you a full protocol participant:

  1. A subdomain of your own — agent-<id>.mcp.demo.fora-protocol.org.
  2. An Ed25519 keypair, generated and held server-side.
  3. A published key directory at that subdomain, so any verifier can resolve your public key.

That directory is live and world-readable. This is the identity from the screenshot above, still serving:

Terminal window
curl -s https://agent-duci2vuk.mcp.demo.fora-protocol.org/.well-known/http-message-signatures-directory
{
"keys": [{
"kty": "OKP", "crv": "Ed25519", "use": "sig", "alg": "EdDSA",
"x": "EdbIZlG3BxFrQOyALo83-2atoIFh5zhzbT1c9L6asa4",
"not_before": "2026-09-17T07:38:33Z",
"not_after": "2027-09-17T07:38:33Z"
}],
"revocation_url": "https://agent-duci2vuk.mcp.demo.fora-protocol.org/.well-known/fora-key-revocations.json"
}

From here on, every protocol call made on your behalf is signed with that key (RFC 9421 HTTP Message Signatures), carries that hostname in a covered Signature-Agent header, and is verified by the Exchange against exactly the directory above. The keyid is the key’s RFC 7638 thumbprint.

Once connected, five tools appear — the protocol verbs.

Connected FORA connector listing five tools: Fora discover, execute, register, report and status.
ToolWhere the call goes
Fora discoverBrokerService.Resolve, via the Broker
Fora executeBrokerService.ExecuteTransaction
Fora registerExchangeService.Register, direct to the Exchange
Fora reportExchangeService.ReportUsage, direct to the offer’s Exchange
Fora statusExchangeService.GetAccountStatus, direct to the Exchange

Two of them traverse the Broker and three go straight to an Exchange. Registration has to be direct, because the Exchange binds your account to your identity using your own inbound signature, and a purchase through the Broker is re-signed with the Broker’s own key. See Identity Service for the rest of that reasoning.

The catalog lives at demo.fora-protocol.org: three fictional publishers, with essays, lyrics and sound-effect metadata.

Demo Publisher Catalog listing Stoa Press philosophy essays, Harmonia Records lyrics and tracks, and FoleyWorks sound effects.

Ask Claude to register you. It reads the Exchange’s manifest, finds what the Exchange asks for, reads the terms, and registers.

Claude reading the registration schema, accepting terms, and reporting a successful registration with exchange, legal entity, email, billing ref and active status.

The Exchange publishes what it wants in its manifest, which is why the agent can do this unattended:

Terminal window
curl -s https://exchange.demo.fora-protocol.org/.well-known/fora.json
{
"ver": "1.0",
"role": "ROLE_EXCHANGE",
"domain": "exchange.demo.fora-protocol.org",
"endpoint": "https://exchange.demo.fora-protocol.org",
"terms_uri": "https://exchange.demo.fora-protocol.org/terms/revision-1.txt",
"supported_profiles": ["fora-news-v1", "fora-comp-v1"],
"base_currency": "EUR",
"max_intermediary_hops": 4,
"account_registration": {
"data_schema": {
"type": "object",
"required": ["legal_entity"],
"properties": {
"legal_entity": { "type": "string", "minLength": 1, "maxLength": 200 },
"email": { "type": "string", "maxLength": 254 }
}
}
},
"terms_digest": "sha256:d51eaaff39d8f2497efd20e34709bddbffad99761deff14de216806a32460785"
}

legal_entity required, email optional — exactly what the agent reported back. The digest it echoed is WellKnownManifest.terms_digest from the manifest above: registration records which revision of the terms you accepted, by digest, so neither side can later disagree about what was agreed. The manifest also advertises WellKnownManifest.supported_profiles and WellKnownManifest.base_currency, which is how an agent knows what the Exchange speaks before it sends anything. WellKnownManifest.max_intermediary_hops is the most request signatures the Exchange accepts on one request. A request signed only by the party that sent it — the agent, or the Broker for a request it authored — carries one, so 4 leaves room for parties that forward a request unchanged and sign it again; the Exchange counts the signatures before it verifies any and refuses a request carrying more with resource_exhausted.

Now the point of all this. Ask Claude to fetch an article from the demo publisher directly.

Claude reporting that it could not fetch the page because the site blocked its request as automated traffic.

The fetch is refused. The edge in front of the demo publisher runs bot detection, and it judged this request to be an AI agent.

That is the situation FORA is for, so it is worth being precise about it: the edge is a heuristic, not a wall. It weighs the declared user-agent along with address reputation, request shape and TLS fingerprint, so results vary by where you call from — a plain curl from a residential address will usually be served. The demo is not trying to be impenetrable. It is set up so the agent path is the one that works reliably, which is the path the next step takes.

The publisher points at the Exchange that carries its catalog:

Terminal window
curl -s https://demo.fora-protocol.org/.well-known/fora.json
{
"ver": "1.0",
"role": "ROLE_PUBLISHER",
"domain": "demo.fora-protocol.org",
"exchanges": [{
"domain": "exchange.demo.fora-protocol.org",
"relationship": "PROVIDER_RELATIONSHIP_DIRECT"
}],
"supported_profiles": ["fora-news-v1"]
}

Ask for the same URL again, and let the agent use the protocol.

Claude discovering the offer, executing the transaction, reporting usage, and then displaying the full licensed article.

Three tool calls, and the article arrives:

  1. Fora discover (BrokerService.Resolve, via the Broker) — the Broker asks the Exchange, which returns an offer per licensing term available to you. This one is free under the Stoa Press AI License.
  2. Fora execute (BrokerService.ExecuteTransaction, via the Broker) — the agent chooses a signed offer, and the Broker re-packages the purchase into a request to the offer’s Exchange, signed with its own key, with the agent’s acceptance in the body. The Exchange verifies Offer.signature and answers with a signed retrieval URL in TransactionResultItem.retrieval_endpoint. The MCP server then fetches the content from that URL itself, because only it holds the key the URL is bound to. The delivery edge verifies the URL and serves the bytes, the same bytes the door refused, and the article comes back in the tool result.
  3. Fora report (ExchangeService.ReportUsage, direct to the offer’s Exchange) — the offer carried a ReportingObligation, so the agent files a report and gets back a UsageReportResponse.report_id.

See Why the service fetches the content for the reason the fetch happens inside Fora execute.

Step 3 is not optional bookkeeping. The offer’s ReportingObligation states what has to be filed and by when, and the Exchange tracks whether it was — an account with overdue reports can be denied on its next transaction with DENIAL_REASON_REPORTING_OVERDUE.

The tools above are ergonomics. The wire is Connect over HTTPS, and the same exchange looks like this:

Terminal window
EX=https://exchange.demo.fora-protocol.org
# Discovery — requires a signed request; see Authentication for the signature base.
# The digest and signature are computed over query.json's exact bytes, so send them
# unchanged with --data-binary. 'Authorization;' sends the header empty; it is covered
# even when empty.
curl -sS "$EX/fora.v1.ExchangeService/DiscoverResources" \
-H 'Content-Type: application/json' \
-H 'Content-Digest: sha-256=:<base64 SHA-256 of query.json>:' \
-H 'Authorization;' \
-H 'Signature-Agent: sig1="https://agent-duci2vuk.mcp.demo.fora-protocol.org"' \
-H 'Signature-Input: sig1=("@method" "@target-uri" "content-digest" "authorization" "signature-agent";key="sig1");created=<now>;expires=<now+300>;keyid="<key thumbprint>";alg="ed25519";nonce="<random>";tag="web-bot-auth"' \
-H 'Signature: sig1=:<Ed25519 signature over the signature base>:' \
--data-binary @query.json

The headers have the shape of the Single-Hop Example: Signature-Agent is a dictionary whose sig1 member names the agent’s https origin, the same host as requester.domain, and the signature covers that member.

with query.json:

{
"ver": "1.0",
"exchange": "exchange.demo.fora-protocol.org",
"requester": {
"id": "my-agent",
"domain": "agent-duci2vuk.mcp.demo.fora-protocol.org",
"type": "REQUESTER_TYPE_AGENT",
"scopes": ["*"]
},
"uris": ["https://demo.fora-protocol.org/articles/philosophers/md/leucippus.md"]
}

ExecuteTransaction and ReportUsage follow the same shape. Rather than hand-rolling the RFC 9421 signature, use an SDK. All three are published, and each ships the signing transport, the offer verifier and the usage-report client:

LanguagePackageInstall
Gogithub.com/FORA-Protocol/protocol/sdk/gogo get github.com/FORA-Protocol/protocol/sdk/go
TypeScript@fora-protocol/sdknpm install @fora-protocol/sdk
Pythonfora-protocol-sdkpip install fora-protocol-sdk

Then:

The connector stays on your account, so the catalog is open to experiment with:

  • Ask for something priced. Not every term is free. Ask Claude to discover offers for a Harmonia Records track and compare what comes back against the Stoa Press essays.
  • Ask for several URIs at once. Fora discover takes up to 256 in one call, and answers with an OfferGroup per URI.
  • Check your account. Fora status returns your registration state without spending anything.
  • Watch a refusal. Ask for a URI that is not in the catalog. The Exchange answers OK with OfferGroup.absence_reason set rather than erroring — “no result” is a successful answer.
  • Point it at your own key. The MCP server signs for you; an agent that holds its own key and publishes its own directory is the same participant. See For AI Agents.

Where to read further: