mirror of
https://github.com/PortSwigger/mcp-server
synced 2026-06-21 13:45:21 +00:00
Fix AutoApproveTargetsPanel and upgrade dependencies (#39)
* Upgrade to Gradle 9.2.0, Kotlin 2.2.21, and latest dependencies with improved build configuration * Fix memory leak by clearing refreshListener reference in AutoApproveTargetsPanel cleanup * Update version to 1.1.2 * Update version to 1.1.2 in serverInfo
This commit is contained in:
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="2.1.21" />
|
||||
<option name="version" value="2.2.21" />
|
||||
</component>
|
||||
</project>
|
||||
+35
-27
@@ -1,5 +1,34 @@
|
||||
import java.time.Instant
|
||||
|
||||
abstract class EmbedProxyJarTask : DefaultTask() {
|
||||
@get:InputFile
|
||||
abstract val shadowJarFile: RegularFileProperty
|
||||
|
||||
@get:InputDirectory
|
||||
abstract val projectDir: DirectoryProperty
|
||||
|
||||
@get:Inject
|
||||
abstract val execOperations: ExecOperations
|
||||
|
||||
@TaskAction
|
||||
fun embedJar() {
|
||||
val shadowJar = shadowJarFile.get().asFile
|
||||
val libsDir = projectDir.dir("libs").get().asFile
|
||||
val proxyJarFile = File(libsDir, "mcp-proxy-all.jar")
|
||||
|
||||
if (!proxyJarFile.exists()) {
|
||||
throw GradleException("Proxy JAR not found at: ${proxyJarFile.absolutePath}")
|
||||
}
|
||||
|
||||
execOperations.exec {
|
||||
workingDir(projectDir.get().asFile)
|
||||
commandLine("jar", "uf", shadowJar.absolutePath, "-C", libsDir.absolutePath, proxyJarFile.name)
|
||||
}
|
||||
|
||||
logger.lifecycle("Embedded proxy JAR into ${shadowJar.name}")
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
alias(libs.plugins.kotlin.serialization)
|
||||
@@ -11,10 +40,6 @@ group = providers.gradleProperty("group").get()
|
||||
version = providers.gradleProperty("version").get()
|
||||
description = providers.gradleProperty("description").get()
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.burp.montoya.api)
|
||||
|
||||
@@ -40,8 +65,8 @@ kotlin {
|
||||
}
|
||||
|
||||
compilerOptions {
|
||||
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_1)
|
||||
languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_1)
|
||||
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
|
||||
languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
|
||||
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21)
|
||||
freeCompilerArgs.addAll(
|
||||
"-Xjsr305=strict"
|
||||
@@ -103,29 +128,12 @@ tasks {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
|
||||
register("embedProxyJar") {
|
||||
register<EmbedProxyJarTask>("embedProxyJar") {
|
||||
group = "build"
|
||||
description = "Embeds the MCP proxy JAR into the shadow JAR"
|
||||
dependsOn(shadowJar)
|
||||
|
||||
notCompatibleWithConfigurationCache("Task references other tasks at execution time")
|
||||
|
||||
doLast {
|
||||
val shadowJarFile = shadowJar.get().archiveFile.get().asFile
|
||||
val libsDir = layout.projectDirectory.dir("libs").asFile
|
||||
val proxyJarFile = File(libsDir, "mcp-proxy-all.jar")
|
||||
|
||||
if (!proxyJarFile.exists()) {
|
||||
throw GradleException("Proxy JAR not found at: ${proxyJarFile.absolutePath}")
|
||||
}
|
||||
|
||||
exec {
|
||||
workingDir(layout.projectDirectory.asFile)
|
||||
commandLine("jar", "uf", shadowJarFile.absolutePath, "-C", libsDir.absolutePath, proxyJarFile.name)
|
||||
}
|
||||
|
||||
logger.lifecycle("Embedded proxy JAR into ${shadowJarFile.name}")
|
||||
}
|
||||
shadowJarFile.set(shadowJar.flatMap { it.archiveFile })
|
||||
projectDir.set(layout.projectDirectory)
|
||||
}
|
||||
|
||||
build {
|
||||
@@ -139,6 +147,6 @@ tasks {
|
||||
}
|
||||
|
||||
tasks.wrapper {
|
||||
gradleVersion = "8.10"
|
||||
gradleVersion = "9.2.0"
|
||||
distributionType = Wrapper.DistributionType.BIN
|
||||
}
|
||||
+5
-1
@@ -1,9 +1,13 @@
|
||||
kotlin.code.style=official
|
||||
kotlin.stdlib.default.dependency=false
|
||||
group=net.portswigger
|
||||
version=1.1.1
|
||||
version=1.1.2
|
||||
description=Burp MCP Server Extension
|
||||
org.gradle.daemon=true
|
||||
org.gradle.parallel=true
|
||||
org.gradle.caching=true
|
||||
org.gradle.configuration-cache=true
|
||||
org.gradle.configuration-cache.parallel=true
|
||||
org.gradle.file.encoding=UTF-8
|
||||
java.toolchain.version=21
|
||||
org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
[versions]
|
||||
# Build System
|
||||
kotlin = "2.1.21"
|
||||
ktor = "3.1.3"
|
||||
kotlin = "2.2.21"
|
||||
ktor = "3.3.1"
|
||||
|
||||
# Runtime Dependencies
|
||||
kotlinx-serialization = "1.8.1"
|
||||
mcp-sdk = "0.5.0"
|
||||
burp-montoya = "2025.5"
|
||||
kotlinx-serialization = "1.9.0"
|
||||
mcp-sdk = "0.7.4"
|
||||
burp-montoya = "2025.10"
|
||||
|
||||
# Test Dependencies
|
||||
mockk = "1.14.2"
|
||||
mockk = "1.14.6"
|
||||
|
||||
[libraries]
|
||||
# Kotlin
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
Vendored
+94
-94
@@ -1,94 +1,94 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
|
||||
+8
-1
@@ -5,8 +5,15 @@ pluginManagement {
|
||||
}
|
||||
}
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
|
||||
}
|
||||
|
||||
rootProject.name = "burp-mcp"
|
||||
@@ -34,7 +34,7 @@ class KtorServerManager(private val api: MontoyaApi) : ServerManager {
|
||||
server = null
|
||||
|
||||
val mcpServer = Server(
|
||||
serverInfo = Implementation("burp-suite", "1.1.1"), options = ServerOptions(
|
||||
serverInfo = Implementation("burp-suite", "1.1.2"), options = ServerOptions(
|
||||
capabilities = ServerCapabilities(
|
||||
tools = ServerCapabilities.Tools(listChanged = false)
|
||||
)
|
||||
|
||||
@@ -13,6 +13,7 @@ import javax.swing.JOptionPane.*
|
||||
class AutoApproveTargetsPanel(private val config: McpConfig) : JPanel() {
|
||||
|
||||
private var listenerHandle: ListenerHandle? = null
|
||||
private var refreshListener: (() -> Unit)? = null
|
||||
|
||||
init {
|
||||
layout = BoxLayout(this, BoxLayout.Y_AXIS)
|
||||
@@ -58,12 +59,12 @@ class AutoApproveTargetsPanel(private val config: McpConfig) : JPanel() {
|
||||
val targetsList = createTargetsList(listModel)
|
||||
updateTargetsList(listModel)
|
||||
|
||||
val refreshListener = {
|
||||
refreshListener = {
|
||||
SwingUtilities.invokeLater {
|
||||
updateTargetsList(listModel)
|
||||
}
|
||||
}
|
||||
listenerHandle = config.addTargetsChangeListener(refreshListener)
|
||||
listenerHandle = config.addTargetsChangeListener(refreshListener!!)
|
||||
|
||||
val scrollPane = createScrollPane(targetsList)
|
||||
val tableContainer = createTableContainer(scrollPane)
|
||||
@@ -294,6 +295,7 @@ class AutoApproveTargetsPanel(private val config: McpConfig) : JPanel() {
|
||||
fun cleanup() {
|
||||
listenerHandle?.remove()
|
||||
listenerHandle = null
|
||||
refreshListener = null
|
||||
}
|
||||
|
||||
}
|
||||
@@ -101,7 +101,7 @@ class ToolsKtTest {
|
||||
}
|
||||
|
||||
private fun setupHttpHeaderMocks() {
|
||||
every { HttpHeader.httpHeader(any(), any()) } answers {
|
||||
every { HttpHeader.httpHeader(any<String>(), any<String>()) } answers {
|
||||
val name = firstArg<String>()
|
||||
val value = secondArg<String>()
|
||||
mockk<HttpHeader>().also {
|
||||
|
||||
Reference in New Issue
Block a user