mcp-server
This server provides tools to inspect and troubleshoot IBM Liberty / WebSphere application servers over SSH:
Read Configuration (
read_config): Connects over SSH to retrieve sanitized application configuration files (server.xml, jvm.options, server.env, bootstrap.properties, and referenced .properties) with sensitive values (passwords, tokens, secrets, API keys) automatically redacted.Health Check (
health_check): Performs an HTTP health probe (via curl/wget/python3) against the application on localhost and verifies the Java process is running viaps -ef— works without root access or JDK tools.List Logs (
list_logs): Enumerates all log files under the application'slogs/directory with size, modification time, and category (e.g., messages.log, console.log, trace.log, FFDC files) to inform targeted analysis.Analyze Logs (
analyze_logs): Searches log files for specified strings or exception names with context lines; supports optional time-range filtering, targeted file selection, and automatic skipping of large files (~25MB) to minimize overhead.Check Connectivity (
check_connectivity): Resolves DNS and probes TCP reachability to a list of host:port targets (e.g., databases, LDAP), checking each resolved IP individually to detect partial failures.Check Resources (
check_resources): Monitors disk usage (space and inodes) for deployment and temporary directories, memory/swap usage, and the application process's open file descriptor count against its ulimit.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-serverhealth check myapp on 10.0.1.25 port 9080"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-server
An MCP server for inspecting IBM Liberty / WebSphere-style application servers over SSH — reading config with secrets redacted, checking whether an app is actually up, searching its logs, and checking outward connectivity and on-box resource pressure for triage.
Tools
read_config
Connects to a remote server over SSH and returns its application config as sanitized text.
Arguments
Name | Type | Description |
| string | Hostname or IP address of the server to connect to over SSH. |
| string | SSH username to authenticate as. |
| string | Path to the private key file (on the machine running this MCP server) used for authentication. |
| string | Base deployment directory containing the application folder. |
| string | Name of the application subfolder to read config from. |
What it does
Opens an SFTP session to
server_ipasos_user, authenticating withssh_key. Strict host key checking is disabled (StrictHostKeyChecking=noequivalent) — unknown hosts are auto-accepted rather than requiring aknown_hostsentry. This trades off protection against man-in-the-middle attacks for not having to pre-seedknown_hostsfor every target server.Looks in
<deployment_directory>/<application>/on that server.Reads
server.xml.Scans
server.xmlfor<include location="...">references and any*.propertiesfile references, and reads those too.Always also reads (if present):
jvm.options,server.env,bootstrap.properties.Redacts values associated with sensitive keys —
password,secret,token,apikey,credential, etc. — in bothkey=valuestyle (properties files,.env,-DJVM options) and XML attribute style, including Liberty's<variable name="db.password" value="..."/>pattern where the keyword and the secret live in separate attributes.Returns a single JSON object with the sanitized content of every file found (and a not-found/error note for anything missing).
References that would resolve outside the application directory (e.g. path
traversal via ../../) or that depend on an unresolved ${variable} are
skipped rather than followed.
Note: only the SSH key path is ever passed to the tool — key material itself never flows through the LLM or tool-call history.
Example result shape
{
"server": "10.0.1.25",
"application_directory": "/opt/liberty/deployments/myapp",
"files": [
{ "path": "server.xml", "found": true, "content": "..." },
{ "path": "jvm.options", "found": true, "content": "..." },
{ "path": "server.env", "found": true, "content": "..." },
{ "path": "bootstrap.properties", "found": true, "content": "..." },
{ "path": "vars/extra.properties", "found": true, "content": "..." }
]
}health_check
Connects to a remote server over SSH and reports whether an IBM Liberty app
is healthy: an HTTP probe plus a process check. Built for locked-down
targets — assumes a non-root SSH user with no access to root-owned
paths, and no JDK installed, so it never shells out to jps, jcmd,
or bin/server status.
Arguments
Name | Type | Description |
| string | Hostname or IP address of the server to connect to over SSH. |
| string | SSH username to authenticate as. |
| string | Path to the private key file (on the machine running this MCP server) used for authentication. |
| integer | Local port the application listens on. |
| string | URI path to request for the HTTP health check (e.g. |
| string | Application/server name to look for among running processes. |
What it does
Opens one SSH session to
server_ipasos_userand runs two small shell scripts on the remote host (no local files needed, nosudo):HTTP check: requests
http://127.0.0.1:<port><uri>using whichever ofcurl,wget, orpython3is present on the target, in that order. If none are available it reports that rather than guessing.Process check: greps
ps -effor a line containing bothjavaandapplication, since Liberty runs as a plain JVM process and there's no JDK on the box to ask it directly.
Returns HTTP reachability + status code + a healthy/unhealthy verdict (2xx/3xx counts as healthy), and process running/not-running + PID.
Example result shape
{
"server": "10.0.1.25",
"application": "myapp",
"http": { "reachable": true, "status_code": 200, "healthy": true, "detail": "HTTP 200" },
"process": { "running": true, "pid": "25579", "detail": "501 25579 ... java ... myapp ..." }
}list_logs
Connects over SSH and enumerates every file under
<deployment_directory>/<application>/logs/ — Liberty's own
messages.log, console.log, trace.log, ffdc/*, plus whatever an
application itself writes into subdirectories there. Meant to be called
before analyze_logs so an LLM can pick which files are actually relevant
instead of blindly grepping everything (trace.log especially can be huge).
Arguments
Name | Type | Description |
| string | Hostname or IP address of the server to connect to over SSH. |
| string | SSH username to authenticate as. |
| string | Path to the private key file (on the machine running this MCP server) used for authentication. |
| string | Base deployment directory containing the application folder. |
| string | Name of the application subfolder whose |
Example result shape
{
"server": "10.0.1.25",
"logs_directory": "/opt/liberty/deployments/myapp/logs",
"files": [
{ "path": "messages.log", "size_bytes": 827, "modified": "2026-07-28T00:45:10+00:00", "category": "liberty_core" },
{ "path": "trace.log", "size_bytes": 111, "modified": "2026-07-28T00:10:00+00:00", "category": "liberty_core" },
{ "path": "ffdc/com.ibm.ws.webcontainer_exception_...txt", "size_bytes": 178, "modified": "2026-07-28T00:15:32+00:00", "category": "ffdc" },
{ "path": "myapplogs/app-2026-07-28.log", "size_bytes": 174, "modified": "2026-07-28T00:50:00+00:00", "category": "app_or_other" }
]
}analyze_logs
Connects over SSH and greps the app's logs for given strings/exception names, returning matches with surrounding context.
Arguments
Name | Type | Description |
| string | Hostname or IP address of the server to connect to over SSH. |
| string | SSH username to authenticate as. |
| string | Path to the private key file (on the machine running this MCP server) used for authentication. |
| string | Base deployment directory containing the application folder. |
| string | Name of the application subfolder whose |
| list of strings | Strings or exception names to search for (case-insensitive, literal match). |
| string, optional | ISO-8601 timestamp; matches before this are excluded when a timestamp is detected. |
| string, optional | ISO-8601 timestamp; matches after this are excluded when a timestamp is detected. |
| list of strings, optional | Paths relative to |
What it does
If
log_filesisn't given, discovers every file underlogs/(capped at 300 files) and skips any over ~25MB — those get reported back underskipped_filesrather than silently ignored, so the LLM knows to pass them explicitly vialog_filesif they're actually needed.If
start_timeis given, skips whole files whose last-modified time predates it (log files are append-only, so an untouched-since-start_timefile can't contain anything newer).Greps the target files for the given terms and groups matches into context blocks. Files are searched in batches of up to 50 per SSH exec call (one remote command greps every file in the batch, with an internal marker separating each file's output) rather than one exec call per file — this cuts SSH round-trips from roughly N+2 down to roughly ⌈N/50⌉+2 for a directory of N log files, which matters most for the unscoped default search across many files.
For each block, tries to find a timestamp — Liberty's basic format (
[7/28/26 0:15:32:123 UTC]), Liberty's JSON format ("ibm_datetime"), or generic ISO-8601 for arbitrary app logs — anchored on the actually matched line (not just the first line of the context block). If found and outside[start_time, end_time], the block is dropped; if no timestamp can be parsed, the block is kept rather than silently discarded — stack traces and multi-line messages don't repeat their header's timestamp, and hiding potentially-relevant lines is worse than including a few extra ones.
Example result shape
{
"server": "10.0.1.25",
"logs_directory": "/opt/liberty/deployments/myapp/logs",
"search": ["NullPointerException"],
"results": [
{
"file": "messages.log",
"timestamp": "2026-07-28T00:15:32.123000",
"lines": [
"2-[7/28/26 0:15:32:123 UTC] ... E SRVE0777E: Exception thrown by application class",
"3:java.lang.NullPointerException: Cannot invoke method on null object",
"4-\tat com.example.myapp.Service.process(Service.java:42)"
]
}
],
"truncated": false,
"skipped_files": []
}check_connectivity
Connects over SSH and, for each host:port dependency target, resolves DNS
and probes TCP reachability — the practical, non-root substitute for a
firewall-rule dump (inspecting actual iptables/firewalld rules would
need privileges these deployments don't have; a connect attempt reports
almost everything a rule dump would for triage purposes: reachable, refused,
or timed out).
Arguments
Name | Type | Description |
| string | Hostname or IP address of the server to connect to over SSH. |
| string | SSH username to authenticate as. |
| string | Path to the private key file (on the machine running this MCP server) used for authentication. |
| list of strings |
|
What it does
Targets are supplied explicitly by the caller rather than auto-discovered from config — parsing every hostname out of
server.xml/datasource URLs/JVM options reliably would need meaningfully more logic (variable resolution, JDBC/endpoint URL parsing), and a missed dependency here is worse than a missed log line: overlooking the one host that's actually down during an incident is worse than a slightly less convenient tool.For each target, resolves DNS via
getent hosts(no root required, no dependency ondig/nslookupbeing installed) and filters to IPv4 addresses only (these deployments are IPv4-only).If a hostname resolves to more than one IP — common for active-active DB replicas, LDAP pairs, or load-balanced backends — every address is probed individually, never just the hostname. Letting the shell resolve the hostname itself would silently pick one address and could report a dependency as fully healthy while one backend is actually down behind a healthy one.
Each address gets a TCP connect attempt (
/dev/tcp/<ip>/<port>via bash, nonc/telnetdependency) with a 3-second timeout, distinguishingconnected/refused/timeout/unreachable.All targets are checked within a single SSH exec call (same round-trip reasoning as the
analyze_logsbatching).
Reports two rollup fields per target because they answer different
questions: reachable (true if at least one resolved address answers
— "can the app get through at all") and fully_reachable (true only if
every resolved address answers — "is a backend silently down behind a
healthy one").
Example result shape
{
"server": "10.0.1.25",
"results": [
{
"target": "db-primary.internal:5432",
"resolved": true,
"addresses": [
{ "ip": "10.0.2.10", "reachable": true, "detail": "connected" },
{ "ip": "10.0.2.11", "reachable": false, "detail": "refused" }
],
"reachable": true,
"fully_reachable": false
},
{
"target": "ldap.corp.example:636",
"resolved": false,
"addresses": [],
"reachable": false,
"fully_reachable": false
}
],
"malformed_targets": []
}check_resources
Connects over SSH and checks disk, memory, and file-descriptor pressure on
the box — root-cause categories that often produce log lines which look
like an unrelated app bug (a NullPointerException three layers deep in
application code can be the downstream symptom of a full disk or an
exhausted fd table).
Arguments
Name | Type | Description |
| string | Hostname or IP address of the server to connect to over SSH. |
| string | SSH username to authenticate as. |
| string | Path to the private key file (on the machine running this MCP server) used for authentication. |
| string | Base deployment directory containing the application folder. |
| string | Name of the application subfolder (also used to find its process among running processes, same |
What it does
Disk — checked for exactly three filesystems, not every mounted one: the filesystem holding
<deployment_directory>/<application>(where logs/FFDC/work files actually get written),/tmp(where the JVM writes temp files by default), and/(root — a cheap sanity check if it's a distinct filesystem from the other two). Enumerating every mount would add noise from filesystems irrelevant to this app; if two of the three checks land on the same filesystem, that's visible from matchingmounted_onvalues rather than hidden. Each check reports both space (df -Pk) and inode (df -Pi) usage — a full inode table can block writes well before the disk is out of bytes (FFDC directories dump one file per failure and can exhaust inodes long before space runs low).Memory —
free -m(falling back to/proc/meminfoiffreeisn't present), reporting total/used/free/available plus swap.Process — finds the app's PID via the same
ps -efgrephealth_checkuses, then reports its open file descriptor count (/proc/<pid>/fd) against its ulimit (/proc/<pid>/limits) — "too many open files" is one of the most common real-world Liberty production failures.All of the above runs within a single SSH exec call.
Example result shape
{
"server": "10.0.1.25",
"deployment_path_checked": "/opt/liberty/deployments/myapp",
"disk": {
"deployment": {
"available": true,
"filesystem": "/dev/sda1",
"mounted_on": "/opt",
"total_mb": 40968.0,
"used_mb": 12065.0,
"available_mb": 26100.0,
"used_pct": 32,
"total_inodes": 2621440,
"used_inodes": 123456,
"available_inodes": 2497984,
"inode_used_pct": 5
},
"tmp": { "available": true, "mounted_on": "/", "used_pct": 47, "inode_used_pct": 2 },
"root": { "available": true, "mounted_on": "/", "used_pct": 47, "inode_used_pct": 2 }
},
"memory": {
"total_mb": 7982,
"used_mb": 1234,
"free_mb": 2048,
"available_mb": 6500,
"swap_total_mb": 2047,
"swap_used_mb": 0,
"swap_free_mb": 2047,
"source": "free"
},
"process": {
"found": true,
"pid": "25579",
"open_file_descriptors": 412,
"fd_soft_limit": 4096,
"fd_hard_limit": 4096,
"fd_usage_pct": 10.1
}
}Related MCP server: Linux MCP Server
Setup
Requires Python 3.11+ and uv.
git clone https://github.com/Murtaza1211/mcp-server.git
cd mcp-server
uv syncThat installs the mcp SDK and registers the mcp-server console script
(uv run mcp-server), which starts the server over stdio.
Connecting to an MCP client
Any MCP client that supports stdio servers can run this directly. The general pattern is:
command:
uvargs:
["--directory", "/absolute/path/to/mcp-server", "run", "mcp-server"]
Hermes Agent
Add to ~/.hermes/config.yaml:
mcp_servers:
server-config-reader:
command: /absolute/path/to/uv
args: ["--directory", "/absolute/path/to/mcp-server", "run", "mcp-server"]Then verify:
hermes mcp list
hermes mcp test server-config-readerhermes mcp test should report a successful connection and list
read_config, health_check, list_logs, analyze_logs,
check_connectivity, and check_resources as discovered tools.
Claude Desktop / other MCP clients
Add an equivalent entry to the client's MCP server config, e.g. for Claude
Desktop's claude_desktop_config.json:
{
"mcpServers": {
"server-config-reader": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/mcp-server", "run", "mcp-server"]
}
}
}Project layout
src/mcp_server/
server.py MCP tool registration (FastMCP)
ssh.py Shared SSH connection helper (used by every tool)
config_reader.py read_config: file discovery over SFTP, path-traversal guard
health_check.py health_check: HTTP probe + process check over SSH exec
logs.py list_logs / analyze_logs: log discovery + batched grep with time filtering
connectivity.py check_connectivity: DNS resolution (multi-IP aware) + TCP reachability probes
resources.py check_resources: disk/inode, memory/swap, and fd-vs-ulimit checks
sanitize.py Regex-based secret redactionDevelopment
uv run python -c "
from mcp_server.config_reader import read_config
import json
print(json.dumps(read_config('10.0.1.25', 'appuser', '~/.ssh/id_rsa', '/opt/liberty/deployments', 'myapp'), indent=2))
"
uv run python -c "
from mcp_server.health_check import check_health
import json
print(json.dumps(check_health('10.0.1.25', 'appuser', '~/.ssh/id_rsa', 9080, '/health', 'myapp'), indent=2))
"
uv run python -c "
from mcp_server.logs import list_logs, analyze_logs
import json
print(json.dumps(list_logs('10.0.1.25', 'appuser', '~/.ssh/id_rsa', '/opt/liberty/deployments', 'myapp'), indent=2))
print(json.dumps(analyze_logs('10.0.1.25', 'appuser', '~/.ssh/id_rsa', '/opt/liberty/deployments', 'myapp', ['NullPointerException']), indent=2))
"
uv run python -c "
from mcp_server.connectivity import check_connectivity
import json
print(json.dumps(check_connectivity('10.0.1.25', 'appuser', '~/.ssh/id_rsa', ['db-primary.internal:5432', 'ldap.corp.example:636']), indent=2))
"
uv run python -c "
from mcp_server.resources import check_resources
import json
print(json.dumps(check_resources('10.0.1.25', 'appuser', '~/.ssh/id_rsa', '/opt/liberty/deployments', 'myapp'), indent=2))
"Available Tools
4 toolsanalyze_logsA
SSH to a server and search the app's logs for the given strings/exception names, returning matches with a couple of lines of context. Time filtering is best-effort: Liberty log entries carry a leading timestamp but continuation/stack-trace lines don't repeat it, so a match is only excluded when a timestamp was actually found and falls outside the window - anything unparseable is kept rather than silently dropped.
If log_files is omitted, every discovered log file is searched, except ones over ~25MB
(skipped and reported back) - call list_logs first and pass specific log_files to search
those anyway, or to scope the search down for a large deployment.
Args:
server_ip: Hostname or IP address of the server to connect to over SSH.
os_user: SSH username to authenticate as.
ssh_key: Path to the private key file (on this machine) used for authentication.
deployment_directory: Base deployment directory containing the application folder.
application: Name of the application subfolder whose logs/ directory to search.
search: Strings or exception names to search for (case-insensitive, literal match).
start_time: Optional ISO-8601 timestamp; matches before this are excluded when detectable.
end_time: Optional ISO-8601 timestamp; matches after this are excluded when detectable.
log_files: Optional list of paths (relative to logs/, as returned by list_logs) to
restrict the search to. Recommended for large deployments or to include files
skipped by the size cap.
| Name | Required | Description | Default |
|---|---|---|---|
| search | Yes | ||
| os_user | Yes | ||
| ssh_key | Yes | ||
| end_time | No | ||
| log_files | No | ||
| server_ip | Yes | ||
| start_time | No | ||
| application | Yes | ||
| deployment_directory | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses key behaviors: best-effort time filtering, handling of unparseable timestamps, skipping files >25MB, and reporting skipped files. SSH authentication requirements are fully described.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with an introductory paragraph and explicit Args list. It is front-loaded with core information. A minor nit: the 'Args' section could be slightly more concise, but overall it's efficient and informative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 9 parameters with no output schema, the description is quite complete. It covers behavior, edge cases, and alternative tool usage. However, it does not specify the exact return format (e.g., JSON) beyond 'matches with context', leaving a small gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description provides extensive parameter semantics beyond the schema (which only has type and title). It explains search case-insensitivity, time format (ISO-8601), log_files being relative paths, and the purpose of each parameter like server_ip, os_user, ssh_key.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it SSHs to a server and searches app logs for given strings/exception names, returning matches with context. It distinguishes from siblings via specific reference to list_logs and by providing scope choices.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells when to use this tool: it details best practice for large deployments (call list_logs first and pass specific log_files), explains time filtering limitations, and warns about size caps.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
health_checkA
SSH to a server and check an IBM Liberty app's health: an HTTP probe against
http://127.0.0.1:port/uri (via curl/wget/python3, whichever is present), and a
process check via ps -ef (no JDK/jps/server-status dependency, no root paths).
Args:
server_ip: Hostname or IP address of the server to connect to over SSH.
os_user: SSH username to authenticate as.
ssh_key: Path to the private key file (on this machine) used for authentication.
port: Local port the application listens on.
uri: URI path to request for the HTTP health check (e.g. /health).
application: Application/server name to look for among running processes.
| Name | Required | Description | Default |
|---|---|---|---|
| uri | Yes | ||
| port | Yes | ||
| os_user | Yes | ||
| ssh_key | Yes | ||
| server_ip | Yes | ||
| application | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden and discloses important behaviors: SSH connection, fallback HTTP clients (curl/wget/python3), process check via ps -ef, and no JDK dependencies. This provides transparency into the tool's operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is fairly concise and well-structured, with a brief overview followed by a clear Args list. However, the Args list could be integrated to reduce redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (6 parameters, no output schema, no annotations), the description is quite complete, explaining both health checks. It could mention return format, but the core functionality is well-covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 0% description coverage, so the description must compensate. It provides detailed explanations for each of the 6 parameters in the Args section, adding meaning beyond the schema's type and title fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: SSH to a server and check an IBM Liberty app's health via HTTP probe and process check. It distinguishes from sibling tools (read_config, list_logs, analyze_logs) which have different purposes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use this tool (for health checking of IBM Liberty apps) but does not explicitly provide when-to-use vs alternatives or exclusions. However, the purpose is clear enough to guide selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_logsA
SSH to a server and enumerate every file under //logs/ (Liberty's own messages.log/console.log/trace.log/ffdc/*, plus any app-written logs in subdirectories), with size, last-modified time, and a rough category for each. Call this first, then pass the relevant paths as log_files to analyze_logs - avoids blindly grepping every file (trace.log especially can be huge).
Args:
server_ip: Hostname or IP address of the server to connect to over SSH.
os_user: SSH username to authenticate as.
ssh_key: Path to the private key file (on this machine) used for authentication.
deployment_directory: Base deployment directory containing the application folder.
application: Name of the application subfolder whose logs/ directory to list.
| Name | Required | Description | Default |
|---|---|---|---|
| os_user | Yes | ||
| ssh_key | Yes | ||
| server_ip | Yes | ||
| application | Yes | ||
| deployment_directory | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so description carries full burden. It discloses SSH connection and listing of files with metadata, implying read-only. However, doesn't explicitly state no side effects or mention permissions, but sufficient for a listing tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is front-loaded with main purpose, followed by oneliner usage guidance, then parameter list. No extraneous text, every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema, but description mentions output includes size, last-modified time, and rough category. Lacks explicit format details, but adequate for understanding. Could mention error handling or timeouts, but not critical for listing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 0% description coverage, but description provides detailed explanations for all 5 parameters, adding meaning about hostname, SSH user, key path, deployment directory, and application subfolder.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool enumerates files under a specific logs directory with metadata. It distinguishes from sibling analyze_logs by advising to call this first and pass paths, showing specific verb and resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Call this first, then pass the relevant paths as log_files to analyze_logs - avoids blindly grepping every file'. Provides clear sequencing and rationale for use vs. alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_configA
SSH to a server and read a Liberty-style app's server.xml plus jvm.options, server.env, bootstrap.properties, and any *.properties files referenced from server.xml, with password/token/secret/key values redacted.
Args:
server_ip: Hostname or IP address of the server to connect to over SSH.
os_user: SSH username to authenticate as.
ssh_key: Path to the private key file (on this machine) used for authentication.
deployment_directory: Base deployment directory containing the application folder.
application: Name of the application subfolder to read config from.
| Name | Required | Description | Default |
|---|---|---|---|
| os_user | Yes | ||
| ssh_key | Yes | ||
| server_ip | Yes | ||
| application | Yes | ||
| deployment_directory | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It discloses redaction of secrets, but lacks details on error handling, potential side effects (e.g., banner files), or authentication requirements beyond SSH key. Could be more comprehensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a front-loaded action statement followed by an Args list. Every sentence is relevant, though slightly verbose. Could be tighter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (5 required params, no output schema or annotations), the description lacks information on output format, what happens on missing files, and redaction specifics. For an agent, gaps remain in understanding the result structure.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema has 0% description coverage, but the Args section in the description provides clear explanations for all 5 parameters. Each parameter's role is defined (e.g., server_ip as hostname/IP, ssh_key as private key path), though format constraints are omitted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it reads specific config files (server.xml, jvm.options, etc.) with redaction. The verb 'read' and resource 'config' are specific. It distinguishes from sibling tools like health_check and list_logs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool vs alternatives. Usage is implied by the description, but no when-not or alternative references are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
4 tool updates
v0.1.0- First observed
analyze_logs - First observed
health_check - First observed
list_logs - First observed
read_config
TDQS
Each tool has a clearly distinct purpose: read_config reads configuration files, health_check performs health checks, list_logs enumerates log files, and analyze_logs searches logs. There is no overlap or ambiguity.
All tool names follow a consistent verb_noun pattern (read_config, health_check, list_logs, analyze_logs), making them predictable and easy to understand.
With 4 tools, the set is reasonably scoped for a diagnostics-focused server. It covers key operations (config reading, health check, log listing, log searching) without being overly numerous or too sparse.
The tool surface covers diagnostics well but lacks lifecycle operations such as deploy, start, stop, or config editing. This is a notable gap for managing Liberty applications, though the set is complete for the implied diagnostic purpose.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
2,000+ MCP servers read at source level. Know what one does before you connect. Free, no key.
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
111Scan any MCP server for tool-poisoning, security, auth & license. Trust score before install.
MCP Server for JFrog, providing tools for development and artifact management.
Related MCP Servers
- AlicenseAqualityBmaintenanceMCP server for managing remote servers via SSH, enabling command execution, file transfer, rsync, tunnels, health checks, backups, and database operations.172,1171MIT
- AlicenseNot gradedqualityBmaintenanceA read-only MCP server for Linux and macOS system administration, diagnostics, and troubleshooting, supporting remote SSH execution and multi-host management.Apache 2.0
- FlicenseNot gradedqualityDmaintenanceMCP server for infrastructure discovery and remote management, enabling SSH command execution, file transfer, log tailing, and machine/service inventory with a companion web dashboard.2-
- AlicenseBqualityCmaintenanceMCP server for administering Linux/Unix hosts via SSH and Windows hosts via WinRM/PowerShell Remoting, supporting persistent inventory, sessions, jobs, and command groups.29MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Murtaza1211/mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server