An AI agent might write a SQL query without being able to access a database. It might describe how to open a GitHub issue without having permission to do so. Acting on external systems requires integrations, and maintaining a different integration for every AI application quickly becomes expensive.
Model Context Protocol (MCP) is an open protocol that standardizes how AI applications connect to tools and information sources. It is not an AI model, an agent, or a substitute for authorization.
1. MCP is a protocol, not an AI model
MCP describes how AI applications and servers discover available capabilities and exchange requests and responses. A model may choose to call a tool, but the model itself is not MCP.
A useful analogy: an API offers operations; MCP makes supported capabilities discoverable through a common interface for AI applications. It does not magically make an external API safe or remove the work required to integrate it.
2. Understand the host–client–server architecture
- Host: the AI application users interact with. It manages connections and user experience.
- MCP client: the host component that communicates with an MCP server. In practice, connections are managed individually.
- MCP server: a process exposing a defined set of capabilities.
Conceptual diagram: the single client node represents multiple host-managed server connections for readability.
3. Servers expose specific capabilities
An MCP server may provide operations for GitHub, files, internal APIs, or a product catalog. It should expose only capabilities its implementation and permissions allow.
For example, a food-truck catalog server could implement find_food_trucks(town) without offering arbitrary database write access. Narrow business operations are easier to reason about and protect than a generic “run any SQL” tool.
Servers can run locally over standard input/output (stdio) or remotely over compatible transports such as Streamable HTTP. Choose based on your deployment, authentication, and operational needs.
4. Tools, Resources, and Prompts are not interchangeable
| Capability | Purpose | Example |
|---|---|---|
| Tools | Execute functions or retrieve data through operations | find_food_trucks("Ponce") |
| Resources | Expose readable content to clients | Internal API documentation |
| Prompts | Provide reusable interaction templates | “Analyze this issue and propose a plan” |
Clients may present these differently, and not every host supports every capability. A tool can be selected during an interaction with the model; resources may be managed by the client; prompts may be selected by users.
MCP vs. Skills
A Skill usually describes a repeatable procedure: steps to follow, quality standards, and expected output. An MCP server offers access to external data and actions. An agent can use an MCP tool while following a Skill, but the two concepts solve different problems.
5. Connectivity does not imply unrestricted permission
The protocol standardizes communication; authorization must still be enforced by the application, server, and upstream systems as appropriate.
- Review server implementations and the tools they expose.
- Apply least-privilege credentials and never put secrets in prompts or committed configuration.
- Separate read and write operations; require approval for destructive changes.
- Validate inputs and authorize sensitive operations server-side.
- Keep useful audit records without collecting unnecessary sensitive data.
Tool outputs and retrieved documents may contain malicious instructions. Treat external content as data, not trusted commands.
Hands-on: build a read-only MCP server with .NET 10
This small example runs locally over stdio and serves a fictional food-truck catalog. It does not require a database, credentials, or an external API.
Requirements: .NET 10 SDK and an MCP-compatible host with stdio server support.
Step 1: create the project
dotnet new console -n BoricuaCoder.McpDemo -f net10.0
cd BoricuaCoder.McpDemo
dotnet add package ModelContextProtocol
dotnet add package Microsoft.Extensions.Hosting
Step 2: replace Program.cs
using System.ComponentModel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
var builder = Host.CreateApplicationBuilder(args);
// stdout is reserved for MCP protocol messages.
// Send console logs to stderr instead.
builder.Logging.AddConsole(options =>
{
options.LogToStandardErrorThreshold = LogLevel.Trace;
});
builder.Services
.AddMcpServer()
.WithStdioServerTransport()
.WithToolsFromAssembly();
await builder.Build().RunAsync();
[McpServerToolType]
public static class CatalogTools
{
[McpServerTool, Description("Lists the towns in the demo catalog.")]
public static string ListTowns() => "Ponce, Bayamón, Caguas";
[McpServerTool, Description("Finds sample food trucks by town without modifying data.")]
public static string FindFoodTrucks(
[Description("The town to search.")] string town)
{
var catalog = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
{
["Ponce"] = ["Ruta del Sabor", "Cocina Sobre Ruedas"],
["Bayamón"] = ["Sabor Urbano"],
["Caguas"] = ["Parada Criolla"]
};
return catalog.TryGetValue(town.Trim(), out var trucks)
? string.Join(", ", trucks)
: "No results in this demonstration catalog.";
}
}
The catalog entries are fictional sample data. WithToolsFromAssembly() finds methods marked with [McpServerTool] inside [McpServerToolType] classes.
Step 3: build and connect
dotnet build
Configure your MCP host to start the dotnet process with arguments like these, replacing the path with the absolute project location:
{
"command": "dotnet",
"args": [
"run",
"--no-build",
"--project",
"/absolute/path/BoricuaCoder.McpDemo/BoricuaCoder.McpDemo.csproj"
]
}
This describes a command and its arguments; it is not a universal configuration file. Hosts differ in their registration format. A stdio server speaks protocol messages, not an interactive terminal menu.
Step 4: verify the tools
Check that your host discovers ListTowns and FindFoodTrucks, then try:
What towns are available in the demo catalog?
Find the sample food trucks in Ponce using the MCP tool.
Check the tool request and result in the host. If discovery fails, verify the absolute path, dependencies, and absence of extra writes to stdout.
Benefits and trade-offs
Benefits: consistent integration surfaces, reusable servers for compatible hosts, and a clear separation between the agent and external systems.
Trade-offs: each integration still needs implementation and maintenance; hosts vary in feature support; MCP does not guarantee correct data, trustworthy tool output, or secure authorization.
Common mistakes
- Installing unreviewed servers. They are executable software with real permissions.
- Assuming connectivity grants authorization. Every sensitive operation still needs access checks.
- Exposing overly broad tools. Prefer narrow business functions over arbitrary commands.
- Trusting external tool output as instructions. Treat returned content as untrusted input.
- Writing logs to
stdoutwithstdio. This can break protocol communication.
A realistic use case
Suppose an operations agent must answer: “How many registrations are pending in Ponce?” An internal MCP server could expose count_pending_registrations(town) and call a protected application API with appropriately scoped credentials. The agent gets the answer without direct database access. Approving a registration should be a separate, authorized tool with additional safeguards.
Final thoughts
MCP solves an integration problem, not a reasoning problem. Start with a read-only tool, test its actual behavior, and expand access only when necessary.
Across the BoricuaCoder series: agents perform tasks; Skills supply procedures; a Harness supports controlled execution; Workflows coordinate stages; MCP standardizes connections to external capabilities.
