turva-mcp
Read-only MCP server for turva.dev, an agent-readiness audit and advisory service.
Should I use this
Quality & Safety
Based on automated analysis of tool definitions and protocol compliance.
Context Cost
This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.
Install
One-Click Install
Add this to your `claude_desktop_config.json` file:
{
"mcpServers": {
"turva-mcp": {
"url": "https://mcp.turva.dev/mcp"
}
}
}Remote endpoints
https://mcp.turva.dev/mcpstreamable-httpWhat it can do
Tool inventory
Tools (5)
🟢get_services
Returns turva.dev's service catalog: the Shopify agent storefront check, agent-readiness audit, advisory, implementation, agent operations, and MCP server design, plus the engagement model and pricing (fixed list prices for the Shopify agent storefront check, audit, advisory and implementation; agent operations and MCP server design on request), and two implementation add-ons that carry a fixed price and are sold only with the diagnosis they follow, bought with it, with its report, or after the report and before implementation starts. The Shopify agent storefront check and the audit each link a published sample report in sample_url, a fictional worked example of the deliverable. Use this when a user asks what turva.dev offers, what it costs, how an engagement works, or what a delivered report looks like. For how to reach turva.dev use get_contact instead, and for the rules an engagement follows use get_principles. Read-only: returns static JSON that is compiled into the Worker, so it changes nothing and updates only on deploy.
Input Schema
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}Output Schema
{
"type": "object",
"properties": {
"pricing_model": {
"type": "string",
"description": "The pricing model. fixed_list_prices means fixed list prices, apart from the services priced on request."
},
"pricing_note": {
"type": "string",
"description": "The VAT treatment by customer type, the services quoted per engagement and the rule for the add-ons."
},
"currency": {
"type": "string",
"description": "ISO 4217 code of every price, EUR."
},
"vat_included": {
"type": "boolean",
"description": "Whether the prices include VAT. False means every price excludes VAT."
},
"engagement": {
"type": "object",
"properties": {
"communication": {
"type": "string",
"description": "How an engagement is communicated, async_only for written exchange with no calls."
},
"notes": {
"type": "array",
"items": {
"type": "string",
"description": "One term of an engagement as a sentence."
},
"description": "Terms of an engagement, one per entry, covering access, scope, dates and completion."
}
},
"required": [
"communication",
"notes"
],
"additionalProperties": false,
"description": "How an engagement is run."
},
"services": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stable identifier of the service."
},
"name": {
"type": "string",
"description": "The name of the service."
},
"url": {
"type": "string",
"description": "The turva.dev page that describes the service."
},
"sample_url": {
"description": "A published sample of the deliverable, where one exists.",
"type": "string"
},
"price": {
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"const": "on request"
}
],
"description": "EUR, VAT not included, or on request."
},
"unit": {
"description": "What the price covers, such as fixed, month or day. Absent when the price is on request.",
"type": "string"
},
"duration": {
"description": "How long delivery takes, where the service states one.",
"type": "string"
},
"duration_from": {
"description": "The event the duration counts from, where the service states one.",
"type": "string"
},
"minimum_commitment": {
"description": "The shortest term the service is sold for, where one applies.",
"type": "string"
},
"summary": {
"type": "string",
"description": "What the service covers and its scope."
},
"deliverable": {
"type": "string",
"description": "What the customer receives and when."
}
},
"required": [
"id",
"name",
"url",
"price",
"summary",
"deliverable"
],
"additionalProperties": false
},
"description": "The services with their prices."
},
"bundled_implementation": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stable identifier of the add-on."
},
"name": {
"type": "string",
"description": "The name of the add-on."
},
"price": {
"type": "number",
"description": "Price in EUR, VAT not included."
},
"unit": {
"type": "string",
"description": "What the price covers, such as fixed."
},
"requires": {
"type": "string",
"description": "The id of the service this add-on is sold with."
},
"sold_separately": {
"type": "boolean",
"description": "Whether the add-on can be bought without its service. False means it cannot."
},
"summary": {
"type": "string",
"description": "What the add-on covers and when it is bought."
}
},
"required": [
"id",
"name",
"price",
"unit",
"requires",
"sold_separately",
"summary"
],
"additionalProperties": false
},
"description": "Implementation add-ons that are sold only with another service."
}
},
"required": [
"pricing_model",
"pricing_note",
"currency",
"vat_included",
"engagement",
"services",
"bundled_implementation"
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}🟢get_agent_readiness
Returns turva.dev's own agent-readiness score from an independent public scanner (isitagentready.com), including category sub-scores, with the measurement date and a link to the scanner's start page, where a new check can be run (the link does not open the recorded reading). Use this when a user asks how turva.dev scores, whether its claims are verifiable, or what proof backs the audit service. For web-security scan results, which are a separate measurement, use get_security_evidence instead. Read-only: returns static JSON that is compiled into the Worker, so it changes nothing and updates only on deploy.
Input Schema
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}Output Schema
{
"type": "object",
"properties": {
"domain": {
"type": "string",
"description": "The domain the reading is about."
},
"measured_at": {
"type": "string",
"description": "Date of the reading, YYYY-MM-DD."
},
"note": {
"type": "string",
"description": "A caveat that the scores are a point-in-time reading by an independent scanner and that the scan url opens the scanner's start page."
},
"scans": {
"type": "array",
"items": {
"type": "object",
"properties": {
"provider": {
"type": "string",
"description": "The domain of the scanner that produced the reading."
},
"result": {
"type": "string",
"description": "The scanner's overall result as text, giving the score out of 100 and the level reached."
},
"note": {
"type": "string",
"description": "Who runs the scanner and a reminder that the reading is the scanner's and can be re-run by anyone."
},
"categories": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string",
"description": "The category score as text, out of 100."
},
"description": "Sub-scores by category. Each key is a category name: discoverability, content, bot_access_control, api_auth_mcp_a2a_discovery or commerce."
},
"url": {
"type": "string",
"description": "The scanner's start page, where a new check can be run. It does not show the recorded reading."
}
},
"required": [
"provider",
"result",
"note",
"categories",
"url"
],
"additionalProperties": false
},
"description": "Readings from independent scanners, one per entry."
}
},
"required": [
"domain",
"measured_at",
"note",
"scans"
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}🟢get_security_evidence
Returns the latest public web-security scan results for turva.dev's own domain (Hardenize, Internet.nl site and mail), each with its scan date. Use this when a user asks about turva.dev's own security posture or wants evidence beyond agent-readiness scores. For the agent-readiness score itself, which is a separate measurement, use get_agent_readiness instead. Read-only: returns static JSON that is compiled into the Worker, so it changes nothing and updates only on deploy.
Input Schema
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}Output Schema
{
"type": "object",
"properties": {
"domain": {
"type": "string",
"description": "The domain the scans are about."
},
"measured_at": {
"type": "string",
"description": "Date of the scans, YYYY-MM-DD."
},
"scans": {
"type": "array",
"items": {
"type": "object",
"properties": {
"provider": {
"type": "string",
"description": "The name of the scan provider."
},
"result": {
"description": "The overall result as text, for a provider that reports passed categories instead of a number. Absent when a numeric score is given.",
"type": "string"
},
"score": {
"description": "The numeric score, on the range given in scale. Absent when the provider reports a text result.",
"type": "number"
},
"scale": {
"description": "The range of the score, written as low-high. Absent when there is no numeric score.",
"type": "string"
},
"note": {
"description": "What passed in full and where the points were lost. Absent when the provider adds no note.",
"type": "string"
},
"measured_at": {
"description": "Date of this reading, YYYY-MM-DD, on a reading that carries its own date. It can equal the top-level date.",
"type": "string"
},
"url": {
"type": "string",
"description": "The provider's public report page for the domain."
}
},
"required": [
"provider",
"url"
],
"additionalProperties": false
},
"description": "Web-security scan results, one per provider and test."
},
"note": {
"type": "string",
"description": "Why turva.dev publishes the scan results of its own domain."
}
},
"required": [
"domain",
"measured_at",
"scans",
"note"
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}🟢get_principles
Returns turva.dev's engagement principles: async-only, least access, the result shows up in scanner numbers, and open and verifiable. Use this when a user asks how turva.dev works with clients or what rules an engagement follows. For what is sold and what it costs use get_services instead, and for how to start use get_contact. Read-only: returns static JSON that is compiled into the Worker, so it changes nothing and updates only on deploy.
Input Schema
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}Output Schema
{
"type": "object",
"properties": {
"model": {
"type": "string",
"description": "The service model the principles belong to, agent_readiness_audit for the agent-readiness audit."
},
"rules": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stable identifier of the principle."
},
"title": {
"type": "string",
"description": "The principle in a short phrase."
},
"rationale": {
"type": "string",
"description": "What the principle means in practice and why it holds."
}
},
"required": [
"id",
"title",
"rationale"
],
"additionalProperties": false
},
"description": "The principles an engagement follows, one per entry."
}
},
"required": [
"model",
"rules"
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}🟢get_contact
Returns who runs turva.dev and the official ways to reach it: the operator and business details, the email address, the Signal link, the LinkedIn profile, the correspondence languages, the first-reply time and the access an audit needs. Use this when a user asks who is behind turva.dev, how to contact it, how to start an audit or what access has to be granted. For what is sold and what it costs use get_services instead. Read-only: returns static JSON that is compiled into the Worker, so it changes nothing and updates only on deploy.
Input Schema
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}Output Schema
{
"type": "object",
"properties": {
"email": {
"type": "string",
"description": "The email address for starting an engagement."
},
"signal": {
"type": "string",
"description": "A link that opens a Signal chat with the operator."
},
"linkedin": {
"type": "string",
"description": "The URL of the operator's LinkedIn profile."
},
"business_id": {
"type": "string",
"description": "The Finnish business ID of the business."
},
"location": {
"type": "string",
"description": "The city and country where the business is based."
},
"engagement": {
"type": "string",
"description": "How an engagement is communicated, async_only for written exchange with no calls."
},
"correspondence_languages": {
"type": "array",
"items": {
"type": "string",
"description": "An ISO 639-1 language code."
},
"description": "ISO 639-1 codes of the languages the correspondence is held in."
},
"first_reply": {
"type": "string",
"description": "How soon the first reply comes and by which channels, and that LinkedIn has no set reply time."
},
"channel_note": {
"type": "string",
"description": "Which channel suits which kind of message, and that there are no calls."
},
"how_to_start": {
"type": "array",
"items": {
"type": "string",
"description": "One step as a sentence."
},
"description": "The steps to start an engagement and the access an audit needs, one per entry."
},
"operator": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The trading name of the business."
},
"run_by": {
"type": "string",
"description": "The person who runs the business."
},
"legal_form": {
"type": "string",
"description": "The legal form of the business."
},
"business_id": {
"type": "string",
"description": "The Finnish business ID of the business."
},
"vat_id": {
"type": "string",
"description": "The VAT identification number of the business."
},
"location": {
"type": "string",
"description": "Where the business is based: city, region and country."
},
"team": {
"type": "string",
"description": "Who works at the business and how clients work with them."
},
"background": {
"type": "string",
"description": "The professional background of the person who runs the business."
},
"company_page": {
"type": "string",
"description": "The turva.dev page that states the business details."
}
},
"required": [
"name",
"run_by",
"legal_form",
"business_id",
"vat_id",
"location",
"team",
"background",
"company_page"
],
"additionalProperties": false,
"description": "Who runs turva.dev and the registered business behind it."
}
},
"required": [
"email",
"signal",
"linkedin",
"business_id",
"location",
"engagement",
"correspondence_languages",
"first_reply",
"channel_note",
"how_to_start",
"operator"
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}Community
Evidence