Vitally MCP Server
The Vitally MCP Server provides access to the Vitally customer success platform's REST API, enabling operations on customer data through MCP-compatible clients.
Tool Discovery: Search available tools by keyword
Account Management: Search accounts by name or external ID, retrieve health scores, conversations, tasks, and notes
User Search: Look up users by email, external ID, or email subdomain
Notes: Retrieve, fetch by ID, or create notes for accounts
Comprehensive Resource Coverage: Full CRUD operations across 17 resource types including organizations, users, conversations, messages, projects, tasks, NPS responses, admins, custom objects, meetings, custom traits, and custom surveys
Flexible Data Center Support: Connects to EU or US Vitally data centers based on configuration
Intelligent API Handling: Automatically retries rate-limited requests and trims heavy response fields for efficiency
Update Management: Built-in
Check_for_updatestool to identify newer GitHub releasesPermission-Aware Tools: Each tool is tagged as
ReadOnlyorDestructivefor bulk permission management by MCP clients
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., "@Vitally MCP Serverfind accounts with 'Acme' in their name"
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.
Vitally MCP Server
A Model Context Protocol server that exposes the Vitally customer success platform's REST API to MCP-compatible clients such as Claude Desktop, Claude Code, VS Code, and Cursor.
Built in C# on .NET 10 and the official ModelContextProtocol SDK, hosted as a remote HTTP MCP server secured with Auth0 (OAuth 2.0 / RFC 9728). Users connect by URL — no install, no executable, no per-user secrets to distribute.
Features
Full CRUD coverage of 92 endpoints across 17 Vitally resource types: accounts, organisations, users, conversations, messages, notes, projects, project templates, project categories, tasks, NPS responses, admins, custom objects (and instances), meetings (with participants and transcripts), custom traits, and custom surveys.
Permission-aware tools — every tool is tagged
ReadOnly/Destructiveso MCP clients can enable or disable categories of operation in bulk.EU and US data centres — defaults to EU (
rest.vitally-eu.io); setVitally:Region=USto point at{subdomain}.rest.vitally.io.Rate-limit-aware HTTP pipeline — auto-retries on
429 Too Many RequestshonouringRetry-AfterandX-RateLimit-Reset, and logs a warning when remaining requests drop below threshold.Client-side field & trait filtering — responses are trimmed before they reach the LLM, each resource type with sensible defaults that exclude heavy fields (rich text, transcripts, full traits objects).
Streamable HTTP transport (MCP 2025-06-18) in stateless mode — easy to scale horizontally, no sticky sessions required.
OAuth 2.0 protection via Auth0 —
/.well-known/oauth-protected-resourceexposes the metadata document so clients discover the authorisation server automatically. The Vitally API key is fetched on demand from Azure Key Vault via the server's managed identity.
Related MCP server: Vitally MCP Server
Using the server (FISCAL users)
Point your MCP client at:
https://vitally.fiscaltec.com/mcpThe first time you connect, your client will redirect you through Auth0 to authenticate. Once authenticated, the server proxies your tool calls to Vitally using a service-account API key it fetches from Azure Key Vault.
Access & groups: authentication alone grants nothing — you must be in a
sg-vitally-*Entra group for your access tier. See ACCESS.md for connecting, the group setup, and how access is granted or revoked.
Claude Desktop
Settings → Connectors → Add custom connector → paste the URL above. Approve the Microsoft sign-in popup.
Claude Code
claude mcp add --transport http vitally https://vitally.fiscaltec.com/mcpRun any MCP-using command (claude itself, or /mcp) and Claude Code will open the Microsoft sign-in flow on first use.
VS Code, Cursor, and other MCP-aware hosts
Most modern MCP clients support the streamable HTTP transport. Add a server entry that points at the URL above; the client handles the OAuth flow automatically via the protected-resource metadata document.
Configuration
The server reads its configuration from appsettings.json, appsettings.{Environment}.json, or environment variables (using the standard ASP.NET Core double-underscore separator for nested keys, e.g. Vitally__Region).
Setting | Required | Default | Description |
| No |
| Data centre: |
| Only when | — | Vitally subdomain, e.g. |
| Yes (prod) | — | Azure Key Vault URI, e.g. |
| No |
| Key Vault secret name holding the Vitally API key. |
| No |
| In-memory TTL for the resolved API key. |
| Yes (local) | — | Local-dev-only fallback API key, used when |
| Yes | — | OAuth/OIDC issuer URL with trailing slash, e.g. |
| Yes | — | The OAuth Resource Server / API identifier, e.g. |
| No | — | Canonical resource identifier published in |
| Recommended (prod) | — | Canonical public origin, e.g. |
| No |
| Server-side RBAC enforcement. When |
| No |
| Permission required for read operations (list/get/search → HTTP GET). Must match a permission defined on the Auth0 API. |
| No |
| Permission required for create/update operations (HTTP POST/PUT/PATCH). |
| No |
| Permission required for delete operations (HTTP DELETE). Set equal to |
| No |
| Optional namespaced claim also checked for permissions (alongside the standard |
| No |
| When |
| No |
| TTL for the per-user live group-membership cache. Lower = faster propagation, more Graph calls. |
| When | — | Entra security-group object ids mapped to the read / read+write / read+write+delete tiers. At least one required when live check is on. |
| No |
| Emit a structured audit record per action (authenticated user + verb + resource + outcome). In production these flow to Application Insights / Log Analytics, giving a per-user "who did what" trail despite the shared Vitally key. |
| No |
| Also audit read operations (HTTP GET). Off by default as reads are high-volume; mutations and denied attempts are always recorded. |
| No | — | Enables the OAuth proxy / DCR shim (see OAuth proxy below). When set, every Dynamic Client Registration call returns this fixed Auth0 client_id, and the server proxies |
| No | — | Confidential-client secret for |
| No |
| Allowlist of non-loopback |
| No |
| Local development only. Skips JWT validation entirely. Logs a warning at startup. |
See VitallyMcp/appsettings.Example.json for the full layout.
Running locally
Prerequisites: .NET 10 SDK.
# Restore + build + run the test suite
dotnet test VitallyMcp.sln -c Debug --nologo --verbosity minimal
# Start the server in dev mode (no Auth0, no Key Vault — uses DevelopmentApiKey from env)
$env:OAuth__NoAuth = "true"
$env:Vitally__Region = "EU"
$env:Vitally__DevelopmentApiKey = "sk_live_your_key"
$env:ASPNETCORE_URLS = "http://localhost:5099"
dotnet run --project VitallyMcp/VitallyMcp.csprojSmoke test:
# OAuth protected-resource metadata
Invoke-RestMethod http://localhost:5099/.well-known/oauth-protected-resource
# MCP initialise (returns capabilities + server info)
$body = @{ jsonrpc='2.0'; id=1; method='initialize'; params=@{ protocolVersion='2025-06-18'; capabilities=@{}; clientInfo=@{ name='smoke'; version='0.0.1' } } } | ConvertTo-Json -Depth 10 -Compress
Invoke-RestMethod -Method Post -Uri http://localhost:5099/mcp -ContentType 'application/json' -Headers @{ Accept='application/json, text/event-stream' } -Body $bodyThen add the dev server to Claude Code:
claude mcp add --transport http vitally-dev http://localhost:5099/mcpSelf-host (replicators)
Deploying your own instance for a different org or against a different Vitally tenant requires three things — none of which are in this repo, all of which are config:
An OIDC identity provider that issues RS256-signed JWTs for your users. Auth0 ID is what FISCAL uses; any compliant provider works (Auth0, Keycloak, Okta, etc.). Register an Application with identifier URI matching your
OAuth:Audiencevalue, plus a delegated scope (e.g.Tools.Access) and public-client redirect URIhttp://localhostfor MCP-client OAuth flows.An Azure Key Vault (or compatible secret store; see the swap notes in CLAUDE.md) containing your Vitally API key as a secret. Default secret name is
vitally-shared; change viaVitally:DefaultSecretRef.A container host that can run the published Docker image. Anywhere ASP.NET Core 10 runs (Azure Container Apps, AWS App Runner, GCP Cloud Run, plain Kubernetes) — Container Apps is what FISCAL uses.
FISCAL's deployment uses Azure Container Apps + Azure Key Vault + Auth0 (which federates to Microsoft Entra for sign-in) — see the Deployment section in CLAUDE.md for the shape. Anyone replicating can swap Container Apps for App Service, ACR for GHCR, Auth0 for Keycloak, etc., without touching the application code. Bicep / azd templates aren't shipped in this repo — the surface is small enough that the README description is the contract.
Architecture
VitallyMcp/
├── Program.cs # ASP.NET Core host, JwtBearer auth, MapMcp
├── OAuthOptions.cs # Authority + Audience + Resource + NoAuth dev flag
├── VitallyServerOptions.cs # Region, KeyVaultUri, secret config
├── VitallyApiKeyProvider.cs # Fetches the API key from Key Vault (cached)
├── VitallyService.cs # HTTP client + client-side JSON filtering
├── VitallyRateLimitHandler.cs # 429 retry + rate-limit warnings
└── Tools/ # One file per Vitally resource type
├── AccountsTools.cs
├── OrganizationsTools.cs
├── UsersTools.cs
├── ConversationsTools.cs
├── MessagesTools.cs
├── NotesTools.cs
├── ProjectsTools.cs
├── ProjectTemplatesTools.cs
├── TasksTools.cs
├── NpsResponsesTools.cs
├── AdminsTools.cs
├── CustomObjectsTools.cs
├── MeetingsTools.cs
├── CustomTraitsTools.cs
└── SurveysTools.csThe MCP server runs on the ModelContextProtocol.AspNetCore package using the streamable HTTP transport in stateless mode. MapMcp("/mcp") is gated by RequireAuthorization() — JWTs are validated against the Auth0 tenant configured in OAuth:Authority / OAuth:Audience. On each tool call, VitallyApiKeyProvider fetches the vitally-shared secret from Key Vault (cached in-memory for 5 min, using the server's user-assigned managed identity), and VitallyService uses it to call Vitally on behalf of all authenticated users.
OAuth proxy
When OAuth:SharedClientId is set the server runs an OAuth 2.0 proxy in front of the upstream Auth0 tenant. It serves:
Endpoint | Purpose |
| RFC 9728 protected-resource metadata — clients use it to discover the authorisation server. |
| RFC 8414 authorisation-server metadata — points |
| Captures the client's |
| Receives the Auth0 redirect, looks up the original client |
| Forwards the code-exchange to Auth0 and injects |
| RFC 7591 Dynamic Client Registration shim — always returns |
This setup exists because MCP clients implement RFC 7591 (DCR) and RFC 8252 (loopback redirect with ephemeral ports), but Auth0 third-party DCR clients trigger a per-session API consent screen and don't natively accept arbitrary loopback ports. The proxy collapses everything onto one pre-registered "first-party" Auth0 app, skipping the consent and accepting any loopback port (Claude Code, VS Code, Cursor, MCP Inspector all rotate ports between sessions). To support hosted MCP clients (e.g. Claude.ai), add their callback URL to OAuth:AllowedClientRedirectUris.
The VitallyService exposes two call patterns:
Standard envelope (
GetResourcesAsync,GetResourceByIdAsync,CreateResourceAsync,UpdateResourceAsync,DeleteResourceAsync) — for endpoints returning{results, next}. Applies client-side field and trait filtering with resource-specific defaults.Raw passthrough (
GetRawAsync,PostRawAsync,DeleteRawAsync) — for endpoints whose response shape differs from the standard envelope (surveys'{data}, custom-fields' bare array) or for sub-resource sub-paths (meeting participants, meeting transcripts).
All HTTP traffic flows through VitallyRateLimitHandler, a DelegatingHandler registered via AddHttpMessageHandler<>() in Program.cs.
Tool catalogue
The server publishes 92 MCP tools, one per Vitally REST endpoint. Each tool's [McpServerTool] attribute sets ReadOnly = true for list/get operations and Destructive = true for create/update/delete, so MCP clients can permission them in bulk.
Resource | List / search | Get | Create | Update | Delete | Sub-resources |
Accounts | ✓ | ✓ | ✓ | ✓ | ✓ | health-score breakdown |
Organizations | ✓ | ✓ | ✓ | ✓ | ✓ | — |
Users | ✓ (+search) | ✓ | ✓ | ✓ | ✓ | by account, by organisation |
Conversations | ✓ | ✓ | ✓ | ✓ | ✓ | by account, by organisation |
Messages | ✓ | ✓ | ✓ | — | ✓ | by conversation |
Notes | ✓ | ✓ | ✓ | ✓ | ✓ | by account, by organisation, note categories |
Projects | ✓ | ✓ | ✓ (from template) | ✓ | ✓ | by account, by organisation |
Project templates | ✓ | ✓ | — | — | — | project categories |
Tasks | ✓ | ✓ | ✓ | ✓ | ✓ | by account, by organisation, task categories |
NPS responses | ✓ | ✓ | ✓ | ✓ | ✓ | by account, by organisation |
Admins | search by email | — | — | — | — | — |
Custom objects | ✓ | ✓ | ✓ | ✓ | — | instances (list, search, CRUD) |
Meetings | ✓ | ✓ | ✓ | ✓ | ✓ | by account, by organisation, participants, transcripts |
Custom traits | schema discovery | — | — | — | — | — |
Custom surveys | responses (list, get) | survey question | — | — | — | — |
Full per-tool descriptions are auto-generated from the [McpServerTool] attributes — call tools/list against the server to see them all.
Security
All MCP requests require a valid JWT signed by the configured Auth0 tenant. Tokens are validated server-side against the issuer + audience and the signature.
Server-side RBAC (
Authorization:*) enforces avitally:read/vitally:write/vitally:deletepermission on every tool call, mapped from the HTTP verb at a single choke point (VitallyService.SendAsync). This is the hard backstop: theReadOnly/Destructivetool attributes are advisory hints for MCP clients, but RBAC physically prevents a caller (or a misbehaving agent) from mutating data without the permission. Permissions are sourced from Auth0 (Enable RBAC + Add Permissions in the Access Token) and assigned via roles — ideally driven by Entra group membership.Per-user audit trail (
Audit:*) — every action is logged at the choke point with the authenticated user's stable Entra subject id (sub— an opaque object id, resolvable to a person in Entra but not itself PII), HTTP verb, target resource path and outcome (denied attempts included). Because all users share one Vitally key, Vitally's own log can't attribute actions to individuals; this server-side record can, and is queryable in Application Insights / Log Analytics. Neither email nor request bodies are logged, keeping personal data out of telemetry while staying fully attributable.The OAuth proxy's
/oauth/tokenonly services theauthorization_codeandrefresh_tokengrants — it rejects any other grant before injecting the confidential client secret, so the secret can't be leveraged to mint tokens without a user sign-in.Set
OAuth:PublicBaseUrlin production so the OAuth metadata documents emit a fixed canonical origin rather than reflecting the requestHost.Vitally API keys are not distributed to clients or stored in tokens — they live in Key Vault, accessed by the server's managed identity.
Tokens are short-lived (8h access, with refresh rotation). The server keeps no session state; restart is transparent to clients.
HTTPS is terminated at the platform ingress (Container Apps managed cert) — the server itself doesn't ship TLS.
The OAuth proxy validates every client
redirect_uriagainstOAuth:AllowedClientRedirectUris(plus the implicit RFC 8252 loopback rule). Without this check, an attacker could exfiltrate authorisation codes via the proxy's/oauth/callbackreflector; with it, the proxy refuses anything that isn't a loopback URI or an explicitly-allowlisted hosted callback.
Licence
Proprietary — © FISCAL Technologies Ltd. All rights reserved.
Support
Internal: Infrastructure team at FISCAL Technologies.
Issues: GitHub Issues.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- 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/fiscaltec/vitally-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server