feat: skip client registration via cli args

This commit is contained in:
Filipe Constantinov Menezes 2025-05-14 15:29:29 +01:00
parent bd75a1cdf0
commit 6fc2d0d7c3
3 changed files with 66 additions and 6 deletions

View file

@ -22,18 +22,23 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
private clientUri: string
private softwareId: string
private softwareVersion: string
private clientId: string | undefined
private clientSecret: string | undefined
private scope: string | undefined
/**
* Creates a new NodeOAuthClientProvider
* @param options Configuration options for the provider
*/
constructor(readonly options: OAuthProviderOptions) {
constructor(readonly options: OAuthProviderOptions & { clientId?: string, clientSecret?: string, scope?: string }) {
this.serverUrlHash = getServerUrlHash(options.serverUrl)
this.callbackPath = options.callbackPath || '/oauth/callback'
this.clientName = options.clientName || 'MCP CLI Client'
this.clientUri = options.clientUri || 'https://github.com/modelcontextprotocol/mcp-cli'
this.softwareId = options.softwareId || '2e6dc280-f3c3-4e01-99a7-8181dbd1d23d'
this.softwareVersion = options.softwareVersion || MCP_REMOTE_VERSION
this.clientId = options.clientId
this.clientSecret = options.clientSecret
this.scope = options.scope
}
get redirectUrl(): string {
@ -50,6 +55,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
client_uri: this.clientUri,
software_id: this.softwareId,
software_version: this.softwareVersion,
scope: this.scope,
}
}
@ -59,6 +65,12 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
*/
async clientInformation(): Promise<OAuthClientInformation | undefined> {
// log('Reading client info')
if (this.clientId) {
return {
client_id: this.clientId,
client_secret: this.clientSecret,
}
}
return readJsonFile<OAuthClientInformation>(this.serverUrlHash, 'client_info.json', OAuthClientInformationSchema)
}

View file

@ -392,9 +392,49 @@ export async function findAvailablePort(preferredPort?: number): Promise<number>
export async function parseCommandLineArgs(args: string[], defaultPort: number, usage: string) {
// Process headers
const headers: Record<string, string> = {}
let clientId: string | undefined = undefined
let clientSecret: string | undefined = undefined
let callbackPath: string | undefined = undefined
let scope: string | undefined = undefined
let i = 0
while (i < args.length) {
if (args[i] === '--header' && i < args.length - 1) {
if (args[i] === '--client-id' && i < args.length - 1) {
const value = args[i + 1]
if (value) {
clientId = value
} else {
log('Warning: ignoring empty client-id argument')
}
args.splice(i, 2)
continue
} else if (args[i] === '--client-secret' && i < args.length - 1) {
const value = args[i + 1]
if (value) {
clientSecret = value
} else {
log('Warning: ignoring empty client-secret argument')
}
args.splice(i, 2)
continue
} else if (args[i] === '--callback-path' && i < args.length - 1) {
const value = args[i + 1]
if (value) {
callbackPath = value
} else {
log('Warning: ignoring empty callback-path argument')
}
args.splice(i, 2)
continue
} else if (args[i] === '--scope' && i < args.length - 1) {
const value = args[i + 1]
if (value) {
scope = value
} else {
log('Warning: ignoring empty scope argument')
}
args.splice(i, 2)
continue
} else if (args[i] === '--header' && i < args.length - 1) {
const value = args[i + 1]
const match = value.match(/^([A-Za-z0-9_-]+):(.*)$/)
if (match) {
@ -468,7 +508,7 @@ export async function parseCommandLineArgs(args: string[], defaultPort: number,
})
}
return { serverUrl, callbackPort, headers, transportStrategy }
return { serverUrl, callbackPort, headers, transportStrategy, callbackPath, clientId, clientSecret, scope }
}
/**

View file

@ -32,6 +32,10 @@ async function runProxy(
callbackPort: number,
headers: Record<string, string>,
transportStrategy: TransportStrategy = 'http-first',
callbackPath?: string,
clientId?: string,
clientSecret?: string,
scope?: string,
) {
// Set up event emitter for auth flow
const events = new EventEmitter()
@ -46,7 +50,11 @@ async function runProxy(
const authProvider = new NodeOAuthClientProvider({
serverUrl,
callbackPort,
callbackPath,
clientName: 'MCP CLI Proxy',
clientId: clientId,
clientSecret: clientSecret,
scope: scope,
})
// Create the STDIO transport for local connections
@ -136,8 +144,8 @@ to the CA certificate file. If using claude_desktop_config.json, this might look
// Parse command-line arguments and run the proxy
parseCommandLineArgs(process.argv.slice(2), 3334, 'Usage: npx tsx proxy.ts <https://server-url> [callback-port]')
.then(({ serverUrl, callbackPort, headers, transportStrategy }) => {
return runProxy(serverUrl, callbackPort, headers, transportStrategy)
.then(({ serverUrl, callbackPort, headers, transportStrategy, callbackPath, clientId, clientSecret, scope }) => {
return runProxy(serverUrl, callbackPort, headers, transportStrategy, callbackPath, clientId, clientSecret, scope)
})
.catch((error) => {
log('Fatal error:', error)