Connecting external systems over the tools protocol extends the agent beyond the repository: it gains typed tools, resources, ready-made prompts and the ability to ask you for structured input. There are three transports - a local process over standard streams, streaming HTTP and a variant based on server-sent events. The configuration lives in project and user files, and that is the same layering principle as everywhere else: the project file describes what the whole team needs, the user file what you need personally.
The naive attitude is to connect a server because it is convenient and stop worrying. But a server receives exactly the powers the protocol grants and acts in an external system on your behalf. A nice name and popularity in a list are not a security review. Connecting an external tool is closer to installing a dependency than to adding a bookmark: it widens the surface and demands the same attention.
It helps to see a configuration with both transports once. Below are a local server started as a process with an environment file and a remote one over HTTP with an authorization header whose value is taken from the environment. The key detail in the second case is that the token is not written in the file literally but substituted. A literal secret in a configuration that lives in the repository is a leaked secret, even if the repository is private.
Substitution supports not only environment variables but also the home directory, the workspace folder, its name and the path separator. That is more useful than it sounds: the configuration becomes portable between machines and operating systems without edits, and the path separator removes the eternal difference between Windows and everything else. For remote servers with authorization through an external provider there are client fields and scopes - and it is the scopes that deserve the most careful review, because they determine what the server will be able to do on your behalf.
Importantly, external servers' tools obey the general run mode and usually require approval. That is not duplication but correct composition: the mode determines whether you are asked, and the server's policy determines which tools are available at all. Team administrators distribute shared servers, while restricting the set of servers, the specific tools and the network destinations is up to the enterprise administrator. And in the editor interoperability protocol team-level servers are not supported - only project and user configuration works there.
The choice of transport is not a matter of taste but a decision about where code executes and where data goes. A local process starts on your machine with your rights: it sees the file system and the environment, but the contents of the calls never leave the machine. A remote server over HTTP does not execute on your side, yet every call travels outward together with its arguments, which means fragments of the code and data you pass into the tool go with it. Hence the practical rule: the local transport suits what works with the repository, the remote one suits what already lives outside.
The request for structured input deserves separate attention. A server can ask you for data during a call - a convenient mechanism for parameters that were not in the original task. But it is exactly that which becomes a channel for social engineering: the request looks like part of the workflow while asking for what it should not. Secrets are not passed through such a channel, and the request itself is read as coming from outside.
There is a sign by which you recognize that too much is connected. The agent starts choosing the wrong tool, approvals pour in at every step, and a simple task takes noticeably longer than usual. The cause is usually one: every enabled tool occupies space in the context with its description and takes part in the choice. A dozen servers with their full sets of capabilities are a hundred descriptions among which the model searches for the right one. So the list of enabled tools is kept narrow and reviewed the way a list of dependencies is.
The engineering conclusion is simple: an external server is an executable integration. You check the publisher, the address or launch command, the scopes, call arguments, the network policy and what the server returns. The returned content is checked separately: it enters the agent's context as ordinary text and may contain instructions you did not write.
The typical failures are predictable. Writing a token into the configuration literally and committing it. Leaving all of a server's tools enabled, including the ones that change data. Treating a connected server as trusted by the fact of connection. And passing a secret through a structured-input request, taking it for part of the interface.
// .cursor/mcp.json
{
"mcpServers": {
"docs": {
"type": "stdio",
"command": "node",
"args": ["./tools/docs-mcp.mjs"],
"envFile": ".env.mcp"
},
"issues": {
"url": "https://mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer ${env:ISSUES_MCP_TOKEN}"
}
}
}
}
// substitution: ${env:NAME}, ${userHome}, ${workspaceFolder}, ${pathSeparator}