# Euler MCP + Code

You can also make use of `@modelcontextprotocol/sdk/client` in order to interact with the euler mcp server. This particular client provides a convenient way to establish a connection and communicate with the euler mcp server, enabling you to perform various operations and access the services offered by the server.

## Quickstart

1. Install dependencies

```
npm install -y @modelcontextprotocol/sdk dotenv openai tsx
```

2. Edit client.ts and Set an OPENAI\_API\_KEY

````
```typescript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
import dotenv from "dotenv";
import OpenAI from "openai";
dotenv.config();

const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
if (!OPENAI_API_KEY) {
  throw new Error("OPENAI_API_KEY is not set");
}

const OPENAI_BASE_URL = process.env.OPENAI_BASE_URL || "https://api.openai.com/v1";
const MCP_SERVER_URL = process.env.MCP_SERVER_URL || "https://dev.euler.ai/mcp/sse";

function openAiToolAdapter(tool: {
  name: string;
  description?: string;
  input_schema: any;
}) {
  return {
    type: "function",
    function: {
      name: tool.name,
      description: tool.description,
      parameters: {
        type: "object",
        properties: tool.input_schema.properties,
        required: tool.input_schema.required,
      },
    },
  };
}

class MCPClient {
  private mcp: Client;
  private openai: OpenAI;
  private tools: Array<any> = [];
  private transport: Transport | null = null;

  constructor() {
    this.openai = new OpenAI({
      apiKey: OPENAI_API_KEY,
      baseURL: OPENAI_BASE_URL,
    });

    this.mcp = new Client({ name: "mcp-client", version: "1.0.0" });
  }

  async connectToServer(serverUrl: string) {
    try {
      this.transport = new SSEClientTransport(new URL(serverUrl));
      await this.mcp.connect(this.transport);

      const toolsResult = await this.mcp.listTools();
      this.tools = toolsResult.tools.map((tool) => {
        return openAiToolAdapter({
          name: tool.name,
          description: tool.description,
          input_schema: tool.inputSchema,
        });
      });
    } catch (e) {
      console.log("Failed to connect to MCP server: ", e);
      throw e;
    }
  }

  async processQuery(query: string) {
    const messages: any[] = [
      {
        role: "user",
        content: query,
      },
    ];

    // console.log("Tools: ", JSON.stringify(this.tools, null, 2));

    let response = await this.openai.chat.completions.create({
      model: "gpt-3.5-turbo",
      max_tokens: 1000,
      messages,
      tools: this.tools,
    });

    const finalText: string[] = [];
    const toolResults: any[] = [];

    console.log(
      "Response from OpenAI: ",
      JSON.stringify(response, null, 2)
    );

    for (const choice of response.choices) {
      const message = choice.message;
      if (message.tool_calls) {
        toolResults.push(
          await this.callTools(message.tool_calls, toolResults, finalText)
        )
      } else {
        finalText.push(message.content || "xx");
      }
    }

    messages.push({
      "role": "user",
      "content": `Tool Response ${JSON.stringify(toolResults)}`
    })
    messages.push({
      "role": "user",
      "content": `Use the Tool Response to answer the user's question: ${query}`
    })

    response = await this.openai.chat.completions.create({
      model: "gpt-3.5-turbo",
      max_tokens: 1000,
      messages,
    });

    if (response.choices && response.choices.length > 0) {
      finalText.push(
        response.choices[0].message.content || "??"
      );
    }

    return finalText.join("\n");
  }
  async callTools(
    tool_calls: OpenAI.Chat.Completions.ChatCompletionMessageToolCall[],
    toolResults: any[],
    finalText: string[]
  ) {
    for (const tool_call of tool_calls) {
      const toolName = tool_call.function.name;
      const args = tool_call.function.arguments;

      console.log(`Calling tool ${toolName} with args ${JSON.stringify(args)}`);

      const toolResult = await this.mcp.callTool({
        name: toolName,
        arguments: JSON.parse(args),
      });
      toolResults.push({
        name: toolName,
        result: toolResult,
      });
      finalText.push(
        `[Calling tool ${toolName} with args ${JSON.stringify(args)}]`
      );
    }
  }
  async cleanup() {
    await this.mcp.close();
  }
}

const client = new MCPClient();
await client.connectToServer(MCP_SERVER_URL);
console.log("Connected to MCP server");

let query = process.argv[2] || "What is the sum of 2 and 3?";
let result = await client.processQuery(query);
console.log("Final result: ", result);

await client.cleanup();
```
````

3. Run the client.ts

```
 tsx src/client.ts "Check the current ETH balance of vitalik.eth"
 
 
```

{% code overflow="wrap" fullWidth="false" %}
```
Calling tool resolve_ens with args "{\"ensName\":\"vitalik.eth\"}"
Final result:  [Calling tool resolve_ens with args "{\"ensName\":\"vitalik.eth\"}"]
The Tool Response indicates that the resolved address of vitalik.eth is 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045. To check the current ETH balance of this address, it is recommended to use a blockchain explorer or a cryptocurrency wallet that supports querying account balances. You can input this address (0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045) in the search bar of a reliable blockchain explorer such as Etherscan to view the current ETH balance associated with vitalik.eth.
```
{% endcode %}
