@blink-authority-com/claude-code-plugin 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.
- package/LICENSE +21 -0
- package/README.md +146 -0
- package/dist/bsec-client.d.ts +35 -0
- package/dist/bsec-client.d.ts.map +1 -0
- package/dist/bsec-client.js +122 -0
- package/dist/bsec-client.js.map +1 -0
- package/dist/docs/cache.d.ts +19 -0
- package/dist/docs/cache.d.ts.map +1 -0
- package/dist/docs/cache.js +92 -0
- package/dist/docs/cache.js.map +1 -0
- package/dist/docs/fetcher.d.ts +19 -0
- package/dist/docs/fetcher.d.ts.map +1 -0
- package/dist/docs/fetcher.js +81 -0
- package/dist/docs/fetcher.js.map +1 -0
- package/dist/docs/parser.d.ts +33 -0
- package/dist/docs/parser.d.ts.map +1 -0
- package/dist/docs/parser.js +145 -0
- package/dist/docs/parser.js.map +1 -0
- package/dist/docs/search.d.ts +38 -0
- package/dist/docs/search.d.ts.map +1 -0
- package/dist/docs/search.js +180 -0
- package/dist/docs/search.js.map +1 -0
- package/dist/docs/tools/api.d.ts +12 -0
- package/dist/docs/tools/api.d.ts.map +1 -0
- package/dist/docs/tools/api.js +58 -0
- package/dist/docs/tools/api.js.map +1 -0
- package/dist/docs/tools/cli.d.ts +12 -0
- package/dist/docs/tools/cli.d.ts.map +1 -0
- package/dist/docs/tools/cli.js +56 -0
- package/dist/docs/tools/cli.js.map +1 -0
- package/dist/docs/tools/concepts.d.ts +18 -0
- package/dist/docs/tools/concepts.d.ts.map +1 -0
- package/dist/docs/tools/concepts.js +136 -0
- package/dist/docs/tools/concepts.js.map +1 -0
- package/dist/docs/tools/sdk.d.ts +12 -0
- package/dist/docs/tools/sdk.d.ts.map +1 -0
- package/dist/docs/tools/sdk.js +72 -0
- package/dist/docs/tools/sdk.js.map +1 -0
- package/dist/docs/tools/search.d.ts +11 -0
- package/dist/docs/tools/search.d.ts.map +1 -0
- package/dist/docs/tools/search.js +36 -0
- package/dist/docs/tools/search.js.map +1 -0
- package/dist/docs/types.d.ts +70 -0
- package/dist/docs/types.d.ts.map +1 -0
- package/dist/docs/types.js +8 -0
- package/dist/docs/types.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +622 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/debug.d.ts +16 -0
- package/dist/prompts/debug.d.ts.map +1 -0
- package/dist/prompts/debug.js +34 -0
- package/dist/prompts/debug.js.map +1 -0
- package/dist/prompts/integrate.d.ts +16 -0
- package/dist/prompts/integrate.d.ts.map +1 -0
- package/dist/prompts/integrate.js +30 -0
- package/dist/prompts/integrate.js.map +1 -0
- package/dist/prompts/review.d.ts +16 -0
- package/dist/prompts/review.d.ts.map +1 -0
- package/dist/prompts/review.js +28 -0
- package/dist/prompts/review.js.map +1 -0
- package/dist/resources/changelog.d.ts +22 -0
- package/dist/resources/changelog.d.ts.map +1 -0
- package/dist/resources/changelog.js +55 -0
- package/dist/resources/changelog.js.map +1 -0
- package/dist/resources/errors.d.ts +16 -0
- package/dist/resources/errors.d.ts.map +1 -0
- package/dist/resources/errors.js +103 -0
- package/dist/resources/errors.js.map +1 -0
- package/dist/resources/patterns.d.ts +16 -0
- package/dist/resources/patterns.d.ts.map +1 -0
- package/dist/resources/patterns.js +151 -0
- package/dist/resources/patterns.js.map +1 -0
- package/dist/templates/approval-workflow.d.ts +6 -0
- package/dist/templates/approval-workflow.d.ts.map +1 -0
- package/dist/templates/approval-workflow.js +467 -0
- package/dist/templates/approval-workflow.js.map +1 -0
- package/dist/templates/audit-trail.d.ts +6 -0
- package/dist/templates/audit-trail.d.ts.map +1 -0
- package/dist/templates/audit-trail.js +396 -0
- package/dist/templates/audit-trail.js.map +1 -0
- package/dist/templates/cli-tool.d.ts +6 -0
- package/dist/templates/cli-tool.d.ts.map +1 -0
- package/dist/templates/cli-tool.js +346 -0
- package/dist/templates/cli-tool.js.map +1 -0
- package/dist/templates/express-api.d.ts +6 -0
- package/dist/templates/express-api.d.ts.map +1 -0
- package/dist/templates/express-api.js +314 -0
- package/dist/templates/express-api.js.map +1 -0
- package/dist/templates/notary.d.ts +6 -0
- package/dist/templates/notary.d.ts.map +1 -0
- package/dist/templates/notary.js +360 -0
- package/dist/templates/notary.js.map +1 -0
- package/dist/test.d.ts +8 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +140 -0
- package/dist/test.js.map +1 -0
- package/dist/tools/add-signing.d.ts +19 -0
- package/dist/tools/add-signing.d.ts.map +1 -0
- package/dist/tools/add-signing.js +317 -0
- package/dist/tools/add-signing.js.map +1 -0
- package/dist/tools/decode.d.ts +13 -0
- package/dist/tools/decode.d.ts.map +1 -0
- package/dist/tools/decode.js +262 -0
- package/dist/tools/decode.js.map +1 -0
- package/dist/tools/hierarchy.d.ts +13 -0
- package/dist/tools/hierarchy.d.ts.map +1 -0
- package/dist/tools/hierarchy.js +319 -0
- package/dist/tools/hierarchy.js.map +1 -0
- package/dist/tools/lint.d.ts +13 -0
- package/dist/tools/lint.d.ts.map +1 -0
- package/dist/tools/lint.js +323 -0
- package/dist/tools/lint.js.map +1 -0
- package/dist/tools/scaffold.d.ts +11 -0
- package/dist/tools/scaffold.d.ts.map +1 -0
- package/dist/tools/scaffold.js +84 -0
- package/dist/tools/scaffold.js.map +1 -0
- package/dist/tools/sign-test.d.ts +17 -0
- package/dist/tools/sign-test.d.ts.map +1 -0
- package/dist/tools/sign-test.js +126 -0
- package/dist/tools/sign-test.js.map +1 -0
- package/dist/tools/test-vectors.d.ts +13 -0
- package/dist/tools/test-vectors.d.ts.map +1 -0
- package/dist/tools/test-vectors.js +169 -0
- package/dist/tools/test-vectors.js.map +1 -0
- package/dist/tools/verify-local.d.ts +17 -0
- package/dist/tools/verify-local.d.ts.map +1 -0
- package/dist/tools/verify-local.js +233 -0
- package/dist/tools/verify-local.js.map +1 -0
- package/dist/tools/verify-test.d.ts +17 -0
- package/dist/tools/verify-test.d.ts.map +1 -0
- package/dist/tools/verify-test.js +107 -0
- package/dist/tools/verify-test.js.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BLINK Authority
|
|
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,146 @@
|
|
|
1
|
+
# @blink-authority-com/claude-code-plugin
|
|
2
|
+
|
|
3
|
+
BLINK Authority's Claude Code Plugin -- AI-native development tools for ephemeral cryptographic signing. This MCP (Model Context Protocol) server gives Claude direct access to BLINK documentation, code scaffolding, signing envelope tools, and optional live BSEC integration for real-time VRF composite signing and verification.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### Claude Code (CLI)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
claude mcp add blink -- npx @blink-authority-com/claude-code-plugin
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or add to your project's `.mcp.json`:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"mcpServers": {
|
|
18
|
+
"blink": {
|
|
19
|
+
"command": "npx",
|
|
20
|
+
"args": ["@blink-authority-com/claude-code-plugin"]
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Claude Desktop
|
|
27
|
+
|
|
28
|
+
Add to your Claude Desktop configuration file:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"mcpServers": {
|
|
33
|
+
"blink": {
|
|
34
|
+
"command": "npx",
|
|
35
|
+
"args": ["@blink-authority-com/claude-code-plugin"]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Available Tools
|
|
42
|
+
|
|
43
|
+
| Tool | Description | Example Usage |
|
|
44
|
+
|------|-------------|---------------|
|
|
45
|
+
| `search_blink_docs` | Search BLINK documentation | "How do I verify a VRF signature?" |
|
|
46
|
+
| `get_api_endpoint` | Get API endpoint specs | "Show me the signing endpoint" |
|
|
47
|
+
| `get_cli_command` | Get CLI command help | "How do I use blink sign?" |
|
|
48
|
+
| `get_sdk_guide` | Get SDK integration guide | "TypeScript signing guide" |
|
|
49
|
+
| `get_concept` | Explain a BLINK concept | "What is VRF key derivation?" |
|
|
50
|
+
| `list_available_docs` | List all doc sections | "What docs are available?" |
|
|
51
|
+
| `blink_scaffold` | Generate a BLINK project | "Create an express-api project" |
|
|
52
|
+
| `blink_add_signing` | Add signing to existing code | "Add BLINK signing to this handler" |
|
|
53
|
+
| `blink_decode_envelope` | Decode a signature envelope | "Decode this base64 envelope" |
|
|
54
|
+
| `blink_generate_test_vectors` | Generate mock test vectors | "Generate 5 Ed25519 test vectors" |
|
|
55
|
+
| `blink_verify_local` | Offline format verification | "Verify this envelope format" |
|
|
56
|
+
| `blink_lint` | Lint for BLINK best practices | "Check this code for BLINK issues" |
|
|
57
|
+
| `blink_hierarchy_design` | Design a key hierarchy | "Design keys for my org" |
|
|
58
|
+
| `blink_sign_test` | Live BSEC signing (connected) | "Sign this payload with BSEC" |
|
|
59
|
+
| `blink_verify_test` | Live BSEC verification (connected) | "Verify this envelope with BSEC" |
|
|
60
|
+
|
|
61
|
+
## Resources and Prompts
|
|
62
|
+
|
|
63
|
+
**Resources** (available via MCP resource protocol):
|
|
64
|
+
- `blink://patterns` -- Common BLINK integration patterns
|
|
65
|
+
- `blink://errors` -- Error codes with causes and fixes
|
|
66
|
+
- `blink://changelog` -- Recent BLINK SDK/CLI/BSEC changes
|
|
67
|
+
|
|
68
|
+
**Prompts** (available via MCP prompt protocol):
|
|
69
|
+
- `blink-review` -- Review code for BLINK integration best practices
|
|
70
|
+
- `blink-integrate` -- Guide BLINK integration into an existing project
|
|
71
|
+
- `blink-debug` -- Debug signing or verification issues
|
|
72
|
+
|
|
73
|
+
## Connected Mode
|
|
74
|
+
|
|
75
|
+
Connected mode enables live signing and verification through a BSEC instance. This is optional -- all other tools work offline.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
claude mcp add blink -- npx @blink-authority-com/claude-code-plugin \
|
|
79
|
+
--bsec-url https://your-bsec:8443 \
|
|
80
|
+
--bsec-token YOUR_SESSION_TOKEN
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Or in `.mcp.json`:
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"mcpServers": {
|
|
88
|
+
"blink": {
|
|
89
|
+
"command": "npx",
|
|
90
|
+
"args": [
|
|
91
|
+
"@blink-authority-com/claude-code-plugin",
|
|
92
|
+
"--bsec-url", "https://your-bsec:8443",
|
|
93
|
+
"--bsec-token", "your-session-token"
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
When connected mode is enabled:
|
|
101
|
+
- `blink_sign_test` sends payloads to BSEC for VRF composite signing
|
|
102
|
+
- `blink_verify_test` performs server-side cryptographic verification
|
|
103
|
+
- All connected tool responses include a warning that data is sent externally
|
|
104
|
+
- Credentials are never logged or included in error messages
|
|
105
|
+
|
|
106
|
+
For self-signed BSEC certificates, set `NODE_TLS_REJECT_UNAUTHORIZED=0` in your environment.
|
|
107
|
+
|
|
108
|
+
## Examples
|
|
109
|
+
|
|
110
|
+
### 1. Scaffold a New Project
|
|
111
|
+
|
|
112
|
+
> "Create a BLINK notary service called my-notary in TypeScript"
|
|
113
|
+
|
|
114
|
+
Claude will use `blink_scaffold` to generate a complete project with BSEC integration, signing middleware, and health checks.
|
|
115
|
+
|
|
116
|
+
### 2. Debug a Verification Failure
|
|
117
|
+
|
|
118
|
+
> "I'm getting a VRF proof chain error. Here's my code: ..."
|
|
119
|
+
|
|
120
|
+
Claude will use `blink_lint` to check for common mistakes, `get_concept` to explain VRF verification, and `blink-debug` prompt for structured troubleshooting.
|
|
121
|
+
|
|
122
|
+
### 3. Review Integration Code
|
|
123
|
+
|
|
124
|
+
> "Review this signing handler for BLINK best practices"
|
|
125
|
+
|
|
126
|
+
Claude will use `blink_lint` and the `blink-review` prompt to analyze your code for error handling, key lifecycle issues, and security patterns.
|
|
127
|
+
|
|
128
|
+
## Configuration Options
|
|
129
|
+
|
|
130
|
+
| Option | Description | Default |
|
|
131
|
+
|--------|-------------|---------|
|
|
132
|
+
| `--bsec-url` | BSEC instance URL for connected mode | _(none -- offline mode)_ |
|
|
133
|
+
| `--bsec-token` | BSEC session token for authentication | _(none -- offline mode)_ |
|
|
134
|
+
| `--cache-ttl` | Documentation cache TTL in seconds | `3600` |
|
|
135
|
+
| `--docs-url` | Custom BLINK documentation URL | `https://docs.blink-authority.com` |
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
|
|
139
|
+
MIT -- see [LICENSE](./LICENSE) for details.
|
|
140
|
+
|
|
141
|
+
## Links
|
|
142
|
+
|
|
143
|
+
- [BLINK Authority](https://blink-authority.com)
|
|
144
|
+
- [npm package](https://www.npmjs.com/package/@blink-authority-com/claude-code-plugin)
|
|
145
|
+
- [Documentation](https://docs.blink-authority.com)
|
|
146
|
+
- [BLINK GitHub](https://github.com/blink-authority)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin BSEC Client — minimal HTTP client for connected mode.
|
|
3
|
+
*
|
|
4
|
+
* Uses Node.js built-in fetch to communicate with a BSEC instance.
|
|
5
|
+
* Credentials are NEVER logged, serialised, or included in error messages.
|
|
6
|
+
*
|
|
7
|
+
* @module bsec-client
|
|
8
|
+
*/
|
|
9
|
+
export interface SignResult {
|
|
10
|
+
signature: string;
|
|
11
|
+
ephemeral_public_key: string;
|
|
12
|
+
vrf_proof: string;
|
|
13
|
+
p_derive: string;
|
|
14
|
+
domain_input: string;
|
|
15
|
+
algo_suite_id: number;
|
|
16
|
+
}
|
|
17
|
+
export interface VerifyResult {
|
|
18
|
+
valid: boolean;
|
|
19
|
+
details: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
export declare class BsecClientError extends Error {
|
|
22
|
+
readonly status: number;
|
|
23
|
+
constructor(status: number, context: string);
|
|
24
|
+
}
|
|
25
|
+
export declare class PluginBsecClient {
|
|
26
|
+
private readonly baseUrl;
|
|
27
|
+
private readonly token;
|
|
28
|
+
constructor(url: string, token: string);
|
|
29
|
+
health(): Promise<boolean>;
|
|
30
|
+
vrfCompositeSign(payload: Buffer, domainInput: string, algoSuiteId?: number): Promise<SignResult>;
|
|
31
|
+
verify(envelope: string, pDerive: string): Promise<VerifyResult>;
|
|
32
|
+
private request;
|
|
33
|
+
}
|
|
34
|
+
export declare function createPluginBsecClient(url: string, token: string): PluginBsecClient;
|
|
35
|
+
//# sourceMappingURL=bsec-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bsec-client.d.ts","sourceRoot":"","sources":["../src/bsec-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,SAAgB,MAAM,EAAE,MAAM,CAAC;gBAEnB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAM5C;AAOD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAShC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAY1B,gBAAgB,CACpB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,WAAW,GAAE,MAAU,GACtB,OAAO,CAAC,UAAU,CAAC;IA6BhB,MAAM,CACV,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC;YA2BV,OAAO;CAyBtB;AAKD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,gBAAgB,CASnF"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin BSEC Client — minimal HTTP client for connected mode.
|
|
3
|
+
*
|
|
4
|
+
* Uses Node.js built-in fetch to communicate with a BSEC instance.
|
|
5
|
+
* Credentials are NEVER logged, serialised, or included in error messages.
|
|
6
|
+
*
|
|
7
|
+
* @module bsec-client
|
|
8
|
+
*/
|
|
9
|
+
export class BsecClientError extends Error {
|
|
10
|
+
status;
|
|
11
|
+
constructor(status, context) {
|
|
12
|
+
// NEVER include raw BSEC error body in the message
|
|
13
|
+
super(`BSEC ${context} failed with status ${status}`);
|
|
14
|
+
this.name = 'BsecClientError';
|
|
15
|
+
this.status = status;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Client
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
const TIMEOUT_MS = 30_000;
|
|
22
|
+
export class PluginBsecClient {
|
|
23
|
+
baseUrl;
|
|
24
|
+
token;
|
|
25
|
+
constructor(url, token) {
|
|
26
|
+
this.baseUrl = url.replace(/\/$/, '');
|
|
27
|
+
this.token = token;
|
|
28
|
+
// token is NEVER logged, NEVER in toString/inspect, NEVER in errors
|
|
29
|
+
}
|
|
30
|
+
// -------------------------------------------------------------------------
|
|
31
|
+
// Health check
|
|
32
|
+
// -------------------------------------------------------------------------
|
|
33
|
+
async health() {
|
|
34
|
+
try {
|
|
35
|
+
const response = await this.request('GET', '/v1/health');
|
|
36
|
+
return response.ok;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// -------------------------------------------------------------------------
|
|
43
|
+
// VRF composite sign
|
|
44
|
+
// -------------------------------------------------------------------------
|
|
45
|
+
async vrfCompositeSign(payload, domainInput, algoSuiteId = 1) {
|
|
46
|
+
const payloadBase64 = payload.toString('base64');
|
|
47
|
+
const domainInputBase64 = Buffer.from(domainInput, 'utf-8').toString('base64');
|
|
48
|
+
const response = await this.request('POST', '/v1/sign/vrf-composite', {
|
|
49
|
+
payload: payloadBase64,
|
|
50
|
+
domain_input: domainInputBase64,
|
|
51
|
+
algo_suite_id: algoSuiteId,
|
|
52
|
+
});
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
throw new BsecClientError(response.status, 'vrfCompositeSign');
|
|
55
|
+
}
|
|
56
|
+
const data = (await response.json());
|
|
57
|
+
return {
|
|
58
|
+
signature: data['signature'],
|
|
59
|
+
ephemeral_public_key: data['ephemeral_public_key'],
|
|
60
|
+
vrf_proof: data['vrf_proof'],
|
|
61
|
+
p_derive: data['vrf_public_key'],
|
|
62
|
+
domain_input: domainInput,
|
|
63
|
+
algo_suite_id: data['algo_suite_id'],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// -------------------------------------------------------------------------
|
|
67
|
+
// Verify (if endpoint available)
|
|
68
|
+
// -------------------------------------------------------------------------
|
|
69
|
+
async verify(envelope, pDerive) {
|
|
70
|
+
const response = await this.request('POST', '/v1/verify', {
|
|
71
|
+
envelope,
|
|
72
|
+
p_derive: pDerive,
|
|
73
|
+
});
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
// Verify endpoint may not exist on all BSEC versions
|
|
76
|
+
if (response.status === 404) {
|
|
77
|
+
return {
|
|
78
|
+
valid: false,
|
|
79
|
+
details: { error: 'BSEC verify endpoint not available on this instance' },
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
throw new BsecClientError(response.status, 'verify');
|
|
83
|
+
}
|
|
84
|
+
const data = (await response.json());
|
|
85
|
+
return {
|
|
86
|
+
valid: data['valid'],
|
|
87
|
+
details: data,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
// -------------------------------------------------------------------------
|
|
91
|
+
// Internal fetch wrapper
|
|
92
|
+
// -------------------------------------------------------------------------
|
|
93
|
+
async request(method, path, body) {
|
|
94
|
+
const url = `${this.baseUrl}${path}`;
|
|
95
|
+
const headers = {
|
|
96
|
+
'Accept': 'application/vnd.blink.v2+json',
|
|
97
|
+
'x-blink-session': this.token,
|
|
98
|
+
};
|
|
99
|
+
const init = {
|
|
100
|
+
method,
|
|
101
|
+
headers,
|
|
102
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
103
|
+
};
|
|
104
|
+
if (body) {
|
|
105
|
+
headers['Content-Type'] = 'application/json';
|
|
106
|
+
init.body = JSON.stringify(body);
|
|
107
|
+
}
|
|
108
|
+
return fetch(url, init);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// Factory
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
export function createPluginBsecClient(url, token) {
|
|
115
|
+
// Warn about self-signed certs
|
|
116
|
+
if (url.startsWith('https://') && !process.env['NODE_TLS_REJECT_UNAUTHORIZED']) {
|
|
117
|
+
process.stderr.write('[blink-plugin] Warning: connecting to BSEC over HTTPS. ' +
|
|
118
|
+
'Set NODE_TLS_REJECT_UNAUTHORIZED=0 for self-signed certificates.\n');
|
|
119
|
+
}
|
|
120
|
+
return new PluginBsecClient(url, token);
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=bsec-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bsec-client.js","sourceRoot":"","sources":["../src/bsec-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BLINK Authority MCP Server — File-based Cache Manager
|
|
3
|
+
*/
|
|
4
|
+
import type { CacheManifest } from './types.js';
|
|
5
|
+
export declare class CacheManager {
|
|
6
|
+
private cacheDir;
|
|
7
|
+
private manifestPath;
|
|
8
|
+
constructor(cacheDir?: string);
|
|
9
|
+
private ensureDir;
|
|
10
|
+
private keyToPath;
|
|
11
|
+
get(key: string): string | null;
|
|
12
|
+
set(key: string, content: string): void;
|
|
13
|
+
isStale(key: string, ttlMs: number): boolean;
|
|
14
|
+
getManifest(): CacheManifest;
|
|
15
|
+
private updateManifest;
|
|
16
|
+
getAllCachedKeys(): string[];
|
|
17
|
+
getAllCachedContent(): Map<string, string>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/docs/cache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAKhD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAAS;gBAEjB,QAAQ,CAAC,EAAE,MAAM;IAM7B,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,SAAS;IAMjB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAU/B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAOvC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAY5C,WAAW,IAAI,aAAa;IAW5B,OAAO,CAAC,cAAc;IAYtB,gBAAgB,IAAI,MAAM,EAAE;IAK5B,mBAAmB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;CAU3C"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BLINK Authority MCP Server — File-based Cache Manager
|
|
3
|
+
*/
|
|
4
|
+
import { mkdirSync, readFileSync, writeFileSync, existsSync, statSync } from 'node:fs';
|
|
5
|
+
import { join, dirname } from 'node:path';
|
|
6
|
+
import { homedir } from 'node:os';
|
|
7
|
+
const CACHE_DIR = join(homedir(), '.blink-mcp', 'cache');
|
|
8
|
+
const MANIFEST_PATH = join(CACHE_DIR, 'manifest.json');
|
|
9
|
+
export class CacheManager {
|
|
10
|
+
cacheDir;
|
|
11
|
+
manifestPath;
|
|
12
|
+
constructor(cacheDir) {
|
|
13
|
+
this.cacheDir = cacheDir ?? CACHE_DIR;
|
|
14
|
+
this.manifestPath = cacheDir ? join(cacheDir, 'manifest.json') : MANIFEST_PATH;
|
|
15
|
+
this.ensureDir(this.cacheDir);
|
|
16
|
+
}
|
|
17
|
+
ensureDir(dir) {
|
|
18
|
+
mkdirSync(dir, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
keyToPath(key) {
|
|
21
|
+
// key like "api/signing" -> ~/.blink-mcp/cache/api/signing.md
|
|
22
|
+
const safePath = key.replace(/[^a-zA-Z0-9/_-]/g, '_');
|
|
23
|
+
return join(this.cacheDir, `${safePath}.md`);
|
|
24
|
+
}
|
|
25
|
+
get(key) {
|
|
26
|
+
const filePath = this.keyToPath(key);
|
|
27
|
+
if (!existsSync(filePath))
|
|
28
|
+
return null;
|
|
29
|
+
try {
|
|
30
|
+
return readFileSync(filePath, 'utf-8');
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
set(key, content) {
|
|
37
|
+
const filePath = this.keyToPath(key);
|
|
38
|
+
this.ensureDir(dirname(filePath));
|
|
39
|
+
writeFileSync(filePath, content, 'utf-8');
|
|
40
|
+
this.updateManifest(key);
|
|
41
|
+
}
|
|
42
|
+
isStale(key, ttlMs) {
|
|
43
|
+
const filePath = this.keyToPath(key);
|
|
44
|
+
if (!existsSync(filePath))
|
|
45
|
+
return true;
|
|
46
|
+
try {
|
|
47
|
+
const stat = statSync(filePath);
|
|
48
|
+
const age = Date.now() - stat.mtimeMs;
|
|
49
|
+
return age > ttlMs;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
getManifest() {
|
|
56
|
+
if (!existsSync(this.manifestPath)) {
|
|
57
|
+
return { lastFetchedAt: '', docCount: 0, documents: {} };
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
return JSON.parse(readFileSync(this.manifestPath, 'utf-8'));
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return { lastFetchedAt: '', docCount: 0, documents: {} };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
updateManifest(key) {
|
|
67
|
+
const manifest = this.getManifest();
|
|
68
|
+
manifest.lastFetchedAt = new Date().toISOString();
|
|
69
|
+
manifest.documents[key] = {
|
|
70
|
+
sourceUrl: key,
|
|
71
|
+
fetchedAt: new Date().toISOString(),
|
|
72
|
+
path: key,
|
|
73
|
+
};
|
|
74
|
+
manifest.docCount = Object.keys(manifest.documents).length;
|
|
75
|
+
writeFileSync(this.manifestPath, JSON.stringify(manifest, null, 2), 'utf-8');
|
|
76
|
+
}
|
|
77
|
+
getAllCachedKeys() {
|
|
78
|
+
const manifest = this.getManifest();
|
|
79
|
+
return Object.keys(manifest.documents);
|
|
80
|
+
}
|
|
81
|
+
getAllCachedContent() {
|
|
82
|
+
const result = new Map();
|
|
83
|
+
for (const key of this.getAllCachedKeys()) {
|
|
84
|
+
const content = this.get(key);
|
|
85
|
+
if (content) {
|
|
86
|
+
result.set(key, content);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/docs/cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BLINK Authority MCP Server — HTTP Content Fetcher
|
|
3
|
+
*/
|
|
4
|
+
export declare function fetchDoc(url: string): Promise<string>;
|
|
5
|
+
/**
|
|
6
|
+
* Parse llms.txt to discover all document URLs.
|
|
7
|
+
* Expected format: lines containing markdown links like [Title](url)
|
|
8
|
+
* or plain URLs ending in .md
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseLlmsTxt(content: string, baseUrl: string): Array<{
|
|
11
|
+
title: string;
|
|
12
|
+
url: string;
|
|
13
|
+
path: string;
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* Fetch all docs listed in llms.txt, with concurrency limiting.
|
|
17
|
+
*/
|
|
18
|
+
export declare function fetchAllDocs(baseUrl: string): Promise<Map<string, string>>;
|
|
19
|
+
//# sourceMappingURL=fetcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../../src/docs/fetcher.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB3D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAuBlH;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA6BhF"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BLINK Authority MCP Server — HTTP Content Fetcher
|
|
3
|
+
*/
|
|
4
|
+
const REQUEST_TIMEOUT_MS = 10_000;
|
|
5
|
+
const CONCURRENT_LIMIT = 5;
|
|
6
|
+
export async function fetchDoc(url) {
|
|
7
|
+
const controller = new AbortController();
|
|
8
|
+
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
9
|
+
try {
|
|
10
|
+
const response = await fetch(url, {
|
|
11
|
+
signal: controller.signal,
|
|
12
|
+
headers: { 'User-Agent': 'blink-docs-mcp/1.0' },
|
|
13
|
+
});
|
|
14
|
+
if (!response.ok) {
|
|
15
|
+
throw new Error(`HTTP ${response.status} fetching ${url}`);
|
|
16
|
+
}
|
|
17
|
+
return await response.text();
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
clearTimeout(timer);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse llms.txt to discover all document URLs.
|
|
25
|
+
* Expected format: lines containing markdown links like [Title](url)
|
|
26
|
+
* or plain URLs ending in .md
|
|
27
|
+
*/
|
|
28
|
+
export function parseLlmsTxt(content, baseUrl) {
|
|
29
|
+
const docs = [];
|
|
30
|
+
const lines = content.split('\n');
|
|
31
|
+
for (const line of lines) {
|
|
32
|
+
// Match markdown links: [Title](path)
|
|
33
|
+
const mdMatch = line.match(/\[([^\]]+)\]\(([^)]+)\)/);
|
|
34
|
+
if (mdMatch) {
|
|
35
|
+
const title = mdMatch[1];
|
|
36
|
+
let url = mdMatch[2];
|
|
37
|
+
// Make relative URLs absolute
|
|
38
|
+
if (url.startsWith('/')) {
|
|
39
|
+
url = `${baseUrl}${url}`;
|
|
40
|
+
}
|
|
41
|
+
else if (!url.startsWith('http')) {
|
|
42
|
+
url = `${baseUrl}/${url}`;
|
|
43
|
+
}
|
|
44
|
+
// Derive a cache path from the URL
|
|
45
|
+
const path = url.replace(baseUrl, '').replace(/^\//, '').replace(/\.md$/, '');
|
|
46
|
+
docs.push({ title, url, path });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return docs;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Fetch all docs listed in llms.txt, with concurrency limiting.
|
|
53
|
+
*/
|
|
54
|
+
export async function fetchAllDocs(baseUrl) {
|
|
55
|
+
const llmsTxtUrl = `${baseUrl}/llms.txt`;
|
|
56
|
+
const llmsTxt = await fetchDoc(llmsTxtUrl);
|
|
57
|
+
const docEntries = parseLlmsTxt(llmsTxt, baseUrl);
|
|
58
|
+
const results = new Map();
|
|
59
|
+
// Process in batches of CONCURRENT_LIMIT
|
|
60
|
+
for (let i = 0; i < docEntries.length; i += CONCURRENT_LIMIT) {
|
|
61
|
+
const batch = docEntries.slice(i, i + CONCURRENT_LIMIT);
|
|
62
|
+
const promises = batch.map(async (entry) => {
|
|
63
|
+
try {
|
|
64
|
+
const content = await fetchDoc(entry.url);
|
|
65
|
+
return { path: entry.path, content };
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
process.stderr.write(`[blink-mcp] Warning: failed to fetch ${entry.url}: ${err}\n`);
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
const batchResults = await Promise.all(promises);
|
|
73
|
+
for (const result of batchResults) {
|
|
74
|
+
if (result) {
|
|
75
|
+
results.set(result.path, result.content);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return results;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=fetcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetcher.js","sourceRoot":"","sources":["../../src/docs/fetcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BLINK Authority MCP Server — Markdown Parser
|
|
3
|
+
*/
|
|
4
|
+
import type { DocSection } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Parse a markdown document into structured sections split by headings.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseDocument(markdown: string, path: string): DocSection[];
|
|
9
|
+
/**
|
|
10
|
+
* Extract structured API endpoint info from a parsed doc section.
|
|
11
|
+
*/
|
|
12
|
+
export declare function extractApiInfo(sections: DocSection[]): {
|
|
13
|
+
method: string;
|
|
14
|
+
apiPath: string;
|
|
15
|
+
description: string;
|
|
16
|
+
requestFormat: string;
|
|
17
|
+
responseFormat: string;
|
|
18
|
+
codeExample: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Extract CLI command info from parsed doc sections.
|
|
22
|
+
*/
|
|
23
|
+
export declare function extractCliInfo(sections: DocSection[]): {
|
|
24
|
+
description: string;
|
|
25
|
+
usage: string;
|
|
26
|
+
flags: Array<{
|
|
27
|
+
flag: string;
|
|
28
|
+
description: string;
|
|
29
|
+
required: boolean;
|
|
30
|
+
}>;
|
|
31
|
+
examples: string[];
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/docs/parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,CA0E1E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB,CA+BA;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACvE,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CA+BA"}
|