line-oa-mcp-ultimate
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| LINE_CHANNEL_ACCESS_TOKEN | Yes | The channel access token for your LINE Messaging API channel. |
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| prompts | {
"listChanged": true
} |
| resources | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| line_send_messageA | Universal LINE sender. Auto-picks the API (reply/push/multicast/narrowcast/broadcast) from the mode: send_now (default) sends immediately; draft returns a LINE OA Manager handoff package (URL + Flex JSON + steps) — use when the user wants to SCHEDULE, since the Messaging API can't schedule but the OA Manager UI can; dry_run validates + estimates cost without sending. Safety: pre-flight /validate before spending quota; Quota Guardian blocks if projected cost >95% of remaining quota unless confirm=true; broadcast { everyone:true } requires confirm=true; quiet-hours 22:00–08:00 BKK warns unless force=true; quiet_push silences the recipient device; reply tokens expire ~1 min (falls back to a push hint). Returns send_now → { success, transport, request_id?, recipient_count_estimated, quota, warnings[] }; draft and dry_run return their own shapes. Narrowcast needs ~24h before line_get_message_stats shows engagement. Example: "ส่งโปรให้ผู้หญิง 25-44 กรุงเทพ" → target.filter { genders:["female"], ages:["age_25","age_30"], areas:["bangkok"] }. |
| line_find_sticker | Find LINE stickers from a curated catalog by mood or keyword (Thai or English). Bots may only send stickers from LINE's limited official list, so this picks by intent ("celebration", "ขอบคุณ", "sorry") instead of guessing IDs. Pass the chosen package_id + sticker_id to line_send_message via message.sticker. Returns { query, count, stickers:[{ package_id, sticker_id, moods, keywords_th, keywords_en, description }] }. |
| line_build_rich_menuA | Create a LINE Rich Menu from an already-hosted image in one call: validate → create → upload image → set as default. Collapses 4 LINE API calls into one, incl. the api-data.line.me domain switch for image upload (the #1 cause of failed implementations). Single-panel menus only. To RENDER the image from labels instead of hosting your own, use line_design_rich_menu_image. image_url must be public HTTPS JPEG/PNG, width 800–2500px, aspect ≥1.45, ≤1MB (validated client-side before upload). areas are tappable regions with postback/message/uri/richmenuswitch actions and must fit inside the image bounds. size 'large' (2500x1686, default) or 'compact' (2500x843). set_as_default default true. Max 1,000 rich menus per OA. Returns { rich_menu_id, name, set_as_default, warnings[] }. |
| line_list_rich_menusA | List all rich menus on an OA and identify the account-wide default. OAs hold up to 1,000 rich menus — run this before line_build_rich_menu to avoid the cap, and line_delete_rich_menu to clean up. Returns { total, default_id?, rich_menus:[{ rich_menu_id, name, chat_bar_text?, size?, is_default, is_selected }] }. |
| line_delete_rich_menuA | Delete a rich menu by ID. Requires confirm=true (guards against prompt drift). If the menu is linked to specific users those links break silently — consider line_audit_user_menu first. Returns { success, deleted_id }. |
| line_audit_user_menuA | Diagnose "why is user X seeing menu Y?" — inspects the rich-menu priority chain: a per-user link (line_link_rich_menu) overrides the account-wide default, and LINE OA Manager-built menus silently override API-built ones. Pass user_id. Returns { user_id, visible_rich_menu_id?, source:'per_user'|'default'|'none', per_user_link?, default_id?, explanation (Thai) }. |
| line_link_rich_menuA | Attach (mode='link') or detach (mode='unlink') a rich menu for specific LINE users. A per-user menu overrides the account-wide default — this is how you show different menus to different segments (e.g. paying vs. free). Unlinking falls the user back to the account default. Pass user_id (single) or user_ids[] (bulk, auto-chunked at 500/batch). rich_menu_id required for link. To set the account-wide default instead, use line_set_default_rich_menu. Returns { mode, linked_count?/unlinked_count?, rich_menu_id?, chunks? }. Example: "ผูก rich menu R123 ให้สมาชิก 800 คน" → { mode:"link", rich_menu_id:"R123", user_ids:[...800 ids] }. |
| line_set_default_rich_menuA | Set or clear the OA's default rich menu — shown to every follower without a per-user menu linked (per-user links via line_link_rich_menu override it). mode 'set' (needs rich_menu_id) or 'clear'. Returns { mode, rich_menu_id? }. |
| line_manage_rich_menu_aliasA | Rich menu alias CRUD. Aliases power tab-switching rich menus: a 'richmenuswitch' action references a richMenuAliasId, and repointing that alias at a different rich menu swaps the displayed panel instantly — no per-user re-linking. modes: create (bind alias_id→rich_menu_id), update (repoint), delete (removes alias, not the underlying menu), get, list. alias_id required except for list; rich_menu_id required for create/update. Returns create/update/delete → { mode, alias_id, rich_menu_id? }; get → { richMenuAliasId, richMenuId }; list → { aliases[] }. Example: "เปลี่ยน alias tab-a ไปที่ R456" → { mode:"update", alias_id:"tab-a", rich_menu_id:"R456" }. |
| line_upload_rich_menu_imageA | Replace the image on an EXISTING rich menu without recreating it — richMenuId, tappable areas, and per-user links are preserved. Downloads from a public HTTPS URL, validates JPEG/PNG ≤1MB, then uploads to the api-data.line.me content endpoint (the domain switch that trips up most implementations). Private/internal addresses are blocked by an SSRF guard. Returns { rich_menu_id, uploaded, bytes }. Example: "เปลี่ยนรูป rich menu R123" → { rich_menu_id:"R123", image_url:"https://.../banner.png" }. |
| line_design_flex | Compose a validated Flex Message for line_send_message. Modes: template mode { template, data } (Thai-localized, recommended; templates: receipt, voucher, shipping_update, order_confirm, appointment_reminder, promo_simple, course_cert, thank_you); raw mode { flex_json, alt_text } (advanced); or { list_templates: true } to get the catalog with Thai descriptions + required fields per template. DESIGN ONLY — never calls the LINE API. Feed the result to line_send_message via message.flex_json, or pass { template, data } straight to line_send_message (same templates). Returns { flex_json, alt_text, preview_url (Flex Simulator), size_bytes, warnings[] } (warns near the 30KB bubble limit). Example: "ออกแบบคูปอง 20% หมด 31 ส.ค." → { template:"voucher", data:{ title:"ส่วนลดวันแม่", code:"MOM20", discount:"ส่วนลด 20%", valid_until:"31 ส.ค. 2026" } }. |
| line_design_imagemapA | Build a validated Imagemap message (LINE OA Manager calls it a "Rich Message") and return it as JSON to hand to line_send_message via message.message_json. DESIGN ONLY — never calls the LINE API. Image hosting (critical): LINE has NO imagemap-image upload API — you must pre-host the image at a public HTTPS base_url, and LINE fetches sized variants Returns { message, usage_hint }. Example: "Rich Message ครึ่งบน-ครึ่งล่าง กดไปคนละลิงก์" → { base_url:"https://cdn.example.com/promo", alt_text:"โปรเดือนนี้", base_height:1040, areas:[{bounds:{x:0,y:0,width:1040,height:520},action:{type:"uri",uri:"https://shop.example.com/a"}},{bounds:{x:0,y:520,width:1040,height:520},action:{type:"uri",uri:"https://shop.example.com/b"}}] }. |
| line_design_cardA | Build a validated LINE Template message (LINE OA Manager calls it a "Card Message") and return it as JSON to hand to line_send_message via message.message_json. DESIGN ONLY — never calls the LINE API.
Returns { message, usage_hint }. Example: "การ์ดยืนยันการจอง ตกลง/ยกเลิก" → { kind:"confirm", alt_text:"ยืนยันการจอง", text:"ยืนยันคิว 14:00 ไหม?", actions:[{type:"postback",label:"ตกลง",data:"confirm=1"},{type:"message",label:"ยกเลิก",text:"ยกเลิก"}] }. |
| line_build_audience_from_csvA | Create a LINE audience by uploading user IDs (or IFAs) — the "CSV from Google Sheets → retargeting audience" flow most Thai SMBs need. LINE indexes for ~5-10 min after creation (line_list_audiences shows IN_PROGRESS then READY). user_ids max 10,000/call; is_ifa true for IFA values instead of LINE user IDs. Region-gated to JP/TW/TH OAs (+premium). Returns { audience_group_id, name, type, created_unix_ms }. Example: "สร้าง audience ลูกค้าเดือนก่อน" → { name:"buyers_last_month", user_ids:[...] }. |
| line_build_audience_from_engagementA | Create a LINE audience from people who clicked or opened a previous broadcast/narrowcast — retarget without a CRM. source_request_id is the request_id returned by a prior line_send_message; type 'clicks' (default, optional click_url filter) or 'opens'. The source message must be ≥24h old before the audience is reliable, needs ~50+ users to be usable in narrowcast, and is region-gated to JP/TW/TH (+premium). Feed the resulting audience back into line_send_message target.audience. Returns { audience_group_id, name, type }. |
| line_list_audiencesA | List audience groups on the OA — including ones created in LINE OA Manager UI (chat-tag, friend-path, web-traffic) that CANNOT be created via Messaging API. status: READY (usable in narrowcast now) | IN_PROGRESS (indexing, wait ~10 min) | FAILED | EXPIRED (both need recreate). Filter with status_filter (default 'all') and name_contains (case-insensitive); paginate with limit/page (default 20). Returns { total, count, page, audiences:[{ audience_group_id, name, status, audience_count?, created, type? }], has_more }. |
| line_delete_audienceA | Delete an audience group. Irreversible — requires confirm=true. audience_group_id (numeric) from line_list_audiences. Returns { success, deleted_id }. |
| line_update_audienceA | Mutate an existing LINE audience group. modes: add_users (append user_ids) | rename (set description). audience_group_id from line_list_audiences. Only Messaging-API-created (upload) audiences accept mutation — audiences built in LINE OA Manager UI (chat-tag, friend-path, web-traffic) are read-only and LINE will reject changes. Returns add_users → { mode, audience_group_id, added_count }; rename → { mode, audience_group_id, new_description }. Example: "เพิ่ม 3 คนเข้า audience 12345" → { mode:"add_users", audience_group_id:12345, user_ids:["U1","U2","U3"] }. |
| line_get_oa_reportA | Digest of LINE OA performance over a date range — bundles 8+ Insight API calls into one Thai-friendly markdown report. range: a preset ('today'|'yesterday'|'this-week'|'last-week'|'this-month'|'last-month', default 'last-week') or { from, to } as YYYY-MM-DD. LINE insight data lags T-2 (yesterday is the latest reliable date) and is masked below the ~20-user privacy floor; demographics populate only with enough consented friends (report surfaces these in notes). Returns { oa_id, range, delivery{total,daily[]}, followers, demographic_available, quota, notes[] }. |
| line_get_message_statsA | Fetch per-broadcast engagement for a request_id (from a prior line_send_message): impressions, opens, clicks, CTR, and per-URL click breakdown. Caveats (in notes): ~24h data lag (stats stabilize ~T+1); below ~20 unique users LINE returns null for privacy; available only for narrowcast/multicast/broadcast, not reply or push-to-single-user. Returns { request_id, delivered?, unique_impression?, unique_click?, ctr_percent?, per_url_clicks[], notes[] }. |
| line_get_oa_statusA | Quick health check of a LINE OA — friend count, monthly quota usage, webhook status, and current default rich menu, aggregating 4 LINE API calls into one card. Good as the first call of a session: current quota and webhook state inform every later decision (send, schedule, switch OA). Returns { oa, friends?, quota, webhook, default_rich_menu?, region?, health:'OK'|'WARNING'|'ERROR', warnings[] }. |
| line_estimate_send_cost | Estimate how many quota messages a planned send will consume, without sending. Useful before confirmation, especially for narrowcast/broadcast. target uses the same shapes as line_send_message; message_count (1-5, default 1) — LINE charges message_count × recipients. Recipients are exact for user_id(s), looked up for a numeric audience, and unknown for filter/everyone (recommends a line_send_message dry_run instead). Returns { estimated_recipients?, estimated_cost_messages?, quota, cost_share_percent?, notes[] }. |
| line_get_narrowcast_progressA | Poll the delivery progress of an async narrowcast (GET /v2/bot/message/progress/narrowcast). Narrowcast runs in the background — the send returns a request_id and this reports how far it got. Pass that request_id. Returns { request_id, phase (waiting|sending|succeeded|failed), status_text, success_count?, failure_count?, target_count?, error_code?, accepted_time?, completed_time? }. |
| line_test_webhookA | Ping the OA's webhook URL from LINE servers and report HTTP status + latency; LINE checks it returns 200 within timeout and that signature verification works. Use this FIRST whenever a bot stops responding, before debugging anything else. Pass override_endpoint to test a URL other than the configured one. reason surfaces LINE's result: INVALID_REPLY | UNAUTHORIZED (bad channel_secret signature) | SERVER_ERROR (5xx) | TIMEOUT (>10s) | SSL_ERROR. Returns { success, status_code, latency_ms?, reason, configured_endpoint?, tested_endpoint }. |
| line_set_webhook_endpointA | Read or write the LINE OA's webhook URL (PUT/GET /v2/bot/channel/webhook/endpoint). mode 'set' (needs endpoint: public HTTPS, ≤500 chars) or 'get'. Complements line_test_webhook — set here, then ping with line_test_webhook. Returns { endpoint, active } (re-read after a 'set' to confirm). |
| line_manage_liff_app | LIFF app lifecycle CRUD. modes: create (needs config.view {type,url}), list, update (liff_id + partial config), delete (liff_id + confirm=true). Auth note: LIFF Server API uses LINE Login channel tokens; this uses the same Messaging API token — for separate-channel setups see docs. Example: "สร้าง LIFF tall https://my.app" → { mode:"create", config:{ view:{ type:"tall", url:"https://my.app" } } }. |
| line_check_tokenA | Verify the active OA's channel access token (GET /oauth2/v2.1/verify) — reports bound client_id, remaining lifetime, and granted scope; warns (Thai) when <7 days remain. Run before a campaign: a token expiring mid-send fails silently. An invalid/expired token surfaces a 401 error (no { valid:false } shape). Returns { valid, client_id, expires_in_seconds, expires_in_days, scope?, warning? }. |
| line_get_user_profileA | Fetch a LINE user's profile (display name, picture, status message, language) by user_id. Only works if the user has added the bot, has not blocked it, and consented to share profile — any failure returns an ambiguous 404, surfaced as a clear Thai explanation. Returns { user_id, display_name, picture_url?, status_message?, language? }. |
| line_list_followersA | Page through every user that has added the OA as a friend. Region-gated: only TH/JP/TW OAs on premium tier — others get LINE 403. page_size 1-1000 (default 300); continuation_token for cursor pagination. For very large OAs (50k+), prefer an engagement audience via line_build_audience_from_engagement over pulling all IDs. Returns { user_ids[], count, has_more, next_continuation_token? }. |
| line_list_oasA | List all LINE Official Accounts available to this MCP instance (from the multi-OA config file, or single-OA env mode). Call before line_use_oa to discover OA IDs. Returns { active_oa, oas:[{ id, display_name?, region?, is_premium?, is_active }] }. |
| line_use_oaA | Switch which OA all subsequent tool calls default to (until changed or process restart). In-memory only — does not edit config.json. oa_id from line_list_oas. Returns { active_oa, display_name }. |
| line_run_on_many_oasA | Agency feature — run any read-only line_* tool across many OAs in parallel; per-OA errors are isolated (one bad token doesn't break the run). tool must be one of the supported read-only tools below; oa_ids an array or 'all' (default); parallel concurrency 1-10 (default 5). Supported tools:
Returns { tool, count_ok, count_failed, results[], errors[] }. Example: "เช็คสถานะทุก OA" → { tool:"line_get_oa_status", oa_ids:"all" }. |
| line_manage_couponA | Coupon CRUD on a LINE OA (POST /v2/bot/coupon). modes: create (maps friendly inputs to LINE's schema — dates to UNIX seconds, visibility, etc.), list, get (by coupon_id), discontinue (ends a live coupon; irreversible — requires confirm=true). Deliver a created coupon via line_send_message message.coupon_id. Rate limit: shared 200 req/sec bucket with multicast. create data: title (≤60, required); discount_type 'percentage'(default)|'fixed'|'explicit' with discount_value (or price_before/price_after for explicit); valid_from/valid_to accept UNIX seconds | 'YYYY-MM-DD' | ISO; visibility PUBLIC|UNLISTED (default UNLISTED); acquisition_type normal|lottery. Example: "Early Bird ลด 20% 1–8 มิ.ย." → { mode:"create", data:{ title:"Early Bird", discount_type:"percentage", discount_value:20, valid_from:"2026-06-01", valid_to:"2026-06-08", coupon_code:"EARLYBIRD" } }. "ปิด coupon C123" → { mode:"discontinue", coupon_id:"C123", confirm:true }. |
| line_get_coupon_stats | Read available stats for a LINE coupon. LINE has no dedicated redemption endpoint, so this combines signals: raw coupon detail (some accounts include usage inline) plus, if you pass click_audience_id, the click-audience size as a clickthrough proxy. coupon_id comes from line_manage_coupon. Caveat (surfaced in notes): click-audience size approximates clickthroughs, NOT actual redemptions — for real counts build the coupon Flex with a postback action and listen via webhook. Returns { coupon_id, raw, click_audience?, estimated_redemptions?, notes[] }. |
| line_design_rich_menu_imageA | Design a professional LINE rich menu PNG from labels alone — pure-JS renderer with Thai typography (LINE Seed / Prompt / Noto), then optionally deploy to LINE in the same call. No design tool or headless browser. ALWAYS preview first: mode="preview" (default) returns the PNG as an image block — LOOK at it, iterate with the user, then call again mode="deploy". mode="save" writes the PNG to disk. Templates (cells filled in reading order; tap areas auto-derived from the same geometry, pixel-perfect):
cells[] length MUST equal the template's cell count; per-cell action is required only for deploy. brand auto-corrects label contrast for readability. deploy needs deploy:{ name, set_default?, alias? } and auto-deletes the orphaned menu on any post-create failure; LINE caps the PNG at <1MB (gradients auto-flatten to solid once). Returns preview → PNG image block + { width, height, bytes, template, font_used, warnings[] }; deploy → { rich_menu_id, areas_count, set_default, alias? }. Example: "ทำเมนูร้านกาแฟ 6 ปุ่ม สีเขียว" → { template:"grid_6", brand:{primary:"#06C755"}, cells:[{label:"สั่งเลย", icon_emoji:"☕", action:{type:"uri", uri:"https://shop.line.me/@cafe"}}, ...5 more] }. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| daily-oa-report | Generate a Thai-language summary of today's / last week's LINE OA performance. |
| build-campaign | Wizard for designing a broadcast: audience → Flex → schedule via OA Manager. |
| schedule-broadcast-howto | Explain 3 patterns to schedule a LINE broadcast: OA Manager UI, Cowork Scheduled Tasks, system cron. |
| diagnose-rich-menu | "ทำไม user ไม่เห็นเมนู?" troubleshooter |
| coupon-campaign | Create coupon → broadcast → audience from clicks → measure |
| migrate-from-line-notify | Help user migrate LINE Notify (dead 2025-03-31) to Messaging API push. |
| webhook-setup-guide | Walk through setting up a LINE webhook handler — signature verification, ngrok/cloudflared, common pitfalls. |
| design-rich-menu | Guided flow: brand colors/font/purpose → template + cells → preview image → iterate → deploy with confirmation. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| flex-templates | Thai-localized Flex Message templates with required fields. |
| stickers-catalog | Bundled curated catalog of bot-safe LINE stickers with mood/keyword tags. |
| thai-holidays | Thai public, royal, Buddhist, and cultural holidays with marketing promo patterns. |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/wasintoh/line-oa-mcp-ultimate'
If you have feedback or need assistance with the MCP directory API, please join our Discord server