git-doc-mcp 0.1.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.
Files changed (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +543 -0
  3. package/dist/audit/index.d.ts +2 -0
  4. package/dist/audit/index.d.ts.map +1 -0
  5. package/dist/audit/index.js +2 -0
  6. package/dist/audit/index.js.map +1 -0
  7. package/dist/audit/logger.d.ts +81 -0
  8. package/dist/audit/logger.d.ts.map +1 -0
  9. package/dist/audit/logger.js +179 -0
  10. package/dist/audit/logger.js.map +1 -0
  11. package/dist/cli/commands/serve.d.ts +44 -0
  12. package/dist/cli/commands/serve.d.ts.map +1 -0
  13. package/dist/cli/commands/serve.js +360 -0
  14. package/dist/cli/commands/serve.js.map +1 -0
  15. package/dist/cli/index.d.ts +21 -0
  16. package/dist/cli/index.d.ts.map +1 -0
  17. package/dist/cli/index.js +71 -0
  18. package/dist/cli/index.js.map +1 -0
  19. package/dist/http/client.d.ts +39 -0
  20. package/dist/http/client.d.ts.map +1 -0
  21. package/dist/http/client.js +114 -0
  22. package/dist/http/client.js.map +1 -0
  23. package/dist/http/index.d.ts +7 -0
  24. package/dist/http/index.d.ts.map +1 -0
  25. package/dist/http/index.js +7 -0
  26. package/dist/http/index.js.map +1 -0
  27. package/dist/http/redirect-utils.d.ts +27 -0
  28. package/dist/http/redirect-utils.d.ts.map +1 -0
  29. package/dist/http/redirect-utils.js +73 -0
  30. package/dist/http/redirect-utils.js.map +1 -0
  31. package/dist/index.d.ts +36 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +44 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/manifest/index.d.ts +7 -0
  36. package/dist/manifest/index.d.ts.map +1 -0
  37. package/dist/manifest/index.js +7 -0
  38. package/dist/manifest/index.js.map +1 -0
  39. package/dist/manifest/loader.d.ts +55 -0
  40. package/dist/manifest/loader.d.ts.map +1 -0
  41. package/dist/manifest/loader.js +222 -0
  42. package/dist/manifest/loader.js.map +1 -0
  43. package/dist/manifest/schema.d.ts +909 -0
  44. package/dist/manifest/schema.d.ts.map +1 -0
  45. package/dist/manifest/schema.js +148 -0
  46. package/dist/manifest/schema.js.map +1 -0
  47. package/dist/rate-limit/index.d.ts +6 -0
  48. package/dist/rate-limit/index.d.ts.map +1 -0
  49. package/dist/rate-limit/index.js +6 -0
  50. package/dist/rate-limit/index.js.map +1 -0
  51. package/dist/rate-limit/limiter.d.ts +38 -0
  52. package/dist/rate-limit/limiter.d.ts.map +1 -0
  53. package/dist/rate-limit/limiter.js +55 -0
  54. package/dist/rate-limit/limiter.js.map +1 -0
  55. package/dist/sandbox/context.d.ts +69 -0
  56. package/dist/sandbox/context.d.ts.map +1 -0
  57. package/dist/sandbox/context.js +134 -0
  58. package/dist/sandbox/context.js.map +1 -0
  59. package/dist/sandbox/executor.d.ts +50 -0
  60. package/dist/sandbox/executor.d.ts.map +1 -0
  61. package/dist/sandbox/executor.js +259 -0
  62. package/dist/sandbox/executor.js.map +1 -0
  63. package/dist/sandbox/index.d.ts +8 -0
  64. package/dist/sandbox/index.d.ts.map +1 -0
  65. package/dist/sandbox/index.js +8 -0
  66. package/dist/sandbox/index.js.map +1 -0
  67. package/dist/sandbox/url-validator.d.ts +40 -0
  68. package/dist/sandbox/url-validator.d.ts.map +1 -0
  69. package/dist/sandbox/url-validator.js +178 -0
  70. package/dist/sandbox/url-validator.js.map +1 -0
  71. package/dist/secrets/index.d.ts +7 -0
  72. package/dist/secrets/index.d.ts.map +1 -0
  73. package/dist/secrets/index.js +7 -0
  74. package/dist/secrets/index.js.map +1 -0
  75. package/dist/secrets/manager.d.ts +55 -0
  76. package/dist/secrets/manager.d.ts.map +1 -0
  77. package/dist/secrets/manager.js +94 -0
  78. package/dist/secrets/manager.js.map +1 -0
  79. package/dist/secrets/patterns.d.ts +33 -0
  80. package/dist/secrets/patterns.d.ts.map +1 -0
  81. package/dist/secrets/patterns.js +71 -0
  82. package/dist/secrets/patterns.js.map +1 -0
  83. package/dist/server/index.d.ts +6 -0
  84. package/dist/server/index.d.ts.map +1 -0
  85. package/dist/server/index.js +6 -0
  86. package/dist/server/index.js.map +1 -0
  87. package/dist/server/mcp.d.ts +60 -0
  88. package/dist/server/mcp.d.ts.map +1 -0
  89. package/dist/server/mcp.js +173 -0
  90. package/dist/server/mcp.js.map +1 -0
  91. package/dist/worker/index.d.ts +7 -0
  92. package/dist/worker/index.d.ts.map +1 -0
  93. package/dist/worker/index.js +7 -0
  94. package/dist/worker/index.js.map +1 -0
  95. package/dist/worker/process.d.ts +64 -0
  96. package/dist/worker/process.d.ts.map +1 -0
  97. package/dist/worker/process.js +222 -0
  98. package/dist/worker/process.js.map +1 -0
  99. package/dist/worker/protocol.d.ts +83 -0
  100. package/dist/worker/protocol.d.ts.map +1 -0
  101. package/dist/worker/protocol.js +55 -0
  102. package/dist/worker/protocol.js.map +1 -0
  103. package/dist/worker/worker-entry.d.ts +30 -0
  104. package/dist/worker/worker-entry.d.ts.map +1 -0
  105. package/dist/worker/worker-entry.js +136 -0
  106. package/dist/worker/worker-entry.js.map +1 -0
  107. package/package.json +55 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,543 @@
1
+ # git-doc-mcp - Turn Any Manifest into an MCP Server
2
+
3
+ [![npm version](https://badge.fury.io/js/git-doc-mcp.svg)](https://www.npmjs.com/package/git-doc-mcp)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org/)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)](https://www.typescriptlang.org/)
7
+ [![Linux](https://img.shields.io/badge/Linux-supported-success.svg)](https://github.com)
8
+ [![macOS](https://img.shields.io/badge/macOS-supported-success.svg)](https://github.com)
9
+ [![Windows](https://img.shields.io/badge/Windows-supported-success.svg)](https://github.com)
10
+
11
+ **Write a manifest, host it anywhere, and users can instantly use it with their AI tools.**
12
+
13
+ ## What is git-doc-mcp?
14
+
15
+ git-doc-mcp is a **declarative MCP manifest system** that lets anyone create and host MCP servers without running infrastructure. It turns any manifest URL into a fully-functional MCP server with custom tools, resources, and prompts - all defined in YAML.
16
+
17
+ **Key features:**
18
+ - **No hosting required** - Use GitHub Pages, GitLab Pages, S3, any static hosting
19
+ - **Custom JavaScript actions** - Define your own tool logic
20
+ - **Capability-scoped secrets** - Fine-grained access control with URL pattern matching
21
+ - **Platform-agnostic** - Works with GitHub, GitLab, S3, local files
22
+ - **TOFU manifest verification** - Trust-on-first-use with fail-closed security
23
+ - **Three-layer isolation** - Worker process + isolated-vm + URL validation
24
+ - **Cross-platform** - Linux, macOS, Windows
25
+
26
+ ## Quick Start
27
+
28
+ ### 1. Install
29
+
30
+ ```bash
31
+ # Using npm
32
+ npm install -g git-doc-mcp
33
+
34
+ # Using npx (no install needed)
35
+ npx git-doc-mcp --manifest https://example.com/.mcp/manifest.yml
36
+ ```
37
+
38
+ ### 2. Configure with Claude Code
39
+
40
+ Add to `~/.claude/config.json`:
41
+
42
+ ```json
43
+ {
44
+ "mcpServers": {
45
+ "my-repo": {
46
+ "command": "npx",
47
+ "args": ["git-doc-mcp", "--manifest", "https://example.com/.mcp/manifest.yml"]
48
+ }
49
+ }
50
+ }
51
+ ```
52
+
53
+ ### 3. Create Your Manifest
54
+
55
+ Create `.mcp/manifest.yml` in your repository:
56
+
57
+ ```yaml
58
+ schemaVersion: "1.0"
59
+ name: my-repo-mcp
60
+ version: 1.0.0
61
+ description: MCP server for my repository
62
+
63
+ tools:
64
+ - name: fetch-file
65
+ description: Fetch a file from the repository
66
+ inputSchema:
67
+ type: object
68
+ properties:
69
+ path: { type: string }
70
+ required: [path]
71
+ action: https://example.com/.mcp/actions/fetch-file.v1.js
72
+ actionHash: "sha256:..."
73
+ annotations:
74
+ readOnlyHint: true
75
+ openWorldHint: true
76
+ ```
77
+
78
+ ## Try It — Live Demo
79
+
80
+ This project uses its own manifest system to serve documentation. Add it to your AI tool to see git-doc-mcp in action:
81
+
82
+ **Claude Code** — add to your project's `.mcp.json`:
83
+
84
+ ```json
85
+ {
86
+ "mcpServers": {
87
+ "git-doc-mcp-docs": {
88
+ "command": "npx",
89
+ "args": [
90
+ "git-doc-mcp",
91
+ "--manifest",
92
+ "https://raw.githubusercontent.com/Z-M-Huang/git-doc-mcp/main/.mcp/manifest.yml"
93
+ ]
94
+ }
95
+ }
96
+ }
97
+ ```
98
+
99
+ **Claude Desktop** — add to `~/.claude/claude_desktop_config.json`:
100
+
101
+ ```json
102
+ {
103
+ "mcpServers": {
104
+ "git-doc-mcp-docs": {
105
+ "command": "npx",
106
+ "args": [
107
+ "git-doc-mcp",
108
+ "--manifest",
109
+ "https://raw.githubusercontent.com/Z-M-Huang/git-doc-mcp/main/.mcp/manifest.yml"
110
+ ]
111
+ }
112
+ }
113
+ }
114
+ ```
115
+
116
+ This gives you 5 tools, 3 resources, and 2 prompts that fetch documentation from the [project wiki](https://github.com/Z-M-Huang/git-doc-mcp/wiki):
117
+
118
+ | Tool | Description |
119
+ |------|-------------|
120
+ | `list_topics` | Browse documentation topics, filter by tag |
121
+ | `get_guide` | Fetch a specific guide (e.g., Getting-Started, Manifest-Reference) |
122
+ | `search_docs` | Search across all documentation by keyword |
123
+ | `get_example` | Get complete working examples (GitHub tools, REST wrapper, etc.) |
124
+ | `get_action_api` | Action scripting API reference (ctx.fetch, ctx.getSecret, etc.) |
125
+
126
+ The [manifest source](.mcp/manifest.yml) and [action scripts](.mcp/actions/) serve as a reference for building your own.
127
+
128
+ ## Installation
129
+
130
+ ### npm
131
+
132
+ ```bash
133
+ npm install -g git-doc-mcp
134
+ ```
135
+
136
+ ### npx (no install)
137
+
138
+ ```bash
139
+ npx git-doc-mcp --manifest <url-or-path>
140
+ ```
141
+
142
+ ### Local Development
143
+
144
+ ```bash
145
+ git clone https://github.com/Z-M-Huang/git-doc-mcp.git
146
+ cd git-doc-mcp
147
+ npm install
148
+ npm run build
149
+ ```
150
+
151
+ ## Usage Examples
152
+
153
+ ### Public Manifest
154
+
155
+ ```bash
156
+ npx git-doc-mcp --manifest https://raw.githubusercontent.com/owner/repo/main/.mcp/manifest.yml
157
+ ```
158
+
159
+ ### Private Manifest with Authentication
160
+
161
+ ```bash
162
+ npx git-doc-mcp --manifest https://private.example.com/.mcp/manifest.yml \
163
+ --manifest-header "Authorization: Bearer $TOKEN"
164
+ ```
165
+
166
+ ### Local Development
167
+
168
+ ```bash
169
+ npx git-doc-mcp --manifest ./path/to/manifest.yml
170
+ ```
171
+
172
+ ### With Pre-approved Secrets
173
+
174
+ ```bash
175
+ # Via CLI flag
176
+ npx git-doc-mcp --manifest https://example.com/.mcp/manifest.yml \
177
+ --secret GITHUB_TOKEN=$GITHUB_TOKEN
178
+
179
+ # Via environment variable
180
+ export GIT_MCP_SECRET_GITHUB_TOKEN=$GITHUB_TOKEN
181
+ npx git-doc-mcp --manifest https://example.com/.mcp/manifest.yml
182
+ ```
183
+
184
+ ### Hash Pinning (for CI/CD)
185
+
186
+ ```bash
187
+ npx git-doc-mcp --manifest https://example.com/.mcp/manifest.yml \
188
+ --manifest-hash sha256:abc123...
189
+ ```
190
+
191
+ ### Rate Limiting
192
+
193
+ ```bash
194
+ # Limit to 30 tool calls per minute
195
+ npx git-doc-mcp --manifest https://example.com/.mcp/manifest.yml \
196
+ --rate-limit 30
197
+ ```
198
+
199
+ ## Manifest Schema
200
+
201
+ ```yaml
202
+ schemaVersion: "1.0" # Required - schema version
203
+ name: my-repo-mcp # Required - server name
204
+ version: 1.0.0 # Required - semantic version
205
+ description: Description # Optional - shown to AI
206
+ instructions: Use when... # Optional - helps AI understand when to use
207
+
208
+ secrets: # Optional - secrets needed
209
+ - name: GITHUB_TOKEN
210
+ description: GitHub token
211
+ scope:
212
+ - "https://api.github.com/*"
213
+ required: false
214
+
215
+ tools: # Required - at least one tool
216
+ - name: fetch-file
217
+ title: Fetch File # Optional - human-readable title
218
+ description: Fetch a file # Required
219
+ inputSchema: # Required - JSON Schema
220
+ type: object
221
+ properties:
222
+ path: { type: string }
223
+ required: [path]
224
+ action: https://... # Required - URL to action script
225
+ actionHash: sha256:... # Required - SHA-256 hash
226
+ annotations: # Optional - hints for AI
227
+ readOnlyHint: true
228
+ destructiveHint: false
229
+ idempotentHint: true
230
+ openWorldHint: true
231
+
232
+ resources: # Optional - static resources
233
+ - name: readme
234
+ uri: https://...
235
+ description: README
236
+ mimeType: text/markdown
237
+
238
+ prompts: # Optional - prompt templates
239
+ - name: explain-code
240
+ description: Explain code
241
+ args:
242
+ - name: path
243
+ required: true
244
+ messages: # Optional - MCP PromptMessage[]
245
+ - role: user
246
+ content:
247
+ type: resource
248
+ resource:
249
+ uri: "https://example.com/{{path}}"
250
+ mimeType: text/plain
251
+ - role: user
252
+ content:
253
+ type: text
254
+ text: "Explain the code above from {{path}}"
255
+ ```
256
+
257
+ ### Prompt Messages
258
+
259
+ Prompts support the full MCP `PromptMessage` format with multi-message templates:
260
+
261
+ - **Without `messages`**: A single user message is built from `description` + args (simple mode)
262
+ - **With `messages`**: Messages are returned directly with `{{argName}}` substitution
263
+
264
+ Each message has a `role` (`user` or `assistant`) and `content` (either `text` or embedded `resource`):
265
+
266
+ ```yaml
267
+ messages:
268
+ - role: user
269
+ content:
270
+ type: text
271
+ text: "Analyze {{path}} for {{focus}}"
272
+ - role: assistant
273
+ content:
274
+ type: text
275
+ text: "I'll analyze the code structure first."
276
+ - role: user
277
+ content:
278
+ type: resource
279
+ resource:
280
+ uri: "https://example.com/{{path}}"
281
+ mimeType: text/plain
282
+ ```
283
+
284
+ ## Action API
285
+
286
+ Actions are plain JavaScript files that export a default async function:
287
+
288
+ ```javascript
289
+ export default async function myAction(input, ctx) {
290
+ const { fetch, getSecret, log, manifest } = ctx;
291
+
292
+ log('info', `Running action for ${manifest.name}`);
293
+
294
+ // Get a secret scoped to the target URL
295
+ const url = 'https://api.example.com/data';
296
+ const token = getSecret('API_KEY', url);
297
+
298
+ const response = await fetch(url, {
299
+ headers: token ? { 'Authorization': `Bearer ${token}` } : {}
300
+ });
301
+
302
+ // response.text is a property (not a method)
303
+ // response.json() is a synchronous method
304
+ const data = response.json();
305
+
306
+ return {
307
+ content: [{ type: 'text', text: JSON.stringify(data, null, 2) }]
308
+ };
309
+ }
310
+ ```
311
+
312
+ ### Context Methods
313
+
314
+ | Method | Description |
315
+ |--------|-------------|
316
+ | `ctx.fetch(url, options)` | Scoped fetch with SSRF protection and redirect validation |
317
+ | `ctx.getSecret(name, url)` | Get a secret value if the URL matches the secret's scope pattern |
318
+ | `ctx.log(level, message)` | Logging (levels: debug, info, warn, error) |
319
+ | `ctx.manifest` | Manifest metadata (`{ name, version }`) |
320
+
321
+ ### Fetch Response
322
+
323
+ `ctx.fetch` returns a serialized response object (not a native `Response`):
324
+
325
+ | Property/Method | Type | Description |
326
+ |-----------------|------|-------------|
327
+ | `response.ok` | `boolean` | `true` if status is 200-299 |
328
+ | `response.status` | `number` | HTTP status code |
329
+ | `response.statusText` | `string` | HTTP status text |
330
+ | `response.text` | `string` | Response body as a string (property, not method) |
331
+ | `response.json()` | `object` | Parse body as JSON (synchronous method) |
332
+ | `response.headers` | `object` | Response headers as key-value pairs |
333
+
334
+ ### Return Format
335
+
336
+ ```javascript
337
+ // Success
338
+ return {
339
+ content: [{ type: 'text', text: 'Result' }]
340
+ };
341
+
342
+ // Error
343
+ return {
344
+ content: [{ type: 'text', text: 'Error message' }],
345
+ isError: true
346
+ };
347
+ ```
348
+
349
+ ## CLI Reference
350
+
351
+ ### Options
352
+
353
+ | Option | Description | Default |
354
+ |--------|-------------|---------|
355
+ | `--manifest <path>` | URL or local path to manifest.yml | (required) |
356
+ | `--manifest-header <header>` | Header for fetching manifest (repeatable) | |
357
+ | `--manifest-hash <hash>` | Expected manifest hash for pinning | |
358
+ | `--action-code-header <header>` | Header for downloading action scripts (repeatable) | |
359
+ | `--resource-header <header>` | Header for fetching resources (repeatable) | |
360
+ | `--secret <name=value>` | Pre-approved secret (repeatable) | |
361
+ | `--timeout <ms>` | Worker timeout in milliseconds | `60000` |
362
+ | `--memory-limit <bytes>` | Sandbox memory limit (8MB - 1GB) | `134217728` (128MB) |
363
+ | `--rate-limit <n>` | Max tool calls per minute (0 = unlimited) | `0` |
364
+ | `--allow-http` | Allow insecure HTTP URLs (HTTPS-only by default) | `false` |
365
+ | `--trust-changed` | Accept manifest hash changes (TOFU override) | `false` |
366
+
367
+ ### Environment Variables
368
+
369
+ Secrets can be provided via environment variables prefixed with `GIT_MCP_SECRET_`:
370
+
371
+ ```bash
372
+ export GIT_MCP_SECRET_GITHUB_TOKEN=ghp_abc123
373
+ export GIT_MCP_SECRET_API_KEY=sk-xyz789
374
+ ```
375
+
376
+ The `--secret` CLI flag takes precedence over environment variables.
377
+
378
+ ### Examples
379
+
380
+ ```bash
381
+ # Basic usage
382
+ git-doc-mcp --manifest ./manifest.yml
383
+
384
+ # With authentication headers
385
+ git-doc-mcp --manifest https://... \
386
+ --manifest-header "Authorization: Bearer $TOKEN" \
387
+ --action-code-header "Authorization: Bearer $TOKEN"
388
+
389
+ # Separate resource headers
390
+ git-doc-mcp --manifest https://... \
391
+ --resource-header "Authorization: Bearer $RESOURCE_TOKEN"
392
+
393
+ # With secrets and rate limiting
394
+ git-doc-mcp --manifest https://... \
395
+ --secret GITHUB_TOKEN=$TOKEN \
396
+ --rate-limit 60
397
+
398
+ # Hash pinned (for CI/CD)
399
+ git-doc-mcp --manifest https://... --manifest-hash sha256:abc123...
400
+
401
+ # Accept manifest changes (TOFU override)
402
+ git-doc-mcp --manifest https://... --trust-changed
403
+
404
+ # Custom memory limit (256MB)
405
+ git-doc-mcp --manifest https://... --memory-limit 268435456
406
+
407
+ # Allow HTTP (not recommended for production)
408
+ git-doc-mcp --manifest http://localhost:8080/manifest.yml --allow-http
409
+ ```
410
+
411
+ ## Comparison
412
+
413
+ | Feature | git-doc-mcp | Context7 | idosal/git-doc-mcp |
414
+ |---------|---------|----------|----------------|
415
+ | **Hosting** | Any static host | Hosted service | Needs separate server |
416
+ | **Custom actions** | User-defined JS | Fixed tools | Limited actions |
417
+ | **Private repos** | Auth headers | OAuth | Unknown |
418
+ | **Platform** | Any (GitHub, GitLab, S3, etc.) | Any | GitHub only |
419
+ | **Local development** | Local files | No | No |
420
+ | **Secret scoping** | URL pattern matching | N/A | N/A |
421
+ | **Manifest integrity** | TOFU + hash pinning | N/A | N/A |
422
+
423
+ ## Security Model
424
+
425
+ ### Trusted-Manifest System
426
+
427
+ Users explicitly configure manifest URLs they trust. This is consistent with the official GitHub MCP Server's approach — the user configures which server to use, so they trust the server author.
428
+
429
+ ### Three-Layer Isolation
430
+
431
+ ```
432
+ Layer 1: Worker Process (Primary Boundary)
433
+ - Separate Node.js child process
434
+ - Sanitized environment (no inherited credentials)
435
+ - Crash in action doesn't kill CLI
436
+
437
+ Layer 2: isolated-vm (Defense-in-Depth)
438
+ - Configurable memory limit (default: 128MB)
439
+ - CPU timeout: 30s
440
+ - No direct filesystem/network access
441
+
442
+ Layer 3: Controlled API Surface
443
+ - ctx.fetch with SSRF protection
444
+ - ctx.getSecret with URL scope validation
445
+ - Audit logging of all network calls
446
+ ```
447
+
448
+ ### SSRF Protection
449
+
450
+ All URLs are validated before fetch:
451
+ - HTTPS-only by default (use `--allow-http` to override)
452
+ - Private IP ranges blocked (10.x, 172.16-31.x, 192.168.x, localhost)
453
+ - DNS resolution validated before connection
454
+ - Every redirect URL re-validated
455
+ - Cross-origin redirects strip sensitive headers (Authorization, Cookie)
456
+
457
+ ### Capability-Scoped Secrets
458
+
459
+ Secrets are scoped to specific URL patterns:
460
+
461
+ ```yaml
462
+ secrets:
463
+ - name: GITHUB_TOKEN
464
+ scope:
465
+ - "https://api.github.com/*"
466
+ - "https://raw.githubusercontent.com/*"
467
+ ```
468
+
469
+ `ctx.getSecret(name, url)` only returns the secret value if the URL matches the scope pattern. Path-boundary-aware wildcard matching prevents `/repos-private` from matching a `/repos/*` scope.
470
+
471
+ ### TOFU (Trust-on-First-Use)
472
+
473
+ On first use, git-doc-mcp stores the manifest's SHA-256 hash. If the manifest changes:
474
+
475
+ ```
476
+ Warning: Manifest content has changed since last use!
477
+ Previous: sha256:abc123...
478
+ Current: sha256:def456...
479
+
480
+ To accept this change, re-run with: --trust-changed
481
+ For CI pinning, use: --manifest-hash sha256:def456...
482
+ ```
483
+
484
+ The server exits with a non-zero code unless `--trust-changed` is provided. For CI/CD, use `--manifest-hash` for hard pinning.
485
+
486
+ ### Rate Limiting
487
+
488
+ Sliding-window rate limiter prevents excessive tool calls:
489
+
490
+ ```bash
491
+ # 60 calls per minute
492
+ git-doc-mcp --manifest https://... --rate-limit 60
493
+ ```
494
+
495
+ ### Audit Logging
496
+
497
+ All `ctx.fetch` calls are logged to `~/.git-doc-mcp/logs/audit.jsonl`:
498
+ - URL, HTTP status, duration
499
+ - Redirect hops
500
+ - Secret access (allowed/denied)
501
+ - Action start/end with timing
502
+
503
+ ## Contributing
504
+
505
+ 1. Fork the repository
506
+ 2. Create a feature branch
507
+ 3. Make your changes
508
+ 4. Build: `npm run build`
509
+ 5. Run tests: `npm test`
510
+ 6. Submit a pull request
511
+
512
+ ### Development Setup
513
+
514
+ ```bash
515
+ npm install # Install dependencies
516
+ npm run build # Build all packages
517
+ npm test # Run all tests (298 tests)
518
+ ```
519
+
520
+ ### Project Structure
521
+
522
+ ```
523
+ git-doc-mcp/
524
+ packages/
525
+ core/ # Manifest loading, sandbox, worker, MCP server
526
+ cli/ # CLI entry point and serve command
527
+ template/ # Example manifest and actions
528
+ ```
529
+
530
+ ## Documentation
531
+
532
+ Full documentation is available on the [GitHub Wiki](https://github.com/Z-M-Huang/git-doc-mcp/wiki):
533
+
534
+ - [Getting Started](https://github.com/Z-M-Huang/git-doc-mcp/wiki/Getting-Started) — Create your first MCP server
535
+ - [Manifest Reference](https://github.com/Z-M-Huang/git-doc-mcp/wiki/Manifest-Reference) — Complete schema docs
536
+ - [Writing Actions](https://github.com/Z-M-Huang/git-doc-mcp/wiki/Writing-Actions) — Action scripting API
537
+ - [Examples](https://github.com/Z-M-Huang/git-doc-mcp/wiki/Examples) — Complete working examples
538
+ - [Security Model](https://github.com/Z-M-Huang/git-doc-mcp/wiki/Security-Model) — Isolation architecture
539
+ - [Troubleshooting](https://github.com/Z-M-Huang/git-doc-mcp/wiki/Troubleshooting) — Common issues
540
+
541
+ ## License
542
+
543
+ MIT License - see [LICENSE](LICENSE) for details.
@@ -0,0 +1,2 @@
1
+ export { type AuditEvent, type AuditLogger, FileAuditLogger, NoopAuditLogger, createAuditLogger, } from './logger.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,eAAe,EACf,eAAe,EACf,iBAAiB,GAClB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { FileAuditLogger, NoopAuditLogger, createAuditLogger, } from './logger.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,eAAe,EACf,eAAe,EACf,iBAAiB,GAClB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Structured audit logger for security events.
3
+ * Writes JSON-lines to ~/.git-doc-mcp/logs/audit.jsonl with auto-rotation at 10MB.
4
+ *
5
+ * IMPORTANT: This logger runs ONLY in the main process.
6
+ * Worker processes use WorkerAuditProxy (defined in worker-entry.ts)
7
+ * which sends audit events via IPC to avoid file write race conditions.
8
+ *
9
+ * @module audit/logger
10
+ */
11
+ /**
12
+ * Audit event types for security-relevant operations.
13
+ */
14
+ export interface AuditEvent {
15
+ timestamp: string;
16
+ event: 'action-start' | 'action-end' | 'fetch' | 'redirect' | 'secret-access' | 'error' | 'action-log';
17
+ actionName?: string;
18
+ url?: string;
19
+ secretName?: string;
20
+ status?: string;
21
+ duration_ms?: number;
22
+ manifestName?: string;
23
+ details?: Record<string, unknown>;
24
+ }
25
+ /**
26
+ * Audit logger interface.
27
+ */
28
+ export interface AuditLogger {
29
+ log(event: AuditEvent): void;
30
+ logFetch(url: string, status?: number, duration?: number, manifestName?: string): void;
31
+ logRedirect(from: string, to: string, manifestName?: string): void;
32
+ logSecretAccess(secretName: string, url: string, allowed: boolean, manifestName?: string): void;
33
+ logActionStart(actionName: string, manifestName?: string): void;
34
+ logActionEnd(actionName: string, status: string, duration_ms: number, manifestName?: string): void;
35
+ logActionLog(level: string, message: string, manifestName?: string): void;
36
+ logError(message: string, details?: Record<string, unknown>, manifestName?: string): void;
37
+ close(): Promise<void>;
38
+ }
39
+ /**
40
+ * File-based audit logger.
41
+ * Writes JSON-lines to disk with buffering and auto-rotation.
42
+ */
43
+ export declare class FileAuditLogger implements AuditLogger {
44
+ private buffer;
45
+ private flushTimer;
46
+ private logDir;
47
+ private logFile;
48
+ private dirCreated;
49
+ private flushing;
50
+ constructor(logDir?: string);
51
+ log(event: AuditEvent): void;
52
+ logFetch(url: string, status?: number, duration?: number, manifestName?: string): void;
53
+ logRedirect(from: string, to: string, manifestName?: string): void;
54
+ logSecretAccess(secretName: string, url: string, allowed: boolean, manifestName?: string): void;
55
+ logActionStart(actionName: string, manifestName?: string): void;
56
+ logActionEnd(actionName: string, status: string, duration_ms: number, manifestName?: string): void;
57
+ logActionLog(level: string, message: string, manifestName?: string): void;
58
+ logError(message: string, details?: Record<string, unknown>, manifestName?: string): void;
59
+ close(): Promise<void>;
60
+ private flush;
61
+ private rotate;
62
+ }
63
+ /**
64
+ * No-op audit logger for testing or when audit logging is disabled.
65
+ */
66
+ export declare class NoopAuditLogger implements AuditLogger {
67
+ log(): void;
68
+ logFetch(): void;
69
+ logRedirect(): void;
70
+ logSecretAccess(): void;
71
+ logActionStart(): void;
72
+ logActionEnd(): void;
73
+ logActionLog(): void;
74
+ logError(): void;
75
+ close(): Promise<void>;
76
+ }
77
+ /**
78
+ * Create an audit logger instance.
79
+ */
80
+ export declare function createAuditLogger(logDir?: string): AuditLogger;
81
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":"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"}