Skip to content

[mcp-client] Allow arbitrary endpoint via URL (in both McpClient and Agent) #1396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions packages/inference/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# 🤗 Hugging Face Inference

A Typescript powered wrapper for the HF Inference API (serverless), Inference Endpoints (dedicated), and all supported Inference Providers.
It works with [Inference API (serverless)](https://huggingface.co/docs/api-inference/index) and [Inference Endpoints (dedicated)](https://huggingface.co/docs/inference-endpoints/index), and even with all supported third-party Inference Providers.
A Typescript powered wrapper for Inference Providers (serverless) and Inference Endpoints (dedicated).
It works with [Inference Providers (serverless)](https://huggingface.co/docs/api-inference/index) – including all supported third-party Inference Providers – and [Inference Endpoints (dedicated)](https://huggingface.co/docs/inference-endpoints/index), and even with .

Check out the [full documentation](https://huggingface.co/docs/huggingface.js/inference/README).

Expand All @@ -25,20 +25,20 @@ yarn add @huggingface/inference

```ts
// esm.sh
import { InferenceClient } from "https://esm.sh/@huggingface/inference"
import { InferenceClient } from "https://esm.sh/@huggingface/inference";
// or npm:
import { InferenceClient } from "npm:@huggingface/inference"
import { InferenceClient } from "npm:@huggingface/inference";
```

### Initialize

```typescript
import { InferenceClient } from '@huggingface/inference'
import { InferenceClient } from '@huggingface/inference';

const hf = new InferenceClient('your access token')
const hf = new InferenceClient('your access token');
```

❗**Important note:** Using an access token is optional to get started, however you will be rate limited eventually. Join [Hugging Face](https://huggingface.co/join) and then visit [access tokens](https://huggingface.co/settings/tokens) to generate your access token for **free**.
❗**Important note:** Always pass an access token. Join [Hugging Face](https://huggingface.co/join) and then visit [access tokens](https://huggingface.co/settings/tokens) to generate your access token for **free**.

Your access token should be kept private. If you need to protect it in front-end applications, we suggest setting up a proxy server that stores the access token.

Expand Down
22 changes: 16 additions & 6 deletions packages/mcp-client/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { version as packageVersion } from "./package.json";

const MODEL_ID = process.env.MODEL_ID ?? "Qwen/Qwen2.5-72B-Instruct";
const PROVIDER = (process.env.PROVIDER as InferenceProvider) ?? "nebius";
const BASE_URL = process.env.BASE_URL;

const SERVERS: StdioServerParameters[] = [
{
Expand Down Expand Up @@ -48,12 +49,21 @@ async function main() {
process.exit(1);
}

const agent = new Agent({
provider: PROVIDER,
model: MODEL_ID,
apiKey: process.env.HF_TOKEN,
servers: SERVERS,
});
const agent = new Agent(
BASE_URL
? {
baseUrl: BASE_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();
Expand Down
16 changes: 13 additions & 3 deletions packages/mcp-client/src/Agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,28 @@ export class Agent extends McpClient {

constructor({
provider,
baseUrl,
model,
apiKey,
servers,
prompt,
}: {
provider: InferenceProvider;
}: (
| {
provider: InferenceProvider;
baseUrl?: undefined;
}
| {
baseUrl: string;
provider?: undefined;
}
) & {
model: string;
apiKey: string;
servers: StdioServerParameters[];
prompt?: string;
}) {
super({ provider, model, apiKey });
super(provider ? { provider, baseUrl, model, apiKey } : { provider, baseUrl, model, apiKey });
/// ^This shenanigan is just here to please an overzealous TS type-checker.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🫠

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @coyotte508 if he has an idea to "fix" (in a later PR?)

Copy link
Member

@coyotte508 coyotte508 Apr 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also had to write something like this in #1322 I think (before the force-push)

this.servers = servers;
this.messages = [
{
Expand Down
28 changes: 23 additions & 5 deletions packages/mcp-client/src/McpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import type { StdioServerParameters } from "@modelcontextprotocol/sdk/client/stdio.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { InferenceClient } from "@huggingface/inference";
import type { InferenceProvider } from "@huggingface/inference";
import type { InferenceClientEndpoint, InferenceProvider } from "@huggingface/inference";
import type {
ChatCompletionInputMessage,
ChatCompletionInputTool,
Expand All @@ -22,14 +22,32 @@ export interface ChatCompletionInputMessageTool extends ChatCompletionInputMessa
}

export class McpClient {
protected client: InferenceClient;
protected provider: string;
protected client: InferenceClient | InferenceClientEndpoint;
protected provider: string | undefined;

protected model: string;
private clients: Map<ToolName, Client> = new Map();
public readonly availableTools: ChatCompletionInputTool[] = [];

constructor({ provider, model, apiKey }: { provider: InferenceProvider; model: string; apiKey: string }) {
this.client = new InferenceClient(apiKey);
constructor({
provider,
baseUrl,
model,
apiKey,
}: (
| {
provider: InferenceProvider;
baseUrl?: undefined;
}
| {
baseUrl: string;
provider?: undefined;
}
) & {
model: string;
apiKey: string;
}) {
this.client = baseUrl ? new InferenceClient(apiKey).endpoint(baseUrl) : new InferenceClient(apiKey);
this.provider = provider;
this.model = model;
}
Expand Down
Loading