{"id":11654,"date":"2026-01-07T08:00:39","date_gmt":"2026-01-07T16:00:39","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cosmosdb\/?p=11654"},"modified":"2026-01-07T09:12:34","modified_gmt":"2026-01-07T17:12:34","slug":"build-ai-tooling-in-go-with-the-mcp-sdk-connecting-ai-apps-to-databases","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cosmosdb\/build-ai-tooling-in-go-with-the-mcp-sdk-connecting-ai-apps-to-databases\/","title":{"rendered":"Build AI Tooling in Go with the MCP SDK \u2013 Connecting AI Apps to Databases"},"content":{"rendered":"<div>\n<div style=\"text-align: center;\"><em><span style=\"font-size: 14pt;\"><strong>A hands\u2011on walkthrough of building MCP servers that can plug AI applications into Azure Cosmos DB<\/p>\n<p><\/strong><\/span><\/em><\/div>\n<\/div>\n<p class=\"code-line\" dir=\"auto\" data-line=\"6\">The\u00a0<a href=\"https:\/\/modelcontextprotocol.io\/docs\/getting-started\/intro\" data-href=\"https:\/\/modelcontextprotocol.io\/docs\/getting-started\/intro\">Model Context Protocol<\/a>\u00a0(MCP) has established itself as the ubiquitous standard for connecting AI applications to external systems. Since its release, there have been\u00a0<a href=\"https:\/\/modelcontextprotocol.io\/docs\/sdk\" data-href=\"https:\/\/modelcontextprotocol.io\/docs\/sdk\">implementations<\/a>\u00a0across various programming languages and frameworks, enabling developers to build solutions that expose data sources, tools, and workflows to AI applications.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"8\">For Go developers, however, the journey to an official MCP SDK took longer (compared to other SDKs like Python and TypeScript). <a href=\"https:\/\/github.com\/orgs\/modelcontextprotocol\/discussions\/224\" data-href=\"https:\/\/github.com\/orgs\/modelcontextprotocol\/discussions\/224\">Discussions<\/a>\u00a0and\u00a0<a href=\"https:\/\/github.com\/orgs\/modelcontextprotocol\/discussions\/364\" data-href=\"https:\/\/github.com\/orgs\/modelcontextprotocol\/discussions\/364\">design\/implementation<\/a>\u00a0work on the official Go implementation began during early to mid 2025. At the time of writing (January 2026) it stands at version\u00a0<strong>1.2.0<\/strong>. As a Gopher, I&#8217;m excited (and relieved!) to finally have a stable,\u00a0<a href=\"https:\/\/github.com\/modelcontextprotocol\/go-sdk\" data-href=\"https:\/\/github.com\/modelcontextprotocol\/go-sdk\">official MCP Go SDK<\/a>\u00a0that the Go community can rely on.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"10\">To explore its capabilities, I built an\u00a0<a href=\"https:\/\/github.com\/abhirockzz\/mcp_cosmosdb_go\" data-href=\"https:\/\/github.com\/abhirockzz\/mcp_cosmosdb_go\">MCP server for Azure Cosmos DB<\/a>. This blog post will dive into the MCP Go SDK fundamentals by walking through it specifics, and exploring concepts such as tools, servers, etc. By the end, you&#8217;ll understand how to use the MCP Go SDK to build your own MCP servers, with Azure Cosmos DB serving as a practical example.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"12\"><strong>Note:<\/strong>\u00a0This project is not intended to replace the\u00a0<a href=\"https:\/\/github.com\/azure\/azure-mcp\" data-href=\"https:\/\/github.com\/azure\/azure-mcp\">Azure MCP Server<\/a>\u00a0or\u00a0<a href=\"https:\/\/github.com\/AzureCosmosDB\/MCPToolKit\" data-href=\"https:\/\/github.com\/AzureCosmosDB\/MCPToolKit\">Azure Cosmos DB MCP Toolkit<\/a>. Rather, it serves as an experimental\u00a0<strong>learning tool<\/strong> that demonstrates how to combine the Azure and MCP Go SDKs to build AI tooling for Azure Cosmos DB.<\/p>\n<p dir=\"auto\" data-line=\"12\"><div class=\"alert alert-info\">This project is not intended to replace the\u00a0<a href=\"https:\/\/github.com\/azure\/azure-mcp\" data-href=\"https:\/\/github.com\/azure\/azure-mcp\">Azure MCP Server<\/a>\u00a0or\u00a0<a href=\"https:\/\/github.com\/AzureCosmosDB\/MCPToolKit\" data-href=\"https:\/\/github.com\/AzureCosmosDB\/MCPToolKit\">Azure Cosmos DB MCP Toolkit<\/a>. Rather, it serves as an experimental\u00a0<strong>learning tool<\/strong>\u00a0that demonstrates how to combine the Azure Go SDK and MCP Go SDK Cosmos DB to build AI tooling for Azure Cosmos DB.<\/div><\/p>\n<h2 id=\"mcp-basics\" class=\"code-line\" dir=\"auto\" data-line=\"14\">MCP Basics<\/h2>\n<p class=\"code-line\" dir=\"auto\" data-line=\"16\">Let&#8217;s briefly cover what MCP is and how the MCP Go SDK works.<\/p>\n<h3 id=\"what-is-the-model-context-protocol\" class=\"code-line\" dir=\"auto\" data-line=\"18\">What is the Model Context Protocol?<\/h3>\n<p class=\"code-line\" dir=\"auto\" data-line=\"20\">The Model Context Protocol (MCP) is an open-source standard for connecting AI applications to external systems. It&#8217;s often referred to as a <strong>USB-C port for AI applications<\/strong>\u00a0\u2014 just as USB-C provides a standardized way to connect devices, MCP provides a standardized way to connect AI applications to data sources, tools, and workflows.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"22\">With MCP, AI applications (ranging from IDEs like VS Code, CLI coding tools like GitHub Copilot or apps like Claude web\/desktop) can:<\/p>\n<ul class=\"code-line\" dir=\"auto\" data-line=\"24\">\n<li class=\"code-line\" dir=\"auto\" data-line=\"24\">Access\u00a0<strong>data sources<\/strong>\u00a0(local files, databases, APIs)<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"25\">Use\u00a0<strong>tools<\/strong>\u00a0(search engines, calculators, external services)<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"26\">Execute\u00a0<strong>workflows<\/strong>\u00a0(specialized prompts, multi-step operations)<\/li>\n<\/ul>\n<p class=\"code-line\" dir=\"auto\" data-line=\"28\">This standardization means developers can build MCP servers once and have them work with any MCP-compatible AI application, rather than creating custom integrations for each platform.<\/p>\n<h3 id=\"the-official-go-mcp-sdk\" class=\"code-line\" dir=\"auto\" data-line=\"30\">MCP Go SDK<\/h3>\n<p class=\"code-line\" dir=\"auto\" data-line=\"32\">The\u00a0<a href=\"https:\/\/github.com\/modelcontextprotocol\/go-sdk\" data-href=\"https:\/\/github.com\/modelcontextprotocol\/go-sdk\">official Go MCP SDK<\/a>\u00a0provides the building blocks to create MCP servers and clients in Go. Here&#8217;s a minimal example of an MCP server with a simple tool:<\/p>\n<pre class=\"prettyprint language-go\"><code class=\"language-go\">package main\r\n\r\nimport (\r\n    \"context\"\r\n    \"log\"\r\n    \"strings\"\r\n\r\n    \"github.com\/modelcontextprotocol\/go-sdk\/mcp\"\r\n)\r\n\r\ntype ReverseInput struct {\r\n    Text string `json:\"text\" jsonschema:\"the text to reverse\"`\r\n}\r\n\r\ntype ReverseOutput struct {\r\n    Reversed string `json:\"reversed\" jsonschema:\"the reversed text\"`\r\n}\r\n\r\nfunc ReverseText(ctx context.Context, req *mcp.CallToolRequest, input ReverseInput) (\r\n    *mcp.CallToolResult,\r\n    ReverseOutput,\r\n    error,\r\n) {\r\n    runes := []rune(input.Text)\r\n    for i, j := 0, len(runes)-1; i &lt; j; i, j = i+1, j-1 {\r\n        runes[i], runes[j] = runes[j], runes[i]\r\n    }\r\n    return nil, ReverseOutput{Reversed: string(runes)}, nil\r\n}\r\n\r\nfunc main() {\r\n    \/\/ Create server\r\n    server := mcp.NewServer(&amp;mcp.Implementation{\r\n        Name:    \"text-tools\",\r\n        Version: \"v1.0.0\",\r\n    }, nil)\r\n\r\n    \/\/ Add a tool\r\n    mcp.AddTool(server, &amp;mcp.Tool{\r\n        Name:        \"reverse\",\r\n        Description: \"reverses the input text\",\r\n    }, ReverseText)\r\n\r\n    \/\/ Run over stdio\r\n    if err := server.Run(context.Background(), &amp;mcp.StdioTransport{}); err != nil {\r\n        log.Fatal(err)\r\n    }\r\n}<\/code><\/pre>\n<p class=\"code-line\" dir=\"auto\" data-line=\"87\">This example demonstrates the key concepts:<\/p>\n<ul class=\"code-line\" dir=\"auto\" data-line=\"89\">\n<li class=\"code-line\" dir=\"auto\" data-line=\"89\"><strong>Tool definition<\/strong>: A\u00a0<code>mcp.Tool<\/code>\u00a0with a name and description<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"90\"><strong>Input\/Output types<\/strong>: Structs with JSON schema tags that define the tool&#8217;s interface<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"91\"><strong>Handler function<\/strong>: The actual logic that executes when the tool is called<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"92\"><strong>Server<\/strong>: Created with\u00a0<code>mcp.NewServer()<\/code>\u00a0and configured with tools<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"93\"><strong>Transport<\/strong>: How the server communicates (here using stdio)<\/li>\n<\/ul>\n<p dir=\"auto\" data-line=\"95\">These concepts will be covered later on the blog.<\/p>\n<h2 id=\"mcp-server-in-action\" class=\"code-line\" dir=\"auto\" data-line=\"97\">MCP Server in Action<\/h2>\n<p class=\"code-line\" dir=\"auto\" data-line=\"99\">\u25b6\ufe0f To get a sense of what the MCP server can do, take a look at this short demo of using the server with <a href=\"https:\/\/code.visualstudio.com\/docs\/copilot\/chat\/chat-agent-mode\" data-href=\"https:\/\/code.visualstudio.com\/docs\/copilot\/chat\/chat-agent-mode\">Agent Mode in Visual Studio Code<\/a>:<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"103\"><iframe src=\"\/\/www.youtube.com\/embed\/b4foQ_wgmcI\" width=\"560\" height=\"314\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"103\">This server exposes several tools that enable AI applications to interact with Azure Cosmos DB:<\/p>\n<ul class=\"code-line\" dir=\"auto\" data-line=\"105\">\n<li class=\"code-line\" dir=\"auto\" data-line=\"105\"><code>list_databases<\/code>\u00a0&#8211; List all databases in a Cosmos DB account<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"106\"><code>list_containers<\/code>\u00a0&#8211; List all containers in a specific database<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"107\"><code>read_item<\/code>\u00a0&#8211; Read a specific item using its ID and partition key<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"108\"><code>execute_query<\/code>\u00a0&#8211; Execute SQL queries against containers<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"109\"><code>create_container<\/code>\u00a0&#8211; Create new containers with partition keys<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"110\"><code>add_item_to_container<\/code>\u00a0&#8211; Add items to containers<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"111\"><code>read_container_metadata<\/code>\u00a0&#8211; Retrieve container configuration details<\/li>\n<\/ul>\n<p><div class=\"alert alert-primary\">If you want to setup and configure the server, check out the If you want to setup and configure the server, check out the\u00a0<a href=\"https:\/\/github.com\/abhirockzz\/mcp_cosmosdb_go\" data-href=\"https:\/\/github.com\/abhirockzz\/mcp_cosmosdb_go\">GitHub repository<\/a>..<\/div><\/p>\n<p>Alright, let&#8217;s dive into how it&#8217;s built.<\/p>\n<h2 id=\"understanding-the-implementation\" class=\"code-line\" dir=\"auto\" data-line=\"117\">Understanding the Implementation<\/h2>\n<p class=\"code-line\" dir=\"auto\" data-line=\"119\"><strong>Tools<\/strong> are the building blocks of an MCP server. Each tool represents a specific operation that the server can perform.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"121\">Let&#8217;s use the\u00a0<code>read_item<\/code>\u00a0tool as an example to understand the fundamental concepts of the MCP Go SDK and how it integrates with the Azure Cosmos DB Go SDK.<\/p>\n<h3 id=\"mcp-tools-definition-handler-and-execution-flow\" class=\"code-line\" dir=\"auto\" data-line=\"123\">MCP Tools: Definition, Handler, and Execution Flow<\/h3>\n<p class=\"code-line\" dir=\"auto\" data-line=\"125\">An MCP tool consists of these components:<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"127\"><strong>Tool Definition<\/strong><\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"129\">The tool definition describes the tool to the AI application. Here&#8217;s how we define the\u00a0<code>read_item<\/code>\u00a0tool:<\/p>\n<pre class=\"prettyprint language-go\"><code class=\"language-go\">func ReadItem() *mcp.Tool {\r\n    return &amp;mcp.Tool{\r\n        Name:        \"read_item\",\r\n        Description: \"Read a specific item from a container in an Azure Cosmos DB database using the item ID and partition key\",\r\n    }\r\n}<\/code><\/pre>\n<p class=\"code-line\" dir=\"auto\" data-line=\"140\">The\u00a0<code>Tool<\/code>\u00a0struct contains:<\/p>\n<ul class=\"code-line\" dir=\"auto\" data-line=\"142\">\n<li class=\"code-line\" dir=\"auto\" data-line=\"142\"><strong>Name<\/strong>: A unique identifier for the tool<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"143\"><strong>Description<\/strong>: Helps the AI understand when to use this tool<\/li>\n<\/ul>\n<p class=\"code-line\" dir=\"auto\" data-line=\"145\">The SDK can automatically infer input and output schemas from your handler function&#8217;s types, which we&#8217;ll see next.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"147\"><strong>Input and Output Types<\/strong><\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"149\">Type-safe input and output structures define the tool&#8217;s interface:<\/p>\n<pre class=\"prettyprint language-go\"><code class=\"language-go\">type ReadItemToolInput struct {\r\n    Account      string `json:\"account\" jsonschema:\"Azure Cosmos DB account name\"`\r\n    Database     string `json:\"database\" jsonschema:\"Name of the database\"`\r\n    Container    string `json:\"container\" jsonschema:\"Name of the container to read data from\"`\r\n    ItemID       string `json:\"itemID\" jsonschema:\"ID of the item to read\"`\r\n    PartitionKey string `json:\"partitionKey\" jsonschema:\"Partition key value of the item\"`\r\n}\r\n\r\ntype ReadItemToolResult struct {\r\n    Item string `json:\"item\" jsonschema:\"The item data as JSON string\"`\r\n}<\/code><\/pre>\n<p class=\"code-line\" dir=\"auto\" data-line=\"165\">The SDK uses these types to automatically generate JSON schemas and handle validation.\u00a0<strong>JSON tags<\/strong>\u00a0define how fields are serialized, and\u00a0<strong>jsonschema tags<\/strong>\u00a0provide descriptions that help AI applications understand what each field represents<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"167\"><strong>Tool Handler<\/strong><\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"169\">The handler is where the actual work happens. The MCP Go SDK provides a generic\u00a0<code>AddTool<\/code>\u00a0function that can bind tools to functions with this signature:<\/p>\n<pre class=\"prettyprint language-go\"><code class=\"language-go\">func(ctx context.Context, request *CallToolRequest, input InputType) (result *CallToolResult, output OutputType, error)<\/code><\/pre>\n<p dir=\"auto\" data-line=\"169\">Here&#8217;s the\u00a0<code>read_item<\/code>\u00a0handler:<\/p>\n<pre class=\"prettyprint language-go\"><code class=\"language-go\">func ReadItemToolHandler(ctx context.Context, _ *mcp.CallToolRequest, input ReadItemToolInput) (*mcp.CallToolResult, ReadItemToolResult, error) {\r\n    \/\/ 1. Validate inputs\r\n    if input.Account == \"\" {\r\n        return nil, ReadItemToolResult{}, errors.New(\"cosmos db account name missing\")\r\n    }\r\n    if input.Database == \"\" {\r\n        return nil, ReadItemToolResult{}, errors.New(\"database name missing\")\r\n    }\r\n    \/\/ ... more validation\r\n\r\n    \/\/ 2. Get Cosmos DB client\r\n    client, err := GetCosmosClientFunc(input.Account)\r\n    if err != nil {\r\n        return nil, ReadItemToolResult{}, err\r\n    }\r\n\r\n    \/\/ 3. Navigate to the container\r\n    databaseClient, err := client.NewDatabase(input.Database)\r\n    if err != nil {\r\n        return nil, ReadItemToolResult{}, fmt.Errorf(\"error creating database client: %v\", err)\r\n    }\r\n\r\n    containerClient, err := databaseClient.NewContainer(input.Container)\r\n    if err != nil {\r\n        return nil, ReadItemToolResult{}, fmt.Errorf(\"error creating container client: %v\", err)\r\n    }\r\n\r\n    \/\/ 4. Read the item using Cosmos DB SDK\r\n    partitionKey := azcosmos.NewPartitionKeyString(input.PartitionKey)\r\n    itemResponse, err := containerClient.ReadItem(ctx, partitionKey, input.ItemID, nil)\r\n    if err != nil {\r\n        return nil, ReadItemToolResult{}, fmt.Errorf(\"error reading item: %v\", err)\r\n    }\r\n\r\n    \/\/ 5. Return the result\r\n    return nil, ReadItemToolResult{Item: string(itemResponse.Value)}, nil\r\n}<\/code><\/pre>\n<p class=\"code-line\" dir=\"auto\" data-line=\"217\">The handler handles (pun intended!) several things:<\/p>\n<ul class=\"code-line\" dir=\"auto\" data-line=\"219\">\n<li class=\"code-line\" dir=\"auto\" data-line=\"219\"><strong>Validates<\/strong>\u00a0input parameters<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"220\"><strong>Interacts<\/strong>\u00a0with Azure Cosmos DB<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"221\"><strong>Returns<\/strong>\u00a0structured output<\/li>\n<\/ul>\n<p class=\"code-line\" dir=\"auto\" data-line=\"223\">Notice we return\u00a0<code>nil<\/code>\u00a0for the\u00a0<code>*mcp.CallToolResult<\/code>. The SDK automatically handles the response marshaling for us. If we return an error, the SDK sets\u00a0<code>IsError: true<\/code>\u00a0in the result automatically.<\/p>\n<h3 id=\"authenticating-with-azure-cosmos-db\" class=\"code-line\" dir=\"auto\" data-line=\"225\">Authenticating with Azure Cosmos DB<\/h3>\n<p class=\"code-line\" dir=\"auto\" data-line=\"227\">The MCP server uses\u00a0<code>NewDefaultAzureCredential<\/code> from the Azure Identity SDK, which automatically handles multiple authentication methods, such as Azure CLI credentials (for local development), Managed Identity (for production), environment variables, and more:<\/p>\n<pre class=\"prettyprint language-go\"><code class=\"language-go\">func GetCosmosDBClient(accountName string) (*azcosmos.Client, error) {\r\n    endpoint := fmt.Sprintf(\"https:\/\/%s.documents.azure.com:443\/\", accountName)\r\n\r\n    cred, err := azidentity.NewDefaultAzureCredential(nil)\r\n    if err != nil {\r\n        return nil, fmt.Errorf(\"error creating credential: %v\", err)\r\n    }\r\n\r\n    client, err := azcosmos.NewClient(endpoint, cred, nil)\r\n    if err != nil {\r\n        return nil, fmt.Errorf(\"error creating Cosmos client: %v\", err)\r\n    }\r\n\r\n    return client, nil\r\n}<\/code><\/pre>\n<p class=\"code-line\" dir=\"auto\" data-line=\"247\">Once we have the client, we use the standard Azure Cosmos DB SDK patterns:<\/p>\n<ul class=\"code-line\" dir=\"auto\" data-line=\"249\">\n<li class=\"code-line\" dir=\"auto\" data-line=\"249\"><code>client.NewDatabase()<\/code>\u00a0to get a database client<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"250\"><code>databaseClient.NewContainer()<\/code>\u00a0to get a container client<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"251\"><code>containerClient.ReadItem()<\/code>\u00a0to perform the actual read operation<\/li>\n<\/ul>\n<h3 id=\"mcp-server-bringing-tools-together\" class=\"code-line\" dir=\"auto\" data-line=\"255\">MCP Server: Bringing Tools Together<\/h3>\n<p>The beauty here is that MCP provides the standardized interface for AI interactions, while the Azure Cosmos DB SDK handles all the database operations \u2013 the handler acts as the <strong>bridge<\/strong>\u00a0between these two worlds.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"257\">Now that we understand individual tools, let&#8217;s see how they&#8217;re organized within an MCP server. An MCP server exposes specific capabilities (tools, resources, prompts) to AI applications through the standardized MCP protocol.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"259\"><strong>Creating the Server<\/strong><\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"261\">Here&#8217;s how we create and configure the MCP server in\u00a0<a href=\"https:\/\/github.com\/abhirockzz\/mcp_cosmosdb_go\/blob\/main\/main.go\" data-href=\"https:\/\/github.com\/abhirockzz\/mcp_cosmosdb_go\/blob\/main\/main.go\">main.go<\/a>:<\/p>\n<pre class=\"prettyprint language-go\"><code class=\"language-go\">func main() {\r\n    \/\/ Create the server with metadata\r\n    server := mcp.NewServer(&amp;mcp.Implementation{\r\n\t\tName:       \"mcp_azure_cosmosdb_go\",\r\n\t\tTitle:      \"Go based MCP server for Azure Cosmos DB using the Azure SDK for Go and the MCP Go SDK\",\r\n\t\tVersion:    \"0.0.1\",\r\n\t\tWebsiteURL: \"https:\/\/github.com\/abhirockzz\/mcp_cosmosdb_go\",\r\n\t}, nil)\r\n\r\n    \/\/ Register all tools with their handlers\r\n    mcp.AddTool(server, tools.ListDatabases(), tools.ListDatabasesToolHandler)\r\n    mcp.AddTool(server, tools.ListContainers(), tools.ListContainersToolHandler)\r\n    mcp.AddTool(server, tools.ReadContainerMetadata(), tools.ReadContainerMetadataToolHandler)\r\n    mcp.AddTool(server, tools.CreateContainer(), tools.CreateContainerToolHandler)\r\n    mcp.AddTool(server, tools.AddItemToContainer(), tools.AddItemToContainerToolHandler)\r\n    mcp.AddTool(server, tools.ReadItem(), tools.ReadItemToolHandler)\r\n    mcp.AddTool(server, tools.ExecuteQuery(), tools.ExecuteQueryToolHandler)\r\n\r\n    \/\/ ... transport setup (covered next)\r\n}<\/code><\/pre>\n<p class=\"code-line\" dir=\"auto\" data-line=\"286\">Breaking this down:<\/p>\n<ol class=\"code-line\" dir=\"auto\" data-line=\"288\">\n<li class=\"code-line\" dir=\"auto\" data-line=\"288\">\n<p class=\"code-line\" dir=\"auto\" data-line=\"288\"><strong><code>mcp.NewServer()<\/code><\/strong>\u00a0creates a new server instance with:<\/p>\n<ul class=\"code-line\" dir=\"auto\" data-line=\"289\">\n<li class=\"code-line\" dir=\"auto\" data-line=\"289\"><strong>Implementation metadata<\/strong>: Name, title, and version that identify the server<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"290\"><strong>ServerOptions<\/strong>: Additional configuration (we use\u00a0<code>nil<\/code>\u00a0for defaults)<\/li>\n<\/ul>\n<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"292\">\n<p class=\"code-line\" dir=\"auto\" data-line=\"292\"><strong><code>mcp.AddTool()<\/code><\/strong>\u00a0registers each tool with the server:<\/p>\n<ul class=\"code-line\" dir=\"auto\" data-line=\"293\">\n<li class=\"code-line\" dir=\"auto\" data-line=\"293\">Takes the server instance<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"294\">The tool definition (from functions like\u00a0<code>tools.ReadItem()<\/code>)<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"295\">The handler function (like\u00a0<code>tools.ReadItemToolHandler<\/code>)<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p class=\"code-line\" dir=\"auto\" data-line=\"297\">When the server connects to a client, it automatically advertises the\u00a0<code>tools<\/code>\u00a0capability, making all registered tools discoverable by the AI application.<\/p>\n<h3 id=\"transport-connecting-server-to-client\" class=\"code-line\" dir=\"auto\" data-line=\"299\">Transport: Connecting Server to Client<\/h3>\n<p class=\"code-line\" dir=\"auto\" data-line=\"301\">A transport defines how the server communicates with clients. It&#8217;s the communication channel that carries JSON-RPC messages between the server and client. The MCP Go SDK supports multiple transport types.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"303\"><strong>HTTP Streamable Transport<\/strong><\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"305\">The server also supports\u00a0<code>http<\/code>\u00a0transport, which is ideal for web-based AI applications. Here&#8217;s how we set it up:<\/p>\n<pre class=\"prettyprint language-go\"><code class=\"language-go\">\/\/ Create the streamable HTTP handler\r\nhandler := mcp.NewStreamableHTTPHandler(func(req *http.Request) *mcp.Server {\r\n    return server\r\n}, nil)\r\n\r\n\/\/ Start the HTTP server\r\nif err := http.ListenAndServe(\":9090\", handler); err != nil {\r\n    log.Fatalf(\"Server failed: %v\", err)\r\n}<\/code><\/pre>\n<p class=\"code-line\" dir=\"auto\" data-line=\"319\">The\u00a0<code>NewStreamableHTTPHandler<\/code>\u00a0creates an HTTP handler that accepts incoming HTTP requests from MCP clients, and returns the appropriate server instance for each request. It handles the streamable transport protocol automatically, and supports multiple concurrent client sessions<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"321\">This transport is ideal when you want to support web-based AI applications and the server needs to be accessible over HTTP\/HTTPS. This allows multiple clients to connect simultaneously.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"323\"><strong>Stdio Transport<\/strong><\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"325\">Another common MCP transport is\u00a0<strong>stdio<\/strong>, used when the server runs as a subprocess:<\/p>\n<pre class=\"prettyprint language-go\"><code class=\"language-go\">err := server.Run(context.Background(), &amp;mcp.StdioTransport{})\r\nif err != nil {\r\n    log.Fatal(err)\r\n}<\/code><\/pre>\n<p class=\"code-line\" dir=\"auto\" data-line=\"334\">The stdio transport runs as a subprocess started by the client and communicates via standard input\/output streams. It&#8217;s perfect for local MCP clients like GitHub Copilot CLI, Claude Code (or Desktop), etc. Both transports implement the same MCP protocol, so the server&#8217;s tools work identically regardless of which transport you choose. The difference is purely in how the server connects to and communicates with clients.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"336\">With the server created, tools registered, and transport configured, the MCP server is ready to accept connections from AI applications and execute operations against Azure Cosmos DB.<\/p>\n<h2 id=\"testing-the-mcp-server\" class=\"code-line\" dir=\"auto\" data-line=\"338\">Testing the MCP Server<\/h2>\n<p class=\"code-line\" dir=\"auto\" data-line=\"340\">This involves verifying functionality at different layers of the stack. This server uses\u00a0<strong>integration tests<\/strong>\u00a0at two levels: tests that verify the MCP protocol aspects, and tests that focus on handler logic with database interactions. Let&#8217;s explore both approaches.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"342\">Before diving into testing, let&#8217;s briefly understand what an MCP client is.<\/p>\n<h3 id=\"understanding-mcp-clients\" class=\"code-line\" dir=\"auto\" data-line=\"344\">Understanding MCP Clients<\/h3>\n<p class=\"code-line\" dir=\"auto\" data-line=\"346\">An\u00a0<strong>MCP client<\/strong>\u00a0is the component that connects to an MCP server to consume its capabilities. In the context of the MCP server:<\/p>\n<ul class=\"code-line\" dir=\"auto\" data-line=\"348\">\n<li class=\"code-line\" dir=\"auto\" data-line=\"348\"><strong>In production<\/strong>: The client is typically an AI application (like Claude Desktop or VS Code) that discovers and calls our tools<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"349\"><strong>In testing<\/strong>: We create programmatic clients to verify our server works correctly<\/li>\n<\/ul>\n<p class=\"code-line\" dir=\"auto\" data-line=\"351\">The MCP Go SDK provides a\u00a0<a href=\"https:\/\/pkg.go.dev\/github.com\/modelcontextprotocol\/go-sdk\/mcp#Client\" data-href=\"https:\/\/pkg.go.dev\/github.com\/modelcontextprotocol\/go-sdk\/mcp#Client\">Client<\/a>\u00a0type that we can use to connect to our server and call its tools, simulating how a real AI application would interact with it.<\/p>\n<h3 id=\"handler-level-integration-testing-with-azure-cosmos-db-vnext-emulator\" class=\"code-line\" dir=\"auto\" data-line=\"353\">Handler-Level Integration Testing with Azure Cosmos DB vNext Emulator<\/h3>\n<p class=\"code-line\" dir=\"auto\" data-line=\"355\">Let&#8217;s start by looking at tests that focus on handler logic and database interactions. It uses the\u00a0<a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/cosmos-db\/emulator-linux\" data-href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/cosmos-db\/emulator-linux\">Azure Cosmos DB vNext Emulator<\/a>\u00a0with\u00a0<a href=\"https:\/\/golang.testcontainers.org\/\" data-href=\"https:\/\/golang.testcontainers.org\/\">testcontainers-go<\/a>.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"358\">From\u00a0<a href=\"https:\/\/github.com\/abhirockzz\/mcp_cosmosdb_go\/blob\/main\/tools\/tools_test.go\" data-href=\"https:\/\/github.com\/abhirockzz\/mcp_cosmosdb_go\/blob\/main\/tools\/tools_test.go\"><code>tools_test.go<\/code><\/a>:<\/p>\n<pre class=\"prettyprint language-go\"><code class=\"language-go\">func TestListDatabases(t *testing.T) {\r\n    tests := []struct {\r\n        name           string\r\n        input          ListDatabasesToolInput\r\n        expectError    bool\r\n        expectedResult string\r\n        expectedErrMsg string\r\n    }{\r\n        {\r\n            name: \"valid account name\",\r\n            input: ListDatabasesToolInput{\r\n                Account: \"dummy_account_does_not_matter\",\r\n            },\r\n            expectError:    false,\r\n            expectedResult: testOperationDBName,\r\n        },\r\n        {\r\n            name: \"empty account name\",\r\n            input: ListDatabasesToolInput{\r\n                Account: \"\",\r\n            },\r\n            expectError:    true,\r\n            expectedErrMsg: \"cosmos db account name missing\",\r\n        },\r\n    }\r\n\r\n    for _, test := range tests {\r\n        t.Run(test.name, func(t *testing.T) {\r\n            _, response, err := ListDatabasesToolHandler(\r\n                context.Background(), \r\n                nil, \r\n                test.input,\r\n            )\r\n\r\n            if test.expectError {\r\n                require.Error(t, err)\r\n                assert.Contains(t, err.Error(), test.expectedErrMsg)\r\n                return\r\n            }\r\n\r\n            require.NoError(t, err)\r\n            assert.Contains(t, response.Databases, test.expectedResult)\r\n        })\r\n    }\r\n}<\/code><\/pre>\n<p dir=\"auto\" data-line=\"358\">These tests call handlers directly (bypassing the MCP protocol layer) and use\u00a0<a href=\"https:\/\/go.dev\/wiki\/TableDrivenTests\" data-href=\"https:\/\/go.dev\/wiki\/TableDrivenTests\">table-driven tests<\/a>\u00a0for input validation and error handling, business logic correctness, database operations and edge cases.<\/p>\n<pre class=\"prettyprint language-go\"><code class=\"language-go\">func setupCosmosEmulator(ctx context.Context) (testcontainers.Container, error) {\r\n    req := testcontainers.ContainerRequest{\r\n        Image:        \"mcr.microsoft.com\/cosmosdb\/linux\/azure-cosmos-emulator:vnext-preview\",\r\n        ExposedPorts: []string{\"8081:8081\", \"8080:8080\"},\r\n        WaitingFor:   wait.ForListeningPort(nat.Port(\"8080\")),\r\n        Env: map[string]string{\r\n            \"PROTOCOL\": \"http\",\r\n        },\r\n    }\r\n\r\n    container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{\r\n        ContainerRequest: req,\r\n        Started:          true,\r\n    })\r\n    \/\/ ... error handling\r\n    \r\n    return container, nil\r\n}<\/code><\/pre>\n<p dir=\"auto\" data-line=\"358\">The\u00a0<code>testcontainers-go<\/code>\u00a0library automatically pulls the emulator image, starts the container, and cleans up after tests complete. This is set up once in\u00a0<a href=\"https:\/\/github.com\/abhirockzz\/mcp_cosmosdb_go\/blob\/main\/tools\/tools_test.go#L22\" data-href=\"https:\/\/github.com\/abhirockzz\/mcp_cosmosdb_go\/blob\/main\/tools\/tools_test.go#L22\">TestMain<\/a>\u00a0function and shared across all tests.<\/p>\n<p dir=\"auto\" data-line=\"358\"><div class=\"alert alert-primary\">You can read more about this in <a href=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/integration-testing-for-go-applications-using-testcontainers-and-containerized-databases\/\">Integration Testing for Go Applications<\/a><\/div><\/p>\n<h3 id=\"mcp-protocol-integration-testing\" class=\"code-line\" dir=\"auto\" data-line=\"434\">MCP Protocol Integration Testing<\/h3>\n<p class=\"code-line\" dir=\"auto\" data-line=\"436\">Beyond handler testing, we also verify the complete MCP protocol stack\u2014from client request through server processing to response. Here&#8217;s an example from\u00a0<a href=\"https:\/\/github.com\/abhirockzz\/mcp_cosmosdb_go\/blob\/main\/tools\/mcp_integration_test.go\" data-href=\"https:\/\/github.com\/abhirockzz\/mcp_cosmosdb_go\/blob\/main\/tools\/mcp_integration_test.go\">mcp_integration_test.go<\/a>:<\/p>\n<pre class=\"prettyprint language-go\"><code class=\"language-go\">func TestMCPIntegration_ReadItem(t *testing.T) {\r\n    ctx := context.Background()\r\n\r\n    \/\/ 1. Create MCP server and register the read_item tool\r\n    server := mcp.NewServer(&amp;mcp.Implementation{\r\n        Name:    \"test-cosmosdb-server\",\r\n        Version: \"0.0.1\",\r\n    }, nil)\r\n    \r\n    mcp.AddTool(server, ReadItem(), ReadItemToolHandler)\r\n\r\n    \/\/ 2. Create in-memory transports for testing\r\n    serverTransport, clientTransport := mcp.NewInMemoryTransports()\r\n\r\n    \/\/ 3. Connect server\r\n    serverSession, err := server.Connect(ctx, serverTransport, nil)\r\n    require.NoError(t, err)\r\n    defer serverSession.Close()\r\n\r\n    \/\/ 4. Create and connect client\r\n    client := mcp.NewClient(&amp;mcp.Implementation{\r\n        Name:    \"test-client\",\r\n        Version: \"0.0.1\",\r\n    }, nil)\r\n\r\n    clientSession, err := client.Connect(ctx, clientTransport, nil)\r\n    require.NoError(t, err)\r\n    defer clientSession.Close()\r\n\r\n    \/\/ 5. Call the tool via MCP protocol\r\n    result, err := clientSession.CallTool(ctx, &amp;mcp.CallToolParams{\r\n        Name: \"read_item\",\r\n        Arguments: map[string]any{\r\n            \"account\":      \"dummy_account_does_not_matter\",\r\n            \"database\":     testOperationDBName,\r\n            \"container\":    testOperationContainerName,\r\n            \"itemID\":       id,\r\n            \"partitionKey\": partitionKeyValue,\r\n        },\r\n    })\r\n\r\n    \/\/ 6. Verify the response\r\n    require.NoError(t, err)\r\n    require.False(t, result.IsError)\r\n    require.NotEmpty(t, result.Content)\r\n\r\n    \/\/ 7. Parse and validate the JSON response\r\n    textContent, ok := result.Content[0].(*mcp.TextContent)\r\n    require.True(t, ok)\r\n\r\n    var response ReadItemToolResult\r\n    err = json.Unmarshal([]byte(textContent.Text), &amp;response)\r\n    require.NoError(t, err)\r\n    \r\n    assert.NotEmpty(t, response.Item)\r\n}<\/code><\/pre>\n<p class=\"code-line\" dir=\"auto\" data-line=\"497\">This test demonstrates several key concepts:<\/p>\n<ol class=\"code-line\" dir=\"auto\" data-line=\"499\">\n<li class=\"code-line\" dir=\"auto\" data-line=\"499\"><strong>In-Memory Transports<\/strong>:\u00a0<code>mcp.NewInMemoryTransports()<\/code>\u00a0creates a pair of connected transports without requiring actual network communication\u2014perfect for testing<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"500\"><strong>Client-Server Connection<\/strong>: Both server and client connect to their respective transports, establishing a session<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"501\"><strong>Tool Invocation<\/strong>:\u00a0<code>clientSession.CallTool()<\/code>\u00a0sends a properly formatted MCP request<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"502\"><strong>Response Handling<\/strong>: The result is parsed from the MCP protocol format back to our domain types<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"503\"><strong>Full Protocol Verification<\/strong>: This tests the complete round trip: request serialization \u2192 tool execution \u2192 response serialization \u2192 client parsing<\/li>\n<\/ol>\n<p class=\"code-line\" dir=\"auto\" data-line=\"504\">Both handler-level and protocol-level tests use the Azure Cosmos DB vNext emulator, not mocks. Handler-level tests provide feedback on business logic, while protocol-level tests ensure MCP compliance and end-to-end functionality.<\/p>\n<h2 id=\"wrap-up\" class=\"code-line\" dir=\"auto\" data-line=\"507\">Wrap Up<\/h2>\n<p class=\"code-line\" dir=\"auto\" data-line=\"509\">With the MCP Go SDK, building MCP servers has become significantly more accessible for Go developers. You don&#8217;t have to <em>go for Python<\/em>\u00a0anymore (sorry Pythonistas, pun intended!).<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"511\">This MCP server demonstrates how to combine the MCP Go SDK with domain-specific tools \u2014 in this case, the Azure Cosmos DB Go SDK. While this server provides useful functionality for interacting with Azure Cosmos DB from AI applications, <strong>its primary purpose is educational<\/strong>. As mentioned before, this is a learning tool that shows how to integrate MCP with real-world services, not a replacement for solutions like the\u00a0<a href=\"https:\/\/github.com\/Azure\/azure-mcp-server\" data-href=\"https:\/\/github.com\/Azure\/azure-mcp-server\">Azure MCP Server<\/a>\u00a0or the\u00a0<a href=\"https:\/\/github.com\/AzureCosmosDB\/MCPToolKit\" data-href=\"https:\/\/github.com\/AzureCosmosDB\/MCPToolKit\">Azure Cosmos DB MCP Toolkit<\/a>.<\/p>\n<p class=\"code-line\" dir=\"auto\" data-line=\"513\">The specific patterns we covered (defining tools, implementing handlers, managing authentication, choosing transports, and writing integration tests) apply to any MCP server you might build. The same concepts apply, whether you&#8217;re exposing APIs, databases, file systems, or custom business logic.<\/p>\n<h3 id=\"next-steps\" class=\"code-line\" dir=\"auto\" data-line=\"515\">Next Steps<\/h3>\n<p class=\"code-line\" dir=\"auto\" data-line=\"517\">Ready to build your own MCP server? Here are some resources to get you started:<\/p>\n<ul class=\"code-line\" dir=\"auto\" data-line=\"519\">\n<li style=\"list-style-type: none;\">\n<ul class=\"code-line\" dir=\"auto\" data-line=\"519\">\n<li class=\"code-line\" dir=\"auto\" data-line=\"519\"><strong>MCP Go SDK resources<\/strong>:\u00a0<a href=\"https:\/\/github.com\/modelcontextprotocol\/go-sdk\/tree\/main\/docs\" data-href=\"https:\/\/github.com\/modelcontextprotocol\/go-sdk\/tree\/main\/docs\">Documentation<\/a>,\u00a0<a href=\"https:\/\/github.com\/modelcontextprotocol\/go-sdk\/tree\/main\/design\" data-href=\"https:\/\/github.com\/modelcontextprotocol\/go-sdk\/tree\/main\/design\">design<\/a>, and\u00a0<a href=\"https:\/\/github.com\/modelcontextprotocol\/go-sdk\/tree\/main\/examples\" data-href=\"https:\/\/github.com\/modelcontextprotocol\/go-sdk\/tree\/main\/examples\">examples<\/a>.<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"520\"><strong>MCP Specification<\/strong>:\u00a0<a href=\"https:\/\/modelcontextprotocol.io\/\" data-href=\"https:\/\/modelcontextprotocol.io\/\">https:\/\/modelcontextprotocol.io\/<\/a><\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"521\"><strong>Azure Cosmos DB Go SDK<\/strong>:\u00a0<a href=\"https:\/\/pkg.go.dev\/github.com\/Azure\/azure-sdk-for-go\/sdk\/data\/azcosmos\" data-href=\"https:\/\/pkg.go.dev\/github.com\/Azure\/azure-sdk-for-go\/sdk\/data\/azcosmos\">https:\/\/pkg.go.dev\/github.com\/Azure\/azure-sdk-for-go\/sdk\/data\/azcosmos<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p class=\"code-line\" dir=\"auto\" data-line=\"524\">The\u00a0<a href=\"https:\/\/www.linuxfoundation.org\/press\/linux-foundation-announces-the-formation-of-the-agentic-ai-foundation\" data-href=\"https:\/\/www.linuxfoundation.org\/press\/linux-foundation-announces-the-formation-of-the-agentic-ai-foundation\">MCP ecosystem is growing rapidly<\/a>, and I am excited for Go developers who now have first-class support for participating in this evolution!<\/p>\n<h2><strong>About Azure Cosmos DB<\/strong><\/h2>\n<p>Azure Cosmos DB is a fully managed and serverless NoSQL and vector database for modern app development, including AI applications. With its SLA-backed speed and availability as well as instant dynamic scalability, it is ideal for real-time NoSQL and MongoDB applications that require high performance and distributed computing over massive volumes of NoSQL and vector data.<\/p>\n<p>To stay in the loop on Azure Cosmos DB updates, follow us on\u00a0<a href=\"https:\/\/twitter.com\/AzureCosmosDB\" target=\"_blank\" rel=\"noopener\">X<\/a>,\u00a0<a href=\"https:\/\/aka.ms\/AzureCosmosDBYouTube\" target=\"_blank\" rel=\"noopener\">YouTube<\/a>, and\u00a0<a href=\"https:\/\/www.linkedin.com\/company\/azure-cosmos-db\/\" target=\"_blank\" rel=\"noopener\">LinkedIn<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A hands\u2011on walkthrough of building MCP servers that can plug AI applications into Azure Cosmos DB The\u00a0Model Context Protocol\u00a0(MCP) has established itself as the ubiquitous standard for connecting AI applications to external systems. Since its release, there have been\u00a0implementations\u00a0across various programming languages and frameworks, enabling developers to build solutions that expose data sources, tools, and [&hellip;]<\/p>\n","protected":false},"author":181737,"featured_media":11673,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1610,1980,14,1935],"tags":[1236,1984,499,1965],"class_list":["post-11654","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","category-azure-cosmos-db","category-core-sql-api","category-go-sdk","tag-ai","tag-ai-agents","tag-azure-cosmos-db","tag-mcp"],"acf":[],"blog_post_summary":"<p>A hands\u2011on walkthrough of building MCP servers that can plug AI applications into Azure Cosmos DB The\u00a0Model Context Protocol\u00a0(MCP) has established itself as the ubiquitous standard for connecting AI applications to external systems. Since its release, there have been\u00a0implementations\u00a0across various programming languages and frameworks, enabling developers to build solutions that expose data sources, tools, and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/11654","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/users\/181737"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/comments?post=11654"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/11654\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media\/11673"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media?parent=11654"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/categories?post=11654"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/tags?post=11654"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}