most of the implementation looking ok but sharing the token the wrong way
This commit is contained in:
parent
743b6b207f
commit
412b5d9486
6 changed files with 364 additions and 62 deletions
|
@ -18,7 +18,8 @@ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
|
|||
import { ListResourcesResultSchema, ListToolsResultSchema } from '@modelcontextprotocol/sdk/types.js'
|
||||
import { UnauthorizedError } from '@modelcontextprotocol/sdk/client/auth.js'
|
||||
import { NodeOAuthClientProvider } from './lib/node-oauth-client-provider'
|
||||
import { parseCommandLineArgs, setupOAuthCallbackServer, setupSignalHandlers, MCP_REMOTE_VERSION } from './lib/utils'
|
||||
import { parseCommandLineArgs, setupSignalHandlers, log, MCP_REMOTE_VERSION, getServerUrlHash } from './lib/utils'
|
||||
import { coordinateAuth } from './lib/coordination'
|
||||
|
||||
/**
|
||||
* Main function to run the client
|
||||
|
@ -27,6 +28,12 @@ async function runClient(serverUrl: string, callbackPort: number, clean: boolean
|
|||
// Set up event emitter for auth flow
|
||||
const events = new EventEmitter()
|
||||
|
||||
// Get the server URL hash for lockfile operations
|
||||
const serverUrlHash = getServerUrlHash(serverUrl)
|
||||
|
||||
// Coordinate authentication with other instances
|
||||
const { server, waitForAuthCode, skipBrowserAuth } = await coordinateAuth(serverUrlHash, callbackPort, events)
|
||||
|
||||
// Create the OAuth client provider
|
||||
const authProvider = new NodeOAuthClientProvider({
|
||||
serverUrl,
|
||||
|
@ -35,6 +42,11 @@ async function runClient(serverUrl: string, callbackPort: number, clean: boolean
|
|||
clean,
|
||||
})
|
||||
|
||||
// If we got auth from another instance, pre-populate with the received code
|
||||
if (skipBrowserAuth) {
|
||||
log('Using auth code from another instance')
|
||||
}
|
||||
|
||||
// Create the client
|
||||
const client = new Client(
|
||||
{
|
||||
|
@ -53,15 +65,15 @@ async function runClient(serverUrl: string, callbackPort: number, clean: boolean
|
|||
|
||||
// Set up message and error handlers
|
||||
transport.onmessage = (message) => {
|
||||
console.log('Received message:', JSON.stringify(message, null, 2))
|
||||
log('Received message:', JSON.stringify(message, null, 2))
|
||||
}
|
||||
|
||||
transport.onerror = (error) => {
|
||||
console.error('Transport error:', error)
|
||||
log('Transport error:', error)
|
||||
}
|
||||
|
||||
transport.onclose = () => {
|
||||
console.log('Connection closed.')
|
||||
log('Connection closed.')
|
||||
process.exit(0)
|
||||
}
|
||||
return transport
|
||||
|
@ -69,16 +81,9 @@ async function runClient(serverUrl: string, callbackPort: number, clean: boolean
|
|||
|
||||
const transport = initTransport()
|
||||
|
||||
// Set up an HTTP server to handle OAuth callback
|
||||
const { server, waitForAuthCode } = setupOAuthCallbackServer({
|
||||
port: callbackPort,
|
||||
path: '/oauth/callback',
|
||||
events,
|
||||
})
|
||||
|
||||
// Set up cleanup handler
|
||||
const cleanup = async () => {
|
||||
console.log('\nClosing connection...')
|
||||
log('\nClosing connection...')
|
||||
await client.close()
|
||||
server.close()
|
||||
}
|
||||
|
@ -86,44 +91,44 @@ async function runClient(serverUrl: string, callbackPort: number, clean: boolean
|
|||
|
||||
// Try to connect
|
||||
try {
|
||||
console.log('Connecting to server...')
|
||||
log('Connecting to server...')
|
||||
await client.connect(transport)
|
||||
console.log('Connected successfully!')
|
||||
log('Connected successfully!')
|
||||
} catch (error) {
|
||||
if (error instanceof UnauthorizedError || (error instanceof Error && error.message.includes('Unauthorized'))) {
|
||||
console.log('Authentication required. Waiting for authorization...')
|
||||
log('Authentication required. Waiting for authorization...')
|
||||
|
||||
// Wait for the authorization code from the callback
|
||||
// Wait for the authorization code from the callback or another instance
|
||||
const code = await waitForAuthCode()
|
||||
|
||||
try {
|
||||
console.log('Completing authorization...')
|
||||
log('Completing authorization...')
|
||||
await transport.finishAuth(code)
|
||||
|
||||
// Reconnect after authorization with a new transport
|
||||
console.log('Connecting after authorization...')
|
||||
log('Connecting after authorization...')
|
||||
await client.connect(initTransport())
|
||||
|
||||
console.log('Connected successfully!')
|
||||
log('Connected successfully!')
|
||||
|
||||
// Request tools list after auth
|
||||
console.log('Requesting tools list...')
|
||||
log('Requesting tools list...')
|
||||
const tools = await client.request({ method: 'tools/list' }, ListToolsResultSchema)
|
||||
console.log('Tools:', JSON.stringify(tools, null, 2))
|
||||
log('Tools:', JSON.stringify(tools, null, 2))
|
||||
|
||||
// Request resources list after auth
|
||||
console.log('Requesting resource list...')
|
||||
log('Requesting resource list...')
|
||||
const resources = await client.request({ method: 'resources/list' }, ListResourcesResultSchema)
|
||||
console.log('Resources:', JSON.stringify(resources, null, 2))
|
||||
log('Resources:', JSON.stringify(resources, null, 2))
|
||||
|
||||
console.log('Listening for messages. Press Ctrl+C to exit.')
|
||||
log('Listening for messages. Press Ctrl+C to exit.')
|
||||
} catch (authError) {
|
||||
console.error('Authorization error:', authError)
|
||||
log('Authorization error:', authError)
|
||||
server.close()
|
||||
process.exit(1)
|
||||
}
|
||||
} else {
|
||||
console.error('Connection error:', error)
|
||||
log('Connection error:', error)
|
||||
server.close()
|
||||
process.exit(1)
|
||||
}
|
||||
|
@ -131,23 +136,23 @@ async function runClient(serverUrl: string, callbackPort: number, clean: boolean
|
|||
|
||||
try {
|
||||
// Request tools list
|
||||
console.log('Requesting tools list...')
|
||||
log('Requesting tools list...')
|
||||
const tools = await client.request({ method: 'tools/list' }, ListToolsResultSchema)
|
||||
console.log('Tools:', JSON.stringify(tools, null, 2))
|
||||
log('Tools:', JSON.stringify(tools, null, 2))
|
||||
} catch (e) {
|
||||
console.log('Error requesting tools list:', e)
|
||||
log('Error requesting tools list:', e)
|
||||
}
|
||||
|
||||
try {
|
||||
// Request resources list
|
||||
console.log('Requesting resource list...')
|
||||
log('Requesting resource list...')
|
||||
const resources = await client.request({ method: 'resources/list' }, ListResourcesResultSchema)
|
||||
console.log('Resources:', JSON.stringify(resources, null, 2))
|
||||
log('Resources:', JSON.stringify(resources, null, 2))
|
||||
} catch (e) {
|
||||
console.log('Error requesting resources list:', e)
|
||||
log('Error requesting resources list:', e)
|
||||
}
|
||||
|
||||
console.log('Listening for messages. Press Ctrl+C to exit.')
|
||||
log('Listening for messages. Press Ctrl+C to exit.')
|
||||
}
|
||||
|
||||
// Parse command-line arguments and run the client
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue