Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
imagej-elphel
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Elphel
imagej-elphel
Commits
ce6ade96
Commit
ce6ade96
authored
Feb 03, 2026
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MCP FS access fine tuning, with examples
parent
8f31b82c
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
100 additions
and
12 deletions
+100
-12
mcp.allowed.example
mcp.allowed.example
+6
-0
McpFsAccess.java
src/main/java/com/elphel/imagej/mcp/McpFsAccess.java
+93
-12
McpServer.java
src/main/java/com/elphel/imagej/mcp/McpServer.java
+1
-0
No files found.
mcp.allowed.example
0 → 100644
View file @
ce6ade96
# Example MCP allowed-config file.
# Point -Delphel.mcp.allowed.configfile to this file.
# You can set either allowed.configdir or allowed.config.
#
# allowed.configdir=/media/elphel/btrfs-data/lwir16-proc/NC/config
# allowed.config=/media/elphel/btrfs-data/lwir16-proc/NC/config/MI184-v89-nc_site_30A-no_out.corr-xml
src/main/java/com/elphel/imagej/mcp/McpFsAccess.java
View file @
ce6ade96
...
...
@@ -17,11 +17,12 @@ import com.elphel.imagej.cameras.EyesisCorrectionParameters.CorrectionParameters
public
class
McpFsAccess
{
private
static
final
String
PROP_ALLOWED_CONFIG
=
"elphel.mcp.allowed.config"
;
private
static
final
String
PROP_ALLOWED_CONFIG_DIR
=
"elphel.mcp.allowed.configdir"
;
private
static
final
String
PROP_ALLOWED_CONFIG_FILE
=
"elphel.mcp.allowed.configfile"
;
private
static
final
String
PROP_ALLOWED_EXTRA
=
"elphel.mcp.allowed.extra"
;
private
static
final
String
CONFIG_LIST_KEY
=
"CORRECTION_PARAMETERS.sourceSequencesList"
;
private
static
List
<
Path
>
cachedRoots
=
null
;
private
static
String
cachedConfig
=
null
;
private
static
String
cachedConfig
Key
=
null
;
private
static
long
cachedConfigMtime
=
-
1L
;
private
McpFsAccess
()
{
...
...
@@ -30,16 +31,41 @@ public class McpFsAccess {
public
static
synchronized
List
<
Path
>
getAllowedRoots
()
{
String
configPath
=
System
.
getProperty
(
PROP_ALLOWED_CONFIG
);
String
configDir
=
System
.
getProperty
(
PROP_ALLOWED_CONFIG_DIR
);
long
mtime
=
getMtime
(
configPath
,
configDir
);
if
(
cachedRoots
!=
null
&&
configEquals
(
configPath
,
cachedConfig
)
&&
mtime
==
cachedConfigMtime
)
{
String
configFile
=
System
.
getProperty
(
PROP_ALLOWED_CONFIG_FILE
);
String
[]
resolved
=
resolveConfigFromFile
(
configPath
,
configDir
,
configFile
);
configPath
=
resolved
[
0
];
configDir
=
resolved
[
1
];
String
cacheKey
=
buildCacheKey
(
configPath
,
configDir
,
configFile
);
long
mtime
=
getMtime
(
configPath
,
configDir
,
configFile
);
if
(
cachedRoots
!=
null
&&
configEquals
(
cacheKey
,
cachedConfigKey
)
&&
mtime
==
cachedConfigMtime
)
{
return
cachedRoots
;
}
cachedRoots
=
buildAllowedRoots
(
configPath
,
configDir
);
cachedConfig
=
configPath
;
cachedConfig
Key
=
cacheKey
;
cachedConfigMtime
=
mtime
;
return
cachedRoots
;
}
public
static
boolean
hasConfig
()
{
String
configPath
=
System
.
getProperty
(
PROP_ALLOWED_CONFIG
);
String
configDir
=
System
.
getProperty
(
PROP_ALLOWED_CONFIG_DIR
);
String
configFile
=
System
.
getProperty
(
PROP_ALLOWED_CONFIG_FILE
);
String
[]
resolved
=
resolveConfigFromFile
(
configPath
,
configDir
,
configFile
);
configPath
=
resolved
[
0
];
configDir
=
resolved
[
1
];
return
(
configPath
!=
null
&&
!
configPath
.
trim
().
isEmpty
())
||
(
configDir
!=
null
&&
!
configDir
.
trim
().
isEmpty
());
}
public
static
void
ensureConfigured
()
{
if
(!
hasConfig
())
{
throw
new
IllegalStateException
(
"MCP enabled but no allowed config specified. Set -Delphel.mcp.allowed.configdir "
+
"or -Delphel.mcp.allowed.config, or provide -Delphel.mcp.allowed.configfile "
+
"pointing to a file with allowed.configdir."
);
}
}
public
static
boolean
isAllowed
(
Path
path
)
{
if
(
path
==
null
)
{
return
false
;
...
...
@@ -200,15 +226,16 @@ public class McpFsAccess {
return
-
1L
;
}
private
static
long
getMtime
(
String
configPath
)
{
if
(
configPath
==
null
||
configPath
.
trim
().
isEmpty
())
{
return
-
1L
;
}
try
{
return
Files
.
getLastModifiedTime
(
Paths
.
get
(
configPath
)).
toMillis
();
}
catch
(
IOException
e
)
{
return
-
1L
;
private
static
long
getMtime
(
String
configPath
,
String
configDir
,
String
configFile
)
{
long
max
=
getMtime
(
configPath
,
configDir
);
if
(
configFile
!=
null
&&
!
configFile
.
trim
().
isEmpty
())
{
try
{
max
=
Math
.
max
(
max
,
Files
.
getLastModifiedTime
(
Paths
.
get
(
configFile
)).
toMillis
());
}
catch
(
IOException
e
)
{
// ignore
}
}
return
max
;
}
private
static
boolean
configEquals
(
String
a
,
String
b
)
{
...
...
@@ -220,4 +247,58 @@ public class McpFsAccess {
}
return
a
.
equals
(
b
);
}
private
static
String
buildCacheKey
(
String
configPath
,
String
configDir
,
String
configFile
)
{
StringBuilder
sb
=
new
StringBuilder
();
if
(
configPath
!=
null
)
{
sb
.
append
(
configPath
);
}
sb
.
append
(
"|"
);
if
(
configDir
!=
null
)
{
sb
.
append
(
configDir
);
}
sb
.
append
(
"|"
);
if
(
configFile
!=
null
)
{
sb
.
append
(
configFile
);
}
return
sb
.
toString
();
}
private
static
String
[]
resolveConfigFromFile
(
String
configPath
,
String
configDir
,
String
configFile
)
{
if
((
configPath
!=
null
&&
!
configPath
.
trim
().
isEmpty
())
||
(
configDir
!=
null
&&
!
configDir
.
trim
().
isEmpty
()))
{
return
new
String
[]
{
configPath
,
configDir
};
}
if
(
configFile
==
null
||
configFile
.
trim
().
isEmpty
())
{
return
new
String
[]
{
configPath
,
configDir
};
}
Path
filePath
=
Paths
.
get
(
configFile
).
toAbsolutePath
().
normalize
();
if
(!
Files
.
exists
(
filePath
))
{
return
new
String
[]
{
configPath
,
configDir
};
}
try
{
List
<
String
>
lines
=
Files
.
readAllLines
(
filePath
);
for
(
String
line
:
lines
)
{
String
trimmed
=
line
.
trim
();
if
(
trimmed
.
isEmpty
()
||
trimmed
.
startsWith
(
"#"
))
{
continue
;
}
int
eq
=
trimmed
.
indexOf
(
'='
);
if
(
eq
>
0
)
{
String
key
=
trimmed
.
substring
(
0
,
eq
).
trim
();
String
value
=
trimmed
.
substring
(
eq
+
1
).
trim
();
if
(
key
.
equals
(
PROP_ALLOWED_CONFIG
))
{
configPath
=
value
;
}
else
if
(
key
.
equals
(
PROP_ALLOWED_CONFIG_DIR
)
||
key
.
equals
(
"allowed.configdir"
))
{
configDir
=
value
;
}
}
else
if
(
configDir
==
null
||
configDir
.
trim
().
isEmpty
())
{
configDir
=
trimmed
;
}
}
}
catch
(
IOException
e
)
{
return
new
String
[]
{
configPath
,
configDir
};
}
return
new
String
[]
{
configPath
,
configDir
};
}
}
src/main/java/com/elphel/imagej/mcp/McpServer.java
View file @
ce6ade96
...
...
@@ -30,6 +30,7 @@ public class McpServer {
if
(
INSTANCE
!=
null
)
{
return
INSTANCE
;
}
McpFsAccess
.
ensureConfigured
();
McpServer
instance
=
new
McpServer
(
owner
,
port
);
instance
.
start
();
INSTANCE
=
instance
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment