Medallia MCP Server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Medallia MCP ServerShow me recent customer feedback."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Medallia MCP Server
An MCP (Model Context Protocol) server that integrates with the Medallia Query API to enable AI applications to query customer feedback, customer profiles, and analytics.
What is MCP?
The Model Context Protocol (MCP) is a standardized protocol that enables AI applications to interact with external tools, data sources, and resources. This server exposes:
Tools: Functions to query Medallia data
Resources: Connection status and metadata
Related MCP server: central-mcp-server
Prerequisites
Node.js 20 or later
npm or yarn
Medallia account with API credentials (OAuth 2.0 token)
Installation
npm installConfiguration
Create a .env file in the project root (you can copy .env.example) and set the following values:
cp .env.example .envThen populate:
# Required: OAuth client credentials
MEDALLIA_CLIENT_ID="your_client_id_here"
MEDALLIA_CLIENT_SECRET="your_client_secret_here"
# Required for the token request endpoint
MEDALLIA_REPORTING_INSTANCE="instance.medallia.com"
MEDALLIA_TENANT_NAME="tenant"
# Optional: override the full token endpoint if needed
# MEDALLIA_OAUTH_TOKEN_URL="https://instance.medallia.com/oauth/tenant/token"
# Optional: GraphQL endpoint (defaults to https://api.medallia.com/v2/graphql)
MEDALLIA_API_ENDPOINT="https://api.medallia.com/v2/graphql"
# Optional: default verbatim fields for queryFeedback when verbatimFieldIds is omitted
# Comma-separated list or JSON array string
MEDALLIA_DEFAULT_VERBATIM_FIELD_IDS="q_comment,q_followup_comment"
# Optional: MCP transport mode (defaults to stdio)
# MCP_TRANSPORT="stdio"
#
# Optional: HTTP transport settings (used when MCP_TRANSPORT=http)
# MCP_HTTP_HOST="127.0.0.1"
# MCP_HTTP_PORT="3000"
# MCP_HTTP_PATH="/mcp"
#
# Optional: host/origin validation for non-loopback HTTP deployments
# Comma-separated hostnames, no scheme.
# MCP_ALLOWED_HOSTS="mcp.example.com"
# MCP_ALLOWED_ORIGINS="app.example.com,copilot.microsoft.com"Notes:
The server reads
.env(and alsoenvfor compatibility) from the project root.Variable expansion is supported, so values like
MEDALLIA_OAUTH_TOKEN_URL=https://${MEDALLIA_REPORTING_INSTANCE}/oauth/${MEDALLIA_TENANT_NAME}/tokenwork.You can override the file path with
ENV_FILE(for exampleENV_FILE=.env.local npm run dev).
Getting Medallia Credentials
Log into your Medallia Experience Cloud instance
Navigate to Administration → API Credentials
Create or retrieve your OAuth 2.0 client ID and client secret
Ensure your API account has the Query API capability enabled
Use the reporting instance and tenant values from your Medallia Experience Cloud environment to fetch an access token dynamically
See Medallia Authentication Docs for detailed instructions.
Development
Run the server in development mode with live TypeScript compilation:
npm run devBuilding
Build the TypeScript to JavaScript:
npm run buildProduction
Run the compiled server:
npm startRemote HTTP transport (for online MCP access)
The server now supports Streamable HTTP transport in addition to stdio.
MCP_TRANSPORT=http MCP_HTTP_HOST=0.0.0.0 MCP_HTTP_PORT=3000 npm startThis exposes the MCP endpoint at:
http://<host>:3000/mcpNotes:
stdioremains the default transport for local IDE integrations.On loopback hosts (
localhost,127.0.0.1,::1), localhost host/origin checks are enabled automatically.On non-loopback hosts, set
MCP_ALLOWED_HOSTSandMCP_ALLOWED_ORIGINSto enable host/origin validation.
Testing
Test the server without Medallia credentials (will show graceful error handling):
npm run build
node test-medallia.jsTo test with actual Medallia data:
MEDALLIA_API_TOKEN="your_token" node test-medallia.jsFeatures
Tools
1. getPrograms
List available Experience Programs in your Medallia tenant.
Parameters:
limit(optional, number): Number of programs to return (default: 10)
Returns: JSON with program metadata including name, status, response count, creation date
Example:
Tool: getPrograms
Parameters: { limit: 5 }2. queryFeedback
Query feedback records with optional filtering by date range and field selection.
Parameters:
limit(optional, number): Records per page (default: 10)dateFrom(optional, string): Filter from date (ISO 8601)dateTo(optional, string): Filter to date (ISO 8601)programId(optional, string): Filter by Experience Program IDfieldIds(optional, string[]): Field IDs to return per feedback record (any field type supported by your Medallia tenant)If omitted, the tool uses
MEDALLIA_DEFAULT_VERBATIM_FIELD_IDSfrom.envwhen set.
Use getFieldCatalog to discover available field IDs for your tenant.
Field Data Types: The response includes fieldData with support for StringFieldData and CommentFieldData types from Medallia's GraphQL schema. Additional field types can be queried and will be returned based on your tenant configuration.
Returns: JSON with feedback nodes, total count, pagination info, and fieldData per node when requested (or when default fields are configured in .env)
Example:
Tool: queryFeedback
Parameters: {
limit: 20,
dateFrom: "2024-01-01",
dateTo: "2024-12-31",
fieldIds: ["q_comment", "q_followup_comment"]
}3. queryCustomers
Query customer profiles from Medallia CX Profiles (if enabled).
Parameters:
limit(optional, number): Number of customers (default: 10)firstName(optional, string): Filter by first nameemail(optional, string): Filter by email
Returns: JSON with customer data (ID, email, name, phone) and pagination
Example:
Tool: queryCustomers
Parameters: { limit: 10 }4. getAggregates
Calculate aggregate metrics from feedback data.
Parameters:
metric(required, enum): Type of aggregationcount- Count of recordsaverage- Average valuesum- Sum of valuescustomCalculationcustomcountUniquebucketCountpercentagetopicPercentageglobalRecordsTopicPercentagetopicImpactscaledTopicImpactsentimentCountsentimentPercentagesentimentNetPercentageregressionBetaregressionCorrelationsegmentAveragesegmentPercentilefilteredsumOfProductmin/max(legacy compatibility)
fieldId(optional, string): Field to aggregate (default: configured default aggregate field)secondaryFieldId(optional, string): Required forsumOfProductunless custom metric config is providedcustomCalculationName(optional, string): Required forcustomCalculationunless custom metric config is providedmetricConfigGraphQL(optional, string): Raw GraphQL metric body for advanced metricsdateFrom(optional, string): Filter from date (ISO 8601)dateTo(optional, string): Filter to date (ISO 8601)
Returns: JSON with metric result and applied filters
Use getFieldCatalog to discover the current valid field IDs for your tenant.
Example:
Tool: getAggregates
Parameters: {
metric: "average",
fieldId: "q_sgb_ltr_scale11",
dateFrom: "2024-01-01"
}Advanced metricConfigGraphQL examples (by metric):
// count (plain record count)
{ metric: "count" }
// count on a field
{ metric: "count", fieldId: "q_sgb_ltr_scale11" }
// average / sum / countUnique / custom
{ metric: "average", fieldId: "q_sgb_ltr_scale11" }
{ metric: "sum", fieldId: "q_sgb_ltr_scale11" }
{ metric: "countUnique", fieldId: "q_sgb_ltr_scale11" }
{ metric: "custom", fieldId: "r_bp_branch_net_promoter_score" }
// customCalculation (requires customCalculationName)
{
metric: "customCalculation",
fieldId: "q_sgb_ltr_scale11",
customCalculationName: "bp_count"
}
// sumOfProduct (two fields)
{
metric: "sumOfProduct",
fieldId: "q_driver_1",
secondaryFieldId: "q_driver_2"
}
// min / max (legacy compatibility)
{ metric: "min", fieldId: "q_sgb_ltr_scale11" }
{ metric: "max", fieldId: "q_sgb_ltr_scale11" }// Advanced metrics use metricConfigGraphQL.
// Pass the metric body exactly as required by your Medallia tenant/schema.
// bucketCount
{ metric: "bucketCount", metricConfigGraphQL: 'fieldFilter: { fieldIds: ["e_responsedate"], gte: "2026-01-01", lt: "2026-02-01" }' }
// percentage (Medallia docs note: aggregateTable-focused metric)
{ metric: "percentage", metricConfigGraphQL: 'axis: ROW' }
// topic metrics
{ metric: "topicPercentage", metricConfigGraphQL: 'topic: { sentiment: POSITIVE }' }
{ metric: "globalRecordsTopicPercentage", metricConfigGraphQL: 'topic: { sentiment: POSITIVE }' }
{ metric: "topicImpact", metricConfigGraphQL: 'metric: { average: { field: { id: "q_sgb_ltr_scale11" } } }' }
{ metric: "scaledTopicImpact", metricConfigGraphQL: 'metric: { average: { field: { id: "q_sgb_ltr_scale11" } } }' }
// sentiment metrics
{ metric: "sentimentCount", metricConfigGraphQL: 'sentiments: [POSITIVE, STRONGLY_POSITIVE]' }
{ metric: "sentimentPercentage", metricConfigGraphQL: 'sentiments: [POSITIVE, STRONGLY_POSITIVE]' }
{ metric: "sentimentNetPercentage", metricConfigGraphQL: '{}' }
// regression metrics
{ metric: "regressionBeta", metricConfigGraphQL: 'dependentField: { id: "q_sgb_ltr_scale11" }, independentFields: [{ id: "q_driver_1" }, { id: "q_driver_2" }]' }
{ metric: "regressionCorrelation", metricConfigGraphQL: 'dependentField: { id: "q_sgb_ltr_scale11" }, independentFields: [{ id: "q_driver_1" }, { id: "q_driver_2" }]' }
// segment metrics
{ metric: "segmentAverage", metricConfigGraphQL: 'metric: { average: { field: { id: "q_sgb_ltr_scale11" } } }, segment: { field: { id: "e_unitid" }, key: "12345" }' }
{ metric: "segmentPercentile", metricConfigGraphQL: 'metric: { average: { field: { id: "q_sgb_ltr_scale11" } } }, percentile: 90, segment: { field: { id: "e_unitid" }, key: "12345" }' }
// filtered (wrapper metric)
{ metric: "filtered", metricConfigGraphQL: 'filter: { fieldIds: ["e_responsedate"], gte: "2026-01-01", lt: "2026-02-01" }, metric: { average: { field: { id: "q_sgb_ltr_scale11" } } }' }For advanced metrics, validate exact shape with your tenant using getFieldCatalog + small trial queries, since Medallia setup/custom modules can affect accepted metric payloads.
Resources
medallia-status
URI: medallia://connection-status
Provides real-time status of the Medallia API connection.
Returns: JSON with:
connected- Whether GraphQL client is initializedauthenticated- Whether API token is configuredendpoint- Configured API endpointstatus- Human-readable status messagetimestamp- Current time
Architecture
src/
├── index.ts # Main server with Medallia tools & resources
test-medallia.js # Integration test client
test-client.js # Generic MCP test harnessMedallia Query API
This server wraps the Medallia Query API, which is a GraphQL API for accessing customer feedback, analytics, and metadata.
Key Concepts
Feedback & Invitations: Records of survey responses and events
Customers: CX Profile data (requires CX Profiles add-on)
Aggregates: Calculated metrics (NPS, averages, counts, etc.)
Programs: Experience Programs define the data schema
Fields: Individual survey questions and data fields
Rate Limits
The Medallia Query API has the following limits:
70 requests per second
975,000 requests per 24-hour window
3,000,000 cost-unit limit per query
See Rate Limits for details.
Error Handling
The server gracefully handles errors:
Missing credentials: Returns clear error message instructing user to set
MEDALLIA_API_TOKENInvalid queries: Returns GraphQL error from Medallia API
Network issues: Returns timeout or connection error
Example error response:
{
"content": [
{
"type": "text",
"text": "Error querying programs: MEDALLIA_API_TOKEN environment variable not set."
}
]
}Next Steps
To extend this server:
Add more GraphQL queries for specific use cases
Implement caching of frequently-accessed data
Add more aggregate calculation types
Create custom tools for your specific data schema
Add prompt templates for common analyses
Learn More
Troubleshooting
"MEDALLIA_API_TOKEN environment variable not set"
This is expected when the environment variable is not configured. Set it before running:
export MEDALLIA_API_TOKEN="your_token"
node dist/index.js"Query cost exceeds limit"
Your GraphQL query is too expensive. Try:
Reducing the
limitparameterAdding more specific filters
Splitting into multiple queries
Connection refused
Check that:
Your API endpoint is correct
Your OAuth token is valid and not expired
Your network can reach
api.medallia.com
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
A paid remote MCP for AI SDK data query MCP, built to return verdicts, receipts, usage logs, and aud
Let AI agents query data and act across all your business apps via MCP.
Connects AI assistants to CloudQuell multi-cloud and AI cost, savings, anomaly, and budget data.
Query your org's data in natural language — read-only MCP access to SQL, NoSQL, files & warehouses.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables AI assistants to query software supply chain compliance data, including asset status, security vulnerabilities, and evidence lineage. It allows for natural language analysis of compliance posture, policy violations, and deployment blockers across an organization.-
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to query HPE Aruba Networking Central data (sites, devices, clients, alerts, events) through natural language.7MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI applications to interact with Tableau for querying data, exploring content, and retrieving views through natural language.9,536Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables read-only access to VortexIQ ecommerce AI data, including store audits, KPIs, alerts, brand DNA, and reports, through natural language queries.MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/yiannis-h-dev/MCP-Hyundai'
If you have feedback or need assistance with the MCP directory API, please join our Discord server