Install
Connect any MCP client — Claude, Cursor, VS Code, OpenAI Codex, Gemini, Mistral — to the Certivant MCP server using your existing Certivant API key as a bearer token.
The Certivant MCP server speaks Streamable HTTP on a single endpoint,
POST /mcp, and authenticates with a Certivant API key sent as a bearer
token. There is no separate MCP credential to provision.
Before you start
Get an API key. Mint one in the dashboard at KYC → Developer
(Owner or Admin only). It starts with kyk_ and is shown once — see
Authentication.
Give it the right scopes. kyc:read is enough for triage,
explanation, and reporting. Add kyc:write to send forms, start
verifications, remind, renew, and submit KYB details. kyc:submit for
releasing a request to processing. The MCP server forwards your key
verbatim — a tool you lack the scope for returns the REST API's own 403.
Know your server URL. If Certivant is running the MCP server for you,
use the host you were given. If you run it yourself, it listens on
MCP_PORT (default 3007) and talks to the app at
CERTIVANT_API_BASE_URL (default http://localhost:3005).
Treat the API key in these config files exactly like a password. Anyone holding it can act on your organization with its scopes — including sending real email to your customers.
Run the server
If you are self-hosting alongside the rest of the platform:
# from the repo root
MCP_PORT=3007 \
CERTIVANT_API_BASE_URL=https://app.certivant.com \
pnpm --filter @repo/mcp start
Confirm it is up — this endpoint is unauthenticated on purpose and reports only that the process is listening, never that the REST API is healthy:
curl http://localhost:3007/health
# → {"status":"ok","service":"certivant","transport":"streamable-http",…}
Works with any MCP client
The Certivant MCP server follows the open Model Context Protocol, so it is not tied to Claude or any single vendor. Any assistant, editor, CLI, or platform that speaks MCP over Streamable HTTP can use it — Claude Desktop and Claude Code, Cursor, VS Code, OpenAI Codex, Google Gemini, Mistral, and new clients arriving all the time.
Whichever one you use, the shape is the same: point the client at
POST https://your-mcp-host/mcp and send your Certivant API key as
Authorization: Bearer kyk_…. The rest is that client's own config format. The
common ones are below — if yours is not listed, use the same URL and header in
its MCP settings and it will work.
Configure an MCP-native host
These hosts read a config file (or a settings UI) and connect to the server for you. Paste the endpoint and your key, and the tools appear in the assistant.
Add it from the CLI:
claude mcp add --transport http certivant https://your-mcp-host/mcp \
--header "Authorization: Bearer kyk_live_…"
Then check it connected:
claude mcp list
Edit ~/.cursor/mcp.json (global) or .cursor/mcp.json in the project:
{
"mcpServers": {
"certivant": {
"url": "https://your-mcp-host/mcp",
"headers": {
"Authorization": "Bearer kyk_live_…"
}
}
}
}
Create .mcp.json in the workspace (or add to your user mcp.json). Prompt for
the key rather than committing it:
{
"inputs": [
{
"id": "certivant-key",
"type": "promptString",
"description": "Certivant API key (kyk_…)",
"password": true
}
],
"servers": {
"certivant": {
"type": "http",
"url": "https://your-mcp-host/mcp",
"headers": {
"Authorization": "Bearer ${input:certivant-key}"
}
}
}
}
Claude Desktop's claude_desktop_config.json launches local servers, so a
remote HTTP endpoint is bridged with mcp-remote:
{
"mcpServers": {
"certivant": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://your-mcp-host/mcp",
"--header",
"Authorization: Bearer kyk_live_…"
]
}
}
}
Restart Claude Desktop after editing the file.
Codex reads ~/.codex/config.toml (or a project .codex/config.toml in a
trusted folder). Add a Streamable HTTP server and source the key from an
environment variable so it is not stored in plain text:
[mcp_servers.certivant]
url = "https://your-mcp-host/mcp"
bearer_token_env_var = "CERTIVANT_API_KEY"
Or add it from the CLI:
export CERTIVANT_API_KEY=kyk_live_…
codex mcp add certivant \
--url https://your-mcp-host/mcp \
--bearer-token-env-var CERTIVANT_API_KEY
Codex sends the value as Authorization: Bearer <token>. For a header other
than Authorization, use http_headers instead of bearer_token_env_var.
Add the server to ~/.gemini/settings.json (or a project .gemini/settings.json).
The httpUrl key selects the Streamable HTTP transport:
{
"mcpServers": {
"certivant": {
"httpUrl": "https://your-mcp-host/mcp",
"headers": {
"Authorization": "Bearer kyk_live_…"
}
}
}
}
Build your own agent (APIs & frameworks)
The section above covers the ready-made clients you just point at the server — Claude, Cursor, VS Code, OpenAI Codex, Gemini CLI. This section is for building your own agent in code. Every model-provider API that supports remote MCP works — OpenAI's Responses API, Anthropic's Messages API, Google Gemini, Mistral — as do the model-agnostic agent frameworks, the Vercel AI SDK and LangChain, which expose the Certivant tools to whatever model you drive. All of them speak the same Streamable HTTP transport, so the same tools are available everywhere.
Who makes the connection matters.
- Provider-hosted connectors — OpenAI's Responses API, Anthropic's
Messages API, Gemini, and Mistral's connector call your MCP server from
their cloud. So the endpoint must be internet-reachable (a
http://localhost:3007dev server will not work — use your deployed HTTPS host), and your API key travels to that provider. - Framework clients — the Vercel AI SDK and LangChain connect from your own code, so the key stays in your process and a local endpoint is fine.
Either way, scope the key to the minimum the workflow needs, and prefer a
kyc:read-only key for autonomous or unattended runs — a kyc:write key
lets a model send real email to your customers with no human in the loop
unless you gate it.
The Responses API takes a remote MCP server directly in tools. It fetches the
tool list from the server and lets the model call it.
from openai import OpenAI
client = OpenAI()
resp = client.responses.create(
model="gpt-4.1",
tools=[
{
"type": "mcp",
"server_label": "certivant",
"server_url": "https://your-mcp-host/mcp",
"headers": {"Authorization": "Bearer kyk_live_…"},
# Gate write tools rather than skipping every prompt — see below.
"require_approval": "always",
}
],
input="What's in my verification queue today?",
)
print(resp.output_text)
require_approval: "never" skips the human confirmation on every tool,
including the ones that email customers, start verifications, or send
reminders. For unattended use, either keep "always", pass an object that
only auto-approves the read tools, or use a kyc:read-only key so no
write tool exists to call.
The same tools entry works from the Node SDK and from a raw
POST https://api.openai.com/v1/responses call.
Claude's own Messages API attaches a remote MCP server directly — a useful reminder that Certivant is a standard server, not a Claude-specific one.
import anthropic
client = anthropic.Anthropic()
resp = client.beta.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": "What's in my verification queue today?"}],
mcp_servers=[
{
"type": "url",
"url": "https://your-mcp-host/mcp",
"name": "certivant",
"authorization_token": "kyk_live_…", # sent as Authorization: Bearer
}
],
betas=["mcp-client-2025-04-04"],
)
Anthropic's MCP connector is beta and actively changing — the beta
header version, and whether the server is passed in mcp_servers or inside
the tools array, have both moved. Treat the snippet as illustrative and
follow the current MCP connector
docs for
the exact shape.
Google's SDK connects through an MCP client session. Open a Streamable HTTP
session against the server and hand it to generate_content as a tool.
import asyncio
from google import genai
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
client = genai.Client()
async def main():
async with streamablehttp_client(
"https://your-mcp-host/mcp",
headers={"Authorization": "Bearer kyk_live_…"},
) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
resp = await client.aio.models.generate_content(
model="gemini-2.0-flash",
contents="What's in my verification queue today?",
config=genai.types.GenerateContentConfig(tools=[session]),
)
print(resp.text)
asyncio.run(main())
Gemini's MCP support is experimental and, at the time of writing, calls tools only — the server's resources and prompts are ignored. The tools are the load-bearing part, so this is rarely a problem in practice.
Mistral connects through a connector you add in Le Chat or in La Plateforme, rather than in code. Mistral requires the same Streamable HTTP transport and bearer auth the server already uses.
https://your-mcp-host/mcp.Choose HTTP Bearer token as the auth method and paste your
kyk_… key. Mistral also supports OAuth 2.1 for servers that offer it —
see the note at the bottom of this page.
initialize handshake and lists the tools.Mistral's connector requires HTTPS with a valid TLS certificate and a
server that returns 200 and answers the initialize call. The deployed
Certivant host satisfies this; a plain-HTTP or self-signed dev server does
not.
The AI SDK connects to the server and exposes its tools to any model you drive
with generateText / streamText — one integration, every model.
import { experimental_createMCPClient as createMCPClient } from "ai";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const mcp = await createMCPClient({
transport: new StreamableHTTPClientTransport(
new URL("https://your-mcp-host/mcp"),
{ requestInit: { headers: { Authorization: "Bearer kyk_live_…" } } },
),
});
const tools = await mcp.tools();
// hand `tools` to generateText({ model, tools, prompt }) with any provider's model
createMCPClient is still flagged experimental_ in the AI SDK.
langchain-mcp-adapters turns the server's tools into LangChain tools for any
LangChain or LangGraph agent, on any model.
from langchain_mcp_adapters.client import MultiServerMCPClient
client = MultiServerMCPClient(
{
"certivant": {
"transport": "streamable_http",
"url": "https://your-mcp-host/mcp",
"headers": {"Authorization": "Bearer kyk_live_…"},
}
}
)
tools = await client.get_tools()
# give `tools` to any LangGraph / LangChain agent
Verify the connection
Ask the assistant "what's in my verification queue today?". It should call
get_todays_queue and come back with counts. If instead you see an
authentication error, the server tells you which of the three failure modes you
hit:
| Response | Cause |
|---|---|
Missing Authorization header… | The host is not sending the header at all — check spelling and quoting in the config. |
Malformed Authorization header… | The value is not of the form Bearer <token>. |
Bearer token does not look like a Certivant API key… | The token is missing the kyk_ prefix. |
| A 401/403 from a tool call | The key itself is invalid, revoked, or lacks the scope. The MCP server does not validate keys — that verdict came from the REST API. |
All four arrive as JSON-RPC errors with a WWW-Authenticate header.
About OAuth
An OAuth 2.1 + Dynamic Client Registration flow is implemented so
directory-listed connectors can install Certivant without pasting a key: the
server answers an unauthenticated request with a WWW-Authenticate pointer
to its protected-resource metadata, and the sign-in, organization choice and
consent happen in Certivant. The tokens it issues behave like API keys. The
guides above use the bearer API key, which works in every host.
MCP Server
Connect an AI assistant to Certivant over the Model Context Protocol — triage the verification queue, send and track forms, chase stalled applicants, explain decisions, and report, all through your existing API key.
Tool reference
All 26 Certivant MCP tools grouped by the job they do — queue triage, sending and tracking forms, lifecycle actions, decision explanation and network risk, live ID verification sessions, KYB registry checks, and reporting — with what each returns and what it deliberately does not.