The Agentic Leap — Part 5: Model Context Protocol (MCP)
MCP can sound abstract when it is described only as a protocol. A calmer way to understand it is to compare it with an interface boundary you already know. An ASP.NET Core API publishes operations and data contracts. MCP publishes model-oriented tools, resources and prompts for an AI host.
MCP standardizes capability exchange; your application still supplies trust and authorization.Model Context Protocol standardises how an AI host discovers and invokes capabilities exposed by servers. It can reduce bespoke integrations, but it does not make a discovered server trustworthy or a tool appropriate for the current user.
This module reflects the current MCP specification family available at publication time, including the 2026-07-28 revision. Protocols evolve; production implementations must negotiate versions and recheck the official specification.
1. The MCP roles
User
-> Host application (our ASP.NET Core control plane)
-> MCP client connection
-> MCP server
-> tools, resources and prompts
The host owns the user experience, model integration and policy. A client manages one server relationship. A server exposes capabilities. This boundary is valuable because capability providers can evolve independently.
2. Tools, resources and prompts
- Tools are callable operations with argument schemas.
- Resources expose addressable contextual data.
- Prompts are reusable prompt templates or workflows offered by a server.
For BuildEstate Pro, an internal planning MCP server might expose get_planning_position, a planning-policy://... resource and a review prompt. It should not expose arbitrary database access.
3. Put a policy gateway between discovery and use
public sealed record DiscoveredCapability(
Uri Server,
string Name,
CapabilityKind Kind,
JsonDocument Schema,
string ProtocolVersion);
public interface IMcpCapabilityPolicy
{
ValueTask<CapabilityDecision> EvaluateAsync(
AgentExecutionContext context,
DiscoveredCapability capability,
CancellationToken cancellationToken);
}
The decision can consider server identity, environment, tenant, data classification, tool name, schema risk and user role. Cache discovery only according to protocol metadata and local revocation requirements.
4. Version and transport deliberately
Send and validate the negotiated protocol version. Current Streamable HTTP messages include routing information that infrastructure can use for metering and controls. Do not assume a transport session is application state; the 2026-07-28 direction favours explicit handles for state that must cross calls.
Set request size, response size, duration and concurrency limits. Validate content types and reject unexpected redirects or destinations. An MCP client is a network integration and deserves the same egress, TLS and SSRF controls as any other.
5. Authentication is not authorisation
For remote HTTP servers, follow the current OAuth-based MCP authorisation specification. Tokens must be audience/resource-bound to the intended MCP server. Use minimal scopes and step-up only when a capability genuinely requires more access.
Do not forward the host’s broad service credential to every server. Do not accept tokens issued for another audience. Keep credentials out of model context and tool arguments.
The server must apply resource-level policy using the verified identity. A tool description saying “managers only” has no enforcement value.
6. Treat server metadata and content as untrusted
A malicious server can advertise misleading tool descriptions, return prompt-injection text, request excessive scopes or change schemas. Therefore:
- connect only to configured or approved servers;
- pin or validate server identity where appropriate;
- allow-list capabilities and schema versions;
- sanitise names and descriptions before model exposure;
- isolate high-risk servers;
- require approval for consequential calls;
- record server, version and capability in the audit trail.
7. Multi-round input and long-running work
Current MCP work supports stateless multi-round interactions where a tool can report that input is required and the client retries with explicit answers. The host must decide how that input is shown, authenticated and bound to the original request.
Long-running task support is moving through protocol extensions. Avoid hiding a durable business workflow inside an opaque tool call. Prefer an explicit task handle, status contract, cancellation and retention policy.
8. MCP server design for .NET
Keep the transport adapter thin:
MCP request
-> schema/deserialisation
-> authenticated application command/query
-> domain policy
-> result mapping and redaction
Reuse the same application handlers called by REST endpoints rather than reimplementing rules inside MCP handlers. Propagate cancellation and trace context. Map expected failures to stable safe error codes; do not serialize exceptions.
9. MCP versus ordinary APIs
Use MCP when model-oriented capability discovery and portable tool/resource semantics produce real value. Use a typed internal API when one application calls one known service. MCP complements REST, messaging and domain services; it does not replace them.
MCP also differs from A2A. MCP generally connects a host to capabilities and context. A2A coordinates work with another agentic system that owns its own task execution.
10. Evaluation and operations
Contract-test discovery, schemas, version negotiation, scope challenges and errors. Test revoked servers, changed tool definitions, oversized results, malicious descriptions, token audience errors and cancellation.
Monitor calls by server and capability, policy denials, latency, failure class, schema drift, token scope, cache age and result size. Maintain a kill switch that removes a server or capability without a redeployment.
Extended implementation review
11. Read the protocol in layers
MCP defines messages and capability semantics; an SDK provides language bindings; the host supplies product policy; and the server owns its underlying domain security. Keeping those layers separate prevents an SDK convenience method from being mistaken for an authorisation decision.
The 2026-07-28 core is stateless at the protocol transport layer. Requests carry version and client metadata, while optional discovery can reveal server capabilities. Application workflows may still be stateful: an operation can return an explicit handle, and the caller supplies it later. This is easier to route and scale than hidden transport session state, but it makes handle protection and expiry an application responsibility.
Tasks now live in an extension rather than the core. A production host should advertise and negotiate extensions explicitly and remain useful when a server supports only core tools or resources. Do not assume that every SDK version implements every extension identically.
12. Capability discovery and registry governance
Discovery results are untrusted metadata. Validate names, schemas, annotations, sizes and supported versions before adding a capability to an internal registry. Apply an administrative allow-list for servers and a runtime allow-list based on user, tenant, environment and goal.
Cache list and resource responses only according to their declared lifetime and your security policy. In the current specification family, list results can communicate cache information, but a cached catalogue must not outlive server revocation. Provide an operator control that invalidates cached capabilities immediately.
Tool descriptions can influence model choice and therefore require change control. Record the server identity and schema digest in traces. Alert when a known capability changes unexpectedly, and rerun contract tests before exposing a new definition broadly.
13. Authorisation end to end
The host authenticates its user, determines the permitted MCP server and obtains a token for that resource. Tokens should be audience-bound, minimally scoped and short-lived. The server validates issuer, audience, expiry and scopes, then performs domain authorisation against the requested project or record.
Never forward the host’s model-provider key. Avoid token passthrough to unrelated upstream systems; the MCP server should obtain appropriate downstream credentials through a deliberate exchange or its own service identity. Protect against confused-deputy behaviour by binding the request to the intended server and capability.
Consent screens must describe the actual capability and data transfer. A scope called tools tells a person almost nothing. Explain whether the server can read project documents, prepare drafts or create records, and allow access to be revoked without rebuilding the host.
14. Multi-round-trip input and approvals
The current specification supports multi-round-trip requests for cases where a tool needs additional input. Treat input_required as a pause in application orchestration. Persist the original call, validate the requested fields and present them through the trusted host UI. The server’s text is untrusted display content and must not inject HTML or bypass policy.
User input does not automatically authorise a consequential command. If the requested response is an approval, the host must apply its own approval policy and bind the decision to the exact operation. A remote request for secrets, broad credentials or unrelated personal data should be denied and investigated.
15. Network and content security
Register endpoints administratively and resolve them through controlled egress. Block loopback, link-local and internal metadata addresses unless specifically required. Limit redirects, response sizes, decompression ratios and content types. Apply TLS validation and consider workload identity or mutual TLS for internal servers.
Resources and tool results may contain prompt injection, malware or active content. Store artifacts safely, scan relevant file types and render them without executing embedded scripts. The model should receive a sanitised representation and stable provenance, not an unchecked binary or arbitrary remote URL.
16. An ASP.NET Core integration boundary
Wrap the MCP client behind an owned interface such as IPlanningCapabilities. The rest of the domain should not depend on protocol-specific result objects. The adapter maps discovery into approved internal capabilities, supplies delegated credentials, applies timeouts and translates errors into your taxonomy.
Use typed options for approved endpoints and protocol versions. Add resilience only where operations are retry-safe. Propagate cancellation and trace context, but redact tokens and sensitive content. A health check should distinguish DNS/TLS failure, authentication failure, incompatible protocol and capability drift.
17. Compatibility and conformance testing
Test against the exact server and SDK versions deployed. Cover discovery absent or delayed, unsupported versions, unknown extensions, changed schemas, paginated results, stale cache metadata and malformed JSON-RPC. Security tests should include issuer mix-up, wrong audience, redirect attacks and a capability description containing adversarial instructions.
Run a small conformance suite in deployment pipelines and a synthetic read in production. Keep a rollback path to the previous protocol/SDK combination. Protocol interoperability reduces bespoke integration only when versioning and ownership are operated seriously.
18. Worked capability decision
Assume a server advertises create_planning_task, read_project_document and generic http_request. Administrative policy rejects the network tool. Runtime policy exposes document reading only for accessible projects. The command remains hidden until proposal review and requires an eligible approver. The server still repeats resource authorisation.
This shows three decisions: whether the organisation trusts a server, whether this user may see a capability, and whether this call is authorised now. MCP discovery answers none of them. It provides metadata on which host and server controls operate.
19. Operational review questions
- Which specification and SDK versions are deployed?
- Can an operator revoke one server or capability immediately?
- Are schema digests monitored for unexpected change?
- Are OAuth issuer, audience and resource protections tested?
- Can results reach internal networks or active-content renderers?
- What happens when input requests ask for excessive data?
- Which team owns failures beyond the adapter?
20. Build or buy the server boundary
An internal MCP server is worthwhile when several hosts need the same model-facing capability catalogue or when a product intentionally supports interoperable clients. Keep its handlers thin: translate protocol contracts into existing domain services rather than recreating business logic. That preserves one source of authorisation and validation.
For a single ASP.NET Core application calling one stable internal service, a typed API may remain clearer. It offers compile-time contracts, familiar monitoring and fewer protocol layers. A future possibility of reuse is not enough; require a concrete consumer and governance model.
For third-party servers, assess supplier security, availability, data use, residency, version support and incident response. Run them through an egress gateway where appropriate. Maintain an inventory of which goals can reach each capability and which data classifications may cross the boundary. Removal must be tested as carefully as onboarding.
Production checklist
- Protocol versions are negotiated and recorded.
- Servers are configured or approved, never model-selected from arbitrary URLs.
- Capability discovery passes through host policy.
- OAuth tokens are minimally scoped and resource-bound.
- Servers repeat resource-level authorisation.
- Results and descriptions are treated as untrusted input.
- Network egress, sizes, deadlines and redirects are controlled.
- Durable work uses explicit handles and cancellation.
- A kill switch and schema-drift monitoring exist.
21. Continue the series
MCP connects an agent host to capabilities. Part 6 moves across another boundary: delegating a stateful task to an independent agent using A2A.
A small ASP.NET Core adapter
Keep protocol types at the integration edge. The application depends on an owned interface:
public interface IPlanningCapabilities
{
Task<PlanningPosition> GetPositionAsync(
AuthorizedProject project,
Guid plotId,
CancellationToken cancellationToken);
}
The MCP adapter selects an approved server, supplies a short-lived token, sets a deadline, calls the tool and validates the result.
public async Task<PlanningPosition> GetPositionAsync(
AuthorizedProject project,
Guid plotId,
CancellationToken ct)
{
var args = new { projectId = project.Id, plotId };
var result = await client.CallToolAsync(
"get_planning_position", args, cancellationToken: ct);
return resultMapper.ToValidatedPosition(result);
}
Authentication, schema checks, size limits and tracing surround this small call. The server repeats project authorization because an approved server is not automatically approved for every record.
MCP in Microsoft Foundry
Microsoft Foundry supports remote MCP servers and managed toolboxes. A toolbox can curate capabilities behind a managed MCP-compatible endpoint with centralized authentication, governance and versioning. This helps when several agents need a consistent catalogue.
The same rule remains: Foundry may manage the platform connection and agent identity; BuildEstate Pro decides which user, project and goal may reach a capability. Treat descriptions and results as untrusted content. Record the negotiated protocol and schema versions.
Use a normal typed API when one .NET application calls one known service and discovery adds no value. Use MCP when several agent hosts need portable model-facing semantics or when you deliberately expose a governed capability ecosystem. MCP is not a badge of maturity; choose the boundary that makes ownership and security clearest.
