Skip to main content
Practical implementation is where MCP’s power becomes tangible. This module bridges conceptual knowledge and hands-on development, guiding you through building, testing, and deploying MCP-based applications with real tools and workflows.
This module covers MCP SDKs aligned with MCP Specification 2025-11-25. The C# SDK is currently in preview and APIs may change.

Learning objectives

By the end of this module, you will be able to:
  • Implement MCP solutions using official SDKs in C#, Java, TypeScript, JavaScript, and Python
  • Debug and test MCP servers systematically
  • Create and use server features — Resources, Prompts, and Tools
  • Handle large result sets with cursor-based pagination
  • Secure and deploy MCP servers to Azure

Official SDKs

MCP provides official SDKs for multiple languages:

C# SDK

NuGet package ModelContextProtocol — preview

Java SDK

Requires Project Reactor for reactive programming

TypeScript SDK

Full SDK for Node.js and browser environments

Python SDK

Async/await support with FastAPI integration

Kotlin SDK

JVM-based SDK for Kotlin projects

Go SDK

Idiomatic Go implementation

Core server features

Every MCP server can implement any combination of three primitives:
Resources provide context and data for the user or AI model:
  • Document repositories and knowledge bases
  • Structured data sources and file systems
  • Any external data that enriches model context
Prompts are templated messages and guided workflows:
  • Pre-defined conversation templates
  • Guided interaction patterns for specific tasks
  • Specialized dialogue structures that ensure consistency
Tools are functions the AI model can invoke:
  • Data processing utilities
  • External API integrations
  • Computational capabilities and search functionality

Language-specific implementations

The C# SDK integrates with ASP.NET Core and supports the full MCP feature set.Key features:
  • NuGet package: ModelContextProtocol
  • ASP.NET Core integration
  • Tool registration with authentication and error handling
  • Multiple implementation patterns for tools of varying complexity
See the official C# SDK samples repository for complete examples.

Pagination and large result sets

When your server handles large datasets, you need pagination to manage memory efficiently and provide responsive experiences.

Why pagination matters

Without pagination, large responses cause:
  • Memory exhaustion — loading millions of records at once
  • Slow response times — users wait while all data loads
  • Timeout errors — requests exceed time limits
  • Poor AI performance — LLMs struggle with massive context windows
MCP uses cursor-based pagination for reliable, consistent paging through result sets.

How cursor-based pagination works

A cursor is an opaque string that marks your position in a result set — think of it as a bookmark in a long book. These MCP methods support pagination:
MethodReturnsCursor support
tools/listTool definitionsYes
resources/listResource definitionsYes
prompts/listPrompt definitionsYes
resources/templates/listResource templatesYes

Server-side pagination

from mcp.server import Server
from mcp.types import Tool, ListToolsResult

app = Server("paginated-server")

ALL_TOOLS = [
    Tool(name=f"tool_{i}", description=f"Tool number {i}", inputSchema={})
    for i in range(100)
]

PAGE_SIZE = 10

@app.list_tools()
async def list_tools(cursor: str | None = None) -> ListToolsResult:
    start_index = 0
    if cursor:
        try:
            start_index = int(cursor)
        except ValueError:
            start_index = 0

    end_index = min(start_index + PAGE_SIZE, len(ALL_TOOLS))
    page_tools = ALL_TOOLS[start_index:end_index]

    next_cursor = str(end_index) if end_index < len(ALL_TOOLS) else None

    return ListToolsResult(tools=page_tools, nextCursor=next_cursor)

Client-side pagination

from mcp import ClientSession

async def get_all_tools(session: ClientSession) -> list:
    """Fetch all tools using cursor-based pagination."""
    all_tools = []
    cursor = None

    while True:
        result = await session.list_tools(cursor=cursor)
        all_tools.extend(result.tools)

        if result.nextCursor is None:
            break
        cursor = result.nextCursor

    return all_tools

Cursor design strategies

The cursor is just the numeric offset into the result set.
cursor = "50"  # Start at item 50
Pros: Simple and stateless. Cons: Results can shift if items are added or removed between pages.
The cursor is the ID of the last seen item.
cursor = "item_abc123"  # Start after this item
Pros: Stable even if items change. Cons: Requires ordered IDs.
The cursor encodes multiple state fields as a base64 string.
import base64, json

def encode_cursor(state: dict) -> str:
    return base64.b64encode(json.dumps(state).encode()).decode()

cursor = encode_cursor({"offset": 50, "filter": "active", "sort": "name"})
Pros: Can encode complex query state. Cons: More complex; produces larger cursor strings.
Never load all results into memory and paginate client-side. Always paginate at the data source to avoid memory exhaustion and timeouts.

API management with Azure

Azure API Management (APIM) is a reliable solution for securing MCP servers. Placing APIM in front of your MCP server gives you:
  • Rate limiting — prevent abuse and ensure fair usage
  • Token management — centralized API key and OAuth handling
  • Monitoring — request logging via Azure Monitor
  • Load balancing — distribute traffic across server instances
  • Security — authentication and authorization enforcement

Deploy a secured MCP server to Azure

1

Clone the sample repository

git clone https://github.com/Azure-Samples/remote-mcp-apim-functions-python.git
cd remote-mcp-apim-functions-python
2

Register the Microsoft.App resource provider

az provider register --namespace Microsoft.App --wait
3

Provision all Azure resources

azd up
This deploys the API Management service, Function App, and all required Azure resources.
4

Test with MCP Inspector

In a new terminal, install and launch the inspector:
npx @modelcontextprotocol/inspector
Set the transport type to SSE and the URL to your APIM SSE endpoint:
https://<apim-servicename>.azure-api.net/mcp/sse
Click List Tools, then select and run a tool to verify the connection.
The authorization flow uses Microsoft Entra for authentication, APIM policies to direct traffic, and Azure Monitor for logging all requests.

Azure Functions quickstart templates

The remote-mcp-functions template set lets you build and deploy custom remote MCP servers using Azure Functions:

Python

Build and deploy with Azure Functions and Python

C# .NET

Build and deploy with Azure Functions and C# .NET

Node/TypeScript

Build and deploy with Azure Functions and TypeScript
All three templates include:
  • Local development and debugging support
  • Security by design with HTTPS and key-based auth
  • OAuth support via built-in auth and APIM
  • Network isolation with Azure Virtual Networks
  • Simple one-command deployment: azd up

Key takeaways

  • MCP SDKs provide language-specific tools for building robust solutions across C#, Java, TypeScript, JavaScript, and Python
  • Use cursor-based pagination for all large result sets — never load everything into memory
  • Debug and test your MCP servers systematically before deploying
  • Azure API Management adds enterprise-grade security, rate limiting, and monitoring to remote MCP servers
  • Reusable prompt templates ensure consistent AI interactions across your application

Exercise

Design a practical MCP workflow that addresses a real-world problem in your domain:
  1. Identify 3–4 tools useful for solving the problem
  2. Create a workflow diagram showing how those tools interact
  3. Implement a basic version of one tool using your preferred language
  4. Add cursor-based pagination if the tool returns a list of items
  5. Create a prompt template that helps the model use your tool effectively

Next: Advanced Topics

Explore multi-modal integration, scaling, security, and enterprise patterns

MCP Specification

Full protocol specification including pagination details

Build docs developers (and LLMs) love