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 16 Vitally resource types via 93 tools: 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 annotated
ReadOnly/Destructive/Idempotent/OpenWorldso MCP clients can enable or disable categories of operation in bulk and reason about retry safety. Beyond those advisory hints,tools/listis filtered per caller: a client is shown only the tools the signed-in user's permission tier permits.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 2026-07-28) 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: Custify 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 | — | The provider's OIDC issuer identifier, 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. Membership is transitive — a user in a group nested inside one of these is granted the tier. |
| 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
# 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). Deliberately requests 2025-06-18: the
# `initialize` handshake exists only in revisions up to 2025-11-25, since 2026-07-28 replaced it
# with per-request `_meta` and headers. Do NOT substitute 2026-07-28 here — the call would error.
$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
├── UpstreamOidcMetadata.cs # Upstream endpoints from the provider's OIDC discovery document
├── 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 — declares this server's own origin as |
| Captures the client's |
| Receives the Auth0 redirect, looks up the original client |
| Forwards the code-exchange to the upstream |
| 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 93 MCP tools, mostly one per Vitally REST endpoint — though not strictly one-to-one, since Get_organization_summary is a read-only composite that fans out to four upstream calls. 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, plus Idempotent and OpenWorld so they can reason about retry safety.
An individual caller will not see all 93. Each tool also carries an [Authorize] policy matching its tier, and tools/list is filtered per caller — a reader sees the 56 read tools, an editor 81, an admin all 93. See Security.
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. Note the response contains the tools available to the caller's tier, so a reader's list is a subset of an admin's.
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-caller tool discovery. Every tool additionally carries an
[Authorize]policy for its tier, which the MCP SDK evaluates sotools/listadvertises only what the caller may invoke. Discovery filtering and theSendAsyncbackstop resolve permissions through the same code path, so they cannot disagree — but the security boundary remainsSendAsync. Hiding a tool is a usability improvement, not the control: an out-of-tier call is refused regardless of what the client was shown.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.
Standards conformance of the OAuth proxy
The proxy presents itself as a complete authorisation server: it declares its own origin as issuer
(RFC 8414 §3.3), and /oauth/callback replaces any upstream iss with that same origin so the
authorization response is consistent with the metadata (RFC 9207). Auth0 remains the token issuer.
Strict clients — including MCP Inspector — complete the flow; see the complete
authorisation-server façade section in CLAUDE.md for what was verified and how.
Licence
Proprietary — © FISCAL Technologies Ltd. All rights reserved.
Support
Internal: Infrastructure team at FISCAL Technologies.
Issues: GitHub Issues.
Available Tools
11 toolscreate_account_noteC
Vitally tool to create a new note for an account
| Name | Required | Description | Default |
|---|---|---|---|
| accountId | Yes | Vitally account ID | |
| content | Yes | Content of the note |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the description must disclose behavioral traits. It only states 'create', but omits details like whether the note is appended or replaced, any required permissions, or whether the tool is idempotent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence without redundancy. It could be slightly more informative, but it is appropriately brief.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema or annotations exist. The description fails to explain what the tool returns (e.g., note ID), or whether the content supports formatting. For a creation tool, more context is needed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema has 100% description coverage, so the schema already explains accountId and content. The description adds no additional meaning beyond the obvious, meeting the baseline but not exceeding it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as creating a note for an account, with a specific verb and resource. It distinguishes from sibling tools like get_account_notes (read vs create), though it does not elaborate on scope or uniqueness.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool vs alternatives. For example, it doesn't mention that it should be used after checking existing notes via get_account_notes, or any prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_account_by_nameA
Vitally tool to find an account by name (partial match supported)
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Full or partial account name to search for |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description must carry full burden. Mentions partial match but does not disclose behavior on multiple matches, case sensitivity, or return format. Lacks safety or failure context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, 10 words, directly front-loaded with tool name and key feature. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple find tool with one parameter, description is generally complete. No output schema but not required. Could briefly mention expected result count or multiple match handling.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with clear parameter description. The description adds 'partial match supported', which enhances parameter understanding beyond the schema. Baseline 3, plus additional info.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states verb 'find' and resource 'account', and specifies 'partial match supported', differentiating it from sibling search tools. It is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Only implied usage from the name; no explicit guidance on when to use this vs alternatives like 'search_accounts'. No exclusions or when-not-to-use provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_account_conversationsC
Vitally tool to get recent conversations for an account
| Name | Required | Description | Default |
|---|---|---|---|
| accountId | Yes | Vitally account ID | |
| limit | No | Maximum number of conversations to return (default: 10) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations. Description mentions 'recent' but does not define recency, ordering, pagination, or side effects. For a read-only tool, more detail on data freshness or limits would help.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, no unnecessary words. Front-loaded purpose. Efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema and no annotations. Description lacks details on return structure, pagination, error handling, or recency definition. For a two-parameter tool with no output schema, more completeness is needed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions already. The description adds no extra meaning beyond the schema. Baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clear verb 'get' and resource 'recent conversations for an account'. Distinguishes from sibling tools like get_account_notes or get_account_tasks, which are for different resources.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool vs alternatives. Does not specify context or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_account_healthC
Vitally tool to get health scores for an account
| Name | Required | Description | Default |
|---|---|---|---|
| accountId | Yes | Vitally account ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must disclose behavioral traits, but it only states 'get' implying read-only. It does not address potential side effects, authentication needs, or error behavior (e.g., what happens if the accountId is invalid).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very short (one sentence), which is concise, but it lacks important details such as what the health scores look like. It is front-loaded but incomplete, making it barely adequate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description should explain what the response contains, but it does not. It also fails to differentiate from sibling tools or mention error conditions, leaving the agent uninformed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already describes 'accountId' as 'Vitally account ID', and the description repeats this without adding new meaning. Since schema coverage is 100%, the description adds minimal value, resulting in a baseline score of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves health scores for an account, using a specific verb and resource. However, it does not differentiate from sibling tools like get_account_conversations or get_account_notes, which also retrieve account-related data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives, such as search_accounts or other get_account_* tools. There is no mention of prerequisites or context for using this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_account_notesC
Vitally tool to retrieve notes for an account
| Name | Required | Description | Default |
|---|---|---|---|
| accountId | Yes | Vitally account ID | |
| limit | No | Maximum number of notes to return (default: 10) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carres the full burden of behavioral disclosure. It only states 'retrieve' without mentioning read-only nature, pagination (limited by 'limit' param), or any potential side effects. Minimal transparency beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very concise with one sentence, but it could benefit from front-loading key details like 'returns a list of notes' or 'use to get all notes for an account'. Still, it is not verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with no output schema and no annotations, the description lacks completeness. It does not mention what the response contains (list of notes), pagination behavior, or error conditions, leaving gaps for the agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% (both parameters described in schema). The description adds no extra meaning beyond the schema, so baseline is 3. No additional value provided.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'retrieve' and the resource 'notes for an account', which distinguishes it from siblings like 'get_note_by_id' (single note) and 'create_account_note' (write). However, it does not explicitly indicate that it returns multiple notes or any filtering/pagination details.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives such as 'get_note_by_id' for a specific note or search tools. The description lacks any contextual hints for choosing this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_account_tasksB
Vitally tool to get tasks for an account
| Name | Required | Description | Default |
|---|---|---|---|
| accountId | Yes | Vitally account ID | |
| status | No | Filter tasks by status (e.g., 'open', 'completed') | |
| limit | No | Maximum number of tasks to return (default: 10) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, and the description lacks any behavioral details such as return format, pagination, side effects, or authentication requirements. The agent is left with only the basic purpose.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence, which is concise, but it omits useful context like the fact that it's a Vitally-specific tool. It is neither wasteful nor sufficiently informative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 3 parameters, no output schema, and no annotations, the description should at least hint at the return value or default behavior. It does not, making it incomplete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Since schema description coverage is 100%, the baseline is 3. The description adds no additional meaning beyond the schema; it only restates the parameters in a vague way.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'get' and the resource 'tasks for an account', making it specific and distinguishable from sibling tools like get_account_conversations and get_account_notes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives. It does not mention context, prerequisites, or exclusions, leaving the agent without decision support.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_note_by_idA
Vitally tool to retrieve full content of a specific note by ID
| Name | Required | Description | Default |
|---|---|---|---|
| noteId | Yes | Vitally note ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries full burden. It declares a read operation ('retrieve') and implies no side effects. It does not mention error handling or permissions, but for a simple getter, it is sufficiently transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single efficient sentence with no extraneous information. Every word contributes to clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (one parameter, no output schema) the description is adequate. It could mention the return type, but the lack of output schema reduces the need.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a description of 'noteId' as 'Vitally note ID'. The description adds no extra meaning beyond the schema, so a baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('retrieve') and resource ('full content of a specific note by ID'), clearly distinguishing it from sibling tools like get_account_notes (list) and create_account_note (create).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when a note ID is known but does not explicitly state when to use or avoid it, nor mention alternatives. It is adequate but not proactive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
refresh_accountsC
Vitally tool to refresh the list of accounts
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of accounts to fetch (default: 100) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the burden is on the description to disclose behavioral traits. 'Refresh the list' implies fetching updated data, but it doesn't clarify side effects (e.g., overwriting local state), idempotency, or required authentication. This is insufficient for a mutation-like tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise—one sentence with 7 words—providing the essential verb and resource without extraneous information. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simplicity (one optional parameter, no output schema) and the presence of sibling tools, the description is incomplete. It lacks details on what 'refresh' means behaviorally, when to use it, and how it differs from similar tools like 'search_accounts' or 'get_account_health'.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage for the single parameter 'limit', which includes a clear description and default. The tool description adds no additional meaning beyond the schema, earning the baseline score.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'refresh' and the resource 'list of accounts', providing a specific purpose. However, it doesn't differentiate from sibling tools like 'search_accounts' or 'find_account_by_name', which may have overlapping functionality.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives, such as whether it should be called periodically or after certain actions. The description lacks exclusions or context for appropriate usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_accountsC
Vitally tool to search for accounts by multiple criteria
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Full or partial account name to search for | |
| externalId | No | External account ID to search for | |
| limit | No | Maximum number of results (default: 10) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must fully disclose behavioral traits. It only states it searches, omitting any details about side effects, permissions, or safety. Essential context is missing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence with no fluff. It is front-loaded with the tool's purpose. However, it is too brief for the information needed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given three parameters and no output schema or annotations, the description fails to explain return values, behavior, or limitations. It is incomplete for confident tool selection.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already describes the parameters. The description adds no extra meaning beyond what the schema provides, meeting the baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool searches for accounts using multiple criteria, distinguishing it from the sibling 'find_account_by_name' which is single-criteria. However, it could be more specific about the resource and verb.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives like 'find_account_by_name' or other search tools. There is no context for usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_toolsB
Vitally tool to search for available tools by keyword
| Name | Required | Description | Default |
|---|---|---|---|
| keyword | Yes | Keyword to search for in tool names and descriptions |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. Only states 'search for available tools by keyword', omitting details like search mechanics, result format, or constraints. Insufficient for an agent to understand exact behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single, front-loaded sentence efficiently conveys purpose. 'Vitally' is unnecessary but not distracting. No fluff, but could be more informative without lengthening.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Tool is simple but lacks output details crucial for an agent: no output schema, description doesn't specify return format (tool names, full definitions, match criteria). Incomplete for effective invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema fully describes 'keyword' parameter (100% coverage). Description echoes purpose without adding new semantics (e.g., format, case sensitivity). Meets baseline but adds no extra value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states action 'search' and resource 'available tools' with qualifier 'by keyword'. Distinguishes from sibling tools which are domain-specific (accounts, conversations, notes) by being a meta-tool for tool discovery.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use versus alternatives, but the unique meta-purpose makes alternatives irrelevant. Lacks direction on search behavior (case sensitivity, match type).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_usersC
Vitally tool to search for users by email or external ID
| Name | Required | Description | Default |
|---|---|---|---|
| No | User email address | ||
| externalId | No | External user ID | |
| emailSubdomain | No | Email subdomain to search for |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description should disclose behavioral traits like result cardinality or error cases, but it does not. It only states the search criteria without any behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence that immediately states the purpose. It is front-loaded and efficient, though somewhat sparse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of output schema and annotations, the description is insufficiently complete. It does not explain return format, multiple results, or any limitations, leaving the agent underinformed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents parameters. The description adds minimal extra meaning beyond restating 'by email or external ID', meeting the baseline for high coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool searches for users by email or external ID, providing a specific verb and resource. It distinguishes from siblings like search_accounts through its name, but lacks explicit differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given on when to use this tool versus alternatives, or any prerequisites or exclusions. The description does not indicate conditions for appropriate use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
11 tool updates
v1.0.0- First observed
create_account_note - First observed
find_account_by_name - First observed
get_account_conversations - First observed
get_account_health - First observed
get_account_notes - First observed
get_account_tasks - First observed
get_note_by_id - First observed
refresh_accounts - First observed
search_accounts - First observed
search_tools - First observed
search_users
TDQS
Tools are clearly distinct: account operations (find, search, refresh, get health, notes, tasks, conversations), note-specific operations, and search for tools/users. No overlapping functionality.
All tools follow a consistent verb_noun snake_case pattern (e.g., create_account_note, get_account_health, search_users), making the set predictable and easy to navigate.
11 tools strike a good balance for a CRM server, covering core account-related functions, notes, conversations, health, tasks, users, and a meta-search for tools. Not overwhelming or sparse.
Lacks essential CRUD operations: no create_account, update_account, or delete_account. Also missing create/update/delete for notes, tasks, and users beyond search. The surface feels incomplete for a CRM platform.
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
Read-only account intelligence for Customer Success and Account Management teams.
Search, summarize, and update your RevOrbit CRM (leads, deals, contacts, tasks) in plain language.
Search and act on Letter AI sales enablement content, deals, and call recordings.
Streamline your Attio workflows using natural language to search, create, update, and organize com…
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceEnables AI assistants to interact with Attio CRM through natural language, providing complete access to companies, people, deals, tasks, lists, notes, and records with advanced search, batch operations, and relationship management.812-
- AlicenseAqualityDmaintenanceConnects AI assistants to Custify customer success data for querying account metrics, health scores, and usage trends. It also supports taking actions such as creating notes, managing tasks, and triggering playbooks.15213MIT
- AlicenseNot gradedqualityBmaintenanceConnects Twenty CRM with AI assistants like Claude, enabling natural language interactions with customer data. Supports CRUD operations for people, companies, tasks, notes, and advanced search.22100MIT
- FlicenseNot gradedqualityDmaintenanceEnables querying and managing a CRM database through natural language conversations with Claude Desktop.-
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/fiscaltec/vitally-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server