mcp: switch HF MCP login to https://hf.co/mcp?login and accept hf.co in strict checks
Browse files- Update examples and Helm envs to use hf.co endpoint
- Relax isStrictHfMcpLogin to allow both hf.co and huggingface.co
- Keeps functionality identical while preferring the shorter domain
- .env +1 -1
- README.md +1 -1
- chart/env/dev.yaml +1 -1
- chart/env/prod.yaml +1 -1
- src/lib/server/mcp/hf.ts +13 -11
- src/lib/utils/hf.ts +13 -11
.env
CHANGED
|
@@ -119,7 +119,7 @@ LLM_SUMMARIZATION=true # generate conversation titles with LLMs
|
|
| 119 |
|
| 120 |
ALLOW_IFRAME=true # Allow the app to be embedded in an iframe
|
| 121 |
|
| 122 |
-
# Base servers list (JSON array). Example: MCP_SERVERS=[{"name": "Web Search (Exa)", "url": "https://mcp.exa.ai/mcp"}, {"name": "Hugging Face", "url": "https://
|
| 123 |
MCP_SERVERS=
|
| 124 |
# When true, forward the logged-in user's Hugging Face access token
|
| 125 |
MCP_FORWARD_HF_USER_TOKEN=
|
|
|
|
| 119 |
|
| 120 |
ALLOW_IFRAME=true # Allow the app to be embedded in an iframe
|
| 121 |
|
| 122 |
+
# Base servers list (JSON array). Example: MCP_SERVERS=[{"name": "Web Search (Exa)", "url": "https://mcp.exa.ai/mcp"}, {"name": "Hugging Face", "url": "https://hf.co/mcp"}]
|
| 123 |
MCP_SERVERS=
|
| 124 |
# When true, forward the logged-in user's Hugging Face access token
|
| 125 |
MCP_FORWARD_HF_USER_TOKEN=
|
README.md
CHANGED
|
@@ -157,7 +157,7 @@ Configure servers (base list for all users):
|
|
| 157 |
# JSON array of servers: name, url, optional headers
|
| 158 |
MCP_SERVERS=[
|
| 159 |
{"name": "Web Search (Exa)", "url": "https://mcp.exa.ai/mcp"},
|
| 160 |
-
{"name": "Hugging Face MCP Login", "url": "https://
|
| 161 |
]
|
| 162 |
|
| 163 |
# Forward the signed-in user's Hugging Face token to the official HF MCP login endpoint
|
|
|
|
| 157 |
# JSON array of servers: name, url, optional headers
|
| 158 |
MCP_SERVERS=[
|
| 159 |
{"name": "Web Search (Exa)", "url": "https://mcp.exa.ai/mcp"},
|
| 160 |
+
{"name": "Hugging Face MCP Login", "url": "https://hf.co/mcp?login"}
|
| 161 |
]
|
| 162 |
|
| 163 |
# Forward the signed-in user's Hugging Face token to the official HF MCP login endpoint
|
chart/env/dev.yaml
CHANGED
|
@@ -71,7 +71,7 @@ envVars:
|
|
| 71 |
LLM_ROUTER_ENABLE_TOOLS: "true"
|
| 72 |
LLM_ROUTER_TOOLS_MODEL: "moonshotai/Kimi-K2-Instruct-0905"
|
| 73 |
MCP_SERVERS: >
|
| 74 |
-
[{"name": "Web Search (Exa)", "url": "https://mcp.exa.ai/mcp"}, {"name": "Hugging Face", "url": "https://
|
| 75 |
PUBLIC_LLM_ROUTER_DISPLAY_NAME: "Omni"
|
| 76 |
PUBLIC_LLM_ROUTER_LOGO_URL: "https://cdn-uploads.huggingface.co/production/uploads/5f17f0a0925b9863e28ad517/C5V0v1xZXv6M7FXsdJH9b.png"
|
| 77 |
PUBLIC_LLM_ROUTER_ALIAS_ID: "omni"
|
|
|
|
| 71 |
LLM_ROUTER_ENABLE_TOOLS: "true"
|
| 72 |
LLM_ROUTER_TOOLS_MODEL: "moonshotai/Kimi-K2-Instruct-0905"
|
| 73 |
MCP_SERVERS: >
|
| 74 |
+
[{"name": "Web Search (Exa)", "url": "https://mcp.exa.ai/mcp"}, {"name": "Hugging Face", "url": "https://hf.co/mcp?login"}]
|
| 75 |
PUBLIC_LLM_ROUTER_DISPLAY_NAME: "Omni"
|
| 76 |
PUBLIC_LLM_ROUTER_LOGO_URL: "https://cdn-uploads.huggingface.co/production/uploads/5f17f0a0925b9863e28ad517/C5V0v1xZXv6M7FXsdJH9b.png"
|
| 77 |
PUBLIC_LLM_ROUTER_ALIAS_ID: "omni"
|
chart/env/prod.yaml
CHANGED
|
@@ -81,7 +81,7 @@ envVars:
|
|
| 81 |
LLM_ROUTER_ENABLE_TOOLS: "true"
|
| 82 |
LLM_ROUTER_TOOLS_MODEL: "moonshotai/Kimi-K2-Instruct-0905"
|
| 83 |
MCP_SERVERS: >
|
| 84 |
-
[{"name": "Web Search (Exa)", "url": "https://mcp.exa.ai/mcp"}, {"name": "Hugging Face", "url": "https://
|
| 85 |
PUBLIC_LLM_ROUTER_DISPLAY_NAME: "Omni"
|
| 86 |
PUBLIC_LLM_ROUTER_LOGO_URL: "https://cdn-uploads.huggingface.co/production/uploads/5f17f0a0925b9863e28ad517/C5V0v1xZXv6M7FXsdJH9b.png"
|
| 87 |
PUBLIC_LLM_ROUTER_ALIAS_ID: "omni"
|
|
|
|
| 81 |
LLM_ROUTER_ENABLE_TOOLS: "true"
|
| 82 |
LLM_ROUTER_TOOLS_MODEL: "moonshotai/Kimi-K2-Instruct-0905"
|
| 83 |
MCP_SERVERS: >
|
| 84 |
+
[{"name": "Web Search (Exa)", "url": "https://mcp.exa.ai/mcp"}, {"name": "Hugging Face", "url": "https://hf.co/mcp?login"}]
|
| 85 |
PUBLIC_LLM_ROUTER_DISPLAY_NAME: "Omni"
|
| 86 |
PUBLIC_LLM_ROUTER_LOGO_URL: "https://cdn-uploads.huggingface.co/production/uploads/5f17f0a0925b9863e28ad517/C5V0v1xZXv6M7FXsdJH9b.png"
|
| 87 |
PUBLIC_LLM_ROUTER_ALIAS_ID: "omni"
|
src/lib/server/mcp/hf.ts
CHANGED
|
@@ -4,17 +4,19 @@ export const hasAuthHeader = (h?: Record<string, string>) =>
|
|
| 4 |
!!h && Object.keys(h).some((k) => k.toLowerCase() === "authorization");
|
| 5 |
|
| 6 |
export const isStrictHfMcpLogin = (urlString: string) => {
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
|
|
|
|
|
|
| 18 |
};
|
| 19 |
|
| 20 |
export const hasNonEmptyToken = (tok: unknown): tok is string =>
|
|
|
|
| 4 |
!!h && Object.keys(h).some((k) => k.toLowerCase() === "authorization");
|
| 5 |
|
| 6 |
export const isStrictHfMcpLogin = (urlString: string) => {
|
| 7 |
+
try {
|
| 8 |
+
const u = new URL(urlString);
|
| 9 |
+
const host = u.hostname.toLowerCase();
|
| 10 |
+
const allowedHosts = new Set(["hf.co", "huggingface.co"]);
|
| 11 |
+
return (
|
| 12 |
+
u.protocol === "https:" &&
|
| 13 |
+
allowedHosts.has(host) &&
|
| 14 |
+
u.pathname === "/mcp" &&
|
| 15 |
+
u.search === "?login"
|
| 16 |
+
);
|
| 17 |
+
} catch {
|
| 18 |
+
return false;
|
| 19 |
+
}
|
| 20 |
};
|
| 21 |
|
| 22 |
export const hasNonEmptyToken = (tok: unknown): tok is string =>
|
src/lib/utils/hf.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
| 1 |
// Client-safe HF utilities used in UI components
|
| 2 |
|
| 3 |
export function isStrictHfMcpLogin(urlString: string): boolean {
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
|
|
|
|
|
|
| 15 |
}
|
|
|
|
| 1 |
// Client-safe HF utilities used in UI components
|
| 2 |
|
| 3 |
export function isStrictHfMcpLogin(urlString: string): boolean {
|
| 4 |
+
try {
|
| 5 |
+
const u = new URL(urlString);
|
| 6 |
+
const host = u.hostname.toLowerCase();
|
| 7 |
+
const allowedHosts = new Set(["hf.co", "huggingface.co"]);
|
| 8 |
+
return (
|
| 9 |
+
u.protocol === "https:" &&
|
| 10 |
+
allowedHosts.has(host) &&
|
| 11 |
+
u.pathname === "/mcp" &&
|
| 12 |
+
u.search === "?login"
|
| 13 |
+
);
|
| 14 |
+
} catch {
|
| 15 |
+
return false;
|
| 16 |
+
}
|
| 17 |
}
|