Within the agreed scope we identified 11 MCP servers wired into Claude Code, Cursor, and an internal agent runner. 7 were absent from any asset register. 4 hold credentials that can reach production systems. 2 findings are graded Critical: a static database credential embedded in a shared client config, and a deployment tool callable by an LLM with no approval gate and no audit trail.
None of this is unusual. MCP adoption at Meridian followed the pattern we see everywhere: individual developers solved local problems, the configs spread through dotfile repos and onboarding docs, and no single team ever owned the full picture. The remediation roadmap in §5 is sequenced so that the two Critical items are closed in week one with configuration changes only.
Discovered via repository and CI scanning of the agreed scope: client configs (claude_desktop_config.json, .cursor/mcp.json, .mcp.json), CI pipeline definitions, and the internal agent runner's deployment manifests.
| ID | Server | Owner | Transport | Found in | Known to security? | Prod reach |
|---|---|---|---|---|---|---|
| S-01 | postgres-mcp | ▮▮▮▮▮▮▮ (Platform) | stdio | infra-tools repo, 23 dev configs | No | Yes — replica + primary |
| S-02 | github-mcp | Dev Productivity | stdio | onboarding doc, dotfiles | Yes | Indirect (CI secrets) |
| S-03 | deploy-helper (internal) | ▮▮▮▮▮ (SRE) | stdio | sre-scripts repo | No | Yes — kubectl apply |
| S-04 | filesystem | individual devs | stdio | 31 dev configs, scoped to ~/ | No | No |
| S-05 | jira-mcp | Dev Productivity | SSE (vendor-hosted) | team wiki | Yes | No |
| S-06 | slack-mcp | ▮▮▮▮▮▮ | stdio | 2 dev configs | No | No (data exposure only) |
| S-07 | s3-mcp | Data Eng | stdio | data-pipelines repo | Yes | Yes — prod buckets r/w |
| S-08 | grafana-mcp | SRE | stdio | sre onboarding | Yes | Read-only |
| S-09 | internal-api-mcp | ▮▮▮▮▮▮▮▮ (Checkout) | stdio | checkout-svc repo | No | Yes — staging + prod API |
| S-10 | browser-mcp | individual devs | stdio | 4 dev configs | No | No |
| S-11 | agent-runner tools (internal) | AI Enablement | HTTP (internal) | agent-runner manifests | No | Staging only |
Capability matrix for the four servers with production reach. "Destructive" means a tool an LLM can invoke that deletes, overwrites, or deploys without human confirmation.
| ID | Reads | Writes | Destructive tools | Credential held | Rotation |
|---|---|---|---|---|---|
| S-01 | All schemas incl. ▮▮▮▮▮▮_customers | Yes (no table allow-list) | execute_sql — unrestricted | Static password, shared role | Never (412 days) |
| S-03 | Cluster state, all namespaces | Yes | apply_manifest, delete_pod | Cluster-admin kubeconfig | 90 days |
| S-07 | All prod buckets | Yes | delete_object | IAM user key, ▮▮▮▮▮▮▮▮▮▮ | Never (688 days) |
| S-09 | Orders, customers, pricing | Yes (POST/PUT pass-through) | refund_order (no cap) | Service token, admin scope | 180 days |
The remaining seven servers are capability-bounded (read-only, non-production, or local filesystem scope) and are covered in Appendix B of the full report.
Graded against the OWASP Top 10 for LLM Applications (2025) plus MCP-specific checks. 9 findings total in the full report; 6 shown in this sample.
Evidence. The postgres-mcp entry distributed via the infra-tools repo embeds a plaintext connection string for a shared role with write access to the primary. The credential has not rotated in 412 days and appears in 23 checked-out configs:
"postgres": {
"command": "npx", "args": ["-y", "postgres-mcp"],
"env": { "DATABASE_URL": "postgres://app_shared:▮▮▮▮▮▮▮▮▮▮▮▮@db-prod-▮▮▮.meridian.internal:5432/meridian" }
}
Impact. Any prompt-injected or misbehaving agent session on any of 23 laptops can read or modify production data. Any laptop compromise yields the credential directly.
Remediation. Rotate immediately; replace with per-developer short-lived credentials (IAM auth or Vault dynamic secrets); point the MCP server at a read replica with a least-privilege role.
Evidence. The internal deploy-helper server exposes apply_manifest with a cluster-admin kubeconfig. Tool calls are not logged anywhere; the only record is the agent conversation on the developer's machine. A deployment triggered this way is indistinguishable from a manual one in cluster audit logs.
Impact. An agent can modify production workloads, and the org cannot reconstruct what an agent did after the fact — the exact incident-response gap described in the engagement brief.
Remediation. Gate destructive tools behind explicit confirmation; scope the kubeconfig to a namespaced role; log every tool call (request, arguments, outcome) to the SIEM — §4 gives the vendor-neutral pattern.
Evidence. s3-mcp authenticates with an IAM user access key (688 days old) granting s3:* on production buckets, including DeleteObject, used from developer laptops.
Remediation. Replace with role assumption + short-lived session credentials; strip delete permissions; enable bucket versioning and object lock on the two buckets holding customer manifests.
Evidence. 8 of 11 servers launch as npx -y <package> with no version pin and no integrity check — every agent session executes whatever the registry serves that day, with the credentials in that server's env block.
Remediation. Pin exact versions; mirror vetted packages in the internal registry; prefer single-binary servers where available.
Evidence. The vendor-hosted jira-mcp (SSE) delivers tool descriptions at runtime. Descriptions are rendered into every agent's context unreviewed; a malicious or compromised description can steer agent behavior across all connected developers simultaneously.
Remediation. Snapshot and diff tool descriptions in CI; alert on changes; treat description changes as a change-management event.
Evidence. No team owns the MCP surface. 7 servers were unknown to security before this audit; 3 had no identifiable owner at all and were attributed via git blame on the introducing commit (▮▮▮▮▮▮▮▮▮).
Remediation. Add MCP servers as an asset class in the register; require an owner and a capability declaration per server; review quarterly. A one-page policy template is included in Appendix C.
Mapped against the question that matters in an incident: "could we reconstruct what an agent did in five minutes?" Today the answer at Meridian is no, for every server.
| Agent action | Visible today? | Where it should land |
|---|---|---|
| Tool call issued (name + args) | No — exists only in local chat history | Structured log → SIEM |
| Tool call latency / error rates | No | Prometheus metrics per server |
| DB queries from S-01 | Partial — pg logs, not attributable to agent vs human | Dedicated role per server → attributable |
| Deploys from S-03 | No — indistinguishable from manual kubectl | Audit-logged service account per agent |
| Server process up/down | No | Liveness metric, alert on flap |
Recommended pattern (vendor-neutral). Wrap each stdio server with a transparent observability proxy emitting Prometheus metrics and a structured JSON event log (the open-source mcpobserve is one zero-dependency option; an OTel collector sidecar is another), route the event log to the existing Splunk pipeline, and add the five dashboard panels specified in Appendix D. Estimated effort: 2–3 engineer-days for all 11 servers.
| # | Action | Closes | Risk ↓ | Effort | Owner | When |
|---|---|---|---|---|---|---|
| R-1 | Rotate S-01 credential; move to read replica + least-privilege role | F-01 | Critical | Hours | Platform | Week 1 |
| R-2 | Scope S-03 kubeconfig to namespaced role; confirmation gate on apply/delete | F-02 | Critical | 1 day | SRE | Week 1 |
| R-3 | Replace S-07 IAM user key with assumed role; strip delete; enable versioning | F-03 | High | 1 day | Data Eng | Week 1–2 |
| R-4 | Pin all MCP server versions; mirror in internal registry | F-04 | High | 2 days | Dev Prod | Week 2 |
| R-5 | Deploy observability proxy + SIEM routing on the 4 prod-reach servers | §4 | High | 2–3 days | SRE | Week 2–3 |
| R-6 | Tool-description snapshot/diff in CI for vendor-hosted servers | F-05 | Medium | 1 day | Dev Prod | Week 3 |
| R-7 | MCP asset-class policy: owner, capability declaration, quarterly review | F-06 | Medium | Policy | Security | Week 4 |
Full report additionally includes: Appendix A (per-server config evidence), B (capability matrix for all 11 servers), C (policy template), D (dashboard & alert specifications), and the 30-minute executive readout deck.
Fixed fee, two weeks, read-only. Founding-client rate in exchange for a case study you redact and approve.
Book a free 20-min scoping call →