typescript sdk

v0.1.2

Verify every MCP server your agents connect to.

Zero-dependency TypeScript SDK with two trust signals (security + runtime), capability flag detection, a CLI, and a GitHub Action for supply-chain safety.

shell
npm install @strata-ai/sdk
npm →github →marketplace →

quick start

Verify in 8 lines.

Pass any GitHub URL, npm package name, or hosted MCP endpoint. The SDK auto-detects the input shape.

typescript
import { Strata } from '@strata-ai/sdk'

const strata = new Strata({ apiKey: process.env.STRATA_API_KEY })

const result = await strata.verify(
  'https://github.com/microsoft/playwright-mcp'
)

console.log(result.risk_level)        // 'low'
console.log(result.capability_flags)  // ['fs_write', 'net_egress']
console.log(result.security_score)    // 85
console.log(result.runtime_score)     // 72

trust signals

Two scores, one judgment.

Every server in the directory carries two independent trust signals. Together they power the risk_level classification.

security_score · 0–100

Repo health

Derived from GitHub signals: stars, commit recency, release discipline, license, and archived/fork status. Scores below 20 are immediately flagged critical.

runtime_score · 0–100

Behavioral trust

Derived from live tool-call probes against the server’s hosted endpoint: response latency, tool count, capability flag detection, and injection scan.

Capability flags are extracted from runtime probes. They describe what a server can actually do — not what its README claims.

shell_exec · highhighRuns arbitrary shell commands on the host machine
dynamic_eval · highhighEvaluates dynamic code at runtime (eval, exec, etc.)
fs_write · mediummediumWrites to the local filesystem outside sandboxed paths
arbitrary_sql · mediummediumExecutes raw SQL queries against a database
net_egress · lowlowMakes outbound network requests to external services
secret_read · lowlowReads environment variables, credentials, or secret stores
process_spawn · lowlowSpawns child processes

authentication

Key or anonymous.

With an API key, every authenticated route is available. Without one, the anonymous tier (10 req/hour per IP) covers verify and findMCP. Get a free key →

typescript
// No API key — anonymous tier (10 req/hour per IP).
const strata = Strata.public()
await strata.verify('@modelcontextprotocol/server-filesystem')

api reference

Methods.

verify(input)

(input: string | VerifyInput) => Promise<VerifyResult>

Single-server lookup. Smart-detects GitHub URLs, npm packages, and hosted endpoints. Returns { found: false, risk_level: 'unknown' } for unknown servers — never throws for not-found.

verifyAll(inputs)

(inputs: Array<string | VerifyInput>) => Promise<VerifyResult[]>

Batch lookup. Order preserved. Uses single bulk POST when N > 5. Counts as ceil(N/10) calls against your monthly quota.

typescript
const results = await strata.verifyAll([
  '@modelcontextprotocol/server-filesystem',
  'https://github.com/microsoft/playwright-mcp',
  { endpoint: 'https://example.com/mcp' },
])

for (const r of results) {
  console.log(`${r.name}: ${r.risk_level}`)
}

findMCP(query, options?)

(query: string, options?: FindMCPOptions) => Promise<McpServer[]>

Semantic search across Strata's directory. Quarantined and archived servers are excluded automatically.

typescript
const servers = await strata.findMCP('browser automation', {
  excludeCapabilities: ['shell_exec', 'dynamic_eval'],
  minSecurityScore: 50,
  minRuntimeScore: 40,
  requireHosted: false,
  limit: 5,
})

ecosystem(slug)

(slug: string) => Promise<EcosystemBrief>

Composite intelligence brief — best practices, news, integrations — in one round trip. Requires authentication.

typescript
const brief = await strata.ecosystem('claude')

console.log(brief.best_practices)  // 5 most recent best practices
console.log(brief.news)            // 10 most recent items
console.log(brief.integrations)    // 10 top integrations

risk model

Five levels, conservative by default.

Strata maps every server to one of five levels. trusted: true is set only at low.

🔴criticalis_quarantined: true OR security_score < 20
🟠highexposes shell_exec or dynamic_eval
🟡mediumexposes fs_write or arbitrary_sql
🟢lownone of the above (trusted = true)
unknownserver not in Strata directory

cli

strata verify · strata scan

The package ships a strata binary. verify checks one server. scan walks an MCP client config and verifies every entry — defaults to your Claude Desktop config path.

shell
# via npx — use @strata-ai/sdk (the bare "strata" name is taken on npm)
$ npx @strata-ai/sdk verify @modelcontextprotocol/server-filesystem
✓ @modelcontextprotocol/server-filesystem
  Risk: 🟢 low (security 85, runtime 72)
  Flags: fs_write, net_egress
  → https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem

$ npx @strata-ai/sdk verify github.com/owner/sketchy-mcp
✗ owner/sketchy-mcp
  Risk: 🔴 critical (security 12, runtime 8)
  Flags: shell_exec, dynamic_eval
  Reasons: exposes shell_exec; security_score 12 below 20

# or: npm install -g @strata-ai/sdk  →  strata verify …
shell
$ npx @strata-ai/sdk scan
Strata MCP Security Scan
~/Library/Application Support/Claude/claude_desktop_config.json

✓ @modelcontextprotocol/server-filesystem  🟢 low      security 85, runtime 72  [fs_write]
! @scope/risky-mcp                         🟠 high     security 60, runtime 30  [shell_exec]
? local-script  unverifiable — local node script

✓ 1 passed  ! 1 warnings  ✗ 0 critical  ? 1 unverifiable

Exit codes: 0 ok, 1 if any server breaches --fail-on, 2 internal error. Pass --json for parseable output.

github action

Gate every PR.

Drop this into .github/workflows/. The action finds every MCP server reference in the repo (Claude Desktop / Cursor / Cline configs, mcp.json, package.json with an mcp field), verifies each one, and posts an idempotent PR comment with the trust report.

yaml
name: MCP Security
on: [pull_request, push]

permissions:
  contents: read
  pull-requests: write

jobs:
  strata:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: PThrower/strata-mcp-check@v1
        with:
          strata_api_key: ${{ secrets.STRATA_API_KEY }}
          fail_on: critical

fail_on: critical | high | medium. Re-runs UPDATE the same comment instead of stacking. Full action README →

error handling

Typed errors for every failure mode.

Every failure has its own class. StrataRateLimitError exposes the parsed reset time so you can decide your retry policy precisely.

typescript
import {
  Strata,
  StrataAuthError,
  StrataRateLimitError,
  StrataValidationError,
  StrataNetworkError,
} from '@strata-ai/sdk'

try {
  await strata.verify(url)
} catch (err) {
  if (err instanceof StrataRateLimitError) {
    console.log('Reset at', err.resetAt)
    console.log('Remaining', err.remaining)
  }
}

links