In-depth architectural comparison of the Faithk7 Gmail MCP and Cv MCP Server MCP servers. Compare execution transports, security boundaries, tool capabilities, quality scores, and ready-to-paste client installation snippets for Claude, Cursor, Windsurf, and VS Code.
At a Glance & Executive Verdict
Faithk7 Gmail MCP
Communication · Local stdio
Quality: 59/100 (Good) | Auth: No auth required
Cv MCP Server
Communication · Local stdio
Quality: 65/100 (Great) | Auth: other
Verdict Summary: Choose Faithk7 Gmail MCP if you need specialized Communication tools running via a local process. Choose Cv MCP Server if your workspace requires Communication integration with local subprocess execution. Both servers can be configured concurrently in your client's mcpServers manifest.
Which MCP Server Should You Choose?
Choose Faithk7 Gmail MCP when:
You need dedicated capabilities in the Communication domain.
You prefer local stdio subprocess transport architecture.
Your security boundary fits: No auth required (Free / Open Source).
You have access to required keys: CLIENT_ID, CLIENT_SECRET, REFRESH_TOKEN.
Manage Gmail messages, threads, labels, drafts, and settings from your workflows. Send and organiz…
MCP Server that connects AI Agents to Carbon Voice. Create, manage, and interact with voice messages, conversations, direct messages, folders, voice memos, AI actions and more in Carbon Voice.
Faithk7 Gmail MCP is categorized under Communication and uses a local stdio subprocess. In contrast, Cv MCP Server belongs to Communication using local stdio subprocess. Select Faithk7 Gmail MCP when you need capabilities focused on communication and Cv MCP Server when you require tools for communication.
List messages with filtering by date, conversation, folder, workspace, creator or language.
USE WHEN: The general-purpose message reader; full bodies incl. transcript and AI summary. Max date span 183 days. `user_ids` filters by SENDER — for messages exchanged WITH someone, pass `conversation_id` from `list_conversations`. Use presigned URLs as-is.
USE INSTEAD: `get_recent_messages` for a quick look at the latest few (hard-capped at 10, no paging). `search_message_ids` for filters this cannot express — notified state, mentions or labels.
FIRST: `workspace_id` comes from `get_workspaces_basic_info` (field `id`) — call it first if you don't have one.
EXAMPLE: {"workspace_id":"ws-abc","start_date":"2026-09-01T00:00:00Z","size":25}
RETURNS: `{page, size, sort_direction, total, results_count, has_next_page, filters, results: [{id, transcript?, ai_summary?, audio_url?, creator_id, conversation_id?, duration_ms, reply_count, status, type, created_at, ...}]}`. Page on `has_next_page`/`total` — do not guess.
NARROW: pass response_fields ["total","has_next_page","results.id","results.transcript","results.created_at"] unless you need more — the full payload is much larger.
get_message
Get one message by ID, optionally expanded with related records.
USE WHEN: You have a message ID. `fields` ADDS related data (`conversation`, `creator`, `labels`) — it does not narrow the response. Use `response_fields` to narrow.
USE INSTEAD: `list_messages` when you do not have an ID, or need several messages — it already returns full bodies, so fetching each one again is wasted.
FIRST: `id` comes from `list_messages` (field `results[].id`) — call it first if you don't have one.
EXAMPLE: {"id":"msg-abc","fields":"creator"}
RETURNS: `{message: {id, transcript?, ai_summary?, audio_url?, creator_id, duration_ms, status, type, attachments?, created_at, ...}}`.
get_recent_messages
Get up to 10 of the most recent messages, each with its conversation, creator and labels.
USE WHEN: A quick "what just happened" glance. Pre-joined, so no follow-up calls for creator or conversation names.
USE INSTEAD: `list_messages` whenever you need more than 10, any date range, paging, or a filter other than conversation and language — this tool supports none of those.
EXAMPLE: {"conversation_id":"conv-abc"}
RETURNS: `{results: [{message: {...}, conversation: {...}, creator: {...}, labels: [...]}]}`. No total and no paging: the cap of 10 is the whole answer.
create_conversation_message
Post a message into an existing conversation, or reply in a thread.
USE WHEN: You have a `conversation_id`. Pass `parent_id` (a message ID) to reply as a thread. Either `transcript` or `links` is required — the schema marks neither individually, so both param descriptions say so.
USE INSTEAD: `create_direct_message` to reach people who are not already in a conversation. `create_voicememo_message` for a standalone memo.
FIRST: `id` comes from `list_conversations` (field `results[].id`) — call it first if you don't have one.
EXAMPLE: {"id":"conv-abc","transcript":"Agreed, shipping Friday."}
RETURNS: `{message: {id, link, transcript?, status, type, conversation_id, created_at, ...}}`.
ERROR BAD_REQUEST: Neither `transcript` nor `links` was provided. — Pass at least one of them.
create_direct_message
Send a direct message to one or more people, by user ID or email.
USE WHEN: Reaching people outside an existing conversation. Address it with `to.user_ids` or `to.emails`. Requires `transcript` or `links`.
USE INSTEAD: `create_conversation_message` when a conversation already exists — a DM starts a separate thread rather than joining it.
FIRST: `to.user_ids` comes from `search_users` (field `id`) — call it first if you don't have one.
EXAMPLE: {"to":{"user_ids":["user-abc"]},"transcript":"Quick question about the deck."}
RETURNS: `{message: {id, link, transcript?, status, conversation_id, created_at, ...}}`.
ERROR BAD_REQUEST: A user ID is invalid, or neither `transcript` nor `links` was provided. — Resolve people with `search_users` — never pass a display name as a user ID — and include a transcript or links.
create_voicememo_message
Create a voice memo, either from text (spoken via text-to-speech) or from an audio file at a URL.
USE WHEN: Pass `transcript` (2-5000 chars) to have Carbon Voice speak the text, or an https `audio_url` to upload audio, which wins over `transcript`. File it with `folder_id`, whose type must match, or a `workspace_id`.
USE INSTEAD: `create_conversation_message` to post into an existing conversation, or `create_direct_message` to send to specific people. A voice memo is standalone and lives in a folder or workspace.
EXAMPLE: {"transcript":"Reminder to review the pricing deck before Friday."}
RETURNS: `{message: {id, link, transcript?, audio_url?, duration_ms, status, type, created_at, ...}}`. `status` is often `processing` at first.
ERROR INVALID_AUDIO_URL: `audio_url` is not https, unreachable, too large, timed out, embeds credentials, or resolves to a private address. — The message gives the reason. Use a public https URL, or pass `transcript` instead.
ERROR BAD_REQUEST: None of `transcript`, `audio_url` or `links` was provided, or the transcript is outside 2-5000 characters. — Provide one of the three, and keep the transcript within the length limits.
add_attachments_to_message
Attach one or more link URLs to an existing message.
USE WHEN: Adding external links to a message that already exists.
USE INSTEAD: `create_message_share_link` to share a Carbon Voice message outward — that produces a link, this consumes them.
FIRST: `id` comes from `list_messages` (field `results[].id`) — call it first if you don't have one.
EXAMPLE: {"id":"msg-abc","links":["https://example.com/spec"]}
RETURNS: `{...}` confirmation with the resulting attachments.
get_user
Get a user's full profile by ID — names, languages, voice settings, workspace roles.
USE WHEN: You already have a user ID and need complete details.
USE INSTEAD: `search_user` / `search_users` to FIND someone by email, phone or name. `get_current_user` for the caller — this tool needs an explicit ID and will not default to you.
FIRST: `id` comes from `search_users` (field `id`) — call it first if you don't have one.
EXAMPLE: {"id":"user-abc"}
RETURNS: `{id, first_name, last_name?, languages, voice_gender, workspace_ids, workspace_roles, user_type, created_at, ...}`.
NARROW: pass response_fields ["id","first_name","last_name","workspace_ids"] unless you need more — the full payload is much larger.
search_user
Find a single user by email, phone or name.
USE WHEN: Resolving ONE person. Supply exactly one of `email`, `phone` or `name`. Name search only matches your own contacts.
USE INSTEAD: `search_users` for several people in one call — it takes arrays and saves a round trip per person. `get_user` when you already have the ID.
EXAMPLE: {"email":"someone@example.com"}
RETURNS: `{id, full_name, first_name, last_name?, link, image_url?, languages?, ...}`. Use `id` wherever another tool asks for a user ID.
ERROR NOT_FOUND: Nobody matched, or a name search hit a non-contact. — Try an email or phone instead of a name; name search is limited to your contacts.
search_users
Resolve several users at once by emails, phones, IDs or names.
USE WHEN: Turning a list of people into user IDs in one call — the right first step before any tool that takes user IDs. Name search only matches your contacts.
USE INSTEAD: `search_user` for a single lookup. `get_user` for a full profile once you have the ID.
EXAMPLE: {"names":["Brett"]}
RETURNS: Array of `{id, full_name, first_name, last_name?, link, languages?, ...}`. If a name returns more than one candidate, ask which person was meant rather than guessing.
NARROW: pass response_fields ["id","full_name"] unless you need more — the full payload is much larger.
get_current_user
Get the calling user's own identity, workspaces and settings.
USE WHEN: Establishing who you are acting as, or finding the caller’s workspace IDs before a workspace-scoped call. Takes no arguments.
USE INSTEAD: `get_user` for somebody else (it requires an explicit ID). `get_workspaces_basic_info` if you only need workspace IDs and names — it is far smaller than this response.
EXAMPLE: {}
RETURNS: `{success, user: {user_guid, first_name, last_name?, email_txt?, phone_txt?, workspace_guids, identities, entries, environments, lifecycle_events, notification_settings, settings, ...}, settings: {...}}`. This payload is LARGE — several unbounded arrays and an open settings map.
NARROW: pass response_fields ["user.user_guid","user.first_name","user.email_txt","user.workspace_guids"] unless you need more — the full payload is much larger.
list_conversations
List your conversations from the last 6 months, optionally filtered by participants, type and name.
USE WHEN: Finding a `conversation_id`. Filter with `user_ids` plus `match`, `types` and `name` — YOUR DM with someone is `user_ids: ["<their id>"], types: ["directMessage"]`. You are always an implicit participant, so never pass your own ID. Filters AND together; if several match, ask which was meant.
USE INSTEAD: `get_conversation` when you already have an ID and want full detail — this returns only id, name, workspace_id and type.
EXAMPLE: {"user_ids":["user-abc"],"types":["directMessage"]}
RETURNS: `{results_count, results: [{id, name, workspace_id, type}]}` where type is `directMessage` | `customerConversation` | `namedConversation` | `asyncMeeting`. No paging: `results_count` is what is returned, after filtering. `name` adds `unfiltered_count`: rows the name was matched against, AFTER `user_ids`/`types`. ALWAYS check it before saying no such conversation exists. 0 of 47 means none matched that string (misspelt, or >6 months old); 0 of 0 means your other filters left nothing — not that the caller has none. Widen the filters or ask; never report it does not exist.