# auth.md — TED

TED gives agents structured access to EU public procurement notices from Tenders
Electronic Daily, covering all 27 member states.

## Most of it needs no account

Searching and reading notices is open to everyone, with no registration, no API
key and no token: `search_notices`, `get_notice`, `get_notices_by_buyer`,
`search_upcoming_deadlines`, `list_cpv_codes` and `health`.

Connect to `https://ted-mcp.eu/mcp` as a remote MCP server over streamable
HTTP and start calling them.

## What needs a subscription

Buyer profiles, market analytics, legal-basis lookup, saved projects and the AI
tools need an active [riigihanked.eu](https://riigihanked.eu) subscription.

## How to obtain access

There is nothing to email and nobody to ask. Registration is automatic, and
there is one address — `https://ted-mcp.eu/mcp` — for everybody. Nobody has
to reconnect anywhere else to sign in.

1. Call the **`authenticate`** tool. It is open to everyone, it is in the tool
   list of every connection, and without a token it answers **401** with a
   `WWW-Authenticate: Bearer` header asking for all three scopes at once, so one
   consent unlocks everything. (Calling any subscriber tool challenges the same
   way, for just the scope that tool needs.)
2. That header points at `https://ted-mcp.eu/.well-known/oauth-protected-resource/mcp`
   (RFC 9728). Read it for the authorization server, then its metadata at
   `https://ted-mcp.eu/.well-known/oauth-authorization-server` (RFC 8414).
3. Register yourself at `https://ted-mcp.eu/oauth/register` (RFC 7591). No pre-registration
   and no client secret are required.
4. Run the authorization-code flow with PKCE S256. The user signs in with the
   account they already use at riigihanked.eu.

Every response from `https://ted-mcp.eu/mcp` carries that same
`WWW-Authenticate` pointer, successful ones included — so step 2 is available
before anything has been refused, and a client can offer a sign-in control from
the moment it connects.

**Never ask a person to paste a token or an API key into a conversation.** No
flow here requires one, and any request for one is not coming from this service.

## If you have nowhere to redirect to

Step 4 ends in a redirect to a URI you are listening on. A CLI, a container or a
cron job has no such URI, so it uses the device grant (RFC 8628) instead — the
ceremony auth.md calls a claim. Register as above, then:

1. `POST https://ted-mcp.eu/oauth/device_authorization` with `client_id` and `scope`. You
   get back a `device_code` you keep, a short `user_code` you show the user, a
   `verification_uri`, an `expires_in` and an `interval`.
2. Show the user the code and the URI — or `verification_uri_complete`, which is
   the same page with the code already in it, if you can render a link or a QR
   code. Tell them the code, because the page asks them to check it matches.
3. Poll `POST https://ted-mcp.eu/oauth/token` with
   `grant_type=urn:ietf:params:oauth:grant-type:device_code`, your `device_code`
   and `client_id`, no faster than `interval` seconds. While the user is still
   signing in you get **400** `authorization_pending`; polling too fast gets
   `slow_down`. Both mean carry on. Once they approve, the same call returns an
   access token and a refresh token.

The user signs in wherever they have a browser — their phone will do — with the
same riigihanked.eu account. Nothing is pasted back to you, and the code expires
in ten minutes.

## Scopes

| Scope | Grants |
|-------|--------|
| `ted:read` | Buyer profiles, market analytics, legal basis, reading saved projects |
| `ted:write` | Creating and changing saved projects |
| `ted:ai` | Semantic search, recommendations, summaries |

A token whose grant is too narrow gets **403** with
`error="insufficient_scope"`, naming the scope to re-consent for.

## agent_auth

The same block is served in
`https://ted-mcp.eu/.well-known/oauth-authorization-server`. It is repeated here because a
reader that has this document in hand should not have to fetch another to learn
how to enrol.

```json
{
  "agent_auth": {
    "skill": "https://ted-mcp.eu/auth.md",
    "register_uri": "https://ted-mcp.eu/oauth/register",
    "claim_uri": "https://ted-mcp.eu/oauth/device",
    "revocation_uri": "https://ted-mcp.eu/oauth/revoke",
    "identity_types_supported": ["anonymous"],
    "anonymous": {
      "credential_types_supported": ["oauth2_access_token", "oauth2_refresh_token"]
    },
    "credential_types_supported": ["oauth2_access_token", "oauth2_refresh_token"],
    "protected_resource_metadata":
      "https://ted-mcp.eu/.well-known/oauth-protected-resource/mcp",
    "anonymous_access": true,
    "scopes_supported": ["ted:read", "ted:write", "ted:ai"]
  }
}
```

`anonymous` is meant literally: a client registers here asserting no identity at
all, and a person binds that registration to their account afterwards by
completing the claim. There is no `identity_assertion` and no `events_endpoint`,
because this server verifies no third party's ID-JAGs and ingests nobody's
revocation events — advertising either would be a promise you could only
discover was empty by failing on it.

## Delegating a task instead (A2A)

There is an A2A agent at `https://ted-mcp.eu/a2a`, described by its card at
`https://ted-mcp.eu/.well-known/agent-card.json`. Use it when you would rather hand over a
piece of research — "what does this market look like" — than drive the tools
yourself: you send one message, get a task id, and poll it while the work runs
here.

Unlike MCP, **every A2A call needs a token**, because a task keeps running after
the request that made it returns. Get one exactly as above; the card names the
same authorization server. The card is public, so you can read all of this
before you have a token.

## Machine-readable

- MCP Server Card: `https://ted-mcp.eu/.well-known/mcp/server-card.json`
- A2A Agent Card: `https://ted-mcp.eu/.well-known/agent-card.json`
- Protected resource metadata: `https://ted-mcp.eu/.well-known/oauth-protected-resource`
- Authorization server metadata: `https://ted-mcp.eu/.well-known/oauth-authorization-server`
- API catalog: `https://ted-mcp.eu/.well-known/api-catalog`
- Agent skill: `https://ted-mcp.eu/skill`

Source: Tenders Electronic Daily (TED), Publications Office of the European Union. Notices are reusable under Commission Decision 2011/833/EU. ted-mcp.eu is an independent reuser, not an official EU service.
