simpler way of setting up

(cherry picked from commit f13d28ad45)
This commit is contained in:
aheizi 2025-03-11 00:50:27 +08:00
parent 5a491672c4
commit a7eac55a2b
4 changed files with 787 additions and 72 deletions

791
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -318,7 +318,7 @@
"@google-cloud/vertexai": "^1.9.3",
"@google/generative-ai": "^0.18.0",
"@mistralai/mistralai": "^1.3.6",
"@modelcontextprotocol/sdk": "^1.5.0",
"@modelcontextprotocol/sdk": "1.5.0",
"@types/clone-deep": "^4.0.4",
"@types/pdf-parse": "^1.1.4",
"@types/tmp": "^0.2.6",

View file

@ -43,26 +43,26 @@ const BaseConfigSchema = z.object({
alwaysAllow: z.array(z.string()).default([]),
})
// Stdio specific configuration
export const StdioConfigSchema = BaseConfigSchema.extend({
type: z.literal("stdio"),
command: z.string(),
args: z.array(z.string()).optional(),
env: z.record(z.string()).optional(),
})
// SSE specific configuration with simplified format
const SSEConfigSchema = BaseConfigSchema.extend({
type: z.literal("sse").optional(),
url: z.string().url(),
headers: z.record(z.string()).optional(),
}).transform((data) => ({
...data,
type: "sse" as const,
}))
// Combined server configuration schema
const ServerConfigSchema = z.union([StdioConfigSchema, SSEConfigSchema])
// Server configuration schema with automatic type inference
export const ServerConfigSchema = z.union([
// Stdio config (has command field)
BaseConfigSchema.extend({
command: z.string(),
args: z.array(z.string()).optional(),
env: z.record(z.string()).optional(),
}).transform((data) => ({
...data,
type: "stdio" as const,
})),
// SSE config (has url field)
BaseConfigSchema.extend({
url: z.string().url(),
headers: z.record(z.string()).optional(),
}).transform((data) => ({
...data,
type: "sse" as const,
})),
])
// Settings schema
const McpSettingsSchema = z.object({
@ -167,6 +167,16 @@ export class McpHub {
}
}
private isLocalhost(hostname: string): boolean {
return (
hostname === "localhost" ||
hostname === "127.0.0.1" ||
hostname === "::1" ||
hostname.endsWith(".localhost") ||
hostname.endsWith(".local")
)
}
private async connectToServer(name: string, config: z.infer<typeof ServerConfigSchema>): Promise<void> {
// Remove existing connection if it exists
await this.deleteConnection(name)
@ -241,9 +251,11 @@ export class McpHub {
const sseOptions = {
requestInit: {
headers: config.headers,
// Allow self-signed certificates if needed
agent: new (require("https").Agent)({
rejectUnauthorized: false,
// Only disable certificate validation for local development connections
...(this.isLocalhost(new URL(config.url).hostname) && {
agent: new (require("https").Agent)({
rejectUnauthorized: false,
}),
}),
},
}
@ -721,7 +733,7 @@ export class McpHub {
let timeout: number
try {
const parsedConfig = StdioConfigSchema.parse(JSON.parse(connection.server.config))
const parsedConfig = ServerConfigSchema.parse(JSON.parse(connection.server.config))
timeout = (parsedConfig.timeout ?? 60) * 1000
} catch (error) {
console.error("Failed to parse server config for timeout:", error)

View file

@ -2,7 +2,7 @@ import type { McpHub as McpHubType } from "../McpHub"
import type { ClineProvider } from "../../../core/webview/ClineProvider"
import type { ExtensionContext, Uri } from "vscode"
import type { McpConnection } from "../McpHub"
import { StdioConfigSchema } from "../McpHub"
import { ServerConfigSchema } from "../McpHub"
const fs = require("fs/promises")
const { McpHub } = require("../McpHub")
@ -297,7 +297,7 @@ describe("McpHub", () => {
command: "test",
timeout: 60,
}
expect(() => StdioConfigSchema.parse(validConfig)).not.toThrow()
expect(() => ServerConfigSchema.parse(validConfig)).not.toThrow()
// Test invalid timeout values
const invalidConfigs = [
@ -307,7 +307,7 @@ describe("McpHub", () => {
]
invalidConfigs.forEach((config) => {
expect(() => StdioConfigSchema.parse(config)).toThrow()
expect(() => ServerConfigSchema.parse(config)).toThrow()
})
})