Skip to main content
Glama

Analytics Legends — SAP AI & Analytics MCP Server

Search the SAP AI & analytics firm directory

search_firms
Read-only

Search SAP AI & analytics service providers (consultancies, Big-4, agencies, SAP partners, platforms) by text, country, region, kind or declared module. Returns slug, name, HQ, website, claim, sap_signal_band; SAP end-customers are in find_sap_clients. Public.

Tool call template

This tool declares no required parameters. Add optional parameters from the input schema as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {},
    "name": "search_firms"
  }
}

Input Schema

NameRequiredDescriptionDefault
kindNoOrganisation kind (list_firm_kinds).
limitNo
queryNoAll words must match.
cursorNo
moduleNoSAP module code; list: count_firms_by by=module.
regionNo
countryNoISO alpha-2.

Output Schema

NameRequiredDescriptionDefault
rowsYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed21 schema fields changed
    • removedInput schema / additionalProperties
      Removed value: -false
    • changedInput schema / properties / country / description
      Previous value: -"ISO-3166-1 alpha-2 country code, e.g. DE, FR, CH."New value: +"ISO alpha-2."
    • addedInput schema / properties / country / examples
      Added value: +[
      +  "DE"
      +]
    • removedInput schema / properties / country / pattern
      Removed value: -"^[A-Za-z]{2}$"
    • removedInput schema / properties / cursor / description
      Removed value: -"Opaque 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."
    • removedInput schema / properties / cursor / maxLength
      Removed value: -512
    • changedInput schema / properties / kind / description
      Previous value: -"Restrict 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 corpus does not hold returns no rows. Neither case is silently ignored, and neither widens the result."New value: +"Organisation kind (list_firm_kinds)."
    • removedInput schema / properties / limit / description
      Removed value: -"Max rows (hard cap 50)."
    • removedInput schema / properties / limit / maximum
      Removed value: -50
    • removedInput schema / properties / limit / minimum
      Removed value: -1
    • changedInput schema / properties / module / description
      Previous value: -"Restrict 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 are structured data, far more selective than free text: `count_firms_by {by:\"module\"}` gives the live vocabulary with counts. A minority of the directory declares any module at all, so this filter finds the DECLARED specialists — absence from the result means no declared link, never that the firm does not work on the module."New value: +"SAP module code; list: count_firms_by by=module."
    • addedInput schema / properties / module / examples
      Added value: +[
      +  "DATASPHERE"
      +]
    • changedInput schema / properties / query / description
      Previous value: -"Free-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."New value: +"All words must match."
    • removedInput schema / properties / query / maxLength
      Removed value: -200
    • removedInput schema / properties / region / description
      Removed value: -"Region code of the HQ country — the platform's six-value geography: EMEA (Europe AND the Middle East), AMER (North America), LATAM, APAC, AFRICA (its own region, not folded into EMEA), GLOBAL (country unknown). Case-insensitive on input; anything else is refused."
    • removedOutput schema / properties / _attribution
      Removed value: -{
      -  "type": "string"
      -}
    • removedOutput schema / properties / _meta
      Removed value: -{
      -  "type": "object"
      -}
    • removedOutput schema / properties / result_count
      Removed value: -{
      -  "type": "integer"
      -}
    • removedOutput schema / properties / rows / items
      Removed value: -{
      -  "properties": {
      -    "citation_scope": {
      -      "enum": [
      -        "record",
      -        "section_hub"
      -      ],
      -      "type": "string"
      -    },
      -    "citation_url": {
      -      "type": "string"
      -    },
      -    "claim": {
      -      "type": [
      -        "string",
      -        "null"
      -      ]
      -    },
      -    "founded_year": {
      -      "type": [
      -        "integer",
      -        "null"
      -      ]
      -    },
      -    "hq_city": {
      -      "type": [
      -        "string",
      -        "null"
      -      ]
      -    },
      -    "hq_country": {
      -      "type": [
      -        "string",
      -        "null"
      -      ]
      -    },
      -    "jobs_url": {
      -      "type": [
      -        "string",
      -        "null"
      -      ]
      -    },
      -    "kind": {
      -      "type": [
      -        "string",
      -        "null"
      -      ]
      -    },
      -    "kind_label": {
      -      "type": [
      -        "string",
      -        "null"
      -      ]
      -    },
      -    "last_verified_at": {
      -      "type": [
      -        "string",
      -        "null"
      -      ]
      -    },
      -    "name": {
      -      "type": [
      -        "string",
      -        "null"
      -      ]
      -    },
      -    "region": {
      -      "type": [
      -        "string",
      -        "null"
      -      ]
      -    },
      -    "sap_signal_band": {
      -      "type": [
      -        "string",
      -        "null"
      -      ]
      -    },
      -    "size_bracket": {
      -      "type": [
      -        "string",
      -        "null"
      -      ]
      -    },
      -    "slug": {
      -      "type": [
      -        "string",
      -        "null"
      -      ]
      -    },
      -    "website": {
      -      "type": [
      -        "string",
      -        "null"
      -      ]
      -    }
      -  },
      -  "type": "object"
      -}
    • removedOutput schema / properties / tool
      Removed value: -{
      -  "type": "string"
      -}
    • changedOutput schema / required
      Previous value: -[
      -  "tool",
      -  "result_count",
      -  "rows",
      -  "_attribution"
      -]New value: +[
      +  "rows"
      +]
  2. Changed1 schema field changed
    • addedOutput schema / properties / rows / items / properties / kind_label
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
  3. Changed1 schema field changed
    • addedInput schema / properties / region
      Added value: +{
      +  "description": "Region code of the HQ country — the platform's six-value geography: EMEA (Europe AND the Middle East), AMER (North America), LATAM, APAC, AFRICA (its own region, not folded into EMEA), GLOBAL (country unknown). Case-insensitive on input; anything else is refused.",
      +  "enum": [
      +    "EMEA",
      +    "AMER",
      +    "LATAM",
      +    "APAC",
      +    "AFRICA",
      +    "GLOBAL"
      +  ],
      +  "type": "string"
      +}
  4. Changed1 schema field changed
    • changedInput schema / properties / kind / enum
      Previous value: -[
      -  "agency_placement",
      -  "professional_services_big4",
      -  "professional_services_esn",
      -  "vendor_sap",
      -  "vendor_partner",
      -  "platform_marketplace",
      -  "community_group",
      -  "client_enterprise",
      -  "other"
      -]New value: +[
      +  "agency_placement",
      +  "professional_services_big4",
      +  "professional_services_esn",
      +  "vendor_sap",
      +  "vendor_partner",
      +  "platform_marketplace",
      +  "community_group",
      +  "training_institution",
      +  "client_enterprise",
      +  "other"
      +]
  5. Changed1 schema field changed
    • changedInput schema / properties / query / description
      Previous value: -"Free-text filter, matched case-insensitively."New value: +"Free-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."
  6. Changed1 schema field changed
    • changedInput schema / properties / cursor / description
      Previous value: -"Opaque token from a previous response's `_meta.next_cursor`. Pass it back with the SAME filter arguments to read the next page; a null `next_cursor` means you have reached the end. It is bound to those filters and refused if they change — a cursor names a POSITION in one ordering, and applying it to another query would start the page in the wrong place."New value: +"Opaque 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."
  7. Changed8 schema fields changed
    • addedOutput schema / properties / rows / items / properties / claim
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / founded_year
      Added value: +{
      +  "type": [
      +    "integer",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / hq_city
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / jobs_url
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / last_verified_at
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / region
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / sap_signal_band
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / size_bracket
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
  8. Changed1 schema field changed
    • addedInput schema / properties / module
      Added value: +{
      +  "description": "Restrict 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 are structured data, far more selective than free text: `count_firms_by {by:\"module\"}` gives the live vocabulary with counts. A minority of the directory declares any module at all, so this filter finds the DECLARED specialists — absence from the result means no declared link, never that the firm does not work on the module.",
      +  "type": "string"
      +}
  9. Changed1 schema field changed
    • addedInput schema / properties / cursor
      Added value: +{
      +  "description": "Opaque token from a previous response's `_meta.next_cursor`. Pass it back with the SAME filter arguments to read the next page; a null `next_cursor` means you have reached the end. It is bound to those filters and refused if they change — a cursor names a POSITION in one ordering, and applying it to another query would start the page in the wrong place.",
      +  "maxLength": 512,
      +  "type": "string"
      +}
  10. Changed1 schema field changed
    • changedInput schema / properties / kind / description
      Previous value: -"Restrict to one organisation kind. Call list_firm_kinds for live counts. A value outside this list is refused, not silently ignored."New value: +"Restrict 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 corpus does not hold returns no rows. Neither case is silently ignored, and neither widens the result."
  11. Changed1 schema field changed
    • changedInput schema / properties / kind / enum
      Previous value: -[
      -  "agency_placement",
      -  "professional_services_big4",
      -  "professional_services_esn",
      -  "vendor_sap",
      -  "vendor_partner",
      -  "platform_marketplace",
      -  "community_group",
      -  "other"
      -]New value: +[
      +  "agency_placement",
      +  "professional_services_big4",
      +  "professional_services_esn",
      +  "vendor_sap",
      +  "vendor_partner",
      +  "platform_marketplace",
      +  "community_group",
      +  "client_enterprise",
      +  "other"
      +]
  12. Changed1 schema field changed
    • changedInput schema / properties / kind / enum
      Previous value: -[
      -  "agency_placement",
      -  "professional_services_big4",
      -  "professional_services_esn",
      -  "vendor_sap",
      -  "vendor_partner",
      -  "platform_marketplace",
      -  "community_group"
      -]New value: +[
      +  "agency_placement",
      +  "professional_services_big4",
      +  "professional_services_esn",
      +  "vendor_sap",
      +  "vendor_partner",
      +  "platform_marketplace",
      +  "community_group",
      +  "other"
      +]
  13. Changed6 schema fields changed
    • removedOutput schema / properties / rows / items / properties / citation_note
      Removed value: -{
      -  "type": "string"
      -}
    • changedOutput schema / properties / rows / items / properties / hq_country / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
    • changedOutput schema / properties / rows / items / properties / kind / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
    • changedOutput schema / properties / rows / items / properties / name / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
    • changedOutput schema / properties / rows / items / properties / slug / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
    • changedOutput schema / properties / rows / items / properties / website / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
  14. Changed2 schema fields changed
    • addedOutput schema / properties / rows / items / properties / citation_note
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / rows / items / properties / citation_scope
      Added value: +{
      +  "enum": [
      +    "record",
      +    "section_hub"
      +  ],
      +  "type": "string"
      +}
  15. Changed1 schema field changed
    • changedInput schema / properties / kind / description
      Previous value: -"Restrict to one organisation kind. Call list_firm_kinds for live counts."New value: +"Restrict to one organisation kind. Call list_firm_kinds for live counts. A value outside this list is refused, not silently ignored."
  16. First observed

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false; the description adds that the directory is 'Public' (no auth) and names the return fields (slug, name, HQ, website, claim, sap_signal_band). It omits pagination behavior and default result count, which would be useful for a cursor-based search.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two dense sentences with zero waste: the searchable dimensions come first, the return fields next, then the disambiguation pointer. Every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter, all-optional search tool with an output schema and read-only annotations, the description covers scope, filters, return shape, and the key sibling boundary. The main missing piece is result-set behavior (limit defaults, cursor usage), which is minor given the schema and output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 57%, and the description maps the filters to concepts ('by text, country, region, kind or declared module'), including the useful hint that module means a declared module. It adds no detail for limit or cursor, and no matching/syntax rules beyond what the schema already states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Search') and resource ('SAP AI & analytics service providers'), enumerates the entity subtypes covered, and lists the filter dimensions. It explicitly differentiates from the sibling find_sap_clients by routing SAP end-customers there.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear when-to-use boundary against the nearest alternative (end-customers go to find_sap_clients) and signals that kinds and modules should be resolved via list_firm_kinds / count_firms_by by=module. It stops short of explicit when-not guidance or describing alternative lookup paths such as get_firm.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.