{
  "name": "sapling",
  "title": "Sapling AI",
  "version": "0.1.0",
  "description": "Sapling's language AI as MCP tools: grammar and spelling checking, AI-generated text detection, rephrasing, summarization, simplification, translation, tone, sentiment and quality scoring, classification, extraction, named-entity recognition, PII redaction, content safety, SEO metadata, style-guide checks and autocomplete.",
  "icon": "https://sapling.ai/static/img/sapling-128x128.png",
  "websiteUrl": "https://sapling.ai/mcp",
  "documentationUrl": "https://sapling.ai/docs/mcp/",
  "serverUrl": "https://mcp.sapling.ai/mcp",
  "transport": "streamable-http",
  "protocolVersions": [
    "2024-11-05",
    "2025-03-26",
    "2025-06-18"
  ],
  "authentication": {
    "required": true,
    "schemes": [
      "oauth2",
      "bearer"
    ],
    "protectedResourceMetadata": "https://mcp.sapling.ai/.well-known/oauth-protected-resource",
    "authorizationServer": "https://api.sapling.ai",
    "scopes": [
      "sapling:api"
    ],
    "description": "Sign in with a Sapling account (OAuth 2.1 + PKCE), or send a Sapling API key as 'Authorization: Bearer <key>'."
  },
  "packages": [
    {
      "registryType": "npm",
      "identifier": "@saplingai/mcp-server",
      "transport": {
        "type": "stdio"
      },
      "environmentVariables": [
        {
          "name": "SAPLING_API_KEY",
          "isRequired": true,
          "isSecret": true
        }
      ]
    }
  ],
  "capabilities": {
    "tools": true
  },
  "tools": [
    {
      "name": "sapling_grammar_check",
      "title": "Grammar and spelling check",
      "description": "Check text for grammar, spelling, and style issues. Returns a list of suggested edits, each with the sentence, character span (start/end), replacement text, and an error type. Set auto_apply=true to also receive applied_text: the input with all suggested edits already applied (useful to return a corrected document in one call). Supports many languages via the lang parameter.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_spellcheck",
      "title": "Spelling-only check",
      "description": "Check text for spelling errors only (no grammar or style suggestions). Returns edits in the same format as sapling_grammar_check. Faster and cheaper than a full grammar check when only misspellings matter.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_ai_detect",
      "title": "AI-generated text detection",
      "description": "Score how likely a text is to be AI-generated. Returns an overall score between 0 (likely human-written) and 1 (likely AI-generated), plus per-sentence scores by default. Provide at least ~50 characters of text for a meaningful score.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_rephrase",
      "title": "Rephrase / paraphrase",
      "description": "Generate alternative phrasings of a text. mapping selects the transformation (default \"paraphrase\"); num_results controls how many alternatives are returned (default 5).",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_summarize",
      "title": "Summarize text",
      "description": "Summarize a longer text, webpage or email thread (HTML input is accepted and flattened). Returns a prose `summary` plus a `key_points` list, sized by the optional `length` option.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_tone",
      "title": "Tone classification",
      "description": "Classify the emotional tone of a text (e.g. friendly, confident, sad, angry). Returns overall and per-sentence tone labels with confidence scores.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_sentiment",
      "title": "Sentiment analysis",
      "description": "Classify the sentiment of a text (positive / neutral / negative). Returns overall and per-sentence sentiment with confidence scores.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_detect_language",
      "title": "Language detection",
      "description": "Detect the language a text is written in. Returns an ISO 639-1 code and a confidence value.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_detect_pii",
      "title": "PII detection and redaction",
      "description": "Detect personally identifiable information (emails, phone numbers, US SSNs, credit card numbers, IP addresses, IBANs, US bank routing numbers) in a text. Detection is deterministic (regex + checksum validation, no ML), and every entity comes with exact character offsets (start/end) into the submitted text. Set redact=true to also receive redacted_text: the input with each entity replaced by a placeholder like [EMAIL]. Person names and street addresses are not detected.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_readability_statistics",
      "title": "Readability statistics",
      "description": "Compute readability statistics for a text: grade-level readability scores, estimated reading time, and counts of characters, words, and sentences.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_quality",
      "title": "Writing quality score",
      "description": "Score the writing quality of a text from 1 (poor) to 5 (excellent). Returns score: a fluency/grammaticality score from a language model. Set sentence_scores=true to also get a per-sentence breakdown (sentences with start/end offsets and their own score) to find the weakest sentences. Set rubric=true for an LLM-judged rubric: overall score, per-dimension scores (clarity, coherence, correctness, concision), a summary, and concrete issues each with the quoted excerpt, offsets, a note, and a suggested rewrite. rubric=true is billed at a higher rate than the plain score.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_seo",
      "title": "SEO analysis and metadata",
      "description": "Analyze a page or article for on-page SEO and generate metadata. Returns stats (words, sentences, paragraphs, reading time, Flesch reading ease and grade), per-target-keyword count/density/whether it appears in the first 100 words, top_terms (the most frequent content words and phrases), and suggestions: title-tag candidates (the model aims for <=60 chars; any over a 90-char hard cap are dropped), meta-description candidates (aims for 120-155 chars; hard cap 220), a URL slug (null if none could be derived) and focus-keyword ideas, written in the language of the text. Pass keywords to have them worked into the suggestions. Set suggestions=false for the free stats-only analysis (suggestions are the billed part). lang (ISO 639-1, default \"en\") selects the readability formulas; unsupported languages get null readability.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_classify",
      "title": "Zero-shot text classification",
      "description": "Classify a text into a set of labels you supply — intent, topic, category, routing queue, sentiment buckets, anything — without training data. Returns label (the best match, always one of your labels), labels (single-label: just the best match; multi-label: every label whose score >= threshold, possibly empty), scores (one {label, score} per input label, descending; a distribution in single-label mode, independent 0-1 applicability in multi-label mode) and a one-sentence rationale. Labels can be plain names or {name, description} objects — a short description per label sharpens borderline decisions. Use context to say what the texts are (e.g. \"support tickets for a billing product\"). 2-20 labels.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_extract",
      "title": "Structured data extraction",
      "description": "Pull structured fields out of unstructured text — invoice numbers, amounts, dates, names, addresses, order ids, anything the document actually states — by describing the fields you want. Returns data (a {field: value} map, null where the text does not state the field), fields (per-field value, the verbatim evidence span it came from, and whether it was found) and missing (the fields the text did not yield). Values are returned in the type you declare (string, number, integer, boolean, date as YYYY-MM-DD, or list of strings) and a value that will not convert is reported missing rather than returned in the wrong type. This is EXTRACTION, not summarization or inference: except for boolean fields, a value must be traceable to a span of the text or it is dropped. Use context to say what the document is. 1-20 fields.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_translate",
      "title": "Translate text",
      "description": "Translate a text into a target language with an LLM. Returns translation, the detected source language (source_lang code + source_lang_name; the detection is reported, never guessed from the hint) and the normalized target (target_lang, target_lang_name). Line breaks, markup and placeholders are preserved in place. target_lang and source_lang accept an ISO 639 code (\"fr\", \"zh-TW\") or an English language name (\"French\"); region variants zh-CN/zh-TW/zh-HK, pt-BR/pt-PT, en-GB/en-US, fr-CA and es-419 are supported as targets. Optional formality picks a formal or informal register where the target language distinguishes them.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_styleguide",
      "title": "Check text against a style guide",
      "description": "Check a text for compliance with caller-supplied style rules (house style, brand voice, editorial guidelines). Returns violations — each with the verbatim offending passage, its start/end offsets in the submitted text (null when the passage cannot be located), the violated rule name, a brief note and a compliant rewrite suggestion — plus a top-level compliant boolean. Only the listed rules are enforced; an empty violations list means the text complies. The text is checked as submitted (markup included), so offsets always index it directly. Provide exactly one of rules (inline) or ruleset (the name of a rule set saved via the API).",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_simplify",
      "title": "Plain-language simplification",
      "description": "Rewrite a text in plain language at a target reading level, keeping all of its content, structure and language (nothing is summarized or dropped). Returns simplified (the rewrite) plus a before/after readability block (Flesch-Kincaid grade and reading ease) when the language supports it, so the improvement is verifiable. Use preserve_terms for names or defined terms that must survive verbatim. Pairs with sapling_readability_statistics for scoring text first.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_autocomplete",
      "title": "Autocomplete a sentence",
      "description": "Predict how a partially written sentence continues. Send the trailing text the user has typed as query (200 characters maximum) and the tool returns the predicted continuation. Requires an API key with autocomplete enabled; other keys get an explicit error back.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_safety",
      "title": "Content safety check",
      "description": "Score a text for unsafe content across seven categories — toxicity, profanity, harassment, hate_speech, self_harm, sexual, violence — each as a 0-1 probability. Returns scores (all seven), flagged (whether any category reached the threshold, default 0.5) and flagged_categories. With spans=true, also returns spans: the specific offending passages, each with its text, start/end offsets into the submitted text, per-category scores and flagged_categories — use it to highlight, quote, or redact just the violating passage instead of rejecting the whole text.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    },
    {
      "name": "sapling_ner",
      "title": "Named-entity recognition",
      "description": "Find named entities in a text — people, organizations, locations, dates, times, money amounts, percentages, quantities, products, events — with character spans. Returns entities (each with its verbatim text, type, and start/end offsets into the exact submitted text) and types (the distinct types found). Every entity is a span the text actually contains — invented mentions are dropped. Offsets index the submitted text as-is (nothing is stripped or normalized), so they can be applied directly to your copy of the document. Use types to restrict recognition to a subset. Complements sapling_detect_pii: that tool finds checksum-validated identifiers (emails, cards, IBANs...), this one finds names and real-world references.",
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": true
      }
    }
  ]
}
