feat: skip client registration via cli args
This commit is contained in:
parent
bd75a1cdf0
commit
6fc2d0d7c3
3 changed files with 66 additions and 6 deletions
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
12
src/proxy.ts
12
src/proxy.ts
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue