Skip to main content
Glama

jb_gateway_mcp

A local MCP server that acts as a credential-holding gateway to Google APIs (Gmail, Calendar, Drive) and, via Enable Banking, read-only bank account data (DNB, Nordea, Revolut, ...). AI agents call MCP tools; the server holds every credential and decides — via a deny-by-default policy — what each caller is allowed to do. Agents never see a token, password, API key, or raw account number.

Full design/architecture: DESIGN.md.

This repo ships one project skill directly, in .claude/skills/:

  • run-jb-gateway-mcp — launches the server and drives a real MCP session against it end-to-end (handshake, tool discovery, ping, policy-gated tool calls, audit log integrity check). Ask e.g. "run jb_gateway_mcp" or "smoke-test the gateway." This one stays here since it's a server-maintainer concern, not something plugin users need.

The account-connection and finance-report skills — plus domain subagents — are distributed separately as Claude Code plugins, so they can be installed standalone without cloning this repo: jb_claude_pluggins (jb-finance-mcp-plugin: bank onboarding + finance reports; jb-google-notify-plugin: Google onboarding + report notifications via Gmail). Both depend on this server being installed standalone first — see "Standalone install" below — and walk through app/consent registration, running the onboarding CLI, and adding the right policy.yaml grants, verifying the result against live data before calling it done.

The rest of this README is the manual reference for each step: useful if you're not driving this through Claude Code, or want to understand exactly what the skills automate.

Related MCP server: gg-mcp

Standalone install (for plugin users, or any MCP client)

If you just want the server itself on PATH — e.g. to use the plugins above, or to point a non-Claude-Code MCP client at it without cloning this repo — install it as a tool instead of uv sync-ing a clone.

Quick path: run the installer script — it installs uv if missing (which in turn manages Python itself, so you don't need Python or uv pre-installed at all), installs the server, bootstraps a default (deny-everything) policy file, and registers with Claude Code if the claude CLI is present:

curl -LsSf https://raw.githubusercontent.com/jitheshb83/jb_gateway_mcp/main/scripts/install.sh | sh

Using Claude Code, or a similar AI coding assistant, already? You don't even need to open a terminal yourself — just ask it to run that command for you (e.g. "install jb_gateway_mcp by running curl -LsSf https://raw.githubusercontent.com/jitheshb83/jb_gateway_mcp/main/scripts/install.sh | sh"). It'll drive the terminal, handle the missing-uv case, and report back — no prior setup assumed on your end beyond having that assistant installed.

It only handles the server + client wiring — connecting a Google account or a bank is still a separate, deliberate step (§2-4, §7 below); nothing works until you do that.

Manual path, if you'd rather see/control each step:

uv tool install --python 3.13 git+https://github.com/jitheshb83/jb_gateway_mcp.git

This puts jb-gateway-mcp, onboard-google, onboard-bank, and uninstall-google on your PATH. Also create a policy file — the server won't start without one, even to serve ping:

mkdir -p ~/.jb_gateway_mcp
echo 'callers: {}' > ~/.jb_gateway_mcp/policy.yaml

That's a valid, safe, deny-everything starting point (see §4 below for the shape once you're ready to add grants) — ~/.jb_gateway_mcp/policy.yaml is the default JB_GATEWAY_POLICY_FILE path a standalone install resolves to automatically, unlike the dev-clone path below where it's the repo's own tracked policy.yaml.

The rest of this README (steps 1–7) still applies for OAuth client setup, onboarding, and policy.yaml grants — those are one-time, per-account steps independent of how the server itself got installed — with one difference: steps 3 and 7b below show uv run onboard-google ... / uv run onboard-bank ... run from inside a cloned repo (the uv sync dev path). With a standalone install, drop both the cd and the uv run prefix — just onboard-google ... / onboard-bank ... directly, since they're already on PATH. If you're developing on this repo itself, uv sync + uv run (as in "Install" below) is the right mode instead.

Already onboarded accounts via a dev-clone install? You don't need to re-run onboarding for the standalone path — tokens/sessions live in the OS keychain (keyring), not tied to which install method wrote them. Only policy.yaml is per-install (each has its own default location), so the one thing a switch between install modes always needs is its own grants.

Prerequisites

  • Python 3.13 (managed automatically by uv)

  • uv

  • For Google tools: a Google account you're willing to grant read-only (or send/write) API access to, and a Google Cloud project to create OAuth credentials in

  • For bank tools: a free Enable Banking account and the bank(s) you want to connect (DNB, Nordea, Revolut, ... currently — see §7)

1. Install

cd jb_gateway_mcp
uv sync

2. Create a Google OAuth client (one-time, in Google Cloud Console)

The gateway needs its own OAuth client to run the consent flow. You do this once, in your own Google account — nothing here can do it for you:

  1. Go to Google Cloud Console and create (or pick) a project.

  2. APIs & Services → Library — enable the Gmail API, Google Calendar API, and Google Drive API.

  3. APIs & Services → OAuth consent screen — configure it (External is fine for personal use; add your own account as a test user if the app stays in "Testing" mode).

  4. APIs & Services → Credentials → Create Credentials → OAuth client ID — Application type: Desktop app. Download the resulting JSON — this is your client_secret.json.

  5. Keep this file out of the repo. Store it somewhere outside the project (e.g. ~/.secrets/jb_gateway_mcp/client_secret.json). The .gitignore here already blocks client_secret*.json as a backstop, but don't rely on that — don't put it in the repo directory at all.

3. Onboard a Google account

This is a one-time, human-run step per Google account. It opens a browser for you to log in and grant consent; the resulting token is written to your OS keychain — it never touches disk in plaintext and is never visible to any agent.

uv run onboard-google \
  --account you@example.com \
  --client-secrets ~/.secrets/jb_gateway_mcp/client_secret.json

By default this requests read-only scopes (Gmail, Calendar, Drive). To also allow sending mail or creating events, pass --scopes explicitly:

uv run onboard-google \
  --account you@example.com \
  --client-secrets ~/.secrets/jb_gateway_mcp/client_secret.json \
  --scopes \
    https://www.googleapis.com/auth/gmail.readonly \
    https://www.googleapis.com/auth/gmail.send \
    https://www.googleapis.com/auth/calendar \
    https://www.googleapis.com/auth/drive.readonly

On success it prints the account and granted scopes — never a token value. Re-run this any time a refresh token is revoked (the server will raise a clear re-consent error if that happens mid-use).

4. Grant policy access

The server ships with policy.yaml denying everything by default — no caller can use any tool until you explicitly grant it. Edit policy.yaml:

callers:
  local:
    allow:
      - tool: gmail.list_messages
        scope: gmail.readonly
      - tool: gmail.read_message
        scope: gmail.readonly
      - tool: calendar.list_events
        scope: calendar.readonly
      - tool: drive.list_files
        scope: drive.readonly
      - tool: drive.read_file
        scope: drive.readonly
      # Only add these if you actually want an agent to be able to send
      # mail / create events on your behalf:
      # - tool: gmail.send_message
      #   scope: gmail.send
      # - tool: calendar.create_event
      #   scope: calendar.events

local is the default caller identity for v1 (single-user, local stdio deployment — see DESIGN.md §7). Override it with the JB_GATEWAY_CALLER_ID environment variable if you want distinct policies per launching client (see §6 below).

5. Run it standalone (quick manual test)

The server is started via scripts/start.sh — a thin wrapper that resolves the project root, checks uv and policy.yaml are present, and execs into uv run jb-gateway-mcp (so a launching client's process management/signals reach the real server directly, no wrapper process left in between). This is the same command every client config below points at.

./scripts/start.sh

This blocks, speaking MCP over stdio — it's meant to be launched by a client, not run interactively. To sanity-check it without a full client, run the automated test suite instead:

uv run pytest -q      # 115 tests: unit + a real stdio round-trip test
uv run ruff check .
uv run mypy .

The stdio round-trip test in tests/test_server.py spawns the real server process and calls ping over a real MCP session — the same mechanism any client uses.

For a fuller live check (handshake, all 13 tools discovered, ping, policy enforcement on the Google tools, and an audit-log integrity check), run the project skill's smoke test:

uv run python .claude/skills/run-jb-gateway-mcp/scripts/smoke_test.py

6. Connect a real client

Every client config below launches scripts/start.sh with JB_GATEWAY_CALLER_ID=local — the same caller id already granted read-only Gmail/Calendar/Drive access in policy.yaml and verified working end-to-end. This repo is a single-user, local deployment (see DESIGN.md §7), so every client sharing one caller id is intentional, not a shortcut — they all run as you, on your machine. If you later want per-client policies (e.g. a stricter grant set for one client), give it its own JB_GATEWAY_CALLER_ID and add a matching entry under callers: in policy.yaml — until you do, any caller id with no entry there is denied everything by default.

Claude Desktop

Copy config/claude_desktop_config.example.json into your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS), replacing the placeholder path with this repo's absolute path, then restart Claude Desktop.

Claude Code

A ready-to-use .mcp.json already exists at this repo's root (project-scoped — Claude Code picks it up automatically when you open this folder). If you'd rather register it globally instead, claude mcp add is the CLI route — run claude mcp --help to confirm the exact current flags for your installed version.

Any other MCP client (Cursor, Windsurf, Cline, etc.)

Most MCP clients use the same mcpServers JSON shape. See config/mcp_client_generic.example.json and that client's own docs for where its config file lives.

7. Connect a bank account (DNB, Nordea, Revolut, ...)

Independent of the Google setup above and §6 — do this before, after, or without ever doing them; it's a separate provider with its own app registration and onboarding CLI. bank.* tools are backed by Enable Banking, a licensed AISP aggregator (direct bank PSD2 APIs require being a regulated TPP with an eIDAS certificate — not viable for a personal project).

7a. Register an Enable Banking application (one-time, in their Control Panel)

  1. Sign in at enablebanking.com/sign-in/ (email + magic link — no business registration needed).

  2. Control Panel → API applicationsAdd a new application.

    • Name: anything identifiable.

    • Redirect URL: exactly https://localhost:8080/callback — Enable Banking requires https://, with no plain-http localhost exception (unlike Google).

    • Privacy/Terms URL: required fields, but not validated while the app stays in Restricted mode (own-accounts-only, which is what this project uses) — any placeholder URL works.

    • Let the browser generate the private key rather than supplying your own — it downloads once as <application-id>.pem and never leaves your machine.

  3. Keep the .pem out of the repo — e.g. ~/.secrets/jb_gateway_mcp/enablebanking/<application-id>.pem, same convention as client_secret.json.

  4. Activate the application. A freshly registered app starts "Inactive" and returns 403 Forbidden on every API call until you click "Activate by linking accounts" in the Control Panel and complete one bank login through their hosted UI. Do this once per institution you plan to connect (DNB, Nordea, Revolut, ...) — Restricted mode only ever serves accounts that have gone through this linking step.

7b. Onboard each institution

uv run onboard-bank --institution dnb \
  --application-id <uuid> \
  --private-key ~/.secrets/jb_gateway_mcp/enablebanking/<uuid>.pem

--application-id/--private-key are only needed the first time — every institution after that reuses the stored app credential:

uv run onboard-bank --institution nordea
uv run onboard-bank --institution revolut

This is interactive: it opens a bank login URL in your browser, and after you complete BankID/SCA login, the browser fails to load the final redirect page (https://localhost:8080/callback?...) — that's expected, nothing is listening there. Copy the full URL from the address bar and paste it back at the terminal prompt; the CLI extracts the authorization code from it. On success it prints e.g. dnb onboarded: 1 account(s) linked, consent valid until 2026-10-30 — never a secret value.

Consent is SCA-backed and valid for 90 days; re-run the same command for the same institution to refresh it — there's no separate "refresh" command, and no way to extend a session without a fresh login (PSD2 requires it).

Supported institution aliases (see src/jb_gateway_mcp/cli/onboard_bank.py): dnb, nordea, revolut — all currently Norway (NO). Adding a new one is a two-line code change.

7c. Grant policy access

callers:
  local:
    allow:
      - tool: bank.list_accounts
        scope: bank.readonly
      - tool: bank.get_balance
        scope: bank.readonly
      - tool: bank.summarize_spending
        scope: bank.readonly
      - tool: bank.list_transactions_summary
        scope: bank.readonly
      # Adds counterparty name + payment description to transaction results
      # (IBANs stay masked either way). Off by default:
      # - tool: bank.list_transactions_detailed
      #   scope: bank.transactions.detailed

Tiered by design: the default read-only tools never return counterparty names, payment descriptions, or raw IBANs (every IBAN — the account holder's own, and any counterparty's — is masked to its last 4 digits). bank.list_transactions_detailed is the only tool that adds counterparty/description text, and it needs its own explicit grant.

7d. Verify

The connect-bank-account skill's status-check script (in the jb_claude_pluggins jb-finance-mcp-plugin) reports connection status (or "not connected"/"EXPIRED") and a live balance check for every onboarded institution:

uv run python skills/connect-bank-account/scripts/check_bank_status.py --live

(run from a clone of that plugin's repo, at its own root directory — see its README for the one-time uv sync setup; the Claude Code plugin install itself doesn't give you a directory to cd into by hand).

Environment variables

Variable

Default

Purpose

JB_GATEWAY_CALLER_ID

local

Identity used for every policy check and audit entry in this process. Must match a callers: key in policy.yaml to be granted anything.

JB_GATEWAY_POLICY_FILE

~/.jb_gateway_mcp/policy.yaml

Path to the policy file. Must exist and be valid YAML — the server fails to start if it's missing, even just to serve ping, since policy loads at startup. This repo's own .mcp.json/example client configs set it explicitly to this repo's tracked policy.yaml; a standalone install (see above) needs you to create the default path yourself (mkdir -p ~/.jb_gateway_mcp && echo 'callers: {}' > ~/.jb_gateway_mcp/policy.yaml is a valid, safe, deny-everything starting point) or point this at wherever you keep your own.

JB_GATEWAY_AUDIT_LOG

~/.jb_gateway_mcp/audit.jsonl

Path to the audit log (JSON Lines, one entry per tool call, secrets redacted). Parent directory is created automatically.

Tool catalog

Tool

Scope

Notes

ping

— (ungated smoke-test tool)

Always available, not policy-gated

gmail.list_messages

gmail.readonly

account, query

gmail.read_message

gmail.readonly

account, message_id

gmail.send_message

gmail.send

account, to, subject, body — not granted by default

calendar.list_events

calendar.readonly

account, calendar_id, max_results

calendar.create_event

calendar.events

account, calendar_id, summary, start_iso, end_iso — not granted by default

drive.list_files

drive.readonly

account, query, page_size

drive.read_file

drive.readonly

account, file_id

bank.list_accounts

bank.readonly

institution — masked IBAN only; local keychain read, no live API call

bank.get_balance

bank.readonly

institution, account_uid — cached 60min (see "Bank tool result caching" below)

bank.summarize_spending

bank.readonly

institution, account_uid, date_from, date_to — aggregated totals only, no line items; cached 60min

bank.list_transactions_summary

bank.readonly

institution, account_uid, date_from, date_to — date/amount/currency only; cached 60min

bank.list_transactions_detailed

bank.transactions.detailed

adds counterparty name/description (IBANs still masked) — not granted by default; cached 60min

Bank tool result caching

Enable Banking enforces a daily, not short-term, per-consent access cap ("consented multiplicity without PSU involvement per day") — a 429 means that institution's whole day is spent, not "wait and retry." The four bank.* tools that actually reach the live API (everything above except bank.list_accounts, which is a local keychain read) cache their result in memory for 60 minutes, keyed by tool name + exact parameters. A repeat call with identical parameters within that window returns the cached result instead of making another live request — still fully audit-logged (outcome: "cached", same params, distinguishable from "success" in JB_GATEWAY_AUDIT_LOG), just without reaching the handler. The cache is in-process memory only — never written to disk, and cleared on every server restart. This is opt-in per tool (ToolSpec.cache_ttl_seconds in src/jb_gateway_mcp/adapters/base.py); write/send tools are never cached.

Network & ports

The gateway itself listens on nothing. It's a stdio MCP server — the client (Claude Desktop/Code, etc.) launches it as a subprocess and talks to it over the process's stdin/stdout pipes. There's no port, no host, no URL, no listening socket at any point during normal operation — it isn't reachable over the network at all, by design (see DESIGN.md).

The one exception is the one-time onboard-google step: it briefly starts a local HTTP server on localhost:8080 (via google_auth_oauthlib's InstalledAppFlow.run_local_server) purely to catch Google's OAuth redirect after you approve consent in the browser. It shuts down immediately once the redirect arrives — nothing is listening before or after that single command runs. If port 8080 is already in use on your machine, that command will fail; there's currently no flag to change the port, so free up 8080 or temporarily stop whatever else is using it before running onboard-google.

Troubleshooting

  • "no grant for caller X on tool Y" — expected deny-by-default behavior. Add the grant to policy.yaml under the caller id you're using.

  • Re-consent error mentioning a revoked/expired refresh token — re-run onboard-google for that account.

  • 403 Forbidden from onboard-bank — the Enable Banking application (or that specific institution) hasn't been through "Activate by linking accounts" in their Control Panel yet — see §7a step 4.

  • multiple ASPSPs matched institution=... from onboard-bank — the institution name is genuinely ambiguous in that country (e.g. "DNB" vs. "DNB Corporate Mastercard"); narrow _INSTITUTION_NAME_HINT in src/jb_gateway_mcp/cli/onboard_bank.py for that alias and retry.

  • NeedsReconsentError / "consent ... expired" from a bank tool call — the 90-day bank consent lapsed; re-run onboard-bank --institution <alias>.

  • Audit log — every call (success, cached, denied, or error) is recorded at JB_GATEWAY_AUDIT_LOG. Tokens/secrets are redacted before writing. cached means a bank.* tool returned a result from the in-memory cache instead of reaching the live API — see "Bank tool result caching" above.

Security notes

  • Never commit client_secret.json, any Enable Banking .pem private key, or any file matching *credentials*.json.gitignore blocks these as a backstop, but treat it as a backstop, not a guarantee.

  • Tokens and bank private keys live only in the OS keychain; they're never logged, never returned in a tool response, and never appear in an audit log entry — the audit log only ever records tool call parameters, never results.

  • gmail.send_message and calendar.create_event are the only write-capable Google tools; they are not granted in the default policy.yaml — add them deliberately, only for callers that actually need them.

  • Bank tools are architecturally read-only — the adapter's HTTP helper only ever issues GET requests; there is no code path capable of initiating a payment, even though Enable Banking's API separately supports one. Every IBAN (the account holder's own, and any transaction counterparty's) is masked to its last 4 digits before it leaves the adapter. bank.list_transactions_detailed is the only tool that surfaces counterparty names/payment descriptions, and it requires its own, off-by-default policy.yaml grant — the default tool set never sends that level of financial detail into an agent's context.

Uninstalling

Deleting the repo folder alone is not enough — stored tokens and the Google-side consent grant live outside it. Full teardown, in order:

  1. Remove it from every client you connected it to:

    • Claude Desktop — delete the jb-gateway-mcp entry from claude_desktop_config.json, then restart Claude Desktop.

    • Claude Code — remove/delete .mcp.json (project-scoped), or claude mcp remove jb-gateway-mcp if you registered it globally instead.

    • Any other client — remove its equivalent mcpServers entry.

  2. Run the uninstall command — revokes the account's grant on Google's side (RFC 7009 token revocation) and deletes its token from the OS keychain, in one step:

    uv run uninstall-google --account you@example.com

    Prompts for confirmation per account (add --yes to skip); repeatable with multiple --account flags to clean up more than one at once. If the network call to Google fails, it still deletes the local keychain entry and tells you to revoke access manually at myaccount.google.com/permissions--keep-remote-grant skips the network call entirely and only deletes locally (e.g. if you already revoked access on Google's side, or the grant was for a different app).

    Deleting the repo without running this leaves the token sitting in your keychain, and the grant active on Google's side, indefinitely.

  3. Delete local state you don't want lingering (all outside the repo, so rm -rf-ing the project directory won't touch these):

    • Audit log: JB_GATEWAY_AUDIT_LOG (default ~/.jb_gateway_mcp/)

    • Your client_secret.json copy, wherever you stored it outside the repo

  4. Remove the project itself:

    rm -rf /path/to/jb_gateway_mcp   # deletes .venv and all repo files together

Steps 1–4 are the parts people usually forget — the repo directory is the least sensitive thing to clean up here.

Uninstalling bank access

There's no uninstall-bank command yet (unlike uninstall-google) — bank access is currently removed in two manual steps instead of one:

  1. Revoke on Enable Banking's side — in their Control Panel, revoke the linked account or delete the application entirely. This is the step that actually matters for security; it's the equivalent of myaccount.google.com/permissions for banks.

  2. Delete the local keychain entrieskeyring stores these under the OS's native secret store (Keychain on macOS, Credential Manager on Windows, Secret Service on Linux), under service names jb_gateway_mcp:enablebanking_app (the app credential, one entry) and jb_gateway_mcp:enablebanking_session (one entry per institution alias you onboarded, e.g. dnb/nordea/revolut). Search for jb_gateway_mcp:enablebanking in your OS's credential manager UI (e.g. Keychain Access.app on macOS) and remove them, or delete a specific institution's private key file if you also want that gone (~/.secrets/jb_gateway_mcp/enablebanking/).

Available Tools

13 tools
bank.get_balanceB

Get current/available balances for a bank account.

ParametersJSON Schema
NameRequiredDescriptionDefault
account_uidYes
institutionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3/5.0
Behavior2/5

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

No annotations are provided, so the description carries full behavioral disclosure burden. It only states that it gets balances, but does not explicitly confirm read-only behavior, authentication requirements, or any nuances of 'current/available' (e.g., real-time or cached values). The description adds minimal transparency beyond the tool name.

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 concise sentence of nine words, directly stating the tool's purpose without filler. Structure is front-loaded and clear.

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?

The output schema exists, so return values are likely documented elsewhere. However, the description lacks key context such as how to obtain account_uid (via bank.list_accounts), whether both current and available balances are always returned, and any prerequisites. With no annotations, the description is only minimally complete for a simple getter tool.

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%, and the description does not mention the parameters (institution and account_uid) at all. It adds no meaning beyond the property names, leaving the agent without clarity on expected formats, required relationships, or how the parameters are used to identify the account.

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 uses the specific verb 'Get' and identifies the resource as 'current/available balances for a bank account,' which clearly distinguishes it from sibling tools like bank.list_accounts that list accounts rather than balances. The scope is explicit and unambiguous.

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

Usage Guidelines2/5

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

No guidance is given on when to use this tool versus alternatives. It does not mention that account_uid can be obtained from bank.list_accounts or clarify when get_balance is preferred over other bank tools. Usage context is entirely implied rather than stated.

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

bank.list_accountsB

List linked bank accounts for an institution (masked IBAN).

ParametersJSON Schema
NameRequiredDescriptionDefault
institutionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.4/5.0
Behavior3/5

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

With no annotations, the description carries full responsibility for behavioral disclosure. It does reveal that returned IBANs are masked, implying a privacy-aware read operation. However, it does not mention authentication, rate limits, pagination, or whether all accounts are returned at once. The 'List' verb implies read-only, but this is not explicit.

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, succinct sentence that front-loads the action 'List linked bank accounts' and appends a valuable clarifying detail about masked IBANs. No wasted words.

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?

Given the tool's simplicity (one parameter, output schema exists), the description covers the basic purpose but lacks usage guidance and parameter semantics. It is minimally adequate but leaves room for confusion about when and how to invoke it.

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

Parameters2/5

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

The only parameter, 'institution', has 0% schema description coverage. The description says 'for an institution' but does not define what an institution is, what format it should take, or provide examples. It essentially repeats the parameter name, adding minimal semantic value.

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 verb 'List', the resource 'linked bank accounts', and the scope 'for an institution' with the detail '(masked IBAN)'. This distinguishes it from sibling tools like get_balance or list_transactions, which have different purposes.

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

Usage Guidelines2/5

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

No guidance is provided on when to use this tool versus alternatives, and there are no prerequisites or exclusions mentioned. The phrase 'for an institution' hints at a required context but does not explain the intended use case or relationship to other bank tools.

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

bank.list_transactions_detailedC

List transactions including counterparty name/description (IBANs still masked).

ParametersJSON Schema
NameRequiredDescriptionDefault
date_toYes
date_fromYes
account_uidYes
institutionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.6/5.0
Behavior2/5

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

With no annotations, the description carries the full burden of disclosing behavioral traits. It notes that IBANs are masked, which is useful, but fails to mention that this is a read-only operation, any authentication requirements, or potential limitations such as pagination or data format.

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

Conciseness4/5

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

The description is a single, front-loaded sentence that immediately conveys the core function. It is concise with no filler, which is appropriate for the tool's simplicity, even though it sacrifices some explanatory detail.

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

Completeness2/5

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

The tool has four required parameters, no annotations, and no parameter documentation. The description is too sparse to provide adequate context for correct invocation, such as expected date formats, what 'details' means beyond counterparty, or how this differs from the summary tool. The presence of an output schema does not compensate for lack of usage context.

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?

The input schema has 0% description coverage, and the description provides no additional meaning for any of the four required parameters (date_from, date_to, account_uid, institution). The agent receives no help understanding formats, semantics, or relationships between parameters.

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 lists transactions and specifies the added detail (counterparty name/description). It distinguishes itself from the sibling 'list_transactions_summary' by implying a more detailed view, though it does not explicitly name the sibling or contrast the difference.

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

Usage Guidelines2/5

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

No guidance is provided about when to use this tool versus alternatives. The description does not mention the summary variant or other sibling tools, and offers no exclusions or context about appropriate use cases.

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

bank.list_transactions_summaryA

List transactions for a date range: date, amount, currency only.

ParametersJSON Schema
NameRequiredDescriptionDefault
date_toYes
date_fromYes
account_uidYes
institutionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior3/5

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

With no annotations provided, the description carries the burden of behavioral disclosure. It does disclose the limited field set, but it does not mention pagination, ordering, authentication requirements, or whether all transactions in the range are returned. For a simple read operation, this is minimally adequate but not rich in 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 a single, front-loaded sentence that wastes no words. It conveys the core purpose and the key limitation in a compact manner, making it easy to parse at a glance.

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

Completeness2/5

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

Given the tool has four required parameters with no descriptions, no annotations, and a sibling with overlapping scope, the description is too sparse. It fails to provide guidance on how the tool fits into a workflow, what distinguishes it from the detailed version, or any security/access considerations. The presence of an output schema mitigates the need to explain return values, but the description still leaves significant gaps.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate for explaining the parameters. It only implies 'date range' for date_from/date_to, leaving institution and account_uid entirely unexplained. This partial coverage is insufficient given all four parameters are required.

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 transactions for a date range and specifies the exact fields returned (date, amount, currency only). This directly distinguishes it from the sibling tool 'bank.list_transactions_detailed' through the word 'summary' and the explicit 'only' constraint.

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 phrase 'date, amount, currency only' implies a summary use case, which contrasts with the detailed sibling. However, it does not explicitly state when to use this tool versus bank.list_transactions_detailed, nor does it mention any prerequisites or exclusions, leaving the choice to inference.

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

bank.summarize_spendingA

Aggregate total in/out/net spending for a date range (no transaction detail).

ParametersJSON Schema
NameRequiredDescriptionDefault
date_toYes
date_fromYes
account_uidYes
institutionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It discloses the lack of transaction detail, which is a behavioral trait, but it does not mention whether the operation is read-only, permission requirements, or specifics like whether pending transactions are included. This is a moderate disclosure at best.

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 sentence, front-loaded with the core action and resource. Every word earns its place, and it efficiently communicates the tool's primary purpose and one key limitation.

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?

An output schema exists, so return values need not be described. The tool is relatively simple and the description covers the main function, but it lacks definitions of terms like 'net' and does not clarify date inclusivity or account context, leaving some gaps for an agent.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate for the missing parameter guidance. The description only hints at 'date range' (mapping to date_from/date_to) but fails to explain institution or account_uid. This leaves the agent to infer their meaning without additional context.

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 uses a specific verb 'aggregate' and clearly identifies the resource (spending) and scope (date range). It also states 'no transaction detail', which helps distinguish it from sibling tools like bank.list_transactions_summary and bank.list_transactions_detailed.

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

Usage Guidelines4/5

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

The description implies when to use this tool: when aggregate totals are needed. The phrase 'no transaction detail' provides a subtle exclusion, hinting that transaction-level tools should be used for details. However, it does not explicitly name alternatives or provide when-not-to-use guidance.

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

calendar.create_eventC

Create a new calendar event.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountYes
end_isoYes
summaryYes
start_isoYes
calendar_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.3/5.0
Behavior1/5

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

With no annotations, the description carries the full burden for behavioral disclosure, but it only says 'create', which is already obvious from the name. It does not mention side effects, authentication requirements, output behavior, or error conditions, making it effectively a tautology.

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

Conciseness4/5

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

The description is a single, front-loaded sentence with no wasted words. It is easy to parse and understand at a glance, though it sacrifices necessary detail for brevity.

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

Completeness1/5

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

Given the tool's complexity (5 required parameters, no parameter documentation, no annotations), this description is severely incomplete. It does not explain ISO date formats, how to identify an account or calendar, or what the tool returns, leaving the agent with almost no operational context.

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?

The schema has 5 required parameters with 0% description coverage, and the tool description adds no parameter-level information. The agent is left without any explanation of what 'account', 'calendar_id', 'summary', 'start_iso', or 'end_iso' mean or how they should be formatted.

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's action ('create') and resource ('a new calendar event'), which separates it from calendar.list_events and other read-only siblings. However, it adds no details beyond the tool name itself, so it is clear but not very descriptive.

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

Usage Guidelines2/5

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

No guidance is provided about when to use this tool versus alternatives. There is no mention that this is the write counterpart to calendar.list_events, nor any context about prerequisites or typical use cases.

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

calendar.list_eventsA

List upcoming events on a calendar.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountYes
calendar_idNoprimary
max_resultsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior3/5

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

No annotations are provided, so the description carries the burden of behavioral disclosure. It adds the 'upcoming' filter, which is not present in the schema, but it does not mention pagination, timezone handling, or whether recurring events are expanded. This is a modest addition beyond the schema.

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

Conciseness5/5

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

The description is a single sentence with no redundant phrases. It is front-loaded with the verb and resource, making it immediately clear what the tool does.

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

Completeness2/5

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

Given there are 3 parameters, no annotations, and a schema coverage of 0%, the description is too sparse to provide complete context. It omits essential details about the required 'account' parameter and the behavior of 'max_results', leaving the agent uncertain about how to use the tool correctly.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate. It does not explain the meaning of 'account', 'calendar_id', or 'max_results' beyond what parameter names suggest. The 'account' parameter is especially ambiguous, and max_results' default limit is not mentioned.

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 it lists upcoming events, using a specific verb ('list') and resource ('events on a calendar'). This distinguishes it from sibling tools like calendar.create_event and other domain tools (gmail, drive).

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 viewing future events but provides no explicit guidance on when to use it versus alternatives such as calendar.create_event. There are no exclusions or alternative tool mentions, so the usage context is only implicit.

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

drive.list_filesB

List Drive files matching a query.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNo
accountYes
page_sizeNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.1/5.0
Behavior2/5

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

With no annotations, the description carries full burden of behavioral disclosure. It only states 'List Drive files matching a query' and does not mention pagination, account requirements, query syntax, or whether it returns metadata or content. This is insufficient for a tool with a required account parameter.

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, front-loaded sentence with no fluff or repetition. It earns its place by conveying the core purpose efficiently.

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

Completeness2/5

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

Given three parameters, no annotations, and a required account field, the description is too sparse. Even with an output schema, it does not provide enough context about query syntax, pagination behavior, or what kind of file metadata is returned.

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

Parameters2/5

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

Schema coverage is 0%, and the description only implies the 'query' parameter via 'matching a query'. It fails to explain the required 'account' parameter or the 'page_size' parameter, leaving their semantics undocumented.

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 action ('List') and resource ('Drive files') with a qualifier ('matching a query'). It is specific and distinct from sibling tools like drive.read_file, which reads file content rather than listing files.

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

Usage Guidelines2/5

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

No guidance is provided on when to use this tool versus alternatives, nor when not to use it. It does not mention relationship to drive.read_file or other siblings, and no usage context is given.

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

drive.read_fileB

Read metadata and text content of a Drive file.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountYes
file_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.1/5.0
Behavior2/5

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

Annotations are absent, and the description only states 'read', which implies a non-destructive operation but does not mention auth requirements, rate limits, or limitations (e.g., binary files vs text). No additional behavioral context provided beyond the basic action.

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?

One sentence, front-loaded with verb 'read', no waste. It efficiently conveys the core purpose without irrelevant details.

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

Completeness2/5

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

For a simple read tool, the description provides core purpose, but lacks details about supported file types, output structure, or relationship to sibling tools. Output schema exists but is not referenced. Given no annotations and minimal schema, more context is needed for reliable invocation.

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

Parameters2/5

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

Schema has two required parameters (account, file_id) with no descriptions. Description does not explain what account refers to or how to obtain file_id. With 0% schema description coverage, the description fails to compensate for the lack of parameter details.

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

Purpose5/5

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

Description states 'Read metadata and text content of a Drive file.' This clearly identifies the tool's purpose as reading a specific Drive file, distinguishing it from sibling drive.list_files which lists files. Verb 'read' is specific and the resource is explicit.

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

Usage Guidelines2/5

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

No mention of when to use this tool versus alternatives. Does not indicate that drive.list_files should be used to obtain file_id, or that this is for reading content after listing. No explicit guidance on usage context or prerequisites.

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

gmail.list_messagesC

List Gmail messages for an account, optionally filtered by query.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNo
accountYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.4/5.0
Behavior1/5

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

With no annotations, the description carries the full burden of behavioral disclosure. It does not mention whether the operation is read-only, whether it returns message metadata or full bodies, or any effects like marking messages as read. The description is minimal and lacks any safety or side-effect information.

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

Conciseness4/5

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

The description is a single, efficient sentence that gets to the point quickly. However, it is under-specified, but conciseness itself is fine.

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

Completeness2/5

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

The tool has an output schema, so return values are covered, but the description lacks usage context, alternatives, parameter details, and behavioral caveats. Given the sibling tools include read_message and send_message, more guidance is needed to understand when listing is appropriate.

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?

The schema has zero descriptive coverage for parameters, and the description only hints that 'query' filters results. It does not explain the Gmail search query syntax, the format of the 'account' parameter, or their defaults and constraints.

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 lists Gmail messages for an account, with optional query filtering. The verb 'list' differentiates it from sibling tools like read_message and send_message, though it does not explicitly distinguish its role. The scope is clear.

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

Usage Guidelines2/5

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

No guidance is provided on when to use this tool versus gmail.read_message or calendar/drive tools. It only mentions optional query filtering, without any context such as 'use this to search messages' or exclusions.

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

gmail.read_messageA

Read a single Gmail message's subject/from/snippet/body.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountYes
message_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden. It does not disclose whether reading affects read status, auth requirements, or other side effects. It only states what is returned, which is minimal.

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 one concise sentence, front-loaded with the action and outcome. It conveys the necessary information without wasted words.

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?

For a simple read tool with an output schema, the description is adequate to convey the core function. However, it misses behavioral context like auth scopes and potential limitations (e.g., body truncation), making it minimally complete but not fully rich.

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

Parameters2/5

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

Schema description coverage is 0%, and the description does not explain the parameters beyond their names. 'account' and 'message_id' are not defined; the description only clarifies the tool's purpose, not the expected parameter values or formats.

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 uses a specific verb ('Read'), a resource ('Gmail message'), and specifies content ('subject/from/snippet/body'). It clearly distinguishes from sibling tools like gmail.list_messages, which lists multiple messages, and gmail.send_message, which sends.

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

Usage Guidelines4/5

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

The description clearly implies when to use: when a single Gmail message's content is needed. It does not explicitly state alternatives or exclusions, but the sibling tool list provides context, and the 'single' scoping is explicit.

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

gmail.send_messageC

Send an email from an account.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYes
bodyYes
accountYes
subjectYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.6/5.0
Behavior2/5

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

With no annotations, the description carries the full burden of disclosing behavioral traits. It only states the action 'send' without mentioning side effects, authentication requirements, rate limits, or what happens after sending. This is insufficient for an agent to understand the tool's behavior beyond the obvious.

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

Conciseness4/5

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

The description is a single concise sentence that front-loads the core purpose. It contains no filler words or redundant information. However, it is so brief that it sacrifices necessary detail, which is a trade-off rather than a pure strength.

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

Completeness2/5

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

Given the tool has four required parameters and no annotations, the description is incomplete. It does not explain how to use the parameters, any prerequisites, or side effects. The presence of an output schema is helpful but does not compensate for the lack of operational context. The description is far from sufficient for an agent to correctly invoke the tool.

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%, so the description must compensate by explaining the parameters. It does not: the four required parameters (account, to, subject, body) are not mentioned at all. The only hint is 'from an account', which vaguely relates to the account parameter but provides no semantics.

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 verb 'send' and the resource 'email', and the phrase 'from an account' adds scope. It distinguishes itself from sibling tools like list_messages and read_message by indicating a write operation. However, it could be more specific about what 'account' refers to and any additional capabilities.

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

Usage Guidelines2/5

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

There is no guidance on when to use this tool versus alternatives, nor any prerequisites or exclusions. The only hint is the tool name and siblings, but the description itself offers no usage direction.

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

pingA

Smoke-test tool confirming the gateway process is reachable.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior3/5

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

With no annotations provided, the description carries the full burden. It discloses the core behavior (confirming reachability) and implies no side effects, but it lacks details on failure modes or prerequisites. The output schema presumably covers return values, which is acceptable.

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, focused sentence that conveys the purpose without any unnecessary words. It is perfectly concise.

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

Completeness4/5

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

The tool is simple, has no parameters, and an output schema exists, so the description provides the essential purpose. It would benefit from explicit usage context, but given the simplicity, it is sufficiently complete.

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?

The tool has zero parameters, so the description does not need to explain parameter semantics. The baseline of 4 is appropriate since there is nothing to add.

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's function as a smoke-test to confirm gateway reachability. It uses a specific verb ('confirming') and resource ('gateway process'), and it is distinct from sibling tools that operate on emails, calendars, or files.

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 phrase 'smoke-test' implies it should be used as a preliminary connectivity check, but the description does not explicitly state when to use it or mention alternatives. It leaves the timing and context to inference.

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

Tool Schema Changelog

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

  1. 5 tool updatesv0.3.0
    • Addedbank.get_balance
    • Addedbank.list_accounts
    • Addedbank.list_transactions_detailed
    • Addedbank.list_transactions_summary
    • Addedbank.summarize_spending
  2. 8 tool updatesv0.1.0
    • First observedcalendar.create_event
    • First observedcalendar.list_events
    • First observeddrive.list_files
    • First observeddrive.read_file
    • First observedgmail.list_messages
    • First observedgmail.read_message
    • First observedgmail.send_message
    • First observedping

TDQS

B3.3/5.0

Scored across 13 tools

Disambiguation5/5

Every tool is explicitly scoped by a domain prefix and a specific action; Gmail, Calendar, Drive, and Bank operations do not overlap. The two transaction-listing tools are differentiated as summary versus detailed.

Naming Consistency5/5

Tools consistently follow a <domain>.<verb>_<object> pattern (e.g. gmail.list_messages, drive.read_file, bank.get_balance). The standalone ping is a minor conventional exception but fits the gateway smoke-test role.

Tool Count5/5

Thirteen tools is a reasonable size for a multi-service gateway covering Gmail, Calendar, Drive, and banking data. Each tool contributes a distinct operation without bloat.

Completeness3/5

The read side is well covered, but the write/update side is incomplete: calendar events can be created but not updated or deleted, and Drive has no upload/update capability. Gmail and bank functionality are adequate for their apparent read/limited-action scope.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    C
    maintenance
    Local-first MCP server for agents that need to work across multiple Gmail and Microsoft 365 accounts without cloud token storage.
    6
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    Local MCP server for reading/sending email via Gmail and managing Google Calendar events, enabling an AI agent to handle email and calendar operations through natural language.
    MIT