Skip to main content
Glama

@layervai/qurl-mcp

npm version

⚠️ Umbenannt von @layerv/qurl-mcp in v0.4.0. Das alte Paket ist veraltet und erhält keine weiteren Updates. Wenn Sie @layerv/qurl-mcp@0.3.x verwenden, tauschen Sie den Scope in Ihrer MCP-Client-Konfiguration aus — gleiches Binary, gleicher API-Schlüssel, keine weiteren Änderungen.

MCP-Server für qURL™ sichere Link-Verwaltung.

Quantum URL (qURL) · Das Internet hat eine verborgene Ebene. So gelangen Sie hinein.

Was es bewirkt

qURL MCP Server ist ein Model Context Protocol-Server, der es KI-Agenten (Claude, GPT, Cursor usw.) ermöglicht, sichere qURL-Links nativ zu erstellen, aufzulösen, aufzulisten und zu verwalten. Er verbindet sich über stdio-Transport mit der qURL-API, sodass jeder MCP-kompatible Client ihn ohne benutzerdefinierten Integrationscode verwenden kann.

Related MCP server: unphurl-mcp

Schnellstart

Fügen Sie den Server zu Ihrer MCP-Client-Konfiguration hinzu (Claude Desktop, Claude Code usw.):

{
  "mcpServers": {
    "qurl": {
      "command": "npx",
      "args": ["@layervai/qurl-mcp"],
      "env": { "QURL_API_KEY": "lv_live_xxx" }
    }
  }
}

Ersetzen Sie lv_live_xxx durch Ihren tatsächlichen API-Schlüssel. Der Schlüssel muss über die entsprechenden Scopes für die Tools verfügen, die Sie verwenden möchten (siehe unten).

Verfügbare Tools

Tool

Beschreibung

Erforderlicher Scope

create_qurl

Erstellt einen sicheren, richtliniengebundenen Link zu einer geschützten Ressource

qurl:write

resolve_qurl

Löst ein Zugriffstoken auf, um die Ziel-URL zu erhalten und den Firewall-Zugriff zu öffnen

qurl:resolve

list_qurls

Listet aktive qURLs mit optionaler Paginierung auf

qurl:read

get_qurl

Ruft Details einer spezifischen qURL anhand der Ressourcen-ID ab

qurl:read

delete_qurl

Widerruft eine qURL und macht den Link sofort ungültig

qurl:write

extend_qurl

Verlängert die Ablaufzeit einer aktiven qURL (Alias für update_qurl)

qurl:write

update_qurl

Aktualisiert Ablaufzeit, Tags oder Beschreibung einer aktiven qURL

qurl:write

mint_link

Erstellt einen neuen Zugriffslink für eine bestehende geschützte Ressource

qurl:write

batch_create_qurls

Erstellt mehrere qURLs in einem einzigen Aufruf

qurl:write

Verfügbare Ressourcen

URI

Name

Beschreibung

qurl://links

Aktive qURL-Links

Liste aller aktiven qURL-Links

qurl://usage

qURL-Nutzung & Kontingent

Aktuelle Kontingent- und Nutzungsinformationen

Konfiguration

Umgebungsvariable

Erforderlich

Beschreibung

Standard

QURL_API_KEY

Bedingt (siehe Beschreibung)

API-Schlüssel mit entsprechenden Scopes (qurl:read, qurl:write, qurl:resolve). Der Server startet ohne ihn, damit MCP-Introspektion (tools/list, resources/list, prompts/list) für Verzeichnis-Probes funktioniert — nur beim ersten Tool-Aufruf oder Ressourcen-Lesevorgang erforderlich, wobei Aufrufe einen typisierten missing_api_key-Fehler ausgeben, bis der Schlüssel gesetzt ist.

--

QURL_API_URL

Nein

qURL API-Basis-URL

https://api.layerv.ai

Docker

Ein mehrstufiges Dockerfile ist für die containerbasierte Bereitstellung enthalten:

docker build -t qurl-mcp .
docker run -i -e QURL_API_KEY=lv_live_xxx qurl-mcp

Das Image läuft als Nicht-Root-node-Benutzer, liefert nur Produktionsabhängigkeiten aus und verwendet tini als PID 1 für eine saubere Signalverarbeitung.

Wenn ein Tool-Aufruf missing_api_key zurückgibt, obwohl QURL_API_KEY gesetzt zu sein scheint, überprüfen Sie stderr auf die Warnung beim Booten — einige MCP-Hosts verbergen stderr, und die Warnung ist der schnellste Weg, einen nur aus Leerzeichen bestehenden oder nicht gesetzten Wert zu erkennen:

docker logs <container>          # if running detached
docker run -i -e QURL_API_KEY=lv_live_xxx qurl-mcp 2>&1  # interactive

Entwicklung

npm install
npm run build
npm test
npm run lint

Zusätzliche Befehle:

npm run dev          # Watch mode (rebuild on changes)
npm run format       # Format source with Prettier
npm run format:check # Check formatting without modifying files

Lizenz

MIT -- LayerV AI

Available Tools

13 tools
batch_create_qurlsBatch Create qURLsA

Create up to 100 qURLs in a single request. The single-call alternative to looping create_qurl — saves round trips and returns a single envelope of per-item results. Only use this when the user explicitly wants multiple qURLs in one request. Never use it for a single URL, a single file, a single image, or a single attachment. Do not use this tool for uploaded files, image attachments, PDFs, or base64 file content — use upload_file_data_qurl (HTTP mode) or upload_file_qurl (stdio mode) instead. Not transactional: items succeed or fail independently (see succeeded/failed counts and per-item error). Use this when you need to mint many qURLs at once (e.g. provisioning a vendor list, distributing per-customer share links). Use create_qurl for a single resource. Response shape: { succeeded: number, failed: number, results: BatchItemResult[], request_id?: string }. Each results[i] carries index (matching the input position), success, plus either qurl_link + resource_id + qurl_site + expires_at (success) OR error: { code, message } (failure). Successful items may also carry branded_domain for custom-domain anchor text. Partial failure signaling: the handler sets isError: true on the tool response whenever failed > 0, so agents can branch without parsing JSON. The HTTP layer also returns 400 when every item fails — that's surfaced through the same shape (read data.results[*].error). One-shot links: like create_qurl, every qurl_link in the response is shown ONCE. Don't lose them.

ParametersJSON Schema
NameRequiredDescriptionDefault
itemsYesArray of qURL creation requests (1-100 items)

Output Schema

ParametersJSON Schema
NameRequiredDescription
failedYes
resultsYes
succeededYes
request_idNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds substantial behavior beyond the sparse annotations: 'Not transactional: items succeed or fail independently', the isError:true signaling convention, the HTTP 400-on-total-failure behavior, and the critical 'One-shot links... shown ONCE. Don't lose them' warning. No contradiction with readOnlyHint=false/idempotentHint=false — creating new batch links is a non-idempotent write, which the description matches.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but well-organized with bold headers and a logical flow from purpose → routing → behavior → response → warning. Minor deductions: the response-shape section is verbose given an output schema exists (which per rubric makes return-value explanation optional), and the batch-vs-single theme is restated several times. Every sentence still earns its place, but some could be trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex batch tool with per-item failures, HTTP status quirks, and destructive-to-lose one-shot links, the description covers every decision an agent needs: when to invoke, what the per-item response looks like, how to detect partial failure without parsing JSON, and the irreversible nature of the links. Input schema covers parameters, output schema covers return types, and the description fills the behavioral gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with a clear description of the `items` array and every nested property, so the schema carries the semantic load. The description reinforces the batch envelope concept and per-item result mapping, but adds no new input-parameter semantics beyond what the schema already documents. Baseline 3 is correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Starts with a specific verb+resource+scope: 'Create up to 100 qURLs in a single request.' It distinguishes itself from siblings explicitly — 'single-call alternative to looping create_qurl' and 'Use create_qurl for a single resource' — so an agent can tell batch creation apart from single creation and file upload without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use ('only when the user explicitly wants multiple qURLs in one request', 'mint many qURLs at once'), explicit when-not-to-use ('Never use it for a single URL...'), and names concrete alternatives with conditions ('use upload_file_data_qurl (HTTP mode) or upload_file_qurl (stdio mode) instead'). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_qurlCreate qURLA

Create a qURL — a policy-bound, expiring access link that gates a target URL with optional IP/geo/UA/AI-agent filters and time or session limits. When to use: minting a fresh protected access link for share-once or time-limited access (e.g. send a customer a 24-hour download link, gate a doc behind an IP allowlist, distribute a one-time-use credential to a contractor). Do NOT use this for chat-uploaded images, PDFs, screenshots, or file attachments. In HTTP MCP mode, those should go through upload_file_data_qurl; in stdio mode, use upload_file_qurl. When NOT to use: use mint_link when you already have a resource identifier and just need an additional access token under it — create_qurl identifies the resource by target URL and may return an existing same-type resource grouping. Use batch_create_qurls to create many in one round-trip. Use update_qurl to retag or extend an existing resource without minting a new one. If the user says 'give me the qURL of this image/file' and the content was uploaded in chat, this is the wrong tool. Behavior: not idempotent — calling twice produces two distinct qURL tokens, though both may share the same resource_id when the target URL groups to an existing same-type resource (this tool doesn't surface the underlying API's Idempotency-Key header). The returned qurl_link is shown ONCE in this response and is never recoverable through get_qurl or list_qurls; persist or share it immediately. A returned resource is in active status with the policy and per-token limits applied. If expires_in is omitted the API defaults to 24h — do not assume the link is permanent. max_sessions is per minted qURL, not resource-wide; set one_time_use: false explicitly when you need max_sessions: 0 to mean unlimited visitors. Returns: { qurl_id: string (q_…), resource_id: string, qurl_link: string (shown once), branded_domain?: string, qurl_site: string, expires_at: string (RFC 3339), label?: string, type?: string }. qurl_id is the only q_… display ID an agent gets in this response — keep it if you plan a follow-up against get_qurl/update_qurl/mint_link (which accept either prefix). Example: create_qurl({ target_url: 'https://example.com/private', expires_in: '24h', one_time_use: true, access_policy: { geo_allowlist: ['US'] } }).

ParametersJSON Schema
NameRequiredDescriptionDefault
typeNoResource type for integrations allowed to mint non-url qURLs (max 64 chars). Defaults to url.
labelNoHuman-readable label identifying who this qURL is for (max 500 chars)
expires_inNoDuration string (e.g., "1h", "24h", "7d")
target_urlYesThe URL to protect with qURL
max_sessionsNoMaximum concurrent sessions for this qURL token (0 = unlimited when one_time_use is explicitly false; max 1000)
one_time_useNoWhether the link can only be used once
access_policyNoAccess control policy for the qURL
custom_domainNoCustom domain to assign to the auto-created resource (max 253 chars, must be registered/active/owned).
session_durationNoHow long access lasts after the recipient reaches the content (e.g., "1h"). This anchors the resource-level session-duration cap when a new resource is created.

Output Schema

ParametersJSON Schema
NameRequiredDescription
typeNoResource type echoed from the create request
labelNo
qurl_idYesDisplay-friendly qURL ID (q_ prefix)
qurl_linkYesOne-shot display access link — shown ONCE on creation, never returned again. Share immediately.
qurl_siteNo
expires_atNo
resource_idYesStable resource identifier (public key or legacy r_ ID)
branded_domainNoBare branded hostname for anchor text when the resource has a usable custom domain
email_deliveryNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate non-idempotence and non-read-only, but the description goes far beyond them: it states calling twice produces two distinct tokens, the qurl_link is shown once and is never recoverable, the API defaults expires_in to 24h, and max_sessions is per-token rather than resource-wide. These are critical behavioral traits that structured fields alone do not convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every sentence earns its place: definition, usage rules, behavioral caveats, return format, and a concrete example. It uses bolded section labels for scannability and front-loads the tool's purpose before routing to alternatives. The density is justified by the tool's complexity and nine parameters.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity, rich schema, and large sibling set, the description is complete. It covers selection criteria, side effects, security-relevant one-time display of the link, default expiry, parameter semantics, and the exact return shape, including the fact that qurl_id is the only persistent handle. An agent has everything needed to invoke and follow up correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds meaningful guidance beyond the schema: target_url groups to an existing same-type resource, expires_in defaults to 24h, max_sessions: 0 requires explicit one_time_use: false, and the returned resource enters active status. This elevates the score above baseline, though not all nine parameters are individually discussed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise verb+object: 'Create a qURL — a policy-bound, expiring access link that gates a target URL.' It enumerates the optional filters and limits, and explicitly names sibling tools it is not, such as mint_link and batch_create_qurls, so an agent can distinguish it without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description contains explicit 'When to use', 'Do NOT use', and 'When NOT to use' guidance. It names concrete alternatives (upload_file_data_qurl, upload_file_qurl, mint_link, batch_create_qurls, update_qurl) and provides a clear chat-upload exclusion, leaving no ambiguity about when this tool should be selected.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_qurlDelete qURLA
DestructiveIdempotent

Permanently revoke a qURL — the link and every access token under it stop working immediately. This action is irreversible. Use this when you want to cut off access entirely (compromised link, departed user, end-of-engagement). Use update_qurl instead when you only need to shorten/extend the expiration, retag, or rename — those preserve the existing access tokens. Use extend_qurl when you only need to push the expiration out. Idempotent: the API returns 404 for re-deletes, never-existed IDs, and resources owned by another API key (ownership-mismatch is collapsed into 404 server-side to avoid existence disclosure); this tool swallows all three. Branch on was_already_revoked to distinguish the no-op case from a successful revoke on this call. When the ID came from user input and ownership matters, call get_qurl first — a 200 confirms ownership; a thrown 404 is equally ambiguous on that endpoint too. Returns a confirmation payload. By default the resource is excluded from list_qurls; pass status: "revoked" to see it.

ParametersJSON Schema
NameRequiredDescriptionDefault
resource_idYesThe resource public key, CRID, or legacy r_ ID to revoke (all tokens; q_ display IDs are not accepted).

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageYesHuman-readable confirmation message
revokedYes
resource_idYes
was_already_revokedYesTrue when the API responded 404 (resource was already revoked or never existed). Agents that need to distinguish 'I revoked it' from 'it was already gone' should branch on this.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

While annotations already declare destructiveHint and idempotentHint, the description adds significant context: irreversibility, the 404-collapsing behavior for ownership-mismatch (avoiding existence disclosure), the branch on was_already_revoked, the effect on list_qurls, and the recommendation to verify ownership via get_qurl. This goes well beyond what annotations state.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is moderately long but every sentence carries necessary information: core purpose first, then alternatives, then idempotency, ownership handling, return payload, and listing behavior. It is logically ordered and free of filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description fully covers the tool's behavior for an agent: purpose, usage conditions, idempotency edge cases, ownership implications, return payload indication, and post-revoke visibility. With an output schema present, the return details are appropriately summarized.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema's resource_id description already explains accepted ID formats and what it revokes. The tool description does not add new parameter semantics beyond that, so a baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise verb ('revoke') and resource ('qURL'), explains the immediate effect (link and all access tokens stop working), and explicitly contrasts with update_qurl and extend_qurl, making the tool's purpose unmistakable even without opening sibling schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides explicit when-to-use guidance (compromised link, departed user, end-of-engagement) and names the exact alternatives (update_qurl for non-destructive edits, extend_qurl for expiration-only changes), leaving no ambiguity about tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

extend_qurlExtend qURL ExpirationA

Push out the expiration of an active qURL by a relative duration. Convenience wrapper for the most common update — equivalent to update_qurl({ resource_id, extend_by }). Use this when the only change you need is more time on the clock. Use update_qurl instead when you also need to change tags, description, or set an absolute expires_at. Use delete_qurl when you want to cut off access entirely. Accepts resource public keys, CRIDs, legacy r_ IDs, and q_ display IDs (q_ is auto-resolved to its parent resource). Not idempotent: calling twice with the same extend_by extends the expiration twice. If you need an absolute target, use update_qurl with expires_at so retries on transient errors don't double-push. Returns the updated resource with the new expires_at (same shape as get_qurl).

ParametersJSON Schema
NameRequiredDescriptionDefault
extend_byYesDuration to extend by (e.g., "24h", "7d")
resource_idYesThe resource public key, CRID, legacy r_ ID, or qURL display ID (q_ prefix) to extend. If a q_ ID is passed, the API resolves it to the parent resource automatically.

Output Schema

ParametersJSON Schema
NameRequiredDescription
slugNoImmutable per-owner resource identity, when one was supplied at create time
tagsNo
qurlsNo
statusYes
qurl_siteNo
created_atYes
expires_atYes
qurl_countNoNumber of access tokens minted for this resource
target_urlNoUnderlying URL the qURL protects; omitted on connector-owned resources
descriptionNo
resource_idYesStable resource identifier (public key or legacy r_ ID)
custom_domainNo
preserve_hostNoWhen true, the original Host header is preserved when proxying via the custom domain. Only meaningful when custom_domain is set; defaults to false on the API side.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare write and non-idempotent behavior, but the description adds practical context: calling twice extends twice, retries on transient errors can double-push, the q_ display ID is auto-resolved to the parent resource, and the return shape matches get_qurl. These are exactly the behavioral details the annotations don't capture, and there is no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core capability is front-loaded, and every subsequent sentence earns its place: equivalence to update_qurl, when-to-use/alternatives, accepted ID forms, non-idempotency warning, retry guidance, and return shape. It is dense but not bloated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter mutating tool, the description covers operation semantics, sibling routing, ID input types, the non-idempotency risk, and the response shape reference. The output schema covers return-value details, and the annotations cover idempotency/safety, leaving no invocation-critical gap. The only minor omission is behavior on an inactive or already-expired qURL, but that doesn't impair correct selection or invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters well. The description still adds value by framing extend_by as a relative duration, contrasting it with absolute expires_at, and clarifying that resource_id accepts public keys, CRIDs, legacy r_ IDs, and auto-resolved q_ IDs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Push out the expiration of an active qURL by a relative duration.' It then explicitly distinguishes this tool from update_qurl and delete_qurl, so an agent can separate it from the dozen sibling tools without opening their schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit selection rules: 'Use this when the only change you need is more time on the clock,' and names update_qurl for tag/description/absolute-time changes and delete_qurl for cutting off access. It even handles the retry edge case by steering agents toward update_qurl when an absolute expires_at is safer.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_qurlGet qURLA
Read-onlyIdempotent

Fetch a single qURL resource by ID and return its current state plus a bounded preview of access tokens. Use this when you have a specific resource ID (public key, CRID, or legacy r_ ID) or qURL display ID (q_ prefix) — q_ IDs are auto-resolved to their parent resource. Do not use this to create a new qURL for a freshly uploaded image, PDF, screenshot, or file attachment. For chat-uploaded file content in HTTP MCP mode, use upload_file_data_qurl instead. Use list_qurls instead when you need to discover qURLs by status, date range, or search query. Use resolve_qurl instead when you have an end-user access token (at_ prefix) and need to redeem it for the underlying URL. If the user asks for 'the qURL of this image/file', this tool is only correct when you already know the existing resource_id or qurl_id. qurls[] is an unordered preview capped by the API at 100 rows and may be omitted on list views, preview lookup failure, or redacted connector-owned resources; use qurl_count to detect that more token rows may exist. The one-shot qurl_link from creation is never returned here.

ParametersJSON Schema
NameRequiredDescriptionDefault
resource_idYesThe resource public key, CRID, legacy r_ ID, or qURL display ID (q_ prefix) to fetch. If a q_ ID is passed, the API resolves it to the parent resource automatically.

Output Schema

ParametersJSON Schema
NameRequiredDescription
slugNoImmutable per-owner resource identity, when one was supplied at create time
tagsNo
qurlsNo
statusYes
qurl_siteNo
created_atYes
expires_atYes
qurl_countNoNumber of access tokens minted for this resource
target_urlNoUnderlying URL the qURL protects; omitted on connector-owned resources
descriptionNo
resource_idYesStable resource identifier (public key or legacy r_ ID)
custom_domainNo
preserve_hostNoWhen true, the original Host header is preserved when proxying via the custom domain. Only meaningful when custom_domain is set; defaults to false on the API side.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations establish readOnly, idempotent, and non-destructive behavior, so the description correctly builds on that rather than repeating it. It adds genuinely useful behavioral caveats: qurls[] is an unordered preview capped at 100 rows, may be omitted on list views or redacted resources, qurl_count should be used to detect more rows, and the one-shot qurl_link from creation is never returned. This is far beyond what annotations alone communicate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than average, but it is front-loaded with the core purpose and then systematically covers alternatives, exclusions, and behavioral caveats. Each sentence adds distinct information; however, a few clauses could be tightened without loss, so it earns a 4 rather than a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a single parameter, rich schema coverage, an output schema, and safety annotations, the description supplies all necessary context: purpose, routing among many siblings, known limitations, and edge-case output behavior. An agent has enough information to select and invoke this tool correctly without further clarification.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already documents the resource_id patterns, the accepted ID forms, and the q_ auto-resolution behavior. The tool description enriches the conceptual context but does not need to repeat the parameter mechanics; the schema carries the semantic load, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource ('Fetch a single qURL resource by ID') and states exactly what is returned ('current state plus a bounded preview of access tokens'). It also distinguishes this tool from siblings by explicitly noting it is not for creating, listing, or resolving qURLs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use conditions (having a resource_id or q_ display ID), explicit when-not-to-use conditions (creating a qURL for a freshly uploaded file), and names concrete alternatives (`list_qurls`, `resolve_qurl`, `upload_file_data_qurl`). It even clarifies the common user request 'qURL of this image/file' and when this tool is not the right choice.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_qurlsList qURLsA
Read-onlyIdempotent

List qURL resources, paginated and optionally filtered by status, date range, or search text. When to use: discovery — finding qURLs by status (e.g. everything still active), auditing date ranges, or full-text search across descriptions and target URLs (via the q parameter). Filters AND together (e.g. status: 'active' + expires_before: '2026-05-01T00:00:00Z' returns active qURLs about to expire). When NOT to use: use get_qurl instead when you already have a specific resource ID — it returns the same per-resource shape more cheaply and includes the qurls[] per-token detail that list_qurls omits. Use resolve_qurl to actually open access to a target URL. Behavior: read-only and idempotent. An empty data[] with meta.has_more: false means no resource matched the filters (not an error). Pagination is cursor-based: when meta.has_more is true, pass meta.next_cursor as cursor on the next call to fetch the following page. Default page size is 20, configurable via limit up to 100. By default only active qURLs are returned; pass status: 'revoked' to see only revoked qURLs or 'active,revoked' to see both. A past resource expires_at does not change its status; individual access tokens can expire. status: 'expired' is not a valid resource filter. Sort defaults to created_at:desc; override with sort: 'expires_at:asc' etc. Returns: { data: QURL[], meta: { has_more: boolean, next_cursor?: string, page_size?: number, request_id?: string } } — each data[] item is the same stable resource shape returned by get_qurl minus per-token detail. Example: list_qurls({ status: "active", sort: "expires_at:asc", limit: 10 }) returns the 10 active qURLs expiring soonest.

ParametersJSON Schema
NameRequiredDescriptionDefault
qNoSearch query (searches description and target_url)
sortNoSort field and direction as 'field:direction'. Valid fields: created_at, expires_at. Valid directions: asc, desc (default desc). Example: 'created_at:desc'.
limitNoMaximum number of qURLs to return (default: 20)
cursorNoPagination cursor from a previous response
statusNoFilter by status (comma-separated, e.g. 'active,revoked'). Defaults to 'active' when omitted; pass 'revoked' or 'active,revoked' to override. Only active and revoked are valid resource filters; expired is not accepted.
created_afterNoFilter: created after this date (RFC 3339)
expires_afterNoFilter: expires after this date (RFC 3339)
created_beforeNoFilter: created before this date (RFC 3339)
expires_beforeNoFilter: expires before this date (RFC 3339)

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
metaYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, and the description reinforces these. More importantly, it adds behavioral detail beyond annotations: empty data[] semantics, cursor-based pagination rules, default status filtering, invalid status values, and sort defaults. This gives the agent a precise model of how the tool behaves at runtime.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with bolded sections and front-loaded purpose, but it is long and repeats some information already present in the schema (e.g. default status and sort). The density is mostly justified by the tool's complexity, though slight trimming would improve conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 9 optional filter/pagination parameters, the description covers discovery scenarios, exclusions, filter semantics, pagination, default behavior, and return shape. Even with an output schema present, it explains the meta contract and edge cases (e.g. expires_at not changing status), making it complete for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds substantial semantic value: filters AND together, defaults ('active', page size 20, sort created_at:desc), the meaning of passing meta.next_cursor as cursor, and invalid filter combinations. These interaction-level details are not evident from individual property descriptions alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'List qURL resources, paginated and optionally filtered by status, date range, or search text.' It also differentiates itself from siblings by explicitly contrasting with get_qurl and resolve_qurl, so an agent can immediately distinguish this listing operation from related ones.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a dedicated 'When to use' section for discovery/audit scenarios and a 'When NOT to use' section naming get_qurl for known IDs and resolve_qurl for opening access. This is explicit, actionable routing guidance that leaves little to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_qurl_sessionsList qURL SessionsA
Read-onlyIdempotent

List active access sessions for a qURL resource. Use this to inspect who currently has live access before rotating, revoking, or terminating sessions. Use terminate_qurl_sessions when active sessions should be ended, and use get_qurl when you need token/resource metadata instead of active session state. Behavior: read-only and idempotent. Empty data[] means no active sessions for the resource.

ParametersJSON Schema
NameRequiredDescriptionDefault
resource_idYesThe resource public key, CRID, or legacy r_ ID to list active sessions for.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
metaNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already carry readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the bar is lowered. The description reinforces these and adds an interpretive detail: empty data[] means no active sessions. It does not elaborate on session expiration or auth requirements, but the annotations adequately cover the safety profile.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences: primary action, usage alternatives, and a clear behavior note. Every sentence earns its place with no filler, and the most important information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter read-only list tool with an output schema and comprehensive annotations, the description fully covers purpose, workflow, alternatives, and the meaning of an empty response. Nothing essential for correct invocation or selection is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with resource_id fully documented by type, pattern, and description. The description adds no parameter-specific detail, but none is required because the schema already carries the semantic load.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States 'List active access sessions for a qURL resource' – a specific verb and resource with a clear scope. It also distinguishes itself from siblings by clarifying that it shows live session state, not token/resource metadata (get_qurl) or session termination (terminate_qurl_sessions).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use and when-not-to-use guidance: inspect sessions before rotating/revoking/terminating, use terminate_qurl_sessions when sessions should be ended, and use get_qurl when metadata is needed instead of active session state. This gives an agent concrete decision rules for tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resolve_qurlResolve qURL Access TokenA

Redeem a qURL access token (the at_ prefix you pulled out of a qurl_link) to reveal the underlying URL and obtain a time-bound, IP-bound network access grant. Use this when an agent has been handed an access token and needs to fetch the protected resource — after a successful resolve, requests from access_grant.src_ip are permitted to the target_url for access_grant.expires_in seconds. Use get_qurl instead when you have a resource identifier (public key, CRID, or legacy r_ ID) or qURL display ID (q_) and want admin-side details rather than end-user redemption. Side-effects: consumes one use on one_time_use tokens, decrements max_sessions, and may trip access policies (IP/geo/UA/AI-agent denylists). idempotentHint: false because one-time-use tokens consume on each call; for non-one-time tokens within an active grant window, repeats are effectively no-ops, but the conservative annotation reflects worst-case behavior.

ParametersJSON Schema
NameRequiredDescriptionDefault
access_tokenYesThe access token from a qURL link (e.g., at_k8xqp9h2sj9lx7r4a)

Output Schema

ParametersJSON Schema
NameRequiredDescription
target_urlYesUnderlying URL revealed by the resolve
resource_idYes
access_grantYesTime-bound, IP-bound network access grant

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing concrete side effects: consumes one-time-use tokens, decrements max_sessions, and may trip access policies. It also explains the idempotentHint:false annotation by distinguishing conservative worst-case behavior from the actual no-op behavior for non-one-time tokens within an active grant window.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-organized and front-loaded: core action first, then when to use, then the alternative, then side effects, then idempotency nuance. Each sentence serves a distinct purpose and no space is wasted on repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a token-redemption tool with an output schema and annotations, the description covers the action, usage boundary, side effects, and annotation rationale. Everything an agent needs to decide to call it and interpret its behavior is present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with an example value, but the description adds useful context: the token originates from a qurl_link and carries the at_ prefix. This helps agents recognize and source the parameter correctly without replacing schema documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb-object pair, 'Redeem a qURL access token', and states the outcome: reveal the underlying URL and obtain a time-bound, IP-bound grant. It also explicitly differentiates itself from get_qurl by token type vs resource identifier, making it unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use guidance ('Use this when an agent has been handed an access token and needs to fetch the protected resource') and explicit when-not-to-use guidance with the named alternative ('Use get_qurl instead when you have a resource identifier...'). No inference required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

revoke_qurl_tokenRevoke qURL TokenA
Destructive

Revoke one qURL token under a resource without revoking the whole resource. Use this when a single recipient/link should stop working but sibling qURLs on the same resource_id must remain active. Use delete_qurl instead when you want to revoke the resource and every token under it. Constraints: requires the parent resource_id (public key, CRID, or legacy r_ ID) and the token display ID (q_…). Re-revoking an inactive token returns an API error rather than being treated as idempotent.

ParametersJSON Schema
NameRequiredDescriptionDefault
qurl_idYesThe qURL display ID (q_ prefix) to revoke.
resource_idYesThe resource public key, CRID, or legacy r_ ID to revoke a specific qURL token from.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageYes
qurl_idYes
revokedYes
resource_idYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool as destructive and non-idempotent, and the description adds useful behavior beyond that: re-revoking an inactive token returns an API error rather than being idempotent. It also clarifies the operation is scoped so sibling tokens stay active, which adds context not fully carried by annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core action, immediately gives the use case, names the alternative tool, and ends with constraints and error behavior. Every sentence earns its place with no repetition or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter mutation tool with an output schema, annotations, and sibling tools present, the description is complete: it explains what it does, when to choose it, when not to, required IDs, and non-idempotent behavior. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both params have descriptions and patterns, so the schema already does most of the work. The description adds a slight semantic benefit by labeling resource_id as the parent and tying qurl_id to the token display ID, but it does not fundamentally go beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description has a specific verb and resource: 'Revoke one qURL token under a resource without revoking the whole resource.' It clearly distinguishes this tool from delete_qurl by scoping the action to a single token rather than the entire resource.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use: when a single recipient/link should stop working but sibling qURLs on the same resource_id must remain active. It also names the alternative, delete_qurl, and the condition for using that instead, which gives an agent a clear routing decision.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

terminate_qurl_sessionsTerminate qURL SessionsA
Destructive

Terminate active access sessions for a qURL resource. Use this after shortening access, rotating a link, or responding to a suspected leak when already-open sessions should end immediately. Pass session_id to terminate one active session; omit it to terminate all active sessions for the resource. Use list_qurl_sessions first when you need to inspect current sessions before taking action. Side-effects: existing access sessions are closed; qURL tokens themselves are not revoked.

ParametersJSON Schema
NameRequiredDescriptionDefault
session_idNoSpecific session ID to terminate. Omit to terminate all active sessions for the resource.
resource_idYesThe resource public key, CRID, or legacy r_ ID to terminate sessions for.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageYes
session_idNo
terminatedYes
resource_idYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and idempotentHint=false, so the description adds side-effect context ('existing access sessions are closed; qURL tokens themselves are not revoked'). This goes beyond annotations by specifying exactly what is destroyed and what is preserved, though it does not detail auth requirements or potential partial failures. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, each earning its place: purpose, use-case triggers, parameter semantics, and side-effects. Front-loaded with the core action and scoped alternatives, with no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity, the schema covers both parameters, annotations cover safety traits, and an output schema exists, the description fully equips an agent to call it correctly. It includes when to use, how to scope, and side-effects, with no missing critical information.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema already explains the optionality of session_id ('Omit to terminate all active sessions'). The description repeats this behavior without adding new information, so it provides no incremental value beyond the schema baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Terminate') and resource ('active access sessions for a qURL resource'), clearly distinguishing it from siblings like revoke_qurl_token by explicitly noting tokens are not revoked. It also references list_qurl_sessions for inspection, reinforcing its unique role.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use it ('after shortening access, rotating a link, or responding to a suspected leak') and directs the agent to use list_qurl_sessions first for inspection. It also clarifies the omission of session_id as a deliberate all-terminate behavior, effectively covering alternatives and when-not scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_qurlUpdate qURLA

Update a qURL's expiration, tags, description, custom domain, or proxy host-header behavior. The richer alternative to extend_qurl — use update_qurl whenever you need anything beyond a relative time push. Accepts resource public keys, CRIDs, legacy r_ IDs, and q_ display IDs for expiration, tags, and description updates (q_ is auto-resolved); custom domain and preserve_host updates require a resource identifier (public key, CRID, or legacy r_ ID) because the qURL API now serves them from PATCH /v1/resources/{id}. Constraints: extend_by and expires_at are mutually exclusive; custom_domain/preserve_host cannot be combined with expiration changes in one call; at least one update field (extend_by, expires_at, tags, description, custom_domain, preserve_host) must be set. Clearing fields: pass description: "", tags: [], or custom_domain: "" to clear those fields explicitly. Use extend_qurl when the only change is a relative time push. Use delete_qurl when you want to revoke entirely. Errors: if the input fails schema refinements (both extend_by + expires_at, or no fields set), the handler returns an isError: true content block before any API call. Other API errors throw with the API's code/statusCode. Returns the updated resource (same shape as get_qurl).

ParametersJSON Schema
NameRequiredDescriptionDefault
tagsNoReplace all tags on this resource (max 10 tags, each 1-50 chars)
extend_byNoDuration to extend by (e.g., "24h", "7d"). Mutually exclusive with expires_at.
expires_atNoAbsolute expiration timestamp (RFC 3339). Mutually exclusive with extend_by.
descriptionNoReplace the resource description (max 500 chars)
resource_idYesThe resource public key, CRID, legacy r_ ID, or qURL display ID (q_ prefix) to update. If a q_ ID is passed, the API resolves it to the parent resource automatically.
custom_domainNoReplace the custom domain bound to this resource (max 253 chars, must be registered/active/owned). Pass "" to clear.
preserve_hostNoWhether to preserve the original Host header when proxying via the custom domain. Only meaningful when custom_domain is set; default false on the API side.

Output Schema

ParametersJSON Schema
NameRequiredDescription
slugNoImmutable per-owner resource identity, when one was supplied at create time
tagsNo
qurlsNo
statusYes
qurl_siteNo
created_atYes
expires_atYes
qurl_countNoNumber of access tokens minted for this resource
target_urlNoUnderlying URL the qURL protects; omitted on connector-owned resources
descriptionNo
resource_idYesStable resource identifier (public key or legacy r_ ID)
custom_domainNo
preserve_hostNoWhen true, the original Host header is preserved when proxying via the custom domain. Only meaningful when custom_domain is set; defaults to false on the API side.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=false and destructiveHint=false, but the description adds crucial behavioral details: mutual exclusivity of extend_by/expires_at, the constraint that custom_domain/preserve_host cannot combine with expiration changes, the requirement of at least one update field, how to clear fields, error behavior (isError:true content block before API call for schema refinements, API errors throw with code/statusCode), and the return shape. This far exceeds the baseline and aligns with annotations (no contradiction).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense paragraph but every sentence earns its place, covering purpose, usage, constraints, error handling, and return. It is front-loaded with purpose and the alternative. However, it could benefit from structured bullets for constraints and clearing fields to improve scannability. Still, it is not overly verbose relative to the information conveyed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is complex with 7 parameters, but the description covers all critical aspects: identifier types, constraints, clearing, error behavior, and return shape (same as get_qurl). An output schema exists, and the description explicitly references it, so nothing essential is missing for an agent to call this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the description adds meaning beyond the schema: it explains the identifier formats accepted (public keys, CRIDs, legacy r_ IDs, q_ display IDs), that q_ is auto-resolved, and that custom_domain/preserve_host require a resource identifier due to the API endpoint change. It also clarifies mutual exclusivity and field-clearing semantics. This adds significant value on top of the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Update a qURL's expiration, tags, description, custom domain, or proxy host-header behavior.' It explicitly names the richer alternative to extend_qurl, distinguishing it from siblings. The purpose is unambiguous and immediately actionable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance: 'Use extend_qurl when the only change is a relative time push. Use delete_qurl when you want to revoke entirely.' It also clarifies when update_qurl is appropriate ('whenever you need anything beyond a relative time push'). This directly addresses when-to-use and when-not-to-use with named alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_qurl_tokenUpdate qURL TokenA

Update one qURL token under a resource: expiration, label, access policy, max sessions, or session duration. Use this when you need to change a specific q_… token without changing sibling tokens or resource-level metadata. Use update_qurl instead for resource-level description/tags/custom-domain changes, and use revoke_qurl_token when the token should stop working entirely. Constraints: extend_by and expires_at are mutually exclusive; at least one token update field must be set. Returns the updated token summary.

ParametersJSON Schema
NameRequiredDescriptionDefault
labelNoHuman-readable label for this token
qurl_idYesThe qURL display ID (q_ prefix) to update.
extend_byNoDuration to extend this token by (e.g., "24h", "7d"). Mutually exclusive with expires_at.
expires_atNoAbsolute token expiration timestamp (RFC 3339). Mutually exclusive with extend_by.
resource_idYesThe resource public key, CRID, or legacy r_ ID to update a specific qURL token under.
max_sessionsNoMaximum concurrent sessions for this token (0 = unlimited, max 1000)
access_policyNoReplace the access policy for this token
session_durationNoHow long access lasts after clicking (e.g., "1h"). Empty string applies the parent resource cap when one is set.

Output Schema

ParametersJSON Schema
NameRequiredDescription
labelNo
statusYesPer-token status (wider than resource status — tokens may be consumed/expired independently)
qurl_idYes
qurl_siteNo
use_countNo
created_atNo
expires_atNo
max_sessionsNo
one_time_useNo
access_policyNoAccess control policy snapshot for this token
session_durationNoSeconds of access granted after a successful resolve

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag this as a mutating, non-idempotent, non-destructive operation, so the description adds value by disclosing key invariants: `extend_by` and `expires_at` are mutually exclusive, at least one token update field must be set, and the operation returns the updated token summary. This goes beyond what annotations alone provide, though details like access-policy replacement semantics are only implied and left to the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: it opens with the action and scope, then provides routing guidance, then lists constraints in a clearly labeled block. Every sentence earns its place, and the structure makes it easy for an agent to scan and act on.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With eight parameters, nested access-policy objects, and a rich sibling set, the description covers the core invocation context—what to update, when to use it, which siblings to prefer, and key constraints. The output schema relieves it from detailing return values. It could have explicitly stated that `access_policy` replaces the entire policy, but the schema's field description already communicates this.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds meaningful semantic constraints not derivable from the schema's `required` array alone—that at least one token-update field must be supplied and that `extend_by` and `expires_at` cannot be combined. It also groups the updateable fields, helping an agent understand the intent of the parameter set.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states a precise action—'Update one qURL token under a resource'—and enumerates the mutable fields: expiration, label, access policy, max sessions, or session duration. It explicitly differentiates from siblings by contrasting with `update_qurl` and `revoke_qurl_token`, making the tool's scope unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides a direct when-to-use condition: 'Use this when you need to change a specific `q_…` token without changing sibling tokens or resource-level metadata.' It also names alternatives and the exact conditions that select them: use `update_qurl` for resource-level changes, and `revoke_qurl_token` when the token should stop working entirely.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 13 tool updatesv0.2.1
    • Changedbatch_create_qurls38 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • removedInput schema / properties / items / items / additionalProperties
        Removed value: -false
      • removedInput schema / properties / items / items / properties / access_policy / additionalProperties
        Removed value: -false
      • removedInput schema / properties / items / items / properties / access_policy / properties / ai_agent_policy / additionalProperties
        Removed value: -false
      • changedInput schema / properties / items / items / properties / access_policy / properties / ai_agent_policy / properties / allow_categories / description
        Previous value: -"AI agent categories to permit (all others blocked)"New value: +"AI agent categories to permit (all others blocked; max 20 entries, 128 chars each)"
      • addedInput schema / properties / items / items / properties / access_policy / properties / ai_agent_policy / properties / allow_categories / items / maxLength
        Added value: +128
      • addedInput schema / properties / items / items / properties / access_policy / properties / ai_agent_policy / properties / allow_categories / items / minLength
        Added value: +1
      • addedInput schema / properties / items / items / properties / access_policy / properties / ai_agent_policy / properties / allow_categories / maxItems
        Added value: +20
      • changedInput schema / properties / items / items / properties / access_policy / properties / ai_agent_policy / properties / deny_categories / description
        Previous value: -"AI agent categories to block (e.g., gptbot, commoncrawl)"New value: +"AI agent categories to block (e.g., gptbot, commoncrawl; max 20 entries, 128 chars each)"
      • addedInput schema / properties / items / items / properties / access_policy / properties / ai_agent_policy / properties / deny_categories / items / maxLength
        Added value: +128
      • addedInput schema / properties / items / items / properties / access_policy / properties / ai_agent_policy / properties / deny_categories / items / minLength
        Added value: +1
      • addedInput schema / properties / items / items / properties / access_policy / properties / ai_agent_policy / properties / deny_categories / maxItems
        Added value: +20
      • changedInput schema / properties / items / items / properties / access_policy / properties / geo_allowlist / description
        Previous value: -"Allowed country codes (ISO 3166-1 alpha-2)"New value: +"Allowed country codes (ISO 3166-1 alpha-2; max 50 entries, 8 chars each)"
      • addedInput schema / properties / items / items / properties / access_policy / properties / geo_allowlist / items / maxLength
        Added value: +8
      • addedInput schema / properties / items / items / properties / access_policy / properties / geo_allowlist / items / minLength
        Added value: +1
      • addedInput schema / properties / items / items / properties / access_policy / properties / geo_allowlist / maxItems
        Added value: +50
      • changedInput schema / properties / items / items / properties / access_policy / properties / geo_denylist / description
        Previous value: -"Denied country codes (ISO 3166-1 alpha-2)"New value: +"Denied country codes (ISO 3166-1 alpha-2; max 50 entries, 8 chars each)"
      • addedInput schema / properties / items / items / properties / access_policy / properties / geo_denylist / items / maxLength
        Added value: +8
      • addedInput schema / properties / items / items / properties / access_policy / properties / geo_denylist / items / minLength
        Added value: +1
      • addedInput schema / properties / items / items / properties / access_policy / properties / geo_denylist / maxItems
        Added value: +50
      • changedInput schema / properties / items / items / properties / access_policy / properties / ip_allowlist / description
        Previous value: -"Allowed IP addresses or CIDR ranges"New value: +"Allowed IP addresses or CIDR ranges (max 100 entries, 64 chars each)"
      • addedInput schema / properties / items / items / properties / access_policy / properties / ip_allowlist / items / maxLength
        Added value: +64
      • addedInput schema / properties / items / items / properties / access_policy / properties / ip_allowlist / items / minLength
        Added value: +1
      • addedInput schema / properties / items / items / properties / access_policy / properties / ip_allowlist / maxItems
        Added value: +100
      • changedInput schema / properties / items / items / properties / access_policy / properties / ip_denylist / description
        Previous value: -"Denied IP addresses or CIDR ranges"New value: +"Denied IP addresses or CIDR ranges (max 100 entries, 64 chars each)"
      • addedInput schema / properties / items / items / properties / access_policy / properties / ip_denylist / items / maxLength
        Added value: +64
      • addedInput schema / properties / items / items / properties / access_policy / properties / ip_denylist / items / minLength
        Added value: +1
      • addedInput schema / properties / items / items / properties / access_policy / properties / ip_denylist / maxItems
        Added value: +100
      • changedInput schema / properties / items / items / properties / access_policy / properties / user_agent_allow_regex / description
        Previous value: -"Regex to allow matching user agents"New value: +"Regex to allow matching user agents (max 256 chars)"
      • addedInput schema / properties / items / items / properties / access_policy / properties / user_agent_allow_regex / maxLength
        Added value: +256
      • changedInput schema / properties / items / items / properties / access_policy / properties / user_agent_deny_regex / description
        Previous value: -"Regex to deny matching user agents"New value: +"Regex to deny matching user agents (max 256 chars)"
      • addedInput schema / properties / items / items / properties / access_policy / properties / user_agent_deny_regex / maxLength
        Added value: +256
      • changedInput schema / properties / items / items / properties / custom_domain / description
        Previous value: -"Custom domain to assign to the auto-created resource"New value: +"Custom domain to assign to the auto-created resource (max 253 chars, must be registered/active/owned)."
      • addedInput schema / properties / items / items / properties / custom_domain / maxLength
        Added value: +253
      • changedInput schema / properties / items / items / properties / max_sessions / description
        Previous value: -"Maximum concurrent sessions (0 = unlimited, max 1000)"New value: +"Maximum concurrent sessions for this qURL token (0 = unlimited when one_time_use is explicitly false; max 1000)"
      • changedInput schema / properties / items / items / properties / session_duration / description
        Previous value: -"How long access lasts after clicking (e.g., \"1h\")"New value: +"How long access lasts after the recipient reaches the content (e.g., \"1h\"). This anchors the resource-level session-duration cap when a new resource is created."
      • addedInput schema / properties / items / items / properties / type
        Added value: +{
        +  "description": "Resource type for integrations allowed to mint non-url qURLs (max 64 chars). Defaults to url.",
        +  "maxLength": 64,
        +  "type": "string"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "failed": {
        +      "type": "number"
        +    },
        +    "request_id": {
        +      "type": "string"
        +    },
        +    "results": {
        +      "items": {
        +        "description": "Per-item result. Discriminated on `success`.",
        +        "oneOf": [
        +          {
        +            "additionalProperties": {},
        +            "properties": {
        +              "branded_domain": {
        +                "description": "Bare branded hostname for anchor text when the resource has a usable custom domain",
        +                "type": "string"
        +              },
        +              "expires_at": {
        +                "type": "string"
        +              },
        +              "index": {
        +                "description": "Index of the corresponding item in the input `items` array",
        +                "type": "number"
        +              },
        +              "qurl_link": {
        +                "description": "One-shot display access link — shown ONCE on creation",
        +                "type": "string"
        +              },
        +              "qurl_site": {
        +                "type": "string"
        +              },
        +              "resource_id": {
        +                "type": "string"
        +              },
        +              "success": {
        +                "const": true,
        +                "type": "boolean"
        +              }
        +            },
        +            "required": [
        +              "index",
        +              "success",
        +              "resource_id",
        +              "qurl_link",
        +              "qurl_site",
        +              "expires_at"
        +            ],
        +            "type": "object"
        +          },
        +          {
        +            "additionalProperties": {},
        +            "properties": {
        +              "error": {
        +                "additionalProperties": {},
        +                "properties": {
        +                  "code": {
        +                    "type": "string"
        +                  },
        +                  "message": {
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "code",
        +                  "message"
        +                ],
        +                "type": "object"
        +              },
        +              "index": {
        +                "description": "Index of the corresponding item in the input `items` array",
        +                "type": "number"
        +              },
        +              "success": {
        +                "const": false,
        +                "type": "boolean"
        +              }
        +            },
        +            "required": [
        +              "index",
        +              "success",
        +              "error"
        +            ],
        +            "type": "object"
        +          }
        +        ]
        +      },
        +      "type": "array"
        +    },
        +    "succeeded": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "succeeded",
        +    "failed",
        +    "results"
        +  ],
        +  "type": "object"
        +}
    • Changedcreate_qurl37 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • removedInput schema / properties / access_policy / additionalProperties
        Removed value: -false
      • removedInput schema / properties / access_policy / properties / ai_agent_policy / additionalProperties
        Removed value: -false
      • changedInput schema / properties / access_policy / properties / ai_agent_policy / properties / allow_categories / description
        Previous value: -"AI agent categories to permit (all others blocked)"New value: +"AI agent categories to permit (all others blocked; max 20 entries, 128 chars each)"
      • addedInput schema / properties / access_policy / properties / ai_agent_policy / properties / allow_categories / items / maxLength
        Added value: +128
      • addedInput schema / properties / access_policy / properties / ai_agent_policy / properties / allow_categories / items / minLength
        Added value: +1
      • addedInput schema / properties / access_policy / properties / ai_agent_policy / properties / allow_categories / maxItems
        Added value: +20
      • changedInput schema / properties / access_policy / properties / ai_agent_policy / properties / deny_categories / description
        Previous value: -"AI agent categories to block (e.g., gptbot, commoncrawl)"New value: +"AI agent categories to block (e.g., gptbot, commoncrawl; max 20 entries, 128 chars each)"
      • addedInput schema / properties / access_policy / properties / ai_agent_policy / properties / deny_categories / items / maxLength
        Added value: +128
      • addedInput schema / properties / access_policy / properties / ai_agent_policy / properties / deny_categories / items / minLength
        Added value: +1
      • addedInput schema / properties / access_policy / properties / ai_agent_policy / properties / deny_categories / maxItems
        Added value: +20
      • changedInput schema / properties / access_policy / properties / geo_allowlist / description
        Previous value: -"Allowed country codes (ISO 3166-1 alpha-2)"New value: +"Allowed country codes (ISO 3166-1 alpha-2; max 50 entries, 8 chars each)"
      • addedInput schema / properties / access_policy / properties / geo_allowlist / items / maxLength
        Added value: +8
      • addedInput schema / properties / access_policy / properties / geo_allowlist / items / minLength
        Added value: +1
      • addedInput schema / properties / access_policy / properties / geo_allowlist / maxItems
        Added value: +50
      • changedInput schema / properties / access_policy / properties / geo_denylist / description
        Previous value: -"Denied country codes (ISO 3166-1 alpha-2)"New value: +"Denied country codes (ISO 3166-1 alpha-2; max 50 entries, 8 chars each)"
      • addedInput schema / properties / access_policy / properties / geo_denylist / items / maxLength
        Added value: +8
      • addedInput schema / properties / access_policy / properties / geo_denylist / items / minLength
        Added value: +1
      • addedInput schema / properties / access_policy / properties / geo_denylist / maxItems
        Added value: +50
      • changedInput schema / properties / access_policy / properties / ip_allowlist / description
        Previous value: -"Allowed IP addresses or CIDR ranges"New value: +"Allowed IP addresses or CIDR ranges (max 100 entries, 64 chars each)"
      • addedInput schema / properties / access_policy / properties / ip_allowlist / items / maxLength
        Added value: +64
      • addedInput schema / properties / access_policy / properties / ip_allowlist / items / minLength
        Added value: +1
      • addedInput schema / properties / access_policy / properties / ip_allowlist / maxItems
        Added value: +100
      • changedInput schema / properties / access_policy / properties / ip_denylist / description
        Previous value: -"Denied IP addresses or CIDR ranges"New value: +"Denied IP addresses or CIDR ranges (max 100 entries, 64 chars each)"
      • addedInput schema / properties / access_policy / properties / ip_denylist / items / maxLength
        Added value: +64
      • addedInput schema / properties / access_policy / properties / ip_denylist / items / minLength
        Added value: +1
      • addedInput schema / properties / access_policy / properties / ip_denylist / maxItems
        Added value: +100
      • changedInput schema / properties / access_policy / properties / user_agent_allow_regex / description
        Previous value: -"Regex to allow matching user agents"New value: +"Regex to allow matching user agents (max 256 chars)"
      • addedInput schema / properties / access_policy / properties / user_agent_allow_regex / maxLength
        Added value: +256
      • changedInput schema / properties / access_policy / properties / user_agent_deny_regex / description
        Previous value: -"Regex to deny matching user agents"New value: +"Regex to deny matching user agents (max 256 chars)"
      • addedInput schema / properties / access_policy / properties / user_agent_deny_regex / maxLength
        Added value: +256
      • changedInput schema / properties / custom_domain / description
        Previous value: -"Custom domain to assign to the auto-created resource"New value: +"Custom domain to assign to the auto-created resource (max 253 chars, must be registered/active/owned)."
      • addedInput schema / properties / custom_domain / maxLength
        Added value: +253
      • changedInput schema / properties / max_sessions / description
        Previous value: -"Maximum concurrent sessions (0 = unlimited, max 1000)"New value: +"Maximum concurrent sessions for this qURL token (0 = unlimited when one_time_use is explicitly false; max 1000)"
      • changedInput schema / properties / session_duration / description
        Previous value: -"How long access lasts after clicking (e.g., \"1h\")"New value: +"How long access lasts after the recipient reaches the content (e.g., \"1h\"). This anchors the resource-level session-duration cap when a new resource is created."
      • addedInput schema / properties / type
        Added value: +{
        +  "description": "Resource type for integrations allowed to mint non-url qURLs (max 64 chars). Defaults to url.",
        +  "maxLength": 64,
        +  "type": "string"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "branded_domain": {
        +      "description": "Bare branded hostname for anchor text when the resource has a usable custom domain",
        +      "type": "string"
        +    },
        +    "email_delivery": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "attempted": {
        +          "type": "boolean"
        +        },
        +        "enabled": {
        +          "type": "boolean"
        +        },
        +        "failed": {
        +          "type": "number"
        +        },
        +        "recipients": {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "results": {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "email": {
        +                "type": "string"
        +              },
        +              "error": {
        +                "type": "string"
        +              },
        +              "message_id": {
        +                "type": "string"
        +              },
        +              "skipped": {
        +                "type": "boolean"
        +              },
        +              "success": {
        +                "type": "boolean"
        +              }
        +            },
        +            "required": [
        +              "email",
        +              "success",
        +              "skipped"
        +            ],
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "sent": {
        +          "type": "number"
        +        },
        +        "skipped_reason": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "attempted",
        +        "enabled",
        +        "recipients",
        +        "sent",
        +        "failed",
        +        "results"
        +      ],
        +      "type": "object"
        +    },
        +    "expires_at": {
        +      "type": "string"
        +    },
        +    "label": {
        +      "type": "string"
        +    },
        +    "qurl_id": {
        +      "description": "Display-friendly qURL ID (q_ prefix)",
        +      "type": "string"
        +    },
        +    "qurl_link": {
        +      "description": "One-shot display access link — shown ONCE on creation, never returned again. Share immediately.",
        +      "type": "string"
        +    },
        +    "qurl_site": {
        +      "type": "string"
        +    },
        +    "resource_id": {
        +      "description": "Stable resource identifier (public key or legacy r_ ID)",
        +      "type": "string"
        +    },
        +    "type": {
        +      "description": "Resource type echoed from the create request",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "qurl_id",
        +    "resource_id",
        +    "qurl_link"
        +  ],
        +  "type": "object"
        +}
    • Changeddelete_qurl5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedInput schema / properties / resource_id / description
        Previous value: -"The resource ID (must start with r_). delete_qurl does not accept q_ (qURL display) IDs."New value: +"The resource public key, CRID, or legacy r_ ID to revoke (all tokens; q_ display IDs are not accepted)."
      • removedInput schema / properties / resource_id / minLength
        Removed value: -1
      • changedInput schema / properties / resource_id / pattern
        Previous value: -"^r\\_"New value: +"^(r_[a-z0-9_-]{11}|(?:[A-Za-z0-9_-]{4}){27,53}|(?:[A-Za-z0-9_-]{4}){27,53}[A-Za-z0-9_-]{2}|(?:[A-Za-z0-9_-]{4}){26,52}[A-Za-z0-9_-]{3}|[a-z2-7]{47}|[a-z2-7]{60})$"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "message": {
        +      "description": "Human-readable confirmation message",
        +      "type": "string"
        +    },
        +    "resource_id": {
        +      "type": "string"
        +    },
        +    "revoked": {
        +      "const": true,
        +      "type": "boolean"
        +    },
        +    "was_already_revoked": {
        +      "description": "True when the API responded 404 (resource was already revoked or never existed). Agents that need to distinguish 'I revoked it' from 'it was already gone' should branch on this.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "resource_id",
        +    "revoked",
        +    "was_already_revoked",
        +    "message"
        +  ],
        +  "type": "object"
        +}
    • Changedextend_qurl5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedInput schema / properties / resource_id / description
        Previous value: -"The resource ID (r_ prefix) or qURL display ID (q_ prefix) to extend. If a q_ ID is passed, the API resolves it to the parent resource automatically."New value: +"The resource public key, CRID, legacy r_ ID, or qURL display ID (q_ prefix) to extend. If a q_ ID is passed, the API resolves it to the parent resource automatically."
      • removedInput schema / properties / resource_id / minLength
        Removed value: -1
      • addedInput schema / properties / resource_id / pattern
        Added value: +"(?:^(r_[a-z0-9_-]{11}|(?:[A-Za-z0-9_-]{4}){27,53}|(?:[A-Za-z0-9_-]{4}){27,53}[A-Za-z0-9_-]{2}|(?:[A-Za-z0-9_-]{4}){26,52}[A-Za-z0-9_-]{3}|[a-z2-7]{47}|[a-z2-7]{60})$)|(?:^q_[0-9a-f]{11}$)"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "created_at": {
        +      "type": "string"
        +    },
        +    "custom_domain": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "description": {
        +      "type": "string"
        +    },
        +    "expires_at": {
        +      "type": "string"
        +    },
        +    "preserve_host": {
        +      "description": "When true, the original Host header is preserved when proxying via the custom domain. Only meaningful when custom_domain is set; defaults to false on the API side.",
        +      "type": "boolean"
        +    },
        +    "qurl_count": {
        +      "description": "Number of access tokens minted for this resource",
        +      "type": "number"
        +    },
        +    "qurl_site": {
        +      "type": "string"
        +    },
        +    "qurls": {
        +      "items": {
        +        "additionalProperties": {},
        +        "description": "Single access token belonging to a qURL resource",
        +        "properties": {
        +          "access_policy": {
        +            "additionalProperties": {},
        +            "description": "Access control policy snapshot for this token",
        +            "properties": {
        +              "ai_agent_policy": {
        +                "additionalProperties": {},
        +                "properties": {
        +                  "allow_categories": {
        +                    "items": {
        +                      "type": "string"
        +                    },
        +                    "type": "array"
        +                  },
        +                  "block_all": {
        +                    "type": "boolean"
        +                  },
        +                  "deny_categories": {
        +                    "items": {
        +                      "type": "string"
        +                    },
        +                    "type": "array"
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "geo_allowlist": {
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "geo_denylist": {
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "ip_allowlist": {
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "ip_denylist": {
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "user_agent_allow_regex": {
        +                "type": "string"
        +              },
        +              "user_agent_deny_regex": {
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "created_at": {
        +            "type": "string"
        +          },
        +          "expires_at": {
        +            "type": "string"
        +          },
        +          "label": {
        +            "type": "string"
        +          },
        +          "max_sessions": {
        +            "type": "number"
        +          },
        +          "one_time_use": {
        +            "type": "boolean"
        +          },
        +          "qurl_id": {
        +            "type": "string"
        +          },
        +          "qurl_site": {
        +            "type": "string"
        +          },
        +          "session_duration": {
        +            "description": "Seconds of access granted after a successful resolve",
        +            "type": "number"
        +          },
        +          "status": {
        +            "default": "unknown",
        +            "description": "Per-token status (wider than resource status — tokens may be consumed/expired independently)",
        +            "enum": [
        +              "active",
        +              "consumed",
        +              "expired",
        +              "revoked",
        +              "unknown"
        +            ],
        +            "type": "string"
        +          },
        +          "use_count": {
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "qurl_id",
        +          "status"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "resource_id": {
        +      "description": "Stable resource identifier (public key or legacy r_ ID)",
        +      "type": "string"
        +    },
        +    "slug": {
        +      "description": "Immutable per-owner resource identity, when one was supplied at create time",
        +      "type": "string"
        +    },
        +    "status": {
        +      "default": "unknown",
        +      "enum": [
        +        "active",
        +        "revoked",
        +        "expired",
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "tags": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "target_url": {
        +      "description": "Underlying URL the qURL protects; omitted on connector-owned resources",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "resource_id",
        +    "expires_at",
        +    "created_at",
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Changedget_qurl5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedInput schema / properties / resource_id / description
        Previous value: -"The resource ID (r_ prefix) or qURL display ID (q_ prefix) to fetch. If a q_ ID is passed, the API resolves it to the parent resource automatically."New value: +"The resource public key, CRID, legacy r_ ID, or qURL display ID (q_ prefix) to fetch. If a q_ ID is passed, the API resolves it to the parent resource automatically."
      • removedInput schema / properties / resource_id / minLength
        Removed value: -1
      • addedInput schema / properties / resource_id / pattern
        Added value: +"(?:^(r_[a-z0-9_-]{11}|(?:[A-Za-z0-9_-]{4}){27,53}|(?:[A-Za-z0-9_-]{4}){27,53}[A-Za-z0-9_-]{2}|(?:[A-Za-z0-9_-]{4}){26,52}[A-Za-z0-9_-]{3}|[a-z2-7]{47}|[a-z2-7]{60})$)|(?:^q_[0-9a-f]{11}$)"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "created_at": {
        +      "type": "string"
        +    },
        +    "custom_domain": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "description": {
        +      "type": "string"
        +    },
        +    "expires_at": {
        +      "type": "string"
        +    },
        +    "preserve_host": {
        +      "description": "When true, the original Host header is preserved when proxying via the custom domain. Only meaningful when custom_domain is set; defaults to false on the API side.",
        +      "type": "boolean"
        +    },
        +    "qurl_count": {
        +      "description": "Number of access tokens minted for this resource",
        +      "type": "number"
        +    },
        +    "qurl_site": {
        +      "type": "string"
        +    },
        +    "qurls": {
        +      "items": {
        +        "additionalProperties": {},
        +        "description": "Single access token belonging to a qURL resource",
        +        "properties": {
        +          "access_policy": {
        +            "additionalProperties": {},
        +            "description": "Access control policy snapshot for this token",
        +            "properties": {
        +              "ai_agent_policy": {
        +                "additionalProperties": {},
        +                "properties": {
        +                  "allow_categories": {
        +                    "items": {
        +                      "type": "string"
        +                    },
        +                    "type": "array"
        +                  },
        +                  "block_all": {
        +                    "type": "boolean"
        +                  },
        +                  "deny_categories": {
        +                    "items": {
        +                      "type": "string"
        +                    },
        +                    "type": "array"
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "geo_allowlist": {
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "geo_denylist": {
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "ip_allowlist": {
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "ip_denylist": {
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "user_agent_allow_regex": {
        +                "type": "string"
        +              },
        +              "user_agent_deny_regex": {
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "created_at": {
        +            "type": "string"
        +          },
        +          "expires_at": {
        +            "type": "string"
        +          },
        +          "label": {
        +            "type": "string"
        +          },
        +          "max_sessions": {
        +            "type": "number"
        +          },
        +          "one_time_use": {
        +            "type": "boolean"
        +          },
        +          "qurl_id": {
        +            "type": "string"
        +          },
        +          "qurl_site": {
        +            "type": "string"
        +          },
        +          "session_duration": {
        +            "description": "Seconds of access granted after a successful resolve",
        +            "type": "number"
        +          },
        +          "status": {
        +            "default": "unknown",
        +            "description": "Per-token status (wider than resource status — tokens may be consumed/expired independently)",
        +            "enum": [
        +              "active",
        +              "consumed",
        +              "expired",
        +              "revoked",
        +              "unknown"
        +            ],
        +            "type": "string"
        +          },
        +          "use_count": {
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "qurl_id",
        +          "status"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "resource_id": {
        +      "description": "Stable resource identifier (public key or legacy r_ ID)",
        +      "type": "string"
        +    },
        +    "slug": {
        +      "description": "Immutable per-owner resource identity, when one was supplied at create time",
        +      "type": "string"
        +    },
        +    "status": {
        +      "default": "unknown",
        +      "enum": [
        +        "active",
        +        "revoked",
        +        "expired",
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "tags": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "target_url": {
        +      "description": "Underlying URL the qURL protects; omitted on connector-owned resources",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "resource_id",
        +    "expires_at",
        +    "created_at",
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Addedlist_qurl_sessions
    • Changedlist_qurls7 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / created_after / pattern
        Added value: +"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
      • addedInput schema / properties / created_before / pattern
        Added value: +"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
      • addedInput schema / properties / expires_after / pattern
        Added value: +"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
      • addedInput schema / properties / expires_before / pattern
        Added value: +"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
      • changedInput schema / properties / status / description
        Previous value: -"Filter by status (comma-separated, e.g., 'active,revoked')"New value: +"Filter by status (comma-separated, e.g. 'active,revoked'). Defaults to 'active' when omitted; pass 'revoked' or 'active,revoked' to override. Only active and revoked are valid resource filters; expired is not accepted."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "data": {
        +      "items": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "created_at": {
        +            "type": "string"
        +          },
        +          "custom_domain": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "description": {
        +            "type": "string"
        +          },
        +          "expires_at": {
        +            "type": "string"
        +          },
        +          "preserve_host": {
        +            "description": "When true, the original Host header is preserved when proxying via the custom domain. Only meaningful when custom_domain is set; defaults to false on the API side.",
        +            "type": "boolean"
        +          },
        +          "qurl_count": {
        +            "description": "Number of access tokens minted for this resource",
        +            "type": "number"
        +          },
        +          "qurl_site": {
        +            "type": "string"
        +          },
        +          "qurls": {
        +            "items": {
        +              "additionalProperties": {},
        +              "description": "Single access token belonging to a qURL resource",
        +              "properties": {
        +                "access_policy": {
        +                  "additionalProperties": {},
        +                  "description": "Access control policy snapshot for this token",
        +                  "properties": {
        +                    "ai_agent_policy": {
        +                      "additionalProperties": {},
        +                      "properties": {
        +                        "allow_categories": {
        +                          "items": {
        +                            "type": "string"
        +                          },
        +                          "type": "array"
        +                        },
        +                        "block_all": {
        +                          "type": "boolean"
        +                        },
        +                        "deny_categories": {
        +                          "items": {
        +                            "type": "string"
        +                          },
        +                          "type": "array"
        +                        }
        +                      },
        +                      "type": "object"
        +                    },
        +                    "geo_allowlist": {
        +                      "items": {
        +                        "type": "string"
        +                      },
        +                      "type": "array"
        +                    },
        +                    "geo_denylist": {
        +                      "items": {
        +                        "type": "string"
        +                      },
        +                      "type": "array"
        +                    },
        +                    "ip_allowlist": {
        +                      "items": {
        +                        "type": "string"
        +                      },
        +                      "type": "array"
        +                    },
        +                    "ip_denylist": {
        +                      "items": {
        +                        "type": "string"
        +                      },
        +                      "type": "array"
        +                    },
        +                    "user_agent_allow_regex": {
        +                      "type": "string"
        +                    },
        +                    "user_agent_deny_regex": {
        +                      "type": "string"
        +                    }
        +                  },
        +                  "type": "object"
        +                },
        +                "created_at": {
        +                  "type": "string"
        +                },
        +                "expires_at": {
        +                  "type": "string"
        +                },
        +                "label": {
        +                  "type": "string"
        +                },
        +                "max_sessions": {
        +                  "type": "number"
        +                },
        +                "one_time_use": {
        +                  "type": "boolean"
        +                },
        +                "qurl_id": {
        +                  "type": "string"
        +                },
        +                "qurl_site": {
        +                  "type": "string"
        +                },
        +                "session_duration": {
        +                  "description": "Seconds of access granted after a successful resolve",
        +                  "type": "number"
        +                },
        +                "status": {
        +                  "default": "unknown",
        +                  "description": "Per-token status (wider than resource status — tokens may be consumed/expired independently)",
        +                  "enum": [
        +                    "active",
        +                    "consumed",
        +                    "expired",
        +                    "revoked",
        +                    "unknown"
        +                  ],
        +                  "type": "string"
        +                },
        +                "use_count": {
        +                  "type": "number"
        +                }
        +              },
        +              "required": [
        +                "qurl_id",
        +                "status"
        +              ],
        +              "type": "object"
        +            },
        +            "type": "array"
        +          },
        +          "resource_id": {
        +            "description": "Stable resource identifier (public key or legacy r_ ID)",
        +            "type": "string"
        +          },
        +          "slug": {
        +            "description": "Immutable per-owner resource identity, when one was supplied at create time",
        +            "type": "string"
        +          },
        +          "status": {
        +            "default": "unknown",
        +            "enum": [
        +              "active",
        +              "revoked",
        +              "expired",
        +              "unknown"
        +            ],
        +            "type": "string"
        +          },
        +          "tags": {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          "target_url": {
        +            "description": "Underlying URL the qURL protects; omitted on connector-owned resources",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "resource_id",
        +          "expires_at",
        +          "created_at",
        +          "status"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "meta": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "has_more": {
        +          "description": "True if more pages are available beyond this response",
        +          "type": "boolean"
        +        },
        +        "next_cursor": {
        +          "description": "Pass to a subsequent list_qurls call to fetch the next page",
        +          "type": "string"
        +        },
        +        "page_size": {
        +          "type": "number"
        +        },
        +        "request_id": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "has_more"
        +      ],
        +      "type": "object"
        +    }
        +  },
        +  "required": [
        +    "data",
        +    "meta"
        +  ],
        +  "type": "object"
        +}
    • Changedmint_link38 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • removedInput schema / properties / access_policy / additionalProperties
        Removed value: -false
      • removedInput schema / properties / access_policy / properties / ai_agent_policy / additionalProperties
        Removed value: -false
      • changedInput schema / properties / access_policy / properties / ai_agent_policy / properties / allow_categories / description
        Previous value: -"AI agent categories to permit (all others blocked)"New value: +"AI agent categories to permit (all others blocked; max 20 entries, 128 chars each)"
      • addedInput schema / properties / access_policy / properties / ai_agent_policy / properties / allow_categories / items / maxLength
        Added value: +128
      • addedInput schema / properties / access_policy / properties / ai_agent_policy / properties / allow_categories / items / minLength
        Added value: +1
      • addedInput schema / properties / access_policy / properties / ai_agent_policy / properties / allow_categories / maxItems
        Added value: +20
      • changedInput schema / properties / access_policy / properties / ai_agent_policy / properties / deny_categories / description
        Previous value: -"AI agent categories to block (e.g., gptbot, commoncrawl)"New value: +"AI agent categories to block (e.g., gptbot, commoncrawl; max 20 entries, 128 chars each)"
      • addedInput schema / properties / access_policy / properties / ai_agent_policy / properties / deny_categories / items / maxLength
        Added value: +128
      • addedInput schema / properties / access_policy / properties / ai_agent_policy / properties / deny_categories / items / minLength
        Added value: +1
      • addedInput schema / properties / access_policy / properties / ai_agent_policy / properties / deny_categories / maxItems
        Added value: +20
      • changedInput schema / properties / access_policy / properties / geo_allowlist / description
        Previous value: -"Allowed country codes (ISO 3166-1 alpha-2)"New value: +"Allowed country codes (ISO 3166-1 alpha-2; max 50 entries, 8 chars each)"
      • addedInput schema / properties / access_policy / properties / geo_allowlist / items / maxLength
        Added value: +8
      • addedInput schema / properties / access_policy / properties / geo_allowlist / items / minLength
        Added value: +1
      • addedInput schema / properties / access_policy / properties / geo_allowlist / maxItems
        Added value: +50
      • changedInput schema / properties / access_policy / properties / geo_denylist / description
        Previous value: -"Denied country codes (ISO 3166-1 alpha-2)"New value: +"Denied country codes (ISO 3166-1 alpha-2; max 50 entries, 8 chars each)"
      • addedInput schema / properties / access_policy / properties / geo_denylist / items / maxLength
        Added value: +8
      • addedInput schema / properties / access_policy / properties / geo_denylist / items / minLength
        Added value: +1
      • addedInput schema / properties / access_policy / properties / geo_denylist / maxItems
        Added value: +50
      • changedInput schema / properties / access_policy / properties / ip_allowlist / description
        Previous value: -"Allowed IP addresses or CIDR ranges"New value: +"Allowed IP addresses or CIDR ranges (max 100 entries, 64 chars each)"
      • addedInput schema / properties / access_policy / properties / ip_allowlist / items / maxLength
        Added value: +64
      • addedInput schema / properties / access_policy / properties / ip_allowlist / items / minLength
        Added value: +1
      • addedInput schema / properties / access_policy / properties / ip_allowlist / maxItems
        Added value: +100
      • changedInput schema / properties / access_policy / properties / ip_denylist / description
        Previous value: -"Denied IP addresses or CIDR ranges"New value: +"Denied IP addresses or CIDR ranges (max 100 entries, 64 chars each)"
      • addedInput schema / properties / access_policy / properties / ip_denylist / items / maxLength
        Added value: +64
      • addedInput schema / properties / access_policy / properties / ip_denylist / items / minLength
        Added value: +1
      • addedInput schema / properties / access_policy / properties / ip_denylist / maxItems
        Added value: +100
      • changedInput schema / properties / access_policy / properties / user_agent_allow_regex / description
        Previous value: -"Regex to allow matching user agents"New value: +"Regex to allow matching user agents (max 256 chars)"
      • addedInput schema / properties / access_policy / properties / user_agent_allow_regex / maxLength
        Added value: +256
      • changedInput schema / properties / access_policy / properties / user_agent_deny_regex / description
        Previous value: -"Regex to deny matching user agents"New value: +"Regex to deny matching user agents (max 256 chars)"
      • addedInput schema / properties / access_policy / properties / user_agent_deny_regex / maxLength
        Added value: +256
      • addedInput schema / properties / expires_at / pattern
        Added value: +"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
      • changedInput schema / properties / max_sessions / description
        Previous value: -"Maximum concurrent sessions (0 = unlimited, max 1000)"New value: +"Maximum concurrent sessions for this qURL token (0 = unlimited, max 1000)"
      • changedInput schema / properties / resource_id / description
        Previous value: -"The resource ID (r_ prefix) or qURL display ID (q_ prefix) to mint a new access link for. If a q_ ID is passed, the API resolves it to the parent resource automatically."New value: +"The resource public key, CRID, legacy r_ ID, or qURL display ID (q_ prefix) to mint a new access link for. If a q_ ID is passed, the API resolves it to the parent resource automatically."
      • removedInput schema / properties / resource_id / minLength
        Removed value: -1
      • addedInput schema / properties / resource_id / pattern
        Added value: +"(?:^(r_[a-z0-9_-]{11}|(?:[A-Za-z0-9_-]{4}){27,53}|(?:[A-Za-z0-9_-]{4}){27,53}[A-Za-z0-9_-]{2}|(?:[A-Za-z0-9_-]{4}){26,52}[A-Za-z0-9_-]{3}|[a-z2-7]{47}|[a-z2-7]{60})$)|(?:^q_[0-9a-f]{11}$)"
      • changedInput schema / properties / session_duration / description
        Previous value: -"How long access lasts after clicking (e.g., \"1h\")"New value: +"How long access lasts after clicking (e.g., \"1h\"). Rejected if it exceeds the parent resource's session-duration cap."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "branded_domain": {
        +      "description": "Bare branded hostname for anchor text when the resource has a usable custom domain",
        +      "type": "string"
        +    },
        +    "email_delivery": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "attempted": {
        +          "type": "boolean"
        +        },
        +        "enabled": {
        +          "type": "boolean"
        +        },
        +        "failed": {
        +          "type": "number"
        +        },
        +        "recipients": {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "results": {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "email": {
        +                "type": "string"
        +              },
        +              "error": {
        +                "type": "string"
        +              },
        +              "message_id": {
        +                "type": "string"
        +              },
        +              "skipped": {
        +                "type": "boolean"
        +              },
        +              "success": {
        +                "type": "boolean"
        +              }
        +            },
        +            "required": [
        +              "email",
        +              "success",
        +              "skipped"
        +            ],
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "sent": {
        +          "type": "number"
        +        },
        +        "skipped_reason": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "attempted",
        +        "enabled",
        +        "recipients",
        +        "sent",
        +        "failed",
        +        "results"
        +      ],
        +      "type": "object"
        +    },
        +    "expires_at": {
        +      "type": "string"
        +    },
        +    "qurl_id": {
        +      "description": "Display-friendly qURL ID (q_ prefix) for the minted token",
        +      "type": "string"
        +    },
        +    "qurl_link": {
        +      "description": "Newly minted access link with one-shot display semantics, like create_qurl",
        +      "type": "string"
        +    },
        +    "type": {
        +      "description": "Resource type echoed from the underlying resource",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "qurl_id",
        +    "qurl_link"
        +  ],
        +  "type": "object"
        +}
    • Changedresolve_qurl2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "access_grant": {
        +      "additionalProperties": {},
        +      "description": "Time-bound, IP-bound network access grant",
        +      "properties": {
        +        "expires_in": {
        +          "description": "Seconds the network grant permits access from `src_ip` before re-resolution is required",
        +          "type": "number"
        +        },
        +        "granted_at": {
        +          "type": "string"
        +        },
        +        "src_ip": {
        +          "description": "Caller IP that the access grant is bound to",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "expires_in",
        +        "granted_at",
        +        "src_ip"
        +      ],
        +      "type": "object"
        +    },
        +    "resource_id": {
        +      "type": "string"
        +    },
        +    "target_url": {
        +      "description": "Underlying URL revealed by the resolve",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "target_url",
        +    "resource_id",
        +    "access_grant"
        +  ],
        +  "type": "object"
        +}
    • Addedrevoke_qurl_token
    • Addedterminate_qurl_sessions
    • Changedupdate_qurl8 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / custom_domain
        Added value: +{
        +  "description": "Replace the custom domain bound to this resource (max 253 chars, must be registered/active/owned). Pass \"\" to clear.",
        +  "maxLength": 253,
        +  "type": "string"
        +}
      • addedInput schema / properties / expires_at / pattern
        Added value: +"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
      • addedInput schema / properties / preserve_host
        Added value: +{
        +  "description": "Whether to preserve the original Host header when proxying via the custom domain. Only meaningful when custom_domain is set; default false on the API side.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / resource_id / description
        Previous value: -"The resource ID (r_ prefix) or qURL display ID (q_ prefix) to update. If a q_ ID is passed, the API resolves it to the parent resource automatically."New value: +"The resource public key, CRID, legacy r_ ID, or qURL display ID (q_ prefix) to update. If a q_ ID is passed, the API resolves it to the parent resource automatically."
      • removedInput schema / properties / resource_id / minLength
        Removed value: -1
      • addedInput schema / properties / resource_id / pattern
        Added value: +"(?:^(r_[a-z0-9_-]{11}|(?:[A-Za-z0-9_-]{4}){27,53}|(?:[A-Za-z0-9_-]{4}){27,53}[A-Za-z0-9_-]{2}|(?:[A-Za-z0-9_-]{4}){26,52}[A-Za-z0-9_-]{3}|[a-z2-7]{47}|[a-z2-7]{60})$)|(?:^q_[0-9a-f]{11}$)"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "created_at": {
        +      "type": "string"
        +    },
        +    "custom_domain": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "description": {
        +      "type": "string"
        +    },
        +    "expires_at": {
        +      "type": "string"
        +    },
        +    "preserve_host": {
        +      "description": "When true, the original Host header is preserved when proxying via the custom domain. Only meaningful when custom_domain is set; defaults to false on the API side.",
        +      "type": "boolean"
        +    },
        +    "qurl_count": {
        +      "description": "Number of access tokens minted for this resource",
        +      "type": "number"
        +    },
        +    "qurl_site": {
        +      "type": "string"
        +    },
        +    "qurls": {
        +      "items": {
        +        "additionalProperties": {},
        +        "description": "Single access token belonging to a qURL resource",
        +        "properties": {
        +          "access_policy": {
        +            "additionalProperties": {},
        +            "description": "Access control policy snapshot for this token",
        +            "properties": {
        +              "ai_agent_policy": {
        +                "additionalProperties": {},
        +                "properties": {
        +                  "allow_categories": {
        +                    "items": {
        +                      "type": "string"
        +                    },
        +                    "type": "array"
        +                  },
        +                  "block_all": {
        +                    "type": "boolean"
        +                  },
        +                  "deny_categories": {
        +                    "items": {
        +                      "type": "string"
        +                    },
        +                    "type": "array"
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "geo_allowlist": {
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "geo_denylist": {
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "ip_allowlist": {
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "ip_denylist": {
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "user_agent_allow_regex": {
        +                "type": "string"
        +              },
        +              "user_agent_deny_regex": {
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "created_at": {
        +            "type": "string"
        +          },
        +          "expires_at": {
        +            "type": "string"
        +          },
        +          "label": {
        +            "type": "string"
        +          },
        +          "max_sessions": {
        +            "type": "number"
        +          },
        +          "one_time_use": {
        +            "type": "boolean"
        +          },
        +          "qurl_id": {
        +            "type": "string"
        +          },
        +          "qurl_site": {
        +            "type": "string"
        +          },
        +          "session_duration": {
        +            "description": "Seconds of access granted after a successful resolve",
        +            "type": "number"
        +          },
        +          "status": {
        +            "default": "unknown",
        +            "description": "Per-token status (wider than resource status — tokens may be consumed/expired independently)",
        +            "enum": [
        +              "active",
        +              "consumed",
        +              "expired",
        +              "revoked",
        +              "unknown"
        +            ],
        +            "type": "string"
        +          },
        +          "use_count": {
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "qurl_id",
        +          "status"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "resource_id": {
        +      "description": "Stable resource identifier (public key or legacy r_ ID)",
        +      "type": "string"
        +    },
        +    "slug": {
        +      "description": "Immutable per-owner resource identity, when one was supplied at create time",
        +      "type": "string"
        +    },
        +    "status": {
        +      "default": "unknown",
        +      "enum": [
        +        "active",
        +        "revoked",
        +        "expired",
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "tags": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "target_url": {
        +      "description": "Underlying URL the qURL protects; omitted on connector-owned resources",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "resource_id",
        +    "expires_at",
        +    "created_at",
        +    "status"
        +  ],
        +  "type": "object"
        +}
    • Addedupdate_qurl_token
  2. 9 tool updatesv0.2.0
    • First observedbatch_create_qurls
    • First observedcreate_qurl
    • First observeddelete_qurl
    • First observedextend_qurl
    • First observedget_qurl
    • First observedlist_qurls
    • First observedmint_link
    • First observedresolve_qurl
    • First observedupdate_qurl

TDQS

A4.5/5.0

Scored across 13 tools

Disambiguation5/5

Each tool targets a distinct resource, token, or session action. Overlapping tools like create_qurl, mint_link, and batch_create_qurls are clearly differentiated with explicit usage guidance. No tool appears duplicative or confusable.

Naming Consistency4/5

The naming is mostly consistent with a verb_qurl* snake_case pattern. The main deviation is 'mint_link', which breaks the expected qurl-related naming, and minor singular/plural inconsistency between get_qurl and list_qurls.

Tool Count5/5

Thirteen tools is well-scoped for managing qURL resources, tokens, and sessions. Each tool serves a distinct purpose with no obvious bloat or excessive granularity.

Completeness3/5

The core resource lifecycle, token management, and session controls are well covered. However, create_qurl and batch_create_qurls explicitly reference upload_file_data_qurl and upload_file_qurl for chat-uploaded files, but those tools are absent from this server, creating a noticeable dead end for a stated use case. A dedicated token-list operation is also missing, though get_qurl provides a limited preview.

Maintenance

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    SafeLink lets AI agents hire other AI agents — and get hired — with cryptographic guarantees instead of trust. Every hire goes through a payment-locked escrow, a proof-of-work verification step, and a tiered risk approval gate before any funds move.
    10 npm
    4
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    URL intelligence for AI agents. One URL in, structured security and data quality signals out across 7 dimensions. 13 tools, risk score 0-100 with 23 configurable weights.
    16
    56 npm
    1
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Generate styled QR codes, manage dynamic short links with click analytics, and publish micro-landing pages via AI agents.
    19
    40 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    QrVerloz lets AI agents create QR codes instantly — no account needed, active for 90 days, and claimable at any time to make them permanent. Retarget the destination URL whenever you need, without reprinting.
    3
    MIT

Appeared in Searches