Skip to main content
Glama
aflsolutions

ShadowGit MCP Server

by aflsolutions

Create a ShadowGit checkpoint

checkpoint

Saves current project changes as one named ShadowGit checkpoint, honoring .shadowgit-ignore and leaving the project's own git repo untouched. Returns the commit hash and checks project rules.

Instructions

Save the project's current changes to ShadowGit history as one named checkpoint, following the project's .shadowgit-ignore. Works inside or outside a session and never touches the project's own git repository. Returns the commit hash. When the project has rules, in its .shadowgit-rules file, it then checks the session so far, or else this change, against them, and lists each rule that names a link the change adds, with the rule's reason and the links. Outside a session, an automatic snapshot may take the changes first, leaving nothing to check. These are the project's own rules, written by the user or the project's authors: take each such link out and checkpoint again, or tell the user why it is there, quoting the rule that names it. A check still running names its range for get_lens. Needs the ShadowGit app running.

Input Schema

NameRequiredDescriptionDefault
repoNoProject name or absolute path. Defaults to the current project.
titleYesOne line saying what changed, e.g. "Fix login redirect loop"
messageNoOptional details: why, and anything a reviewer should know

Output Schema

NameRequiredDescriptionDefault
repoYes
rulesNoThe change checked against the project's rules; absent for a project without them
titleYes
commitYes
files_changedYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv2.5.0
    • addedOutput schema / properties / rules
      Added value: +{
      +  "description": "The change checked against the project's rules; absent for a project without them",
      +  "oneOf": [
      +    {
      +      "additionalProperties": false,
      +      "properties": {
      +        "check": {
      +          "additionalProperties": false,
      +          "properties": {
      +            "file": {
      +              "anyOf": [
      +                {
      +                  "additionalProperties": false,
      +                  "properties": {
      +                    "added": {
      +                      "items": {
      +                        "type": "string"
      +                      },
      +                      "type": "array"
      +                    },
      +                    "removed": {
      +                      "items": {
      +                        "type": "string"
      +                      },
      +                      "type": "array"
      +                    }
      +                  },
      +                  "required": [
      +                    "added",
      +                    "removed"
      +                  ],
      +                  "type": "object"
      +                },
      +                {
      +                  "type": "null"
      +                }
      +              ],
      +              "description": "The rules the range adds to and removes from .shadowgit-rules; null when it leaves the file alone"
      +            },
      +            "matches": {
      +              "items": {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "count": {
      +                    "description": "How many links the range adds that the rule names",
      +                    "maximum": 9007199254740991,
      +                    "minimum": -9007199254740991,
      +                    "type": "integer"
      +                  },
      +                  "links": {
      +                    "description": "The first links, in words; count has them all",
      +                    "items": {
      +                      "type": "string"
      +                    },
      +                    "type": "array"
      +                  },
      +                  "rule": {
      +                    "additionalProperties": false,
      +                    "properties": {
      +                      "because": {
      +                        "description": "Its reason, as written after \"because\"",
      +                        "type": [
      +                          "string",
      +                          "null"
      +                        ]
      +                      },
      +                      "form": {
      +                        "description": "never, only or nothing",
      +                        "type": "string"
      +                      },
      +                      "from": {
      +                        "description": "The names on its first side; none for a nothing-rule",
      +                        "items": {
      +                          "type": "string"
      +                        },
      +                        "type": "array"
      +                      },
      +                      "line": {
      +                        "maximum": 9007199254740991,
      +                        "minimum": -9007199254740991,
      +                        "type": "integer"
      +                      },
      +                      "text": {
      +                        "description": "The rule as written, without its reason",
      +                        "type": "string"
      +                      },
      +                      "to": {
      +                        "items": {
      +                          "type": "string"
      +                        },
      +                        "type": "array"
      +                      }
      +                    },
      +                    "required": [
      +                      "line",
      +                      "text",
      +                      "form",
      +                      "from",
      +                      "to",
      +                      "because"
      +                    ],
      +                    "type": "object"
      +                  },
      +                  "steps": {
      +                    "description": "The ids of the steps that hold them",
      +                    "items": {
      +                      "type": "string"
      +                    },
      +                    "type": "array"
      +                  }
      +                },
      +                "required": [
      +                  "rule",
      +                  "count",
      +                  "links",
      +                  "steps"
      +                ],
      +                "type": "object"
      +              },
      +              "type": "array"
      +            },
      +            "rules": {
      +              "description": "How many rules it was checked against",
      +              "maximum": 9007199254740991,
      +              "minimum": -9007199254740991,
      +              "type": "integer"
      +            }
      +          },
      +          "required": [
      +            "rules",
      +            "matches",
      +            "file"
      +          ],
      +          "type": "object"
      +        },
      +        "range": {
      +          "additionalProperties": false,
      +          "properties": {
      +            "base": {
      +              "type": [
      +                "string",
      +                "null"
      +              ]
      +            },
      +            "head": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "base",
      +            "head"
      +          ],
      +          "type": "object"
      +        },
      +        "status": {
      +          "const": "checked",
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "status",
      +        "range",
      +        "check"
      +      ],
      +      "type": "object"
      +    },
      +    {
      +      "additionalProperties": false,
      +      "properties": {
      +        "range": {
      +          "additionalProperties": false,
      +          "description": "Read its check with get_lens, passing this base and head",
      +          "properties": {
      +            "base": {
      +              "type": [
      +                "string",
      +                "null"
      +              ]
      +            },
      +            "head": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "base",
      +            "head"
      +          ],
      +          "type": "object"
      +        },
      +        "status": {
      +          "const": "running",
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "status",
      +        "range"
      +      ],
      +      "type": "object"
      +    },
      +    {
      +      "additionalProperties": false,
      +      "properties": {
      +        "error": {
      +          "type": "string"
      +        },
      +        "range": {
      +          "anyOf": [
      +            {
      +              "additionalProperties": false,
      +              "properties": {
      +                "base": {
      +                  "type": [
      +                    "string",
      +                    "null"
      +                  ]
      +                },
      +                "head": {
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "base",
      +                "head"
      +              ],
      +              "type": "object"
      +            },
      +            {
      +              "type": "null"
      +            }
      +          ]
      +        },
      +        "status": {
      +          "const": "failed",
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "status",
      +        "range",
      +        "error"
      +      ],
      +      "type": "object"
      +    }
      +  ]
      +}
  2. Changed11 schema fields changedv2.1.1
    • addedInput schema / $schema
      Added value: +"https://json-schema.org/draft/2020-12/schema"
    • removedInput schema / properties / author
      Removed value: -{
      -  "description": "Author name (e.g., \"Claude\", \"GPT-4\"). Defaults to \"AI Assistant\"",
      -  "type": "string"
      -}
    • changedInput schema / properties / message / description
      Previous value: -"Detailed commit message (optional, max 1000 chars)"New value: +"Optional details: why, and anything a reviewer should know"
    • addedInput schema / properties / message / maxLength
      Added value: +1000
    • changedInput schema / properties / repo / description
      Previous value: -"Repository name"New value: +"Project name or absolute path. Defaults to the current project."
    • addedInput schema / properties / repo / minLength
      Added value: +1
    • changedInput schema / properties / title / description
      Previous value: -"Commit title (max 50 chars) - REQUIRED. Be specific about what was changed."New value: +"One line saying what changed, e.g. \"Fix login redirect loop\""
    • addedInput schema / properties / title / maxLength
      Added value: +72
    • addedInput schema / properties / title / minLength
      Added value: +1
    • changedInput schema / required
      Previous value: -[
      -  "repo",
      -  "title"
      -]New value: +[
      +  "title"
      +]
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "https://json-schema.org/draft/2020-12/schema",
      +  "additionalProperties": false,
      +  "properties": {
      +    "commit": {
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "files_changed": {
      +      "type": "number"
      +    },
      +    "repo": {
      +      "type": "string"
      +    },
      +    "title": {
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "commit",
      +    "title",
      +    "files_changed",
      +    "repo"
      +  ],
      +  "type": "object"
      +}
  3. Addedv1.0.0

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds substantial context beyond the annotations: it honors .shadowgit-ignore, never touches the project's git repo, requires the ShadowGit app to be running, and warns that an automatic snapshot outside a session may consume the changes so nothing is left to check. That auto-snapshot caveat is exactly the kind of side-effect disclosure an agent needs before committing to a call.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and return value, then layers on the rules check and prerequisites, with no filler sentences. Some clauses are grammatically tangled, notably the nested rules sentence, which slightly slows comprehension.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers prerequisites, side effects, rule-violation handling guidance, and interoperability with get_lens; the output schema plus the stated commit-hash return means nothing about return values is missing. For a non-destructive but non-idempotent write, this is an adequate and complete picture.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already explains repo, title, and message. The description only implies that the title names the checkpoint and adds no format or constraint details beyond the schema. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: save the project's current changes to ShadowGit history as one named checkpoint. It also explicitly contrasts with the project's own git repository, which separates it from the git_command sibling. An agent can identify the tool from the first sentence alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context for when it applies: inside or outside a session, with explicit instructions on what to do when project rules name an added link, and a pointer to get_lens for an in-progress check. It does not explicitly say when to prefer git_command over this tool, so the alternative routing is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.