Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

Analytics Legends — SAP Analytics Intelligence

REMOTE · ANALYTICSLEGENDS.AI · SCANNED SEP 20

AI agent for SAP analytics: firms, day rates, contract radar, news, concepts, studies

0 this week 83 Trust /100
Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →

Endpoint Security69
Transport & Reachability100
Schema Quality & AI Usability74
  • 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 9917 tokens (~431/item across 23 items; 20 tools + 3 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 Management100
  • No destabilizing schema changes in the last 30 days.Pass
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
  • Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • We read all 20 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
  • An AI judge read all 22 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a current MCP spec version (2026-07-28).Pass
Install

How do I install the Analytics Legends — SAP Analytics Intelligence MCP server?

Analytics Legends — SAP Analytics Intelligence is a hosted endpoint at https://analyticslegends.ai/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

remote · analyticslegends.ai

# add to Claude Code
claude mcp add --transport http ai-analyticslegends-sap-analytics 'https://analyticslegends.ai/mcp'
// .cursor/mcp.json
{
  "mcpServers": {
    "ai-analyticslegends-sap-analytics": {
      "url": "https://analyticslegends.ai/mcp"
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "ai-analyticslegends-sap-analytics": {
      "type": "http",
      "url": "https://analyticslegends.ai/mcp"
    }
  }
}
# ~/.codex/config.toml
[mcp_servers.ai-analyticslegends-sap-analytics]
url = "https://analyticslegends.ai/mcp"
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ai-analyticslegends-sap-analytics": {
      "type": "remote",
      "url": "https://analyticslegends.ai/mcp",
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add ai-analyticslegends-sap-analytics --url 'https://analyticslegends.ai/mcp' --transport streamable-http
# ~/.hermes/config.yaml
mcp_servers:
  ai-analyticslegends-sap-analytics:
    url: "https://analyticslegends.ai/mcp"
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "ai-analyticslegends-sap-analytics": {
      "Transport": "http",
      "Url": "https://analyticslegends.ai/mcp"
    }
  }
}
# add to Vellum
assistant mcp add ai-analyticslegends-sap-analytics -t streamable-http -u 'https://analyticslegends.ai/mcp'
// mcp.json
{
  "mcpServers": {
    "ai-analyticslegends-sap-analytics": {
      "type": "http",
      "url": "https://analyticslegends.ai/mcp"
    }
  }
}

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

Changelog

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.

  • 20 Sept 26 0
    • Tool “get_concept” rewrote its description, which is the text the model reads security
    • Tool “get_concept_card” rewrote its description, which is the text the model reads security
    • Tool “search_concepts” rewrote its description, which is the text the model reads security
  • 17 Sept 26 0
    • Tool “get_day_rate_benchmark” rewrote its description, which is the text the model reads security
  • 9 Sept 26 0
    • Tool “get_academy_module” rewrote its description, which is the text the model reads security
    • Tool “get_concept_card” rewrote its description, which is the text the model reads security
  • 8 Sept 26 0
    • Tool “get_firm_intel” rewrote its description, which is the text the model reads security
    • Tool “list_studies” rewrote its description, which is the text the model reads security
    • Tool “query_knowledge_graph” rewrote its description, which is the text the model reads security
    • “list_studies” reworded the description of “lang” cosmetic
  • 5 Sept 26 +8
    • Judged manipulation: unverified → pass security
    • Schema quality: unverified → excellent functional
    • “find_opportunities” added an optional parameter “lang” cosmetic
  • 4 Sept 26 −8
    • Judged manipulation: pass → unverified security
    • Schema quality: excellent → unverified functional
    • “query_knowledge_graph” added an optional parameter “lang” cosmetic
    • “query_knowledge_graph” reworded the description of “query” cosmetic
  • 29 Aug 26 0
    • Stability: 0.97 → pass security
    • Tool “find_opportunities” rewrote its description, which is the text the model reads security
    • “find_opportunities” reworded the description of “country” cosmetic
    • “find_opportunities” reworded the description of “employment_type” cosmetic
  • 28 Aug 26 +1
    • Tool “get_day_rate_benchmark” rewrote its description, which is the text the model reads security
    • Tool “search_concepts” rewrote its description, which is the text the model reads security
    • “find_opportunities” reworded the description of “employment_type” cosmetic
    • “query_knowledge_graph” reworded the description of “edge_type” cosmetic
Diagnostics

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 20 Sept 2026 · Probed https://analyticslegends.ai/mcp

TLS valid

Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .

Subject Issuer Valid from Valid until Key Signature Serial
CN=analyticslegends.ai CN=WE1,O=Google Trust Services,C=US 30 Jul 2026 28 Oct 2026 ECDSA 256 ECDSA-SHA256 667b836ff5bc74df13613838a9827d4e
SANs: analyticslegends.ai, *.analyticslegends.ai
CN=WE1,O=Google Trust Services,C=US (CA) CN=GTS Root R4,O=Google Trust Services LLC,C=US 13 Dec 2023 20 Feb 2029 ECDSA 256 ECDSA-SHA384 7ff31977972c224a76155d13b6d685e3
CN=GTS Root R4,O=Google Trust Services LLC,C=US (CA) CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE 15 Nov 2023 28 Jan 2028 ECDSA 384 SHA256-RSA 7fe530bf331343bedd821610493d8a1b

Background: What to check on a remote MCP endpoint →

DNSSEC insecure

Validation of analyticslegends.ai. Not signed

Zone DS Keys Algorithms Outcome
. trust_anchor 20326, 38696 8, 8 Verified
ai. present 3799 8 Verified
analyticslegends.ai. absent Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation
Authentication No authorisation required

The endpoint answered without asking for a token. Anyone who knows the URL can reach it.

Result No authorisation required
HTTP status 200
Header Value
strict-transport-security max-age=31536000; includeSubDomains; preload
x-content-type-options nosniff
x-frame-options DENY
referrer-policy strict-origin-when-cross-origin
permissions-policy camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()

Background: How OAuth 2.1 works in the 2026 MCP spec →

Transports 2 probes
Transport URL Outcome Status Location
streamable-http https://analyticslegends.ai/mcp Verified 200
http (plaintext) http://analyticslegends.ai/mcp Inconclusive 405
MCP tools · 20 exposed · ~8,775 tokens

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 →

Tool Tokens
count_firms_by ~378

Answer a COUNTING question about the published firm directory in one call: how many organisations per country, per kind, per declared SAP module, or per SAP signal band — with the same `country`/`kind`/`module`/`query` filters `search_firms` takes, so you can count a slice as easily as the whole. Use this instead of paging `search_firms` and tallying rows: the directory holds thousands of organisations, and reading them all to produce a table of counts costs hundreds of calls and megabytes of rows for numbers Postgres computes in one scan. Every bucket is a value the directory actually stores; `value: null` is a real bucket meaning the field is unknown for those rows, and it is served rather than hidden — a country table that silently drops the rows with no country adds up to less than the population and says nothing about it.

NameTypeReqDescription
bystringyesWhich facet to count on. Required — there is no default worth guessing.
countrystringISO-3166-1 alpha-2 country code, e.g. DE, FR, CH.
kindstringRestrict to one organisation kind before counting, same vocabulary as search_firms. Combining it with `by:"kind"` is legal and returns that single bucket.
modulestringRestrict to organisations with a DECLARED link to one SAP module code before counting, same vocabulary as search_firms' `module`. Combining it with `by:"module"` is legal and returns that single buck…
querystringFree-text filter, case-insensitive. EVERY word must appear in the record (substring per word, any order), so a natural-language phrase narrows the answer instead of having to match verbatim.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

find_academy_modules ~686

Search the Analytics Legends Academy — the written training modules on SAP Datasphere, Business Data Cloud, SAP Analytics Cloud, BW/4HANA and Databricks — by track, level and free text. `_meta.tranche_total_row_count` carries the live catalogue size on every call; it is the only count to quote. Returns the catalogue entry: id, slug, EN/FR title, track, level, duration in minutes, tags and the editor's summary. DO NOT CONFUSE IT WITH `list_sap_modules`, which serves a different population under the same word: that one is the 40-row PRODUCT taxonomy (codes such as SAC, DATASPHERE) used to normalise product wording. This one is the course catalogue. Without `query`, rows come back in the catalogue's own CURRICULUM order — the order a reader is meant to take them in — track by track. This catalogue is written training, NOT SAP certification tracks: this server publishes no certification data at any tier, so a certification question has no answer here rather than a partial one. CATALOGUE ONLY — the module BODY is subscriber content, served by `get_academy_module` on this same endpoint with a subscriber key (Consultant tier or above), which is the same door the €29.90 Consultant Pass opens on the site. On THIS endpoint the machine-access subscription is the MCP Pass (€39.90/month, analyticslegends.ai/pricing/), which opens the ENTIRE paid tranche from one key; the €29.90 Consultant Pass is its web-subscriber equivalent and opens the same tier floor here. `status` and `is_preview` are SERVED, never filtered on: they are the two flags the platform marks free access with, they do not coincide (measured 2026-08-16: 38 rows `status='available'`, 56 rows `is_preview`), and you decide which one your answer needs. PAGINATED: pass `_meta.next_cursor` back as `cursor` with the same filters until it is null. Read `_meta.available_tracks` and `_meta.available_levels` — both counted on the served population at call time — before assuming a facet value exists.

NameTypeReqDescription
cursorstringOpaque token from a previous response's `_meta.next_cursor`. Pass it back with the SAME filter arguments; `null` means the last page. Changing a filter refuses the cursor.
levelstringRestrict to one level, matched case-insensitively: Beginner · Intermediate · Advanced · Expert. Counts in `_meta.available_levels`.
limitintegerMax rows (hard cap 50).
querystringFree-text filter, case-insensitive. EVERY word must appear in the record (substring per word, any order), so a natural-language phrase narrows the answer instead of having to match verbatim.
trackstringRestrict to one track, by SLUG (`databricks-data-eng`) or by English name (`Databricks & Data Eng.`), matched case-insensitively. The live vocabulary with per-track counts is `_meta.available_tracks`…
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

find_opportunities ~1,525

Search every SAP contract and permanent-role posting Analytics Legends publishes to an ANONYMOUS visitor — the same population a human browses on /opportunities/, where each posting has its own prerendered page. It merges the platform's TWO public legs, which are near-disjoint (measured 2026-07-30: 1 row in common): (a) the PROMOTED feed (`public.public_opportunities`) — general SAP work (FI/CO, SD, EWM, MDG, BTP, ABAP), all German cities, dated (posted_at is populated on EVERY active row of that leg — an invariant held since 2026-07-31, not a snapshot). 🔴 THIS LEG CHANGED SHAPE ON 2026-08-28: until then it was fed by three keyless APIs and carried no contract_type, country_code, expires_at or rate at all; it was then loaded from the site radar and now declares contract_type and country_code on most of its rows, an expiry on most, and an advertised rate on a small minority. Do NOT assume a field is null on this leg — read the `_meta` counters on YOUR OWN response, which are computed at query time; (b) the SITE RADAR (`/api/contracts-lean.json`) — these carry country, category, seniority, posted_at, `employment_type` and, on most of them, `expires_at`; they are the analytics-specific ones (SAC Planning, Datasphere Technical Lead, Business Data Cloud). READ `employment_type` BEFORE CALLING THIS A CONTRACT MARKET: the radar is mostly PERMANENT roles, so an unfiltered page answers a freelance question with salaried jobs unless you filter. The argument of the same name does the filtering, and `_meta.tranche_total_row_count` on your own response is the live population — read the split from a filtered call, never from a figure quoted in this text. TWO DIFFERENT RATE FIELDS, AND THEY MEAN DIFFERENT THINGS. `currency` / `daily_rate_min` / `daily_rate_max` are the posting's OWN advertised rate and are almost always null — most listings publish no rate at all. `rate_band` is the platform's editorial benchmark for that posting's (seniority × product × region) cell, present on…

NameTypeReqDescription
countrystringISO-3166-1 alpha-2 code, applied to both legs as a predicate on the row's own country_code. It NO LONGER selects the site-radar leg alone: the promoted feed carried country_code on almost none of its…
cursorstringOpaque token from a previous response's `_meta.next_cursor`. Pass it back with the SAME filter arguments; `null` means the last page. Changing a filter refuses the cursor.
employment_typestringRestrict to one engagement type. THE RADAR IS MOSTLY PERMANENT, so a freelance or contract question answered off an unfiltered page is answered with salaried jobs. For the actual split, make the filt…
langstringReading language for the TITLE — 'EN' (default), 'FR' or 'DE'. This is a RENDERING choice, never a filter: it changes which string `title` carries, never which rows come back. Read `title_lang` on ev…
limitintegerMax rows (hard cap 50).
locationstringCity or place, matched case-insensitively as a substring of the posting's location. The promoted leg is all-German (Hamburg, Frankfurt am Main, Bremen, Munich, Cologne, Dortmund, Hanover, Landshut, M…
querystringFree-text filter, case-insensitive. EVERY word must appear in the record (substring per word, any order), so a natural-language phrase narrows the answer instead of having to match verbatim.
remote_modestringRestrict to one work-location policy: `remote`, `hybrid` or `onsite`. READ THIS BEFORE ANSWERING A REMOTE QUESTION: a large share of the radar declares no policy at all (`_meta.remote_mode_undeclared…
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

find_sap_clients ~374

Search the SAP END-CUSTOMER corpus — the companies that RUN SAP, not the firms that sell services (those are search_firms). This is the paid Legend+ dataset locked away from the public surface on 2026-07-08; it requires a subscriber API key, Legend tier or above. Verification status is SERVED, never silently filtered: `sap_client_verification_status` and `status` are columns on every row ('verified' on ~550 of ~21k rows), and you decide what standard of proof your answer needs. `product` filters on the detected-adoption flags every profile already carries (the `uses_*` columns get_sap_client_profile serves): it keeps only rows where that product was DETECTED. A row it drops is 'not detected by our detection pass', never 'does not use it' — detection is a positive signal with no negative counterpart.

NameTypeReqDescription
countrystringISO-3166-1 alpha-2 country code, e.g. DE, FR, CH.
cursorstringOpaque token from a previous response's `_meta.next_cursor`. Pass it back with the SAME filter arguments; `null` means the last page. Changing a filter refuses the cursor.
industrystringIndustry or sector filter, matched case-insensitively.
limitintegerMax rows (hard cap 50).
productstringKeep only end-customers where this SAP product was DETECTED in use. Absence from the result means undetected, not unused.
querystringFree-text filter, case-insensitive. EVERY word must appear in the record (substring per word, any order), so a natural-language phrase narrows the answer instead of having to match verbatim.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

get_academy_module ~290

Read one Academy training module in full — body, learning objectives and summary, EN, FR and DE — the written course corpus the €29.90 Consultant Pass sells. On THIS endpoint the machine-access subscription is the MCP Pass (€39.90/month, analyticslegends.ai/pricing/), which opens the ENTIRE paid tranche from one key; the €29.90 Consultant Pass is its web-subscriber equivalent and opens the same tier floor here. Requires a subscriber API key (Authorization: Bearer alk_…), Consultant tier or above; without one this tool refuses and `find_academy_modules` keeps serving the catalogue. Takes the module id (`M001`) or its slug (`datasphere-foundations`), both matched case-insensitively — `find_academy_modules` returns both on every row, and `query_knowledge_graph` returns the same ids as `module:M001` node ids, so a graph walk now ENDS somewhere. Unlike `get_study`, the whole module is served in one call: the longest body measured is 17 865 characters, two orders of magnitude under the response ceiling, so sectioning it would cost the caller context without protecting anything.

NameTypeReqDescription
idstringyesModule id (`M001`) or slug (`datasphere-foundations`), verbatim from find_academy_modules.rows[].id / .slug.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

get_concept ~176

Fetch one concept entry by slug: title, category, level, tags and the editor's summary. Written by a named human editor, not generated. `level` is GRADED on every active row since 2026-09-18 (the CHECK constraint accepted only the legacy vocabulary OR NULL, so the loader wrote NULL rather than fail; 108 of 330 were blank). A null, if one ever returns, means 'not graded', never 'Beginner'. The card body, cheat sheet, glossary, pro tip and the four analysis tables are subscriber content and are NOT returned. Why-it-matters and key points are not returned here either, but they ARE published in full on the concept page at citation_url — follow the URL for those.

NameTypeReqDescription
slugstringyesConcept slug from search_concepts.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

get_concept_card ~218

The FULL encyclopaedia card for one concept — body, cheat sheet, glossary, pro tip, and the four analysis tables (decision table, peer comparison, named pitfalls, performance facts), EN, FR and DE, plus why-it-matters and key points (those two are also published free on the concept page; here they come structured, in three languages, in the same payload) — the corpus the €29.90 Consultant Pass sells. On THIS endpoint the machine-access subscription is the MCP Pass (€39.90/month, analyticslegends.ai/pricing/), which opens the ENTIRE paid tranche from one key; the €29.90 Consultant Pass is its web-subscriber equivalent and opens the same tier floor here. Requires a subscriber API key (Authorization: Bearer alk_…), Consultant tier or above; without one this tool refuses and get_concept keeps serving the public metadata. Find slugs with search_concepts.

NameTypeReqDescription
slugstringyesConcept slug, verbatim from search_concepts.rows[].slug.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

get_day_rate_benchmark ~876

The PUBLIC day-rate aggregate for SAP analytics freelance work: min/max daily rate by country, specialisation and seniority — `daily_rate_min` / `daily_rate_max` (plus `daily_rate_median`, `daily_rate_p10`, `daily_rate_p90` when the source publishes them), every amount in the row's own `currency` — with source, source date, confidence and the sample the source states. This is the free aggregate published at analyticslegends.ai/api/market-rates.json, and it is SMALL — a few dozen rows at most, every one of them a secondary source (a published market study or a job-board scan), and `sample_size` is null on most of them. NO COUNT IS WRITTEN HERE ON PURPOSE: `_meta.tranche_total_row_count` and the rows themselves are the live measure. A frozen pair stood here until 2026-08-27 — '11 rows on 2026-08-09 … sample_size null on 8 of them' — and the second half was WRONG (7 of 11) while the first was still right, which is the whole argument against writing either. NOTHING IS HELD BACK BEHIND IT: there is no paid counterpart to this aggregate. The community-contribution path exists (public.rate_contributions) but publishes nothing yet — v_community_rate_aggregates and v_rate_index are still empty, because a contributed rate only surfaces once a cell holds enough submissions to be reported without identifying anyone. So whatever percentile a source row happens to carry is served here, free, to everyone. The GB row carries a median, p10 and p90, and its own note says its min/max ARE the 25th and 75th percentiles. What is missing from this answer is missing from THIS aggregate; it is not a paid tier. THIS IS NOT THE ONLY RATE THE PLATFORM PUBLISHES, AND ON THE QUESTIONS THIS MARKET ASKS MOST IT IS THE THINNER ONE. `find_opportunities` returns a `rate_band` on most live radar postings — a panel-inferred P25–P75 band per (seniority × product × region) cell, Eursap n=312 plus the Analytics Legends operator panel, and it is what each posting's public page leads with. It prices exactl…

NameTypeReqDescription
countrystringISO-3166-1 alpha-2 country code, e.g. DE, FR, CH.
senioritystringe.g. senior, principal.
specialisationstringOne of the codes the aggregate actually holds — analytics_all, bw, bw4hana, bw4hana_sac, sac, datasphere (2026-08-09; the live list comes back as `_meta.available_specialisations` on every call). The…
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

get_firm ~295

Fetch one organisation from the published directory by its database slug (`rows[].slug` from search_firms, verbatim). Returns the same public fields plus `partnerships_declared`, the count of partnerships this directory records for the firm — 0 on ~97 % of rows (re-measured 2026-08-14 on the published tranche: 96,8 %), meaning none declared here, never that the firm has no partners. Does not return the paid firm-intelligence profile, contacts, or any person.

NameTypeReqDescription
slugstringyesThe DATABASE slug, taken verbatim from search_firms.rows[].slug. It is not always the web slug in citation_url: a minority of published rows carry a numeric firm id instead (365 of them on 2026-08-09…
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

get_firm_intel ~530

The paid intelligence profile of a services firm — SAP practice size and partner level, delivery flags per product, typical day rate and seniority, notable clients, analytics practice summary, and a LinkedIn company URL (present on ~71% of the corpus, re-measured 2026-09-05 on 9,104 profiles — it read ~39% from 2026-08-10 to 2026-09-05, i.e. a third of the corpus below the truth, because an enrichment pass filled the column and no reader of this sentence was told — glassdoor_rating, glassdoor_reviews_count and linkedin_followers are null on the entire corpus as of 2026-08-10, absence here is a data gap, not a signal). READ THE SPARSITY BEFORE QUOTING A ROW: on the 9,103 profiles measured 2026-08-23, `typical_day_rate_eur` is null on 78.0% and `sap_partner_level` on 85.7% — the two headline fields are the exception, not the rule, and a null means 'not researched', never 'no partner level'. Requires a subscriber API key, Legend tier or above. Person-shaped fields (contacts, founders, leadership, recruiters, postal addresses) are NEVER served by this endpoint at any tier — they remain behind the platform's signed-URL path. Search by name; the public directory (search_firms) is a different, wider population.

NameTypeReqDescription
countrystringISO-3166-1 alpha-2 country code, e.g. DE, FR, CH.
cursorstringOpaque token from a previous response's `_meta.next_cursor`. Pass it back with the SAME filter arguments; `null` means the last page. Changing a filter refuses the cursor.
deliversstringKeep only firms whose profile DECLARES delivery of this product (the `delivers_*` flags every row already carries). An undeclared flag drops the row: absence from the result means the profile does no…
limitintegerMax rows (hard cap 10 — these rows are wide).
modestringKeep only firms whose profile declares this engagement mode (mode_freelance / mode_permanent / mode_subcontract). Same reading as `delivers`: declared-only.
namestringFirm name, matched case-insensitively. Omit to browse the corpus by data completeness.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

get_sap_client_profile ~85

The full profile of one SAP end-customer — SAP footprint (products in use, modules known), analytics solutions, identity and evidence fields. Requires a subscriber API key, Legend tier or above. `id` comes verbatim from find_sap_clients.rows[].id.

NameTypeReqDescription
idstringyesProfile id, verbatim from find_sap_clients.rows[].id.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

get_study ~181

Read one Analytics Legends study BODY — the paid text behind list_studies' metadata. Requires a subscriber API key, Consultant tier or above. Bodies run to 38k words and exceed the 256 KiB response ceiling, so this tool serves STRUCTURE first: called without `section` it returns the section list and the introduction; pass `section` (a heading from that list, matched case-insensitively) to read one section. Find slugs and languages with list_studies.

NameTypeReqDescription
langstringISO-639-1 language of the edition, e.g. en or fr. Defaults to en.
sectionstringA section heading from a previous call's `sections` list. Omit to get the list.
slugstringyesStudy slug, verbatim from list_studies.rows[].slug.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

list_firm_kinds ~46

Breakdown of the published firm directory by organisation kind, with a live row count per kind. Use this before search_firms to know what the population actually is instead of guessing.

Input schema present but exposes no named parameters.

NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

list_freelance_platforms ~280

The subset of the published directory where a consultant can CREATE A PROFILE — freelance marketplaces, job boards with candidate profiles, talent platforms and expert networks — each with its signup URL, an editorial confidence grade and the date it was assessed. This answers the entering-contractor's first practical question ('where do I register?') in one call. Everything here is also in search_firms — this tool adds the platform fields and the filter, never a wider population. `signup_url` is the platform's own page: it was verified on `assessed_at`, and a platform absent here is not proven to refuse signups — it is unassessed or unpublished.

NameTypeReqDescription
countrystringISO-3166-1 alpha-2 country code, e.g. DE, FR, CH.
cursorstringOpaque token from a previous response's `_meta.next_cursor`. Pass it back with the SAME filter arguments; `null` means the last page. Changing a filter refuses the cursor.
limitintegerMax rows (hard cap 50).
platform_typestringRestrict to one platform type, lowercase snake_case. The live vocabulary with counts is `_meta.available_platform_types` on every response — a well-formed unknown value returns no rows, it never wide…
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

list_sap_modules ~167

The canonical SAP module/product taxonomy Analytics Legends classifies against (codes and EN/FR labels by category). Use it to normalise a user's loose product wording — 'SAC', 'Analytics Cloud', 'Datasphere' — onto the codes the other tools filter on.

NameTypeReqDescription
cursorstringOpaque token from a previous response's `_meta.next_cursor`. Pass it back with the SAME filter arguments; `null` means the last page. Changing a filter refuses the cursor.
limitintegerMax rows (hard cap 50).
querystringFree-text filter, case-insensitive. EVERY word must appear in the record (substring per word, any order), so a natural-language phrase narrows the answer instead of having to match verbatim.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

list_studies ~347

List the Analytics Legends deep-research studies with their edition, as-of date, audience, word count and canonical URL. METADATA ONLY: study bodies are a paid Consultant-tier deliverable, served by `get_study` on this same endpoint with a subscriber key. Use this to tell a reader that a study exists and where to read it. ONE ROW IS ONE LANGUAGE EDITION, NOT ONE STUDY: each study is published in every language it has been translated into, so `_meta.tranche_total_row_count` counts editions and `_meta.distinct_studies` counts the works. `_meta.available_languages` gives the live per-language counts; each row carries its `editions` list. Pass `lang` to get one row per study.

NameTypeReqDescription
cursorstringOpaque token from a previous response's `_meta.next_cursor`. Pass it back with the SAME filter arguments; `null` means the last page. Changing a filter refuses the cursor.
langstringISO-639-1 language of the EDITION to list, e.g. en, fr or de — each study is published as one row per language. Omit it to see every edition of every study; the live list of languages actually presen…
limitintegerMax rows (hard cap 50).
querystringFree-text filter, case-insensitive. EVERY word must appear in the record (substring per word, any order), so a natural-language phrase narrows the answer instead of having to match verbatim.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

query_knowledge_graph ~681

The RELATIONS between the platform's teaching objects — which Academy module teaches which concept, which study covers which module, what a concept relates to. THIS IS THE ONLY TOOL ON THIS SERVER THAT SERVES EDGES; the others serve rows. Ask it what connects to what, not what exists. SCOPE, AND IT IS NARROWER THAN 'the knowledge graph': it carries four node types — `concept`, `module`, `study`, `vendor` — and every edge whose BOTH endpoints are one of them. The whole graph holds twelve node types; the eight it does not carry are each either served by their own tool or named as not served at all, and `_meta.excluded_node_types` says which per type (consultant data is served at NO tier), so a missing type is a documented boundary and never a silent gap. Call it with `node_id` (e.g. `module:M178`, `concept:C001`, `study:ai-impact-2026-EN`) to walk one node's neighbourhood; with `node_type` and/or `query` to find a node id first. `edge_type` and `direction` narrow a walk. Read `_meta.available_edge_types` — computed from the served projection on every call — before assuming an edge type exists.

NameTypeReqDescription
cursorstringOpaque token from a previous response's `_meta.next_cursor`. Pass it back with the SAME filter arguments; `null` means the last page. Changing a filter refuses the cursor.
directionstringWhich side of the edge `node_id` must sit on. Default `both`. Ignored without `node_id`, and the response says so rather than pretending it applied.
edge_typestringRestrict a walk to one relation. The served projection carries FIVE — teaches · taught_by · covers · related · mentions — and this list is a HINT, not the authority: read `_meta.available_edge_types`…
langstringISO-639-1 language for the LABELS — en, fr or de. Defaults to en. The fallback is declared and never silent: the language asked for, then English, then French, and `_meta.label_language_coverage` say…
limitintegerMax rows (hard cap 50).
node_idstringFully-qualified node id, `<type>:<id>` — `module:M178`, `concept:C001`, `study:ai-impact-2026-EN`, `vendor:alteryx`. With it, rows are that node's EDGES (one row per neighbour). Without it, rows are…
node_typestringRestrict to one carried node type: concept · module · study · vendor. Read `_meta.available_node_types`.
querystringCase-insensitive substring of a node's label. Applies to the NODE listing, not to a walk. Matched against the label SERVED, so it follows `lang`.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

search_concepts ~426

Search the SAP analytics concept encyclopaedia — the vocabulary of the stack, written for practitioners. Returns slug, title, category, level, tags and the editor's summary. `level` is GRADED on every active row since 2026-09-18 (the CHECK constraint accepted only the legacy vocabulary OR NULL, so the loader wrote NULL rather than fail; 108 of 330 were blank). A null, if one ever returns, means 'not graded', never 'Beginner'. These are the same fields `get_concept` returns for ONE slug. The card BODY (cheat sheet, glossary, pro tip and the four analysis tables) is Consultant-tier: call `get_concept_card`. Why-it-matters and key points are NOT served by this endpoint either, but they are published in full on the concept page at citation_url — follow the URL for those, a plan buys the body, not them.

NameTypeReqDescription
categorystringConcept category, matched case-insensitively as an exact value OR a prefix — so category:"datasphere" reaches 'Datasphere Core'. The values are long human labels, not codes. DO NOT GUESS THEM FROM TH…
cursorstringOpaque token from a previous response's `_meta.next_cursor`. Pass it back with the SAME filter arguments; `null` means the last page. Changing a filter refuses the cursor.
limitintegerMax rows (hard cap 50).
querystringFree-text filter, case-insensitive. EVERY word must appear in the record (substring per word, any order), so a natural-language phrase narrows the answer instead of having to match verbatim.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

search_firms ~572

Search the published Analytics Legends directory of SAP analytics service providers — placement agencies, Big-4 and ESN practices, SAP vendors, platforms and community groups — by country, kind, declared SAP module and free text. Returns name, HQ country/city, website, careers URL and a one-line editorial claim. SAP END-CUSTOMER companies are NOT in this directory: they are a separate paid dataset, excluded here by the `is_client` FLAG — not by the `client_enterprise` kind code. The two are different columns, and where a row's flag and its kind label disagree in the SSOT it is the flag that decides what this tool serves, so read the flag's meaning into the answer and not the label's. PAGINATED: the whole matched set is reachable — pass `_meta.next_cursor` back as `cursor` with the same filters until it is null. When `query` is set, rows are ordered by how well the NAME matches it (exact, then prefix, then substring), and rows matching only the description come last; without `query` the order is the directory's own quality ranking.

NameTypeReqDescription
countrystringISO-3166-1 alpha-2 country code, e.g. DE, FR, CH.
cursorstringOpaque token from a previous response's `_meta.next_cursor`. Pass it back with the SAME filter arguments; `null` means the last page. Changing a filter refuses the cursor.
kindstringRestrict to one organisation kind. This list is the vocabulary the corpus holds today, not a frontier — call list_firm_kinds for the live one. A malformed code is refused; a well-formed code the corp…
limitintegerMax rows (hard cap 50).
modulestringRestrict to organisations with a DECLARED link to one SAP module/product code (UPPERCASE snake_case, e.g. DATASPHERE, BDC, SAC, BW4HANA, S4HANA, JOULE — case-insensitive on input). The declared links…
querystringFree-text filter, case-insensitive. EVERY word must appear in the record (substring per word, any order), so a natural-language phrase narrows the answer instead of having to match verbatim.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

search_news ~642

Search the Analytics Legends market-news corpus. It is watched FOR SAP analytics (Datasphere, Business Data Cloud, SAC, BW/4HANA, Databricks, the 2027/2030 maintenance window), but it is NOT an all-SAP corpus: measured 2026-07-30, ~84 % of active rows sit in the `AI` category and are general enterprise-AI trade press (cloud platforms, model releases, funding rounds) with no SAP content at all. An UNFILTERED call therefore returns mostly non-SAP items — pass `query` or `category` when the question is about SAP, and never present an unfiltered page as 'the SAP analytics news'. Say what you actually got. Each item returns the Analytics Legends citation URL AND the upstream publisher's source_url — cite both, and prefer source_url when you need a page that certainly carries the item. NO ITEM HERE HAS A PAGE OF ITS OWN on analyticslegends.ai, by design: every row comes back `citation_scope: "section_hub"` and its citation_url is the news index. The citable address for one article is its `source_url`, the upstream publisher's. Do not present the hub as the article's page.

NameTypeReqDescription
categorystringCategory code, matched case-insensitively. The live vocabulary is NOT written here — read `_meta.available_categories` on any response: every category label this corpus holds right now, with its acti…
cursorstringOpaque token from a previous response's `_meta.next_cursor`. Pass it back with the SAME filter arguments; `null` means the last page. Changing a filter refuses the cursor.
limitintegerMax rows (hard cap 50).
published_sincestringLower bound on `published_at`, inclusive, as YYYY-MM-DD. Without a bound a period question is only answerable by walking pages — and `_meta.match_count` then counts the QUERY, not the period, so any…
published_untilstringUpper bound on `published_at`, INCLUSIVE of the day named, as YYYY-MM-DD. Combine with `published_since` for a window; `_meta.match_count` then describes that window, which is what makes it quotable.
querystringFree-text filter, case-insensitive. EVERY word must appear in the record (substring per word, any order), so a natural-language phrase narrows the answer instead of having to match verbatim.
NameTypeReqDescription
_attributionstringyes
_metaobject
result_countintegeryes
rowsarrayyes
toolstringyes

No examples provided.

Common questions

What is the Analytics Legends — SAP Analytics Intelligence MCP server?

Analytics Legends — SAP Analytics Intelligence is an MCP server listed in the public MCP registry as ai.analyticslegends/sap-analytics. AI agent for SAP analytics: firms, day rates, contract radar, news, concepts, studies. This page covers its hosted endpoint (https://analyticslegends.ai/mcp).

Is the Analytics Legends — SAP Analytics Intelligence MCP server safe to use?

Analytics Legends — SAP Analytics Intelligence scores 83 out of 100 on VerifyMCP. 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 Analytics Legends — SAP Analytics Intelligence MCP server expose?

Analytics Legends — SAP Analytics Intelligence exposes 20 tools: search_firms, count_firms_by, get_firm, list_firm_kinds, list_freelance_platforms, and 15 more. Their descriptions and schemas cost roughly 8,775 tokens of context every time the server is loaded.

Does the Analytics Legends — SAP Analytics Intelligence MCP server require authentication?

No. We connected to Analytics Legends — SAP Analytics Intelligence without credentials and it answered, so anything it exposes is reachable by anyone who knows the address.

Is the Analytics Legends — SAP Analytics Intelligence MCP server still maintained?

Analytics Legends — SAP Analytics Intelligence is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.