Skip to main content
Glama
edithatogo

fyi-mcp

by edithatogo

FYI CLI

A multi-jurisdiction Freedom-of-Information (FOI) client for Alaveteli-based platforms — track, submit, and archive official information requests across New Zealand, Australia, the UK, and any other Alaveteli deployment (foi-repository, WhatDoTheyKnow, FragDenStaat, and more), from a single privacy-focused CLI.

PyPI version Crates.io License: MIT CI Codecov Glama MCP Registry

The project's core is a Rust workspace (fyi-core, fyi-cli, fyi-mcp); a legacy Python package (fyi_system) remains available as a reference implementation but is no longer extended.

Where fyi-cli / fyi-mcp is listed

Registry / catalog

Package / server

Status

Link

Official MCP Registry

io.github.edithatogo/fyi-mcp @ 0.1.2

Live

registry.modelcontextprotocol.io · server.json

OpenAI plugin directory (Codex)

fyi-mcp plugin packet

Assets ready — external submission pending

packaging/ai-plugins/codex/

Anthropic Claude Connectors

fyi-mcp connector packet

Assets ready — hosted HTTPS deployment and external submission pending

packaging/ai-plugins/anthropic/

Glama

edithatogo/fyi-cli (fyi-mcp)

Live

glama.ai/mcp/servers/edithatogo/fyi-cli · scores

Smithery

edithatogo/fyi-mcp

Live (score pending)

smithery.ai/server/@edithatogo/fyi-mcp

PyPI

fyi-cli (legacy Python package)

Live

pypi.org/project/fyi-cli

Crates.io

fyi-cli / workspace crates

Published / release flow

crates.io/crates/fyi-cli

GitHub Releases

CLI + MCPB assets

Live

Releases

Awesome-MCP-Servers

Legal section entry

PR submitted

PR #9693

GitHub curated MCP (github.com/mcp)

Blocked external (manual onboarding)

Tracked in #32

Draft / not yet submitted: Scoop, WinGet, Homebrew, Chocolatey, GHCR multi-arch workflow, PulseMCP, mcp.so, Docker MCP Catalog, mcp-get, OpenTools, AUR, nixpkgs, Snap, Flatpak, asdf/mise, Debian/PPA, Fedora/COPR.

cargo-binstall is already assets-ready and wired in-repo, but still depends on matching GitHub Release assets before it can be treated as a live distribution path. Codex and Anthropic packets are assets-ready but still require external submission.

Full status matrix (including planned channels): docs/registry-distribution-matrix.md.


🚀 Quick Start

# Install (Rust workspace, recommended)
cargo install --path crates/fyi-cli
# or: cargo install fyi-cli   (once published to crates.io)

# Initialize
fyi-cli init-db

# Create your first request
fyi-cli register-request ministry-of-justice "OIA Request" "Request body..." --status draft

# Track and manage requests
fyi-cli list-requests

Full guide: QUICKSTART.md


Related MCP server: sourceright

✨ Features

  • 🌐 Multi-Jurisdiction: Works with any Alaveteli deployment — foi-repository (NZ), WhatDoTheyKnow (UK), FragDenStaat (Germany), righttoknow.org.au (Australia), and more, with jurisdiction-aware metadata and localization on the way

  • 🔒 Privacy-First: All data stored locally, optional encryption, Tor support

  • 📊 Track Requests: Monitor FOI/OIA requests from creation to completion

  • 🤖 Automated Monitoring: Watch instances for updates automatically

  • 📈 Reports & Analytics: Generate dashboards, attention reports, handover docs

  • 🔐 Secure Storage: Encrypted credentials, OS keyring integration

  • 💻 CLI + MCP: Command-line tool and an MCP server for AI assistants

  • 📦 Export Options: JSON, CSV, HTML export capabilities

  • 🗄️ Faithful Archiving: WARC/WACZ capture of requests, correspondence, and attachments


📦 Installation

Full guide (Rust-first, all channels): INSTALL.md · version 0.1.2 · homepage github.com/edithatogo/fyi-cli

Path

Command / location

Notes

Cargo (clone)

cargo install --path crates/fyi-cli

Recommended

Cargo (crates.io)

cargo install fyi-cli

When published

cargo-binstall

cargo binstall fyi-cli

assets-ready — needs matching release assets

GitHub Releases

Releases

Prebuilt CLI / MCPB; check asset names per tag

PyPI (legacy)

pip install fyi-cli

Python fyi_system; not extended

MCP binary

cargo install --path crates/fyi-mcp

Or MCPB from Releases

MCP registries

Official / Glama / Smithery

live — see table above

Containers

ghcr.io/edithatogo/fyi-mcp

assets-readydocs/containers.md

Scoop, WinGet, Homebrew, Chocolatey, AUR, nix, Snap, Flatpak, Debian, Fedora, asdf, mise

Drafts under packaging/

Not claimed livedocs/installation-package-managers.md

git clone https://github.com/edithatogo/fyi-cli.git
cd fyi-cli
cargo install --path crates/fyi-cli --locked
fyi-cli --help

Live listings and draft status: Where fyi-cli / fyi-mcp is listed · full matrix: docs/registry-distribution-matrix.md · MCP catalog checklist: packaging/mcp-catalogs/SUBMISSION_CHECKLIST.md.


📖 Documentation

Document

Description

Docs site

Full documentation (Astro + Starlight)

docs/cli-entrypoints-audit.md

Canonical cross-reference for Python CLI, Rust CLI, and Rust MCP surfaces

docs/upstream-relations.md

Alaveteli/instance operator etiquette and outreach log

docs/registry-distribution-matrix.md

MCP catalogs, package managers, containers status

docs/external-registry-followups.md

Smithery score + GitHub MCP onboarding playbook

docs/installation-package-managers.md

Draft package-manager install notes (Scoop, WinGet, brew, …)

docs/containers.md

fyi-mcp container / GHCR

QUICKSTART.md

5-minute getting started guide

USER_GUIDE.md

Comprehensive user documentation

INSTALL.md

Installation guide (Rust-first; all channels)

API_KEY_SETUP.md

How to get and configure API key

CONFIGURATION.md

Configuration reference

TROUBLESHOOTING.md

Troubleshooting guide

FAQ.md

Frequently asked questions

CHANGELOG.md

Version history

CONTRIBUTING.md

How to contribute

CITATION.cff

Citation metadata for releases

.zenodo.json

Zenodo release metadata source


📚 Citation and Zenodo

Release metadata is versioned in CITATION.cff, .zenodo.json, and artifacts/release/zenodo-mirror-manifest.json. DOI fields remain unset until the live Zenodo record is verified for the tagged release.


🛡️ Security

Reporting a Vulnerability

Please do NOT report security vulnerabilities through public GitHub issues.

Use GitHub's private vulnerability reporting: https://github.com/edithatogo/fyi-cli/security/advisories/new

Security Policy: SECURITY.md

Security Features

  • ✅ AES-256-GCM encryption for sensitive data

  • ✅ PBKDF2-HMAC-SHA256 key derivation

  • ✅ OS keyring integration for credential storage

  • ✅ Tamper-evident audit logging

  • ✅ Secure session management

  • ✅ Input validation and sanitization

  • ✅ Security headers (CSP, HSTS, X-Frame-Options)

  • ✅ Automated security scanning (CodeQL, pip-audit, bandit)


🧪 Testing

# Rust release checks used by this repository
cargo +stable-x86_64-pc-windows-gnu fmt --all -- --check
cargo +stable-x86_64-pc-windows-gnu clippy --workspace --all-targets --all-features -- -D warnings
cargo +stable-x86_64-pc-windows-gnu test --workspace --all-features

# Python legacy/support checks
.\.venv\Scripts\python.exe -m pytest tests/test_release_readiness.py

# Opt-in live smoke test
FYI_LIVE_SMOKE=1 .\.venv\Scripts\python.exe -m pytest -m smoke tests/test_discovery_smoke.py

Test Coverage: Rust workspace checks are the release gate. Python support tests remain available for legacy docs and archive tooling.


🤝 Contributing

We welcome contributions! See CONTRIBUTING.md for guidelines.

Quick Start for Contributors

# Fork and clone
git clone https://github.com/YOUR_USERNAME/fyi-cli.git
cd fyi-cli

# Build & test the Rust workspace
cargo build --workspace --all-features
cargo test --workspace --all-features

# Make your changes, then submit a PR
git commit -m "feat: Add awesome feature"
git push origin feature/awesome-feature

See CONTRIBUTING.md for the full development setup, including the legacy Python fyi_system package.

Code of Conduct

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.


📊 Project Status

GitHub Projects

The project board for this repository is fyi-cli Conductor Roadmap. It mirrors the local .conductor/tracks.md registry and tracks completed Conductor work, release-readiness items, and external MCP registry follow-ups.

The umbrella Rare Insights on Open Policy from Aotearoa project is synchronized at the item level. GitHub Projects does not support nested projects, so synchronization is handled by scripts/sync_github_projects.py and the manual/scheduled project-sync workflow.

# Preview synchronization without changing either project
.\.venv\Scripts\python.exe scripts\sync_github_projects.py --dry-run

# Apply synchronization from fyi-cli project 6 into RIOPA project 4
.\.venv\Scripts\python.exe scripts\sync_github_projects.py

The workflow requires a repository secret named PROJECT_SYNC_TOKEN with GitHub Projects access for user-level ProjectsV2 writes. The sync is conservative: it adds missing fyi-cli issue/PR items to RIOPA, copies shared status values, sets the RIOPA mirror source to other unless a fyi-cli option exists, and never deletes umbrella-board items.

Project Status

This project is actively evolving from an NZ-only tool into a multi-jurisdiction FOI/Alaveteli platform built on the Rust workspace. Current work is tracked as Conductor tracks under .conductor/tracks.md, mirrored to GitHub epic issues (#37-#46) and their sub-issues. See the project board below for live status, and CHANGELOG.md for released versions.


🔗 Compatible Platforms

FYI CLI works with any Alaveteli-based platform. The embedded jurisdiction catalog currently includes:

Platform

Region

URL

foi-repository

New Zealand

foi-repository

RightToKnow

Australia

https://www.righttoknow.org.au

WhatDoTheyKnow

United Kingdom

https://www.whatdotheyknow.com

MyRightToKnow

Ireland

https://www.myrighttoknow.org

Ma Da Da (CADA)

France

https://www.madada.fr

Tu Derecho a Saber

Spain

https://www.tuderechoasaber.es

FragDenStaat

Germany

https://fragdenstaat.de

Alaveteli

Any

Self-hosted instances

See .conductor/tracks/jurisdiction-* for the rollout plan covering additional instances and non-English localization.


📋 CLI Commands

Archive Discovery

The archive commands are read-only and do not require an API key.

# Import the official FYI authority list into the local SQLite database
fyi import-authorities

# Walk the public search feed for a date window and save discovered requests
fyi discover --date-from 2024-01-01 --date-to 2024-02-01 \
  --checkpoint data/_state/discovery-2024-01.json \
  --output data/_state/discovered-2024-01.jsonl

# Probe a numeric request ID range for gaps
fyi discover --backfill-ids --id-from 1 --id-to 5000 \
  --output data/_state/backfill-1-5000.jsonl

# Compare feed discovery against the ID backfill
fyi discover-reconcile \
  --feed data/_state/discovered-2024-01.jsonl \
  --backfill data/_state/backfill-1-5000.jsonl \
  --output data/_state/discovery-reconciliation.json

Read-only authority discovery

discover-bodies keeps --base-url as the instance/capture URL. Use the separate --catalog-url option only when the authority CSV is hosted at an explicit alternate URL:

fyi discover-bodies --base-url https://www.righttoknow.org.au \
  --catalog-url https://catalog.example/au-authorities.csv \
  --rate-limit-name archive-discovery-au-rtk --format jsonl --output bodies.jsonl

With --format jsonl, each output line contains only the stable downstream contract fields url_name, name, and tags[]. The default JSON format also includes retrieval provenance for audit records. Both modes are read-only, robots-aware, and use the configured shared limiter.

The JSON output includes the effective catalog URL, whether the default or an override was used, retrieval time, HTTP status, row count, and a SHA-256 of the raw CSV payload. The override is read-only and still uses the catalog host's robots policy, contactable User-Agent, retry backoff, and shared rate limiter. Treat an override URL as trusted configuration: it can redirect discovery to a different authority set and should be reviewed and recorded alongside archive provenance.

Discovery uses a contactable User-Agent, checks robots.txt, and backs off on transient 429/5xx responses. Keep live runs polite: use small date windows, resume with checkpoints, and coordinate archive work with the ethics guidance in the sibling fyi-archive repo at docs/ethics-and-compliance.md.

The Rust fyi-core network path is the primary resource-aware implementation: it parses RateLimit-*/Retry-After, adapts pacing, enforces request/bytes/time guardrails, persists load memory, caches safe GETs, and can emit secret-redacted JSONL traces. Python remains a deliberately compatible discovery/capture path and follows the same identity and retry etiquette.

For concurrent workers, point discover and backfill at the same SQLite database with --db. That enables the shared cross-worker limiter, which reserves one aggregate request slot across processes and records both normal reservations and transient-failure backoff events. Inspect the current state with fyi rate-limit-status --db fyi_system.db.

CLI and MCP surfaces

The full command and server cross-reference is maintained in docs/cli-entrypoints-audit.md. It covers the Python CLI entrypoints (fyi, fyi-cli, fyi-system), the Rust CLI binary (fyi-cli), and the Rust MCP server (fyi-mcp) with its published registry pages.

Opt-in live smoke test:

FYI_LIVE_SMOKE=1 pytest -m smoke tests/test_discovery_smoke.py

The AU RightToKnow smoke is bounded to one discovery page and at most five request captures. It writes only to temporary test directories and remains disabled unless FYI_LIVE_SMOKE=1 is explicitly set.

In the current live verification, RightToKnow returned HTTP 403 for the bounded JSON search request, so the smoke records an explicit external availability skip and does not attempt capture. This does not change default offline CI behavior or retry the denied request aggressively.

Faithful Archive Capture

fyi capture stores the public request JSON, rendered HTML, and attachments as WARC records, deduplicates attachment bytes by SHA-256, and maintains a derived request view for downstream dataset tooling.

fyi capture 12345 \
  --data-dir data \
  --dist-dir dist \
  --max-bytes 500000000 \
  --max-runtime-minutes 30

Capture layout:

data/
  warc/<runid>-<request>.warc.gz
  attachments/<sha-prefix>/<sha256>
  raw/requests/<authority>/<request_id>/
    request.json
    page.html
    attachments.json
    snapshot_meta.json
dist/
  site_snapshots/<YYYYMMDD>.wacz

Each daily WACZ is appendable: subsequent captures add another WARC segment under archive/ and merge the resource metadata in datapackage.json. Replay tooling that supports WACZ/WARC can open the package from dist/site_snapshots/; for low-level inspection, unzip it and read the WARC segments with warcio.

# Database
fyi init-db                    # Initialize database
fyi config show                # Show configuration

# Requests
fyi register-request ...       # Create new request
fyi list-requests              # List all requests
fyi request-detail <id>        # View request details
fyi set-status <id> <status>   # Update status

# Submission
fyi build-prefilled-url <id>   # Generate submission URL

# Monitoring
fyi ingest-feed <url>          # Ingest RSS/Atom feed
fyi scheduler <url>            # Run continuous monitoring
fyi discover                   # Discover public FYI requests
fyi discover-reconcile         # Compare discovery JSONL outputs

# Reports
fyi dashboard --output ...     # Generate dashboard
fyi attention-report           # Generate attention report
fyi handover --output ...      # Generate handover document

# Export
fyi export-requests            # Export all requests
fyi export-bundle <id>         # Export request bundle

# Security
fyi privacy-audit              # Privacy compliance check
fyi health-check               # System health verification

Full CLI reference: See fyi --help or USER_GUIDE.md


🏗️ Architecture

┌───────────────────────────────────────────────────────────────┐
│                         fyi-cli workspace                      │
├───────────────────┬───────────────────────┬───────────────────┤
│   fyi-cli (bin)   │   fyi-mcp (MCP server) │  legacy fyi_system │
│  CLI commands,     │  JSON-RPC over stdio,   │  (Python, reference │
│  TUI dashboard      │  tools for AI assistants│  implementation)   │
├───────────────────┴───────────────────────┴───────────────────┤
│                          fyi-core (lib)                         │
│   Alaveteli API client · Tor client · encryption/keyring ·       │
│   sync engine · jurisdiction/instance registry (in progress)     │
├─────────────────────────────────────────────────────────────────┤
│                        SQLite database                          │
│      (requests, correspondence, authorities, sync_metadata)     │
├─────────────────────────────────────────────────────────────────┤
│      Alaveteli instances: foi-repository · WhatDoTheyKnow ·      │
│      FragDenStaat · righttoknow.org.au · any self-hosted deploy  │
└─────────────────────────────────────────────────────────────────┘

📜 License

This project is licensed under the MIT License - see the LICENSE file for details.


🙏 Acknowledgments

  • Built on the Alaveteli platform by mySociety

  • Inspired by the transparency work of foi-repository

  • Uses cryptography for encryption


📞 Support


Made with ❤️ for transparency and privacy

Available Tools

15 tools
check_statusCheck StatusA
Read-onlyIdempotent

Check FYI MCP SQLite readiness and return record-count metrics for requests, correspondence, and optional sync totals. Use as a first health probe or liveness check; prefer sync_monitor for queue/offline depth and list_requests for request content. Read-only, idempotent, and safe to call repeatedly; does not write data or contact remote services.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesOverall service health, reported as healthy when database queries succeed.
metricsYesRecord-count metrics for core FYI tables.
databaseYesDatabase connection state used by the MCP server.

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint. Description adds that it is safe to call repeatedly and does not write data or contact remote services, which supplements but does not contradict. No contradictions.

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?

Two sentences: the first states purpose and output, the second provides usage guidelines and behavioral traits. Every sentence adds value, no redundancy.

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 zero input parameters and the existence of an output schema, the description fully informs about the return value (record-count metrics) and the tool's role. No gaps remain.

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 describes zero parameters with 100% coverage, so baseline is 4. Description does not need to add parameter details but mentions 'optional sync totals' which relates to output, not input. No missing information.

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 clearly states the tool checks SQLite readiness and returns record-count metrics for specific entities (requests, correspondence, optional sync totals). It distinguishes from siblings by naming alternatives like sync_monitor and list_requests.

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 advises use as a first health probe or liveness check, and provides clear alternatives: prefer sync_monitor for queue/offline depth and list_requests for request content. No usage ambiguity.

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

compute_deadlineCompute DeadlineA
Read-onlyIdempotent

Compute a statutory FOI/OIA deadline from a start date and day count using the bleeding-edge fyi-core deadline engine. Use for local working-day or calendar-day deadline math; do not use for listing requests (list_requests) or sync health (sync_monitor). Read-only and idempotent; pure calculation with no database or network access. Returns a StatutoryDeadline JSON object (start_date, due_date, statutory_deadline_days, working_day_rule).

ParametersJSON Schema
NameRequiredDescriptionDefault
daysYesNumber of statutory days to count after start_date (working days by default).
calendarNoWhen true, count calendar days including weekends; when false/omitted, count weekdays only (Mon–Fri).
start_dateYesInclusive statutory period start date in YYYY-MM-DD (typically submission/receipt day).

Output Schema

ParametersJSON Schema
NameRequiredDescription
due_dateYesComputed due date (YYYY-MM-DD).
start_dateYesStart date echoed from input (YYYY-MM-DD).
instance_idNo
working_day_ruleYesRule applied: weekdays_only or calendar_days.
statutory_deadline_daysYesDay count used in the calculation.

TDQS

A4.7/5.0
Behavior5/5

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

Disclosures go beyond annotations: 'Read-only and idempotent; pure calculation with no database or network access' and mentions return type. 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?

Three sentences: purpose, usage, behavior/return. No redundant information, well-structured.

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?

Complete for a simple tool with output schema: covers purpose, usage, behavior, and return type adequately.

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% so description adds little param detail beyond implicit mention of start date and day count, but adequate given high coverage.

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 clearly states the tool computes statutory FOI/OIA deadlines from start date and day count, and explicitly differentiates from siblings list_requests and sync_monitor.

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 (local working-day or calendar-day deadline math) and when not to use, listing sibling tools as alternatives.

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

create_requestCreate RequestA

Create a new local FYI/Alaveteli request row (draft or tracked) in SQLite. Use only when starting a new request; use update_request to change an existing ID and delete_request to remove one. Mutating and not idempotent: each call allocates a new ID. Does not submit to a remote authority, send email, or require network access; title and body are required.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoOptional absolute FYI/Alaveteli URL when the request already exists online; omit for pure local drafts.
bodyYesFull request body or draft text to store locally (required, non-empty).
tagsNoOptional local classification tags for filtering/reporting; replace-not-merge semantics only apply on update_request.
titleYesShort public-facing request title (required, non-empty).
statusNoOptional initial local lifecycle status. Prefer draft until the request is ready; does not trigger remote submission.
user_nameNoOptional requester display name for local tracking only.

Output Schema

ParametersJSON Schema
NameRequiredDescription
requestYesThe newly created local request record.

TDQS

A4.7/5.0
Behavior5/5

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

Beyond annotations (readOnlyHint=false, idempotentHint=false), description adds 'Mutating and not idempotent: each call allocates a new ID. Does not submit to a remote authority, send email, or require network access.' 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?

Two well-structured sentences. First sentence states purpose and scope; second gives usage constraints and behavioral notes. No wasted words.

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?

Covers core behavior, exclusions, side effects, and sibling references. Output schema exists so return values need not be described. Complete for a tool with 6 params and 2 required.

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%, so baseline is 3. Description only mentions that title and body are required, which is already in schema. No additional parameter guidance beyond 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?

Description explicitly states 'Create a new local FYI/Alaveteli request row (draft or tracked) in SQLite', with verb, resource, and scope. Also names siblings update_request and delete_request to distinguish.

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?

Clearly says 'Use only when starting a new request; use update_request to change an existing ID and delete_request to remove one.' Provides explicit when-to-use, when-not-to-use, and alternatives.

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

delete_requestDelete RequestA
Destructive

Permanently delete a local request and all of its stored correspondence from SQLite. Use only after the agent confirms the ID should be discarded; prefer update_request for status/text edits and list_requests/retrieve_request for inspection. Destructive and irreversible in this database; does not delete anything on remote FYI/Alaveteli sites.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesStable local request ID to delete permanently.

Output Schema

ParametersJSON Schema
NameRequiredDescription
deletedYesTrue when the local delete operation completed.
request_idYesRequest ID that was targeted for deletion.

TDQS

A4.5/5.0
Behavior4/5

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

Reinforces annotations' destructiveHint: true and adds scope limitation: 'does not delete anything on remote FYI/Alaveteli sites.' Provides context beyond annotations, though could mention error handling or side effects.

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 concise sentences, no redundancy. Important information front-loaded. Every sentence contributes value.

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?

Covers purpose, scope, usage guidelines, and alternatives. Simple one-parameter delete tool—description is thorough enough for correct tool selection and invocation.

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?

Single parameter with 100% schema coverage. Description does not add extra meaning beyond schema's 'Stable local request ID to delete permanently.' 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?

Clearly states 'Permanently delete a local request and all of its stored correspondence from SQLite' with specific verb and resource. Distinguishes from sibling tools by naming update_request for edits and list_requests/retrieve_request for inspection.

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 instructs to use only after confirming ID should be discarded, and provides clear alternatives (update_request for edits, list/retrieve for inspection). Notes destructive and irreversible nature.

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

endorsed_route_statusEndorsed Route StatusB
Read-onlyIdempotent

Evaluate an operator-published endorsed-client capability document locally. Read-only, fail-closed, and never enables a route or contacts a remote service.

ParametersJSON Schema
NameRequiredDescriptionDefault
scopesYes
client_idYes
now_epochYes
bulk_exportNo
capabilitiesYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
quotasNo
reasonNo
scopesNo
statusYes
bulk_exportNo
instance_idNo

TDQS

B3.4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false. The description adds 'fail-closed' and 'never enables a route or contacts a remote service', which are valuable behavioral specifics beyond the 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?

Two sentences, front-loaded with the main action, no filler. Every word adds value. Ideal conciseness.

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

Completeness3/5

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

While the description covers the tool's core behavior and safety profile, it fails to explain what parameters mean despite low schema coverage. The output schema exists, reducing burden for return values, but parameter semantics are missing.

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

Parameters1/5

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

Schema description coverage is 0%, meaning the schema only provides type info. The description does not explain the meaning or usage of any of the 5 parameters (scopes, client_id, now_epoch, bulk_export, capabilities). This is a critical gap for an agent to correctly invoke the tool.

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

Purpose4/5

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

The description clearly states the tool evaluates an operator-published endorsed-client capability document locally. It specifies it's read-only and fail-closed, giving a precise action. However, it does not explicitly differentiate from siblings like check_status, which could be similar in spirit.

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

Usage Guidelines3/5

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

The description implies usage for local evaluation and says it never enables a route or contacts remote services. This provides implicit guidance (don't use if you need to enable routes or contact remotes), but lacks explicit when-to-use or when-not-to-use statements or alternative tool suggestions.

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

import_authoritiesImport AuthoritiesA
Idempotent

Upsert local public authority reference records by slug for request routing and discovery. Use after list_authorities when seeding or refreshing the catalog; do not use for FOI request CRUD (create_request/update_request). Mutating but non-destructive and idempotent: same slug re-import updates name/url without creating duplicates; does not contact remote authority directories.

ParametersJSON Schema
NameRequiredDescriptionDefault
authoritiesYesAuthority records to upsert; slug is the primary key, name is required, url is optional.

Output Schema

ParametersJSON Schema
NameRequiredDescription
importedYesNumber of authority records accepted for import or update.

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already indicate idempotentHint=true and destructiveHint=false. The description adds context beyond annotations: explains the upsert mechanics ('same slug re-import updates name/url without creating duplicates') and states 'does not contact remote authority directories', which is not captured in 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?

Three sentences: first states purpose, second gives usage guideline, third explains behavioral traits. No filler; every sentence adds distinct value. The description is front-loaded with the core action.

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 has one parameter (array) fully described in schema, annotations present, and output schema exists (handles return value documentation). The description covers the upsert semantics, idempotency, and relation to sibling tools, making it fully informative for correct usage.

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%, so baseline is 3. The description adds value by explaining that slug is the import key (primary key for upsert) and that the operation is idempotent and non-destructive, which clarifies the behavior of the 'authorities' parameter beyond its schema definition.

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 clearly states 'Upsert local public authority reference records by slug for request routing and discovery', specifying the verb (upsert) and resource (authority records by slug). It also distinguishes from siblings by explicitly saying 'do not use for FOI request CRUD (create_request/update_request)' and recommends usage 'after list_authorities'.

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 ('after list_authorities when seeding or refreshing the catalog') and when not to use ('do not use for FOI request CRUD'). Also names alternative tools (list_authorities, create_request, update_request), offering clear guidance.

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

list_authoritiesList AuthoritiesA
Read-onlyIdempotent

List imported public authority records (government/public bodies) used to route or classify FOI/OIA requests. Use to browse existing slugs/names before drafting; use import_authorities to add or upsert records, and list_requests for request data. Read-only and idempotent; returns the full local authority table (no pagination).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
authoritiesYesImported public authority records.

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, destructiveHint. The description adds that the tool is read-only, idempotent, and returns the full local authority table without pagination, providing behavioral context beyond 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?

Two sentences: the first states purpose and return value, the second gives usage guidelines. No superfluous words.

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 covers purpose, usage, return behavior (full table, no pagination), and distinguishes from siblings. With an output schema present, no further details on return format are needed.

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?

There are zero parameters, and schema coverage is 100%. The description adds no param-specific info because none are needed; baseline for 0 params is 4.

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 clearly states the tool lists imported public authority records for FOI/OIA routing, using the verb 'List' and specifying the resource. It distinguishes itself from sibling tools like import_authorities and list_requests.

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 ('browse existing slugs/names before drafting') and when not to, naming alternative tools (import_authorities for adding/upserting, list_requests for request data).

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

list_requestsList RequestsA
Read-onlyIdempotent

List locally tracked FYI/Alaveteli official information requests, ordered newest first. Use for dashboards, triage, or finding an ID before retrieve_request; do not use when you already know the ID and need correspondence (use retrieve_request) or only need health metrics (use check_status). Read-only and idempotent; does not contact remote authorities.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of request records to return (1-500). Defaults to 100 when omitted; raise only when the agent needs a broader scan.

Output Schema

ParametersJSON Schema
NameRequiredDescription
requestsYesRequests ordered by most recently updated.

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, ensuring the agent knows it's safe and non-mutating. The description adds that it 'does not contact remote authorities', providing extra behavioral clarity beyond the 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?

Two compact sentences deliver full purpose, usage guidelines, and safety info. Front-loaded with the primary action and ordering. Every clause earns its place; no redundancy.

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 simplicity (1 parameter, no required fields, output schema exists), the description covers all necessary aspects: what it does, when to use it, parameter behavior, and safety guarantees. No gaps remain for an AI agent to handle this tool 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 covers the single parameter 'limit' with 100% description coverage. The description adds context: 'raise only when the agent needs a broader scan', which helps the agent decide when to increase the default. This adds value beyond the schema's own description.

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 clearly states 'List locally tracked FYI/Alaveteli official information requests, ordered newest first'. It specifies the data source and ordering, and distinguishes from siblings by mentioning not to use for known ID (retrieve_request) or health metrics (check_status).

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 provides use cases ('dashboards, triage, or finding an ID before retrieve_request') and exclusions ('do not use when you already know the ID... or only need health metrics'), naming specific alternative tools. This leaves no ambiguity for an AI agent.

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

retrieve_requestRetrieve RequestA
Read-onlyIdempotent

Retrieve one locally tracked FYI/Alaveteli request and its stored correspondence by request ID. Use after list_requests when you need full text/history for a single request; do not use for bulk listing (list_requests) or database health (check_status). Read-only and idempotent; fails if the ID is missing; never contacts remote sites.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesStable local request ID to load (must already exist; typically from list_requests).

Output Schema

ParametersJSON Schema
NameRequiredDescription
requestYesThe requested FYI/Alaveteli request record.
correspondenceYesStored correspondence items linked to the request, in database order.

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already provide readOnlyHint, idempotentHint, and destructiveHint. Description adds 'fails if the ID is missing' and 'never contacts remote sites', which are useful beyond annotations. However, the core behavioral traits (read-only, idempotent) are redundant with annotations, preventing a 5.

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 concise sentences, front-loaded with the core purpose, no wasted words. Every sentence adds distinct value: purpose, usage guidance, and behavioral transparency.

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 simple retrieval tool with one parameter and an existing output schema, the description covers all necessary aspects: what it does, when to use, failure behavior, and safety profile. No 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 description coverage is 100%, and the parameter description in the schema is already clear ('Stable local request ID to load...'). The tool description does not add new parameter-level information beyond reinforcing the ID usage context. Baseline 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?

Description clearly states the verb 'Retrieve' and resource 'one locally tracked FYI/Alaveteli request and its stored correspondence by request ID'. It explicitly distinguishes from sibling tools like list_requests and check_status, meeting the high standard for purpose clarity.

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 ('after list_requests when you need full text/history for a single request'), when not to use ('do not use for bulk listing or database health'), and names alternatives (list_requests, check_status). This is exemplary guidance.

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

search_corpusSearch CorpusA
Read-onlyIdempotent

Search a built-in sample FOI document corpus with the bleeding-edge in-memory inverted index (demo). Use for experimental full-text search over sample titles/bodies; prefer list_requests/retrieve_request for real local SQLite requests. Read-only and idempotent; does not query the database or network. Returns ranked hits with id, score, and title.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of ranked hits to return (1-50). Defaults to 10.
queryYesFree-text search query tokenized into alphanumeric terms.

Output Schema

ParametersJSON Schema
NameRequiredDescription
hitsYesRanked search hits (id, score, title).
queryYesEcho of the search query.
document_countYesNumber of documents in the demo corpus.

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare read-only, idempotent, and non-destructive. The description adds significant context beyond annotations: it specifies the tool does not query the database or network, and it describes the return format (ranked hits with id, score, title). This enhances transparency.

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 sentences, front-loaded with purpose, no filler. Every sentence adds value: purpose, usage guidance, and behavioral details. Highly efficient.

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 simple search tool with an output schema, the description covers all necessary context: experimental nature, read-only, idempotent, no DB/network, return fields. With annotations providing safety guarantees, this is complete.

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%, so the schema already documents both parameters. The description adds minimal parameter meaning beyond the schema. It mentions the query is tokenized into alphanumeric terms, which is already in the schema. Baseline 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 clearly states the tool searches a built-in sample FOI document corpus using an experimental in-memory index. It distinguishes itself from related tools like list_requests/retrieve_request by specifying it's for full-text search over sample data, not real database queries.

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 explicitly provides guidance: 'Use for experimental full-text search over sample titles/bodies; prefer list_requests/retrieve_request for real local SQLite requests.' This tells the agent when to use this tool and when to use alternatives.

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

sync_conflictsSync ConflictsA
Read-onlyIdempotent

List locally tracked requests whose offline sync metadata is marked conflict. Use after sync_monitor shows conflict>0 to obtain IDs for review; use sync_resolve_conflict to clear a conflict, list_requests for all requests regardless of sync state. Read-only and idempotent; does not resolve conflicts or start network sync.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of conflicted request records to return (1-500). Defaults to 100 when omitted.

Output Schema

ParametersJSON Schema
NameRequiredDescription
conflictsYesRequests with sync_status set to conflict.

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false. The description adds that it does not resolve conflicts or start network sync, confirming and supplementing annotations. It also clarifies it deals with locally tracked requests, adding context beyond 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 three sentences: purpose, usage context with alternatives, and behavioral notes. No redundant or unnecessary words; every sentence earns its place.

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 simple single-parameter input, full annotations, and presence of an output schema, the description sufficiently explains the tool's role in a workflow (after sync_monitor, before sync_resolve_conflict). It mentions the data source (locally tracked) and explicitly states what it does and does not do.

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?

The single parameter 'limit' has full schema coverage (100%) with detailed description. The tool description does not add additional parameter information beyond what's in the schema, so baseline 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 clearly states the tool lists locally tracked requests with offline sync metadata marked as conflict. It uses specific verbs and resources, and distinguishes from sibling tools like list_requests and sync_resolve_conflict.

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 guidance: use after sync_monitor shows conflict>0 to obtain IDs, and offers alternatives (sync_resolve_conflict to clear, list_requests for all requests). This gives clear when-to-use and when-not-to-use context.

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

sync_monitorSync MonitorA
Read-onlyIdempotent

Summarize offline synchronization health: clean/dirty/conflict request counts, outgoing queue depth, latest sync time, and offline degradation indicators. Use for an operations overview; prefer sync_status for one request, sync_conflicts to list conflicted rows, and check_status for database connectivity/record totals. Read-only and idempotent; does not start a sync job.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
syncYesAggregate request sync counts and latest sync timestamp.
queueYesOutgoing offline queue counts by pending, submitted, and failed status.
offline_degradationYesOperational indicators showing queued local changes and dirty records.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already provide readOnlyHint, idempotentHint, destructiveHint=false. Description adds 'does not start a sync job' and reinforces read-only, idempotent nature, providing context beyond annotations without 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?

Two sentences, front-loaded with key information (purpose, output list), followed by usage guidance. Every sentence is essential and concise.

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 zero parameters, a rich output schema, and 13 siblings, the description covers purpose, usage, behavioral traits, and sibling differentiation completely. No gaps remain.

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?

No parameters exist, so the description correctly omits parameter details. The schema covers 100% with no properties. The description adds value by listing the output fields, which is sufficient.

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 clearly states the tool summarizes offline synchronization health with specific metrics (clean/dirty/conflict counts, queue depth, latest sync time, degradation indicators). It distinguishes from siblings sync_status, sync_conflicts, and check_status.

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 ('operations overview') and when not to, recommending alternatives for different tasks (sync_status for one request, sync_conflicts for conflicts, check_status for connectivity/totals).

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

sync_resolve_conflictResolve Sync ConflictA
Idempotent

Resolve a local offline-sync conflict by updating only the request's sync metadata: mark_clean=true after the agent has reconciled local vs remote (status becomes clean); mark_clean=false keeps the row dirty for a later push. Prerequisite: the request should already appear in sync_conflicts. Side effects are local SQLite metadata only—no automatic merge of body text, no remote API calls, and no deletion of the request. Prefer sync_conflicts to list candidates and sync_status to inspect timestamps; do not use for ordinary field edits (update_request). Mutating, non-destructive, and idempotent for the same mark_clean value.

ParametersJSON Schema
NameRequiredDescriptionDefault
mark_cleanNotrue: mark reconciled/clean after manual review; false (default): leave dirty so a later offline push is expected. Does not rewrite title/body.
request_idYesLocal request ID currently in conflict (from sync_conflicts).

Output Schema

ParametersJSON Schema
NameRequiredDescription
resolvedYesTrue when the conflict metadata was written successfully.
request_idYesRequest ID whose conflict state was updated.
sync_statusYesResulting sync status string (typically clean or dirty).

TDQS

A4.9/5.0
Behavior5/5

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

Beyond annotations (idempotentHint=true, destructiveHint=false), the description discloses that only local SQLite metadata is affected, no automatic merge, no remote API calls, no deletion, and idempotency for the same mark_clean value. This adds significant behavioral context.

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 concise, well-structured, and front-loaded with the core action. Every sentence provides necessary information without redundancy.

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 complexity of sync conflict resolution, the description covers prerequisites, side effects, and differentiators. Output schema exists, so return values are handled. Complete and actionable.

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 descriptions, but the description adds behavioral context for mark_clean (e.g., effect on status and later push). This adds value beyond the schema 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 clearly states the tool resolves a local offline-sync conflict by updating sync metadata (mark_clean). It uses specific verbs and resources, and distinguishes from sibling tools like update_request, sync_conflicts, and sync_status.

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 prerequisites (request must appear in sync_conflicts), when to use (for conflict resolution), and when not to use (ordinary field edits). It also guides the agent to prefer sync_conflicts for listing and sync_status for timestamps.

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

sync_statusSync StatusA
Read-onlyIdempotent

Read offline-sync metadata either as aggregate counts (omit request_id) or for one request (provide request_id). Use when you need clean/dirty/pending/conflict numbers or per-request last_synced timestamps; use sync_monitor for queue depth + offline degradation, sync_conflicts for conflicted rows only, and check_status for database health. Read-only and idempotent; does not mutate state or trigger network sync.

ParametersJSON Schema
NameRequiredDescriptionDefault
request_idNoOptional local request ID. Omit for aggregate counts; set to load that request's sync_status, last_synced_at, and conflict_version.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A5/5.0
Behavior5/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint. Description adds 'does not mutate state or trigger network sync', providing extra behavioral context beyond 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?

Three concise sentences, no wasted words. Purpose is front-loaded, and every sentence adds value.

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?

With annotations and output schema, description fully covers the tool's behavior, usage modes, safety profile, and ties to sibling tools. Nothing missing.

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?

Only one parameter (request_id) with 100% schema coverage. Description adds critical semantics: omit for aggregate counts, provide for per-request details including specific fields (sync_status, last_synced_at, conflict_version).

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 specifies verb 'Read', resource 'offline-sync metadata', and two modes (aggregate or per-request). It clearly distinguishes from sibling tools like sync_monitor, sync_conflicts, and check_status.

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 ('Use when you need clean/dirty/pending/conflict numbers or per-request last_synced timestamps') and provides specific alternatives for related tasks, leaving no ambiguity.

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

update_requestUpdate RequestA
Idempotent

Replace editable fields on an existing local FYI/Alaveteli request by ID and mark the record dirty for offline sync. Use when the request already exists and fields changed; use create_request for a new ID and delete_request to remove. Requires id, title, and body (full replacement for those fields, not a sparse patch). Mutating but non-destructive; safe to re-run with the same values; does not call remote APIs.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesExisting local request ID to update (must already exist).
urlNoOptional replacement absolute FYI/Alaveteli URL.
bodyYesReplacement request body or draft text (required; full replace).
tagsNoOptional full replacement tag list (not appended to existing tags).
titleYesReplacement request title (required; full replace, not merge).
statusNoOptional replacement local lifecycle status; changing status does not submit or withdraw a remote request.
user_nameNoOptional replacement requester display name; when omitted, existing local value is preserved.

Output Schema

ParametersJSON Schema
NameRequiredDescription
requestYesThe updated local request record.

TDQS

A4.8/5.0
Behavior4/5

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

Annotations already provide idempotentHint=true and destructiveHint=false. The description adds context: 'mark the record dirty for offline sync', 'mutating but non-destructive', and 'does not call remote APIs', which enriches understanding beyond 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.

Conciseness5/5

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

The description is a single dense paragraph with efficient front-loading: first sentence states action, then usage guidelines, parameter semantics, and behavioral notes. Every sentence adds value without redundancy.

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 7 parameters, 3 required, and an output schema, the description covers purpose, usage, parameter behaviors, and side effects (dirty marking, no remote calls). It is complete for an AI agent to use 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?

Despite 100% schema coverage, the description adds crucial semantics: 'full replacement for those fields, not a sparse patch' for title/body, 'not appended to existing tags' for tags, and 'changing status does not submit or withdraw a remote request' for status. This goes well 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 specifies 'Replace editable fields on an existing local FYI/Alaveteli request by ID and mark the record dirty for offline sync', which clearly states the verb, resource, and scope. It also distinguishes from siblings by mentioning create_request for new ID and delete_request for removal.

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: 'Use when the request already exists and fields changed', and provides alternatives: 'use create_request for a new ID and delete_request to remove'. Also notes it is safe to re-run with same values.

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. Dates show when Glama detected each change.

  1. 15 tool updatesv0.1.1
    • Changedcheck_status6 fields changed
      • addedOutput schema / properties / database / description
        Added value: +"Database connection state used by the MCP server."
      • addedOutput schema / properties / metrics / additionalProperties
        Added value: +false
      • addedOutput schema / properties / metrics / description
        Added value: +"Record-count metrics for core FYI tables."
      • addedOutput schema / properties / metrics / properties
        Added value: +{
        +  "sync": {
        +    "additionalProperties": false,
        +    "description": "Aggregate sync counts when sync metadata can be read.",
        +    "properties": {
        +      "clean": {
        +        "description": "Number of clean synchronized requests.",
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "conflict": {
        +        "description": "Number of requests in sync conflict.",
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "dirty": {
        +        "description": "Number of requests with unsynced local changes.",
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "pending": {
        +        "description": "Number of requests pending sync.",
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "total": {
        +        "description": "Total number of requests represented in sync metadata.",
        +        "minimum": 0,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "total",
        +      "clean",
        +      "dirty",
        +      "pending",
        +      "conflict"
        +    ],
        +    "type": [
        +      "object",
        +      "null"
        +    ]
        +  },
        +  "total_correspondence": {
        +    "description": "Number of correspondence records in the database.",
        +    "minimum": 0,
        +    "type": "integer"
        +  },
        +  "total_requests": {
        +    "description": "Number of request records in the database.",
        +    "minimum": 0,
        +    "type": "integer"
        +  }
        +}
      • addedOutput schema / properties / metrics / required
        Added value: +[
        +  "total_requests",
        +  "total_correspondence",
        +  "sync"
        +]
      • addedOutput schema / properties / status / description
        Added value: +"Overall service health, reported as healthy when database queries succeed."
    • Addedcompute_deadline
    • Changedcreate_request14 fields changed
      • changedInput schema / properties / body / description
        Previous value: -"The request body."New value: +"Full request body or draft text to store locally (required, non-empty)."
      • addedInput schema / properties / body / minLength
        Added value: +1
      • changedInput schema / properties / status / description
        Previous value: -"Status of the request."New value: +"Optional initial local lifecycle status. Prefer draft until the request is ready; does not trigger remote submission."
      • addedInput schema / properties / status / enum
        Added value: +[
        +  "draft",
        +  "submitted",
        +  "waiting_response",
        +  "successful",
        +  "partially_successful",
        +  "refused",
        +  "overdue",
        +  "clean",
        +  "dirty",
        +  "pending",
        +  "conflict"
        +]
      • changedInput schema / properties / tags / description
        Previous value: -"Optional list of tags."New value: +"Optional local classification tags for filtering/reporting; replace-not-merge semantics only apply on update_request."
      • changedInput schema / properties / title / description
        Previous value: -"The request title."New value: +"Short public-facing request title (required, non-empty)."
      • addedInput schema / properties / title / minLength
        Added value: +1
      • changedInput schema / properties / url / description
        Previous value: -"The URL on Alaveteli or FYI."New value: +"Optional absolute FYI/Alaveteli URL when the request already exists online; omit for pure local drafts."
      • addedInput schema / properties / url / format
        Added value: +"uri"
      • changedInput schema / properties / user_name / description
        Previous value: -"Name of the user."New value: +"Optional requester display name for local tracking only."
      • addedOutput schema / properties / request / additionalProperties
        Added value: +false
      • addedOutput schema / properties / request / description
        Added value: +"The newly created local request record."
      • addedOutput schema / properties / request / properties
        Added value: +{
        +  "body": {
        +    "description": "Request body or draft correspondence text.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "created_at": {
        +    "description": "ISO-8601 creation timestamp when recorded.",
        +    "format": "date-time",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "id": {
        +    "description": "Stable local request identifier.",
        +    "minimum": 1,
        +    "type": "integer"
        +  },
        +  "status": {
        +    "description": "Current Alaveteli/FYI request lifecycle status.",
        +    "enum": [
        +      "draft",
        +      "submitted",
        +      "waiting_response",
        +      "successful",
        +      "partially_successful",
        +      "refused",
        +      "overdue",
        +      "clean",
        +      "dirty",
        +      "pending",
        +      "conflict",
        +      null
        +    ],
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "tags": {
        +    "description": "Optional local tags attached to the request.",
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": [
        +      "array",
        +      "null"
        +    ]
        +  },
        +  "title": {
        +    "description": "Public title of the official information request.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "updated_at": {
        +    "description": "ISO-8601 update timestamp used for ordering and sync.",
        +    "format": "date-time",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "url": {
        +    "description": "Canonical public request URL when available.",
        +    "format": "uri",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "user_name": {
        +    "description": "Requester display name when known.",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  }
        +}
      • addedOutput schema / properties / request / required
        Added value: +[
        +  "id",
        +  "title",
        +  "body"
        +]
    • Changeddelete_request4 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"The request ID."New value: +"Stable local request ID to delete permanently."
      • addedInput schema / properties / id / minimum
        Added value: +1
      • addedOutput schema / properties / deleted / description
        Added value: +"True when the local delete operation completed."
      • addedOutput schema / properties / request_id / description
        Added value: +"Request ID that was targeted for deletion."
    • Addedendorsed_route_status
    • Changedimport_authorities10 fields changed
      • changedInput schema / properties / authorities / description
        Previous value: -"Authority records to import."New value: +"Authority records to upsert; slug is the primary key, name is required, url is optional."
      • addedInput schema / properties / authorities / items / description
        Added value: +"Public authority record used to route or classify requests."
      • changedInput schema / properties / authorities / items / properties / name / description
        Previous value: -"Authority name."New value: +"Human-readable public authority name."
      • addedInput schema / properties / authorities / items / properties / name / minLength
        Added value: +1
      • changedInput schema / properties / authorities / items / properties / slug / description
        Previous value: -"Authority slug."New value: +"Stable authority slug used as an import key."
      • addedInput schema / properties / authorities / items / properties / slug / minLength
        Added value: +1
      • changedInput schema / properties / authorities / items / properties / url / description
        Previous value: -"Optional authority URL."New value: +"Optional public authority URL."
      • addedInput schema / properties / authorities / items / properties / url / format
        Added value: +"uri"
      • changedInput schema / properties / authorities / items / properties / url / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / imported / description
        Added value: +"Number of authority records accepted for import or update."
    • Changedlist_authorities5 fields changed
      • addedOutput schema / properties / authorities / description
        Added value: +"Imported public authority records."
      • addedOutput schema / properties / authorities / items / additionalProperties
        Added value: +false
      • addedOutput schema / properties / authorities / items / description
        Added value: +"Public authority record used to route or classify requests."
      • addedOutput schema / properties / authorities / items / properties
        Added value: +{
        +  "name": {
        +    "description": "Human-readable public authority name.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "slug": {
        +    "description": "Stable authority slug used as an import key.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "url": {
        +    "description": "Optional public authority URL.",
        +    "format": "uri",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  }
        +}
      • addedOutput schema / properties / authorities / items / required
        Added value: +[
        +  "slug",
        +  "name"
        +]
    • Changedlist_requests8 fields changed
      • addedInput schema / properties / limit / default
        Added value: +100
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of requests to return."New value: +"Maximum number of request records to return (1-500). Defaults to 100 when omitted; raise only when the agent needs a broader scan."
      • addedInput schema / properties / limit / maximum
        Added value: +500
      • addedInput schema / properties / limit / minimum
        Added value: +1
      • addedOutput schema / properties / requests / items / additionalProperties
        Added value: +false
      • addedOutput schema / properties / requests / items / description
        Added value: +"One tracked FYI/Alaveteli request."
      • addedOutput schema / properties / requests / items / properties
        Added value: +{
        +  "body": {
        +    "description": "Request body or draft correspondence text.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "created_at": {
        +    "description": "ISO-8601 creation timestamp when recorded.",
        +    "format": "date-time",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "id": {
        +    "description": "Stable local request identifier.",
        +    "minimum": 1,
        +    "type": "integer"
        +  },
        +  "status": {
        +    "description": "Current Alaveteli/FYI request lifecycle status.",
        +    "enum": [
        +      "draft",
        +      "submitted",
        +      "waiting_response",
        +      "successful",
        +      "partially_successful",
        +      "refused",
        +      "overdue",
        +      "clean",
        +      "dirty",
        +      "pending",
        +      "conflict",
        +      null
        +    ],
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "tags": {
        +    "description": "Optional local tags attached to the request.",
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": [
        +      "array",
        +      "null"
        +    ]
        +  },
        +  "title": {
        +    "description": "Public title of the official information request.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "updated_at": {
        +    "description": "ISO-8601 update timestamp used for ordering and sync.",
        +    "format": "date-time",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "url": {
        +    "description": "Canonical public request URL when available.",
        +    "format": "uri",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "user_name": {
        +    "description": "Requester display name when known.",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  }
        +}
      • addedOutput schema / properties / requests / items / required
        Added value: +[
        +  "id",
        +  "title",
        +  "body"
        +]
    • Changedretrieve_request11 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"The unique request ID."New value: +"Stable local request ID to load (must already exist; typically from list_requests)."
      • addedInput schema / properties / id / minimum
        Added value: +1
      • addedOutput schema / properties / correspondence / description
        Added value: +"Stored correspondence items linked to the request, in database order."
      • addedOutput schema / properties / correspondence / items / additionalProperties
        Added value: +false
      • addedOutput schema / properties / correspondence / items / description
        Added value: +"A correspondence item associated with an FYI request."
      • addedOutput schema / properties / correspondence / items / properties
        Added value: +{
        +  "attachments": {
        +    "description": "Optional attachment URLs or identifiers linked to the correspondence.",
        +    "items": {
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "type": [
        +      "array",
        +      "null"
        +    ]
        +  },
        +  "body": {
        +    "description": "Message body or extracted correspondence text.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "direction": {
        +    "description": "Whether the correspondence was sent by the requester or received as an authority response.",
        +    "enum": [
        +      "request",
        +      "response"
        +    ],
        +    "type": "string"
        +  },
        +  "sent_at": {
        +    "description": "ISO-8601 sent timestamp when captured.",
        +    "format": "date-time",
        +    "type": "string"
        +  },
        +  "state": {
        +    "description": "Optional Alaveteli correspondence state when captured.",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  }
        +}
      • addedOutput schema / properties / correspondence / items / required
        Added value: +[
        +  "direction",
        +  "body",
        +  "sent_at"
        +]
      • addedOutput schema / properties / request / additionalProperties
        Added value: +false
      • addedOutput schema / properties / request / description
        Added value: +"The requested FYI/Alaveteli request record."
      • addedOutput schema / properties / request / properties
        Added value: +{
        +  "body": {
        +    "description": "Request body or draft correspondence text.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "created_at": {
        +    "description": "ISO-8601 creation timestamp when recorded.",
        +    "format": "date-time",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "id": {
        +    "description": "Stable local request identifier.",
        +    "minimum": 1,
        +    "type": "integer"
        +  },
        +  "status": {
        +    "description": "Current Alaveteli/FYI request lifecycle status.",
        +    "enum": [
        +      "draft",
        +      "submitted",
        +      "waiting_response",
        +      "successful",
        +      "partially_successful",
        +      "refused",
        +      "overdue",
        +      "clean",
        +      "dirty",
        +      "pending",
        +      "conflict",
        +      null
        +    ],
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "tags": {
        +    "description": "Optional local tags attached to the request.",
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": [
        +      "array",
        +      "null"
        +    ]
        +  },
        +  "title": {
        +    "description": "Public title of the official information request.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "updated_at": {
        +    "description": "ISO-8601 update timestamp used for ordering and sync.",
        +    "format": "date-time",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "url": {
        +    "description": "Canonical public request URL when available.",
        +    "format": "uri",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "user_name": {
        +    "description": "Requester display name when known.",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  }
        +}
      • addedOutput schema / properties / request / required
        Added value: +[
        +  "id",
        +  "title",
        +  "body"
        +]
    • Addedsearch_corpus
    • Changedsync_conflicts9 fields changed
      • addedInput schema / properties / limit / default
        Added value: +100
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of conflicts to return."New value: +"Maximum number of conflicted request records to return (1-500). Defaults to 100 when omitted."
      • addedInput schema / properties / limit / maximum
        Added value: +500
      • addedInput schema / properties / limit / minimum
        Added value: +1
      • addedOutput schema / properties / conflicts / description
        Added value: +"Requests with sync_status set to conflict."
      • addedOutput schema / properties / conflicts / items / additionalProperties
        Added value: +false
      • addedOutput schema / properties / conflicts / items / description
        Added value: +"A request currently marked as a sync conflict."
      • addedOutput schema / properties / conflicts / items / properties
        Added value: +{
        +  "body": {
        +    "description": "Request body or draft correspondence text.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "created_at": {
        +    "description": "ISO-8601 creation timestamp when recorded.",
        +    "format": "date-time",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "id": {
        +    "description": "Stable local request identifier.",
        +    "minimum": 1,
        +    "type": "integer"
        +  },
        +  "status": {
        +    "description": "Current Alaveteli/FYI request lifecycle status.",
        +    "enum": [
        +      "draft",
        +      "submitted",
        +      "waiting_response",
        +      "successful",
        +      "partially_successful",
        +      "refused",
        +      "overdue",
        +      "clean",
        +      "dirty",
        +      "pending",
        +      "conflict",
        +      null
        +    ],
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "tags": {
        +    "description": "Optional local tags attached to the request.",
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": [
        +      "array",
        +      "null"
        +    ]
        +  },
        +  "title": {
        +    "description": "Public title of the official information request.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "updated_at": {
        +    "description": "ISO-8601 update timestamp used for ordering and sync.",
        +    "format": "date-time",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "url": {
        +    "description": "Canonical public request URL when available.",
        +    "format": "uri",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "user_name": {
        +    "description": "Requester display name when known.",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  }
        +}
      • addedOutput schema / properties / conflicts / items / required
        Added value: +[
        +  "id",
        +  "title",
        +  "body"
        +]
    • Changedsync_monitor12 fields changed
      • addedOutput schema / properties / offline_degradation / additionalProperties
        Added value: +false
      • addedOutput schema / properties / offline_degradation / description
        Added value: +"Operational indicators showing queued local changes and dirty records."
      • addedOutput schema / properties / offline_degradation / properties
        Added value: +{
        +  "dirty_records": {
        +    "description": "Requests with unsynced local changes.",
        +    "minimum": 0,
        +    "type": "integer"
        +  },
        +  "queued_changes": {
        +    "description": "Pending plus failed outgoing queue entries.",
        +    "minimum": 0,
        +    "type": "integer"
        +  }
        +}
      • addedOutput schema / properties / offline_degradation / required
        Added value: +[
        +  "queued_changes",
        +  "dirty_records"
        +]
      • addedOutput schema / properties / queue / additionalProperties
        Added value: +false
      • addedOutput schema / properties / queue / description
        Added value: +"Outgoing offline queue counts by pending, submitted, and failed status."
      • addedOutput schema / properties / queue / properties
        Added value: +{
        +  "failed": {
        +    "description": "Outgoing queue entries that failed submission.",
        +    "minimum": 0,
        +    "type": "integer"
        +  },
        +  "pending": {
        +    "description": "Outgoing queue entries waiting to be submitted.",
        +    "minimum": 0,
        +    "type": "integer"
        +  },
        +  "submitted": {
        +    "description": "Outgoing queue entries already submitted.",
        +    "minimum": 0,
        +    "type": "integer"
        +  }
        +}
      • addedOutput schema / properties / queue / required
        Added value: +[
        +  "pending",
        +  "submitted",
        +  "failed"
        +]
      • addedOutput schema / properties / sync / additionalProperties
        Added value: +false
      • addedOutput schema / properties / sync / description
        Added value: +"Aggregate request sync counts and latest sync timestamp."
      • addedOutput schema / properties / sync / properties
        Added value: +{
        +  "clean": {
        +    "description": "Requests known to be cleanly synchronized.",
        +    "minimum": 0,
        +    "type": "integer"
        +  },
        +  "conflict": {
        +    "description": "Requests with unresolved sync conflicts.",
        +    "minimum": 0,
        +    "type": "integer"
        +  },
        +  "dirty": {
        +    "description": "Requests with unsynced local changes.",
        +    "minimum": 0,
        +    "type": "integer"
        +  },
        +  "latest_sync": {
        +    "description": "Most recent successful synchronization timestamp.",
        +    "format": "date-time",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "pending": {
        +    "description": "Requests pending synchronization.",
        +    "minimum": 0,
        +    "type": "integer"
        +  },
        +  "total": {
        +    "description": "Total number of requests tracked by sync metadata.",
        +    "minimum": 0,
        +    "type": "integer"
        +  }
        +}
      • addedOutput schema / properties / sync / required
        Added value: +[
        +  "total",
        +  "clean",
        +  "dirty",
        +  "pending",
        +  "conflict",
        +  "latest_sync"
        +]
    • Changedsync_resolve_conflict7 fields changed
      • addedInput schema / properties / mark_clean / default
        Added value: +false
      • changedInput schema / properties / mark_clean / description
        Previous value: -"Set true to mark the conflict clean; false keeps it dirty."New value: +"true: mark reconciled/clean after manual review; false (default): leave dirty so a later offline push is expected. Does not rewrite title/body."
      • changedInput schema / properties / request_id / description
        Previous value: -"The request ID to resolve."New value: +"Local request ID currently in conflict (from sync_conflicts)."
      • addedInput schema / properties / request_id / minimum
        Added value: +1
      • addedOutput schema / properties / request_id / description
        Added value: +"Request ID whose conflict state was updated."
      • addedOutput schema / properties / resolved / description
        Added value: +"True when the conflict metadata was written successfully."
      • addedOutput schema / properties / sync_status / description
        Added value: +"Resulting sync status string (typically clean or dirty)."
    • Changedsync_status7 fields changed
      • changedInput schema / properties / request_id / description
        Previous value: -"Optional request ID for per-request sync metadata."New value: +"Optional local request ID. Omit for aggregate counts; set to load that request's sync_status, last_synced_at, and conflict_version."
      • addedInput schema / properties / request_id / minimum
        Added value: +1
      • changedOutput schema / additionalProperties
        Previous value: -trueNew value: +false
      • changedOutput schema / description
        Previous value: -"Synchronization metadata."New value: +"Synchronization metadata. Aggregate counts are returned when request_id is omitted; per-request metadata is returned when request_id is provided."
      • addedOutput schema / oneOf
        Added value: +[
        +  {
        +    "additionalProperties": false,
        +    "description": "Aggregate offline synchronization counts.",
        +    "properties": {
        +      "clean": {
        +        "description": "Number of requests with clean sync metadata.",
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "conflict": {
        +        "description": "Number of requests currently in conflict.",
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "dirty": {
        +        "description": "Number of requests with unsynced local changes.",
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "pending": {
        +        "description": "Number of requests queued or pending sync.",
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "total": {
        +        "description": "Total number of requests represented in aggregate sync status.",
        +        "minimum": 0,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "total",
        +      "clean",
        +      "dirty",
        +      "pending",
        +      "conflict"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Per-request offline synchronization metadata.",
        +    "properties": {
        +      "conflict_version": {
        +        "description": "Conflict version counter when a sync conflict has been detected.",
        +        "minimum": 0,
        +        "type": [
        +          "integer",
        +          "null"
        +        ]
        +      },
        +      "last_synced_at": {
        +        "description": "Last successful sync timestamp for this request.",
        +        "format": "date-time",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "local_updated_at": {
        +        "description": "Last local update timestamp known for this request.",
        +        "format": "date-time",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "remote_updated_at": {
        +        "description": "Last remote update timestamp known for this request.",
        +        "format": "date-time",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "request_id": {
        +        "description": "Request ID for the per-request sync lookup.",
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "sync_status": {
        +        "description": "Per-request sync status, or null when that request has no sync metadata.",
        +        "enum": [
        +          "clean",
        +          "dirty",
        +          "pending",
        +          "conflict",
        +          null
        +        ],
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "request_id",
        +      "sync_status"
        +    ],
        +    "type": "object"
        +  }
        +]
      • removedOutput schema / properties
        Removed value: -{
        -  "request_id": {
        -    "type": "integer"
        -  },
        -  "sync_status": {
        -    "type": [
        -      "string",
        -      "null"
        -    ]
        -  }
        -}
      • removedOutput schema / required
        Removed value: -[
        -  "request_id",
        -  "sync_status"
        -]
    • Changedupdate_request16 fields changed
      • changedInput schema / properties / body / description
        Previous value: -"The request body."New value: +"Replacement request body or draft text (required; full replace)."
      • addedInput schema / properties / body / minLength
        Added value: +1
      • changedInput schema / properties / id / description
        Previous value: -"The request ID."New value: +"Existing local request ID to update (must already exist)."
      • addedInput schema / properties / id / minimum
        Added value: +1
      • changedInput schema / properties / status / description
        Previous value: -"Status of the request."New value: +"Optional replacement local lifecycle status; changing status does not submit or withdraw a remote request."
      • addedInput schema / properties / status / enum
        Added value: +[
        +  "draft",
        +  "submitted",
        +  "waiting_response",
        +  "successful",
        +  "partially_successful",
        +  "refused",
        +  "overdue",
        +  "clean",
        +  "dirty",
        +  "pending",
        +  "conflict"
        +]
      • changedInput schema / properties / tags / description
        Previous value: -"Optional list of tags."New value: +"Optional full replacement tag list (not appended to existing tags)."
      • changedInput schema / properties / title / description
        Previous value: -"The request title."New value: +"Replacement request title (required; full replace, not merge)."
      • addedInput schema / properties / title / minLength
        Added value: +1
      • changedInput schema / properties / url / description
        Previous value: -"The URL on Alaveteli or FYI."New value: +"Optional replacement absolute FYI/Alaveteli URL."
      • addedInput schema / properties / url / format
        Added value: +"uri"
      • changedInput schema / properties / user_name / description
        Previous value: -"Name of the user."New value: +"Optional replacement requester display name; when omitted, existing local value is preserved."
      • addedOutput schema / properties / request / additionalProperties
        Added value: +false
      • addedOutput schema / properties / request / description
        Added value: +"The updated local request record."
      • addedOutput schema / properties / request / properties
        Added value: +{
        +  "body": {
        +    "description": "Request body or draft correspondence text.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "created_at": {
        +    "description": "ISO-8601 creation timestamp when recorded.",
        +    "format": "date-time",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "id": {
        +    "description": "Stable local request identifier.",
        +    "minimum": 1,
        +    "type": "integer"
        +  },
        +  "status": {
        +    "description": "Current Alaveteli/FYI request lifecycle status.",
        +    "enum": [
        +      "draft",
        +      "submitted",
        +      "waiting_response",
        +      "successful",
        +      "partially_successful",
        +      "refused",
        +      "overdue",
        +      "clean",
        +      "dirty",
        +      "pending",
        +      "conflict",
        +      null
        +    ],
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "tags": {
        +    "description": "Optional local tags attached to the request.",
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": [
        +      "array",
        +      "null"
        +    ]
        +  },
        +  "title": {
        +    "description": "Public title of the official information request.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "updated_at": {
        +    "description": "ISO-8601 update timestamp used for ordering and sync.",
        +    "format": "date-time",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "url": {
        +    "description": "Canonical public request URL when available.",
        +    "format": "uri",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "user_name": {
        +    "description": "Requester display name when known.",
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  }
        +}
      • addedOutput schema / properties / request / required
        Added value: +[
        +  "id",
        +  "title",
        +  "body"
        +]
  2. 12 tool updatesv0.1.0
    • First observedcheck_status
    • First observedcreate_request
    • First observeddelete_request
    • First observedimport_authorities
    • First observedlist_authorities
    • First observedlist_requests
    • First observedretrieve_request
    • First observedsync_conflicts
    • First observedsync_monitor
    • First observedsync_resolve_conflict
    • First observedsync_status
    • First observedupdate_request

TDQS

A4.2/5.0
Disambiguation5/5

Each tool targets a distinct action and resource. Even similar-sounding tools like list_requests and retrieve_request are clearly differentiated by purpose (listing vs. full detail). Sync-related tools (sync_monitor, sync_status, sync_conflicts, sync_resolve_conflict) have distinct roles.

Naming Consistency4/5

Most tools follow a clear verb_noun pattern with lowercase and underscores (e.g., create_request, list_authorities). The only outlier is 'endorsed_route_status', which uses a past participle instead of a verb, but it remains readable and consistent in style.

Tool Count5/5

With 15 tools, the server covers request CRUD, authority management, sync operations, and utilities without being overloaded. Each tool serves a clear purpose within the domain.

Completeness4/5

The surface covers core request lifecycle (create, read, update, delete, list) and sync management. Minor gaps exist: no tool for adding or editing correspondence individually, and no submission capability, but these are plausible scope decisions.

Maintenance

ActivityMaintained
ResponsivenessResponsive

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Model Context Protocol (MCP) server for Belgian Electronic Invoicing (Peppol BIS 3.0 / PINT-BE / Mercurius). Provides tools to validate, generate, and transform UBL 2.1 e-invoices, and look up BCE/KBO enterprise data and Peppol participants.
    50
    Apache 2.0
  • A
    license
    Not graded
    quality
    F
    maintenance
    An MCP server that provides safe, read-only access to Boston's open data portal, enabling natural language exploration of civic datasets.
    2
    GPL 3.0
  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides tools for DeepTempo AI SOC including findings and case management, investigation workflow orchestration, action approval workflows, and MITRE ATT&CK layer generation.
    2
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/edithatogo/fyi-cli'

If you have feedback or need assistance with the MCP directory API, please join our Discord server