diff --git a/.github/brand/social.png b/.github/brand/social.png new file mode 100644 index 0000000..ca27666 Binary files /dev/null and b/.github/brand/social.png differ diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 72f8882..ee76bf5 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -23,6 +23,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - run: | + python3 Scripts/check-brand.py python3 -m unittest discover -s Tests -p 'test_*.py' python3 Scripts/build_package.py dist > package-receipt.json - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 diff --git a/AGENTS.md b/AGENTS.md index 2e0c234..9db22b0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,3 +11,11 @@ Keep vendor installation, authentication, subscription usage, and updates outsid Use Python standard library only unless a dependency demonstrably removes required complexity. Tests must cover MCP initialization, tool discovery, ACP framing, permission response, deterministic package contents, and executable archive mode. Before handoff run the unit tests, native non-model interface check, deterministic package build, Computer MCP package validation/doctor where available, and git status. Do not publish or create a release implicitly. + +## Brand delivery + +The main Computer MCP repository owns ProductIdentity and BRAND. Imported +`Documentation/Brand/header.svg` travels with the packaged manual; +`.github/brand/social.png` supplies the repository preview. `brand.lock.json` +binds both to canonical exports. Run `python3 Scripts/check-brand.py` locally +and in CI. Update imports with the main repository's `Scripts/brand.py sync`. diff --git a/Documentation/Brand/header.svg b/Documentation/Brand/header.svg new file mode 100644 index 0000000..02cfab9 --- /dev/null +++ b/Documentation/Brand/header.svg @@ -0,0 +1,13 @@ + + Computer MCP — Cursor + + + + + First-party plugin + Computer MCP + Cursor + + Cursor Agent CLI and ACP integration + + diff --git a/README.md b/README.md index 9d071d8..3e7120b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -# Cursor Plugin +![Computer MCP — Cursor](Documentation/Brand/header.svg) + +# Computer MCP — Cursor + +Part of the [Computer MCP](https://computer-mcp.github.io/) family. +**Let ChatGPT use your local tools.** An independent Computer MCP plugin for Cursor. The same package contributes a canonical CLI Tree, a stdio MCP adapter and client-neutral usage Skills. It does not link Computer MCP Core or require a host release to add vendor behavior. diff --git a/Scripts/check-brand.py b/Scripts/check-brand.py new file mode 100644 index 0000000..1cb6c74 --- /dev/null +++ b/Scripts/check-brand.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +"""Verify a repository's locked Computer MCP brand delivery without a source checkout.""" + +import hashlib +import json +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +LOCK = ROOT / "brand.lock.json" +if not LOCK.exists(): + LOCK = ROOT / "public/brand/brand.lock.json" +record = json.loads(LOCK.read_text()) +assert record["schema_version"] == 1, "Unsupported brand lock" +assert record["source"] == "https://github.com/computer-mcp/computer-mcp", "Unexpected brand authority" +for name, expected in record["files"].items(): + path = ROOT / name + assert path.resolve().is_relative_to(ROOT), f"Invalid delivery path: {name}" + assert hashlib.sha256(path.read_bytes()).hexdigest() == expected, f"Brand delivery drift: {name}" +if record["consumer"] == "computer-mcp.github.io": + text = (ROOT / "index.html").read_text() + for promise in record["promise"].values(): + assert promise in text, "Website promise differs from the imported brand" + assert 'brand/social-en.png' in text, "Website sharing artwork differs" +else: + manual = ROOT / ("profile/README.md" if record["consumer"] == ".github" else "README.md") + text = manual.read_text() + assert record["name"] in text, "Master name missing from public entry point" + assert record["promise"]["en"] in text, "Master promise missing from public entry point" + header = "brand/header.svg" if record["consumer"] == ".github" else "Documentation/Brand/header.svg" + assert header in text, "Family header missing from public entry point" +print(f"Locked Computer MCP brand verified for {record['consumer']}") diff --git a/brand.lock.json b/brand.lock.json new file mode 100644 index 0000000..e914a18 --- /dev/null +++ b/brand.lock.json @@ -0,0 +1,16 @@ +{ + "schema_version": 1, + "source": "https://github.com/computer-mcp/computer-mcp", + "revision": "3c498108b1b847ae126fd2593cd0d3ddb4d0d9858d0dae214b1439ff69226e50", + "consumer": "plugin-cursor", + "name": "Computer MCP", + "promise": { + "en": "Let ChatGPT use your local tools.", + "zh-CN": "\u8ba9 ChatGPT\uff0c\u7528\u4e0a\u4f60\u7684\u672c\u673a\u5de5\u5177\u3002" + }, + "files": { + "Documentation/Brand/header.svg": "3eb525deef20b9797cecb4021033bca30a680bb1379762b17365903bfe70f58d", + ".github/brand/social.png": "56bfb7ef7421894501b6c12e956bdd3c30f766b13b6722c394a1e56083d59ae6", + "Scripts/check-brand.py": "2ec3c64469774b48fbfa6fbfa7f6a35c6a172fe4de347beb1881766632fbfdde" + } +}