@huggingface/mcp-client
Version:
Client for the Model Context Protocol
152 lines (150 loc) • 4 kB
JavaScript
import {
ANSI,
Agent,
urlToServerConfig,
version
} from "./chunk-3XTAMMYA.mjs";
// cli.ts
import * as readline from "readline/promises";
import { stdin, stdout } from "process";
import { join } from "path";
import { homedir } from "os";
import { parseArgs } from "util";
var MODEL_ID = process.env.MODEL_ID ?? "Qwen/Qwen2.5-72B-Instruct";
var PROVIDER = process.env.PROVIDER ?? "nebius";
var ENDPOINT_URL = process.env.ENDPOINT_URL ?? process.env.BASE_URL;
var SERVERS = [
{
// Filesystem "official" mcp-server with access to your Desktop
command: "npx",
args: [
"-y",
"@modelcontextprotocol/server-filesystem",
process.platform === "darwin" ? join(homedir(), "Desktop") : homedir()
]
},
{
// Playwright MCP
command: "npx",
args: ["@playwright/mcp@latest"]
}
];
var {
values: { url: urls }
} = parseArgs({
options: {
url: {
type: "string",
multiple: true
}
}
});
if (urls?.length) {
while (SERVERS.length) {
SERVERS.pop();
}
for (const url of urls) {
try {
SERVERS.push(urlToServerConfig(url));
} catch (error) {
console.error(`Error adding server from URL "${url}": ${error.message}`);
}
}
}
async function main() {
if (process.argv.includes("--version")) {
console.log(version);
process.exit(0);
}
if (!process.env.HF_TOKEN) {
console.error(`a valid HF_TOKEN must be present in the env`);
process.exit(1);
}
const agent = new Agent(
ENDPOINT_URL ? {
endpointUrl: ENDPOINT_URL,
model: MODEL_ID,
apiKey: process.env.HF_TOKEN,
servers: SERVERS
} : {
provider: PROVIDER,
model: MODEL_ID,
apiKey: process.env.HF_TOKEN,
servers: SERVERS
}
);
const rl = readline.createInterface({ input: stdin, output: stdout });
let abortController = new AbortController();
let waitingForInput = false;
async function waitForInput() {
waitingForInput = true;
const input = await rl.question("> ");
waitingForInput = false;
return input;
}
rl.on("SIGINT", async () => {
if (waitingForInput) {
await agent.cleanup();
stdout.write("\n");
rl.close();
} else {
abortController.abort();
abortController = new AbortController();
stdout.write("\n");
stdout.write(ANSI.GRAY);
stdout.write("Ctrl+C a second time to exit");
stdout.write(ANSI.RESET);
stdout.write("\n");
}
});
process.on("uncaughtException", (err) => {
stdout.write("\n");
rl.close();
throw err;
});
await agent.loadTools();
stdout.write(ANSI.BLUE);
stdout.write(`Agent loaded with ${agent.availableTools.length} tools:
`);
stdout.write(agent.availableTools.map((t) => `- ${t.function.name}`).join("\n"));
stdout.write(ANSI.RESET);
stdout.write("\n");
while (true) {
const input = await waitForInput();
for await (const chunk of agent.run(input, { abortSignal: abortController.signal })) {
if ("choices" in chunk) {
const delta = chunk.choices[0]?.delta;
if (delta.content) {
stdout.write(delta.content);
}
if (delta.tool_calls) {
stdout.write(ANSI.GRAY);
for (const deltaToolCall of delta.tool_calls) {
if (deltaToolCall.id) {
stdout.write(`<Tool ${deltaToolCall.id}>
`);
}
if (deltaToolCall.function.name) {
stdout.write(deltaToolCall.function.name + " ");
}
if (deltaToolCall.function.arguments) {
stdout.write(deltaToolCall.function.arguments);
}
}
stdout.write(ANSI.RESET);
}
} else {
stdout.write("\n\n");
stdout.write(ANSI.GREEN);
stdout.write(`Tool[${chunk.name}] ${chunk.tool_call_id}
`);
stdout.write(chunk.content);
stdout.write(ANSI.RESET);
stdout.write("\n\n");
}
}
stdout.write("\n");
}
}
main();