Skip to content

MCP Server (AI Agent Integration)

Fencer exposes a Model Context Protocol (MCP) server at https://app.fencer.dev/mcp/ that lets AI agents and LLM-powered tools read your security data. Through the MCP server, an AI assistant can list your organizations, set an active organization context, look up assets and members, and list or read vulnerabilities. The server is read-only.

Clients authenticate with OAuth 2.0, a personal API key, or a service account token.

  • A Fencer account with access to at least one organization.
  • An MCP-compatible AI client (e.g., Claude Desktop, Cursor, or any tool that supports MCP over HTTP).
  • To use a token instead of OAuth: a personal API key, or a service account token with Enable MCP access turned on (see API Access).

Most MCP clients handle the OAuth authentication flow automatically — on first connection you will be redirected to log in to Fencer in your browser and approve access.

Add the Fencer server to your Claude Desktop configuration file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

You can also open it from Claude Desktop via Settings > Developer > Edit Config.

{
"mcpServers": {
"Fencer": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://app.fencer.dev/mcp/"]
}
}
}

Restart Claude Desktop after saving. Requires Node.js 20+.

Run a single CLI command:

Terminal window
claude mcp add --transport http Fencer https://app.fencer.dev/mcp/

Then type /mcp in chat to authenticate.

Open Settings > Tools & MCP > New MCP Server, or add to .cursor/mcp.json in your project:

{
"mcpServers": {
"Fencer": {
"type": "http",
"url": "https://app.fencer.dev/mcp/"
}
}
}

Add to ~/.codex/config.toml (global) or .codex/config.toml (project-scoped):

[mcp_servers.fencer]
url = "https://app.fencer.dev/mcp/"

Add to opencode.json in your project root:

{
"mcp": {
"fencer": {
"type": "remote",
"url": "https://app.fencer.dev/mcp/"
}
}
}

The MCP server implements the MCP 2025-03-26 protocol over HTTP using JSON-RPC 2.0, and answers as server-sent events when the client asks for text/event-stream. Clients authenticate using OAuth 2.0 with PKCE, which Fencer supports via dynamic client registration — meaning your AI tool can register itself automatically without any manual setup.

Instead of OAuth, a client can send a Fencer personal API key or service account token as the bearer token. A personal API key reaches the organizations it has been granted. A service account token works only when the service account has Enable MCP access turned on, and is always bound to its own organization.

Once authenticated, the client calls tools exposed by the server. The server enforces organization-level access control, the role’s permissions and OAuth scopes on every request, so an agent can only access data the authenticated user is permitted to see.

Your MCP client starts by fetching the server’s metadata endpoints:

GET /.well-known/oauth-authorization-server
GET /.well-known/oauth-protected-resource

The authorization server metadata returns the endpoints needed for the OAuth flow:

  • authorization_endpoint — /oauth/authorize/
  • token_endpoint — /oauth/token/
  • revocation_endpoint — /oauth/revoke_token/
  • registration_endpoint — /oauth/register/

The protected resource metadata identifies the MCP resource (/mcp/) and the supported scopes: mcp:vulnerabilities:read, cli:api:read and cli:api:write.

MCP clients register themselves via the dynamic client registration endpoint:

POST /oauth/register/
Content-Type: application/json
{
"client_name": "My AI Agent",
"redirect_uris": ["http://localhost:3000/callback"]
}

The response includes a client_id you use for the authorization code flow. Clients are registered as public OAuth clients (no client secret) using the authorization code grant with PKCE (S256) and refresh tokens.

Complete the standard OAuth 2.0 authorization code flow with PKCE:

  1. Redirect the user to the authorization_endpoint with code_challenge_method=S256 and the mcp:vulnerabilities:read scope.
  2. The user logs in and grants access.
  3. Exchange the authorization code at the token_endpoint for an access token.

Send JSON-RPC 2.0 requests to the MCP endpoint:

POST /mcp/
Authorization: Bearer <access_token>
Content-Type: application/json

The server supports these JSON-RPC methods:

MethodDescription
initializeHandshake — returns server info, protocol version, capabilities and the flow
tools/listLists all available tools and their input schemas
tools/callInvokes a specific tool with arguments
pingReturns an empty result

resources/list, resources/templates/list and prompts/list return empty lists. Notifications (requests without an id) are acknowledged with HTTP 202.

The server exposes these tools:

ToolDescription
organizations.listLists the organizations you can access and the active one. Call this first.
session.set_organizationSets the active organization for later tool calls.
vulnerabilities.listLists vulnerabilities, with filters, ordering and pagination.
vulnerabilities.getGets one vulnerability by slug, including detail fields such as code and location.
assets.listLists assets, to turn an asset name into the slug vulnerabilities.list filters by.
members.listLists members, to turn a name or email into the id vulnerabilities.list filters by.

The server enforces a specific workflow for organization-scoped tools. You must:

  1. Call organizations.list to discover accessible organizations.
  2. Call session.set_organization to set your active organization context.
  3. Then call data tools like vulnerabilities.list and vulnerabilities.get.

Alternatively, you can pass organization_slug directly as an argument to any organization-scoped tool to skip step 2. A service account token always uses its own organization.

{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize"
}
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "organizations.list",
"arguments": {}
}
}
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "session.set_organization",
"arguments": {
"organization_slug": "my-org"
}
}
}
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "vulnerabilities.list",
"arguments": {
"page": 1,
"page_size": 10,
"q": "critical"
}
}
}

The vulnerabilities.list tool supports the following parameters:

ParameterTypeDescription
organization_slugstring (optional)Override the active session organization
pageintegerPage number (default: 1)
page_sizeintegerResults per page (default: 20)
qstring (optional)Search query
severitylist of stringsOnly these severities
statusstring (optional)Only this status
categorystring (optional)Only this category
liveboolean (optional)Only vulnerabilities that are live in production
ignoredboolean (optional)Only ignored (or only not ignored) vulnerabilities
deferredboolean (optional)Only deferred (or only not deferred) vulnerabilities
has_assigneeboolean (optional)Only assigned (or only unassigned) vulnerabilities
in_scopeboolean (optional)Only in-scope (or only out-of-scope) vulnerabilities
assetlist of stringsAsset slugs from assets.list, not asset names
assigneelist of stringsMember ids from members.list; "null" matches unassigned
priority_levellist of stringsOnly these priority levels
order_bystring (optional)Sort order
filtersstring (optional)Advanced filter expression (JSON), e.g. for date ranges
filter_operatorstring (optional)Operator for combining filters

401 Unauthorized with resource_metadata header — Your access token is missing or expired. The response includes a WWW-Authenticate header pointing to the /.well-known/oauth-protected-resource endpoint. Re-authenticate using the OAuth flow.

“Organization not found” or “Forbidden” errors — The organization_slug you provided doesn’t exist or your account doesn’t have access. Call organizations.list first to see which organizations are available.

“Call organizations.list then session.set_organization, or pass organization_slug.” — No organization is set for the session. Set one, or pass organization_slug.

“Missing required scope” error — Your OAuth token doesn’t include the required scope for the tool. vulnerabilities.list, vulnerabilities.get, assets.list and members.list require the mcp:vulnerabilities:read scope (cli:api:read or cli:api:write also work). Request the scope during authorization.

“MCP access is not enabled for this service account.” — Turn on Enable MCP access for the service account, or use a different token.

Rate limiting — The MCP endpoint enforces per-user rate limits (120 requests per minute by default). If you receive a 429 response, reduce your request frequency.