index.ts•4.09 kB
#!/usr/bin/env node
// Add basic error handling
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { Fetcher } from "./Fetcher.js";
import { RequestPayloadSchema } from "./types.js";
process.on("uncaughtException", (error) => {
console.error("Uncaught Exception:", error);
process.exit(1);
});
process.on("unhandledRejection", (reason, promise) => {
console.error("Unhandled Rejection at:", promise, "reason:", reason);
process.exit(1);
});
// Add input validation
function validateUrl(url: string): boolean {
try {
new URL(url);
return true;
} catch {
return false;
}
}
const server = new Server(
{
name: "@tokenizin/mcp-npx-fetch",
version: "0.13.37",
},
{
capabilities: {
resources: {},
tools: {},
},
}
);
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "fetch_html",
description: "Fetch a website and return the content as HTML",
inputSchema: {
type: "object",
properties: {
url: {
type: "string",
description: "URL of the website to fetch",
},
headers: {
type: "object",
description: "Optional headers to include in the request",
},
},
required: ["url"],
},
},
{
name: "fetch_markdown",
description: "Fetch a website and return the content as Markdown",
inputSchema: {
type: "object",
properties: {
url: {
type: "string",
description: "URL of the website to fetch",
},
headers: {
type: "object",
description: "Optional headers to include in the request",
},
},
required: ["url"],
},
},
{
name: "fetch_txt",
description:
"Fetch a website, return the content as plain text (no HTML)",
inputSchema: {
type: "object",
properties: {
url: {
type: "string",
description: "URL of the website to fetch",
},
headers: {
type: "object",
description: "Optional headers to include in the request",
},
},
required: ["url"],
},
},
{
name: "fetch_json",
description: "Fetch a JSON file from a URL",
inputSchema: {
type: "object",
properties: {
url: {
type: "string",
description: "URL of the JSON to fetch",
},
headers: {
type: "object",
description: "Optional headers to include in the request",
},
},
required: ["url"],
},
},
],
};
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
const validatedArgs = RequestPayloadSchema.parse(args);
if (request.params.name === "fetch_html") {
const fetchResult = await Fetcher.html(validatedArgs);
return fetchResult;
}
if (request.params.name === "fetch_json") {
const fetchResult = await Fetcher.json(validatedArgs);
return fetchResult;
}
if (request.params.name === "fetch_txt") {
const fetchResult = await Fetcher.txt(validatedArgs);
return fetchResult;
}
if (request.params.name === "fetch_markdown") {
const fetchResult = await Fetcher.markdown(validatedArgs);
return fetchResult;
}
throw new Error("Tool not found");
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});