Skip to main content
Glama
alessandro-afloarei

ShadowGit MCP Server

Create a ShadowGit checkpoint

checkpoint

Save the project's current changes to ShadowGit history as one named checkpoint without touching its own git repository. Returns the commit hash and checks the change against the project's 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 save: the check then reads that snapshot. 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?

Beyond the annotations, the description discloses important behavior: it follows .shadowgit-ignore, may trigger a rule check, may let an automatic snapshot take changes first outside a session, and requires the ShadowGit app to be running. It also explains what to do when project rules identify links in the change, which is valuable operational context.

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?

The core purpose is front-loaded in the first sentence, and every subsequent sentence adds relevant context about rules, snapshots, or prerequisites. However, the middle sentence about rule checking is dense and could be clearer with structure.

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?

The description covers prerequisites, side effects, rule-check behavior, outside-session snapshot behavior, and the get_lens relationship. With an output schema present and complete parameter coverage, an agent has enough information to invoke this tool correctly.

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 documents repo, title, and message. The description adds only that the checkpoint is named and returns a commit hash, but does not add parameter-level meaning beyond the schema.

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?

The description states a specific verb and resource: save the project's current changes to ShadowGit history as one named checkpoint. It also clarifies scope by saying it works inside or outside a session and never touches the project's own git repository, which distinguishes it from git_command.

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?

The description gives clear context for when this applies, including inside or outside a session and the prerequisite that the ShadowGit app must be running. It does not explicitly name git_command as an alternative, but the distinction is implied by saying it never touches the project's own git repository.

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