# Section 4 — Building MCP Servers in C#

> **Summary — what this page covers**
> The payoff of Day 1's MCP section: yesterday attendees *used* the GitHub MCP server; today they
> *build their own* in C# to **connect Claude to their own database and internal services.** Using
> the official ModelContextProtocol SDK, they define typed tools, wire them through DI to the real
> BookTracker `DbContext` and services, and connect the server to Claude Code for live testing.
> Lean into the "I used one yesterday, I'm building one today" ah-ha. Pair with **Lab 4**.

**2:15 – 3:15 PM · 60 min** — 30 min lecture/demo + 30 min lab

## Learning objectives

- Connect Day 1's MCP host/client/server model to a concrete C# implementation
- Install/configure the official **ModelContextProtocol** NuGet package (v1.x GA)
- Define MCP **tools** with strongly-typed input schemas in C#
- **Connect Claude to your own data:** wire MCP tools through DI to the BookTracker **database
  (EF Core `DbContext`)** and existing **internal services** — reuse, don't reimplement
- Connect a custom C# MCP server to **Claude Code** for live testing
- Apply tool-description design principles for reliable model usage
- Understand security: authentication, input validation, audit logging

## Content

### Block 4A — MCP server architecture in .NET (≈15 min)

**Recap from Day 1.** MCP is **host / client / server** with three primitives — **tools** (callable
functions), **resources** (readable data), **prompts** (templates). Yesterday you were the *host*
using GitHub's *server*. Today you write the **server**.

**The C# SDK.** The official **`ModelContextProtocol`** NuGet package (v1.x GA) lets you build an
MCP server as an ordinary ASP.NET Core host. Project layout: a new **`BookTracker.Mcp`** project that
references the existing Core/Data projects so it can reuse your services.

**Transport: use Streamable HTTP** — the current MCP transport. (Not the older HTTP+SSE transport; the
SDK defaults to Streamable HTTP for HTTP-hosted servers.)

```csharp
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMcpServer()
    .WithHttpTransport()              // Streamable HTTP
    .WithToolsFromAssembly();         // discover [McpServerTool] methods
// register the BookTracker services/DbContext the tools will use:
builder.Services.AddDbContext<BookTrackerContext>(/* ... */);
var app = builder.Build();
app.MapMcp();
app.Run();
```

### Block 4B — Define tools & connect to your data (≈25 min)

Define tools as attributed methods with typed parameters. **Tool descriptions are the contract**
with the model — the same description discipline as skills and in-process tools (say when to use it).
Inject the BookTracker `DbContext` and existing services so the tool runs *your* code:

```csharp
[McpServerToolType]
public class BookTools
{
    [McpServerTool, Description("Search BookTracker for books matching a title or author.")]
    public async Task<string> SearchBooks(BookTrackerContext db, string query) =>
        // reuse your real query path — Claude never touches the DB directly
        Serialize(await db.Books.Where(b => b.Title.Contains(query)).Take(10).ToListAsync());
}
```

**Connect Claude to your own data.** Example tools: `search_books` (queries the DB),
`get_reading_progress`, `add_book`. The MCP server is a **thin, governed gateway** over systems you
already own — Claude calls *your tools*, and your tools decide what's allowed. Reuse services; don't
reimplement them.

### Block 4C — Connect to Claude Code & secure it (≈20 min)

Register the running server with **Claude Code** (`claude mcp add`), confirm with `claude mcp list`,
and ask Claude Code to invoke a tool — watch it execute against the real BookTracker database.

**Security patterns** (a governed gateway is only as safe as its rules):

- **Authentication** — require a token; don't expose the server unauthenticated.
- **Input validation** — validate tool arguments before they hit the data layer (the same
  discipline as your API endpoints).
- **Audit logging** — log every tool invocation (who, what, when) so you can answer "what did the
  agent do?"

## Demos referenced here

- **Defining a tool** (attribute + DI to a real service) · **Connecting the running server to
  Claude Code and invoking a tool live** against the database. [Scripts in `_instructor/`.]

→ Continue to [**Lab 4**](10-lab-4-mcp.md).
