diff --git a/README.md b/README.md index 6a04e76..70b4fbd 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,6 @@ # TSMCP + + +## use inspector to test mcp server +https://www.npmjs.com/package/@modelcontextprotocol/inspector \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..1919d69 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "type": "module", + "scripts": { + "inspector": "npx @modelcontextprotocol/inspector tsx src/main.ts" + }, + "dependencies": { + "@modelcontextprotocol/sdk": "^1.8.0", + "zod": "^3.24.2" + }, + "devDependencies": { + "tsx": "^4.19.3" + } +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..fbd3715 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,94 @@ +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) }] + }) +); + +// Adiciona uma ferramenta que se comunica com o Ollama +server.tool("ollama", + { + prompt: z.string(), + model: z.string().default("llama3"), + options: z.object({ + temperature: z.number().min(0).max(2).optional().default(0.7), + max_tokens: z.number().optional().default(500) + }).optional().default({}) + }, + async ({ prompt, model, options }) => { + try { + console.log(`Enviando para Ollama: modelo=${model}, prompt="${prompt.substring(0, 30)}..."`); + + // A API do Ollama espera os parâmetros no corpo da solicitação + // e não dentro de um objeto options separado + const response = await fetch("http://localhost:11434/api/generate", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + model: model, + prompt: prompt, + stream: false, + temperature: options.temperature, + num_predict: options.max_tokens + // Remova o objeto options aninhado + }), + }); + + if (!response.ok) { + const error = await response.text(); + console.error(`Erro na resposta do Ollama: ${error}`); + return { + content: [{ type: "text", text: `Erro ao chamar Ollama: ${error}` }] + }; + } + + const data = await response.json(); + console.log("Resposta recebida do Ollama"); + + if (!data.response) { + console.error("Formato de resposta inesperado:", data); + return { + content: [{ type: "text", text: `Erro: formato de resposta inesperado do Ollama` }] + }; + } + + return { + content: [{ type: "text", text: data.response }] + }; + } catch (error) { + console.error(`Erro na comunicação com Ollama:`, error); + return { + content: [{ type: "text", text: `Erro ao conectar com Ollama: ${error.message}` }] + }; + } + } +); + +// 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 +const transport = new StdioServerTransport(); +await server.connect(transport); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c0eae60 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "module": "ESNext" + }, +} \ No newline at end of file