Note · 2026-09-21

Keep Secrets Out of the Prompt with MCP Connectors

A practical look at how MCP servers front real systems so your assistant calls tools without ever seeing a password or API key.

When an assistant reaches a live scheduling system or an EHR, the worst design is to paste a username, password, or API key into the prompt. The model should ask for a task, not carry the secret. This post explains the connector pattern that keeps credentials in a server process and out of the model context.

Why prompts are the wrong place for secrets

A prompt is copied more than people expect. It may be logged by the model provider, stored for retry, shown in a debugging UI, or forwarded through an observability tool. If a secret is in that text, every copy becomes another place to leak. Even if the model never intentionally reveals it, an injection or a confused instruction can make the assistant repeat part of its context.

The alternative is to separate transport from content. The assistant needs enough information to call a tool: the tool name, a description, and the parameters it can pass. It does not need the bearer token that the server will attach. Putting secrets in the process environment or a local secret manager means the prompt stays small and unprivileged. This is the same reason a web server reads a database password from an environment variable instead of hardcoding it in the HTML.

For tools that wrap real systems like a fibre scheduling helper or a Practice Fusion EHR connector, the risk is higher because those systems contain customer data and operational schedules. A leaked API key is not an abstract problem; it is a direct path to patient records or appointment changes.

The MCP server boundary

MCP stands for Model Context Protocol. You can think of it as a narrow contract between an assistant and a tool. The server runs as a separate process on your own machine or in your own cloud account. It loads credentials from a configuration file or secret store. It then exposes a small set of tool definitions to the assistant.

FTTHelper and a Practice Fusion connector are examples of this class. I am not listing their current action schemas here because those change and need a licence check before reuse. The point is not the exact tool names, but where the token lives. In a clean MCP setup, the token never enters the model prompt. The assistant sees a tool called something like "get appointments for a date range" and knows it can pass a date. The server turns that call into an authenticated request to the real system.

This boundary also changes how you debug. If a call fails, you inspect the server log on your own infrastructure, not the model transcript. You can review which tool was called and with what parameters without exposing raw credentials in a chat interface. For an example of how this fits into a larger automation flow, see the notes on n8n.

What the assistant actually sees

A well-designed MCP server exposes only the minimum surface. The assistant sees:

  • A tool name and a one-line description.
  • The input parameters, with types and constraints.
  • The output shape, clearly typed.
  • An error message if the server rejects the call.

It does not see:

  • The base URL of the internal API, if you choose to hide it.
  • The client ID or secret.
  • The database connection string.
  • Any retry or audit metadata you keep in the server.

This is not a vague best practice; it is a practical separation. You can run the assistant in one process and the MCP server in another. The assistant can be replaced, re-prompted, or reset without touching the credential store. That is useful when you are testing a new model or trying a different orchestration library.

Scoping and rotating credentials

Separating secrets from prompts is only half the work. The credential the MCP server holds should be scoped to the smallest set of actions required. For an appointment scheduler, that might mean read-only access for a single clinic calendar. For an EHR connector, it might mean the ability to query one patient at a time but not export bulk records.

Use short-lived tokens where the API supports them. If the system uses OAuth, let the MCP server handle refresh tokens in the background. If it uses static API keys, rotate them on a calendar and store them in a local secret manager, not in the tool description that gets sent to the model. The server should also log only the tool name and parameter values you need for audit. Never log the Authorization header, even at debug level.

When you review a connector, check whether it can run with read-only permissions first. You can add write actions later only after you have tested the read path. This reduces the blast radius if the assistant is tricked into calling an action it should not.

Building this pattern without a product pitch

You do not need a particular vendor to get this boundary. A small script that reads an environment variable and exposes a function over MCP already does the job. Many teams run the server next to their existing automation platform. The notes on Playwright show a similar separation for browser actions: the browser runs in a controlled process, and the assistant only passes high-level instructions.

The key is to treat the assistant as an untrusted caller. It can suggest actions, but the server enforces auth, rate limits, and input validation. If the assistant asks for a patient record, the server checks that the request meets the allowed schema. If the assistant asks for a token, the server has no token to return because the token never entered the context.

Before adding any named connector to a production flow, check its licence and current repository. Tool names like FTTHelper and Practice Fusion are used here as examples of the class, not as endorsements or a promise that a specific package is safe. The site standard at R21 Labs is to credit and licence-check any named tool before relying on it, and that check belongs outside the prompt as much as the secret does.

All notes·Catalog