Skip to content
This repository was archived by the owner on Jul 21, 2025. It is now read-only.

Commit 84bb558

Browse files
committed
refactor: improve base executor and encryption handling, standardize tag constants and method enums across codebase
1 parent dace328 commit 84bb558

14 files changed

Lines changed: 127 additions & 119 deletions

File tree

packages/dvmcp-bridge/src/announcer.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
TAG_KIND,
1313
TAG_SERVER_IDENTIFIER,
1414
TAG_SUPPORT_ENCRYPTION,
15+
TAG_EVENT_ID,
16+
TAG_CAPABILITY,
1517
} from '@dvmcp/commons/core';
1618
import type { Event } from 'nostr-tools/pure';
1719
import { loggerBridge } from '@dvmcp/commons/core';
@@ -120,7 +122,12 @@ export class NostrAnnouncer {
120122
for (const tool of toolsResult.tools) {
121123
const pricing = this.mcpPool.getToolPricing(tool.name);
122124
if (pricing?.price) {
123-
tags.push(['cap', tool.name, pricing.price, pricing.unit || 'sats']);
125+
tags.push([
126+
TAG_CAPABILITY,
127+
tool.name,
128+
pricing.price,
129+
pricing.unit || 'sats',
130+
]);
124131
}
125132
}
126133
}
@@ -148,7 +155,7 @@ export class NostrAnnouncer {
148155
const pricing = this.mcpPool.getResourcePricing(resource.uri);
149156
if (pricing?.price) {
150157
tags.push([
151-
'cap',
158+
TAG_CAPABILITY,
152159
resource.uri,
153160
pricing.price,
154161
pricing.unit || 'sats',
@@ -189,7 +196,7 @@ export class NostrAnnouncer {
189196
// Add capability tags for each resource template name
190197
for (const template of resourceTemplatesResult.resourceTemplates) {
191198
if (template.name) {
192-
tags.push(['cap', template.name]);
199+
tags.push([TAG_CAPABILITY, template.name]);
193200
}
194201
}
195202

@@ -218,7 +225,7 @@ export class NostrAnnouncer {
218225
const pricing = this.mcpPool.getPromptPricing(prompt.name);
219226
if (pricing?.price) {
220227
tags.push([
221-
'cap',
228+
TAG_CAPABILITY,
222229
prompt.name,
223230
pricing.price,
224231
pricing.unit || 'sats',
@@ -341,7 +348,7 @@ export class NostrAnnouncer {
341348
...this.keyManager.createEventTemplate(5),
342349
content: reason,
343350
tags: [
344-
...events.map((ev) => ['e', ev.id]),
351+
...events.map((ev) => [TAG_EVENT_ID, ev.id]),
345352
[TAG_UNIQUE_IDENTIFIER, this.serverId],
346353
],
347354
});

packages/dvmcp-bridge/src/dvm-bridge.ts

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ import {
1313
TAG_EVENT_ID,
1414
TAG_STATUS,
1515
TAG_SERVER_IDENTIFIER,
16+
MCPMETHODS,
1617
} from '@dvmcp/commons/core';
1718
import { loggerBridge } from '@dvmcp/commons/core';
18-
import { type NostrEvent, type EventTemplate, getEventHash } from 'nostr-tools';
19+
import { type NostrEvent, getEventHash } from 'nostr-tools';
1920
import { getServerId } from './utils';
20-
import { EncryptionManager } from '@dvmcp/commons/encryption';
21+
import { EncryptionManager, EncryptionMode } from '@dvmcp/commons/encryption';
2122
import { EventPublisher } from '@dvmcp/commons/nostr';
2223

2324
import { handleToolsList, handleToolsCall } from './handlers/tool-handlers';
@@ -203,7 +204,7 @@ export class DVMBridge {
203204
private async decryptEventAndExtractSender(
204205
giftWrapEvent: NostrEvent
205206
): Promise<{
206-
eventTemplate: EventTemplate;
207+
eventTemplate: NostrEvent;
207208
realSenderPubkey: string;
208209
} | null> {
209210
try {
@@ -221,15 +222,8 @@ export class DVMBridge {
221222
return null;
222223
}
223224

224-
const eventTemplate: EventTemplate = {
225-
kind: decryptionResult.decryptedEvent.kind,
226-
content: decryptionResult.decryptedEvent.content,
227-
tags: decryptionResult.decryptedEvent.tags,
228-
created_at: decryptionResult.decryptedEvent.created_at,
229-
};
230-
231225
return {
232-
eventTemplate,
226+
eventTemplate: decryptionResult.decryptedEvent,
233227
realSenderPubkey: decryptionResult.sender,
234228
};
235229
} catch (error) {
@@ -281,7 +275,9 @@ export class DVMBridge {
281275
}
282276

283277
// Handle regular unencrypted events
284-
await this.processRegularRequest(event);
278+
if (this.config.encryption?.mode !== EncryptionMode.REQUIRED) {
279+
await this.processRegularRequest(event);
280+
}
285281
} catch (error) {
286282
console.error('Error handling request:', error);
287283
}
@@ -392,17 +388,17 @@ export class DVMBridge {
392388
};
393389

394390
switch (method) {
395-
case 'initialize':
391+
case MCPMETHODS.initialize:
396392
break;
397-
case 'ping':
393+
case MCPMETHODS.ping:
398394
await handlePing(
399395
event,
400396
this.keyManager,
401397
this.relayHandler,
402398
responseContext
403399
);
404400
break;
405-
case 'tools/list':
401+
case MCPMETHODS.toolsList:
406402
await handleToolsList(
407403
event,
408404
this.mcpPool,
@@ -411,7 +407,7 @@ export class DVMBridge {
411407
responseContext
412408
);
413409
break;
414-
case 'tools/call':
410+
case MCPMETHODS.toolsCall:
415411
await handleToolsCall(
416412
event,
417413
this.mcpPool,
@@ -421,7 +417,7 @@ export class DVMBridge {
421417
responseContext
422418
);
423419
break;
424-
case 'resources/list':
420+
case MCPMETHODS.resourcesList:
425421
await handleResourcesList(
426422
event,
427423
this.mcpPool,
@@ -430,7 +426,7 @@ export class DVMBridge {
430426
responseContext
431427
);
432428
break;
433-
case 'resources/read':
429+
case MCPMETHODS.resourcesRead:
434430
await handleResourcesRead(
435431
event,
436432
this.mcpPool,
@@ -440,7 +436,7 @@ export class DVMBridge {
440436
responseContext
441437
);
442438
break;
443-
case 'resources/templates/list':
439+
case MCPMETHODS.resourcesTemplatesList:
444440
await handleResourceTemplatesList(
445441
event,
446442
this.mcpPool,
@@ -449,7 +445,7 @@ export class DVMBridge {
449445
responseContext
450446
);
451447
break;
452-
case 'prompts/list':
448+
case MCPMETHODS.promptsList:
453449
await handlePromptsList(
454450
event,
455451
this.mcpPool,
@@ -458,7 +454,7 @@ export class DVMBridge {
458454
responseContext
459455
);
460456
break;
461-
case 'prompts/get':
457+
case MCPMETHODS.promptsGet:
462458
await handlePromptsGet(
463459
event,
464460
this.mcpPool,
@@ -467,7 +463,7 @@ export class DVMBridge {
467463
responseContext
468464
);
469465
break;
470-
case 'completion/complete':
466+
case MCPMETHODS.completionComplete:
471467
await handleCompletionComplete(
472468
event,
473469
this.mcpPool,
@@ -494,7 +490,7 @@ export class DVMBridge {
494490
await this.publishResponse(notImpl, responseContext);
495491
}
496492
} else if (kind === NOTIFICATION_KIND) {
497-
if (method === 'notifications/cancel') {
493+
if (method === MCPMETHODS.notificationsCancel) {
498494
const shouldEncryptResponse =
499495
this.encryptionManager?.shouldEncryptResponse(isEncrypted) || false;
500496

packages/dvmcp-bridge/src/handlers/notification-handlers.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { loggerBridge } from '@dvmcp/commons/core';
1+
import { loggerBridge, MCPMETHODS } from '@dvmcp/commons/core';
22
import {
33
TAG_EVENT_ID,
44
TAG_PUBKEY,
@@ -37,15 +37,15 @@ export async function handleNotificationsCancel(
3737

3838
await eventPublisher.publishNotification(
3939
JSON.stringify({
40-
method: 'notifications/progress',
40+
method: MCPMETHODS.notificationsProgress,
4141
params: { message: 'cancellation-acknowledged' },
4242
}),
4343
pubkey,
4444
[
4545
[TAG_STATUS, 'cancelled'],
4646
[TAG_EVENT_ID, eventIdToCancel],
4747
[TAG_PUBKEY, pubkey],
48-
[TAG_METHOD, 'notifications/progress'],
48+
[TAG_METHOD, MCPMETHODS.notificationsProgress],
4949
],
5050
responseContext?.shouldEncrypt || false
5151
);

packages/dvmcp-bridge/src/handlers/payment-handler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { loggerBridge } from '@dvmcp/commons/core';
1+
import { loggerBridge, TAG_INVOICE } from '@dvmcp/commons/core';
22
import {
33
TAG_AMOUNT,
44
TAG_EVENT_ID,
@@ -65,7 +65,7 @@ export async function handlePaymentFlow(
6565
[
6666
[TAG_STATUS, 'payment-required'],
6767
[TAG_AMOUNT, price, unit],
68-
['invoice', zapRequest.paymentRequest],
68+
[TAG_INVOICE, zapRequest.paymentRequest],
6969
[TAG_EVENT_ID, eventId],
7070
[TAG_PUBKEY, pubkey],
7171
],

packages/dvmcp-bridge/src/handlers/payment-processor.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { loggerBridge } from '@dvmcp/commons/core';
1+
import { loggerBridge, MCPMETHODS } from '@dvmcp/commons/core';
22
import type { DvmcpBridgeConfig, MCPPricingConfig } from '../config-schema.js';
33
import type { KeyManager } from '@dvmcp/commons/nostr'; // KeyManager might still be needed for handlePaymentFlow
44
import type { RelayHandler } from '@dvmcp/commons/nostr'; // RelayHandler might still be needed for handlePaymentFlow
@@ -51,14 +51,14 @@ export class PaymentProcessor {
5151

5252
await this.notificationPublisher.publishNotification(
5353
JSON.stringify({
54-
method: 'notifications/progress',
54+
method: MCPMETHODS.notificationsProgress,
5555
params: { message: 'processing payment' },
5656
}),
5757
pubkey,
5858
[
5959
[TAG_PUBKEY, pubkey],
6060
[TAG_EVENT_ID, eventId],
61-
[TAG_METHOD, 'notifications/progress'],
61+
[TAG_METHOD, MCPMETHODS.notificationsProgress],
6262
],
6363
shouldEncrypt
6464
);

packages/dvmcp-commons/src/core/constants.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,16 @@ export const TAG_AMOUNT = 'amount'; // Nostr-specific notification amount/invoic
2525
export const TAG_INVOICE = 'invoice'; // Nostr-specific notification invoice
2626
export const TAG_SUPPORT_ENCRYPTION = 'support_encryption';
2727
export const MCPMETHODS = {
28+
initialize: 'initialize',
2829
toolsList: 'tools/list',
2930
toolsCall: 'tools/call',
3031
resourcesList: 'resources/list',
32+
resourcesTemplatesList: 'resources/templates/list',
3133
resourcesRead: 'resources/read',
3234
promptsList: 'prompts/list',
33-
promptsCall: 'prompts/call',
35+
promptsGet: 'prompts/get',
36+
completionComplete: 'completion/complete',
37+
ping: 'ping',
38+
notificationsCancel: 'notifications/cancel',
39+
notificationsProgress: 'notifications/progress',
3440
} as const;

packages/dvmcp-commons/src/encryption/encryption-manager.test.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ describe('EncryptionManager', () => {
1212
expect(manager.getEncryptionMode()).toBe(EncryptionMode.REQUIRED);
1313
expect(manager.isEncryptionRequired()).toBe(true);
1414
expect(manager.shouldAttemptEncryption()).toBe(true);
15-
expect(manager.canAcceptUnencrypted()).toBe(false);
1615
});
1716

1817
it('should default to OPTIONAL when no config provided', () => {
@@ -22,7 +21,6 @@ describe('EncryptionManager', () => {
2221
expect(manager.isEncryptionEnabled()).toBe(true);
2322
expect(manager.isEncryptionRequired()).toBe(false);
2423
expect(manager.shouldAttemptEncryption()).toBe(false);
25-
expect(manager.canAcceptUnencrypted()).toBe(true);
2624
});
2725
});
2826

@@ -33,7 +31,6 @@ describe('EncryptionManager', () => {
3331
expect(manager.isEncryptionEnabled()).toBe(false);
3432
expect(manager.isEncryptionRequired()).toBe(false);
3533
expect(manager.shouldAttemptEncryption()).toBe(false);
36-
expect(manager.canAcceptUnencrypted()).toBe(true);
3734

3835
// Should never encrypt responses regardless of incoming format
3936
expect(manager.shouldEncryptResponse(true)).toBe(false);
@@ -46,7 +43,6 @@ describe('EncryptionManager', () => {
4643
expect(manager.isEncryptionEnabled()).toBe(true);
4744
expect(manager.isEncryptionRequired()).toBe(false);
4845
expect(manager.shouldAttemptEncryption()).toBe(false);
49-
expect(manager.canAcceptUnencrypted()).toBe(true);
5046

5147
// Should mirror incoming message format
5248
expect(manager.shouldEncryptResponse(true)).toBe(true);
@@ -59,7 +55,6 @@ describe('EncryptionManager', () => {
5955
expect(manager.isEncryptionEnabled()).toBe(true);
6056
expect(manager.isEncryptionRequired()).toBe(true);
6157
expect(manager.shouldAttemptEncryption()).toBe(true);
62-
expect(manager.canAcceptUnencrypted()).toBe(false);
6358

6459
// Should always encrypt responses regardless of incoming format
6560
expect(manager.shouldEncryptResponse(true)).toBe(true);

packages/dvmcp-commons/src/encryption/encryption-manager.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
GIFT_WRAP_KIND,
1414
PRIVATE_DIRECT_MESSAGE_KIND,
1515
SEALED_DIRECT_MESSAGE_KIND,
16+
TAG_PUBKEY,
1617
} from '../core/constants';
1718

1819
export interface DecryptedMessage {
@@ -67,13 +68,6 @@ export class EncryptionManager {
6768
return this.mode === EncryptionMode.REQUIRED;
6869
}
6970

70-
/**
71-
* Determines if we can accept unencrypted messages
72-
*/
73-
public canAcceptUnencrypted(): boolean {
74-
return this.mode !== EncryptionMode.REQUIRED;
75-
}
76-
7771
/**
7872
* Encrypt a message using NIP-17/NIP-59 gift wrap scheme
7973
* @param senderPrivateKey - Sender's private key
@@ -131,7 +125,7 @@ export class EncryptionManager {
131125
const giftWrap: UnsignedEvent = {
132126
kind: GIFT_WRAP_KIND,
133127
content: encryptedSeal,
134-
tags: [['p', recipientPublicKey]],
128+
tags: [[TAG_PUBKEY, recipientPublicKey]],
135129
created_at: Math.floor(Date.now() / 1000),
136130
pubkey: giftWrapPublicKey,
137131
};
@@ -162,7 +156,7 @@ export class EncryptionManager {
162156

163157
// Check if this gift wrap is for us
164158
const isForUs = event.tags.some(
165-
(tag) => tag[0] === 'p' && tag[1] === recipientPublicKey
159+
(tag) => tag[0] === TAG_PUBKEY && tag[1] === recipientPublicKey
166160
);
167161

168162
if (!isForUs) {
@@ -258,7 +252,7 @@ export class EncryptionManager {
258252
}
259253

260254
return event.tags.some(
261-
(tag) => tag[0] === 'p' && tag[1] === recipientPublicKey
255+
(tag) => tag[0] === TAG_PUBKEY && tag[1] === recipientPublicKey
262256
);
263257
}
264258

0 commit comments

Comments
 (0)