Skip to content

MCP server

Vendorica ships a Model Context Protocol server, so an AI agent can read your compliance posture, controls, vendors and incidents as tools rather than by you pasting exports into a chat window.

POST https://api.vendorica.com/mcp

Stateless Streamable HTTP, plain JSON responses. Every request is a complete JSON-RPC exchange — there is no session to keep alive and nothing to reconnect.

Both resolve to the same principal, and both carry your organization’s scopes.

Credential Looks like Use it for
API key vnd_live_… your own agents and scripts
OAuth access token vnd_mcp_at_… connecting a hosted assistant

For the OAuth path the server implements discovery, dynamic client registration and PKCE, so a client that speaks MCP can connect without anyone pre-registering it:

GET /.well-known/oauth-authorization-server
POST /mcp/oauth/register
GET /mcp/oauth/authorize ← the human consents here
POST /mcp/oauth/token

A 401 from POST /mcp carries a WWW-Authenticate header pointing at the protected-resource metadata, which is how a client discovers where to authorize. That header is part of the contract, not an implementation detail.

Tools come in two lanes, and the lane travels on the wire as the MCP tool annotations your client reads. That is what lets Claude — or any client that honours the annotations — run a read under a standing approval while stopping to ask a human before a write.

Lane Annotation What a client should do with it
Read readOnlyHint: true, openWorldHint: false Answers a question about data you already hold and changes nothing. Safe to allow once for the session.
Write readOnlyHint: false, destructiveHint: false Mutates something, spends your AI budget, or leaves Vendorica. Put a person in front of each call.

destructiveHint is false on every tool and always will be: nothing that deletes or irreversibly overwrites is exposed as a tool at all.

Tool Scope What it answers
get_compliance_posture compliance:read overall readiness, by framework
get_control_status controls:read one control in full, or a search by name — status, owner, domain, and the framework citations it satisfies
list_vendors vendors:read the vendor register, paginated — filter by name, lifecycle state, country or inherent-risk band
query_vendor_risk vendors:read + risks:read vendors with their open risk scenarios, scores and approval status
list_contracts contracts:read the contract register, paginated — filter by counterparty, lifecycle phase or creation date
list_incidents incidents:read the incident register, paginated — filter by title, status, priority or vendor
get_incident_context incidents:read one incident: classification, severity, status, reporter, timeline
search_regulatory_requirements controls:read the regulatory knowledge base
run_gap_analysis compliance:read per-citation gaps for a framework, worst first, with the counts behind each score
get_audit_evidence evidence:read evidence for a control — automated test results and manual uploads together
Tool Scope What it does
draft_policy policies:write a policy draft grounded in the knowledge base, returned with its citations

draft_policy saves nothing, so calling it a write is a judgement — and it is the judgement the annotation exists to express. Each call spends your organization’s AI budget and reaches a model provider (hence openWorldHint: true), and it is the one tool whose scope the default OAuth grant withholds. A client that auto-ran it would be auto-spending.

The three list_* tools return pagination alongside the rows, and default to 25 rows per call (100 maximum) rather than the /v1 default of 100. The bound is about the model, not the database: a page of 500 rows is context the agent pays for and then has less room left to reason with. Walk a whole register by following pagination.totalPages:

{
"tool": "list_vendors",
"arguments": { "state": "active", "page": 2, "limit": 50 }
}

Plus resources for the regulatory texts themselves:

regulation://dora/articles
regulation://mica/articles

Resources carry no lane — a resource is a read by definition, and the protocol has no annotation for one.

Scopes bind the agent exactly as they bind a key. A tool call runs with the scopes of the credential behind it, so a read-only key stays read-only through MCP. get_audit_evidence additionally excludes evidence flagged sensitive for agent connections.

The lane and the scope agree by construction. A write-lane tool gates on a :write scope and a read-lane tool gates only on :read scopes — the server refuses to start otherwise. So the annotation your client trusts and the authorization the server enforces are two readings of one declaration, not two lists someone keeps in sync.

The whole catalogue is listed even when your credential is narrower. A tool you cannot call answers with an isError result naming the scope to re-consent to, rather than being hidden — an agent that cannot see a tool reports the feature as nonexistent, which is a worse answer than “ask for this scope”.

draft_policy does not save anything. It returns markdown and the citations it was grounded in; a human reviews it and creates the policy in Vendorica. AI suggests, people confirm — and that boundary is in the server, not in a prompt.

Every tool call is logged. Each invocation writes an audit row, and an OAuth-token call also records the human who granted the connection, so “the agent did it” is never the end of the trail.

120/min, keyed per client — deliberately tighter than the /v1 read budget because one tool call fans out into several kernel queries. Not overridable. See rate limits.