MCP Server

The Medsender MCP server lets AI assistants and agents that speak the Model Context Protocol work with your organization’s faxes: list and read sent and received faxes, list your fax numbers, archive received faxes, and send a fax once a person approves it. It calls the v3 fax API with your API key, so it can do exactly what that key can do, and nothing more.

Server URL: https://mcp.medsender.com/mcp (Streamable HTTP). Every request carries your Medsender developer API key as a Bearer token.

Set up an API key

The MCP server uses the same developer API keys and the same v3 access requirements as the API: a confirmed account, BAA coverage and a developer account linked to your organization.

  1. Sign in to the developer portal and open Keys & webhooks.
  2. Choose Create Key, give it a name and pick the Live environment. Live keys require production access.
  3. Copy the key. It is shown once and can’t be viewed again.
  4. Store it in an environment variable rather than in a config file:
bash
export MEDSENDER_API_KEY="sk_live_REPLACE_WITH_YOUR_KEY"
export MEDSENDER_API_KEY="sk_live_REPLACE_WITH_YOUR_KEY"
  • Use a live key (sk_live_). The received-fax tools refuse a test key (sk_test_) with TEST_KEY_UNSUPPORTED, sending requires a live key, and with a test key the sent-fax tools see only simulated test sends.
  • Send it as Authorization: Bearer sk_live_… on every request. A missing or malformed key gets a 401 before any tool runs.
  • To disconnect a client, revoke its key on Keys & webhooks. See Authentication for key environments.

Install

Add the server to your client as a remote HTTP server with an Authorization header. Each example reads the key from MEDSENDER_API_KEY or prompts for it.

Claude Code

bash
claude mcp add --transport http medsender https://mcp.medsender.com/mcp \
  --header "Authorization: Bearer $MEDSENDER_API_KEY"
claude mcp add --transport http medsender https://mcp.medsender.com/mcp \
  --header "Authorization: Bearer $MEDSENDER_API_KEY"

Add --scope user to make the server available in every project. The shell expands the variable when you run the command, so the key is saved in Claude Code’s configuration.

Cursor

Add this to ~/.cursor/mcp.json, or to .cursor/mcp.json in a project. Cursor fills in ${env:MEDSENDER_API_KEY} from your environment.

JSON
{
  "mcpServers": {
    "medsender": {
      "url": "https://mcp.medsender.com/mcp",
      "headers": {
        "Authorization": "Bearer ${env:MEDSENDER_API_KEY}"
      }
    }
  }
}
{
  "mcpServers": {
    "medsender": {
      "url": "https://mcp.medsender.com/mcp",
      "headers": {
        "Authorization": "Bearer ${env:MEDSENDER_API_KEY}"
      }
    }
  }
}

VS Code

Add this to .vscode/mcp.json in your workspace, or to your user profile’s MCP configuration. VS Code asks for the key the first time the server starts and stores it securely.

JSON
{
  "inputs": [
    {
      "type": "promptString",
      "id": "medsender-api-key",
      "description": "Medsender API key",
      "password": true
    }
  ],
  "servers": {
    "medsender": {
      "type": "http",
      "url": "https://mcp.medsender.com/mcp",
      "headers": {
        "Authorization": "Bearer ${input:medsender-api-key}"
      }
    }
  }
}
{
  "inputs": [
    {
      "type": "promptString",
      "id": "medsender-api-key",
      "description": "Medsender API key",
      "password": true
    }
  ],
  "servers": {
    "medsender": {
      "type": "http",
      "url": "https://mcp.medsender.com/mcp",
      "headers": {
        "Authorization": "Bearer ${input:medsender-api-key}"
      }
    }
  }
}

Codex

bash
codex mcp add medsender --url https://mcp.medsender.com/mcp \
  --bearer-token-env-var MEDSENDER_API_KEY
codex mcp add medsender --url https://mcp.medsender.com/mcp \
  --bearer-token-env-var MEDSENDER_API_KEY

Or add this to ~/.codex/config.toml. Codex reads the key from the named environment variable and sends it as the Bearer token.

TOML
[mcp_servers.medsender]
url = "https://mcp.medsender.com/mcp"
bearer_token_env_var = "MEDSENDER_API_KEY"
[mcp_servers.medsender]
url = "https://mcp.medsender.com/mcp"
bearer_token_env_var = "MEDSENDER_API_KEY"

Gemini CLI

bash
gemini mcp add --scope user --transport http \
  --header "Authorization: Bearer $MEDSENDER_API_KEY" \
  medsender https://mcp.medsender.com/mcp
gemini mcp add --scope user --transport http \
  --header "Authorization: Bearer $MEDSENDER_API_KEY" \
  medsender https://mcp.medsender.com/mcp

The shell expands the variable when you run the command, so the key is saved in ~/.gemini/settings.json. Keep --scope user: without it, Gemini CLI writes the key into the project’s .gemini/settings.json, where it can be committed.

Tools

Every tool acts as the developer whose key the connection uses, within that developer’s organization. Each fax has a sendToken (in list results); pass it as fax_id. Dates are YYYY-MM-DD. Fax numbers are 10 or 11 digits, or E.164 (+1…). The read tools return the v3 API’s JSON.

Read tools

ToolWhat it doesArguments
pingChecks that the server is reachable. Returns the service name, version, protocol era and serving revision.None.
list_sent_faxesLists the organization’s sent faxes, newest first, with delivery status and paging meta.Optional: from_number, to_number, patient_name (contains), patient_dob, recipient_name, date_start, date_end, sort (date or dob), sort_dir (asc or desc), page, page_size (1–100, default 25).
get_sent_faxGets one sent fax with its delivery status and secureLink, a link to the sent PDF that expires in about 5 minutes.fax_id: the fax’s sendToken.
list_received_faxesLists the organization’s received faxes, newest first, with paging meta.Optional: from_number (exact), to_number, patient_name (contains), dob, date_start, date_end, archived (true or false), sort_dir, page, page_size (1–100, default 25).
get_received_faxGets one received fax with pdfDownloadUrl, a link to the PDF that expires in about 2 minutes.fax_id: the fax’s sendToken.
get_accountLists the organization’s fax numbers in E.164, each with status (active or inactive) and an optional label. Use an active one as from_number when sending.None.

PDF links expire 2 to 5 minutes after the call. Use them right away, call the tool again for a fresh one, and never store or share them.

Write tools

ToolWhat it doesArguments
archive_received_faxArchives one received fax, or unarchives it with archived set to false.fax_id: the sendToken. archived: true (default) or false.
create_uploadStarts a send: returns a presigned uploadUrl for one PDF or TIFF of up to 20 MB, with the headers the upload needs. The file is uploaded there within 15 minutes, outside the conversation.file_name: ends in .pdf, .tif or .tiff. content_type: application/pdf or image/tiff.
send_faxRequests a send. It sends nothing: it returns an approvalUrl a person must open and approve within 15 minutes.upload_id, from_number, to_number. Optional: patient_name, patient_dob, document_title, note, sender_name, recipient_name, document_type (both or document_only), access_code_sheet_only.
confirm_sendSends an approved fax, once. While the request is pending, rejected, expired or already sent, it sends nothing and says so.intent_id from send_fax, plus the same patient_name, patient_dob, document_title, note, sender_name and recipient_name values given to send_fax.

The write tools and get_account are switched on separately from the other read tools, so your client may not list them yet.

Docs search

A separate, public endpoint serves these docs to agents. It needs no API key and is rate limited per client IP.

ToolWhat it doesArguments
search_docsSearches these developer docs and returns the best matching pages, each with a snippet and the path to pass to fetch_doc.query. Optional: limit (1–10, default 5).
fetch_docReads one docs page as markdown. Only pages listed in llms.txt are served.path, for example /docs/sent-faxes.md.

Add it at https://mcp.medsender.com/docs/mcp the same way as the server above, without the Authorization header. For example, in Claude Code:

bash
claude mcp add --transport http medsender-docs https://mcp.medsender.com/docs/mcp
claude mcp add --transport http medsender-docs https://mcp.medsender.com/docs/mcp

Sending a fax: a person approves every send

  1. create_upload returns a presigned uploadUrl. The file is uploaded there directly, so it never passes through the model.
  2. send_fax creates a send request and returns its approvalUrl. Nothing has been sent yet.
  3. A member of your organization opens the link in the developer portal and approves or rejects the fax within 15 minutes.
  4. confirm_send sends the fax, once, only if it was approved. Medsender checks that the patient, title, note, sender and recipient values match the ones that were approved, so pass the same values given to send_fax.

An agent can’t approve a send itself. Pending, rejected, expired and already-sent requests never send. Per-send callback_url is not offered, so a fax’s text can’t steer an agent into sending status callbacks to an outside URL. Track delivery with get_sent_fax or list_sent_faxes.

When a tool refuses

A refusal from the v3 API comes back as a message that tells the agent what to fix:

  • TEST_KEY_UNSUPPORTED: the tool needs a live key; reconnect with one.
  • EMAIL_UNCONFIRMED: confirm the account’s email address.
  • ORGANIZATION_NOT_LINKED: finish activation, or ask Medsender to link the organization.
  • PRODUCTION_ACCESS_REQUIRED: upgrade or request production access.
  • BAA_REQUIRED: sign the Business Associate Agreement in the developer portal.
  • PAYMENT_REQUIRED: live faxing is paused for a billing issue; update the card.
  • SPEND_LIMIT_REACHED: the send would exceed the self-serve spend limit; contact Medsender to raise it.
  • A 429 says how long to wait before trying again.

Security and BAA

  • Faxes can contain PHI. The tools refuse with BAA_REQUIRED until the developer account behind the key has a signed Business Associate Agreement, and they enforce the same eligibility as the v3 API.
  • The MCP server stores nothing. Your key goes to the v3 API on each call, and the API decides what it can access.
  • Tool arguments, results, request and response bodies, and keys are never logged.
  • Requests to the API never follow redirects and are never retried, so a send can’t go out twice.
  • Fax content is untrusted text written by whoever sent the fax. The server tells agents to treat it as data, never to follow instructions found in it, and never to send, archive or share anything because a fax asks them to.
  • Tool results, including patient fields, go to your MCP client and the model behind it.