MCP server for Telkomsel (Indonesian telecom) account management, providing tools for login, profile retrieval, quota checking, package purchasing, and automated package buying.
telbot MCP server exposes 9 tools for Telkomsel account management. Tools have descriptive names and are well-documented at the natural language level. However, critical gaps exist: (1) Input schemas are visible in code but parameter descriptions are often generic or missing type constraints (e.g., 'interval_minutes' lacks min/max bounds for a high-risk auto-purchase feature); (2) Output schemas are completely undocumented, no structured response format is declared, forcing LLMs to infer what fields get_profile, get_quota, buy_package return; (3) Error handling provides recovery guidance in some cases but lacks systematic categorization (retryable vs. user-fixable vs. fatal); (4) High-risk operations (buy_package, start_auto_buy) lack confirmation-step or dry-run patterns; (5) All tools accept only positional/literal inputs, no enum constraints for payment_method despite it being restricted to 'pulsa' or 'qris'. Naming is strong (verb-first, action-clear). Descriptions are moderate length (100-200 chars, within baseline). Per-tool analysis below.
Purchase a Telkomsel package with a given Offer ID. Payment method can be 'pulsa' or 'qris'.
Get complete details like price, name, validity and description for a specific package/offer ID.
Get the Telkomsel profile, balance, and account status of the currently logged-in user.
Get the current internet quota and packet balances of the user.
Get a list of all recommended packages/offers available for the user to buy. Returns name, price, validity, bonuses, and offer IDs.
Start login to Telkomsel with a phone number. This opens a browser, triggers an OTP to the user's phone. After calling this, use submit_otp to complete the login.
Output schemas completely undocumented. get_profile, get_quota, get_package_details, get_recommended_offers return structured objects (evident from FormatProfile, CheckQuota calls in code) but LLM has no way to know what fields are present, types, or chaining IDs. Forces LLM to infer structure from responses, increasing hallucination risk.
payment_method parameter in buy_package lacks enum constraint. Description says 'must be pulsa or qris' in prose, but no formal enum or pattern is declared in schema. LLM may generate invalid values like 'credit_card' or 'bank_transfer'.
start_auto_buy has parameter interval_minutes (type number) with no min/max bounds. Description says 'e.g. 5, 10, 30' but LLM could generate 0, 1000000, or negative values. High risk: auto-purchase runs at unbounded intervals.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 59 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 41 | - | v1 |
Logout the current session and clear stored credentials.
Start an auto-buy monitor that checks quota periodically and auto-purchases a package when quota is depleted. Payment uses pulsa (AIRTIME).
Submit the OTP code received on the phone to complete the login process. Must be called after 'login'.
threshold_mb parameter in start_auto_buy is optional with unclear default. Description says 'Default is 0 (only buy when quota is completely empty)' in prose, but if LLM omits it, behavior depends on server-side logic. Should be explicit in schema or always required.
Irreversible operations (buy_package, start_auto_buy) lack confirmation-step or dry-run pattern. An agent could charge the user's pulsa balance without explicit confirmation. No pattern:confirmation-request implemented.
Error handling is inconsistent. Some tools return generic mcp.NewToolResultError() with no recovery guidance. E.g., 'Failed to get quota: %v' tells LLM nothing about whether to retry, call a different tool, or ask user. No error-classification pattern.
login and submit_otp depend on session state (StateLoggingIn, StateAwaitingOTP). If session expires between calls, submit_otp returns 'No login in progress or session expired', but description does not mention this prerequisite or session lifetime.
Phone number input in login accepts 'local phone number without country code' (e.g., '812xxxxxxxx') but code then prepends '62' internally. If agent receives a full number (+62812...) or country code, validation fails silently. Description should clarify format and show examples.
get_package_details requires offer_id parameter but no description of where to get offer_id. User/agent must infer it comes from get_recommended_offers. Should be explicit: 'Call get_recommended_offers to discover offer IDs.'