@mcptoolshop/shipcheck 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,234 @@
1
+ # Error Contract
2
+
3
+ Structured errors across all MCP Tool Shop products.
4
+
5
+ Two tiers: the **shape** is mandatory everywhere, the **base type** is optional for larger projects.
6
+
7
+ ---
8
+
9
+ ## Tier 1: Structured Error Shape (mandatory)
10
+
11
+ Every user-facing error — whether thrown, returned, or printed — must carry these fields:
12
+
13
+ | Field | Type | Required | Purpose |
14
+ |-------|------|----------|---------|
15
+ | `code` | string | yes | Machine-readable, namespaced (see registry rules below) |
16
+ | `message` | string | yes | What went wrong |
17
+ | `hint` | string | yes | What the user should do about it |
18
+ | `cause` | string/error | no | Original error, for chaining |
19
+ | `retryable` | boolean | no | Can the caller safely retry? |
20
+
21
+ **Simple scripts** don't need a class. Just emit the shape:
22
+
23
+ ```json
24
+ {
25
+ "code": "IO_READ_FAILED",
26
+ "message": "Could not read config.json",
27
+ "hint": "Check file permissions or run with --debug",
28
+ "retryable": false
29
+ }
30
+ ```
31
+
32
+ ```python
33
+ # Minimal: return a dict
34
+ {"code": "IO_READ_FAILED", "message": str(e), "hint": "Check file permissions"}
35
+ ```
36
+
37
+ The contract is the shape, not the implementation.
38
+
39
+ ---
40
+
41
+ ## Tier 2: Base Error Type + Exit Codes (CLI / MCP / Desktop)
42
+
43
+ For repos with a CLI, MCP server, or desktop UI — formalize the shape into a typed error class with two output modes.
44
+
45
+ ### Output modes
46
+
47
+ | Mode | Audience | Stack traces? | When |
48
+ |------|----------|---------------|------|
49
+ | **safe** | End users, LLMs, MCP | Never | Default |
50
+ | **debug** | Developers | Yes, if available | `--debug` flag |
51
+
52
+ ### Exit codes (CLI only)
53
+
54
+ | Code | Meaning |
55
+ |------|---------|
56
+ | 0 | Success |
57
+ | 1 | User error (bad input, missing args, invalid config) |
58
+ | 2 | Runtime error (crash, IO failure, dependency missing) |
59
+ | 3 | Partial success (some items ok, some failed) |
60
+
61
+ ### TypeScript reference
62
+
63
+ ```typescript
64
+ export class ProductError extends Error {
65
+ readonly code: string;
66
+ readonly hint: string;
67
+ readonly cause?: Error;
68
+ readonly retryable: boolean;
69
+
70
+ constructor(
71
+ code: string,
72
+ message: string,
73
+ hint: string,
74
+ opts?: { cause?: Error; retryable?: boolean },
75
+ ) {
76
+ super(message);
77
+ this.name = 'ProductError'; // rename per-product
78
+ this.code = code;
79
+ this.hint = hint;
80
+ this.cause = opts?.cause;
81
+ this.retryable = opts?.retryable ?? false;
82
+ }
83
+
84
+ /** Safe output — no stack traces. For MCP responses + UI. */
85
+ toSafeText(): string {
86
+ const lines = [
87
+ `Error [${this.code}]: ${this.message}`,
88
+ `Hint: ${this.hint}`,
89
+ ];
90
+ if (this.cause) lines.push(`Cause: ${this.cause.message}`);
91
+ return lines.join('\n');
92
+ }
93
+
94
+ /** Debug output — includes stack. For CLI --debug. */
95
+ toDebugText(): string {
96
+ const lines = [
97
+ `[${this.code}] ${this.message}`,
98
+ ` Hint: ${this.hint}`,
99
+ ];
100
+ if (this.cause) {
101
+ lines.push(` Cause: ${this.cause.message}`);
102
+ if (this.cause.stack) lines.push(` Stack: ${this.cause.stack}`);
103
+ }
104
+ return lines.join('\n');
105
+ }
106
+ }
107
+
108
+ export function wrapError(
109
+ err: unknown,
110
+ code: string,
111
+ hint: string,
112
+ ): ProductError {
113
+ if (err instanceof ProductError) return err;
114
+ const cause = err instanceof Error ? err : new Error(String(err));
115
+ return new ProductError(code, cause.message, hint, { cause });
116
+ }
117
+ ```
118
+
119
+ ### Python reference
120
+
121
+ ```python
122
+ class ProductError(Exception):
123
+ """Structured error with code, hint, and optional cause."""
124
+
125
+ def __init__(
126
+ self,
127
+ code: str,
128
+ message: str,
129
+ hint: str,
130
+ *,
131
+ cause: Exception | None = None,
132
+ retryable: bool = False,
133
+ ):
134
+ super().__init__(message)
135
+ self.code = code
136
+ self.hint = hint
137
+ self.__cause__ = cause
138
+ self.retryable = retryable
139
+
140
+ def to_safe_text(self) -> str:
141
+ """Safe output — no stack traces. For MCP responses + UI."""
142
+ lines = [f"Error [{self.code}]: {self}", f"Hint: {self.hint}"]
143
+ if self.__cause__:
144
+ lines.append(f"Cause: {self.__cause__}")
145
+ return "\n".join(lines)
146
+
147
+ def to_debug_text(self) -> str:
148
+ """Debug output — includes stack. For CLI --debug."""
149
+ import traceback
150
+
151
+ lines = [f"[{self.code}] {self}", f" Hint: {self.hint}"]
152
+ if self.__cause__:
153
+ lines.append(f" Cause: {self.__cause__}")
154
+ lines.append(
155
+ "".join(traceback.format_exception(self.__cause__))
156
+ )
157
+ return "\n".join(lines)
158
+
159
+
160
+ def wrap_error(err: Exception, code: str, hint: str) -> ProductError:
161
+ """Wrap any exception into a ProductError."""
162
+ if isinstance(err, ProductError):
163
+ return err
164
+ return ProductError(code, str(err), hint, cause=err)
165
+ ```
166
+
167
+ ### .NET pattern
168
+
169
+ ```csharp
170
+ public class ProductException : Exception
171
+ {
172
+ public string Code { get; }
173
+ public string Hint { get; }
174
+ public bool Retryable { get; }
175
+
176
+ public ProductException(
177
+ string code, string message, string hint,
178
+ Exception? cause = null, bool retryable = false)
179
+ : base(message, cause)
180
+ {
181
+ Code = code;
182
+ Hint = hint;
183
+ Retryable = retryable;
184
+ }
185
+
186
+ public string ToSafeText() =>
187
+ $"Error [{Code}]: {Message}\nHint: {Hint}"
188
+ + (InnerException != null ? $"\nCause: {InnerException.Message}" : "");
189
+ }
190
+ ```
191
+
192
+ ### Naming convention
193
+
194
+ Each product renames the class: `GuardianError`, `AttestiaError`, `SoundboardError`, etc.
195
+
196
+ ---
197
+
198
+ ## Error Code Registry Rules
199
+
200
+ Three rules.
201
+
202
+ ### 1. Codes are namespaced
203
+
204
+ Use a prefix from this table (extend as needed):
205
+
206
+ | Prefix | Domain |
207
+ |--------|--------|
208
+ | `IO_` | File system, streams, paths |
209
+ | `CONFIG_` | Configuration, settings, env vars |
210
+ | `PERM_` | Permissions, access control |
211
+ | `DEP_` | Dependencies, external services |
212
+ | `RUNTIME_` | Unexpected failures, OOM, timeouts |
213
+ | `PARTIAL_` | Some items succeeded, some failed |
214
+ | `INPUT_` | Bad user input, validation failures |
215
+ | `STATE_` | Corrupt or stale internal state |
216
+
217
+ Examples: `IO_READ_FAILED`, `CONFIG_MISSING_KEY`, `STATE_CORRUPT`, `DEP_OLLAMA_UNREACHABLE`
218
+
219
+ ### 2. Codes are stable once released
220
+
221
+ A code that appears in a shipped version is permanent. You can add new codes. You can deprecate old ones (map to a successor). You cannot change what an existing code means.
222
+
223
+ ### 3. Every code maps to an exit code + default hint
224
+
225
+ Maintain a table in your repo (in the error file or a separate `ERROR_CODES.md`):
226
+
227
+ ```
228
+ IO_READ_FAILED → exit 2 → "Check file exists and permissions are correct"
229
+ CONFIG_MISSING_KEY → exit 1 → "Add the required key to your config file"
230
+ STATE_CORRUPT → exit 2 → "Run --reset to rebuild state"
231
+ PARTIAL_BATCH → exit 3 → "Check logs for individual failures"
232
+ ```
233
+
234
+ This table is your error contract with users. Treat it like an API.
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@mcptoolshop/shipcheck",
3
+ "version": "1.0.0",
4
+ "description": "Product standards for MCP Tool Shop — Ship Gate checklist, error contract, and adoption guides.",
5
+ "type": "module",
6
+ "bin": {
7
+ "shipcheck": "bin/shipcheck.mjs"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "templates",
12
+ "contracts",
13
+ "ADOPTION.md",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "license": "MIT",
18
+ "author": "mcp-tool-shop <64996768+mcp-tool-shop@users.noreply.github.com>",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/mcp-tool-shop-org/shipcheck.git"
22
+ },
23
+ "homepage": "https://mcp-tool-shop-org.github.io/shipcheck/",
24
+ "keywords": [
25
+ "shipcheck",
26
+ "standards",
27
+ "ship-gate",
28
+ "error-contract",
29
+ "checklist",
30
+ "quality",
31
+ "mcp-tool-shop"
32
+ ],
33
+ "engines": {
34
+ "node": ">=18.0.0"
35
+ }
36
+ }
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+
12
+ ### Fixed
13
+
14
+ ### Changed
15
+
16
+ <!-- ## [0.1.0] - YYYY-MM-DD -->
17
+ <!-- ### Added -->
18
+ <!-- - Initial release -->
@@ -0,0 +1,71 @@
1
+ # Handbook
2
+
3
+ > Field manual for operating **<!-- product name -->**.
4
+ > If it says WARN, do this. If CRITICAL, do this. No fluff.
5
+
6
+ ## What it does
7
+
8
+ <!-- One paragraph. What problem it solves, for whom. -->
9
+
10
+ ## How it works
11
+
12
+ <!-- Brief architecture: inputs → processing → outputs. Keep it to 3–5 sentences. -->
13
+
14
+ ## Daily operations
15
+
16
+ ### Starting up
17
+
18
+ ```bash
19
+ # Replace with your actual startup command
20
+ ```
21
+
22
+ ### Normal output
23
+
24
+ <!-- What does "healthy" look like? Example output or status. -->
25
+
26
+ ### Logging levels
27
+
28
+ | Level | What you see | When to use |
29
+ |-------|-------------|-------------|
30
+ | silent | Nothing | Automation, scripts |
31
+ | normal | Status + warnings | Default |
32
+ | verbose | Above + progress | Troubleshooting |
33
+ | debug | Everything + stack traces | Bug reports |
34
+
35
+ ## When things go wrong
36
+
37
+ ### WARN conditions
38
+
39
+ <!-- List warning states and what to do about each. Example: -->
40
+
41
+ | Signal | Meaning | Action |
42
+ |--------|---------|--------|
43
+ | <!-- e.g., "State file stale" --> | <!-- meaning --> | <!-- action --> |
44
+
45
+ ### CRITICAL conditions
46
+
47
+ | Signal | Meaning | Action |
48
+ |--------|---------|--------|
49
+ | <!-- e.g., "State corrupt" --> | <!-- meaning --> | <!-- action --> |
50
+
51
+ ### Recovery
52
+
53
+ <!-- Step-by-step recovery procedure for the worst case. -->
54
+
55
+ 1. <!-- Step 1 -->
56
+ 2. <!-- Step 2 -->
57
+ 3. <!-- Step 3 -->
58
+
59
+ ## Where things live
60
+
61
+ | What | Path |
62
+ |------|------|
63
+ | Config | <!-- path --> |
64
+ | Logs | <!-- path --> |
65
+ | State | <!-- path --> |
66
+
67
+ ## Privacy
68
+
69
+ - All data stays local
70
+ - No telemetry, no network unless explicitly configured
71
+ - Secrets are never logged or included in diagnostics
@@ -0,0 +1,49 @@
1
+ # Scorecard
2
+
3
+ > Score a repo before remediation. Fill this out first, then use SHIP_GATE.md to fix.
4
+
5
+ **Repo:** <!-- repo name -->
6
+ **Date:** <!-- YYYY-MM-DD -->
7
+ **Type tags:** <!-- [npm] [mcp] [cli] etc. -->
8
+
9
+ ## Pre-Remediation Assessment
10
+
11
+ | Category | Score | Notes |
12
+ |----------|-------|-------|
13
+ | A. Security | /10 | |
14
+ | B. Error Handling | /10 | |
15
+ | C. Operator Docs | /10 | |
16
+ | D. Shipping Hygiene | /10 | |
17
+ | E. Identity (soft) | /10 | |
18
+ | **Overall** | **/50** | |
19
+
20
+ ## Key Gaps
21
+
22
+ <!-- List the 3-5 most critical gaps that need fixing. Be specific. -->
23
+
24
+ 1.
25
+ 2.
26
+ 3.
27
+
28
+ ## Remediation Priority
29
+
30
+ <!-- What to fix first, second, third. Informed by the gaps above. -->
31
+
32
+ | Priority | Item | Estimated effort |
33
+ |----------|------|-----------------|
34
+ | 1 | | |
35
+ | 2 | | |
36
+ | 3 | | |
37
+
38
+ ## Post-Remediation
39
+
40
+ <!-- Fill this out after applying SHIP_GATE.md -->
41
+
42
+ | Category | Before | After |
43
+ |----------|--------|-------|
44
+ | A. Security | /10 | /10 |
45
+ | B. Error Handling | /10 | /10 |
46
+ | C. Operator Docs | /10 | /10 |
47
+ | D. Shipping Hygiene | /10 | /10 |
48
+ | E. Identity (soft) | /10 | /10 |
49
+ | **Overall** | /50 | /50 |
@@ -0,0 +1,37 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ <!-- Replace with your version table -->
6
+
7
+ | Version | Supported |
8
+ |---------|-----------|
9
+ | latest | Yes |
10
+
11
+ ## Reporting a Vulnerability
12
+
13
+ Email: **64996768+mcp-tool-shop@users.noreply.github.com**
14
+
15
+ Include:
16
+ - Description of the vulnerability
17
+ - Steps to reproduce
18
+ - Version affected
19
+ - Potential impact
20
+
21
+ ### Response timeline
22
+
23
+ | Action | Target |
24
+ |--------|--------|
25
+ | Acknowledge report | 48 hours |
26
+ | Assess severity | 7 days |
27
+ | Release fix | 30 days |
28
+
29
+ ## Scope
30
+
31
+ <!-- Customize per-product. Examples: -->
32
+
33
+ This tool operates **locally only**.
34
+ - **Data touched:** <!-- e.g., local log files, process metrics -->
35
+ - **No network egress** unless explicitly configured
36
+ - **No secrets handling** — does not read, store, or transmit credentials
37
+ - **No telemetry** is collected or sent
@@ -0,0 +1,80 @@
1
+ # Ship Gate
2
+
3
+ > No repo is "done" until every applicable line is checked.
4
+ > Copy this into your repo root. Check items off per-release.
5
+
6
+ **Tags:** `[all]` every repo · `[npm]` `[pypi]` `[vsix]` `[desktop]` `[container]` published artifacts · `[mcp]` MCP servers · `[cli]` CLI tools
7
+
8
+ ---
9
+
10
+ ## A. Security Baseline
11
+
12
+ - [ ] `[all]` SECURITY.md exists (report email, supported versions, response timeline)
13
+ - [ ] `[all]` README includes threat model paragraph (data touched, data NOT touched, permissions required)
14
+ - [ ] `[all]` No secrets, tokens, or credentials in source or diagnostics output
15
+ - [ ] `[all]` No telemetry by default — state it explicitly even if obvious
16
+
17
+ ### Default safety posture
18
+
19
+ - [ ] `[cli|mcp|desktop]` Dangerous actions (kill, delete, restart) require explicit `--allow-*` flag
20
+ - [ ] `[cli|mcp|desktop]` File operations constrained to known directories
21
+ - [ ] `[mcp]` Network egress off by default
22
+ - [ ] `[mcp]` Stack traces never exposed — structured error results only
23
+
24
+ ## B. Error Handling
25
+
26
+ - [ ] `[all]` Errors follow the Structured Error Shape: `code`, `message`, `hint`, `cause?`, `retryable?`
27
+ - [ ] `[cli]` Exit codes: 0 ok · 1 user error · 2 runtime error · 3 partial success
28
+ - [ ] `[cli]` No raw stack traces without `--debug`
29
+ - [ ] `[mcp]` Tool errors return structured results — server never crashes on bad input
30
+ - [ ] `[mcp]` State/config corruption degrades gracefully (stale data over crash)
31
+ - [ ] `[desktop]` Errors shown as user-friendly messages — no raw exceptions in UI
32
+ - [ ] `[vscode]` Errors surface via VS Code notification API — no silent failures
33
+
34
+ ## C. Operator Docs
35
+
36
+ - [ ] `[all]` README is current: what it does, install, usage, supported platforms + runtime versions
37
+ - [ ] `[all]` CHANGELOG.md (Keep a Changelog format)
38
+ - [ ] `[all]` LICENSE file present and repo states support status
39
+ - [ ] `[cli]` `--help` output accurate for all commands and flags
40
+ - [ ] `[cli|mcp|desktop]` Logging levels defined: silent / normal / verbose / debug — secrets redacted at all levels
41
+ - [ ] `[mcp]` All tools documented with description + parameters
42
+ - [ ] `[complex]` HANDBOOK.md: daily ops, warn/critical response, recovery procedures
43
+
44
+ ## D. Shipping Hygiene
45
+
46
+ - [ ] `[all]` `verify` script exists (test + build + smoke in one command)
47
+ - [ ] `[all]` Version in manifest matches git tag
48
+ - [ ] `[all]` Dependency scanning runs in CI (ecosystem-appropriate)
49
+ - [ ] `[all]` Automated dependency update mechanism exists
50
+ - [ ] `[npm]` `npm pack --dry-run` includes: dist/, README.md, CHANGELOG.md, LICENSE
51
+ - [ ] `[npm]` `engines.node` set · `[pypi]` `python_requires` set
52
+ - [ ] `[npm]` Lockfile committed · `[pypi]` Clean wheel + sdist build
53
+ - [ ] `[vsix]` `vsce package` produces clean .vsix with correct metadata
54
+ - [ ] `[desktop]` Installer/package builds and runs on stated platforms
55
+
56
+ ## E. Identity (soft gate — does not block ship)
57
+
58
+ - [ ] `[all]` Logo in README header
59
+ - [ ] `[all]` Translations (polyglot-mcp, 8 languages)
60
+ - [ ] `[org]` Landing page (@mcptoolshop/site-theme)
61
+ - [ ] `[all]` GitHub repo metadata: description, homepage, topics
62
+
63
+ ---
64
+
65
+ ## Gate Rules
66
+
67
+ **Hard gate (A–D):** Must pass before any version is tagged or published.
68
+ If a section doesn't apply, mark `SKIP:` with justification — don't leave it unchecked.
69
+
70
+ **Soft gate (E):** Should be done. Product ships without it, but isn't "whole."
71
+
72
+ **Checking off:**
73
+ ```
74
+ - [x] `[all]` SECURITY.md exists (2026-02-27)
75
+ ```
76
+
77
+ **Skipping:**
78
+ ```
79
+ - [ ] `[pypi]` SKIP: not a Python project
80
+ ```