From 5c7c8c2a8ac2bdc2b6ac7b316d98cec4985320ec Mon Sep 17 00:00:00 2001 From: Ismael Sampaio Date: Sun, 6 Apr 2025 22:11:08 -0300 Subject: [PATCH] Separating server files --- README.md | 14 ++++++++- package.json | 5 +++- src/config/servers.json | 5 ++++ src/main.ts | 63 ++++----------------------------------- src/server/mcpServer.ts | 19 ++++++++++++ src/tools/MCPTools.ts | 20 +++++++++++++ src/tools/add.ts | 0 src/tools/ollama.tool.ts | 64 ++++++++++++++++++++++++++++++++++++++++ src/tools/remove.ts | 0 tsconfig.json | 15 +++++++++- 10 files changed, 144 insertions(+), 61 deletions(-) create mode 100644 src/config/servers.json create mode 100644 src/server/mcpServer.ts create mode 100644 src/tools/MCPTools.ts create mode 100644 src/tools/add.ts create mode 100644 src/tools/ollama.tool.ts create mode 100644 src/tools/remove.ts diff --git a/README.md b/README.md index 70b4fbd..3dcd049 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,18 @@ # TSMCP - +## Config file must be a json in format: +```json +{ + "mcpServers": { + "serverName": { + "command": "node", + "args": [ + "C:\\PATH\\TO\\PARENT\\FOLDER\\servername\\build\\index.js" + ] + } + } +} +``` ## 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 index 1919d69..65ba020 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "type": "module", + "scripts": { "inspector": "npx @modelcontextprotocol/inspector tsx src/main.ts" }, @@ -8,6 +9,8 @@ "zod": "^3.24.2" }, "devDependencies": { - "tsx": "^4.19.3" + "@types/node": "^22.14.0", + "tsx": "^4.19.3", + "typescript": "^5.8.3" } } diff --git a/src/config/servers.json b/src/config/servers.json new file mode 100644 index 0000000..0326942 --- /dev/null +++ b/src/config/servers.json @@ -0,0 +1,5 @@ +{ + "mcpServers": { + + } +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index fbd3715..b1b5bf8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,7 @@ import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; +import { MCPTools } from "@tools/MCPTools.js"; +import { ollamaTool } from "@tools/ollama.tool.js"; import { z } from "zod"; // Create an MCP server @@ -8,6 +10,8 @@ const server = new McpServer({ version: "1.0.0" }); +const serverTools = new MCPTools(server); + // Add an addition tool server.tool("add", { a: z.number(), b: z.number() }, @@ -16,66 +20,9 @@ server.tool("add", }) ); -// 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 - }), - }); +serverTools.registerTool(ollamaTool) - 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( diff --git a/src/server/mcpServer.ts b/src/server/mcpServer.ts new file mode 100644 index 0000000..0f795e4 --- /dev/null +++ b/src/server/mcpServer.ts @@ -0,0 +1,19 @@ +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; +import { version } from "os"; +import { z } from "zod"; + + +const server = new McpServer({ + name: "DatabaseServer", + version: "0.0.1", + capabilities: { + resources: {}, + tools: {} + } +}) + +async function main() { + const transport = new StdioServerTransport(); + await server.co +} \ No newline at end of file diff --git a/src/tools/MCPTools.ts b/src/tools/MCPTools.ts new file mode 100644 index 0000000..e21366d --- /dev/null +++ b/src/tools/MCPTools.ts @@ -0,0 +1,20 @@ +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { Tool } from "@modelcontextprotocol/sdk/types.js"; + + +export class MCPTools { + + constructor(private readonly server: McpServer) { + + } + + registerTool(toolFactory: () => { name: string, schema: any, handler: any }) { + const tool = toolFactory(); + this.server.tool(tool.name, tool.schema, tool.handler); + } + + removeTool() { + + } +} + diff --git a/src/tools/add.ts b/src/tools/add.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/tools/ollama.tool.ts b/src/tools/ollama.tool.ts new file mode 100644 index 0000000..4c36b26 --- /dev/null +++ b/src/tools/ollama.tool.ts @@ -0,0 +1,64 @@ +import {z} from "zod" + +export function ollamaTool() { + return { + name: "ollama", + schema: { + prompt: z.string(), + model: z.string().default("gemma3:4b"), + options: z.object({ + temperature: z.number().min(0).max(2).optional().default(0.7), + max_tokens: z.number().optional().default(4000) + }).optional().default({}) + }, + handler: async ({ prompt, model, options }, extra) => { + try { + console.log(`Enviando para Ollama: modelo=${model}, prompt="${prompt.substring(0, 30)}..."`); + + 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 + }), + }); + + if (!response.ok) { + const error = await response.text(); + console.error(`Erro na resposta do Ollama: ${error}`); + return { + content: [{ type: "text" as const, 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" as const, text: `Erro: formato de resposta inesperado do Ollama` }] + }; + } + + return { + content: [{ + type: "text" as const, + text: data.response + }] + }; + } catch (error) { + console.error(`Erro na comunicação com Ollama:`, error); + return { + content: [{ type: "text" as const, text: `Erro ao conectar com Ollama: ${error.message}` }] + }; + } + } + } +} \ No newline at end of file diff --git a/src/tools/remove.ts b/src/tools/remove.ts new file mode 100644 index 0000000..e69de29 diff --git a/tsconfig.json b/tsconfig.json index c0eae60..e394d25 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,18 @@ { "compilerOptions": { - "module": "ESNext" + "target": "ES2022", + "module": "Node16", + "moduleResolution": "Node16", + "baseUrl": ".", + "rootDir": "./src", + "outDir": "./build", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "paths": { + "@tools/*": ["src/tools/*"] + } }, + "include": ["src/**/*"], + "exclude": ["node_modules"] } \ No newline at end of file