@1sat/cli 0.0.13 → 0.0.14
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/package.json +3 -2
- package/src/commands/mcp-proxy.ts +39 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1sat/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "CLI for 1Sat Ordinals SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/cli.ts",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"chalk": "^5.0.0",
|
|
25
25
|
"@clack/prompts": "^0.8.0",
|
|
26
26
|
"bitcoin-backup": "^0.0.11",
|
|
27
|
-
"dotenv": "^17.0.0"
|
|
27
|
+
"dotenv": "^17.0.0",
|
|
28
|
+
"evlog": "^2.10.0"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
31
|
"@types/bun": "^1.3.9",
|
|
@@ -7,18 +7,17 @@
|
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
8
8
|
import { Hash, KeyDeriver, PrivateKey, Signature, Utils } from '@bsv/sdk'
|
|
9
9
|
import type { WalletProtocol } from '@bsv/sdk'
|
|
10
|
+
import { createLogger, initLogger } from 'evlog'
|
|
10
11
|
|
|
11
12
|
const { toBase64, toArray } = Utils
|
|
12
13
|
|
|
14
|
+
initLogger({ env: { service: '1sat-mcp-proxy' } })
|
|
15
|
+
|
|
13
16
|
const MCP_URL = process.env.ONESAT_MCP_URL ?? 'http://127.0.0.1:3322'
|
|
14
17
|
const KEY_DIR = `${process.env.HOME}/.1sat-wallet`
|
|
15
18
|
const CLIENT_KEY_PATH = `${KEY_DIR}/mcp-agent.key`
|
|
16
19
|
const AUTH_PROTOCOL_ID: WalletProtocol = [2, 'authrite message signature']
|
|
17
20
|
|
|
18
|
-
function log(msg: string): void {
|
|
19
|
-
process.stderr.write(`[1sat mcp-proxy] ${msg}\n`)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
21
|
function generateNonce(): string {
|
|
23
22
|
const bytes = new Uint8Array(32)
|
|
24
23
|
crypto.getRandomValues(bytes)
|
|
@@ -32,7 +31,9 @@ function getClientKey(): PrivateKey {
|
|
|
32
31
|
}
|
|
33
32
|
const key = PrivateKey.fromRandom()
|
|
34
33
|
writeFileSync(CLIENT_KEY_PATH, key.toWif(), { mode: 0o600 })
|
|
35
|
-
log
|
|
34
|
+
const log = createLogger({ context: 'startup' })
|
|
35
|
+
log.set({ event: 'key_generated', path: CLIENT_KEY_PATH })
|
|
36
|
+
log.emit()
|
|
36
37
|
return key
|
|
37
38
|
}
|
|
38
39
|
|
|
@@ -75,7 +76,10 @@ async function handshake(key: PrivateKey): Promise<Session> {
|
|
|
75
76
|
const sig = Signature.fromDER(data.signature as string, 'hex')
|
|
76
77
|
if (!serverPub.verify(Array.from(msgHash), sig)) throw new Error('Server signature verification failed')
|
|
77
78
|
|
|
78
|
-
log
|
|
79
|
+
const log = createLogger({ context: 'auth' })
|
|
80
|
+
log.set({ event: 'handshake_complete', serverIdentityKey: (data.identityKey as string).slice(0, 16) })
|
|
81
|
+
log.emit()
|
|
82
|
+
|
|
79
83
|
return { serverIdentityKey: data.identityKey as string, serverNonce, clientKey: key }
|
|
80
84
|
}
|
|
81
85
|
|
|
@@ -98,17 +102,25 @@ function signHeaders(session: Session, pathname: string): Record<string, string>
|
|
|
98
102
|
}
|
|
99
103
|
|
|
100
104
|
export async function handleMcpProxyCommand(): Promise<void> {
|
|
105
|
+
const startLog = createLogger({ context: 'startup' })
|
|
106
|
+
|
|
101
107
|
try {
|
|
102
108
|
await fetch(MCP_URL, { signal: AbortSignal.timeout(2000) })
|
|
103
109
|
} catch {
|
|
104
|
-
|
|
110
|
+
startLog.set({ event: 'server_unreachable', url: MCP_URL })
|
|
111
|
+
startLog.emit()
|
|
112
|
+
process.stderr.write(`[1sat mcp-proxy] Server not reachable at ${MCP_URL} — is 1Sat wallet running?\n`)
|
|
105
113
|
process.exit(1)
|
|
106
114
|
}
|
|
107
115
|
|
|
116
|
+
startLog.set({ event: 'started', url: MCP_URL })
|
|
117
|
+
startLog.emit()
|
|
118
|
+
|
|
108
119
|
const key = getClientKey()
|
|
109
120
|
const session = await handshake(key)
|
|
110
121
|
|
|
111
122
|
let mcpSessionId: string | null = null
|
|
123
|
+
let requestCount = 0
|
|
112
124
|
const decoder = new TextDecoder()
|
|
113
125
|
const reader = Bun.stdin.stream().getReader()
|
|
114
126
|
let buffer = ''
|
|
@@ -125,6 +137,9 @@ export async function handleMcpProxyCommand(): Promise<void> {
|
|
|
125
137
|
buffer = buffer.slice(newlineIdx + 1)
|
|
126
138
|
if (!line) continue
|
|
127
139
|
|
|
140
|
+
requestCount++
|
|
141
|
+
const reqLog = createLogger({ context: 'proxy' })
|
|
142
|
+
|
|
128
143
|
const headers: Record<string, string> = {
|
|
129
144
|
'Content-Type': 'application/json',
|
|
130
145
|
Accept: 'application/json, text/event-stream',
|
|
@@ -136,6 +151,11 @@ export async function handleMcpProxyCommand(): Promise<void> {
|
|
|
136
151
|
}
|
|
137
152
|
|
|
138
153
|
try {
|
|
154
|
+
let method: string | undefined
|
|
155
|
+
try {
|
|
156
|
+
method = JSON.parse(line).method
|
|
157
|
+
} catch {}
|
|
158
|
+
|
|
139
159
|
const res = await fetch(`${MCP_URL}/mcp`, { method: 'POST', headers, body: line })
|
|
140
160
|
|
|
141
161
|
const sessionHeader = res.headers.get('mcp-session-id')
|
|
@@ -143,6 +163,16 @@ export async function handleMcpProxyCommand(): Promise<void> {
|
|
|
143
163
|
|
|
144
164
|
const contentType = res.headers.get('content-type') ?? ''
|
|
145
165
|
|
|
166
|
+
reqLog.set({
|
|
167
|
+
event: 'request',
|
|
168
|
+
requestNum: requestCount,
|
|
169
|
+
method,
|
|
170
|
+
status: res.status,
|
|
171
|
+
contentType: contentType.split(';')[0],
|
|
172
|
+
sessionId: mcpSessionId?.slice(0, 8),
|
|
173
|
+
})
|
|
174
|
+
reqLog.emit()
|
|
175
|
+
|
|
146
176
|
if (contentType.includes('text/event-stream')) {
|
|
147
177
|
const text = await res.text()
|
|
148
178
|
for (const eventLine of text.split('\n')) {
|
|
@@ -157,7 +187,8 @@ export async function handleMcpProxyCommand(): Promise<void> {
|
|
|
157
187
|
}
|
|
158
188
|
} catch (err) {
|
|
159
189
|
const msg = err instanceof Error ? err.message : String(err)
|
|
160
|
-
|
|
190
|
+
reqLog.set({ event: 'request_failed', requestNum: requestCount, error: msg })
|
|
191
|
+
reqLog.emit()
|
|
161
192
|
process.stdout.write(`${JSON.stringify({
|
|
162
193
|
jsonrpc: '2.0',
|
|
163
194
|
error: { code: -32000, message: `MCP proxy error: ${msg}` },
|