Created
April 11, 2025 11:17
-
-
Save laiso/d82d4320f2277627ed1ca8060ef2860e to your computer and use it in GitHub Desktop.
SETUP: docker build -t mcp-server-fetch:latest .
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM denoland/deno:latest | |
# Create the application directory | |
WORKDIR /app | |
# Copy dependency files first for caching | |
COPY deno.json deno.lock* ./ | |
# Copy the rest of the application code | |
COPY . . | |
# Cache application dependencies (optional) | |
RUN deno cache mcp-server-fetch.ts | |
# Expose port 8000 (if needed) | |
EXPOSE 8000 | |
# Run the application | |
CMD ["run", "--allow-net", "--allow-read", "--allow-env", "mcp-server-fetch.ts"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env -S deno run --allow-net --allow-read --allow-env | |
/** | |
* Simple MCP Server for Deno with Fetch Tool | |
* Using Model Context Protocol SDK | |
*/ | |
import { Server } from "npm:@modelcontextprotocol/[email protected]/server/index.js"; | |
import { StdioServerTransport } from "npm:@modelcontextprotocol/[email protected]/server/stdio.js"; | |
import { | |
CallToolRequestSchema, | |
ListToolsRequestSchema, | |
Tool, | |
} from "npm:@modelcontextprotocol/[email protected]/types.js"; | |
// Fetch tool definition | |
const FETCH_TOOL: Tool = { | |
name: "fetch_url", | |
description: "Fetches content from the specified URL", | |
inputSchema: { | |
type: "object", | |
properties: { | |
url: { | |
type: "string", | |
description: "URL to fetch content from" | |
}, | |
headers: { | |
type: "object", | |
additionalProperties: { type: "string" }, | |
description: "Optional headers for the request" | |
} | |
}, | |
required: ["url"] | |
} | |
}; | |
// Server implementation | |
const server = new Server( | |
{ | |
name: "Fetch-MCP-Server", | |
version: "1.0.0", | |
}, | |
{ | |
capabilities: { | |
tools: {}, | |
}, | |
}, | |
); | |
function isFetchArgs(args: unknown): args is { url: string; headers?: Record<string, string> } { | |
return ( | |
typeof args === "object" && | |
args !== null && | |
"url" in args && | |
typeof (args as { url: string }).url === "string" | |
); | |
} | |
// Tool execution function | |
async function fetchExecute(url: string, headers?: Record<string, string>) { | |
try { | |
const response = await fetch(url, { | |
headers: headers || {}, | |
}); | |
if (!response.ok) { | |
throw new Error(`Fetch failed with status: ${response.status}`); | |
} | |
const contentType = response.headers.get("content-type") || ""; | |
// Handle response based on content type | |
if (contentType.includes("application/json")) { | |
const jsonData = await response.json(); | |
return JSON.stringify(jsonData, null, 2); | |
} else { | |
const textData = await response.text(); | |
return textData; | |
} | |
} catch (error: unknown) { | |
console.error("Error in fetch:", error); | |
const errorMessage = error instanceof Error | |
? error.message | |
: "An unknown error occurred"; | |
return `Error fetching content: ${errorMessage}`; | |
} | |
} | |
// Tool handlers | |
server.setRequestHandler(ListToolsRequestSchema, async () => ({ | |
tools: [FETCH_TOOL], | |
})); | |
server.setRequestHandler(CallToolRequestSchema, async (request) => { | |
try { | |
const { name, arguments: args } = request.params; | |
if (!args) { | |
throw new Error("No arguments provided"); | |
} | |
switch (name) { | |
case "fetch_url": { | |
if (!isFetchArgs(args)) { | |
throw new Error("Invalid arguments for fetch_url"); | |
} | |
const { url, headers } = args; | |
const results = await fetchExecute(url, headers); | |
return { | |
content: [{ type: "text", text: results }], | |
isError: false, | |
}; | |
} | |
default: | |
return { | |
content: [{ type: "text", text: `Unknown tool: ${name}` }], | |
isError: true, | |
}; | |
} | |
} catch (error) { | |
return { | |
content: [ | |
{ | |
type: "text", | |
text: `Error: ${error instanceof Error ? error.message : String(error)}`, | |
}, | |
], | |
isError: true, | |
}; | |
} | |
}); | |
async function runServer() { | |
const transport = new StdioServerTransport(); | |
await server.connect(transport); | |
console.error("Fetch MCP Server running on stdio"); | |
} | |
runServer().catch((error) => { | |
console.error("Fatal error running server:", error); | |
Deno.exit(1); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"servers": { | |
"deno-fetch": { | |
"type": "stdio", | |
"command": "docker", | |
"args": [ | |
"run", | |
"-i", | |
"mcp-server-fetch:latest" | |
] | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment