02 Client

Module
Getting Started
Progress
11%

Creating a client

Clients are custom applications or scripts that communicate directly with an MCP Server to request resources, tools, and prompts.

Unlike using the inspector tool, which provides a graphical interface for interacting with the server, writing your own client allows for programmatic and automated interactions.

This enables developers to integrate MCP capabilities into their own workflows, automate tasks, and build custom solutions tailored to specific needs.

Overview

This lesson introduces the concept of clients within the Model Context Protocol (MCP) ecosystem. You'll learn how to write your own client and have it connect to an MCP Server.

Learning Objectives

By the end of this lesson, you will be able to:

  • Understand what a client can do.
  • Write your own client.
  • Connect and test the client with an MCP server to ensure the latter works as expected.
  • What goes into writing a client?

    To write a client, you'll need to do the following:

  • Import the correct libraries. You'll be using the same library as before, just different constructs.
  • Instantiate a client. This will involve creating a client instance and connect it to the chosen transport method.
  • Decide on what resources to list. Your MCP server comes with resources, tools and prompts, you need to decide which one to list.
  • Integrate the client to a host application. Once you know the capabilities of the server you need to integrate this your host application so that if a user types a prompt or other command the corresponding server feature is invoked.
  • Now that we understand at high level what we're about to do, let's look at an example next.

    An example client

    Let's have a look at this example client:

    TypeScript

    
    import { Client } from "@modelcontextprotocol/sdk/client/index.js";
    
    import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
    
    
    
    const transport = new StdioClientTransport({
    
      command: "node",
    
      args: ["server.js"]
    
    });
    
    
    
    const client = new Client(
    
      {
    
        name: "example-client",
    
        version: "1.0.0"
    
      }
    
    );
    
    
    
    await client.connect(transport);
    
    
    
    // List prompts
    
    const prompts = await client.listPrompts();
    
    
    
    // Get a prompt
    
    const prompt = await client.getPrompt({
    
      name: "example-prompt",
    
      arguments: {
    
        arg1: "value"
    
      }
    
    });
    
    
    
    // List resources
    
    const resources = await client.listResources();
    
    
    
    // Read a resource
    
    const resource = await client.readResource({
    
      uri: "file:///example.txt"
    
    });
    
    
    
    // Call a tool
    
    const result = await client.callTool({
    
      name: "example-tool",
    
      arguments: {
    
        arg1: "value"
    
      }
    
    });
    
    

    In the preceding code we:

  • Import the libraries
  • Create an instance of a client and connect it using stdio for transport.
  • List prompts, resources and tools and invoke them all.
  • There you have it, a client that can talk to an MCP Server.

    Let's take our time in the next exercise section and break down each code snippet and explain what's going on.

    Exercise: Writing a client

    As said above, let's take our time explaining the code, and by all means code along if you want.

    -1- Import the libraries

    Let's import the libraries we need, we will need references to a client and to our chosen transport protocol, stdio. stdio is a protocol for things meant to run on your local machine.

    SSE is another transport protocol we will show in future chapters but that's your other option.

    For now though, let's continue with stdio.

    TypeScript
    
    import { Client } from "@modelcontextprotocol/sdk/client/index.js";
    
    import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
    
    
    Python
    
    from mcp import ClientSession, StdioServerParameters, types
    
    from mcp.client.stdio import stdio_client
    
    
    .NET
    
    using Microsoft.Extensions.AI;
    
    using Microsoft.Extensions.Configuration;
    
    using Microsoft.Extensions.Hosting;
    
    using ModelContextProtocol.Client;
    
    
    Java

    For Java, you'll create a client that connects to the MCP server from the previous exercise.

    Using the same Java Spring Boot project structure from Getting Started with MCP Server, create a new Java class called SDKClient in the src/main/java/com/microsoft/mcp/sample/client/ folder and add the following imports:

    
    import java.util.Map;
    
    import org.springframework.web.reactive.function.client.WebClient;
    
    import io.modelcontextprotocol.client.McpClient;
    
    import io.modelcontextprotocol.client.transport.WebFluxSseClientTransport;
    
    import io.modelcontextprotocol.spec.McpClientTransport;
    
    import io.modelcontextprotocol.spec.McpSchema.CallToolRequest;
    
    import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
    
    import io.modelcontextprotocol.spec.McpSchema.ListToolsResult;
    
    
    Rust

    You will need to add the following dependencies to your Cargo.toml file.

    
    [package]
    
    name = "calculator-client"
    
    version = "0.1.0"
    
    edition = "2024"
    
    
    
    [dependencies]
    
    rmcp = { version = "0.5.0", features = ["client", "transport-child-process"] }
    
    serde_json = "1.0.141"
    
    tokio = { version = "1.46.1", features = ["rt-multi-thread"] }
    
    

    From there, you can import the necessary libraries in your client code.

    
    use rmcp::{
    
        RmcpError,
    
        model::CallToolRequestParam,
    
        service::ServiceExt,
    
        transport::{ConfigureCommandExt, TokioChildProcess},
    
    };
    
    use tokio::process::Command;
    
    

    Let's move on to instantiation.

    -2- Instantiating client and transport

    We will need to create an instance of the transport and that of our client:

    TypeScript
    
    const transport = new StdioClientTransport({
    
      command: "node",
    
      args: ["server.js"]
    
    });
    
    
    
    const client = new Client(
    
      {
    
        name: "example-client",
    
        version: "1.0.0"
    
      }
    
    );
    
    
    
    await client.connect(transport);
    
    

    In the preceding code we've:

  • Created an stdio transport instance. Note how it specifies command and args for how to find and start up the server as that's something we will need to do as we create the client.
  • ```typescript

    const transport = new StdioClientTransport({

    command: "node",

    args: ["server.js"]

    });

    ```

  • Instantiated a client by giving it a name and version.
  • ```typescript

    const client = new Client(

    {

    name: "example-client",

    version: "1.0.0"

    });

    ```

  • Connected the client to the chosen transport.
  • ```typescript

    await client.connect(transport);

    ```

    Python
    
    from mcp import ClientSession, StdioServerParameters, types
    
    from mcp.client.stdio import stdio_client
    
    
    
    # Create server parameters for stdio connection
    
    server_params = StdioServerParameters(
    
        command="mcp",  # Executable
    
        args=["run", "server.py"],  # Optional command line arguments
    
        env=None,  # Optional environment variables
    
    )
    
    
    
    async def run():
    
        async with stdio_client(server_params) as (read, write):
    
            async with ClientSession(
    
                read, write
    
            ) as session:
    
                # Initialize the connection
    
                await session.initialize()
    
    
    
              
    
    
    
    if __name__ == "__main__":
    
        import asyncio
    
    
    
        asyncio.run(run())
    
    

    In the preceding code we've:

  • Imported the needed libraries
  • Instantiated a server parameters object as we will use this to run the server so we can connect to it with our client.
  • Defined a method run that in turn calls stdio_client which starts a client session.
  • Created an entry point where we provide the run method to asyncio.run.
  • .NET
    
    using Microsoft.Extensions.AI;
    
    using Microsoft.Extensions.Configuration;
    
    using Microsoft.Extensions.Hosting;
    
    using ModelContextProtocol.Client;
    
    
    
    var builder = Host.CreateApplicationBuilder(args);
    
    
    
    builder.Configuration
    
        .AddEnvironmentVariables()
    
        .AddUserSecrets<Program>();
    
    
    
    
    
    
    
    var clientTransport = new StdioClientTransport(new()
    
    {
    
        Name = "Demo Server",
    
        Command = "dotnet",
    
        Arguments = ["run", "--project", "path/to/file.csproj"],
    
    });
    
    
    
    await using var mcpClient = await McpClient.CreateAsync(clientTransport);
    
    

    In the preceding code we've:

  • Imported the needed libraries.
  • Create an stdio transport and created a client mcpClient. The latter is something we will use to list and invoke features on the MCP Server.
  • Note, in "Arguments", you can either point to the *.csproj* or to the executable.

    Java
    
    public class SDKClient {
    
        
    
        public static void main(String[] args) {
    
            var transport = new WebFluxSseClientTransport(WebClient.builder().baseUrl("http://localhost:8080"));
    
            new SDKClient(transport).run();
    
        }
    
        
    
        private final McpClientTransport transport;
    
    
    
        public SDKClient(McpClientTransport transport) {
    
            this.transport = transport;
    
        }
    
    
    
        public void run() {
    
            var client = McpClient.sync(this.transport).build();
    
            client.initialize();
    
            
    
            // Your client logic goes here
    
        }
    
    }
    
    

    In the preceding code we've:

  • Created a main method that sets up an SSE transport pointing to http://localhost:8080 where our MCP server will be running.
  • Created a client class that takes the transport as a constructor parameter.
  • In the run method, we create a synchronous MCP client using the transport and initialize the connection.
  • Used SSE (Server-Sent Events) transport which is suitable for HTTP-based communication with Java Spring Boot MCP servers.
  • Rust

    Note this Rust client assumes the server is a sibling project named "calculator-server" in the same directory. The code below will start the server and connect to it.

    
    async fn main() -> Result<(), RmcpError> {
    
        // Assume the server is a sibling project named "calculator-server" in the same directory
    
        let server_dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
    
            .parent()
    
            .expect("failed to locate workspace root")
    
            .join("calculator-server");
    
    
    
        let client = ()
    
            .serve(
    
                TokioChildProcess::new(Command::new("cargo").configure(|cmd| {
    
                    cmd.arg("run").current_dir(server_dir);
    
                }))
    
                .map_err(RmcpError::transport_creation::<TokioChildProcess>)?,
    
            )
    
            .await?;
    
    
    
        // TODO: Initialize
    
    
    
        // TODO: List tools
    
    
    
        // TODO: Call add tool with arguments = {"a": 3, "b": 2}
    
    
    
        client.cancel().await?;
    
        Ok(())
    
    }
    
    

    -3- Listing the server features

    Now, we have a client that can connect to should the program be run. However, it doesn't actually list its features so let's do that next:

    TypeScript
    
    // List prompts
    
    const prompts = await client.listPrompts();
    
    
    
    // List resources
    
    const resources = await client.listResources();
    
    
    
    // list tools
    
    const tools = await client.listTools();
    
    
    Python
    
    # List available resources
    
    resources = await session.list_resources()
    
    print("LISTING RESOURCES")
    
    for resource in resources:
    
        print("Resource: ", resource)
    
    
    
    # List available tools
    
    tools = await session.list_tools()
    
    print("LISTING TOOLS")
    
    for tool in tools.tools:
    
        print("Tool: ", tool.name)
    
    

    Here we list the available resources, list_resources() and tools, list_tools and print them out.

    .NET
    
    foreach (var tool in await client.ListToolsAsync())
    
    {
    
        Console.WriteLine($"{tool.Name} ({tool.Description})");
    
    }
    
    

    Above is an example how we can list the tools on the server. For each tool, we then print out its name.

    Java
    
    // List and demonstrate tools
    
    ListToolsResult toolsList = client.listTools();
    
    System.out.println("Available Tools = " + toolsList);
    
    
    
    // You can also ping the server to verify connection
    
    client.ping();
    
    

    In the preceding code we've:

  • Called listTools() to get all available tools from the MCP server.
  • Used ping() to verify that the connection to the server is working.
  • The ListToolsResult contains information about all tools including their names, descriptions, and input schemas.
  • Great, now we've captures all the features.

    Now the question is when do we use them?

    Well, this client is pretty simple, simple in the sense that we will need to explicitly call the features when we want them.

    In the next chapter, we will create a more advanced client that has access to it's own large language model, LLM.

    For now though, let's see how we can invoke the features on the server:

    Rust

    In the main function, after initializing the client, we can initialize the server and list some of its features.

    
    // Initialize
    
    let server_info = client.peer_info();
    
    println!("Server info: {:?}", server_info);
    
    
    
    // List tools
    
    let tools = client.list_tools(Default::default()).await?;
    
    println!("Available tools: {:?}", tools);
    
    

    -4- Invoke features

    To invoke the features we need to ensure we specify the correct arguments and in some cases the name of what we're trying to invoke.

    TypeScript
    
    
    
    // Read a resource
    
    const resource = await client.readResource({
    
      uri: "file:///example.txt"
    
    });
    
    
    
    // Call a tool
    
    const result = await client.callTool({
    
      name: "example-tool",
    
      arguments: {
    
        arg1: "value"
    
      }
    
    });
    
    
    
    // call prompt
    
    const promptResult = await client.getPrompt({
    
        name: "review-code",
    
        arguments: {
    
            code: "console.log(\"Hello world\")"
    
        }
    
    })
    
    

    In the preceding code we:

  • Read a resource, we call the resource by calling readResource() specifying uri. Here's what it most likely look like on the server side:
  • ```typescript

    server.resource(

    "readFile",

    new ResourceTemplate("file://{name}", { list: undefined }),

    async (uri, { name }) => ({

    contents: [{

    uri: uri.href,

    text: Hello, ${name}!

    }]

    })

    );

    ```

    Our uri value file://example.txt matches file://{name} on the server. example.txt will be mapped to name.

  • Call a tool, we call it by specifying its name and its arguments like so:
  • ```typescript

    const result = await client.callTool({

    name: "example-tool",

    arguments: {

    arg1: "value"

    }

    });

    ```

  • Get prompt, to get a prompt, you call getPrompt() with name and arguments. The server code looks like so:
  • ```typescript

    server.prompt(

    "review-code",

    { code: z.string() },

    ({ code }) => ({

    messages: [{

    role: "user",

    content: {

    type: "text",

    text: Please review this code:\n\n${code}

    }

    }]

    })

    );

    ```

    and your resulting client code therefore looks like so to match what's declared on the server:

    ```typescript

    const promptResult = await client.getPrompt({

    name: "review-code",

    arguments: {

    code: "console.log(\"Hello world\")"

    }

    })

    ```

    Python
    
    # Read a resource
    
    print("READING RESOURCE")
    
    content, mime_type = await session.read_resource("greeting://hello")
    
    
    
    # Call a tool
    
    print("CALL TOOL")
    
    result = await session.call_tool("add", arguments={"a": 1, "b": 7})
    
    print(result.content)
    
    

    In the preceding code, we've:

  • Called a resource called greeting using read_resource.
  • Invoked a tool called add using call_tool.
  • .NET

    1. Let's add some code to call a tool:

    ```csharp

    var result = await mcpClient.CallToolAsync(

    "Add",

    new Dictionary() { ["a"] = 1, ["b"] = 3 },

    cancellationToken:CancellationToken.None);

    ```

    1. To print out the result, here's some code to handle that:

    ```csharp

    Console.WriteLine(result.Content.First(c => c.Type == "text").Text);

    // Sum 4

    ```

    Java
    
    // Call various calculator tools
    
    CallToolResult resultAdd = client.callTool(new CallToolRequest("add", Map.of("a", 5.0, "b", 3.0)));
    
    System.out.println("Add Result = " + resultAdd);
    
    
    
    CallToolResult resultSubtract = client.callTool(new CallToolRequest("subtract", Map.of("a", 10.0, "b", 4.0)));
    
    System.out.println("Subtract Result = " + resultSubtract);
    
    
    
    CallToolResult resultMultiply = client.callTool(new CallToolRequest("multiply", Map.of("a", 6.0, "b", 7.0)));
    
    System.out.println("Multiply Result = " + resultMultiply);
    
    
    
    CallToolResult resultDivide = client.callTool(new CallToolRequest("divide", Map.of("a", 20.0, "b", 4.0)));
    
    System.out.println("Divide Result = " + resultDivide);
    
    
    
    CallToolResult resultHelp = client.callTool(new CallToolRequest("help", Map.of()));
    
    System.out.println("Help = " + resultHelp);
    
    

    In the preceding code we've:

  • Called multiple calculator tools using callTool() method with CallToolRequest objects.
  • Each tool call specifies the tool name and a Map of arguments required by that tool.
  • The server tools expect specific parameter names (like "a", "b" for mathematical operations).
  • Results are returned as CallToolResult objects containing the response from the server.
  • Rust
    
    // Call add tool with arguments = {"a": 3, "b": 2}
    
    let a = 3;
    
    let b = 2;
    
    let tool_result = client
    
        .call_tool(CallToolRequestParam {
    
            name: "add".into(),
    
            arguments: serde_json::json!({ "a": a, "b": b }).as_object().cloned(),
    
        })
    
        .await?;
    
    println!("Result of {:?} + {:?}: {:?}", a, b, tool_result);
    
    

    -5- Run the client

    To run the client, type the following command in the terminal:

    TypeScript

    Add the following entry to your "scripts" section in *package.json*:

    
    "client": "tsc && node build/client.js"
    
    
    
    npm run client
    
    
    Python

    Call the client with the following command:

    
    python client.py
    
    
    .NET
    
    dotnet run
    
    
    Java

    First, ensure your MCP server is running on http://localhost:8080. Then run the client:

    
    # Build you project
    
    ./mvnw clean compile
    
    
    
    # Run the client
    
    ./mvnw exec:java -Dexec.mainClass="com.microsoft.mcp.sample.client.SDKClient"
    
    

    Alternatively, you can run the complete client project provided in the solution folder 03-GettingStarted\02-client\solution\java:

    
    # Navigate to the solution directory
    
    cd 03-GettingStarted/02-client/solution/java
    
    
    
    # Build and run the JAR
    
    ./mvnw clean package
    
    java -jar target/calculator-client-0.0.1-SNAPSHOT.jar
    
    
    Rust
    
    cargo fmt
    
    cargo run
    
    

    Assignment

    In this assignment, you'll use what you've learned in creating a client but create a client of your own.

    Here's a server you can use that you need to call via your client code, see if you can add more features to the server to make it more interesting.

    TypeScript

    
    import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
    
    import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
    
    import { z } from "zod";
    
    
    
    // Create an MCP server
    
    const server = new McpServer({
    
      name: "Demo",
    
      version: "1.0.0"
    
    });
    
    
    
    // Add an addition tool
    
    server.tool("add",
    
      { a: z.number(), b: z.number() },
    
      async ({ a, b }) => ({
    
        content: [{ type: "text", text: String(a + b) }]
    
      })
    
    );
    
    
    
    // Add a dynamic greeting resource
    
    server.resource(
    
      "greeting",
    
      new ResourceTemplate("greeting://{name}", { list: undefined }),
    
      async (uri, { name }) => ({
    
        contents: [{
    
          uri: uri.href,
    
          text: `Hello, ${name}!`
    
        }]
    
      })
    
    );
    
    
    
    // Start receiving messages on stdin and sending messages on stdout
    
    
    
    async function main() {
    
      const transport = new StdioServerTransport();
    
      await server.connect(transport);
    
      console.error("MCPServer started on stdin/stdout");
    
    }
    
    
    
    main().catch((error) => {
    
      console.error("Fatal error: ", error);
    
      process.exit(1);
    
    });
    
    

    Python

    
    # server.py
    
    from mcp.server.fastmcp import FastMCP
    
    
    
    # Create an MCP server
    
    mcp = FastMCP("Demo")
    
    
    
    
    
    # Add an addition tool
    
    @mcp.tool()
    
    def add(a: int, b: int) -> int:
    
        """Add two numbers"""
    
        return a + b
    
    
    
    
    
    # Add a dynamic greeting resource
    
    @mcp.resource("greeting://{name}")
    
    def get_greeting(name: str) -> str:
    
        """Get a personalized greeting"""
    
        return f"Hello, {name}!"
    
    
    
    

    .NET

    
    using Microsoft.Extensions.DependencyInjection;
    
    using Microsoft.Extensions.Hosting;
    
    using Microsoft.Extensions.Logging;
    
    using ModelContextProtocol.Server;
    
    using System.ComponentModel;
    
    
    
    var builder = Host.CreateApplicationBuilder(args);
    
    builder.Logging.AddConsole(consoleLogOptions =>
    
    {
    
        // Configure all logs to go to stderr
    
        consoleLogOptions.LogToStandardErrorThreshold = LogLevel.Trace;
    
    });
    
    
    
    builder.Services
    
        .AddMcpServer()
    
        .WithStdioServerTransport()
    
        .WithToolsFromAssembly();
    
    await builder.Build().RunAsync();
    
    
    
    [McpServerToolType]
    
    public static class CalculatorTool
    
    {
    
        [McpServerTool, Description("Adds two numbers")]
    
        public static string Add(int a, int b) => $"Sum {a + b}";
    
    }
    
    

    See this project to see how you can add prompts and resources.

    Also, check this link for how to invoke prompts and resources.

    Rust

    In the previous section, you learned how to create a simple MCP server with Rust.

    You can continue to build on that or check this link for more Rust-based MCP server examples: MCP Server Examples

    Solution

    The solution folder contains complete, ready-to-run client implementations that demonstrate all the concepts covered in this tutorial. Each solution includes both client and server code organized in separate, self-contained projects.

    πŸ“ Solution Structure

    The solution directory is organized by programming language:

    
    solution/
    
    β”œβ”€β”€ typescript/          # TypeScript client with npm/Node.js setup
    
    β”‚   β”œβ”€β”€ package.json     # Dependencies and scripts
    
    β”‚   β”œβ”€β”€ tsconfig.json    # TypeScript configuration
    
    β”‚   └── src/             # Source code
    
    β”œβ”€β”€ java/                # Java Spring Boot client project
    
    β”‚   β”œβ”€β”€ pom.xml          # Maven configuration
    
    β”‚   β”œβ”€β”€ src/             # Java source files
    
    β”‚   └── mvnw             # Maven wrapper
    
    β”œβ”€β”€ python/              # Python client implementation
    
    β”‚   β”œβ”€β”€ client.py        # Main client code
    
    β”‚   β”œβ”€β”€ server.py        # Compatible server
    
    β”‚   └── README.md        # Python-specific instructions
    
    β”œβ”€β”€ dotnet/              # .NET client project
    
    β”‚   β”œβ”€β”€ dotnet.csproj    # Project configuration
    
    β”‚   β”œβ”€β”€ Program.cs       # Main client code
    
    β”‚   └── dotnet.sln       # Solution file
    
    β”œβ”€β”€ rust/                # Rust client implementation
    
    |  β”œβ”€β”€ Cargo.lock        # Cargo lock file
    
    |  β”œβ”€β”€ Cargo.toml        # Project configuration and dependencies
    
    |  β”œβ”€β”€ src               # Source code
    
    |  β”‚   └── main.rs       # Main client code
    
    └── server/              # Additional .NET server implementation
    
        β”œβ”€β”€ Program.cs       # Server code
    
        └── server.csproj    # Server project file
    
    

    πŸš€ What Each Solution Includes

    Each language-specific solution provides:

  • Complete client implementation with all features from the tutorial
  • Working project structure with proper dependencies and configuration
  • Build and run scripts for easy setup and execution
  • Detailed README with language-specific instructions
  • Error handling and result processing examples
  • πŸ“– Using the Solutions

    1. Navigate to your preferred language folder:

    ```bash

    cd solution/typescript/ # For TypeScript

    cd solution/java/ # For Java

    cd solution/python/ # For Python

    cd solution/dotnet/ # For .NET

    ```

    2. Follow the README instructions in each folder for:

    - Installing dependencies

    - Building the project

    - Running the client

    3. Example output you should see:

    ```text

    Prompt: Please review this code: console.log("hello");

    Resource template: file

    Tool result: { content: [ { type: 'text', text: '9' } ] }

    ```

    For complete documentation and step-by-step instructions, see: πŸ“– Solution Documentation

    🎯 Complete Examples

    We've provided complete, working client implementations for all programming languages covered in this tutorial.

    These examples demonstrate the full functionality described above and can be used as reference implementations or starting points for your own projects.

    Available Complete Examples

    | Language | File | Description |

    |----------|------|-------------|

    | Java | [client_example_java.java](./client_example_java.java) | Complete Java client using SSE transport with comprehensive error handling |

    | C# | [client_example_csharp.cs](./client_example_csharp.cs) | Complete C# client using stdio transport with automatic server startup |

    | TypeScript | [client_example_typescript.ts](./client_example_typescript.ts) | Complete TypeScript client with full MCP protocol support |

    | Python | [client_example_python.py](./client_example_python.py) | Complete Python client using async/await patterns |

    | Rust | [client_example_rust.rs](./client_example_rust.rs) | Complete Rust client using Tokio for async operations |

    Each complete example includes:

  • βœ… Connection establishment and error handling
  • βœ… Server discovery (tools, resources, prompts where applicable)
  • βœ… Calculator operations (add, subtract, multiply, divide, help)
  • βœ… Result processing and formatted output
  • βœ… Comprehensive error handling
  • βœ… Clean, documented code with step-by-step comments
  • Getting Started with Complete Examples

    1. Choose your preferred language from the table above

    2. Review the complete example file to understand the full implementation

    3. Run the example following the instructions in [complete_examples.md](./complete_examples.md)

    4. Modify and extend the example for your specific use case

    For detailed documentation about running and customizing these examples, see: πŸ“– Complete Examples Documentation

    πŸ’‘ Solution vs. Complete Examples

    | Solution Folder | Complete Examples |

    |--------------------|--------------------- |

    | Full project structure with build files | Single-file implementations |

    | Ready-to-run with dependencies | Focused code examples |

    | Production-like setup | Educational reference |

    | Language-specific tooling | Cross-language comparison |

    Both approaches are valuable - use the solution folder for complete projects and the complete examples for learning and reference.

    Key Takeaways

    The key takeaways for this chapter is the following about clients:

  • Can be used to both discover and invoke features on the server.
  • Can start a server while it starts itself (like in this chapter) but clients can connect to running servers as well.
  • Is a great way to test out server capabilities next to alternatives like the Inspector as was described in the previous chapter.
  • Additional Resources

  • Building clients in MCP
  • Samples

  • Java Calculator
  • .Net Calculator
  • JavaScript Calculator
  • TypeScript Calculator
  • Python Calculator
  • Rust Calculator
  • What's Next

  • Next: Creating a client with an LLM
  • ν΄λΌμ΄μ–ΈνŠΈ μƒμ„±ν•˜κΈ°

    ν΄λΌμ΄μ–ΈνŠΈλŠ” MCP μ„œλ²„μ™€ 직접 ν†΅μ‹ ν•˜μ—¬ λ¦¬μ†ŒμŠ€, 도ꡬ 및 ν”„λ‘¬ν”„νŠΈλ₯Ό μš”μ²­ν•˜λŠ” λ§žμΆ€ν˜• μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ˜λŠ” μŠ€ν¬λ¦½νŠΈμž…λ‹ˆλ‹€. μ„œλ²„μ™€ μƒν˜Έμž‘μš©ν•˜κΈ° μœ„ν•œ κ·Έλž˜ν”½ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ œκ³΅ν•˜λŠ” 검사 도ꡬ와 달리, μžμ‹ λ§Œμ˜ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μž‘μ„±ν•˜λ©΄ ν”„λ‘œκ·Έλž˜λ° λ°©μ‹μœΌλ‘œ μžλ™ν™”λœ μƒν˜Έμž‘μš©μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 κ°œλ°œμžλŠ” MCP κΈ°λŠ₯을 μžμ‹ μ˜ μ›Œν¬ν”Œλ‘œμš°μ— ν†΅ν•©ν•˜κ³  μž‘μ—…μ„ μžλ™ν™”ν•˜λ©° νŠΉμ • μš”κ΅¬ 사항에 맞좘 맞좀 μ†”λ£¨μ…˜μ„ ꡬ좕할 수 μžˆμŠ΅λ‹ˆλ‹€.

    κ°œμš”

    이 μˆ˜μ—…μ—μ„œλŠ” Model Context Protocol(MCP) μƒνƒœκ³„ λ‚΄ ν΄λΌμ΄μ–ΈνŠΈμ˜ κ°œλ…μ„ μ†Œκ°œν•©λ‹ˆλ‹€. 직접 ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μž‘μ„±ν•˜κ³  MCP μ„œλ²„μ— μ—°κ²°ν•˜λŠ” 방법을 배우게 λ©λ‹ˆλ‹€.

    ν•™μŠ΅ λͺ©ν‘œ

    이 μˆ˜μ—…μ΄ λλ‚˜λ©΄ λ‹€μŒμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

  • ν΄λΌμ΄μ–ΈνŠΈκ°€ 무엇을 ν•  수 μžˆλŠ”μ§€ μ΄ν•΄ν•©λ‹ˆλ‹€.
  • μžμ‹ λ§Œμ˜ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μž‘μ„±ν•©λ‹ˆλ‹€.
  • MCP μ„œλ²„μ™€ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μ—°κ²° 및 ν…ŒμŠ€νŠΈν•˜μ—¬ μ„œλ²„κ°€ μ˜ˆμƒλŒ€λ‘œ μž‘λ™ν•˜λŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
  • ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μž‘μ„±ν•˜λ €λ©΄ 무엇이 ν•„μš”ν•œκ°€?

    ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μž‘μ„±ν•˜λ €λ©΄ λ‹€μŒ μž‘μ—…μ„ μˆ˜ν–‰ν•΄μ•Ό ν•©λ‹ˆλ‹€:

  • μ˜¬λ°”λ₯Έ 라이브러리 μž„ν¬νŠΈ. 이전과 같은 라이브러리λ₯Ό μ‚¬μš©ν•˜μ§€λ§Œ λ‹€λ₯Έ ꡬ성 μš”μ†Œλ“€μ„ μ‚¬μš©ν•©λ‹ˆλ‹€.
  • ν΄λΌμ΄μ–ΈνŠΈ μΈμŠ€ν„΄μŠ€ν™”. ν΄λΌμ΄μ–ΈνŠΈ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜κ³  μ„ νƒν•œ 전솑 방식에 μ—°κ²°ν•΄μ•Ό ν•©λ‹ˆλ‹€.
  • λ‚˜μ—΄ν•  λ¦¬μ†ŒμŠ€ κ²°μ •. MCP μ„œλ²„μ—λŠ” λ¦¬μ†ŒμŠ€, 도ꡬ, ν”„λ‘¬ν”„νŠΈκ°€ μžˆμœΌλ―€λ‘œ μ–΄λ–€ 것을 λ‚˜μ—΄ν• μ§€ κ²°μ •ν•΄μ•Ό ν•©λ‹ˆλ‹€.
  • 호슀트 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— ν΄λΌμ΄μ–ΈνŠΈ 톡합. μ„œλ²„ κΈ°λŠ₯을 ν˜ΈμΆœν•˜λ„λ‘ μ‚¬μš©μž μž…λ ₯에 따라 ν΄λΌμ΄μ–ΈνŠΈλ₯Ό 호슀트 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— 톡합해야 ν•©λ‹ˆλ‹€.
  • 이제 ν•˜μ΄λ ˆλ²¨λ‘œ μ€€λΉ„ν•  λ‚΄μš©μ„ μ΄ν•΄ν–ˆμœΌλ‹ˆ, λ‹€μŒμœΌλ‘œ 예제λ₯Ό μ‚΄νŽ΄λ΄…μ‹œλ‹€.

    ν΄λΌμ΄μ–ΈνŠΈ 예제

    이 ν΄λΌμ΄μ–ΈνŠΈ 예제λ₯Ό λ³΄κ² μŠ΅λ‹ˆλ‹€:

    TypeScript

    
    import { Client } from "@modelcontextprotocol/sdk/client/index.js";
    
    import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
    
    
    
    const transport = new StdioClientTransport({
    
      command: "node",
    
      args: ["server.js"]
    
    });
    
    
    
    const client = new Client(
    
      {
    
        name: "example-client",
    
        version: "1.0.0"
    
      }
    
    );
    
    
    
    await client.connect(transport);
    
    
    
    // ν”„λ‘¬ν”„νŠΈ λͺ©λ‘
    
    const prompts = await client.listPrompts();
    
    
    
    // ν”„λ‘¬ν”„νŠΈ κ°€μ Έμ˜€κΈ°
    
    const prompt = await client.getPrompt({
    
      name: "example-prompt",
    
      arguments: {
    
        arg1: "value"
    
      }
    
    });
    
    
    
    // λ¦¬μ†ŒμŠ€ λͺ©λ‘
    
    const resources = await client.listResources();
    
    
    
    // λ¦¬μ†ŒμŠ€ 읽기
    
    const resource = await client.readResource({
    
      uri: "file:///example.txt"
    
    });
    
    
    
    // 도ꡬ 호좜
    
    const result = await client.callTool({
    
      name: "example-tool",
    
      arguments: {
    
        arg1: "value"
    
      }
    
    });
    
    

    μœ„ μ½”λ“œμ—μ„œ:

  • 라이브러리λ₯Ό κ°€μ Έμ™”μŠ΅λ‹ˆλ‹€.
  • ν΄λΌμ΄μ–ΈνŠΈ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜κ³  stdio 전솑 방식을 μ‚¬μš©ν•΄ μ—°κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
  • ν”„λ‘¬ν”„νŠΈ, λ¦¬μ†ŒμŠ€, 도ꡬλ₯Ό λ‚˜μ—΄ν•˜κ³  λͺ¨λ‘ ν˜ΈμΆœν–ˆμŠ΅λ‹ˆλ‹€.
  • μ΄λ ‡κ²Œ MCP μ„œλ²„μ™€ 톡신할 수 μžˆλŠ” ν΄λΌμ΄μ–ΈνŠΈκ°€ μ™„μ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

    λ‹€μŒ μ—°μŠ΅ μ„Ήμ…˜μ—μ„œ 각 μ½”λ“œ 쑰각을 μžμ„Ένžˆ λΆ„μ„ν•˜κ³  λ‚΄μš©μ„ μ„€λͺ…ν•˜κ² μŠ΅λ‹ˆλ‹€.

    μ—°μŠ΅: ν΄λΌμ΄μ–ΈνŠΈ μž‘μ„±ν•˜κΈ°

    μœ„μ—μ„œ λ§ν–ˆλ“―μ΄, μ½”λ“œλ₯Ό 천천히 μ‚΄νŽ΄λ³΄κ³  μ›ν•˜λ©΄ 직접 따라 μ½”λ”©ν•΄λ³΄μ„Έμš”.

    -1- 라이브러리 μž„ν¬νŠΈ

    ν•„μš”ν•œ 라이브러리λ₯Ό μž„ν¬νŠΈν•©λ‹ˆλ‹€. ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„ νƒν•œ 전솑 ν”„λ‘œν† μ½œ stdio에 λŒ€ν•œ μ°Έμ‘°κ°€ ν•„μš”ν•©λ‹ˆλ‹€. stdioλŠ” 둜컬 λ¨Έμ‹ μ—μ„œ μ‹€ν–‰λ˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μš© ν”„λ‘œν† μ½œμž…λ‹ˆλ‹€. SSEλŠ” 이후 μž₯μ—μ„œ μ†Œκ°œν•  또 λ‹€λ₯Έ 전솑 λ°©μ‹μž…λ‹ˆλ‹€. μ§€κΈˆμ€ stdioλ₯Ό 계속 μ‚¬μš©ν•©μ‹œλ‹€.

    TypeScript
    
    import { Client } from "@modelcontextprotocol/sdk/client/index.js";
    
    import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
    
    
    Python
    
    from mcp import ClientSession, StdioServerParameters, types
    
    from mcp.client.stdio import stdio_client
    
    
    .NET
    
    using Microsoft.Extensions.AI;
    
    using Microsoft.Extensions.Configuration;
    
    using Microsoft.Extensions.Hosting;
    
    using ModelContextProtocol.Client;
    
    
    Java

    Javaμ—μ„œλŠ” 이전 μ‹€μŠ΅μ˜ MCP μ„œλ²„μ— μ—°κ²°ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. Getting Started with MCP Server의 Java Spring Boot ν”„λ‘œμ νŠΈ ꡬ쑰λ₯Ό κ·ΈλŒ€λ‘œ μ‚¬μš©ν•˜λ©°, src/main/java/com/microsoft/mcp/sample/client/ 폴더에 SDKClientλΌλŠ” μƒˆ Java 클래슀λ₯Ό μƒμ„±ν•˜κ³  λ‹€μŒ μž„ν¬νŠΈλ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€:

    
    import java.util.Map;
    
    import org.springframework.web.reactive.function.client.WebClient;
    
    import io.modelcontextprotocol.client.McpClient;
    
    import io.modelcontextprotocol.client.transport.WebFluxSseClientTransport;
    
    import io.modelcontextprotocol.spec.McpClientTransport;
    
    import io.modelcontextprotocol.spec.McpSchema.CallToolRequest;
    
    import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
    
    import io.modelcontextprotocol.spec.McpSchema.ListToolsResult;
    
    
    Rust

    Cargo.toml νŒŒμΌμ— λ‹€μŒ μ˜μ‘΄μ„±μ„ μΆ”κ°€ν•΄μ•Ό ν•©λ‹ˆλ‹€.

    
    [package]
    
    name = "calculator-client"
    
    version = "0.1.0"
    
    edition = "2024"
    
    
    
    [dependencies]
    
    rmcp = { version = "0.5.0", features = ["client", "transport-child-process"] }
    
    serde_json = "1.0.141"
    
    tokio = { version = "1.46.1", features = ["rt-multi-thread"] }
    
    

    κ·Έ ν›„ ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œμ—μ„œ ν•„μš”ν•œ 라이브러리λ₯Ό μž„ν¬νŠΈν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    
    use rmcp::{
    
        RmcpError,
    
        model::CallToolRequestParam,
    
        service::ServiceExt,
    
        transport::{ConfigureCommandExt, TokioChildProcess},
    
    };
    
    use tokio::process::Command;
    
    

    λ‹€μŒμœΌλ‘œ μΈμŠ€ν„΄μŠ€ν™”λ₯Ό ν•΄λ΄…μ‹œλ‹€.

    -2- ν΄λΌμ΄μ–ΈνŠΈ 및 전솑 μΈμŠ€ν„΄μŠ€ν™”

    전솑과 ν΄λΌμ΄μ–ΈνŠΈ μΈμŠ€ν„΄μŠ€λ₯Ό 생성해야 ν•©λ‹ˆλ‹€:

    TypeScript
    
    const transport = new StdioClientTransport({
    
      command: "node",
    
      args: ["server.js"]
    
    });
    
    
    
    const client = new Client(
    
      {
    
        name: "example-client",
    
        version: "1.0.0"
    
      }
    
    );
    
    
    
    await client.connect(transport);
    
    

    μœ„ μ½”λ“œμ—μ„œλŠ”:

  • stdio 전솑 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν–ˆμŠ΅λ‹ˆλ‹€. λͺ…λ Ήκ³Ό 인자(argument)λ₯Ό μ§€μ •ν•΄ μ„œλ²„λ₯Ό μ°Ύκ³  μ‹œμž‘ν•˜λŠ” 방법을 μ •μ˜ν–ˆλŠ”λ°, ν΄λΌμ΄μ–ΈνŠΈλ₯Ό λ§Œλ“€ λ•Œ ν•„μš”ν•œ λΆ€λΆ„μž…λ‹ˆλ‹€.
  • ```typescript

    const transport = new StdioClientTransport({

    command: "node",

    args: ["server.js"]

    });

    ```

  • 이름과 버전을 μ§€μ •ν•΄ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μΈμŠ€ν„΄μŠ€ν™” ν–ˆμŠ΅λ‹ˆλ‹€.
  • ```typescript

    const client = new Client(

    {

    name: "example-client",

    version: "1.0.0"

    });

    ```

  • ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μ„ νƒν•œ 전솑 방식에 μ—°κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
  • ```typescript

    await client.connect(transport);

    ```

    Python
    
    from mcp import ClientSession, StdioServerParameters, types
    
    from mcp.client.stdio import stdio_client
    
    
    
    # stdio 연결을 μœ„ν•œ μ„œλ²„ λ§€κ°œλ³€μˆ˜ 생성
    
    server_params = StdioServerParameters(
    
        command="mcp",  # μ‹€ν–‰ 파일
    
        args=["run", "server.py"],  # 선택적 λͺ…령쀄 인수
    
        env=None,  # 선택적 ν™˜κ²½ λ³€μˆ˜
    
    )
    
    
    
    async def run():
    
        async with stdio_client(server_params) as (read, write):
    
            async with ClientSession(
    
                read, write
    
            ) as session:
    
                # μ—°κ²° μ΄ˆκΈ°ν™”
    
                await session.initialize()
    
    
    
              
    
    
    
    if __name__ == "__main__":
    
        import asyncio
    
    
    
        asyncio.run(run())
    
    

    μœ„ μ½”λ“œμ—μ„œλŠ”:

  • ν•„μˆ˜ 라이브러리λ₯Ό μž„ν¬νŠΈν–ˆμŠ΅λ‹ˆλ‹€.
  • μ„œλ²„ 싀행을 μœ„ν•œ λ§€κ°œλ³€μˆ˜ 객체λ₯Ό μƒμ„±ν–ˆμœΌλ©°, 이λ₯Ό μ‚¬μš©ν•΄ ν΄λΌμ΄μ–ΈνŠΈκ°€ μ—°κ²°ν•  μ„œλ²„λ₯Ό κ΅¬λ™ν•©λ‹ˆλ‹€.
  • stdio_clientλ₯Ό ν˜ΈμΆœν•˜λŠ” run 비동기 λ©”μ„œλ“œλ₯Ό μ •μ˜ν–ˆμŠ΅λ‹ˆλ‹€.
  • asyncio.run에 run λ©”μ„œλ“œλ₯Ό μ „λ‹¬ν•˜μ—¬ μ§„μž…μ μ„ λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€.
  • .NET
    
    using Microsoft.Extensions.AI;
    
    using Microsoft.Extensions.Configuration;
    
    using Microsoft.Extensions.Hosting;
    
    using ModelContextProtocol.Client;
    
    
    
    var builder = Host.CreateApplicationBuilder(args);
    
    
    
    builder.Configuration
    
        .AddEnvironmentVariables()
    
        .AddUserSecrets<Program>();
    
    
    
    
    
    
    
    var clientTransport = new StdioClientTransport(new()
    
    {
    
        Name = "Demo Server",
    
        Command = "dotnet",
    
        Arguments = ["run", "--project", "path/to/file.csproj"],
    
    });
    
    
    
    await using var mcpClient = await McpClient.CreateAsync(clientTransport);
    
    

    μœ„ μ½”λ“œμ—μ„œλŠ”:

  • 라이브러리λ₯Ό μž„ν¬νŠΈν–ˆμŠ΅λ‹ˆλ‹€.
  • stdio 전솑을 μƒμ„±ν•˜κ³  mcpClientλΌλŠ” ν΄λΌμ΄μ–ΈνŠΈλ₯Ό λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 MCP μ„œλ²„μ˜ κΈ°λŠ₯을 λ‚˜μ—΄ 및 ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 참고둜, Argumentsμ—λŠ” *.csproj* νŒŒμΌμ΄λ‚˜ μ‹€ν–‰ 파일 경둜λ₯Ό μ§€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    Java
    
    public class SDKClient {
    
        
    
        public static void main(String[] args) {
    
            var transport = new WebFluxSseClientTransport(WebClient.builder().baseUrl("http://localhost:8080"));
    
            new SDKClient(transport).run();
    
        }
    
        
    
        private final McpClientTransport transport;
    
    
    
        public SDKClient(McpClientTransport transport) {
    
            this.transport = transport;
    
        }
    
    
    
        public void run() {
    
            var client = McpClient.sync(this.transport).build();
    
            client.initialize();
    
            
    
            // ν΄λΌμ΄μ–ΈνŠΈ λ‘œμ§μ€ 여기에 μž‘μ„±ν•˜μ„Έμš”
    
        }
    
    }
    
    

    μœ„ μ½”λ“œμ—μ„œλŠ”:

  • MCP μ„œλ²„κ°€ μ‹€ν–‰ 쀑일 http://localhost:8080λ₯Ό κ°€λ¦¬ν‚€λŠ” SSE 전솑을 μ„€μ •ν•˜λŠ” main λ©”μ„œλ“œλ₯Ό λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€.
  • μƒμ„±μž λ§€κ°œλ³€μˆ˜λ‘œ 전솑을 λ°›λŠ” ν΄λΌμ΄μ–ΈνŠΈ 클래슀λ₯Ό λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€.
  • run λ©”μ„œλ“œμ—μ„œ 전솑을 μ‚¬μš©ν•΄ 동기 MCP ν΄λΌμ΄μ–ΈνŠΈλ₯Ό λ§Œλ“€κ³  연결을 μ΄ˆκΈ°ν™”ν–ˆμŠ΅λ‹ˆλ‹€.
  • Java Spring Boot MCP μ„œλ²„μ™€μ˜ HTTP 기반 톡신에 μ ν•©ν•œ SSE(Server-Sent Events) 전솑을 μ‚¬μš©ν–ˆμŠ΅λ‹ˆλ‹€.
  • Rust

    이 Rust ν΄λΌμ΄μ–ΈνŠΈλŠ” μ„œλ²„κ°€ 같은 디렉터리 λ‚΄ "calculator-server"λΌλŠ” ν˜•μ œ ν”„λ‘œμ νŠΈλΌκ³  κ°€μ •ν•©λ‹ˆλ‹€. μ•„λž˜ μ½”λ“œλŠ” μ„œλ²„λ₯Ό μ‹œμž‘ν•˜κ³  μ—°κ²°ν•©λ‹ˆλ‹€.

    
    async fn main() -> Result<(), RmcpError> {
    
        // μ„œλ²„κ°€ 같은 디렉토리에 μžˆλŠ” ν˜•μ œ ν”„λ‘œμ νŠΈμΈ "calculator-server"라고 κ°€μ •ν•©λ‹ˆλ‹€
    
        let server_dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
    
            .parent()
    
            .expect("failed to locate workspace root")
    
            .join("calculator-server");
    
    
    
        let client = ()
    
            .serve(
    
                TokioChildProcess::new(Command::new("cargo").configure(|cmd| {
    
                    cmd.arg("run").current_dir(server_dir);
    
                }))
    
                .map_err(RmcpError::transport_creation::<TokioChildProcess>)?,
    
            )
    
            .await?;
    
    
    
        // ν•  일: μ΄ˆκΈ°ν™”
    
    
    
        // ν•  일: 도ꡬ λͺ©λ‘ μž‘μ„±
    
    
    
        // ν•  일: 인수 = {"a": 3, "b": 2}둜 add 도ꡬ 호좜
    
    
    
        client.cancel().await?;
    
        Ok(())
    
    }
    
    

    -3- μ„œλ²„ κΈ°λŠ₯ λ‚˜μ—΄ν•˜κΈ°

    ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ˜λ©΄ ν΄λΌμ΄μ–ΈνŠΈκ°€ μ„œλ²„μ— μ—°κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ„œλ²„μ˜ κΈ°λŠ₯을 λ‚˜μ—΄ν•˜μ§€λŠ” μ•ŠμœΌλ―€λ‘œ, 이λ₯Ό ν•΄λ΄…μ‹œλ‹€:

    TypeScript
    
    // ν”„λ‘¬ν”„νŠΈ λͺ©λ‘
    
    const prompts = await client.listPrompts();
    
    
    
    // λ¦¬μ†ŒμŠ€ λͺ©λ‘
    
    const resources = await client.listResources();
    
    
    
    // 도ꡬ λͺ©λ‘
    
    const tools = await client.listTools();
    
    
    Python
    
    # μ‚¬μš© κ°€λŠ₯ν•œ λ¦¬μ†ŒμŠ€ λ‚˜μ—΄
    
    resources = await session.list_resources()
    
    print("LISTING RESOURCES")
    
    for resource in resources:
    
        print("Resource: ", resource)
    
    
    
    # μ‚¬μš© κ°€λŠ₯ν•œ 도ꡬ λ‚˜μ—΄
    
    tools = await session.list_tools()
    
    print("LISTING TOOLS")
    
    for tool in tools.tools:
    
        print("Tool: ", tool.name)
    
    

    μ—¬κΈ°μ„œλŠ” μ‚¬μš© κ°€λŠ₯ν•œ λ¦¬μ†ŒμŠ€ list_resources()와 도ꡬ list_toolsλ₯Ό λ‚˜μ—΄ν•˜κ³  좜λ ₯ν•©λ‹ˆλ‹€.

    .NET
    
    foreach (var tool in await client.ListToolsAsync())
    
    {
    
        Console.WriteLine($"{tool.Name} ({tool.Description})");
    
    }
    
    

    μœ„ μ½”λ“œλŠ” μ„œλ²„μ˜ 도ꡬλ₯Ό λ‚˜μ—΄ν•˜λŠ” μ˜ˆμ œμž…λ‹ˆλ‹€. 도ꡬ 각각의 이름을 좜λ ₯ν•©λ‹ˆλ‹€.

    Java
    
    // 도ꡬ λ‚˜μ—΄ 및 μ‹œμ—°
    
    ListToolsResult toolsList = client.listTools();
    
    System.out.println("Available Tools = " + toolsList);
    
    
    
    // μ—°κ²° 확인을 μœ„ν•΄ μ„œλ²„μ— 핑을 보낼 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€
    
    client.ping();
    
    

    μœ„ μ½”λ“œμ—μ„œλŠ”:

  • listTools()λ₯Ό ν˜ΈμΆœν•΄ MCP μ„œλ²„μ˜ λͺ¨λ“  도ꡬλ₯Ό κ°€μ Έμ™”μŠ΅λ‹ˆλ‹€.
  • ping()으둜 μ„œλ²„ μ—°κ²° μƒνƒœ 확인을 ν–ˆμŠ΅λ‹ˆλ‹€.
  • ListToolsResultμ—λŠ” 도ꡬ 이름, μ„€λͺ…, μž…λ ₯ μŠ€ν‚€λ§ˆ λ“±μ˜ 정보가 ν¬ν•¨λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.
  • μ’‹μŠ΅λ‹ˆλ‹€. 이제 λͺ¨λ“  κΈ°λŠ₯을 κ°€μ Έμ™”μŠ΅λ‹ˆλ‹€. 그럼 μ–Έμ œ 이 κΈ°λŠ₯듀을 μ‚¬μš©ν•˜λŠ” κ±ΈκΉŒμš”? 이 ν΄λΌμ΄μ–ΈνŠΈλŠ” κ°„λ‹¨ν•΄μ„œ, κΈ°λŠ₯을 μ‚¬μš©ν•˜λ €λ©΄ λͺ…μ‹œμ μœΌλ‘œ ν˜ΈμΆœν•΄μ•Ό ν•©λ‹ˆλ‹€. λ‹€μŒ μž₯μ—μ„œλŠ” 자체 λŒ€ν˜• μ–Έμ–΄ λͺ¨λΈ(LLM)에 μ ‘κ·Όν•  수 μžˆλŠ” 더 μ§„λ³΄λœ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό λ§Œλ“€ κ²ƒμž…λ‹ˆλ‹€. μ§€κΈˆμ€ μ„œλ²„ κΈ°λŠ₯을 ν˜ΈμΆœν•˜λŠ” 법을 μ‚΄νŽ΄λ΄…μ‹œλ‹€.

    Rust

    main ν•¨μˆ˜μ—μ„œ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μ΄ˆκΈ°ν™”ν•œ ν›„ μ„œλ²„λ₯Ό μ΄ˆκΈ°ν™”ν•˜κ³  λͺ‡ κ°€μ§€ κΈ°λŠ₯을 λ‚˜μ—΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    
    // μ΄ˆκΈ°ν™”
    
    let server_info = client.peer_info();
    
    println!("Server info: {:?}", server_info);
    
    
    
    // 도ꡬ λͺ©λ‘
    
    let tools = client.list_tools(Default::default()).await?;
    
    println!("Available tools: {:?}", tools);
    
    

    -4- κΈ°λŠ₯ ν˜ΈμΆœν•˜κΈ°

    κΈ°λŠ₯을 ν˜ΈμΆœν•˜λ €λ©΄ μ˜¬λ°”λ₯Έ μΈμžμ™€, κ²½μš°μ— 따라 ν˜ΈμΆœν•˜λ €λŠ” 이름을 μ§€μ •ν•΄μ•Ό ν•©λ‹ˆλ‹€.

    TypeScript
    
    
    
    // λ¦¬μ†ŒμŠ€λ₯Ό μ½μŠ΅λ‹ˆλ‹€
    
    const resource = await client.readResource({
    
      uri: "file:///example.txt"
    
    });
    
    
    
    // 도ꡬλ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€
    
    const result = await client.callTool({
    
      name: "example-tool",
    
      arguments: {
    
        arg1: "value"
    
      }
    
    });
    
    
    
    // ν”„λ‘¬ν”„νŠΈ 호좜
    
    const promptResult = await client.getPrompt({
    
        name: "review-code",
    
        arguments: {
    
            code: "console.log(\"Hello world\")"
    
        }
    
    })
    
    

    μœ„ μ½”λ“œμ—μ„œλŠ”:

  • λ¦¬μ†ŒμŠ€λ₯Ό λΆˆλŸ¬μ˜΅λ‹ˆλ‹€. readResource()λ₯Ό ν˜ΈμΆœν•˜κ³  uriλ₯Ό μ§€μ •ν•©λ‹ˆλ‹€. μ„œλ²„ μΈ‘ μ½”λ“œλŠ” λ‹€μŒκ³Ό μœ μ‚¬ν•©λ‹ˆλ‹€:
  • ```typescript

    server.resource(

    "readFile",

    new ResourceTemplate("file://{name}", { list: undefined }),

    async (uri, { name }) => ({

    contents: [{

    uri: uri.href,

    text: Hello, ${name}!

    }]

    })

    );

    ```

    uriκ°’ file://example.txtλŠ” μ„œλ²„μ˜ file://{name}에 λ§€ν•‘λ˜λ©°, example.txtλŠ” name으둜 μ²˜λ¦¬λ©λ‹ˆλ‹€.

  • 도ꡬ 호좜: 도ꡬ 이름(name)κ³Ό 인자(arguments)λ₯Ό μ§€μ •ν•˜μ—¬ ν˜ΈμΆœν•©λ‹ˆλ‹€:
  • ```typescript

    const result = await client.callTool({

    name: "example-tool",

    arguments: {

    arg1: "value"

    }

    });

    ```

  • ν”„λ‘¬ν”„νŠΈ 호좜: getPrompt()λ₯Ό 이름과 μΈμžμ™€ ν•¨κ»˜ ν˜ΈμΆœν•©λ‹ˆλ‹€. μ„œλ²„ μ½”λ“œλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:
  • ```typescript

    server.prompt(

    "review-code",

    { code: z.string() },

    ({ code }) => ({

    messages: [{

    role: "user",

    content: {

    type: "text",

    text: Please review this code:\n\n${code}

    }

    }]

    })

    );

    ```

    λ”°λΌμ„œ ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œλŠ” μ„œλ²„ μ„ μ–Έκ³Ό μΌμΉ˜ν•˜λ„λ‘ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

    ```typescript

    const promptResult = await client.getPrompt({

    name: "review-code",

    arguments: {

    code: "console.log(\"Hello world\")"

    }

    })

    ```

    Python
    
    # λ¦¬μ†ŒμŠ€λ₯Ό μ½μŠ΅λ‹ˆλ‹€
    
    print("READING RESOURCE")
    
    content, mime_type = await session.read_resource("greeting://hello")
    
    
    
    # 도ꡬλ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€
    
    print("CALL TOOL")
    
    result = await session.call_tool("add", arguments={"a": 1, "b": 7})
    
    print(result.content)
    
    

    μœ„ μ½”λ“œμ—μ„œ:

  • greeting λ¦¬μ†ŒμŠ€λ₯Ό read_resource둜 ν˜ΈμΆœν–ˆμŠ΅λ‹ˆλ‹€.
  • add 도ꡬλ₯Ό call_tool둜 ν˜ΈμΆœν–ˆμŠ΅λ‹ˆλ‹€.
  • .NET

    1. 도ꡬλ₯Ό ν˜ΈμΆœν•˜λŠ” μ½”λ“œλ₯Ό μΆ”κ°€ν•©μ‹œλ‹€:

    ```csharp

    var result = await mcpClient.CallToolAsync(

    "Add",

    new Dictionary() { ["a"] = 1, ["b"] = 3 },

    cancellationToken:CancellationToken.None);

    ```

    2. κ²°κ³Όλ₯Ό 좜λ ₯ν•˜λŠ” μ½”λ“œλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

    ```csharp

    Console.WriteLine(result.Content.First(c => c.Type == "text").Text);

    // Sum 4

    ```

    Java
    
    // λ‹€μ–‘ν•œ 계산기 도ꡬ 호좜
    
    CallToolResult resultAdd = client.callTool(new CallToolRequest("add", Map.of("a", 5.0, "b", 3.0)));
    
    System.out.println("Add Result = " + resultAdd);
    
    
    
    CallToolResult resultSubtract = client.callTool(new CallToolRequest("subtract", Map.of("a", 10.0, "b", 4.0)));
    
    System.out.println("Subtract Result = " + resultSubtract);
    
    
    
    CallToolResult resultMultiply = client.callTool(new CallToolRequest("multiply", Map.of("a", 6.0, "b", 7.0)));
    
    System.out.println("Multiply Result = " + resultMultiply);
    
    
    
    CallToolResult resultDivide = client.callTool(new CallToolRequest("divide", Map.of("a", 20.0, "b", 4.0)));
    
    System.out.println("Divide Result = " + resultDivide);
    
    
    
    CallToolResult resultHelp = client.callTool(new CallToolRequest("help", Map.of()));
    
    System.out.println("Help = " + resultHelp);
    
    

    μœ„ μ½”λ“œμ—μ„œλŠ”:

  • μ—¬λŸ¬ 계산 도ꡬλ₯Ό callTool() λ©”μ„œλ“œμ™€ CallToolRequest 객체둜 ν˜ΈμΆœν–ˆμŠ΅λ‹ˆλ‹€.
  • 도ꡬ 호좜 μ‹œ 이름과 도ꡬ별 ν•„μš” 인자λ₯Ό Map으둜 μ „λ‹¬ν–ˆμŠ΅λ‹ˆλ‹€.
  • μ„œλ²„ λ„κ΅¬λŠ” μˆ˜ν•™ μ—°μ‚° 등을 μœ„ν•΄ β€œa”, β€œb” 같은 νŠΉμ • λ§€κ°œλ³€μˆ˜ 이름을 κΈ°λŒ€ν•©λ‹ˆλ‹€.
  • κ²°κ³ΌλŠ” μ„œλ²„ 응닡을 ν¬ν•¨ν•˜λŠ” CallToolResult 객체둜 λ°˜ν™˜λ©λ‹ˆλ‹€.
  • Rust
    
    // 인수 = {"a": 3, "b": 2}둜 add 도ꡬλ₯Ό ν˜ΈμΆœν•˜μ‹­μ‹œμ˜€
    
    let a = 3;
    
    let b = 2;
    
    let tool_result = client
    
        .call_tool(CallToolRequestParam {
    
            name: "add".into(),
    
            arguments: serde_json::json!({ "a": a, "b": b }).as_object().cloned(),
    
        })
    
        .await?;
    
    println!("Result of {:?} + {:?}: {:?}", a, b, tool_result);
    
    

    -5- ν΄λΌμ΄μ–ΈνŠΈ μ‹€ν–‰ν•˜κΈ°

    ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μ‹€ν–‰ν•˜λ €λ©΄ ν„°λ―Έλ„μ—μ„œ λ‹€μŒ λͺ…λ Ήμ–΄λ₯Ό μž…λ ₯ν•˜μ„Έμš”:

    TypeScript

    *package.json*의 "scripts" μ„Ήμ…˜μ— λ‹€μŒ ν•­λͺ©μ„ μΆ”κ°€ν•©λ‹ˆλ‹€:

    
    "client": "tsc && node build/client.js"
    
    
    
    npm run client
    
    
    Python

    λ‹€μŒ λͺ…λ Ήμ–΄λ‘œ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€:

    
    python client.py
    
    
    .NET
    
    dotnet run
    
    
    Java

    λ¨Όμ € MCP μ„œλ²„κ°€ http://localhost:8080μ—μ„œ μ‹€ν–‰ 쀑인지 ν™•μΈν•˜μ„Έμš”. 그러고 λ‚˜μ„œ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μ‹€ν–‰ν•©λ‹ˆλ‹€:

    
    # ν”„λ‘œμ νŠΈλ₯Ό λΉŒλ“œν•˜μ„Έμš”
    
    ./mvnw clean compile
    
    
    
    # ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μ‹€ν–‰ν•˜μ„Έμš”
    
    ./mvnw exec:java -Dexec.mainClass="com.microsoft.mcp.sample.client.SDKClient"
    
    

    λ˜λŠ” μ†”λ£¨μ…˜ 폴더 03-GettingStarted\02-client\solution\java에 제곡된 μ™„μ„±λœ ν΄λΌμ΄μ–ΈνŠΈ ν”„λ‘œμ νŠΈλ₯Ό μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

    
    # μ†”λ£¨μ…˜ λ””λ ‰ν† λ¦¬λ‘œ 이동
    
    cd 03-GettingStarted/02-client/solution/java
    
    
    
    # JAR을 λΉŒλ“œν•˜κ³  μ‹€ν–‰
    
    ./mvnw clean package
    
    java -jar target/calculator-client-0.0.1-SNAPSHOT.jar
    
    
    Rust
    
    cargo fmt
    
    cargo run
    
    

    과제

    이번 κ³Όμ œμ—μ„œλŠ” 배운 λ‚΄μš©μ„ ν™œμš©ν•΄ 직접 ν΄λΌμ΄μ–ΈνŠΈλ₯Ό λ§Œλ“€μ–΄ λ΄…λ‹ˆλ‹€.

    μ•„λž˜ μ„œλ²„λ₯Ό ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œλ‘œ ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ„œλ²„μ— 더 ν₯미둜운 κΈ°λŠ₯을 μΆ”κ°€ν•΄ λ³΄μ„Έμš”.

    TypeScript

    
    import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
    
    import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
    
    import { z } from "zod";
    
    
    
    // MCP μ„œλ²„λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€
    
    const server = new McpServer({
    
      name: "Demo",
    
      version: "1.0.0"
    
    });
    
    
    
    // λ§μ…ˆ 도ꡬλ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€
    
    server.tool("add",
    
      { a: z.number(), b: z.number() },
    
      async ({ a, b }) => ({
    
        content: [{ type: "text", text: String(a + b) }]
    
      })
    
    );
    
    
    
    // 동적 인사말 λ¦¬μ†ŒμŠ€λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€
    
    server.resource(
    
      "greeting",
    
      new ResourceTemplate("greeting://{name}", { list: undefined }),
    
      async (uri, { name }) => ({
    
        contents: [{
    
          uri: uri.href,
    
          text: `Hello, ${name}!`
    
        }]
    
      })
    
    );
    
    
    
    // stdinμ—μ„œ λ©”μ‹œμ§€λ₯Ό μˆ˜μ‹ ν•˜κ³  stdout으둜 λ©”μ‹œμ§€λ₯Ό μ „μ†‘ν•˜κΈ° μ‹œμž‘ν•©λ‹ˆλ‹€
    
    
    
    async function main() {
    
      const transport = new StdioServerTransport();
    
      await server.connect(transport);
    
      console.error("MCPServer started on stdin/stdout");
    
    }
    
    
    
    main().catch((error) => {
    
      console.error("Fatal error: ", error);
    
      process.exit(1);
    
    });
    
    

    Python

    
    # server.py
    
    from mcp.server.fastmcp import FastMCP
    
    
    
    # MCP μ„œλ²„ 생성
    
    mcp = FastMCP("Demo")
    
    
    
    
    
    # μΆ”κ°€ 도ꡬ μΆ”κ°€
    
    @mcp.tool()
    
    def add(a: int, b: int) -> int:
    
        """Add two numbers"""
    
        return a + b
    
    
    
    
    
    # 동적 인사말 λ¦¬μ†ŒμŠ€ μΆ”κ°€
    
    @mcp.resource("greeting://{name}")
    
    def get_greeting(name: str) -> str:
    
        """Get a personalized greeting"""
    
        return f"Hello, {name}!"
    
    
    
    

    .NET

    
    using Microsoft.Extensions.DependencyInjection;
    
    using Microsoft.Extensions.Hosting;
    
    using Microsoft.Extensions.Logging;
    
    using ModelContextProtocol.Server;
    
    using System.ComponentModel;
    
    
    
    var builder = Host.CreateApplicationBuilder(args);
    
    builder.Logging.AddConsole(consoleLogOptions =>
    
    {
    
        // Configure all logs to go to stderr
    
        consoleLogOptions.LogToStandardErrorThreshold = LogLevel.Trace;
    
    });
    
    
    
    builder.Services
    
        .AddMcpServer()
    
        .WithStdioServerTransport()
    
        .WithToolsFromAssembly();
    
    await builder.Build().RunAsync();
    
    
    
    [McpServerToolType]
    
    public static class CalculatorTool
    
    {
    
        [McpServerTool, Description("Adds two numbers")]
    
        public static string Add(int a, int b) => $"Sum {a + b}";
    
    }
    
    

    이 ν”„λ‘œμ νŠΈμ—μ„œ ν”„λ‘¬ν”„νŠΈμ™€ λ¦¬μ†ŒμŠ€ μΆ”κ°€ 방법을 μ°Έμ‘°ν•˜μ„Έμš”.

    λ˜ν•œ, ν”„λ‘¬ν”„νŠΈμ™€ λ¦¬μ†ŒμŠ€ 호좜 방법도 ν™•μΈν•˜μ„Έμš”.

    Rust

    이전 μ„Ήμ…˜(../01-first-server)μ—μ„œ Rust둜 κ°„λ‹¨ν•œ MCP μ„œλ²„λ₯Ό λ§Œλ“œλŠ” 방법을 λ°°μ› μŠ΅λ‹ˆλ‹€.

    κ·Έ μ½”λ“œλ₯Ό ν™•μž₯ν•˜κ±°λ‚˜ λ‹€μŒ λ§ν¬μ—μ„œ 더 λ§Žμ€ Rust 기반 MCP μ„œλ²„ 예제λ₯Ό ν™•μΈν•˜μ„Έμš”: MCP Server Examples

    μ†”λ£¨μ…˜

    μ†”λ£¨μ…˜ ν΄λ”μ—λŠ” λ³Έ νŠœν† λ¦¬μ–Όμ—μ„œ 닀룬 κ°œλ…λ“€μ„ λͺ¨λ‘ ν¬ν•¨ν•œ, μ‹€ν–‰ κ°€λŠ₯ν•œ μ™„μ „ν•œ ν΄λΌμ΄μ–ΈνŠΈ κ΅¬ν˜„ μ˜ˆμ œκ°€ λ“€μ–΄ μžˆμŠ΅λ‹ˆλ‹€. 각 μ†”λ£¨μ…˜μ€ ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„œλ²„ μ½”λ“œλ₯Ό λ³„λ„μ˜ λ…λ¦½ν˜• ν”„λ‘œμ νŠΈλ‘œ μ •λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€.

    πŸ“ μ†”λ£¨μ…˜ ꡬ쑰

    μ†”λ£¨μ…˜ λ””λ ‰ν„°λ¦¬λŠ” ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄λ³„λ‘œ κ΅¬μ„±λ©λ‹ˆλ‹€:

    
    solution/
    
    β”œβ”€β”€ typescript/          # TypeScript client with npm/Node.js setup
    
    β”‚   β”œβ”€β”€ package.json     # Dependencies and scripts
    
    β”‚   β”œβ”€β”€ tsconfig.json    # TypeScript configuration
    
    β”‚   └── src/             # Source code
    
    β”œβ”€β”€ java/                # Java Spring Boot client project
    
    β”‚   β”œβ”€β”€ pom.xml          # Maven configuration
    
    β”‚   β”œβ”€β”€ src/             # Java source files
    
    β”‚   └── mvnw             # Maven wrapper
    
    β”œβ”€β”€ python/              # Python client implementation
    
    β”‚   β”œβ”€β”€ client.py        # Main client code
    
    β”‚   β”œβ”€β”€ server.py        # Compatible server
    
    β”‚   └── README.md        # Python-specific instructions
    
    β”œβ”€β”€ dotnet/              # .NET client project
    
    β”‚   β”œβ”€β”€ dotnet.csproj    # Project configuration
    
    β”‚   β”œβ”€β”€ Program.cs       # Main client code
    
    β”‚   └── dotnet.sln       # Solution file
    
    β”œβ”€β”€ rust/                # Rust client implementation
    
    |  β”œβ”€β”€ Cargo.lock        # Cargo lock file
    
    |  β”œβ”€β”€ Cargo.toml        # Project configuration and dependencies
    
    |  β”œβ”€β”€ src               # Source code
    
    |  β”‚   └── main.rs       # Main client code
    
    └── server/              # Additional .NET server implementation
    
        β”œβ”€β”€ Program.cs       # Server code
    
        └── server.csproj    # Server project file
    
    

    πŸš€ 각 μ†”λ£¨μ…˜μ— ν¬ν•¨λœ λ‚΄μš©

    각 언어별 μ†”λ£¨μ…˜μ—λŠ” λ‹€μŒμ΄ ν¬ν•¨λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€:

  • νŠœν† λ¦¬μ–Όμ˜ λͺ¨λ“  κΈ°λŠ₯을 ν¬ν•¨ν•œ μ™„μ „ν•œ ν΄λΌμ΄μ–ΈνŠΈ κ΅¬ν˜„
  • μ μ ˆν•œ μ˜μ‘΄μ„±κ³Ό ꡬ성 파일이 ν¬ν•¨λœ μž‘λ™ κ°€λŠ₯ν•œ ν”„λ‘œμ νŠΈ ꡬ쑰
  • μ†μ‰¬μš΄ μ„€μ •κ³Ό 싀행을 μœ„ν•œ λΉŒλ“œ 및 μ‹€ν–‰ 슀크립트
  • 언어별 μ•ˆλ‚΄κ°€ μžˆλŠ” 상세 README
  • μ—λŸ¬ 처리 및 κ²°κ³Ό 처리 예제
  • πŸ“– μ†”λ£¨μ…˜ μ‚¬μš©λ²•

    1. μ„ ν˜Έν•˜λŠ” μ–Έμ–΄ ν΄λ”λ‘œ μ΄λ™ν•©λ‹ˆλ‹€:

    ```bash

    cd solution/typescript/ # TypeScript 용

    cd solution/java/ # Java 용

    cd solution/python/ # Python 용

    cd solution/dotnet/ # .NET 용

    ```

    2. 각 폴더 λ‚΄ README 지침에 따라:

    - μ˜μ‘΄μ„± μ„€μΉ˜

    - ν”„λ‘œμ νŠΈ λΉŒλ“œ

    - ν΄λΌμ΄μ–ΈνŠΈ μ‹€ν–‰

    3. μ˜ˆμƒ 좜λ ₯ μ˜ˆμ‹œ:

    ```text

    Prompt: Please review this code: console.log("hello");

    Resource template: file

    Tool result: { content: [ { type: 'text', text: '9' } ] }

    ```

    μžμ„Έν•œ λ¬Έμ„œμ™€ 단계별 μ•ˆλ‚΄λŠ” λ‹€μŒμ„ μ°Έμ‘°ν•˜μ„Έμš”: πŸ“– μ†”λ£¨μ…˜ λ¬Έμ„œ

    🎯 μ™„μ„±λœ 예제

    νŠœν† λ¦¬μ–Όμ—μ„œ 닀룬 λͺ¨λ“  ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μš© μ™„μ„±λœ ν΄λΌμ΄μ–ΈνŠΈ κ΅¬ν˜„ 예제λ₯Ό μ œκ³΅ν–ˆμŠ΅λ‹ˆλ‹€. 이 μ˜ˆμ œλ“€μ€ μœ„μ—μ„œ μ„€λͺ…ν•œ 전체 κΈ°λŠ₯을 κ΅¬ν˜„ν•˜λ©° μ°Έκ³  λ˜λŠ” μžμ‹ λ§Œμ˜ ν”„λ‘œμ νŠΈ μ‹œμž‘μ μœΌλ‘œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    μ‚¬μš© κ°€λŠ₯ μ™„μ„± 예제

    | μ–Έμ–΄ | 파일 | μ„€λͺ… |

    |--------|-----------------------------|-----------------------------------------------------------|

    | Java | [client_example_java.java](../../../../03-GettingStarted/02-client/client_example_java.java) | SSE 전솑을 μ‚¬μš©ν•˜λŠ” μ™„μ „ν•œ Java ν΄λΌμ΄μ–ΈνŠΈλ‘œ 포괄적 μ—λŸ¬ 처리 포함 |

    | C# | [client_example_csharp.cs](../../../../03-GettingStarted/02-client/client_example_csharp.cs) | stdio 전솑 및 μžλ™ μ„œλ²„ μ‹œμž‘ κΈ°λŠ₯을 κ°–μΆ˜ μ™„μ „ν•œ C# ν΄λΌμ΄μ–ΈνŠΈ |

    | TypeScript | [client_example_typescript.ts](../../../../03-GettingStarted/02-client/client_example_typescript.ts) | μ™„λ²½ν•œ MCP ν”„λ‘œν† μ½œ 지원을 μ œκ³΅ν•˜λŠ” μ™„μ „ν•œ TypeScript ν΄λΌμ΄μ–ΈνŠΈ |

    | Python | [client_example_python.py](../../../../03-GettingStarted/02-client/client_example_python.py) | async/await νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λŠ” μ™„μ „ν•œ Python ν΄λΌμ΄μ–ΈνŠΈ |

    | Rust | [client_example_rust.rs](../../../../03-GettingStarted/02-client/client_example_rust.rs) | Tokio 기반 비동기 μž‘μ—…μ„ μ§€μ›ν•˜λŠ” μ™„μ „ν•œ Rust ν΄λΌμ΄μ–ΈνŠΈ |

    각 μ™„μ„± μ˜ˆμ œμ—λŠ”:

  • βœ… μ—°κ²° μ„€μ • 및 였λ₯˜ 처리
  • βœ… μ„œλ²„ 검색 (도ꡬ, λ¦¬μ†ŒμŠ€, ν”„λ‘¬ν”„νŠΈ 포함 μ‹œ)
  • βœ… 계산기 μž‘μ—… (λ”ν•˜κΈ°, λΉΌκΈ°, κ³±ν•˜κΈ°, λ‚˜λˆ„κΈ°, 도움말)
  • βœ… κ²°κ³Ό 처리 및 포맷된 좜λ ₯
  • βœ… 포괄적인 였λ₯˜ 처리
  • βœ… λͺ…ν™•ν•˜κ³  λ¬Έμ„œν™”λœ μ½”λ“œμ™€ 단계별 주석
  • μ™„μ „ν•œ 예제 μ‹œμž‘ν•˜κΈ°

    1. μœ„ ν‘œμ—μ„œ μ„ ν˜Έν•˜λŠ” μ–Έμ–΄ 선택

    2. 전체 κ΅¬ν˜„μ„ μ΄ν•΄ν•˜κΈ° μœ„ν•΄ μ™„μ „ν•œ 예제 파일 κ²€ν† 

    3. [complete_examples.md](./complete_examples.md) μ—μ„œ 지침에 따라 예제 μ‹€ν–‰

    4. νŠΉμ • μ‚¬μš© 사둀에 맞게 예제 μˆ˜μ • 및 ν™•μž₯

    μžμ„Έν•œ μ‹€ν–‰ 및 μ‚¬μš©μž μ •μ˜ λ¬Έμ„œλŠ” λ‹€μŒμ„ μ°Έμ‘°ν•˜μ„Έμš”: πŸ“– μ™„μ „ν•œ 예제 λ¬Έμ„œ

    πŸ’‘ μ†”λ£¨μ…˜ vs. μ™„μ „ν•œ 예제

    | μ†”λ£¨μ…˜ 폴더 | μ™„μ „ν•œ 예제 |

    |--------------------------|--------------------------|

    | λΉŒλ“œ νŒŒμΌμ„ ν¬ν•¨ν•œ 전체 ν”„λ‘œμ νŠΈ ꡬ쑰 | 단일 파일 κ΅¬ν˜„ |

    | 쒅속성 포함 μ¦‰μ‹œ μ‹€ν–‰ κ°€λŠ₯ | μ§‘μ€‘λœ μ½”λ“œ 예제 |

    | ν”„λ‘œλ•μ…˜ ν™˜κ²½κ³Ό μœ μ‚¬ν•œ μ„€μ • | ꡐ윑용 μ°Έκ³  자료 |

    | 언어별 툴링 | μ–Έμ–΄ κ°„ 비ꡐ |

    두 접근법 λͺ¨λ‘ μœ μš©ν•©λ‹ˆλ‹€ - 전체 ν”„λ‘œμ νŠΈλŠ” μ†”λ£¨μ…˜ 폴더λ₯Ό, ν•™μŠ΅κ³Ό μ°Έμ‘°λŠ” μ™„μ „ν•œ 예제λ₯Ό μ‚¬μš©ν•˜μ„Έμš”.

    μ£Όμš” λ‚΄μš© μš”μ•½

    이번 μž₯μ—μ„œ ν΄λΌμ΄μ–ΈνŠΈμ— λŒ€ν•œ μ£Όμš” λ‚΄μš©μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

  • μ„œλ²„μ—μ„œ κΈ°λŠ₯을 λ°œκ²¬ν•˜κ³  ν˜ΈμΆœν•˜λŠ” 데 λͺ¨λ‘ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • ν΄λΌμ΄μ–ΈνŠΈκ°€ μžμ‹ μ„ μ‹œμž‘ν•˜λŠ” λ™μ•ˆ μ„œλ²„λ₯Ό μ‹œμž‘ν•  수 있으며(이번 μž₯처럼) μ‹€ν–‰ 쀑인 μ„œλ²„μ— μ—°κ²°ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.
  • 이전 μž₯μ—μ„œ μ„€λͺ…ν•œ Inspector와 같은 λŒ€μ•ˆκ³Ό ν•¨κ»˜ μ„œλ²„ κΈ°λŠ₯을 ν…ŒμŠ€νŠΈν•˜λŠ” 쒋은 λ°©λ²•μž…λ‹ˆλ‹€.
  • μΆ”κ°€ 자료

  • MCPμ—μ„œ ν΄λΌμ΄μ–ΈνŠΈ κ΅¬μΆ•ν•˜κΈ°
  • μƒ˜ν”Œ

  • Java 계산기
  • .Net 계산기
  • JavaScript 계산기
  • TypeScript 계산기
  • Python 계산기
  • Rust 계산기
  • λ‹€μŒ λ‚΄μš©

  • λ‹€μŒ: LLM을 μ‚¬μš©ν•œ ν΄λΌμ΄μ–ΈνŠΈ λ§Œλ“€κΈ°
  • ---

    λ©΄μ±… μ‘°ν•­:

    이 λ¬Έμ„œλŠ” AI λ²ˆμ—­ μ„œλΉ„μŠ€ Co-op Translatorλ₯Ό μ‚¬μš©ν•˜μ—¬ λ²ˆμ—­λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

    정확성을 μœ„ν•΄ λ…Έλ ₯ν•˜κ³  μžˆμœΌλ‚˜, μžλ™ λ²ˆμ—­μ—λŠ” 였λ₯˜λ‚˜ λΆ€μ •ν™•ν•œ λ‚΄μš©μ΄ 포함될 수 μžˆμŒμ„ μœ μ˜ν•˜μ‹œκΈ° λ°”λžλ‹ˆλ‹€.

    원문 λ¬Έμ„œκ°€ κΆŒμœ„ μžˆλŠ” 좜처둜 κ°„μ£Όλ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

    μ€‘μš”ν•œ μ •λ³΄μ˜ 경우, 전문적인 인간 λ²ˆμ—­μ„ ꢌμž₯ν•©λ‹ˆλ‹€.

    λ³Έ λ²ˆμ—­ μ‚¬μš©μœΌλ‘œ μΈν•œ μ˜€ν•΄λ‚˜ 잘λͺ»λœ 해석에 λŒ€ν•΄ λ‹Ήμ‚¬λŠ” μ±…μž„μ„ μ§€μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

    MCP Academy — microsoft/mcp-for-beginners