Merge remote-tracking branch 'upstream/main' into liri/post-auth-redirect
This commit is contained in:
commit
921928219d
7 changed files with 65 additions and 41 deletions
27
.github/workflows/publish.yml
vendored
Normal file
27
.github/workflows/publish.yml
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
name: Publish Any Commit
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "**"
|
||||||
|
tags:
|
||||||
|
- "!**"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup pnpm & install
|
||||||
|
uses: wyvox/action-setup-pnpm@v3
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
pnpm-version: 10
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: pnpm build
|
||||||
|
|
||||||
|
- run: pnpm dlx pkg-pr-new publish --compact --bin
|
|
@ -55,7 +55,7 @@ To bypass authentication, or to emit custom headers on all requests to your remo
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note:** Cursor has a bug where spaces inside `args` aren't escaped when it invokes `npx`, which ends up mangling these values. You can work around it using:
|
**Note:** Cursor and Claude Desktop (Windows) have a bug where spaces inside `args` aren't escaped when it invokes `npx`, which ends up mangling these values. You can work around it using:
|
||||||
|
|
||||||
```jsonc
|
```jsonc
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "mcp-remote",
|
"name": "mcp-remote",
|
||||||
"version": "0.1.1",
|
"version": "0.1.4",
|
||||||
"description": "Remote proxy for Model Context Protocol, allowing local-only clients to connect to remote servers using oAuth",
|
"description": "Remote proxy for Model Context Protocol, allowing local-only clients to connect to remote servers using oAuth",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"mcp",
|
"mcp",
|
||||||
|
@ -35,9 +35,7 @@
|
||||||
"@modelcontextprotocol/sdk": "^1.10.2",
|
"@modelcontextprotocol/sdk": "^1.10.2",
|
||||||
"@types/express": "^5.0.0",
|
"@types/express": "^5.0.0",
|
||||||
"@types/node": "^22.13.10",
|
"@types/node": "^22.13.10",
|
||||||
"@types/react": "^19.0.12",
|
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"react": "^19.0.0",
|
|
||||||
"tsup": "^8.4.0",
|
"tsup": "^8.4.0",
|
||||||
"tsx": "^4.19.3",
|
"tsx": "^4.19.3",
|
||||||
"typescript": "^5.8.2"
|
"typescript": "^5.8.2"
|
||||||
|
@ -53,8 +51,6 @@
|
||||||
"dts": true,
|
"dts": true,
|
||||||
"clean": true,
|
"clean": true,
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"external": [
|
"external": []
|
||||||
"react"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
24
pnpm-lock.yaml
generated
24
pnpm-lock.yaml
generated
|
@ -24,15 +24,9 @@ importers:
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^22.13.10
|
specifier: ^22.13.10
|
||||||
version: 22.13.10
|
version: 22.13.10
|
||||||
'@types/react':
|
|
||||||
specifier: ^19.0.12
|
|
||||||
version: 19.0.12
|
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^3.5.3
|
specifier: ^3.5.3
|
||||||
version: 3.5.3
|
version: 3.5.3
|
||||||
react:
|
|
||||||
specifier: ^19.0.0
|
|
||||||
version: 19.0.0
|
|
||||||
tsup:
|
tsup:
|
||||||
specifier: ^8.4.0
|
specifier: ^8.4.0
|
||||||
version: 8.4.0(tsx@4.19.3)(typescript@5.8.2)
|
version: 8.4.0(tsx@4.19.3)(typescript@5.8.2)
|
||||||
|
@ -350,9 +344,6 @@ packages:
|
||||||
'@types/range-parser@1.2.7':
|
'@types/range-parser@1.2.7':
|
||||||
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
|
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
|
||||||
|
|
||||||
'@types/react@19.0.12':
|
|
||||||
resolution: {integrity: sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA==}
|
|
||||||
|
|
||||||
'@types/send@0.17.4':
|
'@types/send@0.17.4':
|
||||||
resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==}
|
resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==}
|
||||||
|
|
||||||
|
@ -479,9 +470,6 @@ packages:
|
||||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|
||||||
csstype@3.1.3:
|
|
||||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
|
||||||
|
|
||||||
debug@2.6.9:
|
debug@2.6.9:
|
||||||
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
|
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -899,10 +887,6 @@ packages:
|
||||||
resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==}
|
resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
react@19.0.0:
|
|
||||||
resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
|
|
||||||
readdirp@4.1.2:
|
readdirp@4.1.2:
|
||||||
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
|
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
|
||||||
engines: {node: '>= 14.18.0'}
|
engines: {node: '>= 14.18.0'}
|
||||||
|
@ -1334,10 +1318,6 @@ snapshots:
|
||||||
|
|
||||||
'@types/range-parser@1.2.7': {}
|
'@types/range-parser@1.2.7': {}
|
||||||
|
|
||||||
'@types/react@19.0.12':
|
|
||||||
dependencies:
|
|
||||||
csstype: 3.1.3
|
|
||||||
|
|
||||||
'@types/send@0.17.4':
|
'@types/send@0.17.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/mime': 1.3.5
|
'@types/mime': 1.3.5
|
||||||
|
@ -1474,8 +1454,6 @@ snapshots:
|
||||||
shebang-command: 2.0.0
|
shebang-command: 2.0.0
|
||||||
which: 2.0.2
|
which: 2.0.2
|
||||||
|
|
||||||
csstype@3.1.3: {}
|
|
||||||
|
|
||||||
debug@2.6.9:
|
debug@2.6.9:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.0.0
|
ms: 2.0.0
|
||||||
|
@ -1896,8 +1874,6 @@ snapshots:
|
||||||
iconv-lite: 0.6.3
|
iconv-lite: 0.6.3
|
||||||
unpipe: 1.0.0
|
unpipe: 1.0.0
|
||||||
|
|
||||||
react@19.0.0: {}
|
|
||||||
|
|
||||||
readdirp@4.1.2: {}
|
readdirp@4.1.2: {}
|
||||||
|
|
||||||
resolve-from@5.0.0: {}
|
resolve-from@5.0.0: {}
|
||||||
|
|
|
@ -37,7 +37,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
get redirectUrl(): string {
|
get redirectUrl(): string {
|
||||||
return `http://127.0.0.1:${this.options.callbackPort}${this.callbackPath}`
|
return `http://localhost:${this.options.callbackPort}${this.callbackPath}`
|
||||||
}
|
}
|
||||||
|
|
||||||
get clientMetadata() {
|
get clientMetadata() {
|
||||||
|
|
|
@ -32,14 +32,21 @@ export function mcpProxy({ transportToClient, transportToServer }: { transportTo
|
||||||
let transportToClientClosed = false
|
let transportToClientClosed = false
|
||||||
let transportToServerClosed = false
|
let transportToServerClosed = false
|
||||||
|
|
||||||
transportToClient.onmessage = (message) => {
|
transportToClient.onmessage = (_message) => {
|
||||||
// @ts-expect-error TODO
|
// TODO: fix types
|
||||||
|
const message = _message as any
|
||||||
log('[Local→Remote]', message.method || message.id)
|
log('[Local→Remote]', message.method || message.id)
|
||||||
|
if (message.method === 'initialize') {
|
||||||
|
const { clientInfo } = message.params
|
||||||
|
if (clientInfo) clientInfo.name = `${clientInfo.name} (via mcp-remote ${MCP_REMOTE_VERSION})`
|
||||||
|
log(JSON.stringify(message, null, 2))
|
||||||
|
}
|
||||||
transportToServer.send(message).catch(onServerError)
|
transportToServer.send(message).catch(onServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
transportToServer.onmessage = (message) => {
|
transportToServer.onmessage = (_message) => {
|
||||||
// @ts-expect-error TODO: fix this type
|
// TODO: fix types
|
||||||
|
const message = _message as any
|
||||||
log('[Remote→Local]', message.method || message.id)
|
log('[Remote→Local]', message.method || message.id)
|
||||||
transportToClient.send(message).catch(onClientError)
|
transportToClient.send(message).catch(onClientError)
|
||||||
}
|
}
|
||||||
|
@ -305,7 +312,16 @@ export function setupOAuthCallbackServerWithLongPoll(options: OAuthCallbackServe
|
||||||
log(`Redirecting to post-auth redirect URI: ${postAuthRedirectUri}`)
|
log(`Redirecting to post-auth redirect URI: ${postAuthRedirectUri}`)
|
||||||
res.redirect(postAuthRedirectUri)
|
res.redirect(postAuthRedirectUri)
|
||||||
} else {
|
} else {
|
||||||
res.send('Authorization successful! You may close this window and return to the CLI.')
|
res.send(`
|
||||||
|
Authorization successful!
|
||||||
|
You may close this window and return to the CLI.
|
||||||
|
<script>
|
||||||
|
// If this is a non-interactive session (no manual approval step was required) then
|
||||||
|
// this should automatically close the window. If not, this will have no effect and
|
||||||
|
// the user will see the message above.
|
||||||
|
window.close();
|
||||||
|
</script>
|
||||||
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify main flow that auth code is available
|
// Notify main flow that auth code is available
|
||||||
|
@ -382,8 +398,9 @@ export async function findAvailablePort(preferredPort?: number): Promise<number>
|
||||||
export async function parseCommandLineArgs(args: string[], defaultPort: number, usage: string) {
|
export async function parseCommandLineArgs(args: string[], defaultPort: number, usage: string) {
|
||||||
// Process headers
|
// Process headers
|
||||||
const headers: Record<string, string> = {}
|
const headers: Record<string, string> = {}
|
||||||
args.forEach((arg, i) => {
|
let i = 0
|
||||||
if (arg === '--header' && i < args.length - 1) {
|
while (i < args.length) {
|
||||||
|
if (args[i] === '--header' && i < args.length - 1) {
|
||||||
const value = args[i + 1]
|
const value = args[i + 1]
|
||||||
const match = value.match(/^([A-Za-z0-9_-]+):(.*)$/)
|
const match = value.match(/^([A-Za-z0-9_-]+):(.*)$/)
|
||||||
if (match) {
|
if (match) {
|
||||||
|
@ -392,8 +409,11 @@ export async function parseCommandLineArgs(args: string[], defaultPort: number,
|
||||||
log(`Warning: ignoring invalid header argument: ${value}`)
|
log(`Warning: ignoring invalid header argument: ${value}`)
|
||||||
}
|
}
|
||||||
args.splice(i, 2)
|
args.splice(i, 2)
|
||||||
|
// Do not increment i, as the array has shifted
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
i++
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
const serverUrl = args[0]
|
const serverUrl = args[0]
|
||||||
const specifiedPort = args[1] ? parseInt(args[1]) : undefined
|
const specifiedPort = args[1] ? parseInt(args[1]) : undefined
|
||||||
|
@ -470,6 +490,11 @@ export function setupSignalHandlers(cleanup: () => Promise<void>) {
|
||||||
|
|
||||||
// Keep the process alive
|
// Keep the process alive
|
||||||
process.stdin.resume()
|
process.stdin.resume()
|
||||||
|
process.stdin.on('end', async () => {
|
||||||
|
log('\nShutting down...')
|
||||||
|
await cleanup()
|
||||||
|
process.exit(0)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"lib": ["ES2022", "DOM"],
|
"lib": ["ES2022", "DOM"],
|
||||||
"types": ["node", "react"],
|
"types": ["node"],
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"resolveJsonModule": true
|
"resolveJsonModule": true
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue