Lesson 4 gave us tool calling inside the app.
Lesson 5 takes the next architectural step: move tools into an MCP server so they are reusable by any MCP-capable client.
Lessons in this series
Before you start (self-setup)
If you’re following along on your own, complete lesson 0 and lesson 4 first.
Lesson 5 does not require a new Azure resource, but it does require a reliable local multi-project setup.
Self-setup: local MCP server/client wiring
- Keep
StarWarsCopilotandStarWarsMCPServerin stable local paths. - In your copilot app config (
MCPServerOptions), use an absolute--projectpath toStarWarsMCPServer.csproj. - Verify the MCP server independently before launching your copilot:
npx @modelcontextprotocol/inspector dotnet run --project /absolute/path/to/StarWarsMCPServer.csproj
If the inspector can list tools and run WookiepediaTool, your MCP server wiring is ready.
Why MCP
Without MCP, tools are often tightly embedded in one app.
With MCP:
- tools live in a separate server
- clients discover and call tools dynamically
- the same tooling can be reused across copilots, IDEs, and agents
This decoupling is huge once your tool surface grows.
Building the MCP server
The workshop creates a separate StarWarsMCPServer .NET console app and wires:
AddMcpServer()- stdio transport
- tool discovery from assembly
Important implementation detail: stdio transport means logging should go to stderr, not stdout.
Porting the tool
The previous WookiepediaTool logic becomes an MCP tool via [McpServerTool] in a StarWarsTools class.
You still keep strong natural-language descriptions because the model depends on those descriptions to choose tools correctly.
Testing with MCP Inspector
Before integrating the copilot client, the workshop validates server behavior using the MCP Inspector:
- connect
- list tools
- run tool
- inspect responses
That “test tools independently first” pattern saves a lot of debugging pain later.
MCP client in the copilot
Then the app switches from local in-process tools to:
StdioClientTransportMcpClient.CreateAsync(...)ListToolsAsync()feedingChatOptions.Tools
At that point your copilot is now an MCP host/client combo and can scale by adding more servers, not more hardcoded tool wrappers.
Suggested banner prompt
A futuristic illustration of a central AI copilot console connected by glowing protocol lines to multiple external tool servers in separate modules, with a clean developer workspace aesthetic, cinematic contrast, high detail, no text, no logos.
Follow along
Workshop source for this lesson: Lesson 5 README.
Next up: RAG from a structured database using an MCP tool.
Note: Original workshop repository: jimbobbennett/StarWarsCopilot.
