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.
- package/LICENSE +21 -0
- package/README.md +543 -0
- package/dist/audit/index.d.ts +2 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +2 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/audit/logger.d.ts +81 -0
- package/dist/audit/logger.d.ts.map +1 -0
- package/dist/audit/logger.js +179 -0
- package/dist/audit/logger.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +44 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +360 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/index.d.ts +21 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +71 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/http/client.d.ts +39 -0
- package/dist/http/client.d.ts.map +1 -0
- package/dist/http/client.js +114 -0
- package/dist/http/client.js.map +1 -0
- package/dist/http/index.d.ts +7 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +7 -0
- package/dist/http/index.js.map +1 -0
- package/dist/http/redirect-utils.d.ts +27 -0
- package/dist/http/redirect-utils.d.ts.map +1 -0
- package/dist/http/redirect-utils.js +73 -0
- package/dist/http/redirect-utils.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest/index.d.ts +7 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest/index.js +7 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/manifest/loader.d.ts +55 -0
- package/dist/manifest/loader.d.ts.map +1 -0
- package/dist/manifest/loader.js +222 -0
- package/dist/manifest/loader.js.map +1 -0
- package/dist/manifest/schema.d.ts +909 -0
- package/dist/manifest/schema.d.ts.map +1 -0
- package/dist/manifest/schema.js +148 -0
- package/dist/manifest/schema.js.map +1 -0
- package/dist/rate-limit/index.d.ts +6 -0
- package/dist/rate-limit/index.d.ts.map +1 -0
- package/dist/rate-limit/index.js +6 -0
- package/dist/rate-limit/index.js.map +1 -0
- package/dist/rate-limit/limiter.d.ts +38 -0
- package/dist/rate-limit/limiter.d.ts.map +1 -0
- package/dist/rate-limit/limiter.js +55 -0
- package/dist/rate-limit/limiter.js.map +1 -0
- package/dist/sandbox/context.d.ts +69 -0
- package/dist/sandbox/context.d.ts.map +1 -0
- package/dist/sandbox/context.js +134 -0
- package/dist/sandbox/context.js.map +1 -0
- package/dist/sandbox/executor.d.ts +50 -0
- package/dist/sandbox/executor.d.ts.map +1 -0
- package/dist/sandbox/executor.js +259 -0
- package/dist/sandbox/executor.js.map +1 -0
- package/dist/sandbox/index.d.ts +8 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/index.js +8 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sandbox/url-validator.d.ts +40 -0
- package/dist/sandbox/url-validator.d.ts.map +1 -0
- package/dist/sandbox/url-validator.js +178 -0
- package/dist/sandbox/url-validator.js.map +1 -0
- package/dist/secrets/index.d.ts +7 -0
- package/dist/secrets/index.d.ts.map +1 -0
- package/dist/secrets/index.js +7 -0
- package/dist/secrets/index.js.map +1 -0
- package/dist/secrets/manager.d.ts +55 -0
- package/dist/secrets/manager.d.ts.map +1 -0
- package/dist/secrets/manager.js +94 -0
- package/dist/secrets/manager.js.map +1 -0
- package/dist/secrets/patterns.d.ts +33 -0
- package/dist/secrets/patterns.d.ts.map +1 -0
- package/dist/secrets/patterns.js +71 -0
- package/dist/secrets/patterns.js.map +1 -0
- package/dist/server/index.d.ts +6 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +6 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/mcp.d.ts +60 -0
- package/dist/server/mcp.d.ts.map +1 -0
- package/dist/server/mcp.js +173 -0
- package/dist/server/mcp.js.map +1 -0
- package/dist/worker/index.d.ts +7 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +7 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker/process.d.ts +64 -0
- package/dist/worker/process.d.ts.map +1 -0
- package/dist/worker/process.js +222 -0
- package/dist/worker/process.js.map +1 -0
- package/dist/worker/protocol.d.ts +83 -0
- package/dist/worker/protocol.d.ts.map +1 -0
- package/dist/worker/protocol.js +55 -0
- package/dist/worker/protocol.js.map +1 -0
- package/dist/worker/worker-entry.d.ts +30 -0
- package/dist/worker/worker-entry.d.ts.map +1 -0
- package/dist/worker/worker-entry.js +136 -0
- package/dist/worker/worker-entry.js.map +1 -0
- 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
|
+
[](https://www.npmjs.com/package/git-doc-mcp)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://nodejs.org/)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://github.com)
|
|
8
|
+
[](https://github.com)
|
|
9
|
+
[](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 @@
|
|
|
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 @@
|
|
|
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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"}
|