advancedmd-connector

advancedmd-connector

Centralized MCP server that provides a unified tool surface for accessing AdvancedMD data, managing credentials, sessions, and rate limits for multiple backend workflows and AI agents via HTTP or MCP.

Category
Visit Server

README

advancedmd-connector

advancedmd-connector is the one process in the organization that talks to AdvancedMD. Every consumer of AdvancedMD data — backend workflows (appointment-validator, srt-auths, note-audit, patient-intake), the admin-console credential check, and AI agents (Adam and any Claude Code, Cursor, or Desktop agent) — sends it a tool call over HTTP or MCP and gets back a JSON result. It holds the only AdvancedMD credentials, the only login session, and the only rate clock.

Today fifteen processes each hold AdvancedMD credentials, log in independently, and rate-limit independently against AdvancedMD's per-office-key caps (which bill $0.01 per excess call and refuse logins faster than about once a minute). The connector fixes that by owning the session and the clock centrally: one process, one rate clock, one tool surface, unchanged tool names and result shapes for every existing consumer. See SPEC.md for the full contract and docs/CONNECTOR_DECISIONS.md for why each choice was made.

Architecture

 backend workflows ------ JSON tool call ------> +-----------------------------+
 (validator, srt-auths,                          |    advancedmd-connector     |
  note-audit, intake,                            |                             |
  admin-console, chatbot)                        |  HTTP API   MCP surface     |
                                                  |      \        /             |
 agents ----------------- MCP tool call -------> |     receivers (one per      |
 (Adam via remote MCP;                           |       open request)         |
  Cursor, Claude Code,                           |          |                  |
  Desktop via stdio shim                         |     entry queue             |
  or remote MCP)                                 |          |                  |
                                                  |     worker loop  (1 at a    |
                                                  |          |        time)     |
                                                  |      handler                |
                                                  |          |                  |
                                                  |    request queue            |
                                                  |          |                  |
                                                  |     sender loop  (clock,    |
                                                  |          |        session)  |
                                                  +----------|------------------+
                                                             |  XML over HTTPS
                                                             v
                                                        AdvancedMD

One process. One port (default 8820). Everything above the dashed box is a consumer; nothing outside the box holds AMD credentials or sends XML.

Run locally in five commands

cp .env.example .env                      # fill AMD_USERNAME, AMD_PASSWORD, AMD_OFFICE_KEY
pip install -e ".[dev]"
export $(cat .env | grep -v '^#' | xargs) CONNECTOR_TOKENS_PATH=/tmp/tokens.json
connector tokens add myapp --priority interactive --tools '*'   # prints a token once
uvicorn --factory connector.app:build_app --host 0.0.0.0 --port 8820

GET http://localhost:8820/health should answer {"status": "starting"} or "ok" once the first login attempt completes. docker compose up --build runs the same thing containerized, reading the same .env.

Attach an agent

Tool names, argument schemas, and redacted result shapes are identical across all three attachment methods (SPEC 12.1), so an agent config can move from one to another without changing prompts.

Remote MCP (hosted agents, e.g. Adam) — point at the connector's streamable-HTTP surface directly:

{"mcpServers": {"amd-patients": {"type": "http",
  "url": "http://advancedmd-connector:8820/mcp/patients",
  "headers": {"Authorization": "Bearer <agent token>"}}}}

Ten routes are served: /mcp/patients, /mcp/visits, /mcp/providers, /mcp/codes, /mcp/billing, /mcp/payments, /mcp/masterfiles, /mcp/system, /mcp/ehr, and /mcp/all (the union).

Local stdio shim (agents on a workstation) — install the published advancedmd-mcp package and point it at the connector over the network; it holds no credentials and no tool logic:

{"mcpServers": {"amd-patients": {"command": "uvx",
  "args": ["advancedmd-mcp", "--domain", "patients"],
  "env": {"ADVANCEDMD_CONNECTOR_URL": "http://100.94.62.115:8820",
          "ADVANCEDMD_CONNECTOR_TOKEN": "<agent token>"}}}}

Claude Code pluginplugin/ declares all nine stdio servers with ${ADVANCEDMD_CONNECTOR_URL} and ${ADVANCEDMD_CONNECTOR_TOKEN} environment references:

claude plugin add <path or repo>/plugin

The same plugin/.mcp.json is valid for Cursor and Claude Desktop by copy.

Use it from a workflow

Backend Python services use the SDK in orlando-derm-backend/lib/advancedmd_connector/, which keeps every existing method name and typed result:

from lib.advancedmd_connector import AmdConnector

connector = AmdConnector.from_env()          # ADVANCEDMD_CONNECTOR_URL, ADVANCEDMD_CONNECTOR_TOKEN
bundle = await connector.get_patient_bundle(patient_id)
result = await connector.tool("getdemographic", patient_id=patient_id)   # generic call

The SDK holds no AMD credentials, no XML, and no AMD URL — it is HTTP only. See SPEC 13 for the full method table and exception mapping.

Issue a token

Tokens are issued and revoked with the bundled connector CLI against the token table file (CONNECTOR_TOKENS_PATH):

connector tokens add appointment-validator --priority batch --tools '*'
connector tokens add my-agent --priority interactive --tools getdemographic,lookuppatient
connector tokens list
connector tokens revoke my-agent

A plaintext token is printed once at issuance and never stored or recoverable. See docs/OPERATIONS.md for the full flag reference and docs/TOKENS.md for the token model.

Where to look when something is slow

  • GET /health (no token, internal network only) — session state, entry-queue depth and oldest wait, request-queue depth, and the rate clock's used/limit per tier, all in one call.
  • GET /metrics (no token) — Prometheus text: tool call counts and wait histograms by caller/tool/outcome, AMD request counts and post-time histograms by tier, clock used/limit/sleep-time per tier, relogin and login-refusal counters, queue depths. See SPEC 18 for the full metric list and the alert conditions in SPEC 18.2.
  • A slow AMD reply must never delay /health — the sender loop and /health run on the same event loop but blocking I/O is forbidden (SPEC 4.4), so a hung AMD call shows up as clock/queue pressure on /health, not as an unresponsive connector.

Batch schedule

The connector itself runs no batch jobs; it serializes whatever its batch-priority callers send. The consumers currently scheduled against it (SPEC 22 migration table) are appointment-validator (one nightly run), srt-auths (scan and event runs), and note-audit (one daily run). Batch-priority requests age into promotion after BATCH_AGING_MS (default 60 s) so a long batch backlog cannot starve interactive calls indefinitely (SPEC 5.3); deploys should still avoid these windows since a restart drops the in-memory session (SPEC 16.3).

Further reading

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured