Tengence GEO Agent
NPM · @TENGENCE/GEO-MCP · SCANNED OCT 4
GEO/SEO content pipeline MCP: plan, write, gate-check, publish, submit, monitor AI visibility.
Available components
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security90
- No malware found by supply-chain analysis.Pass
- CVE check failed: a known high-severity CVE affects @xmldom/xmldom 0.9.10, reached via @tengence/geo-sdk > @rbbtsn0w/wechat-markdown > mathjax-full > speech-rule-engine > @xmldom/xmldom. A fixed version is available. View diagnostics → Fail
- No install/post-install scripts declared.Pass
- 53 of 225 dependencies flagged as unhealthy (3 deprecated). View diagnostics → Partial
Provenance & Transparency97
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Cryptographically verified build provenance (signed, bound to tengence-team/tengence-geo-agent). View diagnostics → Pass
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 1 days ago).Pass
- Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability77
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 7333 tokens (~130/item across 56 items; 56 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management0
- Stability not yet verified: not enough scan history yet (needs a 30-day window).Unverified
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
Tool Safety75
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- 0 of 13 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "check_article" implies "publish" and declares no destructiveHint at all, which the MCP spec reads as destructive by default. See how to fix → Fail
- An AI judge read all 56 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Unverified: 1 category
A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.
How do I install the Tengence GEO Agent MCP server?
Tengence GEO Agent runs locally as an npm package, launched with npx -y @tengence/geo-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
npm · @tengence/geo-mcp
claude mcp add tengence-team-geo -- npx -y @tengence/geo-mcp
{
"mcpServers": {
"tengence-team-geo": {
"command": "npx",
"args": [
"-y",
"@tengence/geo-mcp"
]
}
}
} {
"servers": {
"tengence-team-geo": {
"command": "npx",
"args": [
"-y",
"@tengence/geo-mcp"
]
}
}
} codex mcp add tengence-team-geo -- npx -y @tengence/geo-mcp
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"tengence-team-geo": {
"type": "local",
"command": [
"npx",
"-y",
"@tengence/geo-mcp"
],
"enabled": true
}
}
} openclaw mcp add tengence-team-geo --command npx --arg -y --arg @tengence/geo-mcp
mcp_servers:
tengence-team-geo:
command: "npx"
args: ["-y", "@tengence/geo-mcp"] {
"McpServers": {
"tengence-team-geo": {
"Transport": "stdio",
"Command": "npx",
"Arguments": [
"-y",
"@tengence/geo-mcp"
]
}
}
} assistant mcp add tengence-team-geo -t stdio -c npx -a -y @tengence/geo-mcp
{
"mcpServers": {
"tengence-team-geo": {
"command": "npx",
"args": [
"-y",
"@tengence/geo-mcp"
]
}
}
} Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 28 Sept 26 +15
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 27 Sept 26 62
First indexed and scored.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 4 Oct 2026 · Analysed npm/@tengence/geo-mcp@0.1.1
Provenance Verified
A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.
| Result | Verified |
|---|---|
| Ecosystem | npm |
| Reason | Verified |
| Discovered via | Registry attestation endpoint |
| Source repo | tengence-team/tengence-geo-agent |
| Certificate issuer | https://token.actions.githubusercontent.com |
| Certificate SAN | https://github.com/tengence-team/tengence-geo-agent/.github/workflows/release.yml@refs/tags/v0.1.1 |
| Rekor log index | 2976193043 |
| Predicate type | SLSA build provenance https://slsa.dev/provenance/v1 |
| Subject digest | sha512:5f6f4370bbc7fed8dd3e41500b6885d7a476d0c87e171fd7acc6daad444193f4c95813d042af9590088e629211af1e5dcfece04a2ce6719816981324b |
Background: How many MCP packages publish verified provenance →
Vulnerabilities 13 findings
| ID | CVE | Severity | Vector | Fix available |
|---|---|---|---|---|
| GHSA-27p8-2357-5qqv | CVE-2026-83608 | high | yes | |
| GHSA-3px3-54cx-rmw9 | CVE-2026-83609 | high | yes | |
| GHSA-4w3w-2rp5-g8jm | CVE-2026-83605 | high | yes | |
| GHSA-6gmq-8vp8-gcm6 | CVE-2026-83610 | medium | yes | |
| GHSA-6h8r-xr42-gp59 | CVE-2026-83611 | medium | yes | |
| GHSA-6mj3-qw4j-hgrw | CVE-2026-83612 | high | yes | |
| GHSA-8344-3jmq-59r6 | CVE-2026-83613 | high | yes | |
| GHSA-93r5-fhx6-vmg9 | CVE-2026-83614 | high | yes | |
| GHSA-965w-775f-mr7g | CVE-2026-83615 | high | yes | |
| GHSA-c7q8-3ch8-vqpv | CVE-2026-83616 | high | yes | |
| GHSA-g53g-w8rj-fmg7 | CVE-2026-83606 | high | yes | |
| GHSA-vr34-hp96-76pp | CVE-2026-83618 | high | yes | |
| GHSA-w2rr-34g9-rvrj | CVE-2026-83607 | high | yes |
Background: What a vulnerability scan can and cannot prove →
Dependencies 225 packages
| Packages resolved | 225 |
|---|---|
| Deprecated | 3 |
| Stale | 52 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
article_draft ~161
Assemble a ready-to-use writing brief for a new article: the matched T1–T7 body skeleton, the pre-writing research-brief template, and the full writing standard (base + supplement). The body you author MUST follow this brief; the check_article gate enforces the same G1–G14 editorial gates before publishing. Call this first, then write the Markdown body, then check_article.
| Name | Type | Req | Description |
|---|---|---|---|
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| topic | string | – | working topic / target keyword (echoed into the brief for context) |
| type | string | – | T1–T7 body type: definition|howto|product|case|industry|comparison|guide (default guide) |
No output schema declared.
No examples provided.
article_export ~55
Export an article md + brief from the DB to the site data/inbox (for rewriting)
| Name | Type | Req | Description |
|---|---|---|---|
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| slug | string | yes | article slug |
No output schema declared.
No examples provided.
article_ingest ~106
Content ingest (single entry): body md + research brief → articles table (CLI canonical orchestration)
| Name | Type | Req | Description |
|---|---|---|---|
| lang | string | – | language (defaults to the site default) |
| md_path | string | yes | absolute path to the body Markdown file |
| research_path | string | – | absolute path to the research brief (required by the publish gate) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| slug | string | yes | article slug |
No output schema declared.
No examples provided.
article_list ~68
List articles (articles table), with status/limit filters
| Name | Type | Req | Description |
|---|---|---|---|
| limit | number | – | max rows (default 50) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| status | string | – | draft|queued|published etc. (optional) |
No output schema declared.
No examples provided.
channel_check ~147
Validate a title/body against a platform's style rules — the 校验 (validation) half. Deterministic, no content generation. Returns errors (HARD: title length / forbidden words / body length / removeBlocks) and warnings (SOFT: CTA presence / internal links / keepBlocks) plus the platform checklist and rewrite.strategy. Run AFTER rewriting to confirm it passes before channel_publish. Platform-scoped (wechat / juejin / blog / any registry platform).
| Name | Type | Req | Description |
|---|---|---|---|
| body | string | – | article body (markdown) to validate |
| platform | string | yes | platform key, e.g. wechat / juejin / blog |
| title | string | – | article title to validate |
No output schema declared.
No examples provided.
channel_list ~199
List all external content platforms in the syndicate registry: API type (official|cookie|none), status (ready|pending|manual), capabilities (multi-article merge, per-platform limits, draft/cover/tags) and the full platform rewrite rules (styles). The rewrite rules are the HARNESS rewriting guide — the server never rewrites content: read the original via article_export, apply these rules yourself, then channel_publish to land the draft/export. READY PLATFORMS: wechat (微信公众号, official API), juejin (掘金, cookie — can publish article drafts) and csdn (CSDN, cookie — the creator-console gateway; needs CSDN_COOKIE before status becomes ready). To publish to Juejin/CSDN pass platform="juejin"/"csdn" to channel_publish / channel_plan_*; this server is multi-channel.
| Name | Type | Req | Description |
|---|---|---|---|
| platform | string | – | filter to one platform key |
No output schema declared.
No examples provided.
channel_plan_mark ~112
Update a channel_plan row status (todo | draft | published | paused) and optionally record its draft ids (media ids). Call after channel_publish to persist the created draft (e.g. wechat media_id) and keep the calendar in sync.
| Name | Type | Req | Description |
|---|---|---|---|
| draftIds | array | – | draft/media ids to record (e.g. wechat media_id); omit to keep existing |
| id | number | yes | channel_plan row id (see channel_plan_next rows) |
| status | string | yes | new row status |
No output schema declared.
No examples provided.
channel_plan_next ~233
Per-platform publishing calendar: return the next article to publish for a platform plus all calendar rows (status/period/topic/weekday/slugs). Each platform has its OWN rows in the same channel_plan table. wechat keeps a real per-issue calendar (returns the earliest row still todo). juejin / csdn (and other api platforms) treat the table as a PUBLISH LOG — nextDue is DERIVED from the blog article_plan: it returns the next blog-published article (by publish_order) that is NOT yet recorded as published on THAT platform, so each platform's queue follows the blog order and resumes right after the last article published to it (failed rows retry). Nothing is ever bulk-copied from the blog plan: only real outcomes are recorded, so juejin and csdn each keep their own independent calendar in the shared table. Seed already-published articles with channel_plan_reconcile (platform=csdn) before the first nextDue, otherwise the csdn queue starts from the very first blog article.
| Name | Type | Req | Description |
|---|---|---|---|
| platform | string | – | filter rows to one platform (default: all platforms) |
No output schema declared.
No examples provided.
channel_plan_reconcile ~206
Reconcile a platform channel_plan with what is ACTUALLY published on that platform (platform=juejin | csdn). This SEEDS the publish log with already-published articles — we do NOT bulk-import the blog plan (the table only logs real outcomes, so each platform keeps its own calendar). Pass map[] of {slug, title?, blogOrder?} for the explicitly-known published articles (recommended — avoids API rate limits), or omit map to live-read the platform published list and match titles back to blog slugs. Idempotent (upsert by slug). Run this once per platform before the first channel_plan_next so the already-published articles are skipped instead of re-published.
| Name | Type | Req | Description |
|---|---|---|---|
| map | array | – | explicit known published articles; omit to live-read the platform |
| platform | string | yes | platform key, e.g. juejin or csdn |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
channel_publish ~561
Publish/export to one external platform. Mode A: pass slugs[] and the server reads the DB and runs the platform pipeline (wechat drafts box — preview in mp.weixin.qq.com before mass-sending; juejin draft → publish; csdn draft → publish; devto publish). Mode B: pass pre-written articles[] ({slug,title,contentMd,summary,tags,sourceUrl,cover}) — the harness-rewritten draft — and the server exports a publish package to <site>/data/channel-export/<platform>/<slug>.md with full front matter (manual publishing on every platform; required for api:none platforms). asDraft defaults true (never mass-sends). PLATFORMS: wechat, juejin (cookie — 原文直发 via juejin draft), csdn (cookie — 通过创作中心网关一步发文), devto. Juejin pipeline: reads DB article → resolves category/tags against the cached platform dictionary (channel_taxonomy; our article_plan.category/tags → the platform's category_id/tag_ids — see channel_taxonomy_resolve) → creates draft → writes body → publishes; dryRun=true previews the plan AND the resolved taxonomy with no external calls; idempotent — skips a slug already on Juejin (draft or published). Category and tag are both required by Juejin, so a fallback chain (alias → dictionary → env → dictionary default) guarantees both are always sent. CSDN pipeline: reads DB article → Markdown is converted to CSDN HTML locally (CSDN does NOT convert server-side) → one saveArticle call (status 2=draft / 0=publish); tags come from article_plan.tags else target_keywords (1~5 required to publish). Idempotent through the SAME slug-based dedup as juejin. Every publish outcome is logged to channel_plan under its own platform, so each platform keeps an INDEPENDENT publishing calendar (only real outcomes are recorded — the blog plan is never bulk-imported). This server is multi-channel; choose by platform=.
| Name | Type | Req | Description |
|---|---|---|---|
| articles | array | – | Mode B: pre-written (harness-rewritten) articles to export as publish packages |
| asDraft | boolean | – | default true: create draft (wechat/juejin), never mass-send |
| dryRun | boolean | – | print the plan, no external calls |
| keepOrder | boolean | – | wechat only: keep slugs order (1st = headline) |
| platform | string | yes | platform key (see channel_list) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| slugs | array | – | Mode A: article slugs to publish through the platform pipeline |
No output schema declared.
No examples provided.
channel_style_get ~148
Return the FULL platform style / rewrite rules for ONE platform (wechat / juejin / blog / …). This is the RULES half of the rewrite surface: the server only serves the rules, the harness/Skill does the actual rewriting. Covers rewrite.strategy (source|title|body|both — what to change), title hooks + forbidden words, body structure + style, internalLinks requirement, cta and the acceptance checklist. ALWAYS call this BEFORE rewriting an article for a platform so the latest rules are used (never hardcode rules in the client). Multi-channel: pick by platform=.
| Name | Type | Req | Description |
|---|---|---|---|
| platform | string | yes | platform key, e.g. wechat / juejin / blog |
No output schema declared.
No examples provided.
channel_taxonomy_list ~189
Read the cached external-platform taxonomy dictionary (channel_taxonomy) — the platform's OWN categories and tags with their ids. Filter by kind (category|tag); look one up exactly with name=, or by prefix with prefix= (prefix lookups use the NOCASE index; infix/contains search is NOT index-accelerated, so do it client-side over this list). Use it to see which platform tags exist before choosing an alias.
| Name | Type | Req | Description |
|---|---|---|---|
| kind | string | – | category | tag (omit for both) |
| limit | number | – | max rows (default 100) |
| name | string | – | exact name lookup (case-insensitive) |
| platform | string | – | platform key (default juejin) |
| prefix | string | – | name prefix lookup, e.g. "搜索" |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
channel_taxonomy_resolve ~178
Preview how OUR taxonomy maps onto a platform's (article_plan.category/tags → platform category_id/tag_ids) WITHOUT publishing. Returns the chosen ids/names plus a per-item origin showing which fallback layer fired (alias / exact / token:<kw> / fuzzy / default / env / first / hardcoded). Use it to sanity-check a mapping before a real publish; it never makes external calls and never writes.
| Name | Type | Req | Description |
|---|---|---|---|
| category | string | – | our category slug, e.g. geo-ai-search |
| keywords | array | – | extra keywords (article target_keywords) |
| platform | string | – | platform key (default juejin) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| tags | array | – | our tag slugs, e.g. ["geo-seo","search-system"] |
No output schema declared.
No examples provided.
channel_taxonomy_sync ~218
Refresh the cached dictionary of an EXTERNAL platform's own taxonomy (category + tag id/name) into the workspace table channel_taxonomy. Currently juejin: 8 categories + ~725 tags fetched from the platform APIs. The dictionary is PLATFORM-scoped, shared by every site — a site publishing to Juejin needs NO mapping file of its own. It is used to map our article_plan category/tags onto the platform's category_id/tag_ids at publish time. Idempotent (upsert by platform id); publish auto-runs this once when the dictionary is empty, so calling it manually is only needed to refresh after a platform word-list change. Names are indexed for exact/prefix lookup (infix search runs in memory). Requires JUEJIN_COOKIE in the site .env. Read-only on the platform — it fetches lists, it does not publish.
| Name | Type | Req | Description |
|---|---|---|---|
| platform | string | – | platform key (default juejin) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
check_article ~140
Publish gate: enforces the editorial rules codified in the "article-writing-standards" standard (citation dual-channel, word count by T1–T7 type, banned words, the three GEO blocks — Summary / Key Takeaways / FAQ / Data Sources — and the research-brief hard check). Read that standard via standards_read before authoring, and run article_draft first to scaffold per-spec.
| Name | Type | Req | Description |
|---|---|---|---|
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| slug | string | yes | article slug |
| type | string | – | T1..T7 (hard word-count check by type when declared) |
No output schema declared.
No examples provided.
csdn_article_delete ~174
Delete a CSDN article (blog/phoenix/console/v1/article/del). IRREVERSIBLE — pass confirm=true only after verifying the article id via csdn_status. Requires CSDN_COOKIE in the site .env. NOTE: this removes it from CSDN only; the local channel_plan publish log (the CSDN publishing calendar) is not touched — re-run channel_plan_reconcile(platform=csdn) afterwards if you want the log back in sync.
| Name | Type | Req | Description |
|---|---|---|---|
| articleId | string | yes | article id from csdn_status items[].id |
| confirm | boolean | yes | must be true to actually delete |
| deep | boolean | – | also purge from the recycle bin (default false) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
csdn_status ~180
Read the CSDN blog backend for this site: the draft box and the published list (blog/phoenix/console/v1/article/list with status=draft / all_v2). Read-only. Requires CSDN_COOKIE in the site .env. Use it to verify before publishing (idempotency) and to see what is already on CSDN. page is 1-based (default 1). An expired login is surfaced as cookieExpired=true + code 401 instead of an empty list — renew CSDN_COOKIE then. This is the CSDN counterpart of juejin_status.
| Name | Type | Req | Description |
|---|---|---|---|
| page | number | – | 1-based page index (default 1) |
| pageSize | number | – | page size (default 20) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
db_init ~62
Explicitly initialize the database (sqlite idempotent table creation / mysql DDL; --drop rebuilds)
| Name | Type | Req | Description |
|---|---|---|---|
| drop | boolean | – | drop and rebuild (dangerous) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
db_status ~43
Database status: driver, path, schema version, table list, missing tables
| Name | Type | Req | Description |
|---|---|---|---|
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
diagnose_site ~174
Full GEO/SEO site diagnosis: domain (DNS/TLS cert/WHOIS), transport & server fingerprint (CMS/framework/platform/CDN), robots.txt, sitemap, homepage + representative pages (meta, H1..H6 structure, JSON-LD, OG, images/alt, links, mixed content), performance and security checks. Bootstraps the site on first use (url → site key, dots → underscores).
| Name | Type | Req | Description |
|---|---|---|---|
| max_pages | integer | – | max representative pages to sample (default 4; the site is sampled, never fully crawled) |
| pages | array | – | extra page URLs to diagnose in addition to the homepage |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| url | string | yes | site URL, e.g. https://www.example.com |
No output schema declared.
No examples provided.
image_acquire ~98
Auto image pipeline (search → red-line filter → download → WebP crop → upload to WP media library)
| Name | Type | Req | Description |
|---|---|---|---|
| count | number | – | count (default 3) |
| dry_run | boolean | – | preview only, nothing persisted |
| query | string | yes | image search keyword |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| slug | string | yes | target article slug (for registration) |
No output schema declared.
No examples provided.
juejin_article_delete ~107
Delete a published Juejin article (article/delete). IRREVERSIBLE — pass confirm=true only after verifying the article id via juejin_status. Requires JUEJIN_COOKIE + JUEJIN_UID in the site .env.
| Name | Type | Req | Description |
|---|---|---|---|
| articleId | string | yes | article id from juejin_status published[].id |
| confirm | boolean | yes | must be true to actually delete |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
juejin_draft_delete ~109
Delete a Juejin draft (article_draft/delete). IRREVERSIBLE — pass confirm=true only after verifying the draft id via juejin_status. Requires JUEJIN_COOKIE + JUEJIN_UID in the site .env.
| Name | Type | Req | Description |
|---|---|---|---|
| confirm | boolean | yes | must be true to actually delete |
| draftId | string | yes | draft id from juejin_status drafts[].id |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
juejin_status ~130
Read the Juejin (掘金) backend for this site: the draft box (article_draft/list_by_user) and the published list (article/list_by_user). Read-only. Requires JUEJIN_COOKIE + JUEJIN_UID in the site .env. Use it to verify before publishing (idempotency) and to see what is already on Juejin. page defaults to 0 (50 per page).
| Name | Type | Req | Description |
|---|---|---|---|
| page | number | – | page index (default 0) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
monitor_report ~53
Read monitoring results (latest round or a given run_id)
| Name | Type | Req | Description |
|---|---|---|---|
| run_id | string | – | YYYYMMDD (default latest) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
monitor_run ~77
Run GEO monitoring (one round of site prompts × models; results persisted)
| Name | Type | Req | Description |
|---|---|---|---|
| layers | array | – | subset of layers |
| models | array | – | subset of model keys |
| run_id | string | – | YYYYMMDD (default today) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
plan_import ~63
Import/update the plan table from the site plan directory (idempotent)
| Name | Type | Req | Description |
|---|---|---|---|
| file | string | – | absolute path to a plan file (default: scan the site plan directory) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
plan_list ~75
Article plan table list (status/batch/category/node filters)
| Name | Type | Req | Description |
|---|---|---|---|
| batch | string | – | batch |
| limit | number | – | max rows (default 100) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| status | string | – | todo|written|queued|published etc. |
No output schema declared.
No examples provided.
plan_mark_status ~63
Update a plan row status (todo/written/queued/published/archived)
| Name | Type | Req | Description |
|---|---|---|---|
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| slug | string | yes | article slug |
| status | string | yes | target status |
No output schema declared.
No examples provided.
publish_daily ~109
Run the daily promotion task (promotes due drafts to publish by plan publish_order; default 1/day). Optional date sets the promoted article publish/modified time (YYYY-MM-DDTHH:MM:SS, site timezone).
| Name | Type | Req | Description |
|---|---|---|---|
| date | string | – | publish/modified time for the promoted article, YYYY-MM-DDTHH:MM:SS in the site timezone; omit to leave WordPress untouched |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
publish_draft ~77
Publish a draft (default draft → WP; can --status=publish directly, must pass the gate first)
| Name | Type | Req | Description |
|---|---|---|---|
| md_path | string | yes | absolute path to the body Markdown |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| status | string | – | draft|publish (default draft) |
No output schema declared.
No examples provided.
publish_from_db ~80
Publish an article from the DB to WordPress (--force updates an existing article)
| Name | Type | Req | Description |
|---|---|---|---|
| article_id | number | yes | articles.id |
| force | boolean | – | force-update when it already exists |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| status | string | – | draft|publish (default draft) |
No output schema declared.
No examples provided.
publish_update_article ~250
Bypass update of an existing article (title/content/status + sync SEO/GEO meta). When meta_title / meta_description / post_title is provided, runs meta-only mode: updates ONLY those fields (meta_title → DB seo.title + WP seo_meta_title; meta_description → DB seo.meta_description + WP seo_meta_description, 165–175 chars hard gate; post_title → DB title + WP post_title itself); body/content/status/excerpt untouched.
| Name | Type | Req | Description |
|---|---|---|---|
| md_path | string | – | absolute path to the body Markdown (required for full update; omit in meta-only mode) |
| meta_description | string | – | new meta_description (165–175 characters). Providing it switches to meta-only mode |
| meta_title | string | – | new SEO title (≤200 characters). Providing it switches to meta-only mode |
| post_id | number | – | target WP post id (either slug or post_id) |
| post_title | string | – | new WordPress post title itself (≤200 characters, also updates DB title column). Providing it switches to meta-only mode |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| slug | string | – | target slug |
No output schema declared.
No examples provided.
report_write ~98
Write a Markdown report into the site data/reports/ directory (path-safe: filename is basenamed and confined to the reports dir). Auto-bootstraps the site on first use.
| Name | Type | Req | Description |
|---|---|---|---|
| content | string | yes | Markdown report content |
| filename | string | – | report filename (default <YYYYMMDD>-<site>-diagnosis.md) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
search_gsc_inspect ~110
Query one URL's Google indexing status (URL Inspection API, read-only): verdict, coverageState, indexingState, lastCrawlTime, googleCanonical. Use it to check whether a specific article page is indexed. Quota: 2000 calls/day.
| Name | Type | Req | Description |
|---|---|---|---|
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| url | string | yes | fully-qualified URL to inspect, e.g. https://www.tengence.com/blog/article/<slug>/ |
No output schema declared.
No examples provided.
search_gsc_stats ~241
Read Google Search Console Search Analytics data: clicks / impressions / CTR / average position, grouped by query (default), page, date, country or device. This is the ONLY Google source for search performance — and the only source at all for page-level data (Bing dropped its page/traffic endpoints on 2026-08-31). GSC data is finalised 2–3 days late: the default window is the 28 days ending 3 days ago. Requires the GSC service account (secrets/gsc-service-account.json or GOOGLE_SA_JSON).
| Name | Type | Req | Description |
|---|---|---|---|
| dimensions | array | – | group-by dimensions; default ["query"]. Use ["page"] for per-URL clicks/impressions, ["date"] for a daily trend, ["query","page"] for both. |
| end_date | string | – | YYYY-MM-DD (default: 3 days ago) |
| row_limit | number | – | max rows to return (default 100) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| start_date | string | – | YYYY-MM-DD (default: 27 days before end_date) |
No output schema declared.
No examples provided.
search_submit_baidu ~178
Submit URLs to Baidu normal inclusion (requires BAIDU_TOKEN / BAIDU_SITE). Two modes: pass url for an explicit list, or all=true to push the sitemap incrementally — it recursively flattens sitemap_index.xml, skips every URL already logged as submitted in data/baidu-log.jsonl, and pushes at most limit URLs (default 10) so a scheduled run stays inside the daily quota.
| Name | Type | Req | Description |
|---|---|---|---|
| all | boolean | – | sitemap incremental mode: push only URLs not yet logged as submitted |
| limit | number | – | max URLs to push when all=true (default 10) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| url | string | – | URLs to submit (multiple allowed, comma-separated, ≤2000 per call); omit when all=true |
No output schema declared.
No examples provided.
search_submit_gsc ~56
Submit the sitemap to Google Search Console (soft-fail)
| Name | Type | Req | Description |
|---|---|---|---|
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| sitemap_url | string | – | sitemap URL (default: auto-derived) |
No output schema declared.
No examples provided.
search_submit_indexnow ~56
Submit URLs to IndexNow (requires INDEXNOW_KEY)
| Name | Type | Req | Description |
|---|---|---|---|
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| url | string | yes | URLs to submit (multiple allowed, comma-separated) |
No output schema declared.
No examples provided.
site_init ~102
Scaffold a site inside the bound workspace: <workspace>/<key>/{config,data/inbox,data/reports,.env} (idempotent, never overwrites existing files)
| Name | Type | Req | Description |
|---|---|---|---|
| domain | string | – | canonical domain, defaults to the key |
| key | string | yes | site key (lowercase letters, digits, underscore) |
| lang | string | – | default language (default zh-CN) |
| name | string | – | display name, defaults to the domain |
No output schema declared.
No examples provided.
site_list ~39
List the sites inside the bound user workspace (site key, domain, app_id, storage driver). Returns a hint instead when no workspace is bound yet.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
site_status ~44
Site status: config paths, .env readiness, DB driver and SQLite init state
| Name | Type | Req | Description |
|---|---|---|---|
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
standards_list ~51
List the generic writing & GEO standards shipped with the engine (titles, whether a site-specific supplement exists). Read one with standards_read before authoring an article; see article_draft for a ready-to-use brief.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
standards_read ~100
Read a generic standard document (base + any site-specific supplement merged). Names are repository-relative without `.md`, e.g. "article-writing-standards", "content-strategy", "block-conventions", "templates/skeletons/howto", "templates/research-brief". This is the canonical way to pull the requirements an article must satisfy.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | standard name without .md, e.g. article-writing-standards |
No output schema declared.
No examples provided.
util_ping ~27
Connectivity self-check: SDK version, driver, internal data directory, bound workspace and site count
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
webmaster_bing_status ~109
Read Bing Webmaster console data (verified sites / URL submission quota / query stats / crawl issues). Requires BING_WEBMASTER_API_KEY in the site .env. Note: Bing trimmed its JSON API on 2026-08-31 (GetPages/GetSitemaps/GetTrafficStats/GetUrlSubmissionStatus now 404).
| Name | Type | Req | Description |
|---|---|---|---|
| action | string | yes | what to read from the Bing Webmaster console |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
webmaster_bing_submit ~81
Write to Bing Webmaster: submit URL(s) (comma-separated = batch, ≤10000 per call). Requires BING_WEBMASTER_API_KEY in the site .env.
| Name | Type | Req | Description |
|---|---|---|---|
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| url | string | yes | URL(s) to submit; multiple allowed, comma-separated |
No output schema declared.
No examples provided.
wechat_article_delete ~156
Delete a published article (freepublish/delete, article_id from wechat_status published). IRREVERSIBLE — verify the article_id first; index (1-based) deletes one article of a multi-article message, omit to delete the whole message.
| Name | Type | Req | Description |
|---|---|---|---|
| article_id | string | yes | published article_id (see wechat_status published) |
| confirm | string | – | must be "YES" to actually delete (irreversible); not needed for dryRun |
| dryRun | boolean | – | print the payload, do not delete |
| index | number | – | 1-based position within the message; omit to delete the whole message |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
wechat_draft_publish ~129
Publish a draft box media_id to the account homepage via freepublish/submit (NO push to followers — the draft is consumed and moves to the published list, where it is visible in the account homepage). Use for the "发布" step; mass push (推送粉丝) is a separate tool wechat_mass_send.
| Name | Type | Req | Description |
|---|---|---|---|
| dryRun | boolean | – | print the payload, do not publish |
| media_id | string | yes | draft box media_id (see wechat_status drafts) |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
No output schema declared.
No examples provided.
wechat_mass_preview ~146
Send a draft (media_id from the draft box) to one user as a preview (message/mass/preview). Requires a verified account; pass openid (touser) or wxname (towxname). Use this to check layout before mass-sending.
| Name | Type | Req | Description |
|---|---|---|---|
| dryRun | boolean | – | print the payload, do not send |
| media_id | string | yes | draft box media_id (see wechat_status drafts) |
| openid | string | – | receiver openid |
| site | string | – | site key; auto-selected when the workspace holds exactly one site |
| wxname | string | – | receiver wxname (user must have interacted with the account) |
No output schema declared.
No examples provided.
What is the Tengence GEO Agent MCP server?
Tengence GEO Agent is an MCP server listed in the public MCP registry as io.github.tengence-team/geo. GEO/SEO content pipeline MCP: plan, write, gate-check, publish, submit, monitor AI visibility. This page covers its npm package (@tengence/geo-mcp).
Is the Tengence GEO Agent MCP server safe to use?
Tengence GEO Agent scores 77 out of 100 on VerifyMCP. We recorded 13 known advisories against it as of 4 October 2026. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Tengence GEO Agent MCP server expose?
Tengence GEO Agent exposes 56 tools: workspace_use, site_init, site_list, site_status, article_list, and 51 more. Their descriptions and schemas cost roughly 7,333 tokens of context every time the server is loaded.
Is the Tengence GEO Agent MCP server still maintained?
Tengence GEO Agent is still listed as active in the MCP registry. We last reached this channel on 4 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the Tengence GEO Agent MCP server under?
Tengence GEO Agent declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.