BoxLang 🚀 A New JVM Dynamic Language Learn More...
|:------------------------------------------------------: |
| ⚡︎ B o x L a n g ⚡︎
| Dynamic : Modular : Productive
|:------------------------------------------------------: |
This module provides a Model Context Protocol (MCP) server for the BoxLang runtime. It exposes a comprehensive set of runtime introspection tools — allowing external MCP clients such as AI coding assistants and monitoring tools to query, inspect, and manage a live BoxLang instance over HTTP.
The tool set now also includes a holistic performance snapshot endpoint that combines memory, garbage collection, threads, top executors, slow queries, slow requests, slow HTTP/SOAP calls, buffer pools, optional web server metrics, and a built-in health report with recommendations.
The server auto-registers with the bx-ai module and
exposes an endpoint at /~bxmcp/boxlang.bxm.
box install bx-mcp
Or use the module installer appropriate to your runtime as described in the Module Installation Guide.
Feature Requests and Bug Reports may be submitted via JIRA.
If you file a bug report, your issue should contain a title, a clear description of the issue, a way to replicate the issue, and any support files that we might need to replicate your issue. The goal of a bug report is to make it easy for yourself — and others — to replicate the bug and develop a fix for it. All issues that do not contain a way to replicate will not be addressed.
If you have any questions on usage, professional support or just ideas to bounce off the maintainers, please do not create an issue. Leverage our support channels first.
All settings are configured in the module's boxlang.json
entry under modules.bxmcp.settings.
{
"modules": {
"bxmcp": {
"enabled": true,
"settings": {
"enabled": true,
"authToken": "FILL_THIS_OUT_ALWAYS",
"allowedIPs": ["127.0.0.1"],
"corsAllowedOrigins": [],
"enableStats": true,
"maxRequestBodySize": 0,
"enablePoolLatencyTracking": false,
"heapDumpDir": "",
"slowSQL": {
"enabled": true,
"slowQueryThresholdMs": 1000,
"slowQueryBufferSize": 200,
"slowQueryCapture": true
},
"slowRequests": {
"enabled": true,
"slowRequestThresholdMs": 1000,
"slowRequestBufferSize": 200,
"slowRequestCaptureStack": false
},
"slowHttp": {
"enabled": true,
"slowHttpThresholdMs": 1000,
"slowHttpBufferSize": 200,
"slowHttpCaptureBody": false
},
"securityProfiles": {
"admin": {
"includedTools": ["*"],
"excludedTools": []
},
"readonly": {
"includedTools": ["*_get*", "*_has*", "*_search*", "*_read*"],
"excludedTools": []
}
},
"routeMetrics": {
"enabled": true,
"maxRoutes": 200,
"normalizePathParams": true
},
"includedTools": ["*"],
"excludedTools": []
}
}
}
}
| Setting | Type | Default | Description |
|---|---|---|---|
enabled
| boolean | true
| Master switch. When false, the MCP server is
not registered at runtime. |
authToken
| string | array | ""
| Bearer token(s) controlling access. Supports a simple string or an array of structs with per-token tool filters. Empty = no auth. See Authentication & Access Control. |
allowedIPs
| array | ["127.0.0.1"]
| IP allowlist. Supports individual IPs and CIDR ranges
(192.168.0.0/24). Empty array = all IPs allowed. |
corsAllowedOrigins
| array | []
| CORS allowed origins. Supports wildcards
(*.domain.com). Empty = no CORS headers. |
enableStats
| boolean | true
| Enable MCP server statistics tracking (tool call counts, timing). |
maxRequestBodySize
| numeric | 0
| Max HTTP request body size in bytes. 0 = no limit. |
includedTools
| array | ["*"]
| Tool whitelist. ["*"] = all tools.
Supports exact names and glob patterns (jvm*, cache_get*). |
excludedTools
| array | []
| Tools to hide from the MCP client after the whitelist is applied. Supports exact names and glob patterns. |
securityProfiles
| struct | { admin: { includedTools:
["*"], excludedTools: [] }, readonly: {
includedTools:
["*_get*","*_has*","*_search*","*_read*"],
excludedTools: [] } }
| Named security profiles that define reusable tool access
policies. Profiles are referenced from authToken
entries via the profile field. Two built-in
profiles (admin and readonly) are
always available and can be overridden. See Security Profiles. |
enablePoolLatencyTracking
| boolean | false
| Enable HikariCP connection-pool latency histograms for
all datasources (acquire/usage/creation percentiles + timeout
count). Requires BoxLang 1.14+ with
ON_DATASOURCE_INITIALIZED event support. |
heapDumpDir
| string | ""
| Directory where .hprof heap dump files are
written by the jvm_trigger_heap_dump tool. Empty =
system temp directory. The directory is created automatically if
it does not exist. |
slowSQL
| struct | { enabled: true,
slowQueryThresholdMs: 1000, slowQueryBufferSize: 200,
slowQueryCapture: true }
| Enable slow SQL capture through the
SlowJDBCCollector interceptor. enabled
registers the collector; slowQueryThresholdMs sets
the slow-query cutoff; slowQueryBufferSize controls
the in-memory sample window; slowQueryCapture
controls whether rendered SQL text is stored. |
slowRequests
| struct | { enabled: true,
slowRequestThresholdMs: 1000, slowRequestBufferSize: 200,
slowRequestCaptureStack: false }
| Enable slow inbound request capture through the
SlowRequestCollector interceptor.
enabled registers the collector;
slowRequestThresholdMs sets the slow-request
cutoff; slowRequestBufferSize controls the
in-memory rolling window; slowRequestCaptureStack
controls whether a completion-time thread stack snapshot is stored. |
routeMetrics
| struct | { enabled: true, maxRoutes: 200,
normalizePathParams: true }
| Enable per-route inbound request metrics.
enabled registers the
RouteMetricsCollector interceptor;
maxRoutes limits tracked unique routes (LRU
eviction); normalizePathParams controls whether
digit-only and UUID path segments are normalized to
{id} to prevent route table explosion. |
slowHttp
| struct | { enabled: true,
slowHttpThresholdMs: 1000, slowHttpBufferSize: 200,
slowHttpCaptureBody: false }
| Enable slow outbound HTTP/SOAP call capture through the
SlowHttpCollector interceptor. Since SOAP calls
transit through the same BoxHttpClient pipeline,
they are captured automatically. enabled registers
the collector; slowHttpThresholdMs sets the
slow-call cutoff; slowHttpBufferSize controls the
in-memory sample window; slowHttpCaptureBody
controls whether a truncated (500-char) response body snippet is stored. |
authToken
: Strongly recommended for any non-localhost deployment.
Clients must send Authorization: Bearer {token}.allowedIPs
: Defaults to localhost only. For access from
Docker containers or remote machines, add their IPs or CIDR ranges.excludedTools
: Use this to hide sensitive operations (e.g.,
runtime_get_config, cache_clear_all,
module_reload_all) from MCP clients. Glob patterns like
cache_clear* are supported.The authToken setting supports two shapes.
One token, full access to every registered tool:
{
"modules": {
"bxmcp": {
"settings": {
"authToken": "my-secret-token"
}
}
}
}
Clients send:
Authorization: Bearer my-secret-token
Multiple tokens, each with independent tool-level access control:
{
"modules": {
"bxmcp": {
"settings": {
"authToken": [
{
"token": "admin-token",
"includedTools": ["*"],
"excludedTools": []
},
{
"token": "readonly-token",
"includedTools": ["runtime_get_info", "jvm_get_memory_info", "module_get_all"],
"excludedTools": []
},
{
"token": "ops-token",
"includedTools": ["*"],
"excludedTools": ["jvm_trigger_gc", "cache_clear_all", "module_reload_all"]
},
{
"token": "jvm-readonly-token",
"includedTools": ["jvm*", "runtime_get_info"],
"excludedTools": []
}
]
}
}
}
}
Each struct requires a token field. Both
includedTools and excludedTools are optional:
| Field | Default | Description |
|---|---|---|
token
| (required) | The Bearer token value the client must send. |
profile
| "admin"
| Named security profile to apply. References a profile
defined in securityProfiles. See Security Profiles. |
includedTools
| ["*"]
| Tool whitelist. ["*"] means all
tools. Provide specific names to restrict access. Overrides the
profile's includedTools when set. |
excludedTools
| []
| Tools to block even if they match the
includedTools whitelist. Merged with the profile's excludedTools. |
Filtering rules (applied in order):
includedTools does not contain
"*" and the tool name does not match any
pattern → denied.excludedTools
→ denied.Both includedTools and excludedTools
support glob patterns:
| Pattern | Matches |
|---|---|
"*"
| All tools |
"jvm*"
| All tools starting with jvm_
|
"cache_get*"
| cache_get_all, cache_get_stats,
cache_get_keys, … |
"*_health*"
| Any tool with _health in its name |
"runtime_get_info"
| Exact match only |
Security profiles let you define reusable named access policies that
can be referenced from multiple authToken entries via the
profile field. This avoids repeating the same
includedTools/excludedTools patterns across tokens.
Two profiles are built in and always available (you can override them
in securityProfiles):
| Profile | includedTools | excludedTools | Use Case |
|---|---|---|---|
admin
| ["*"]
| []
| Unrestricted access to every tool |
readonly
| ["*_get*", "*_has*",
"*_search*", "*_read*"]
| []
| Read-only observability — all inspection tools, no mutation |
Define additional profiles in the securityProfiles setting:
{
"modules": {
"bxmcp": {
"settings": {
"securityProfiles": {
"operator": {
"includedTools": ["*_get*", "*_has*", "module_reload*", "scheduler_*"],
"excludedTools": ["app_stop", "runtime_toggle_debug_mode"]
},
"jvm-only": {
"includedTools": ["jvm*", "runtime_get_info"],
"excludedTools": ["jvm_trigger_gc", "jvm_trigger_heap_dump"]
}
}
}
}
}
}
Each authToken entry can reference a profile using the
profile field:
{
"modules": {
"bxmcp": {
"settings": {
"securityProfiles": {
"operator": {
"includedTools": ["*_get*", "*_has*", "module_reload*", "scheduler_*"],
"excludedTools": ["app_stop"]
}
},
"authToken": [
{ "token": "admin-token", "profile": "admin" },
{ "token": "readonly-token", "profile": "readonly" },
{ "token": "operator-token", "profile": "operator" },
{
"token": "restricted-ops-token",
"profile": "operator",
"excludedTools": ["module_reload_all", "scheduler_run_task"]
}
]
}
}
}
}
When a profile is specified:
includedTools and
excludedTools are loaded as the baseline.includedTools, it
overrides the profile's includedTools.excludedTools, they
are merged with the profile's excludedTools.Token has profile
|
Token has includedTools
|
Token has excludedTools
|
Result |
|---|---|---|---|
| Yes | No | No | Profile's settings used as-is |
| Yes | Yes | No | Token's
includedTools overrides profile |
| Yes | No | Yes | Profile's
includedTools + merged excludedTools
|
| Yes | Yes | Yes | Token's
includedTools overrides profile + merged excludedTools
|
| No | Yes/No | Yes/No | No profile applied; token's own settings used directly |
Leave authToken empty ("") or
omit it entirely to run in open-access mode (no
Authorization header required). This is suitable only for
localhost-only deployments already protected by allowedIPs.
The server exposes tools across 17 runtime domains. Each tool is an
@mcpTool annotated method discovered automatically via
classpath scanning.
BoxLangTools
| Tool | Description |
|---|---|
runtime_get_info
| BoxLang version, JVM environment, OS details, start time, uptime, and license status |
runtime_get_license_status
| Current license status: trial mode, validity, expiration, product info (no sensitive tokens) |
runtime_get_config
| Full runtime configuration: datasources, caches, executors, logging, security, schedulers |
runtime_get_config_value
| Get a specific config value by dotted path (e.g. caches.default.provider) |
runtime_config_diff
| Diff live BoxRuntime configuration against
boxlang.json on disk |
runtime_get_bif_summary
| BIF counts by category and sorted name list |
runtime_get_bif_info
| Detailed metadata for a specific BIF: signature, parameters, documentation |
runtime_search_bifs
| Search BIFs by keyword |
runtime_get_component_summary
| All registered components with total count |
runtime_get_component_info
| Metadata for a specific component: methods, properties, inheritance |
runtime_search_components
| Search components by keyword |
runtime_get_global_services
| All registered global runtime services |
runtime_toggle_debug_mode
| Toggle BoxLang debug mode on/off |
runtime_get_class_resolver_info
| Class resolver prefixes, cache size, dynamic class loader count |
runtime_clear_system_cache
| Clear compiled class caches (template, function, component, etc.) |
runtime_clear_page_pool
| Clear the Boxpiler page pool of compiled class instances |
JVMTools
| Tool | Description |
|---|---|
jvm_get_memory_info
| Heap and non-heap memory: used, committed, max, free, percent used |
jvm_get_memory_pool_details
| Memory pool breakdown: Eden, Survivor, Old Gen, Metaspace, Code Cache |
jvm_get_thread_info
| Thread counts: total, daemon, peak, started, by state |
jvm_get_thread_dump
| Full JVM thread dump with stack traces |
jvm_get_hot_threads
| Top-N CPU-consuming threads over a sampling window using ThreadMXBean CPU-time deltas; includes stack traces |
jvm_get_top_allocators
| Top-N thread allocators over a sampling window using per-thread allocated-bytes deltas; includes stack traces and allocation rate |
jvm_get_deadlocks
| Detects deadlocked threads; returns participant stacks, waited lock owner, locked monitors, and synchronizers |
jvm_get_cpu_info
| Available processors, system load average, process CPU time |
jvm_get_gc_info
| GC algorithm statistics: collection count, cumulative collection time |
jvm_trigger_gc
| Manually trigger a garbage collection; returns before/after memory stats |
jvm_trigger_heap_dump
| Trigger an on-demand JVM heap dump (.hprof) to the
configured heapDumpDir. Only file metadata (path,
size, timing) is returned — the binary dump is not streamed.
Pairs with Eclipse MAT for offline leak analysis. |
jvm_get_class_loading_info
| Currently loaded, total loaded, and total unloaded class counts |
jvm_get_runtime_info
| JVM name, vendor, version, uptime |
jvm_get_system_properties
| All JVM system properties |
jvm_get_environment_variables
| JVM environment variables (sensitive values masked) |
jvm_get_operating_system_info
| OS name, version, architecture, available processors |
jvm_get_file_descriptors
| Open and max file descriptor counts plus utilization percent (Unix/Linux/macOS only; returns platform message on Windows) |
jvm_get_disk_usage
| Disk usage for all mounted volumes and BoxLang-relevant paths (temp, logs, home, working directory). Returns total, usable, free space with human-readable sizes and usage percentages. |
jvm_get_hot_threads identifies hot threads by taking a
CPU-time snapshot for all threads, waiting for a sampling window,
taking a second snapshot, and ranking threads by CPU delta
(endNs - startNs).
durationMs=3000,
topN=5, stackDepth=20
jvm_get_top_allocators identifies allocation-heavy
threads by taking a per-thread allocated-bytes snapshot, waiting for a
sampling window, taking a second snapshot, and ranking threads by
allocation delta (endBytes - startBytes).
durationMs=3000, topN=10
jvm_get_deadlocks returns an empty array when no deadlock
exists. When a deadlock is found, each array entry represents one
participant thread.
[
{
"thread": {
"id": 51,
"name": "worker-A",
"state": "BLOCKED",
"daemon": false,
"priority": 5
},
"waitingOnLock": {
"name": "java.lang.Object@4a1f5b2",
"ownerThreadId": 52,
"ownerThreadName": "worker-B"
},
"stackTrace": ["com.example.Worker.run(Worker.java:42)"],
"lockedMonitors": [
{
"className": "java.lang.Object",
"identityHashCode": 777123,
"lockedStackDepth": 1,
"lockedStackFrame": "com.example.Worker.run(Worker.java:40)"
}
],
"lockedSynchronizers": [
{
"className": "java.util.concurrent.locks.ReentrantLock$NonfairSync",
"identityHashCode": 998877
}
]
}
]
CacheTools
| Tool | Description |
|---|---|
cache_get_all
| All registered cache providers with stats, configuration, status |
cache_get_names
| Cache provider names only |
cache_get_stats
| Detailed cache stats: hits, misses, evictions, performance ratio |
cache_get_keys
| All keys stored in a specific cache |
cache_get_size
| Number of elements in a specific cache |
cache_get_key_metadata
| Metadata for a specific cached object |
cache_has_key
| Check if a key exists in a cache |
cache_get_store_metadata
| Full store metadata report for a cache |
cache_clear
| Clear all elements from a specific cache |
cache_clear_item
| Remove a specific item from a cache |
cache_reap
| Reap (clean up expired entries) from a cache |
cache_clear_stats
| Reset hit/miss/eviction counters for a cache |
cache_clear_all
| Clear all elements from every registered cache |
cache_reap_all
| Reap expired entries from every registered cache |
cache_get_health
| Structured health assessment: status, score, issues with codes per cache |
DatasourceTools
| Tool | Description |
|---|---|
datasource_get_all
| All registered datasources with configurations and pool metrics |
datasource_get_names
| Datasource names only |
datasource_get
| Single datasource details with pool metrics |
datasource_has
| Check if a datasource is registered |
datasource_get_pool_metrics
| Connection pool metrics: active, idle, total connections, wait times |
datasource_get_config
| Datasource configuration (passwords masked) |
datasource_test
| Test a datasource connection; returns success/failure with timing |
datasource_get_health
| Structured health assessment: status, score, per-datasource pool utilization issues |
datasource_get_pool_latency
| Connection pool latency histograms:
acquire/usage/creation p50/p95/p99/max/count + timeout count.
Requires enablePoolLatencyTracking: true. |
SQLTools
| Tool | Description |
|---|---|
sql_get_slow_queries
| Recent captured slow query samples with optional limit and since filter |
sql_get_query_stats
| Aggregate slow query statistics by original SQL and datasource |
sql_clear
| Clear all captured slow-query samples and statistics |
sql_get_config
| Current slow SQL collector configuration |
sql_set_config
| Update slow SQL collector configuration at runtime |
SlowHttpTools
| Tool | Description |
|---|---|
slow_http_get_calls
| Recent captured slow outbound HTTP/SOAP call samples with optional limit and since filter |
slow_http_get_stats
| Aggregate slow call statistics by destination host (count, average latency, max latency) |
slow_http_clear
| Clear all captured slow-call samples and statistics |
slow_http_get_config
| Current slow HTTP collector configuration |
slow_http_set_config
| Update slow HTTP collector configuration at runtime |
RequestsTools
| Tool | Description |
|---|---|
requests_get_slow_requests
| Recent captured slow request samples with optional limit and since filter |
requests_get_stats
| Aggregate slow-request statistics and collector configuration |
requests_get_config
| Current slow request collector configuration |
requests_set_config
| Update slow request collector threshold, buffer size, and stack capture setting at runtime |
requests_clear
| Clear all captured slow-request samples and counters |
RouteMetricsTools
| Tool | Description |
|---|---|
routes_get_all
| Per-route request metrics sorted by count, error rate, p99, or last seen time |
routes_get_route
| Detailed metrics for a single route by its exact key
(e.g. GET /api/users/{id}) |
routes_get_summary
| Aggregate summary: total requests, error rate, route count, top-5 slowest routes by p99 |
routes_get_config
| Current route metrics collector configuration |
routes_set_config
| Update route metrics collector config at runtime (maxRoutes, normalizePathParams) |
routes_clear
| Clear all accumulated route metrics data |
PerformanceTools
| Tool | Description |
|---|---|
performance_get_snapshot
| Single round-trip snapshot of memory, garbage collection, CPU, threads, top memory pools, top executors, slow queries, slow requests, slow HTTP/SOAP calls, buffer pools, optional web server metrics, and a structured health report |
SystemTools
| Tool | Description |
|---|---|
system_get_health
| Unified health across all subsystems: datasources, caches, watchers, schedulers, executors, web server. Returns a consolidated structured report with overall status, score, and merged issues |
AsyncTools
| Tool | Description |
|---|---|
executor_get_all
| All registered async executors with status, pool info, task stats |
executor_get_names
| Executor names only |
executor_get_info
| Detailed executor info: type, status, configuration |
executor_get_stats
| Pool utilization, queue status, task counts, health metrics |
executor_get_health
| Structured health report: status, score, per-executor issues with codes |
executor_get_health_summary
| Structured health summary across all executors with status and score |
SchedulerTools
| Tool | Description |
|---|---|
scheduler_get_all
| All registered schedulers with configurations and tasks |
scheduler_get_names
| Scheduler names only |
scheduler_get
| Single scheduler details including tasks and records |
scheduler_has
| Check if a scheduler is registered |
scheduler_get_task_stats
| Execution statistics for a specific task |
scheduler_get_task_info
| Task details: configuration and metadata |
scheduler_get_all_tasks
| All tasks across all schedulers |
scheduler_run_task
| Force-run a scheduled task immediately |
scheduler_pause_task
| Pause a scheduled task |
scheduler_resume_task
| Resume a paused scheduled task |
scheduler_pause_persisted_task
| Pause a disk-persisted task (updates tasks.json) |
scheduler_resume_persisted_task
| Resume a disk-persisted task |
scheduler_pause_all_persisted_tasks
| Pause all disk-persisted tasks (filterable by scheduler/group) |
scheduler_resume_all_persisted_tasks
| Resume all disk-persisted tasks |
scheduler_get_health
| Structured health assessment: status, score, per-scheduler issues |
scheduler_get_all_task_stats
| Task stats summary across all schedulers |
scheduler_get_persisted_tasks
| All scheduled tasks persisted on disk (tasks.json) |
ModuleTools
| Tool | Description |
|---|---|
module_get_all
| All registered modules with configuration and status |
module_get_names
| Module names only |
module_get_info
| Full configuration and status for a specific module |
module_get_settings
| Settings for a specific module |
module_get_paths
| Registered module search paths |
module_reload
| Reload a specific module (unload, re-register, re-activate) |
module_reload_all
| Reload all registered modules |
module_has
| Check if a module is registered |
module_get_stats
| Module statistics: total count, activated, enabled, etc. |
InterceptorTools
| Tool | Description |
|---|---|
interceptor_get_points
| All registered interception point names (sorted) |
interceptor_has_point
| Check if a specific interception point is registered |
interceptor_get_states
| All interceptor states with listener counts |
interceptor_get_state
| Listener count for a specific event |
interceptor_get_summary
| Registry totals, active states, events with most listeners |
ApplicationTools
| Tool | Description |
|---|---|
app_get_names
| Active application names |
app_get_all
| All active applications: start times, session counts, class loader counts, expiry status |
app_get
| Full runtime details: session cache metadata, application scope keys, class loaders, uptime |
app_has
| Check if an application is active |
app_get_summary
| Summary: totals, session load, expired apps in registry |
app_stop
| Shut down a running application by name |
app_restart
| Restart a named application, picking up config/code changes |
app_sessions_clear
| Clear all sessions for an application (logs out all users) |
LoggingTools
| Tool | Description |
|---|---|
logging_get_info
| Log directory, logger count, appender count |
logging_get_config
| Log levels, appenders, retention policies |
logging_get_loggers
| All registered loggers with names and appenders |
logging_get_logger
| Details for a specific logger |
logging_get_root_logger
| Root logger details and attached appenders |
logging_get_appenders
| All registered appenders: file paths, types, configuration |
logging_read_entries
| Last N log entries from a log file |
logging_get_last_error
| Most recent ERROR or FATAL entry from a logger |
logging_search_entries
| Search log entries by keyword or pattern |
logging_log_message
| Write a test log message (verify logging works) |
HttpTools
| Tool | Description |
|---|---|
http_get_client_count
| Number of active HTTP clients |
http_get_client_names
| HTTP client keys |
http_get_clients
| Per-client stats: connection counts, request counts, error rates |
http_get_soap_clients
| Per-WSDL SOAP client usage details |
http_get_executor
| HTTP executor thread pool status and configuration |
http_get_service_summary
| Consolidated HTTP service summary |
WatcherTools
| Tool | Description |
|---|---|
watcher_get_all
| All registered filesystem watchers with configuration and state |
watcher_get_names
| Watcher names only |
watcher_get
| Single watcher details |
watcher_has
| Check if a watcher is registered |
watcher_get_stats
| Watcher execution statistics |
watcher_start
| Start a stopped watcher |
watcher_stop
| Stop a running watcher |
watcher_restart
| Restart a watcher |
watcher_remove
| Remove a watcher from the registry and stop it |
watcher_get_health
| Structured health assessment: status, score, per-watcher errors |
UndertowTools
| Tool | Description |
|---|---|
undertow_get_stats
| Undertow web server statistics: worker pool (core/max/current/busy/queue), IO pool, listener connection/request/error counts, active requests, WebSocket connections |
undertow_get_health
| Structured health assessment: status, score, worker saturation, queue depth, listener error rates with issue codes |
These tools auto-detect the deployment mode — BoxLang MiniServer,
Runwar/CommandBox, or generic Undertow via JMX — and return rich
metrics regardless of which Undertow-based server is running. Worker
pool data comes from the XnioWorkerMXBean; listener and
request-level metrics are available on MiniServer and Runwar. On
non-Undertow deployments, the tools return { available: false }.
All health tools return a consistent structured report that enables clients to rank, filter, and reason about runtime health programmatically.
{
"status": "healthy",
"score": 85,
"issues": [
{
"severity": "warning",
"code": "DS_POOL_HIGH_UTILIZATION",
"message": "Datasource 'mainDB' pool is under high load at 87% (28/32 active)",
"suggestedAction": "Monitor pool utilization and consider increasing pool size",
"entity": "mainDB",
"entityMetrics": { "utilization": 87, "active": 28, "max": 32 }
}
],
"scoreBreakdown": {
"base": 100,
"deductions": [
{ "code": "DS_POOL_HIGH_UTILIZATION", "severity": "warning", "penalty": 15 }
]
}
}
| Severity | Penalty | Score Range |
|---|---|---|
| healthy | — | 80 – 100 |
| warning | 25 per issue | 50 – 79 |
| critical | 50 per issue | 0 – 49 |
| info | 5 per issue | no status change |
| Domain | Code | Severity | Trigger |
|---|---|---|---|
| Datasource | DS_POOL_NOT_STARTED
| warning | Pooling not started |
DS_POOL_HIGH_UTILIZATION
| warning | >80% utilization | |
DS_POOL_SATURATED
| critical | >=95% utilization | |
DS_POOL_THREADS_AWAITING
| warning | Waiting threads > 0 | |
| Cache | CACHE_DISABLED
| warning | Cache not enabled |
CACHE_LOW_HIT_RATE
| warning | Hit rate <30% | |
CACHE_HIGH_EVICTIONS
| warning | Evictions >= size (thrashing) | |
| Watcher | WATCHER_STOPPED
| warning | Watcher is stopped |
WATCHER_ERRORS
| warning | Consecutive errors > 0 | |
WATCHER_HIGH_ERRORS
| critical | Consecutive errors >= 10 | |
| Scheduler | SCHEDULER_NOT_STARTED
| warning | Scheduler not started |
SCHEDULER_ALL_TASKS_PAUSED
| warning | All tasks paused | |
| Web Server | WEB_WORKER_SATURATED
| critical | Worker pool saturated |
WEB_WORKER_HIGH_LOAD
| warning | >=80% utilization | |
WEB_QUEUE_HIGH
| critical | Queue > 50% of max | |
WEB_LISTENER_HIGH_ERROR_RATE
| warning | Error rate >5% | |
WEB_HIGH_CONNECTION_RATIO
| info | Connections >> workers | |
| Executor | EXECUTOR_UNHEALTHY
| critical | Shutdown/terminated/critical |
EXECUTOR_DEGRADED
| warning | Degraded/draining/idle | |
EXECUTOR_NEAR_SATURATION
| warning | High saturation score | |
| Performance | JVM_HEAP_CRITICAL
| critical | Heap >95% |
JVM_HEAP_PRESSURE
| warning | Heap >85% | |
JVM_BLOCKED_THREADS
| warning | Blocked threads > 0 | |
PERF_SLOW_QUERIES
| info | Slow queries present | |
PERF_SLOW_REQUESTS
| info | Slow requests present | |
PERF_SLOW_HTTP
| info | Slow HTTP calls present |
The system_get_health tool calls every subsystem health
endpoint in a single round-trip and returns:
{
"status": "warning",
"score": 65,
"issues": [
{ "code": "executors:EXECUTOR_DEGRADED", "severity": "warning", ... }
],
"subsystems": {
"datasources": { "status": "healthy", "score": 100, "issues": [], ... },
"caches": { "status": "warning", "score": 85, "issues": [...], ... },
"watchers": { "status": "healthy", "score": 100, "issues": [], ... },
"schedulers": { "status": "healthy", "score": 100, "issues": [], ... },
"executors": { "status": "warning", "score": 65, "issues": [...], ... },
"webServer": { "status": "healthy", "score": 100, "available": true, ... }
},
"scoreBreakdown": {
"base": 100,
"subsystems": [
{ "subsystem": "datasources", "score": 100, "status": "healthy" },
...
]
}
}
The overall score is the minimum subsystem score (weakest-link
model). Issue codes are prefixed with the subsystem name (e.g.,
executors:EXECUTOR_DEGRADED) so clients can filter by domain.
The server registers pre-built MCP prompts that guide AI clients through common diagnostic and administrative workflows. Each prompt instructs the AI agent which tools to call and in what order, and provides system-level context for interpreting results.
| Prompt | Description | Arguments |
|---|---|---|
runtime_health_check
| Comprehensive health check: memory, caches, datasources, executors, modules | — |
full_system_audit
| End-to-end audit of every subsystem (JVM, threads, web server, caches, datasources, modules, schedulers, executors, logging, watchers) | — |
performance_troubleshooting
| Interactive diagnostic guide for a given symptom (slow responses, high memory, CPU spikes, thread pool exhaustion) | symptom
(required)
|
diagnose_memory_pressure
| JVM memory diagnosis: heap, non-heap, pools, GC activity; identifies leaks and misconfiguration | threshold
(optional, default: 80)
|
executor_saturation_check
| Async executor pool saturation, queue buildup, and rejected tasks | — |
deployment_validation
| Validate a deployment after a new release or module update: confirms runtime started cleanly, expected modules loaded, datasources reachable, executor pools healthy, and web server accepting traffic | expectedModules
(optional)
|
| Prompt | Description | Arguments |
|---|---|---|
analyze_cache_performance
| Cache hit rates, eviction patterns, sizing; optionally focus on a named cache | cacheName
(optional)
|
datasource_health_report
| Datasource connectivity, connection pool utilization, configuration audit | — |
slow_sql_diagnosis
| Identify and diagnose slow SQL queries: patterns, datasource hotspots, and tuning recommendations | limit
(optional, default: 50)
|
slow_http_diagnosis
| Identify and diagnose slow outbound HTTP/SOAP calls: destination host hotspots, error-prone integrations, timeout and connection pool tuning recommendations | limit
(optional, default: 50)
|
| Prompt | Description | Arguments |
|---|---|---|
thread_dump_analysis
| JVM thread dump: identifies deadlocks, blocked threads, pool saturation, long-running operations | — |
investigate_errors
| Recent log error investigation: patterns, root causes, fixes | loggerName, keyword
(optional)
|
logging_infrastructure_review
| Logging infrastructure audit: log levels, appenders, recent error patterns | — |
class_loader_diagnostics
| Class loader health: resolver cache, loader count, deployment mode, runtime home | — |
jvm_resource_audit
| OS-level JVM resource audit: file descriptors, disk space on all volumes, CPU load, key system properties — capacity planning and resource leak detection | — |
cpu_profiling
| Live CPU profiling via hot-thread and allocation-heavy-thread sampling over a configurable window; correlates with GC activity and thread dumps | durationMs
(optional, default: 3000), topN
(optional, default: 10)
|
| Prompt | Description | Arguments |
|---|---|---|
module_audit
| All registered modules: status, version, BIFs, components, interceptors, configuration | — |
interceptor_registry_audit
| Interceptor/event system: registered points, listener counts, coverage gaps | — |
scheduler_status_report
| Scheduler task execution history, upcoming runs, failures | schedulerName
(optional)
|
application_lifecycle_status
| All active applications: uptime, session counts, expired apps, load indicators | — |
http_connectivity_audit
| Outbound HTTP and SOAP client activity: connections, pool usage, errors | — |
file_watcher_health
| File watcher health check: running vs. stopped state, events processed, error counts; flags stalled or failing watchers | — |
| Prompt | Description | Arguments |
|---|---|---|
web_server_diagnostics
| Deep-dive Undertow diagnostics: worker thread pool saturation, IO pool, active/queued requests, listener stats, WebSocket connections | — |
slow_request_analysis
| Identify slow inbound HTTP requests: correlates captured samples with per-route metrics to surface worst-performing endpoints | limit
(optional, default: 50)
|
route_performance_analysis
| Per-route HTTP performance: identify slowest and highest-traffic endpoints, error rates, prioritized optimization backlog | sortBy
(optional, default: avgLatency), limit
(optional, default: 20)
|
| Prompt | Description | Arguments |
|---|---|---|
bif_component_discovery
| Explore available BIFs and components; search by keyword | keyword
(optional)
|
application_debug_assistant
| Targeted debug assistant for a specific application: lifecycle state, log errors, datasource health, cache stats, thread context | appName
(required)
|
| Prompt | Description | Arguments |
|---|---|---|
incident_triage
| Rapid incident triage: scan errors, threads, memory, web server, datasources, and executors to identify what's broken right now | — |
error_spike_response
| Error spike response: correlate timing, identify blast radius, and recommend containment actions | keyword
(optional)
|
cascade_failure_diagnosis
| Cascade failure diagnosis: trace failure chains across subsystems (datasource timeout → thread saturation → request queuing) | — |
rollback_decision
| Rollback decision: structured go/no-go comparison of current state vs. deployment baseline | expectedModules
(optional)
|
post_incident_review
| Post-incident review: collect timeline, identify impact, determine root cause, and generate improvement actions | keyword
(optional)
|
Once installed, the MCP server is available at
http://localhost:8080/~bxmcp/boxlang.bxm. Configure your
MCP client (Claude Desktop, Cursor, VS Code, etc.) to connect to this endpoint.
{
"mcpServers": {
"boxlang": {
"url": "http://localhost:8080/~bxmcp/boxlang.bxm",
"headers": {
"Authorization": "Bearer your-auth-token"
}
}
}
}
You can also configure it in your VSCode workspace by creating a
.vscode/mcp.json file with the following content:
{
"mcpServers": {
"boxlang-mcp": {
"url": "http://localhost:8080/~bxmcp/boxlang.bxm",
"headers": {
"Authorization": "Bearer your-auth-token"
}
}
}
}
Replace
your-auth-tokenwith the value ofauthTokenfrom your module settings. IfauthTokenis empty, omit theheadersblock.
Selectively expose only the tools you need:
{
"modules": {
"bxmcp": {
"settings": {
"includedTools": [
"runtime_get_info",
"jvm_get_memory_info",
"scheduler_get_all"
]
}
}
}
}
Or use glob patterns to expose entire categories:
{
"modules": {
"bxmcp": {
"settings": {
"includedTools": ["jvm*", "runtime_get_info", "datasource_get_health"]
}
}
}
}
Or exclude sensitive admin tools:
{
"modules": {
"bxmcp": {
"settings": {
"includedTools": ["*"],
"excludedTools": [
"cache_clear_all",
"module_reload_all",
"app_stop"
]
}
}
}
}
You are not limited to the built-in introspection tools. Any module
or application can register its own tools, resources, and prompts into
the BoxLang MCP server at runtime using the bx-ai BIF
mcpServer( "boxlang" ).
// Get the BoxLang MCP server instance
var server = mcpServer( "boxlang" )
// Register a simple tool with a handler
server.registerTool(
aiTool(
"check_deployment_status",
"Check the current deployment status of the application",
( environment ) => {
var status = deploymentService.getStatus( environment )
return {
environment: arguments.environment,
version: status.version,
deployedAt: status.deployedAt.toString(),
healthy: status.healthy
}
}
)
.addParameter(
aiToolParam( "environment", "string", "The deployment environment to check (e.g., staging, production)" )
.required()
)
)
mcpServer( "boxlang" ).registerPrompt(
"deployment_health_check",
"Check the health of the current deployment by analyzing application status and recent logs",
( args ) => [
{
role: "system",
content: "You are a deployment operations expert. Verify the current deployment by checking the application status and analyzing recent logs."
},
{
role: "user",
content: "Check the deployment health. Use `check_deployment_status` for the '#args.environment ?: 'production'#' environment and `get_last_error` from the logging tools."
}
],,
[
{ name: "environment", description: "The deployment environment to check", required: false }
]
)
The server supports several registration patterns:
server.scan(
"myapp.tools" ) to auto-discover methods
annotated with @mcpTool
aiTool()
objects and register them individually or as an array via
server.registerTools( [...] )
You can also access any existing tool by name:
var tool = mcpServer( "boxlang" ).getTool( "runtime_get_info" )
writeOutput( tool.getDescription() )
The ideal time to register custom tools is your application or module
startup code. For your application you can use the
onApplicationStart lifecycle method, and for modules you
can use the onLoad method in your module's main class.
This ensures your tools are available as soon as the MCP server is
active. If you are in a ColdBox application, you can also register
them in your config/ColdBox.cfc in the
configure() method, or in the
onApplicationStart handler.
mcpServer( "boxlang" )
.registerTool( aiTool( "my_custom_tool", "Description", handler ) )
The module ships with a built-in interactive CLI client that connects to any MCP server endpoint. Launch it from the BoxLang CLI:
boxlang bxmcp [url] [--timeout=ms] [--token=bearer] [--help]
| Argument | Description |
|---|---|
url
| The MCP server endpoint URL (optional — will prompt if omitted) |
--timeout=ms
| Request timeout in milliseconds (default: 30000) |
--token=bearer
| Bearer token for authenticated MCP servers |
--help, -h
| Show the help message |
# Launch interactively — prompts for URL
boxlang bxmcp
# Connect to a local BoxLang MCP server
boxlang bxmcp http://localhost:8080/~bxmcp/index.bxm
# With authentication and custom timeout
boxlang bxmcp http://localhost:8080/~bxmcp/index.bxm --timeout=5000 --token=secret123
Once connected, the CLI provides tab completion and the following commands:
| Command | Description |
|---|---|
help, ?
| Show available commands and syntax |
connect
| Re-run the connection handshake |
tools
| List all available MCP tools (cached) |
prompts
| List all available MCP prompts (cached) |
resources
| List all available MCP resources (cached) |
run <tool> [args]
| Invoke a tool by name with optional JSON arguments |
prompt <name> [args]
| Get a prompt by name with optional arguments |
resource <uri>
| Read a resource by URI |
stats
| Display MCP client connection statistics |
clear
| Clear the terminal screen |
watch <tool> [interval]
| Poll a tool every N seconds (default 5) until interrupted |
exit, quit, q
| Disconnect and exit |
The CLI uses BoxLang's MiniConsole with a modular design:
| Component | File | Purpose |
|---|---|---|
MCPConsole
| cli/MCPConsole.bx
| Interactive shell loop, command dispatch, MiniConsole integration |
MCPCommandParser
| cli/MCPCommandParser.bx
| Tokenizes input into command + target + JSON arguments |
MCPResponseFormatter
| cli/MCPResponseFormatter.bx
| Pretty-prints tables, JSON, errors, banners, stats with ANSI styling |
MCPSpinner
| cli/MCPSpinner.bx
| ASCII spinner animation during blocking MCP calls |
MCPTabProvider
| cli/MCPTabProvider.bx
| Tab completion for commands, cached tool/prompt/resource names |
All interactions use JSON-RPC 2.0 over HTTP POST to /~bxmcp/boxlang.bxm.
Replace
http://localhost:8080with your server URL. AddAuthorization: Bearer {token}ifauthTokenis configured.
curl -s http://localhost:8080/~bxmcp/boxlang.bxm \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/list","id":"1"}' | jq '.result.tools[] | {name, description}'
curl -s http://localhost:8080/~bxmcp/boxlang.bxm \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"runtime_get_info","arguments":{}},"id":"2"}' | jq '.result.content[0].text | fromjson'
curl -s http://localhost:8080/~bxmcp/boxlang.bxm \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"jvm_get_memory_info","arguments":{}},"id":"3"}' | jq '.result.content[0].text | fromjson'
curl -s http://localhost:8080/~bxmcp/boxlang.bxm \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"jvm_get_thread_dump","arguments":{}},"id":"4"}' | jq '.result.content[0].text | fromjson'
curl -s http://localhost:8080/~bxmcp/boxlang.bxm \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"jvm_get_deadlocks","arguments":{}},"id":"5"}' | jq '.result.content[0].text | fromjson'
curl -s http://localhost:8080/~bxmcp/boxlang.bxm \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"cache_get_health","arguments":{}},"id":"6"}' | jq '.result.content[0].text | fromjson'
curl -s http://localhost:8080/~bxmcp/boxlang.bxm \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"datasource_get_health","arguments":{}},"id":"7"}' | jq '.result.content[0].text | fromjson'
curl -s http://localhost:8080/~bxmcp/boxlang.bxm \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"datasource_test","arguments":{"dsn":"mainDB"}},"id":"8"}' | jq '.result.content[0].text | fromjson'
curl -s http://localhost:8080/~bxmcp/boxlang.bxm \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"module_get_all","arguments":{}},"id":"9"}' | jq '.result.content[0].text | fromjson'
curl -s http://localhost:8080/~bxmcp/boxlang.bxm \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"logging_search_entries","arguments":{"loggerName":"runtime","keyword":"error","limit":20}},"id":"10"}' | jq '.result.content[0].text | fromjson'
curl -s http://localhost:8080/~bxmcp/boxlang.bxm \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"scheduler_get_all","arguments":{}},"id":"11"}' | jq '.result.content[0].text | fromjson'
Tip: Pipe through
jqto extract and parse the JSON response. The MCP server wraps tool results insideresult.content[0].textas a JSON-encoded string.
curl -s http://localhost:8080/~bxmcp/boxlang.bxm \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"prompts/get","params":{"name":"full_system_audit","arguments":{}},"id":"11"}' | jq '.result.messages'
Copyright Since 2023 by Ortus Solutions, Corp
www.boxlang.io | www.ortussolutions.com
BoxLang is a professional open-source project and it is completely funded by the community and Ortus Solutions, Corp. Ortus Patreons get many benefits like a cfcasts account, a FORGEBOX Pro account and so much more. If you are interested in becoming a sponsor, please visit our patronage page: https://patreon.com/ortussolutions
"I am the way, and the truth, and the life; no one comes to the Father, but by me (JESUS)" Jn 14:1-12
statusCounts and 5xx-only serverErrorRate instead of the previous combined errorCount/errorRate fields.undertow_get_stats, undertow_get_health) — worker pool, listener, request metrics, WebSocket connections with MiniServer/Runwar/JMX fallback detectionsql_get_slow_queries, sql_get_query_stats, sql_set_config, sql_clear) via new SlowJDBCCollector Java interceptorrequests_get_slow_requests, requests_get_stats, requests_set_config, requests_clear) via SlowRequestCollector interceptorslow_http_get_calls, slow_http_get_stats, slow_http_clear) via SlowHttpCollector interceptorroutes_get_all, routes_get_route, routes_get_summary) with count, status-class counts, server error rate, and p50/p95/p99 latency histograms via RouteMetricsCollector interceptordatasource_get_pool_latency) with bucket-based tracking via PoolLatencyTrackersystem_get_health) — consolidated datasource, cache, watcher, scheduler, executor, and web server health in one callperformance_get_snapshot) — combined memory, GC, threads, executors, slow queries/requests, buffer pools, and web server statsjvm_get_hot_threads, jvm_get_top_allocators, jvm_get_deadlocks, jvm_get_cpu_info, jvm_get_gc_info, jvm_trigger_gc, jvm_trigger_heap_dump, jvm_get_class_loading_info, jvm_get_runtime_info, jvm_get_system_properties, jvm_get_environment_variables, jvm_get_operating_system_info, jvm_get_file_descriptors, jvm_get_disk_usagecache_get_all, cache_get_names, cache_get_stats, cache_get_keys, cache_get_size, cache_get_key_metadata, cache_has_key, cache_get_store_metadata, cache_clear, cache_clear_itemdatasource_get_all, datasource_get_names, datasource_get, datasource_has, datasource_get_pool_metrics, datasource_get_config, datasource_test, datasource_get_healthlogging_get_info, logging_get_config, logging_get_loggers, logging_get_logger, logging_get_root_logger, logging_get_appenders, logging_read_entries, logging_get_last_error, logging_search_entries, logging_log_messageexecutor_get_all, executor_get_names, executor_get_info, executor_get_stats, executor_get_health, executor_get_health_summaryruntime_get_license_status, runtime_get_config, runtime_get_config_value, runtime_config_diff, runtime_get_bif_summary, runtime_get_bif_info, runtime_search_bifs, runtime_get_component_summary, runtime_get_component_info, runtime_search_components, runtime_get_global_services, runtime_toggle_debug_mode, runtime_get_class_resolver_info, runtime_clear_system_cache, runtime_clear_page_pooladmin (full access) and readonly (get/has/search/read only) profiles, plus custom named profiles with glob patternsauthToken supports simple string, profile-referenced, or inline per-token includedTools/excludedTools glob arraysdatasource_get_pool_metrics and datasource_get_health NoSuchMethod on HikariPoolget_memory_info → jvm_get_memory_info, get_all_datasources → datasource_get_all)* and ?)BasePrompt subclassesauthToken setting now supports string, profile array, or inline glob array formatsslowSQL, slowRequests, slowHTTP, enablePoolLatencyTracking, and heapDumpDir settingsbxmcp-tool-development skill
$
box install bx-mcp