bizidashboard-mcp
This MCP server exposes historical and analytical data for the Zaragoza Bizi bike-share system, going beyond the official GBFS real-time feed. You can:
Get latest station snapshots (
get_stations): bikes available, free anchors, capacity, location.Rank stations (
get_rankings) by turnover or availability to identify busiest or most reliably stocked stations.List active alerts (
get_alerts) for stations low on bikes or anchors.Query alert history (
get_alerts_history) by station, type, severity, state, and time range.Get hourly occupancy patterns (
get_patterns) for weekday vs. weekend.Retrieve occupancy heatmap cells (
get_heatmap) by day and hour.Analyze mobility signals (
get_mobility): hourly demand curves, station-to-station flows, and transit impact.Access full historical daily demand data (
get_history) since BiziDashboard started recording.Generate a rebalancing report (
get_rebalancing_report) with station classifications, empty/full risk predictions, and origin-destination transfer recommendations.
Most tools support JSON or CSV output (some CSV exports or extended windows require elevated permissions), and the server can integrate with LLM clients like Claude, ChatGPT, and Gemini via local stdio or remote HTTP/OpenAPI endpoints.
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., "@bizidashboard-mcpShow me the stations with the highest turnover this week."
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.
bizidashboard-mcp
Model Context Protocol server for BiziDashboard's Zaragoza bike-share analytics: stations, history, occupancy, alerts, mobility, and rebalancing.
Unlike the official GBFS feed (which only exposes the current state of the system), BiziDashboard stores and analyzes history: rankings, occupancy patterns, mobility signals, alert history, and a station rebalancing diagnostic report. This server makes that analytical layer easy to query from Claude Desktop or any other MCP client.
Installation
Published on npm — no cloning or compiling required. Add it to your MCP client config
(e.g. claude_desktop_config.json):
{
"mcpServers": {
"bizidashboard": {
"command": "npx",
"args": ["-y", "bizidashboard-mcp"]
}
}
}From source
git clone https://github.com/gcaguilar/bizidashboard-mcp.git
cd bizidashboard-mcp
npm install
npm run buildThen point your MCP client at the built entrypoint:
{
"mcpServers": {
"bizidashboard": {
"command": "node",
"args": ["/absolute/path/to/bizidashboard-mcp/dist/index.js"]
}
}
}Related MCP server: mcp-stm-montevideo
Configuration
BiziDashboard API (outbound)
Variable | Default | Purpose |
|
| Base URL of the BiziDashboard instance to query. Override to point at another city's deployment or a local dev server. |
| (none) | Local stdio only. Optional legacy |
| (none) | Optional local stdio Auth0 access token forwarded to DatosBizi. |
HTTP Server & OAuth (inbound, remote clients only)
The HTTP server requires OAuth-based authentication via Auth0. Before running it, you must:
Create an Auth0 API for the MCP resource, with exact identifier
https://mcp.datosbizi.com/mcp, RS256, and scopesread:dashboardandread:exports. Enable Dynamic Client Registration and Resource Parameter Compatibility Profile in the tenant. Claude and ChatGPT then register their own public clients; users do not receive an OAuth secret.In Applications → APIs → the MCP API, select Add Application to create its Custom API Client. Grant that client user-delegated access to
https://api.datosbizi.comand enable On-Behalf-Of Token Exchange. It is not the ordinary Machine-to-Machine application. Keep its client secret only in the MCP deployment.Configure these environment variables:
Variable | Purpose |
| Required. Your Auth0 tenant domain, e.g., |
| Required in production. Exact MCP Auth0 API identifier: |
| Required in production. Existing DatosBizi API identifier, e.g. |
| Required in production. Client ID of the special Auth0 resource-server OBO client. |
| Required in production. Secret of that OBO client. Store only as a Coolify secret. |
| Optional comma-separated browser origins allowed to call the HTTP MCP, e.g. |
| (optional) The public URL of this server (e.g., |
| (optional) HTTP port. Default |
Do not set AUTH0_AUDIENCES, AUTH0_ACCESS_TOKEN_ALLOWED_CLIENT_IDS,
AUTH0_CLIENT_IDS, or OAUTH_PROXY_ORIGIN on this public DCR deployment.
BASE_URL is required in production and must be the HTTPS MCP URL. Set
BIZI_ALLOWED_API_HOSTS to an explicit comma-separated allowlist (normally
datosbizi.com) so authenticated tokens are never forwarded to an unintended
origin.
For local authenticated use, enable Device Authorization for a local DatosBizi
Auth0 client and run bizidashboard-mcp-login with AUTH0_DOMAIN,
AUTH0_CLIENT_ID and AUTH0_AUDIENCE. It stores tokens in
~/.config/bizidashboard-mcp/tokens.json; the stdio server refreshes them when a
refresh token is available. Set BIZI_TOKEN_FILE to override that path.
Stdio Server (Claude Desktop, no auth needed)
All BIZI_* variables above are optional; if omitted, they default to the public BiziDashboard.
The stdio server (bizidashboard-mcp) needs no authentication.
Tools
Tool | Description |
| Latest availability snapshot for every station. |
| Rank stations by turnover or availability. |
| Currently active low-bikes/low-anchors alerts. |
| Filterable/paginated alert history. Remote |
| Weekday/weekend hourly occupancy pattern for one station. |
| Occupancy heatmap cells for one station. |
| Hourly/daily mobility signals and transit impact. |
| Full historical daily demand data since first record. |
| Station diagnostics (A–F classification), risk predictions, and transfer recommendations. Remote |
Every tool remains visible to every authenticated remote user. Every tool returns the
API's JSON response as-is (or CSV text when format: "csv" is requested); nothing is
summarized or transformed. An elevated request without read:exports returns an
actionable authorization error telling the user to reconnect with that scope. Other
upstream errors (bad params, rate limits) retain their original status and message.
Remote connector (Claude / ChatGPT)
npx bizidashboard-mcp (stdio) only works for local clients like Claude
Desktop. To use this data from claude.ai remote connectors or ChatGPT,
run the HTTP server instead and expose it publicly over HTTPS. It exposes the
same nine tools through one standard MCP endpoint:
Endpoint | Protocol | Used by |
| MCP Streamable HTTP (stateless) | Claude and ChatGPT |
Every route except /healthz requires an OAuth bearer token
(Authorization Code flow with Auth0), obtained after registering as described above.
The remote server validates issuer, MCP audience, signature, expiry, azp (when
configured), and read:dashboard. It then performs an Auth0 On-Behalf-Of exchange,
so BiziDashboard receives a token for https://api.datosbizi.com, preserving the
signed-in user and their scopes without accepting an MCP token at the downstream API.
Run it on your own server
With Docker (image published to GHCR on every push to main/tag by
.github/workflows/docker-publish.yml):
docker run -d \
--name bizidashboard-mcp \
-p 8787:8787 \
-e AUTH0_DOMAIN=<your-auth0-domain> \
-e MCP_AUTH0_AUDIENCE=https://mcp.yourdomain.com/mcp \
-e API_AUTH0_AUDIENCE=https://api.datosbizi.com \
-e MCP_AUTH0_CLIENT_ID=<obo-client-id> \
-e MCP_AUTH0_CLIENT_SECRET=<obo-client-secret> \
-e BASE_URL=https://mcp.yourdomain.com \
ghcr.io/gcaguilar/bizidashboard-mcp:latestFrom source:
npm install
npm run build
AUTH0_DOMAIN=<your-auth0-domain> \
MCP_AUTH0_AUDIENCE=https://mcp.yourdomain.com/mcp \
API_AUTH0_AUDIENCE=https://api.datosbizi.com \
MCP_AUTH0_CLIENT_ID=<obo-client-id> \
MCP_AUTH0_CLIENT_SECRET=<obo-client-secret> \
npm run start:httpEither way, put it behind a reverse proxy (Caddy, nginx, Traefik, …) on your
VPS to terminate TLS on a real domain — https://mcp.yourdomain.com — since
neither client below will call a plain-HTTP or self-signed endpoint.
Register it
Claude (claude.ai → Settings → Connectors → Add custom connector): URL
https://mcp.yourdomain.com/mcp. Authentication is OAuth 2.0 Authorization Code; Claude will discover the flow automatically via/.well-known/oauth-protected-resource.ChatGPT MCP / GPT builder: use the MCP URL and let the client complete OAuth through Dynamic Client Registration. Do not embed the OBO client secret in ChatGPT or in a public page.
OpenAI plugin submission
The MCP-only plugin package is in plugins/bizidashboard-mcp. It includes the
directory metadata and starter prompts for ChatGPT/Codex. Submission copy and
review cases are in docs/openai-plugin-submission.md.
The public submission still needs a verified OpenAI publisher identity, legal
URLs, regional availability, and OAuth reviewer credentials.
Development
npm run build # compile TypeScript to dist/ (both the stdio and HTTP entrypoints)
npm run typecheck # type-check without emitting
npm test # build, then run integration tests against the live public API
npm run start:http # run the HTTP MCP server locally (needs the Auth0 MCP/OBO variables above)To build the Docker image locally: docker build -t bizidashboard-mcp .
The existing tool smoke tests hit https://datosbizi.com for real. Focused
authorization tests use no live credentials and verify that remote HTTP requests never
send BIZI_PUBLIC_API_KEY.
Available Tools
9 toolsget_alertsA
List currently active alerts (stations running low on bikes or free anchors right now).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of alerts to return. Defaults to 50. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses the read-only nature ('List') and defines the alert context, but does not mention ordering, pagination, or any side effects. Since it's a simple list operation, this is minimally adequate but lacking richer behavioral detail.
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, well-structured sentence that front-loads the action and scope. Every word adds value; no redundancy or filler.
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 simple one-parameter tool and no output schema, the description adequately conveys what the tool returns (a list of active alerts). It could mention result ordering or that limit controls total count, but the schema already covers the default. Overall, it's sufficient for the tool's complexity.
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 100%, so the baseline is 3. The description adds meaning to the alerts themselves but not to the 'limit' parameter, which is already well-described in the schema. No additional context needed beyond the schema.
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 ('List') and clearly identifies the resource ('currently active alerts') with an explicit definition ('stations running low on bikes or free anchors right now'). This clearly differentiates it from siblings like get_alerts_history and get_stations.
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 the tool is for real-time or current alert status, contrasting with historical alerts (get_alerts_history). However, it does not explicitly state when not to use it or name alternatives, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_alerts_historyA
Query historical alerts (resolved and active) with filters by station, alert type, severity, and time range. This is the tool for "how often has station X run out of bikes" style questions. Requesting format=csv or a limit above 500 rows requires BIZI_PUBLIC_API_KEY to be configured.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | End datetime, ISO 8601. | |
| from | No | Start datetime, ISO 8601. | |
| limit | No | Rows per page. Defaults to 200. Values above 500 require BIZI_PUBLIC_API_KEY. | |
| state | No | Filter by alert state. Defaults to all. | |
| format | No | Response format. csv requires BIZI_PUBLIC_API_KEY. Defaults to json. | |
| offset | No | Pagination offset. Defaults to 0. | |
| severity | No | Filter by severity (1=media, 2=critica). | |
| alertType | No | Filter by alert type. Defaults to all. | |
| stationId | No | Filter by a specific station id. |
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 explicitly discloses that requesting csv format or a limit above 500 requires BIZI_PUBLIC_API_KEY, which is a critical behavioral constraint. While it doesn't cover all possible quirks (e.g., pagination defaults), it adds meaningful context 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?
Two sentences, front-loaded with the core action and then the key exception. Every sentence contributes meaningful information without repetition or filler.
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?
Despite 9 optional parameters and no output schema, the description covers the essential usage context: historical scope, example analysis, and authentication constraints. It doesn't describe return values, but the 100% schema coverage and focus on filters/constraints make it adequate for a query 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 coverage is 100%, so baseline is 3. The description adds value by mapping filters to the conceptual fields (station, alert type, severity, time range) and by explaining the API key requirement for specific parameter values (limit > 500). This goes beyond what the schema alone provides.
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 clearly states the tool queries historical alerts (both resolved and active) with specific filters. The example question 'how often has station X run out of bikes' further clarifies its analytical purpose and distinguishes it from likely real-time sibling tools like get_alerts.
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?
Provides a concrete use case ('how often has station X run out of bikes') indicating when to choose this tool. However, it does not explicitly mention when NOT to use it or directly compare to alternatives like get_alerts or get_history, so it narrowly misses a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_heatmapB
Get occupancy heatmap cells (day x hour) for a single station.
| Name | Required | Description | Default |
|---|---|---|---|
| stationId | Yes | Station identifier. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must disclose behavioral traits. It only states the action without mentioning side effects, return format, pagination, or data freshness. It adds minimal behavioral context beyond the basic retrieve operation.
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 with no wasteful words. It is front-loaded and delivers the essential information 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 one parameter, no output schema, and no annotations, the description is minimal but adequate for a basic read operation. However, it lacks details on the exact return format, time range, or limitations, leaving some 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?
The schema describes stationId as 'Station identifier' with 100% coverage. The tool description adds no additional meaning to this parameter, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves occupancy heatmap cells (day x hour) for a single station, using a specific verb and resource. This distinguishes it from sibling tools like get_stations or get_rankings, which focus on other data.
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 provides no guidance on when to use this tool versus alternatives such as get_history or get_patterns, nor does it mention exclusions or prerequisites. The implied usage is clear from the verb, but no explicit context is given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_historyA
Get full historical daily demand/balance data since BiziDashboard started recording this city, plus coverage metadata. This is the long-range view the official GBFS feed cannot provide since it only exposes current state.
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | Response format. Defaults to json. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden. It discloses the data scope ('since BiziDashboard started recording') and the inclusion of coverage metadata. However, it does not mention limits, pagination, or performance characteristics. It is honest about what it returns but lacks deep behavioral detail.
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 two sentences, front-loaded with the core action and resource. The second sentence adds valuable context about why this tool exists relative to GBFS. 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?
For a tool with one optional parameter and no output schema, the description is fairly complete. It explains what data is returned (demand/balance history, coverage metadata) and the temporal scope. It could mention the default format, but the schema already documents that. Minor gaps remain about how data is structured, but overall adequate.
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 100% coverage of the single optional 'format' parameter, so the description does not need to add parameter details. It does not repeat or supplement the schema, and no additional parameter meaning is provided. A baseline of 3 is appropriate given the high schema coverage.
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 ('Get') and resource ('full historical daily demand/balance data') plus additional context ('coverage metadata'). It clearly distinguishes from sibling tools like get_alerts_history by specifying the data type (demand/balance) and the long-range scope.
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 provides clear context: it is for long-range historical data that GBFS cannot provide. This implies when to use it, though it does not explicitly name alternative tools or state when not to use it. The contrast with GBFS gives a practical alternative but not a sibling exclusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_mobilityA
Get mobility signals: hourly demand curve, station-to-station flow signals, and public transit impact analysis. Good for understanding usage rhythms rather than instantaneous state.
| Name | Required | Description | Default |
|---|---|---|---|
| month | No | Optional specific month to inspect, formatted YYYY-MM. | |
| demandDays | No | Lookback window in days for the daily demand curve. Defaults to 30. | |
| mobilityDays | No | Lookback window in days for hourly mobility signals. Defaults to 14. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of disclosure. It enumerates the types of data returned (daily demand curve, flow signals, transit analysis) and adds a limitation ('usage rhythms rather than instantaneous state'). It does not explicitly state side effects or rate limits, but the tool's read-only nature is evident from the name and description, and the provided detail is substantial.
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 two sentences: the first lists the tool's outputs, and the second provides a concise usage hint. Every word earns its place, and the most important information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description fully covers the tool's purpose, output categories, and intended use case. With no output schema, it does not explain return shape, but the enumerated signal types provide sufficient context for an agent to understand the tool's capabilities. The schema covers parameters, so nothing critical is missing.
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 100%, so the baseline is 3. The description does not add additional meaning to the parameters (month, demandDays, mobilityDays) beyond what the schema already provides, but it does not need to since the schema is complete. It stays at baseline.
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 ('Get') and clearly identifies the resource ('mobility signals'), breaking it down into distinct components (demand curve, flow signals, transit impact). It also distinguishes itself from sibling tools by contrasting 'usage rhythms' with 'instantaneous state.'
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 provides a clear use case ('understanding usage rhythms') and implicitly excludes alternative use cases via 'rather than instantaneous state.' It does not explicitly name sibling tools or provide a full when/when-not matrix, but the guidance is sufficiently clear for an agent to decide.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_patternsA
Get weekday vs. weekend hourly occupancy patterns for a single station, showing typical bike availability by hour.
| Name | Required | Description | Default |
|---|---|---|---|
| stationId | Yes | Station identifier. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must disclose behavior itself. It mentions 'typical' and 'weekday vs. weekend' which indicates a summarized/aggregated output, but does not explain how the patterns are computed, what time range is covered, or what the response format looks like. It adds some context but not comprehensive behavioral details.
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?
A single, well-front-loaded sentence that packs the core purpose and differentiation into 17 words. No filler or redundant information; every word contributes to understanding.
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 simple one-parameter tool and no output schema, the description could be more explicit about what the returned data looks like (e.g., a table of hours and bike availability values). The core concept is clear, but the absence of any return-format hint leaves some gaps for an AI agent invoking 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?
The schema already documents stationId at 100% coverage. The description adds minimal value by restating 'single station' but does not provide additional meaning such as station ID format or examples. It meets the baseline but does not exceed it.
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 a specific action ('Get weekday vs. weekend hourly occupancy patterns') and resource ('for a single station'), with a concrete scope ('typical bike availability by hour'). It differentiates from sibling tools like get_history (raw history) and get_heatmap (likely aggregated heatmap) by specifying the pattern nature.
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 the tool (when you need typical hourly patterns for a single station) but provides no explicit exclusions or alternatives. It does not mention when to prefer get_history or get_heatmap instead, leaving some ambiguity in tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_rankingsA
Rank stations by turnover (bike rotation activity) or availability. Useful for finding the busiest or most reliably stocked stations over the observed history.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | Ranking metric to sort by. | |
| limit | No | Maximum number of stations to return. Defaults to 20. | |
| format | No | Response format. Defaults to json. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description is the only source of behavioral context. It explains the meaning of turnover and availability and mentions the historical scope, but omits important details like sort order direction, default limit handling, or how availability is computed.
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?
Two concise, front-loaded sentences with no redundant information. Every phrase contributes to the tool's purpose or use context.
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 three-parameter tool with no output schema, the description covers the core purpose and metrics. However, it lacks explicit details about return ordering (ascending vs descending), response shape, or the exact time range of 'observed history', leaving some gaps for an agent to infer.
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 100%, so the baseline is 3. The description adds value by clarifying 'turnover' as 'bike rotation activity' and linking availability to being 'reliably stocked', which enriches the enum semantics beyond the schema's single-line description.
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 ranks stations by two specific metrics (turnover and availability), using a specific verb ('Rank') and resource ('stations'). This distinguishes it from sibling tools like get_stations or get_patterns.
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?
Provides clear use cases ('finding the busiest or most reliably stocked stations over the observed history'), which helps an agent know when to use it. However, it doesn't explicitly name alternatives or state when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_rebalancing_reportA
Get the station rebalancing diagnostic report: per-station classification (overstock, deficit, peak saturation, peak emptying, balanced, data_review), 1h/3h empty/full risk predictions, and origin-destination bike transfer recommendations. Optionally filter by district/barrio. Requesting format=csv or a days window above 30 requires BIZI_PUBLIC_API_KEY to be configured.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | Analysis window in days. Defaults to 15. Values above 30 require BIZI_PUBLIC_API_KEY. | |
| format | No | Response format. csv requires BIZI_PUBLIC_API_KEY. Defaults to json. | |
| district | No | Filter by barrio/district name, e.g. "Centro" or "Delicias". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the behavioral disclosure burden. It clearly states the output contents, the optional filter, and the auth prerequisite for certain options, implying default json format and ≤30-day windows. It doesn't cover error handling, but the disclosed constraints are meaningful and not contradicted by any annotations.
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, well-organized sentence that front-loads the primary purpose, then adds output details, filtering options, and prerequisites in a logical order. There is no redundancy or filler, and every phrase contributes useful information.
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 three optional parameters, no output schema, and no annotations, the description covers the main purpose, report contents, optional filtering, and auth constraints—sufficient for most use cases. It omits default day values (present in schema) and exact error behavior, but the missing details are not critical for a well-formed definition.
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 100%, so the description doesn't need to re-explain parameters. It adds a bit of context (district filter is optional, csv and days>30 require API key), but these are already reflected in the schema. The description does not introduce new parameter meaning beyond what the schema provides.
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 ('Get') and identifies a clear resource ('station rebalancing diagnostic report'), then elaborates with detailed output components (per-station classification, risk predictions, transfer recommendations). This level of specificity clearly distinguishes it from sibling tools like get_stations or get_rankings.
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 provides solid context for usage, including optional district/barrio filtering and explicit API key requirements for csv format or windows above 30 days. However, it doesn't name alternative tools or explicitly state when not to use this tool, so it stops short of full guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_stationsA
List every Bizi Zaragoza station with its latest known availability snapshot (bikes available, free anchors, capacity, location). Reflects the most recent GBFS collection, not necessarily real time to the second.
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | Response format. Defaults to json. |
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 clearly states that data is a snapshot and not real-time, which is a non-obvious limitation. It also implies a read-only 'list' operation. This is good, though it does not mention response size, pagination, or potential errors.
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?
Two sentences, front-loaded with the main purpose, followed by a concise caveat about data timeliness. No fluff or repetition.
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 description explains what the tool returns (station list with availability fields) and adds a freshness caveat. There is no output schema, so this is sufficient for a simple listing tool. Missing details like sorting or station count are minor.
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, 'format', has a complete schema description ('Response format. Defaults to json.') with an enum. Since schema coverage is 100%, the description does not need to add anything. The tool description does not mention parameters, but the schema already fully accounts for them.
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 opens with a specific verb and resource: 'List every Bizi Zaragoza station.' It also enumerates the included data (bikes available, free anchors, capacity, location), making the tool's purpose immediately clear and distinct from sibling tools like get_rankings or get_alerts.
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 gives useful context about data freshness ('latest known availability snapshot', 'not necessarily real time'), which helps an agent decide if this tool is appropriate. However, it does not explicitly mention when to use this tool over siblings or exclude any cases.
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.
9 tool updates
v0.1.0- First observed
get_alerts - First observed
get_alerts_history - First observed
get_heatmap - First observed
get_history - First observed
get_mobility - First observed
get_patterns - First observed
get_rankings - First observed
get_rebalancing_report - First observed
get_stations
TDQS
Scored across 9 tools
Most tools have clearly distinct purposes, but get_patterns and get_heatmap both describe occupancy patterns for a single station, differing only in data format (weekday/weekend hourly vs day x hour heatmap). get_rankings and get_mobility are also somewhat related but descriptions clarify their distinct focuses.
All tools follow a consistent get_<noun> pattern, using snake_case throughout. The naming is predictable and makes it easy for an agent to infer the resource being accessed.
Nine tools is a well-scoped set for a bike-sharing analytics dashboard, covering current status, alerts, historical trends, mobility patterns, and rebalancing diagnostics without feeling bloated or sparse.
The tool set provides comprehensive coverage of the station analytics domain: current availability, rankings, active and historical alerts, hourly patterns, heatmaps, long-range history, mobility signals, and rebalancing recommendations. No obvious dead ends or missing core operations.
Maintenance
Related MCP Connectors
MCP server exposing the Backtest360 engine API as tools for AI agents.
- UnifAPIOAuthcom.unifapi
Hosted MCP server for live public-data APIs and Skills for AI agents.
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
MCP server that lets AI assistants use all OneSchema features exposed via the public API.
Related MCP Servers
- AlicenseAqualityFmaintenanceMCP server for querying Spanish government open data APIs including grants, legislation, company registry, statistics, and open data catalog. Enables LLMs to access Spanish public information on-the-fly.265MIT
- AlicenseNot gradedqualityDmaintenanceMCP server exposing Montevideo public transportation data (STM) as tools for AI assistants, enabling natural language queries about routes, stops, arrivals, and trip planning.7 npm1MIT
- AlicenseNot gradedqualityDmaintenanceMCP server to query public open data from Recife, Brazil using natural language. It exposes tools for schema exploration and SQL query generation via Gemini 2.5 Flash, backed by a local DuckDB database.1MIT
- AlicenseBqualityCmaintenanceMCP server for grounded analysis of synthetic electric-taxi operations data, exposing tools for aggregated metrics, charging risk, and policy retrieval.3MIT