SSH + Oracle DB MCP Server
Enables secure SSH and Oracle DB operations with persistent sessions, audit logging, and safe command execution, plus Oracle NMS documentation access.
README
SSH + Oracle DB MCP Server
Production-grade MCP server for persistent SSH PTY sessions and cached Oracle DB diagnostic sessions, with strict server-side review, confirmation, and audit logging.
Highlights
- Uses
ssh2directly so the server can keep a real PTY shell alive across MCP calls - Keeps Oracle DB connections open across MCP calls so agents can reuse DB session state
- Supports guided interactive PTY commands with prompt classification and follow-up input tools
- Auto-runs only an explicit safe read-only command list and safe SELECT queries
- Requires user confirmation for anything outside the explicit safe list
- Supports custom project and NMS commands, but never runs them blindly when MCP is not confident about the consequences
- Can browse Oracle Utilities Network Management System documentation versions, download guide PDFs on demand, and return a cached local file path to the agent
- Writes an audit record for SSH commands, Oracle SQL, hosts, DB targets, approvals, blocks, starts, completions, timeouts, and interrupts to a file on disk
- Supports MCP stdio by default and optional HTTP + SSE transport
Project layout
src/
|-- index.ts
|-- session.ts
|-- ssh.ts
|-- executor.ts
|-- nms-docs.ts
|-- sudo.ts
|-- db.ts
|-- db-session.ts
|-- policy.ts
|-- sql-policy.ts
|-- policy-config.ts
|-- oracledb.d.ts
`-- utils.ts
ssh-mcp-policy.json
ssh-mcp-policy.example.json
mcp-audit.ndjson
scripts/mcp_smoke_test.mjs
Environment variables
Shell and transport:
MCP_SSH_IDLE_TIMEOUT_MSdefault1800000MCP_SSH_DEFAULT_TIMEOUT_MSdefault30000MCP_SSH_APPROVAL_TTL_MSdefault600000MCP_SSH_MAX_SESSIONSdefault10MCP_SSH_ALGORITHM_PROFILEdefaultcompat; usedefaultto fall back to the rawssh2algorithm orderMCP_SSH_POLICY_FILEoptional path to a custom JSON policy fileMCP_TRANSPORTstdioorsse, defaultstdioMCP_SSE_PORTdefault3000
Oracle DB:
MCP_DB_IDLE_TIMEOUT_MSdefault1800000MCP_DB_DEFAULT_TIMEOUT_MSdefault30000MCP_DB_MAX_SESSIONSdefault5MCP_DB_MAX_ROWSdefault200MCP_DB_CONFIG_DIRoptional Oracle Net config directory for wallet or TNS-based connections; if unset, MCP also falls back toTNS_ADMINwhen presentMCP_DB_WALLET_LOCATIONoptional wallet directoryMCP_DB_WALLET_PASSWORDoptional wallet passwordMCP_DB_HTTPS_PROXYoptional HTTPS proxy for secure Oracle DB connectionsMCP_DB_HTTPS_PROXY_PORToptional proxy port
Audit:
MCP_AUDIT_LOG_FILEdefaultC:\ProjectNMS\NMS_MCP\mcp-audit.ndjsonwhen running from this repo
Oracle NMS documentation:
MCP_NMS_DOCS_BOOKS_URLdefaulthttps://docs.oracle.com/en/industries/energy-water/network-management-system/books.htmlMCP_NMS_DOCS_CACHE_DIRdefault%USERPROFILE%\Documents\nms-docs
Tools
Shell tools:
ssh_connectssh_connect_target_sessionreview_commandreview_command_batchexecute_commandexecute_command_batchstart_interactive_commandwrite_stdinsend_interaction_inputread_outputread_interaction_stateresize_terminallist_sessionsclose_sessioninterrupt_session
Oracle DB tools:
oracle_connectreview_sqlexecute_sqllist_db_sessionslist_nms_guidesget_nms_guide_pdfclose_db_sessioninterrupt_db_session
Shared visibility:
read_usage_guideread_policyread_audit_log
Oracle NMS documentation tools:
list_nms_guidesget_nms_guide_pdf
Safety model
The server does not trust user intent or agent intent. It reviews the exact command or SQL text first, decides whether it is on the explicit safe list, and otherwise requires confirmation before running it.
Interactive PTY model
For simple commands, use execute_command.
When you already know the target project or admin account you need, prefer ssh_connect_target_session so MCP logs in once, adopts that target shell once, and then lets the rest of the session run without repeating sudo.
For a related sequence of standalone checks on the same host, use execute_command_batch so MCP can review the whole set together and, when needed, ask for one shared confirmation instead of one prompt per command.
For anything that may prompt, stream, or open a REPL, use the guided interactive flow:
start_interactive_commandread_interaction_statesend_interaction_inputinterrupt_sessionor wait for the command to complete
The server keeps the PTY stateful, classifies common prompt types, and returns structured interaction metadata such as:
promptTypepromptTextexpectsInputsafeToAutoRespondsuggestedInputsforegroundCommand
Prompt types currently include shell prompts, sudo/password prompts, yes/no prompts, press-enter prompts, Python REPL prompts, SQL prompts, pagers, and fallback unknown interactive prompts.
Safe shell auto-run list
These commands can auto-run when MCP can clearly recognize them and does not detect extra unsafe behavior:
lspwdcdgrepfindlocatecatpstailheadsortuniqwcechoprintfhostnamewhoamiiddateunameenvprintenvcommandtypessnetstatlsofreadlinkrealpathsmsReportISQLread-onlySELECTcommands onlyISQL -adminread-onlySELECTcommands only
Notes:
cdis treated as low-impact and allowed because it only changes the active shell directory- Exact Oracle NMS read-only diagnostics such as
hostname,whoami,id,getent,grep -n ... | head,ps -ef | grep ... | grep -v grep,find ... | sort | tail,ss -ltn, and exact.nmsrcvalidation bundles can auto-run when they match the built-in diagnostics profile - Exact LDAP-style target-user handoffs such as
sudo su - <target-user>orsudo -iu <target-user>can auto-run so MCP can adopt the target shell without an extra confirmation step - Exact read-only target-user diagnostics such as
sudo -u <target-user> whoami,ps,grep,find, log-path discovery pipelines, orsmsReport 2>&1 | head -n ...can auto-run when the underlying command already matches the safe diagnostics rules - Other
sudousage is still higher scrutiny and can require confirmation or be blocked by policy - For the cleanest Codex workflow, use
ssh_connect_target_sessioninstead of repeatingsudo -u <target-user>on every command - Prefer plain read-only diagnostics or exact
.nmsrcwrappers over privilege-changing bundles whenever possible - After switching to or adopting a target user shell, do not source
.bashrc,.profile, or similar login files unless the command truly depends on extra environment setup - Commands that start interactive terminal programs such as
python,sqlplus,ISQL,tail -f,less,top, orsshare not treated as safe auto-run commands - If MCP sees shell redirection to files, heredocs, inline scripts,
sudo, or other risky patterns, it will stop auto-running and ask first - If MCP is not confident that a custom project command is harmless, it asks first
Safe SQL auto-run list
These statements can auto-run when MCP can clearly recognize them as read-only:
SELECT ...WITH ... SELECT ...
Notes:
- Package or schema-qualified function calls inside a
SELECTare not auto-run if MCP is not confident about side effects SELECT ... FOR UPDATEis not auto-run
Confirmation behavior
Anything outside the safe auto-run lists requires explicit user confirmation.
What MCP returns:
decision: "allow"for explicit safe commands or queriesdecision: "allow"for safe read-only command batches whose individual commands are all recognized as low riskdecision: "approval_required"for unknown, custom, mutating, or higher-risk actionsdecision: "blocked"only when a deny rule or explicit blocked category in your policy file says MCP must refuse it entirely
Confirmation rule:
- MCP asks the agent to show the exact command or SQL and a simple consequence summary
- For
execute_command_batch, MCP can ask once for the whole related command set - The user must reply with exact
CONFIRM - The agent must retry with the returned
approvalIdanduserConfirmation: "CONFIRM" - MCP should never self-confirm
Audit logging
Every reviewed or executed operation is appended to the audit file:
- SSH host and username
- DB target and username
- command or SQL text
- review / block / start / completion / timeout / interrupt events
- timestamps and structured details
The default audit file is mcp-audit.ndjson. Each line is one JSON object so it is easy to search or archive.
Oracle NMS documentation access
Use list_nms_guides to scrape the live Oracle NMS docs library and discover available versions plus guide titles.
Use get_nms_guide_pdf with a version and guide query to resolve one PDF to a local cached file path. If the file is already cached, MCP returns that local path immediately. Otherwise MCP downloads the PDF into the configured cache directory first and then returns the absolute path.
Examples:
list_nms_guidesto inspect all currently published versions and guideslist_nms_guideswith{"version":"25.12"}get_nms_guide_pdfwith{"version":"25.12","guide":"installation guide"}get_nms_guide_pdfwith{"version":"25.12","guide":"nms-installation-guide","refresh":true}
Policy files
The server loads ssh-mcp-policy.json by default. You can point to a different file with MCP_SSH_POLICY_FILE.
Current policy file model:
- Top-level fields apply to shell command policy
- Nested
sqlPolicyfields apply to Oracle SQL policy denyRulesalways win overallowRulesblockedCategoriesare for commands or SQL you want MCP to hard-refuseapprovalCategoriesare for categories that should always require confirmationapprovedScratchPathsdefine the only scratch paths MCP will treat as explicitly approved write targetsdiagnosticsProfilesenable exact built-in read-only command bundles such as the Oracle NMS diagnostics profileallowRulesare for narrow exceptions you want MCP to recognize explicitly
Default files:
- ssh-mcp-policy.json blocks high-risk admin categories by default and enables the exact Oracle NMS read-only diagnostics profile
- ssh-mcp-policy.example.json shows how to deny dangerous patterns and allow very narrow exceptions
Policy file shape
{
"blockedCategories": [
"privilege-escalation",
"password-change"
],
"approvalCategories": [
"session-state",
"privileged-command"
],
"approvedScratchPaths": [
"/tmp",
"/var/tmp"
],
"diagnosticsProfiles": [
"oracle-nms-readonly"
],
"allowRules": [],
"denyRules": [
{
"name": "block-service-restarts",
"regex": "\\b(systemctl|service)\\b.*\\b(start|stop|restart|reload)\\b",
"reason": "Hard-block service interruption through MCP."
}
],
"sqlPolicy": {
"blockedCategories": [
"ddl-destructive",
"lock-control"
],
"approvalCategories": ["session-state"],
"allowRules": [],
"denyRules": [
{
"name": "block-delete",
"regex": "^delete\\b",
"reason": "Hard-block row deletion through MCP."
}
]
}
}
Recommended agent behavior
Use these tools anytime they would help NMS development, debugging, runtime validation, issue analysis, or environment checks.
Good uses:
- SSH tools for host state, WebLogic status, log reading, process inspection,
.nmsrcsetup, and NMS utility checks - Oracle DB tools for safe read-only queries, counts, data checks, schema context checks, and troubleshooting evidence
review_commandfor custom project commands when MCP is not fully certainreview_command_batchandexecute_command_batchfor a human-style sequence of related standalone checks on the same hostreview_sqlfor any SQL beyond a plain safeSELECT
Required behavior:
- Show the exact command or SQL to the user before asking for confirmation.
- Include the simple consequence summary from MCP in that prompt.
- Never self-supply
CONFIRM. - Treat
POLICY_BLOCKEDas final unless a human intentionally changes the policy file. - Check the audit log when you need proof of what MCP reviewed or executed.
- Prefer standalone checks over bundled shell scripts whenever possible. Run
smsReport, thengrep, thenfind, instead of one giant quoted shell command that has to be mentally unpacked later.
Run
On Windows PowerShell, use npm.cmd and codex.cmd. The .ps1 shims may be blocked by execution policy on locked-down machines.
Install dependencies:
npm.cmd install
Build:
npm.cmd run build
Start over stdio:
npm.cmd start
Start over SSE:
$env:MCP_TRANSPORT = "sse"
$env:MCP_SSE_PORT = "3000"
npm.cmd start
Codex setup
Build the project first:
cd C:\ProjectNMS\NMS_MCP
npm.cmd install
npm.cmd run build
Register the server with Codex:
codex.cmd mcp add nms-mcp `
--env MCP_SSH_DEFAULT_TIMEOUT_MS=120000 `
--env MCP_SSH_IDLE_TIMEOUT_MS=3600000 `
--env MCP_SSH_APPROVAL_TTL_MS=600000 `
--env MCP_SSH_POLICY_FILE=C:\ProjectNMS\NMS_MCP\ssh-mcp-policy.json `
--env MCP_SSH_MAX_SESSIONS=10 `
--env MCP_DB_DEFAULT_TIMEOUT_MS=60000 `
--env MCP_DB_IDLE_TIMEOUT_MS=3600000 `
--env MCP_DB_MAX_SESSIONS=5 `
--env MCP_DB_MAX_ROWS=200 `
--env MCP_AUDIT_LOG_FILE=C:\ProjectNMS\NMS_MCP\mcp-audit.ndjson `
-- node C:\ProjectNMS\NMS_MCP\dist\index.js
Verify it is registered:
codex.cmd mcp list
Notes:
- Replace
C:\ProjectNMS\NMS_MCPwith your actual checkout path if it is different - Do not store SSH passwords or DB passwords in the Codex MCP registration; pass them when calling
ssh_connectororacle_connect - Tell Codex to review first, show the exact command or SQL to the user, and only continue after exact
CONFIRM
Cline setup
Build the project first if you have not already:
cd C:\ProjectNMS\NMS_MCP
npm.cmd install
npm.cmd run build
Open Cline and add a local stdio MCP server using this shape:
{
"mcpServers": {
"nms-mcp": {
"command": "node",
"args": ["C:\\ProjectNMS\\NMS_MCP\\dist\\index.js"],
"env": {
"MCP_SSH_DEFAULT_TIMEOUT_MS": "120000",
"MCP_SSH_IDLE_TIMEOUT_MS": "3600000",
"MCP_SSH_APPROVAL_TTL_MS": "600000",
"MCP_SSH_POLICY_FILE": "C:\\ProjectNMS\\NMS_MCP\\ssh-mcp-policy.json",
"MCP_SSH_MAX_SESSIONS": "10",
"MCP_DB_DEFAULT_TIMEOUT_MS": "60000",
"MCP_DB_IDLE_TIMEOUT_MS": "3600000",
"MCP_DB_MAX_SESSIONS": "5",
"MCP_DB_MAX_ROWS": "200",
"MCP_AUDIT_LOG_FILE": "C:\\ProjectNMS\\NMS_MCP\\mcp-audit.ndjson"
},
"disabled": false
}
}
}
Notes:
- Do not store SSH passwords or DB passwords in the Cline config; pass them when calling
ssh_connectororacle_connect - Ask Cline to never self-confirm and to show the exact command or SQL plus the consequence summary in the chat before proceeding
First use
SSH:
- Call
ssh_connect. - Call
review_commandfor anything outside the obvious safe list or when you want MCP to explain the risk before asking the user. - Use
execute_commandfor one-shot commands,execute_command_batchfor a related set of standalone checks, orstart_interactive_commandfor prompt-driven commands. - If MCP returns
CONFIRMATION_REQUIRED, show the exact command or command set plus the summary, then retry with the sameapprovalIdanduserConfirmation: "CONFIRM". - For interactive runs, inspect
read_interaction_stateand continue withsend_interaction_input.
Oracle DB:
- Call
oracle_connectwith DB credentials and eitherconnectStringorhostplusserviceNameorsid. - Call
review_sqlfor anything beyond a plain safeSELECT. - Run
execute_sql. - If MCP returns
CONFIRMATION_REQUIRED, show the exact SQL and the summary, then retry with the sameapprovalIdanduserConfirmation: "CONFIRM".
Example flows
Safe shell command:
{
"sessionId": "abc123",
"command": "ps -ef | grep -i nms_1 | grep -v grep"
}
Custom project command that requires confirmation:
{
"sessionId": "abc123",
"command": "smsReport"
}
Interactive prompt-driven command:
{
"sessionId": "abc123",
"command": "python3 -q",
"waitForOutputMs": 1500
}
Follow-up interactive input:
{
"sessionId": "abc123",
"input": "print(2 + 2)\\n",
"waitForOutputMs": 1000
}
Safe SQL query:
{
"dbSessionId": "db123",
"sql": "select count(*) as class_count from classes"
}
SQL that requires confirmation:
{
"dbSessionId": "db123",
"sql": "alter session set current_schema = NMS"
}
PTY recovery flow
If a long-running command times out or an interactive program appears stuck, the PTY session stays attached on purpose so the agent can recover it instead of losing shell state.
Recommended recovery steps:
- Call
read_outputto inspect the latest PTY output. - Call
read_interaction_statewhen you want prompt classification instead of raw output alone. - Call
interrupt_sessionwithctrlCto bring the shell back to a prompt. - Call
read_outputagain if you want to capture the interrupt output. - Run a safe command such as
pwdto confirm the shell is ready again.
This is safer than blindly starting a new session because the existing working directory, sourced environment, and any confirmed elevation state remain visible and auditable.
Smoke test
The smoke harness verifies the SSH path end-to-end, exercises the review flow for shell and SQL, and checks PTY recovery with interrupt_session. It auto-confirms inside the local harness only so the test can complete; production agents must not do that.
SSH smoke test:
$env:SSH_TEST_HOST = "your-ssh-host"
$env:SSH_TEST_PORT = "2222"
$env:SSH_TEST_USER = "your_ssh_user"
$env:SSH_TEST_PASSWORD = "your_ssh_password"
node scripts\mcp_smoke_test.mjs
Optional direct Oracle DB smoke test:
$env:DB_TEST_USER = "your_db_user"
$env:DB_TEST_PASSWORD = "your_db_password"
$env:DB_TEST_CONNECT_STRING = "db-host:1521/your_service"
node scripts\mcp_smoke_test.mjs
Audit file example:
Get-Content C:\ProjectNMS\NMS_MCP\mcp-audit.ndjson -Tail 20
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.