@jdr377/mapapp-agent-connector 0.1.0-pre.7 → 0.1.0-pre.8
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/README.md +29 -30
- package/bun.lock +23 -0
- package/dist/{chunk-4vxwffe8.js → chunk-1qfba14s.js} +3 -3
- package/dist/{chunk-7x21m78n.js → chunk-1yn5h5zx.js} +12 -15
- package/dist/chunk-2c4gc3ws.js +2 -0
- package/dist/{chunk-8cn99cmc.js → chunk-2z3hggm4.js} +1 -1
- package/dist/chunk-576jrq3v.js +3 -0
- package/dist/{chunk-0yre97pb.js → chunk-b04ecsf5.js} +1 -1
- package/dist/chunk-zfr69r1n.js +3 -0
- package/dist/participant-mcp-server.js +12 -6
- package/distribution.json +41 -18
- package/package.json +2 -1
- package/dist/chunk-4tt14q1n.js +0 -3
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import*as z from"zod/v4";var diagnosticSchema=z.object({code:z.string(),remedy:z.string()}).describe("Allow-listed failure code and fixed remedy. Contains no upstream error text, credentials, private paths or message content.");var remedies=new Map;function group(remedy,codes){for(const code of codes)remedies.set(code,remedy)}group("Check the selected tool schema, command options and retained connection metadata. Preserve the original wallet binding.",["participant_configuration_invalid","participant_configuration_too_large","participant_invocation_invalid","participant_tool_not_found","participant_arguments_invalid","participant_arguments_too_large","participant_services_configuration_invalid","participant_wallet_target_invalid","invalid_agent_wallet_connection_configuration","setup_deployment_invalid","setup_state_invalid","invalid_operation_id"]);group("Check retained state and input file paths. Reuse the original wallet or its recovery material; do not replace its root.",["participant_existing_wallet_required","participant_arguments_unavailable","setup_existing_directory_unrecognized","setup_file_invalid","setup_recovery_archive_invalid","restore_operations_invalid","local_intent_database_incompatible"]);group("Wait for the active connection or original operation to settle, then reopen the same state. Do not force an unlock or start a replacement action.",["local_intent_repository_busy","execution_in_progress","participant_closing","read_in_progress"]);group("Verify private-file access, writable storage and free space. Keep original files and keys; do not broaden access or recreate the wallet.",["local_intent_repository_open_failed","local_intent_durability_unavailable","local_intent_namespace_limit","wallet_backup_unavailable"]);group("Check the selected provider, unlock state and app permissions. Keep its expected identity and network; do not substitute a wallet.",["wallet_unauthenticated","permission_denied","read_failed","read_timeout","required_method_missing","invalid_read_response","setup_provider_locked","setup_provider_denied","setup_provider_unavailable","setup_provider_binding_changed","participant_connection_changed","participant_wallet_identity_changed","participant_wallet_network_changed","provider_binding_changed","network_binding_changed","identity_binding_changed","caller_mismatch","setup_deployment_changed","setup_identity_changed","setup_wallet_binding_changed"]);group("Use a new nonexistent destination for a new setup/restore. For recovery, retain the exact root, matching ZIP/binding and a closed checkpointed operation copy.",["restore_requires_new_directory","restore_operations_not_checkpointed","restore_outcome_unknown"]);group("Use the original operationId with this workflow's status/reconcile tools. Preserve original evidence; do not create a replacement spend or message.",["original_intake_unavailable","original_identity_unavailable","original_identity_interrupted","original_sponsor_evidence_unavailable","original_sponsor_or_intake_unavailable","original_sponsor_operation_interrupted","original_operation_interrupted","operation_already_started","unresolved_operation","original_identity_attempt_unresolved","operation_not_prepared","participant_operation_unavailable","setup_operation_unavailable","messaging_operation_unavailable","participant_invocation_unavailable","request_cancelled"]);group("The original operation is prepared. Execute that same ID only within user authority; do not create a replacement.",["operation_not_started"]);group("Reuse the existing published identity and check readiness. Do not publish another identity.",["identity_already_published"]);group("Check retained wallet configuration and prerequisite availability. Keep original state; after an uncertain action, use its original operationId with status/reconcile.",["participant_startup_unavailable","participant_setup_unavailable","participant_close_unavailable","participant_prerequisite_unavailable","participant_prerequisite_invalid","identity_sponsor_unavailable","identity_prerequisite_changed"]);function participantDiagnostic(reason,fallback="participant_operation_unavailable"){const safeFallback=remedies.has(fallback)?fallback:"participant_operation_unavailable";const code=typeof reason==="string"&&remedies.has(reason)?reason:safeFallback;return{code,remedy:remedies.get(code)??remedies.get("participant_operation_unavailable")}}function participantErrorDiagnostic(error,fallback){const value=error&&typeof error==="object"?error:{};const filesystem={ENOENT:"participant_existing_wallet_required",EEXIST:"setup_existing_directory_unrecognized",EACCES:"local_intent_repository_open_failed",EPERM:"local_intent_repository_open_failed",ENOSPC:"local_intent_repository_open_failed"};const code=typeof value.code==="string"&&remedies.has(value.code)?value.code:typeof value.message==="string"&&remedies.has(value.message)?value.message:typeof value.code==="string"&&Object.hasOwn(filesystem,value.code)?filesystem[value.code]:value.name==="SyntaxError"||value.name==="ZodError"?"participant_configuration_invalid":undefined;return participantDiagnostic(code,fallback)}function outcomeDiagnostic(outcome){return outcome.kind==="blocked"||outcome.kind==="recovery_required"?{diagnostic:participantDiagnostic(outcome.reason)}:{}}function silenceParticipantConsole(){const methods=["log","info","warn","error","debug"];const originals=methods.map((method)=>console[method]);for(const method of methods)console[method]=()=>{};return()=>{methods.forEach((method,index)=>{console[method]=originals[index]})}}
|
|
3
|
+
export{diagnosticSchema,participantErrorDiagnostic,outcomeDiagnostic,silenceParticipantConsole};
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
import{__require}from"./chunk-btwmey1h.js";import{StdioServerTransport}from"@modelcontextprotocol/server/stdio";var
|
|
3
|
+
import{participantErrorDiagnostic,silenceParticipantConsole}from"./chunk-zfr69r1n.js";import{__require}from"./chunk-btwmey1h.js";import{StdioServerTransport}from"@modelcontextprotocol/server/stdio";var invocationUsage=`Tools: mapapp-participant tools --wallet-dir <existing-state> [--tool <name>]
|
|
4
|
+
Call: mapapp-participant call --wallet-dir <existing-state> --tool <name> [--arguments-file <utf8-json-file-or->]
|
|
5
|
+
Omit --arguments-file for {}. Use - to read JSON from stdin. Calls use the same MCP tools; retain original operation IDs after uncertainty.
|
|
6
|
+
`;var usage=`Usage: mapapp-participant --wallet-dir <existing-protected-wallet>
|
|
4
7
|
Setup: mapapp-participant setup --wallet-dir <new-protected-directory> --deployment <https-origin>
|
|
5
8
|
Restore: mapapp-participant restore --wallet-dir <new-protected-directory> --deployment <https-origin> --root-file <protected-wif-file> --backup-file <clean-wallet-zip> --connection-file <original-wallet-json-or-legacy-policy> --operations-file <closed-operation-db>
|
|
6
9
|
Connect: mapapp-participant connect --wallet-dir <new-connector-directory> --deployment <https-origin> --wallet-endpoint <trusted-provider-url> --identity-key <expected-public-key>
|
|
7
10
|
First setup/connect/restore: the final destination must not already exist, even empty. Keep the MCP host/client session open until awaited calls finish.
|
|
8
11
|
One local stdio MCP provides discovery, paid/sponsored/social actions and private messaging. No HTTP listener. Delegation belongs to the user and agent; connected wallets enforce their own permissions. Preserve original operation IDs after uncertainty. Read /developers?guide=agent-setup.
|
|
9
|
-
`;function readParticipantSetupCommand(args){if(!["setup","restore","connect"].includes(args[0]??""))return null;const fields={};const allowed=args[0]==="restore"?["--wallet-dir","--deployment","--root-file","--backup-file","--connection-file","--operations-file"]:args[0]==="connect"?["--wallet-dir","--deployment","--wallet-endpoint","--identity-key"]:["--wallet-dir","--deployment"];for(let i=1;i<args.length;i+=2){const key=args[i],value=args[i+1];if(!allowed.includes(key)||fields[key]||!value||value.startsWith("--"))throw new Error("participant_configuration_invalid");fields[key]=value}if(allowed.some((key)=>!fields[key]))throw new Error("participant_configuration_invalid");return{walletDirectory:fields["--wallet-dir"],deployment:fields["--deployment"],...args[0]==="connect"?{walletEndpoint:fields["--wallet-endpoint"],identityKey:fields["--identity-key"]}:{},...args[0]==="restore"?{restore:{rootFile:fields["--root-file"],backupFile:fields["--backup-file"],connectionFile:fields["--connection-file"],operationsFile:fields["--operations-file"]}}:{}}}function readParticipantMcpConfig(args){if(args.length===1&&["--help","-h"].includes(args[0]))return null;let walletDirectory;let connectionFile;const seen=new Set;for(let i=0;i<args.length;i++){const key=args[i];if(seen.has(key))throw new Error("participant_configuration_invalid");seen.add(key);const value=args[++i];if(!value||value.startsWith("--"))throw new Error("participant_configuration_invalid");if(key==="--wallet-dir")walletDirectory=value;else if(key==="--connection-file")connectionFile=value;else throw new Error("participant_configuration_invalid")}if(!walletDirectory)throw new Error("participant_configuration_invalid");return{walletDirectory,...connectionFile?{connectionFile}:{}}}if(import.meta.main){let
|
|
10
|
-
`)}};
|
|
11
|
-
`)}else if(!config)process.stderr.write(usage);else{const[{openAgentParticipantRuntime},{createMapAppParticipantServer,PARTICIPANT_MCP_MAX_MESSAGE_BYTES}]=await Promise.all([import("./chunk-
|
|
12
|
-
`)}process.
|
|
13
|
-
|
|
12
|
+
`;function readParticipantSetupCommand(args){if(!["setup","restore","connect"].includes(args[0]??""))return null;const fields={};const allowed=args[0]==="restore"?["--wallet-dir","--deployment","--root-file","--backup-file","--connection-file","--operations-file"]:args[0]==="connect"?["--wallet-dir","--deployment","--wallet-endpoint","--identity-key"]:["--wallet-dir","--deployment"];for(let i=1;i<args.length;i+=2){const key=args[i],value=args[i+1];if(!allowed.includes(key)||fields[key]||!value||value.startsWith("--"))throw new Error("participant_configuration_invalid");fields[key]=value}if(allowed.some((key)=>!fields[key]))throw new Error("participant_configuration_invalid");return{walletDirectory:fields["--wallet-dir"],deployment:fields["--deployment"],...args[0]==="connect"?{walletEndpoint:fields["--wallet-endpoint"],identityKey:fields["--identity-key"]}:{},...args[0]==="restore"?{restore:{rootFile:fields["--root-file"],backupFile:fields["--backup-file"],connectionFile:fields["--connection-file"],operationsFile:fields["--operations-file"]}}:{}}}function readParticipantMcpConfig(args){if(args.length===1&&["--help","-h"].includes(args[0]))return null;let walletDirectory;let connectionFile;const seen=new Set;for(let i=0;i<args.length;i++){const key=args[i];if(seen.has(key))throw new Error("participant_configuration_invalid");seen.add(key);const value=args[++i];if(!value||value.startsWith("--"))throw new Error("participant_configuration_invalid");if(key==="--wallet-dir")walletDirectory=value;else if(key==="--connection-file")connectionFile=value;else throw new Error("participant_configuration_invalid")}if(!walletDirectory)throw new Error("participant_configuration_invalid");return{walletDirectory,...connectionFile?{connectionFile}:{}}}if(import.meta.main){silenceParticipantConsole();let runtime;let participant;let closing;const setupMode=["setup","restore","connect"].includes(process.argv[2]??"");const invocationMode=["tools","call"].includes(process.argv[2]??"");const close=()=>closing??=(async()=>{try{await participant?.close()}finally{await runtime?.close()}})();const closeInvocation=async()=>{try{await close()}catch{process.stderr.write(JSON.stringify({error:participantErrorDiagnostic(null,"participant_close_unavailable")})+`
|
|
13
|
+
`);process.exitCode=1}};try{const args=process.argv.slice(2);const invocation=invocationMode?(await import("./chunk-2c4gc3ws.js")).readParticipantInvocation(args):null;const setup=readParticipantSetupCommand(args);const config=setup?null:readParticipantMcpConfig(invocation?.walletArgs??args);if(setup){const{setupParticipantWallet,connectParticipantWallet}=await import("./chunk-2z3hggm4.js");const outcome=setup.walletEndpoint&&setup.identityKey?await connectParticipantWallet({...setup,walletEndpoint:setup.walletEndpoint,identityKey:setup.identityKey}):await setupParticipantWallet(setup);process.stdout.write(JSON.stringify(outcome)+`
|
|
14
|
+
`)}else if(!config)process.stderr.write(usage+invocationUsage);else{const[{openAgentParticipantRuntime},{createMapAppParticipantServer,PARTICIPANT_MCP_MAX_MESSAGE_BYTES}]=await Promise.all([import("./chunk-b04ecsf5.js"),import("./chunk-1yn5h5zx.js")]);const invocationArgs=invocation?await(await import("./chunk-2c4gc3ws.js")).readInvocationArguments(invocation.argumentsFile,PARTICIPANT_MCP_MAX_MESSAGE_BYTES):undefined;runtime=await openAgentParticipantRuntime(config);participant=createMapAppParticipantServer(runtime);const stop=()=>{close().then(()=>process.exit(invocation?130:0),()=>{process.stderr.write(JSON.stringify({error:participantErrorDiagnostic(null,"participant_close_unavailable")})+`
|
|
15
|
+
`);process.exit(1)})};process.once("SIGINT",stop);process.once("SIGTERM",stop);if(invocation){try{const outcome=await(await import("./chunk-2c4gc3ws.js")).invokeParticipant(participant.server,invocation,invocationArgs);process.stdout.write(JSON.stringify(outcome)+`
|
|
16
|
+
`);process.exitCode="isError"in outcome&&outcome.isError?1:0}finally{await closeInvocation();process.off("SIGINT",stop);process.off("SIGTERM",stop)}}else{process.stdin.once("end",stop);await participant.server.connect(new StdioServerTransport(process.stdin,process.stdout,{maxBufferSize:PARTICIPANT_MCP_MAX_MESSAGE_BYTES}))}}}catch(error){if(invocationMode){process.stdout.write(JSON.stringify((await import("./chunk-2c4gc3ws.js")).invocationFailure(error))+`
|
|
17
|
+
`);await closeInvocation();process.exitCode=1}else{const diagnostic=participantErrorDiagnostic(error,setupMode?"participant_setup_unavailable":"participant_startup_unavailable");if(setupMode){process.stdout.write(JSON.stringify({state:"blocked",reason:diagnostic.code,diagnostic})+`
|
|
18
|
+
`)}process.stderr.write(JSON.stringify({error:diagnostic})+`
|
|
19
|
+
`);await closeInvocation();process.exitCode=1}}}export{readParticipantSetupCommand,readParticipantMcpConfig};
|
package/distribution.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "mapapp-agent-connector-distribution/v1",
|
|
3
3
|
"name": "@jdr377/mapapp-agent-connector",
|
|
4
|
-
"version": "0.1.0-pre.
|
|
4
|
+
"version": "0.1.0-pre.8",
|
|
5
5
|
"runtime": {
|
|
6
6
|
"bun": "1.3.11",
|
|
7
7
|
"requirement": ">=1.3.11 <2.0.0",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"sourceInputs": [
|
|
16
16
|
{
|
|
17
17
|
"path": "scripts/agent/participant-mcp-server.ts",
|
|
18
|
-
"sha256": "
|
|
18
|
+
"sha256": "f90ee70bc87c449c7f2861777343ef7e25e405c6b491d8e90196869e74f78de2"
|
|
19
19
|
},
|
|
20
20
|
{
|
|
21
21
|
"path": "scripts/lib/agentLocalIntentRepository.ts",
|
|
@@ -51,19 +51,35 @@
|
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
"path": "server/agent/discoveryHttp.ts",
|
|
54
|
-
"sha256": "
|
|
54
|
+
"sha256": "03a3b2ac68277fa4eacab31d654e6bec87c5df78b1297a96401e5cbe10fd2847"
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
57
|
"path": "server/agent/discoveryTools.ts",
|
|
58
|
-
"sha256": "
|
|
58
|
+
"sha256": "b3fae480511d757373604d3564c56da3368aa10ae0afd7ed8478866ac215b920"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"path": "server/agent/geohashTool.ts",
|
|
62
|
+
"sha256": "8dee69324f8aeef915d68dcd6e7981fa9eaf223f1cf8ddecaab959d275636784"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"path": "server/agent/mcp/diagnostics.ts",
|
|
66
|
+
"sha256": "b3f3087c7c8527e8d12a01d7574fc8d53de2fc816582ddd03f6a80b57e499230"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"path": "server/agent/mcp/invoke.ts",
|
|
70
|
+
"sha256": "a2b09c7cd359413fd940368456fe86699458dae1efeafc14e8b5b8eb5c8c5ada"
|
|
59
71
|
},
|
|
60
72
|
{
|
|
61
73
|
"path": "server/agent/mcp/participant.ts",
|
|
62
|
-
"sha256": "
|
|
74
|
+
"sha256": "da3cfd2df8ab33bf45d036150e0b4f8c2ca657059881de9c9f8ea4b2cde36833"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"path": "server/agent/mcp/publication.ts",
|
|
78
|
+
"sha256": "2f8fcd0c7414369e883079859ff943c212d8476e0d2d0194393bbc5afd608720"
|
|
63
79
|
},
|
|
64
80
|
{
|
|
65
81
|
"path": "server/agent/onboarding.ts",
|
|
66
|
-
"sha256": "
|
|
82
|
+
"sha256": "aeb1bef612a634e0066a45680a26dd84f4c1a77da6d28cd9c737b1db05e05af4"
|
|
67
83
|
},
|
|
68
84
|
{
|
|
69
85
|
"path": "server/agent/parser.ts",
|
|
@@ -79,7 +95,11 @@
|
|
|
79
95
|
},
|
|
80
96
|
{
|
|
81
97
|
"path": "shared/freeposting/u12.ts",
|
|
82
|
-
"sha256": "
|
|
98
|
+
"sha256": "98dd20f08f4e7589b3483ad07a496cfe13b3baad9192d3889cc9421305e7a488"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"path": "shared/geohash.ts",
|
|
102
|
+
"sha256": "db35db3427cb3a8fac5b156e9458207d08b9ac5eb0cab0d8dc7183db9eb33254"
|
|
83
103
|
},
|
|
84
104
|
{
|
|
85
105
|
"path": "shared/mediaLimits.ts",
|
|
@@ -111,7 +131,7 @@
|
|
|
111
131
|
},
|
|
112
132
|
{
|
|
113
133
|
"path": "src/bitcoin/agentIdentity.ts",
|
|
114
|
-
"sha256": "
|
|
134
|
+
"sha256": "a511dc04a674b0d68b8eed5c4e21fa91400d328a3f06330cc662799bf9a5c037"
|
|
115
135
|
},
|
|
116
136
|
{
|
|
117
137
|
"path": "src/bitcoin/agentMedia.ts",
|
|
@@ -123,7 +143,7 @@
|
|
|
123
143
|
},
|
|
124
144
|
{
|
|
125
145
|
"path": "src/bitcoin/agentPaidPost.ts",
|
|
126
|
-
"sha256": "
|
|
146
|
+
"sha256": "a663f3d60c564d4b3b64e73b94e609d1d1ff58bf9c4357310e69e3c270fbe932"
|
|
127
147
|
},
|
|
128
148
|
{
|
|
129
149
|
"path": "src/bitcoin/agentParticipantBinding.ts",
|
|
@@ -223,18 +243,20 @@
|
|
|
223
243
|
}
|
|
224
244
|
],
|
|
225
245
|
"files": {
|
|
226
|
-
"README.md": "
|
|
227
|
-
"bun.lock": "
|
|
228
|
-
"dist/chunk-
|
|
229
|
-
"dist/chunk-
|
|
230
|
-
"dist/chunk-
|
|
231
|
-
"dist/chunk-
|
|
232
|
-
"dist/chunk-
|
|
246
|
+
"README.md": "fac0a469368ed3bf597f35fd01ca157a731344ca2bdd418dc61dab3161c209f4",
|
|
247
|
+
"bun.lock": "70b49fe644812578e2c365f4600fa57b694710f16a8095dc05e4dbc257b3c58a",
|
|
248
|
+
"dist/chunk-1qfba14s.js": "ee2c33a502379fde2d7e9a72329b731f55957f5cb34c52340ad722251dd99ef1",
|
|
249
|
+
"dist/chunk-1yn5h5zx.js": "612416156d2647c4e21f1b320eb348ce624b933e130e582ff72c168547750c81",
|
|
250
|
+
"dist/chunk-2c4gc3ws.js": "835c82f9f8a0a9a0f7763628390ddcaf307620fa5d42af6885abc58572b05965",
|
|
251
|
+
"dist/chunk-2z3hggm4.js": "808b1d6a4378c6a0be0817df098de278c77a35556ef3b317159ee2d8ae75085e",
|
|
252
|
+
"dist/chunk-576jrq3v.js": "d9feca2aaf0e3dc49bee60f611782d5b91cfd2fbf37da962289ef6502352b97c",
|
|
253
|
+
"dist/chunk-b04ecsf5.js": "79fd5a5561a9d7910f1588768c8e6a079d24099c3ed38906b7fc3970fda181e7",
|
|
233
254
|
"dist/chunk-btwmey1h.js": "4e3cec1f9adaea9464cd99ea40ea0b7a693d800040e59540856f6c2b8ff013ee",
|
|
234
255
|
"dist/chunk-c74qq5ek.js": "36c949a5d21a3a2ac2c0e7a1020ebc995f1b665194ea43e8e29244eb8e166257",
|
|
235
256
|
"dist/chunk-e6y2yzbj.js": "4be64909a0536718a794f3d7bd11c4b5af95097ca7295c05cde1394a80027b38",
|
|
236
|
-
"dist/
|
|
237
|
-
"
|
|
257
|
+
"dist/chunk-zfr69r1n.js": "86b03e172324c14a302c765d6e47476f4cf029767ce1c508cbda246e39a12d0f",
|
|
258
|
+
"dist/participant-mcp-server.js": "0f5d892874b026018688f79f036e1e805bf453c73857f2f98d585da3e68cfcc6",
|
|
259
|
+
"package.json": "df4ffb932bfa9412e34ae183b35b54605a7a047df244af04ee569c4396702559"
|
|
238
260
|
},
|
|
239
261
|
"dependencies": {
|
|
240
262
|
"@1sat/actions": "0.0.224",
|
|
@@ -249,6 +271,7 @@
|
|
|
249
271
|
"@bsv/wallet-toolbox-client": "npm:@bopen-io/wallet-toolbox-client@2.6.2-brc153.5",
|
|
250
272
|
"@jdr377/message-box-store": "0.1.0-beta.0",
|
|
251
273
|
"@jsquash/webp": "1.5.0",
|
|
274
|
+
"@modelcontextprotocol/client": "2.3.1",
|
|
252
275
|
"@modelcontextprotocol/server": "2.3.1",
|
|
253
276
|
"mediabunny": "1.52.3",
|
|
254
277
|
"zod": "4.6.5"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jdr377/mapapp-agent-connector",
|
|
3
|
-
"version": "0.1.0-pre.
|
|
3
|
+
"version": "0.1.0-pre.8",
|
|
4
4
|
"description": "Local MCP for MapApp discovery, participant wallet actions and private messaging",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"@bsv/wallet-toolbox-client": "npm:@bopen-io/wallet-toolbox-client@2.6.2-brc153.5",
|
|
31
31
|
"@jdr377/message-box-store": "0.1.0-beta.0",
|
|
32
32
|
"@jsquash/webp": "1.5.0",
|
|
33
|
+
"@modelcontextprotocol/client": "2.3.1",
|
|
33
34
|
"@modelcontextprotocol/server": "2.3.1",
|
|
34
35
|
"mediabunny": "1.52.3",
|
|
35
36
|
"zod": "4.6.5"
|
package/dist/chunk-4tt14q1n.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{__require}from"./chunk-btwmey1h.js";var MEDIA_RELAY_SAFE_MAX_BYTES=99*1024;function readWebpDimensions(bytes){if(bytes.length<20||text4(bytes,0)!=="RIFF"||text4(bytes,8)!=="WEBP"||u32(bytes,4)+8!==bytes.length)return null;let offset=12;let extended=null;let image=null;while(offset<bytes.length){if(offset+8>bytes.length)return null;const kind=text4(bytes,offset);const length=u32(bytes,offset+4);const payload=offset+8;const end=payload+length;const paddedEnd=end+(length&1);if(end>bytes.length||paddedEnd>bytes.length)return null;if(!extended&&kind==="VP8X"){if(length!==10)return null;extended={width:1+u24(bytes,payload+4),height:1+u24(bytes,payload+7)}}else if(!image&&kind==="VP8 "){if(length<10||bytes[payload+3]!==157||bytes[payload+4]!==1||bytes[payload+5]!==42)return null;image={width:(bytes[payload+6]|bytes[payload+7]<<8)&16383,height:(bytes[payload+8]|bytes[payload+9]<<8)&16383}}else if(!image&&kind==="VP8L"){if(length<5||bytes[payload]!==47)return null;const bits=u32(bytes,payload+1);image={width:1+(bits&16383),height:1+(bits>>>14&16383)}}offset=paddedEnd}if(offset!==bytes.length||!image)return null;if(extended&&(extended.width!==image.width||extended.height!==image.height))return null;return extended??image}function text4(bytes,offset){return String.fromCharCode(...bytes.slice(offset,offset+4))}function u24(bytes,offset){return bytes[offset]|bytes[offset+1]<<8|bytes[offset+2]<<16}function u32(bytes,offset){return(bytes[offset]|bytes[offset+1]<<8|bytes[offset+2]<<16|bytes[offset+3]<<24)>>>0}var AGENT_MEDIA_MAX_BASE64_LENGTH=4*Math.ceil(MEDIA_RELAY_SAFE_MAX_BYTES/3);class AgentMediaError extends Error{code;constructor(code){super(code);this.code=code}}function fail(code){throw new AgentMediaError(code)}function validAgentMediaInput(value){if(!value||typeof value!=="object"||Array.isArray(value))return false;const media=value;return Object.keys(media).length===4&&Object.keys(media).every((key)=>["contentType","base64","byteSize","sha256"].includes(key))&&["image/webp","video/webm"].includes(media.contentType)&&typeof media.base64==="string"&&media.base64.length>0&&media.base64.length<=AGENT_MEDIA_MAX_BASE64_LENGTH&&media.base64.length%4===0&&/^[A-Za-z0-9+/]*={0,2}$/.test(media.base64)&&Number.isSafeInteger(media.byteSize)&&media.byteSize>0&&media.byteSize<=MEDIA_RELAY_SAFE_MAX_BYTES&&typeof media.sha256==="string"&&/^[0-9a-f]{64}$/.test(media.sha256)}async function inspectAgentMedia(value){if(!validAgentMediaInput(value))fail("invalid_media_input");const binary=atob(value.base64);if(btoa(binary)!==value.base64)fail("invalid_media_base64");const bytes=Uint8Array.from(binary,(character)=>character.charCodeAt(0));if(bytes.length!==value.byteSize)fail("media_size_mismatch");const hash=new Uint8Array(await crypto.subtle.digest("SHA-256",bytes.buffer));const sha256=Array.from(hash,(byte)=>byte.toString(16).padStart(2,"0")).join("");if(sha256!==value.sha256)fail("media_hash_mismatch");const dimensions=value.contentType==="image/webp"?await inspectImage(bytes):await inspectVideo(bytes);return{media:value.contentType==="image/webp"?{kind:"image",contentType:"image/webp",bytes}:{kind:"video",contentType:"video/webm",bytes},summary:{contentType:value.contentType,byteSize:bytes.length,sha256,...dimensions}}}async function inspectImage(bytes){const dimensions=readWebpDimensions(bytes);if(!dimensions)fail("invalid_media_container");if(dimensions.width<1||dimensions.height<1||dimensions.width>1024||dimensions.height>1024)fail("media_dimensions_too_large");try{const{default:decode}=await import("@jsquash/webp/decode.js");const decoded=await decode(Uint8Array.from(bytes).buffer);if(decoded.width!==dimensions.width||decoded.height!==dimensions.height)fail("invalid_media_container");return dimensions}catch{return fail("invalid_media_container")}}async function inspectVideo(bytes){const{Input,BufferSource,WEBM}=await import("mediabunny");const input=new Input({source:new BufferSource(bytes),formats:[WEBM]});let timeout;try{return await Promise.race([(async()=>{const[videos,audios,tracks]=await Promise.all([input.getVideoTracks(),input.getAudioTracks(),input.getTracks()]);if(videos.length!==1||audios.length>1||tracks.length!==videos.length+audios.length)fail("media_tracks_unsupported");const track=videos[0];const[codec,width,height,displayWidth,displayHeight,duration,stats]=await Promise.all([track.getCodec(),track.getCodedWidth(),track.getCodedHeight(),track.getDisplayWidth(),track.getDisplayHeight(),input.computeDuration(),track.computePacketStats(1)]);if(codec!=="vp8"&&codec!=="vp9")fail("media_codec_unsupported");if([width,height,displayWidth,displayHeight].some((size)=>!Number.isFinite(size)||size<1||size>512))fail("media_dimensions_too_large");if(!Number.isFinite(duration)||duration<=0||duration>30)fail("media_video_duration_invalid");if(stats.packetCount<1)fail("invalid_media_container");if(audios[0]&&!["opus","vorbis"].includes(await audios[0].getCodec()??""))fail("media_codec_unsupported");return{width,height,durationMs:Math.ceil(duration*1000)}})(),new Promise((_,reject)=>{timeout=setTimeout(()=>{input.dispose();reject(new AgentMediaError("media_inspection_timeout"))},5000)})])}catch(error){if(error instanceof AgentMediaError)throw error;return fail("invalid_media_container")}finally{clearTimeout(timeout);input.dispose()}}var MAPAPP_CATEGORY_TOKENS=["\uD83C\uDF31","\uD83D\uDCCD","\uD83E\uDDED","\uD83C\uDFA8","\uD83C\uDFB5","\uD83C\uDF7D\uFE0F","\u2615","\uD83D\uDED2","\uD83C\uDFC0","\uD83C\uDFAE","\uD83D\uDCF0","\uD83D\uDCAC","\uD83D\uDCF8","\uD83C\uDFAC","\uD83D\uDCBB","\uD83D\uDEE0\uFE0F","\uD83C\uDFE0","\uD83D\uDE97","\uD83C\uDF0A","\u26F0\uFE0F","\uD83C\uDF33","\uD83D\uDC3E","\uD83C\uDF93","\uD83C\uDFE5","\u26A0\uFE0F","\uD83C\uDF89","\uD83D\uDCBC","\uD83D\uDD2C","\u2708\uFE0F","\uD83E\uDDD8","\uD83E\uDE99","\u2764\uFE0F"];var DEFAULT_MAPAPP_CATEGORY=MAPAPP_CATEGORY_TOKENS[0];import{Hash,Utils}from"@bsv/sdk";var MESSAGING_IDENTITY_VERSION="mapapp-messaging-identity-v1";var MESSAGING_IDENTITY_MUTATION_VERSION="mapapp-messaging-identity-mutation-v1";var MAPAPP_MESSAGE_VERSION="mapapp-message-v1";var MAPAPP_MESSAGE_BOX_NAME="mapapp-messaging-v1";var MESSAGEBOX_PROTOCOL=[1,"messagebox"];var MESSAGEBOX_KEY_ID="1";var DEFAULT_MESSAGE_PLAINTEXT_MAX_BYTES=8*1024;var MAPAPP_MESSAGE_ID_MAX_BYTES=256;function serializeMessagingIdentityMutationV1(input){const mutation=assertMessagingIdentityMutationV1(input);return new TextEncoder().encode(JSON.stringify({version:mutation.version,operation:mutation.operation,bapId:mutation.bapId,walletIdentityKey:mutation.walletIdentityKey,messageBoxHost:mutation.messageBoxHost,deployment:mutation.deployment,canonicalOrigin:mutation.canonicalOrigin,network:mutation.network,expectedProfileOutpoint:mutation.expectedProfileOutpoint,expectedEvidenceHash:mutation.expectedEvidenceHash,acceptedSequence:mutation.acceptedSequence,projectionVersion:mutation.projectionVersion,clientOperationId:mutation.clientOperationId}))}function serializeMapAppMessageV1(input,maxPlaintextBytes=DEFAULT_MESSAGE_PLAINTEXT_MAX_BYTES){const message=assertMapAppMessageV1(input,maxPlaintextBytes);return JSON.stringify({version:message.version,messageId:message.messageId,senderIdentityKey:message.senderIdentityKey,recipientIdentityKey:message.recipientIdentityKey,conversationId:message.conversationId,sentAt:message.sentAt,text:message.text})}function conversationIdForIdentityKeys(first,second){assertCompressedIdentityKey(first,"first identity key");assertCompressedIdentityKey(second,"second identity key");if(first.toLowerCase()===second.toLowerCase())throw new TypeError("Self-messaging is not allowed.");const[left,right]=[first.toLowerCase(),second.toLowerCase()].sort();return Utils.toHex(Hash.sha256(Array.from(new TextEncoder().encode(`mapapp-messaging/conversation/v1\\0${left}\\0${right}`))))}function assertMapAppMessageV1(value,maxPlaintextBytes=DEFAULT_MESSAGE_PLAINTEXT_MAX_BYTES){const record=strictRecord(value,["version","messageId","senderIdentityKey","recipientIdentityKey","conversationId","sentAt","text"],"MapAppMessageV1");if(record.version!==MAPAPP_MESSAGE_VERSION)throw new TypeError("Unsupported MapApp message version.");const messageId=stringField(record,"messageId");if(messageId.trim()===""||new TextEncoder().encode(messageId).byteLength>MAPAPP_MESSAGE_ID_MAX_BYTES)throw new TypeError("messageId must be a bounded non-empty string.");assertCanonicalIsoTimestamp(stringField(record,"sentAt"),"sentAt");const senderIdentityKey=stringField(record,"senderIdentityKey");const recipientIdentityKey=stringField(record,"recipientIdentityKey");assertCompressedIdentityKey(senderIdentityKey,"sender identity key");assertCompressedIdentityKey(recipientIdentityKey,"recipient identity key");if(senderIdentityKey.toLowerCase()===recipientIdentityKey.toLowerCase())throw new TypeError("Self-messaging is not allowed.");const expectedConversationId=conversationIdForIdentityKeys(senderIdentityKey,recipientIdentityKey);if(stringField(record,"conversationId")!==expectedConversationId)throw new TypeError("Message conversation ID does not match its participants.");if(!Number.isSafeInteger(maxPlaintextBytes)||maxPlaintextBytes<=0)throw new TypeError("Plaintext maximum must be a positive safe integer.");const text=stringField(record,"text");if(text.trim()==="")throw new TypeError("Message text must not be blank.");if(new TextEncoder().encode(text).byteLength>maxPlaintextBytes)throw new RangeError("Message text exceeds the plaintext maximum.");return record}function assertMessagingIdentityMutationV1(value){const record=strictRecord(value,["version","operation","bapId","walletIdentityKey","messageBoxHost","deployment","canonicalOrigin","network","expectedProfileOutpoint","expectedEvidenceHash","acceptedSequence","projectionVersion","clientOperationId"],"MessagingIdentityMutationV1");if(record.version!==MESSAGING_IDENTITY_MUTATION_VERSION)throw new TypeError("Unsupported messaging identity mutation version.");if(record.operation!=="register"&&record.operation!=="rotate"&&record.operation!=="revoke")throw new TypeError("Unsupported messaging identity operation.");for(const key of["bapId","messageBoxHost","deployment","canonicalOrigin","clientOperationId"])assertNonEmptyString(record[key],key);assertCompressedIdentityKey(stringField(record,"walletIdentityKey"),"wallet identity key");if(record.network!=="mainnet"&&record.network!=="testnet")throw new TypeError("Unsupported messaging network.");assertProfileEvidenceGroup(record);assertHttpsUrl(stringField(record,"messageBoxHost"),"messageBoxHost");assertHttpsUrl(stringField(record,"canonicalOrigin"),"canonicalOrigin");return record}function assertMessagingIdentityV1(value){const record=strictRecord(value,["version","bapId","walletIdentityKey","messageBoxHost","deployment","canonicalOrigin","network","expectedProfileOutpoint","expectedEvidenceHash","acceptedSequence","projectionVersion"],"MessagingIdentityV1");if(record.version!==MESSAGING_IDENTITY_VERSION)throw new TypeError("Unsupported messaging identity version.");for(const key of["bapId","messageBoxHost","deployment","canonicalOrigin"])assertNonEmptyString(record[key],key);assertCompressedIdentityKey(stringField(record,"walletIdentityKey"),"wallet identity key");if(record.network!=="mainnet"&&record.network!=="testnet")throw new TypeError("Unsupported messaging network.");assertProfileEvidenceGroup(record);assertHttpsUrl(stringField(record,"messageBoxHost"),"messageBoxHost");assertHttpsUrl(stringField(record,"canonicalOrigin"),"canonicalOrigin");return record}function assertCompressedIdentityKey(value,field="identity key"){if(!/^(02|03)[0-9a-fA-F]{64}$/.test(value))throw new TypeError(`${field} must be a compressed public key.`)}function strictRecord(value,keys,name){if(!value||typeof value!=="object"||Array.isArray(value))throw new TypeError(`${name} must be an object.`);const record=value;if(Object.keys(record).length!==keys.length||keys.some((key)=>!(key in record)))throw new TypeError(`${name} has unsupported or missing fields.`);return record}function stringField(record,key){const value=record[key];if(typeof value!=="string")throw new TypeError(`${key} must be a string.`);return value}function numberField(record,key){const value=record[key];if(typeof value!=="number"||!Number.isSafeInteger(value))throw new TypeError(`${key} must be a non-negative safe integer.`);return value}function assertProfileEvidenceGroup(record){const fields=[record.expectedProfileOutpoint,record.expectedEvidenceHash,record.acceptedSequence,record.projectionVersion];if(fields.every((value)=>value===null))return;if(fields.some((value)=>value===null))throw new TypeError("Profile evidence must be entirely present or absent.");assertNonEmptyString(record.expectedProfileOutpoint,"expectedProfileOutpoint");assertNonEmptyString(record.expectedEvidenceHash,"expectedEvidenceHash");if(numberField(record,"acceptedSequence")<1)throw new TypeError("acceptedSequence must be positive.");if(numberField(record,"projectionVersion")<0)throw new TypeError("projectionVersion must be non-negative.")}function assertNonEmptyString(value,field){if(typeof value!=="string"||value.trim()==="")throw new TypeError(`${field} must be a non-empty string.`)}function assertHttpsUrl(value,field){try{const parsed=new URL(String(value));if(parsed.protocol!=="https:"||parsed.username||parsed.password||parsed.pathname!=="/"||parsed.search||parsed.hash)throw new Error}catch{throw new TypeError(`${field} must be an HTTPS origin without a path.`)}}function assertCanonicalIsoTimestamp(value,field="timestamp"){if(!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(value)||!Number.isFinite(Date.parse(value))||new Date(value).toISOString()!==value)throw new TypeError(`${field} must be a canonical ISO-8601 UTC timestamp.`)}
|
|
3
|
-
export{MEDIA_RELAY_SAFE_MAX_BYTES,AGENT_MEDIA_MAX_BASE64_LENGTH,AgentMediaError,validAgentMediaInput,inspectAgentMedia,MAPAPP_CATEGORY_TOKENS,MESSAGING_IDENTITY_MUTATION_VERSION,MAPAPP_MESSAGE_VERSION,MAPAPP_MESSAGE_BOX_NAME,MESSAGEBOX_PROTOCOL,MESSAGEBOX_KEY_ID,DEFAULT_MESSAGE_PLAINTEXT_MAX_BYTES,MAPAPP_MESSAGE_ID_MAX_BYTES,serializeMessagingIdentityMutationV1,serializeMapAppMessageV1,conversationIdForIdentityKeys,assertMapAppMessageV1,assertMessagingIdentityV1,assertCompressedIdentityKey,assertCanonicalIsoTimestamp};
|