> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sedata-ai.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# safetyCheck

> Wrap a tool handler with inline content validation.

```ts theme={null}
function safetyCheck(
  handler: (params: any) => Promise<any> | any,
  options: SafetyCheckOptions,
): (params: any) => Promise<any>
```

A higher-order function that wraps an MCP tool handler so that one of its
input parameters is validated against Sedata's safety API before the handler
runs. Flagged input short-circuits with a structured "blocked" response.

## Parameters

<ParamField path="handler" type="(params: any) => Promise<any> | any" required>
  Your original tool handler, exactly as you'd pass to `server.registerTool`.
</ParamField>

<ParamField path="options" type="SafetyCheckOptions" required>
  Configuration for the wrapper.
</ParamField>

### `SafetyCheckOptions`

<ParamField path="parameterName" type="string" required>
  Name of the parameter on the handler input to validate. Only string values
  are checked — non-string values are ignored.
</ParamField>

<ParamField path="output_screen" type="boolean">
  When `true`, prints a `🚨 Safety Check Alert: ...` line to stdout when
  content is flagged. Useful for local debugging. Defaults to `false`.
</ParamField>

<ParamField path="endpoint" type="string">
  Reserved for a future override of the safety endpoint. Currently the wrapper
  always calls `https://api.sedata-ai.tech/security/safety-check`.
</ParamField>

## Returns

A new handler with the same signature. Internally:

* Reads `params[options.parameterName]`.
* If it's a string, calls `checkSafety(value)` and writes the result to
  `params._safetyCheck` so the instrumentation layer can attach
  `mcp.safety_check.*` attributes.
* If `flagged`, returns a structured blocked response without calling the
  original handler.
* Otherwise calls the original handler with `params`.

## Blocked response

```json theme={null}
{
  "content": [
    {
      "type": "text",
      "text": "{ \"summary\": \"🚫 CONTENT BLOCKED: ...\", \"blocked\": true, \"reason\": \"Content flagged by safety check\", \"timestamp\": \"...\" }"
    }
  ],
  "structuredContent": {
    "summary": "🚫 CONTENT BLOCKED: ..."
  }
}
```

The `structuredContent.summary` field is what most tools surface to the
caller. If your tool's `outputSchema` uses a different key name, you'll need
to fork or adapt the wrapper.

## Example

```ts theme={null}
import { z } from 'zod'
import { safetyCheck } from '@sedata-ai/mcp'

server.registerTool(
  'text-summarizer',
  {
    title: 'Text Summarizer',
    description: 'Summarize text content',
    inputSchema: { text: z.string() },
    outputSchema: { summary: z.string() },
  },
  safetyCheck(
    async ({ text }) => {
      const summary = text.substring(0, 100) + '...'
      return {
        content: [{ type: 'text', text: JSON.stringify({ summary }) }],
        structuredContent: { summary },
      }
    },
    { parameterName: 'text', output_screen: true },
  ),
)
```

## Authentication

The wrapper uses the API key set during `instrumentServer(...)`. Both
`exporterAuth.apiKey` and `exporterAuth.token` are forwarded as the
`x-api-key` header.

To override:

```ts theme={null}
import { setTelemetryApiKey } from '@sedata-ai/mcp'
setTelemetryApiKey('different-key')
```

## Failure modes

| Failure                                 | Behavior                                              |
| --------------------------------------- | ----------------------------------------------------- |
| Network error                           | Logged. Handler runs. `_safetyCheck.success = false`. |
| Non-200 from safety API                 | Logged. Handler runs. `_safetyCheck.success = false`. |
| `parameterName` not a string or missing | Handler runs without check.                           |

The wrapper **fails open** — telemetry should never break your tool.

## Span attributes added

When the wrapper runs, the active tool span receives:

| Attribute                     | Type    |
| ----------------------------- | ------- |
| `mcp.safety_check.content`    | string  |
| `mcp.safety_check.flagged`    | boolean |
| `mcp.safety_check.latency_ms` | number  |
| `mcp.safety_check.success`    | boolean |

## See also

<CardGroup cols={2}>
  <Card title="checkSafety" icon="shield" href="/api-reference/check-safety">
    The lower-level function that talks to the safety API.
  </Card>

  <Card title="Safety checks concept" icon="book-open" href="/concepts/safety-checks">
    What it means and when to use it.
  </Card>
</CardGroup>
