jb_gateway_mcp
This MCP server acts as a credential-holding, policy-gated gateway, giving AI agents controlled access to Google services (Gmail, Calendar, Drive) and bank account data (via Enable Banking) without exposing sensitive credentials.
Ping:
pingconfirms the server is reachable; always available.Gmail:
list_messages: List messages for an account, optionally filtered by query.read_message: Get a single message's details (subject, from, snippet, body).send_message: Send an email (requires explicit policy grant; deny-by-default).
Calendar:
list_events: List upcoming events (default primary calendar).create_event: Create an event with start/end times (requires explicit grant).
Drive:
list_files: List files matching a query.read_file: Read metadata and text content of a file.
Bank (read-only, via Enable Banking):
list_accounts: List linked accounts (masked IBANs).get_balance: Retrieve balance for an account.summarize_spending: Aggregated spending totals over a date range.list_transactions_summary: Transactions with date/amount/currency only.list_transactions_detailed: Adds counterparty names and descriptions (requires explicit grant).
Key characteristics: deny-by-default policy gates every tool call per caller-specific grants; credentials and secrets are never exposed; bank data is strictly read-only with privacy protections like IBAN masking and minimal transaction details.
Provides tools for listing, reading, and sending emails through the Gmail API.
Provides tools for listing and reading files through the Google Drive API.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@jb_gateway_mcpWhat's on my calendar for today?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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.
Skills & plugins (recommended if you're using Claude Code)
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 | shUsing 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.gitThis 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.yamlThat'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)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 sync2. 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:
Go to Google Cloud Console and create (or pick) a project.
APIs & Services → Library — enable the Gmail API, Google Calendar API, and Google Drive API.
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).
APIs & Services → Credentials → Create Credentials → OAuth client ID — Application type: Desktop app. Download the resulting JSON — this is your
client_secret.json.Keep this file out of the repo. Store it somewhere outside the project (e.g.
~/.secrets/jb_gateway_mcp/client_secret.json). The.gitignorehere already blocksclient_secret*.jsonas 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.jsonBy 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.readonlyOn 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.eventslocal 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.shThis 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.py6. 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)
Sign in at enablebanking.com/sign-in/ (email + magic link — no business registration needed).
Control Panel → API applications → Add a new application.
Name: anything identifiable.
Redirect URL: exactly
https://localhost:8080/callback— Enable Banking requireshttps://, 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>.pemand never leaves your machine.
Keep the
.pemout of the repo — e.g.~/.secrets/jb_gateway_mcp/enablebanking/<application-id>.pem, same convention asclient_secret.json.Activate the application. A freshly registered app starts "Inactive" and returns
403 Forbiddenon 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 revolutThis 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.detailedTiered 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 |
|
| Identity used for every policy check and audit entry in this process. Must match a |
|
| Path to the policy file. Must exist and be valid YAML — the server fails to start if it's missing, even just to serve |
|
| Path to the audit log (JSON Lines, one entry per tool call, secrets redacted). Parent directory is created automatically. |
Tool catalog
Tool | Scope | Notes |
| — (ungated smoke-test tool) | Always available, not policy-gated |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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.yamlunder the caller id you're using.Re-consent error mentioning a revoked/expired refresh token — re-run
onboard-googlefor that account.403 Forbiddenfromonboard-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=...fromonboard-bank— the institution name is genuinely ambiguous in that country (e.g. "DNB" vs. "DNB Corporate Mastercard"); narrow_INSTITUTION_NAME_HINTinsrc/jb_gateway_mcp/cli/onboard_bank.pyfor that alias and retry.NeedsReconsentError/ "consent ... expired" from a bank tool call — the 90-day bank consent lapsed; re-runonboard-bank --institution <alias>.Audit log — every call (
success,cached,denied, orerror) is recorded atJB_GATEWAY_AUDIT_LOG. Tokens/secrets are redacted before writing.cachedmeans abank.*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.pemprivate key, or any file matching*credentials*.json—.gitignoreblocks 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_messageandcalendar.create_eventare the only write-capable Google tools; they are not granted in the defaultpolicy.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_detailedis the only tool that surfaces counterparty names/payment descriptions, and it requires its own, off-by-defaultpolicy.yamlgrant — 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:
Remove it from every client you connected it to:
Claude Desktop — delete the
jb-gateway-mcpentry fromclaude_desktop_config.json, then restart Claude Desktop.Claude Code — remove/delete
.mcp.json(project-scoped), orclaude mcp remove jb-gateway-mcpif you registered it globally instead.Any other client — remove its equivalent
mcpServersentry.
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.comPrompts for confirmation per account (add
--yesto skip); repeatable with multiple--accountflags 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-grantskips 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.
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.jsoncopy, wherever you stored it outside the repo
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:
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.
Delete the local keychain entries —
keyringstores these under the OS's native secret store (Keychain on macOS, Credential Manager on Windows, Secret Service on Linux), under service namesjb_gateway_mcp:enablebanking_app(the app credential, one entry) andjb_gateway_mcp:enablebanking_session(one entry per institution alias you onboarded, e.g.dnb/nordea/revolut). Search forjb_gateway_mcp:enablebankingin 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 toolsbank.get_balanceB
Get current/available balances for a bank account.
| Name | Required | Description | Default |
|---|---|---|---|
| account_uid | Yes | ||
| institution | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| institution | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| date_to | Yes | ||
| date_from | Yes | ||
| account_uid | Yes | ||
| institution | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| date_to | Yes | ||
| date_from | Yes | ||
| account_uid | Yes | ||
| institution | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| date_to | Yes | ||
| date_from | Yes | ||
| account_uid | Yes | ||
| institution | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | ||
| end_iso | Yes | ||
| summary | Yes | ||
| start_iso | Yes | ||
| calendar_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | ||
| calendar_id | No | primary | |
| max_results | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | ||
| account | Yes | ||
| page_size | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | ||
| file_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | ||
| account | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | ||
| message_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | ||
| body | Yes | ||
| account | Yes | ||
| subject | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
5 tool updates
v0.3.0- Added
bank.get_balance - Added
bank.list_accounts - Added
bank.list_transactions_detailed - Added
bank.list_transactions_summary - Added
bank.summarize_spending
8 tool updates
v0.1.0- First observed
calendar.create_event - First observed
calendar.list_events - First observed
drive.list_files - First observed
drive.read_file - First observed
gmail.list_messages - First observed
gmail.read_message - First observed
gmail.send_message - First observed
ping
TDQS
Scored across 13 tools
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.
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.
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.
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
Related MCP Connectors
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
Hosted Google Calendar MCP server for AI agents. No self-hosting or Google Cloud setup.
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
- gatewayOAuthai.sealgate
MCP gateway with runtime security policy, tool-call-level control, and audit of agent actions.
Related MCP Servers
- FlicenseAqualityCmaintenanceLocal-first MCP server for agents that need to work across multiple Gmail and Microsoft 365 accounts without cloud token storage.6-
- AlicenseBqualityDmaintenanceA Model Context Protocol (MCP) server that connects AI agents to Google Workspace (Gmail, Calendar, Drive, Docs, Sheets, and Slides).302MIT
- AlicenseNot gradedqualityAmaintenanceLocal 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
- AlicenseAqualityBmaintenanceA small MCP server for read-write access to Google Tasks, Calendar, and Drive, enforcing human approval for all mutating operations.1MIT