index.ts•15.6 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
// Optional: Define configuration schema to require configuration at connection time
export const configSchema = z.object({
debug: z.boolean().default(false).describe("Enable debug logging"),
lifiApiKey: z.string().describe("API key for LI.FI API authentication"),
});
export default function createStatelessServer({
config,
}: {
config: z.infer<typeof configSchema>;
}) {
const server = new McpServer({
name: "My MCP Server",
version: "1.0.0",
});
// LI.FI chains API tool
server.tool(
"lifi_get_chains",
"Get information about all currently supported chains from LI.FI API",
{
chainTypes: z.string().optional().describe("Optional filter to restrict the resulting chains to specific chainTypes"),
},
async ({ chainTypes }) => {
try {
const url = new URL("https://li.quest/v1/chains");
// Add query parameter if provided
if (chainTypes) {
url.searchParams.append("chainTypes", chainTypes);
}
const response = await fetch(url.toString(), {
method: "GET",
headers: {
"x-lifi-api-key": config.lifiApiKey,
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`LI.FI API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error fetching chains from LI.FI API: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
}
);
// LI.FI tokens API tool
server.tool(
"lifi_get_tokens",
"Get information about all supported tokens from LI.FI API",
{
chains: z.string().optional().describe("Optional comma-separated list of chain ids or keys to filter tokens"),
chainTypes: z.string().optional().describe("Optional filter to restrict the resulting tokens to specific chainTypes"),
minPriceUSD: z.number().optional().describe("Optional filter by minimum token price in USD (minimum 0, default 0.0001)"),
},
async ({ chains, chainTypes, minPriceUSD }) => {
try {
const url = new URL("https://li.quest/v1/tokens");
// Add query parameters if provided
if (chains) {
url.searchParams.append("chains", chains);
}
if (chainTypes) {
url.searchParams.append("chainTypes", chainTypes);
}
if (minPriceUSD !== undefined) {
url.searchParams.append("minPriceUSD", minPriceUSD.toString());
}
const response = await fetch(url.toString(), {
method: "GET",
headers: {
"x-lifi-api-key": config.lifiApiKey,
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`LI.FI API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error fetching tokens from LI.FI API: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
}
);
// LI.FI single token API tool
server.tool(
"lifi_get_token",
"Get detailed information about a specific token from LI.FI API",
{
chain: z.string().describe("Chain ID or name where the token exists"),
token: z.string().describe("Token address or symbol to get information for"),
},
async ({ chain, token }) => {
try {
const url = new URL("https://li.quest/v1/token");
url.searchParams.append("chain", chain);
url.searchParams.append("token", token);
const response = await fetch(url.toString(), {
method: "GET",
headers: {
"x-lifi-api-key": config.lifiApiKey,
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`LI.FI API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error fetching token from LI.FI API: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
}
);
// LI.FI tools API tool
server.tool(
"lifi_get_tools",
"Get information about all supported tools (bridges and exchanges) from LI.FI API",
{
chains: z.string().optional().describe("Optional comma-separated list of chain ids or keys to filter tools"),
},
async ({ chains }) => {
try {
const url = new URL("https://li.quest/v1/tools");
// Add query parameter if provided
if (chains) {
url.searchParams.append("chains", chains);
}
const response = await fetch(url.toString(), {
method: "GET",
headers: {
"x-lifi-api-key": config.lifiApiKey,
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`LI.FI API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error fetching tools from LI.FI API: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
}
);
// LI.FI connections API tool
server.tool(
"lifi_get_connections",
"Get information about supported chain connections from LI.FI API",
{
fromChain: z.string().optional().describe("Optional source chain id or key to filter connections from"),
toChain: z.string().optional().describe("Optional destination chain id or key to filter connections to"),
fromToken: z.string().optional().describe("Optional source token address to filter connections"),
toToken: z.string().optional().describe("Optional destination token address to filter connections"),
allowBridges: z.string().optional().describe("Optional comma-separated list of allowed bridge keys"),
denyBridges: z.string().optional().describe("Optional comma-separated list of denied bridge keys"),
allowExchanges: z.string().optional().describe("Optional comma-separated list of allowed exchange keys"),
denyExchanges: z.string().optional().describe("Optional comma-separated list of denied exchange keys"),
},
async ({ fromChain, toChain, fromToken, toToken, allowBridges, denyBridges, allowExchanges, denyExchanges }) => {
try {
const url = new URL("https://li.quest/v1/connections");
// Add query parameters if provided
if (fromChain) {
url.searchParams.append("fromChain", fromChain);
}
if (toChain) {
url.searchParams.append("toChain", toChain);
}
if (fromToken) {
url.searchParams.append("fromToken", fromToken);
}
if (toToken) {
url.searchParams.append("toToken", toToken);
}
if (allowBridges) {
url.searchParams.append("allowBridges", allowBridges);
}
if (denyBridges) {
url.searchParams.append("denyBridges", denyBridges);
}
if (allowExchanges) {
url.searchParams.append("allowExchanges", allowExchanges);
}
if (denyExchanges) {
url.searchParams.append("denyExchanges", denyExchanges);
}
const response = await fetch(url.toString(), {
method: "GET",
headers: {
"x-lifi-api-key": config.lifiApiKey,
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`LI.FI API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error fetching connections from LI.FI API: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
}
);
// LI.FI gas prices API tool
server.tool(
"lifi_get_gas_prices",
"Get gas price information for a specific chain from LI.FI API",
{
chainId: z.string().describe("Chain ID to get gas prices for"),
},
async ({ chainId }) => {
try {
const url = new URL(`https://li.quest/v1/gas/prices/${chainId}`);
const response = await fetch(url.toString(), {
method: "GET",
headers: {
"x-lifi-api-key": config.lifiApiKey,
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`LI.FI API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error fetching gas prices from LI.FI API: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
}
);
// LI.FI gas suggestion API tool
server.tool(
"lifi_get_gas_suggestion",
"Get gas amount suggestions for a specific chain from LI.FI API",
{
chain: z.string().describe("Chain ID or key to get gas suggestions for"),
fromChain: z.string().optional().describe("Optional source chain to calculate required fromToken amount"),
fromToken: z.string().optional().describe("Optional source token address to calculate required amount"),
},
async ({ chain, fromChain, fromToken }) => {
try {
const url = new URL(`https://li.quest/v1/gas/suggestion/${chain}`);
// Add query parameters if provided
if (fromChain) {
url.searchParams.append("fromChain", fromChain);
}
if (fromToken) {
url.searchParams.append("fromToken", fromToken);
}
const response = await fetch(url.toString(), {
method: "GET",
headers: {
"x-lifi-api-key": config.lifiApiKey,
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`LI.FI API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error fetching gas suggestions from LI.FI API: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
}
);
// LI.FI transaction status API tool
server.tool(
"lifi_get_transaction_status",
"Get the status of a cross-chain transfer by transaction hash from LI.FI API",
{
txHash: z.string().optional().describe("Optional transaction hash to check status for"),
transactionId: z.string().optional().describe("Optional alternative transaction identifier"),
},
async ({ txHash, transactionId }) => {
try {
const url = new URL(`https://li.quest/v1/status`);
if (txHash) {
url.searchParams.append("txHash", txHash);
}
if (transactionId) {
url.searchParams.append("transactionId", transactionId);
}
const response = await fetch(url.toString(), {
method: "GET",
headers: {
"x-lifi-api-key": config.lifiApiKey,
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`LI.FI API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error fetching transaction status from LI.FI API: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
}
);
// LI.FI integrator fee withdrawal API tool
server.tool(
"lifi_get_integrator_fee_withdrawal",
"Get integrator fee withdrawal transaction for a specific chain from LI.FI API",
{
integratorId: z.string().describe("Integrator ID to get fee withdrawal transaction for"),
chainId: z.string().describe("Chain ID to withdraw fees from"),
tokens: z.string().optional().describe("Optional comma-separated list of token addresses to withdraw"),
},
async ({ integratorId, chainId, tokens }) => {
try {
const url = new URL(`https://li.quest/v1/integrator/${integratorId}/fees/${chainId}`);
if (tokens) {
url.searchParams.append("tokens", tokens);
}
const response = await fetch(url.toString(), {
method: "GET",
headers: {
"x-lifi-api-key": config.lifiApiKey,
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`LI.FI API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error fetching integrator fee withdrawal from LI.FI API: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
}
);
return server.server;
}