@hashgraphonline/standards-agent-kit 0.2.110 → 0.2.113

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.
Files changed (138) hide show
  1. package/dist/cjs/builders/hcs6/hcs6-builder.d.ts +47 -0
  2. package/dist/cjs/builders/hcs6/index.d.ts +1 -0
  3. package/dist/cjs/builders/index.d.ts +1 -0
  4. package/dist/cjs/index.d.ts +1 -1
  5. package/dist/cjs/standards-agent-kit.cjs +1 -1
  6. package/dist/cjs/standards-agent-kit.cjs.map +1 -1
  7. package/dist/cjs/tools/hcs6/CreateDynamicRegistryTool.d.ts +44 -0
  8. package/dist/cjs/tools/hcs6/QueryDynamicRegistryTool.d.ts +50 -0
  9. package/dist/cjs/tools/hcs6/RegisterDynamicHashinalTool.d.ts +102 -0
  10. package/dist/cjs/tools/hcs6/UpdateDynamicHashinalTool.d.ts +96 -0
  11. package/dist/cjs/tools/hcs6/base-hcs6-tools.d.ts +28 -0
  12. package/dist/cjs/tools/hcs6/hcs6-tool-params.d.ts +18 -0
  13. package/dist/cjs/tools/hcs6/index.d.ts +6 -0
  14. package/dist/cjs/tools/index.d.ts +1 -0
  15. package/dist/cjs/tools/inscriber/InscribeFromBufferTool.d.ts +4 -4
  16. package/dist/es/builders/hcs6/hcs6-builder.d.ts +47 -0
  17. package/dist/es/builders/hcs6/index.d.ts +1 -0
  18. package/dist/es/builders/index.d.ts +1 -0
  19. package/dist/es/index.d.ts +1 -1
  20. package/dist/es/standards-agent-kit.es.js +44 -31
  21. package/dist/es/standards-agent-kit.es.js.map +1 -1
  22. package/dist/es/standards-agent-kit.es10.js +27 -27
  23. package/dist/es/standards-agent-kit.es10.js.map +1 -1
  24. package/dist/es/standards-agent-kit.es11.js +20 -30
  25. package/dist/es/standards-agent-kit.es11.js.map +1 -1
  26. package/dist/es/standards-agent-kit.es12.js +27 -37
  27. package/dist/es/standards-agent-kit.es12.js.map +1 -1
  28. package/dist/es/standards-agent-kit.es13.js +48 -60
  29. package/dist/es/standards-agent-kit.es13.js.map +1 -1
  30. package/dist/es/standards-agent-kit.es14.js +60 -23
  31. package/dist/es/standards-agent-kit.es14.js.map +1 -1
  32. package/dist/es/standards-agent-kit.es15.js +23 -23
  33. package/dist/es/standards-agent-kit.es15.js.map +1 -1
  34. package/dist/es/standards-agent-kit.es16.js +23 -33
  35. package/dist/es/standards-agent-kit.es16.js.map +1 -1
  36. package/dist/es/standards-agent-kit.es17.js +34 -10
  37. package/dist/es/standards-agent-kit.es17.js.map +1 -1
  38. package/dist/es/standards-agent-kit.es18.js +16 -155
  39. package/dist/es/standards-agent-kit.es18.js.map +1 -1
  40. package/dist/es/standards-agent-kit.es19.js +150 -22
  41. package/dist/es/standards-agent-kit.es19.js.map +1 -1
  42. package/dist/es/standards-agent-kit.es20.js +25 -39
  43. package/dist/es/standards-agent-kit.es20.js.map +1 -1
  44. package/dist/es/standards-agent-kit.es21.js +26 -28
  45. package/dist/es/standards-agent-kit.es21.js.map +1 -1
  46. package/dist/es/standards-agent-kit.es22.js +16 -19
  47. package/dist/es/standards-agent-kit.es22.js.map +1 -1
  48. package/dist/es/standards-agent-kit.es23.js +21 -15
  49. package/dist/es/standards-agent-kit.es23.js.map +1 -1
  50. package/dist/es/standards-agent-kit.es24.js +18 -21
  51. package/dist/es/standards-agent-kit.es24.js.map +1 -1
  52. package/dist/es/standards-agent-kit.es25.js +35 -32
  53. package/dist/es/standards-agent-kit.es25.js.map +1 -1
  54. package/dist/es/standards-agent-kit.es26.js +38 -25
  55. package/dist/es/standards-agent-kit.es26.js.map +1 -1
  56. package/dist/es/standards-agent-kit.es27.js +25 -116
  57. package/dist/es/standards-agent-kit.es27.js.map +1 -1
  58. package/dist/es/standards-agent-kit.es28.js +33 -166
  59. package/dist/es/standards-agent-kit.es28.js.map +1 -1
  60. package/dist/es/standards-agent-kit.es29.js +42 -121
  61. package/dist/es/standards-agent-kit.es29.js.map +1 -1
  62. package/dist/es/standards-agent-kit.es30.js +40 -77
  63. package/dist/es/standards-agent-kit.es30.js.map +1 -1
  64. package/dist/es/standards-agent-kit.es31.js +42 -37
  65. package/dist/es/standards-agent-kit.es31.js.map +1 -1
  66. package/dist/es/standards-agent-kit.es32.js +20 -237
  67. package/dist/es/standards-agent-kit.es32.js.map +1 -1
  68. package/dist/es/standards-agent-kit.es33.js +154 -135
  69. package/dist/es/standards-agent-kit.es33.js.map +1 -1
  70. package/dist/es/standards-agent-kit.es34.js +168 -23
  71. package/dist/es/standards-agent-kit.es34.js.map +1 -1
  72. package/dist/es/standards-agent-kit.es35.js +126 -21
  73. package/dist/es/standards-agent-kit.es35.js.map +1 -1
  74. package/dist/es/standards-agent-kit.es36.js +86 -3
  75. package/dist/es/standards-agent-kit.es36.js.map +1 -1
  76. package/dist/es/standards-agent-kit.es37.js +45 -0
  77. package/dist/es/standards-agent-kit.es37.js.map +1 -0
  78. package/dist/es/standards-agent-kit.es38.js +249 -0
  79. package/dist/es/standards-agent-kit.es38.js.map +1 -0
  80. package/dist/es/standards-agent-kit.es39.js +141 -0
  81. package/dist/es/standards-agent-kit.es39.js.map +1 -0
  82. package/dist/es/standards-agent-kit.es4.js +65 -32
  83. package/dist/es/standards-agent-kit.es4.js.map +1 -1
  84. package/dist/es/standards-agent-kit.es40.js +33 -0
  85. package/dist/es/standards-agent-kit.es40.js.map +1 -0
  86. package/dist/es/standards-agent-kit.es41.js +28 -0
  87. package/dist/es/standards-agent-kit.es41.js.map +1 -0
  88. package/dist/es/standards-agent-kit.es42.js +7 -0
  89. package/dist/es/standards-agent-kit.es42.js.map +1 -0
  90. package/dist/es/standards-agent-kit.es5.js +35 -311
  91. package/dist/es/standards-agent-kit.es5.js.map +1 -1
  92. package/dist/es/standards-agent-kit.es6.js +320 -20
  93. package/dist/es/standards-agent-kit.es6.js.map +1 -1
  94. package/dist/es/standards-agent-kit.es7.js +19 -227
  95. package/dist/es/standards-agent-kit.es7.js.map +1 -1
  96. package/dist/es/standards-agent-kit.es8.js +216 -65
  97. package/dist/es/standards-agent-kit.es8.js.map +1 -1
  98. package/dist/es/standards-agent-kit.es9.js +72 -23
  99. package/dist/es/standards-agent-kit.es9.js.map +1 -1
  100. package/dist/es/tools/hcs6/CreateDynamicRegistryTool.d.ts +44 -0
  101. package/dist/es/tools/hcs6/QueryDynamicRegistryTool.d.ts +50 -0
  102. package/dist/es/tools/hcs6/RegisterDynamicHashinalTool.d.ts +102 -0
  103. package/dist/es/tools/hcs6/UpdateDynamicHashinalTool.d.ts +96 -0
  104. package/dist/es/tools/hcs6/base-hcs6-tools.d.ts +28 -0
  105. package/dist/es/tools/hcs6/hcs6-tool-params.d.ts +18 -0
  106. package/dist/es/tools/hcs6/index.d.ts +6 -0
  107. package/dist/es/tools/index.d.ts +1 -0
  108. package/dist/es/tools/inscriber/InscribeFromBufferTool.d.ts +4 -4
  109. package/dist/umd/builders/hcs6/hcs6-builder.d.ts +47 -0
  110. package/dist/umd/builders/hcs6/index.d.ts +1 -0
  111. package/dist/umd/builders/index.d.ts +1 -0
  112. package/dist/umd/index.d.ts +1 -1
  113. package/dist/umd/standards-agent-kit.umd.js +1 -1
  114. package/dist/umd/standards-agent-kit.umd.js.map +1 -1
  115. package/dist/umd/tools/hcs6/CreateDynamicRegistryTool.d.ts +44 -0
  116. package/dist/umd/tools/hcs6/QueryDynamicRegistryTool.d.ts +50 -0
  117. package/dist/umd/tools/hcs6/RegisterDynamicHashinalTool.d.ts +102 -0
  118. package/dist/umd/tools/hcs6/UpdateDynamicHashinalTool.d.ts +96 -0
  119. package/dist/umd/tools/hcs6/base-hcs6-tools.d.ts +28 -0
  120. package/dist/umd/tools/hcs6/hcs6-tool-params.d.ts +18 -0
  121. package/dist/umd/tools/hcs6/index.d.ts +6 -0
  122. package/dist/umd/tools/index.d.ts +1 -0
  123. package/dist/umd/tools/inscriber/InscribeFromBufferTool.d.ts +4 -4
  124. package/package.json +2 -2
  125. package/src/builders/hcs6/hcs6-builder.ts +136 -0
  126. package/src/builders/hcs6/index.ts +1 -0
  127. package/src/builders/index.ts +1 -0
  128. package/src/index.ts +1 -1
  129. package/src/tools/hcs6/CreateDynamicRegistryTool.ts +66 -0
  130. package/src/tools/hcs6/QueryDynamicRegistryTool.ts +72 -0
  131. package/src/tools/hcs6/RegisterDynamicHashinalTool.ts +79 -0
  132. package/src/tools/hcs6/UpdateDynamicHashinalTool.ts +74 -0
  133. package/src/tools/hcs6/base-hcs6-tools.ts +63 -0
  134. package/src/tools/hcs6/hcs6-tool-params.ts +21 -0
  135. package/src/tools/hcs6/index.ts +6 -0
  136. package/src/tools/index.ts +1 -0
  137. package/src/tools/inscriber/InscribeFromBufferTool.ts +1 -1
  138. package/src/tools/inscriber/InscribeFromUrlTool.ts +60 -7
@@ -0,0 +1,72 @@
1
+ import { z } from 'zod';
2
+ import { BaseHCS6QueryTool } from './base-hcs6-tools';
3
+ import { HCS6QueryToolParams } from './hcs6-tool-params';
4
+ import type { TransactionResponse } from 'hedera-agent-kit';
5
+
6
+ /**
7
+ * Schema for querying a dynamic registry
8
+ */
9
+ const QueryDynamicRegistrySchema = z.object({
10
+ topicId: z.string()
11
+ .describe('The registry topic ID to query'),
12
+ limit: z.number()
13
+ .optional()
14
+ .default(100)
15
+ .describe('Maximum number of entries to retrieve'),
16
+ order: z.enum(['asc', 'desc'])
17
+ .optional()
18
+ .default('desc')
19
+ .describe('Order of entries (desc shows latest first)'),
20
+ skip: z.number()
21
+ .optional()
22
+ .describe('Number of entries to skip'),
23
+ });
24
+
25
+ export type QueryDynamicRegistryInput = z.infer<typeof QueryDynamicRegistrySchema>;
26
+
27
+ /**
28
+ * Tool for querying HCS-6 dynamic registries
29
+ */
30
+ export class QueryDynamicRegistryTool extends BaseHCS6QueryTool<typeof QueryDynamicRegistrySchema> {
31
+ name = 'queryDynamicRegistry';
32
+ description = 'Query a dynamic registry to get the current state of a dynamic hashinal';
33
+ schema = QueryDynamicRegistrySchema;
34
+
35
+ constructor(params: HCS6QueryToolParams) {
36
+ super(params);
37
+ }
38
+
39
+ protected async _call(
40
+ params: QueryDynamicRegistryInput
41
+ ): Promise<TransactionResponse> {
42
+ try {
43
+ const registry = await this.hcs6Builder.getRegistry(params.topicId, {
44
+ limit: params.limit,
45
+ order: params.order,
46
+ skip: params.skip,
47
+ });
48
+
49
+ return {
50
+ status: 'success',
51
+ data: {
52
+ topicId: registry.topicId,
53
+ registryType: 'NON_INDEXED',
54
+ ttl: registry.ttl,
55
+ latestEntry: registry.latestEntry ? {
56
+ topicId: registry.latestEntry.message.t_id,
57
+ timestamp: registry.latestEntry.timestamp,
58
+ memo: registry.latestEntry.message.m,
59
+ sequence: registry.latestEntry.sequence,
60
+ payer: registry.latestEntry.payer,
61
+ } : null,
62
+ totalEntries: registry.entries.length,
63
+ },
64
+ };
65
+ } catch (error) {
66
+ return {
67
+ status: 'error',
68
+ message: error instanceof Error ? error.message : 'Unknown error',
69
+ };
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,79 @@
1
+ import { z } from 'zod';
2
+ import { BaseHCS6TransactionTool } from './base-hcs6-tools';
3
+ import { HCS6TransactionToolParams } from './hcs6-tool-params';
4
+ import type { TransactionResponse } from 'hedera-agent-kit';
5
+
6
+ /**
7
+ * Schema for registering a dynamic hashinal
8
+ */
9
+ const RegisterDynamicHashinalSchema = z.object({
10
+ metadata: z.record(z.unknown())
11
+ .describe('Metadata object for the hashinal (e.g., name, description, attributes)'),
12
+ data: z.object({
13
+ base64: z.string().optional().describe('Base64 encoded data for the hashinal'),
14
+ url: z.string().optional().describe('URL to fetch data from'),
15
+ mimeType: z.string().optional().describe('MIME type of the data'),
16
+ }).optional()
17
+ .describe('Data to inscribe with the hashinal'),
18
+ memo: z.string()
19
+ .optional()
20
+ .describe('Optional memo for the registration'),
21
+ ttl: z.number()
22
+ .min(3600)
23
+ .default(86400)
24
+ .describe('Time-to-live in seconds for the inscription'),
25
+ registryTopicId: z.string()
26
+ .optional()
27
+ .describe('Registry topic ID to use. If not provided, a new registry will be created'),
28
+ submitKey: z.string()
29
+ .optional()
30
+ .describe('Submit key for the registry (required if registry has a submit key)'),
31
+ });
32
+
33
+ export type RegisterDynamicHashinalInput = z.infer<typeof RegisterDynamicHashinalSchema>;
34
+
35
+ /**
36
+ * Tool for registering (creating) dynamic hashinals
37
+ */
38
+ export class RegisterDynamicHashinalTool extends BaseHCS6TransactionTool<typeof RegisterDynamicHashinalSchema> {
39
+ name = 'registerDynamicHashinal';
40
+ description = 'Create and register a new dynamic hashinal that can be updated over time';
41
+ schema = RegisterDynamicHashinalSchema;
42
+
43
+ constructor(params: HCS6TransactionToolParams) {
44
+ super(params);
45
+ }
46
+
47
+ protected async _call(
48
+ params: RegisterDynamicHashinalInput
49
+ ): Promise<TransactionResponse> {
50
+ try {
51
+ const result = await this.hcs6Builder.register({
52
+ metadata: params.metadata,
53
+ data: params.data,
54
+ memo: params.memo,
55
+ ttl: params.ttl,
56
+ registryTopicId: params.registryTopicId,
57
+ submitKey: params.submitKey,
58
+ });
59
+
60
+ if (!result.success || !result.registryTopicId || !result.inscriptionTopicId) {
61
+ throw new Error(result.error || 'Failed to register dynamic hashinal');
62
+ }
63
+
64
+ return {
65
+ status: 'success',
66
+ data: {
67
+ registryTopicId: result.registryTopicId,
68
+ inscriptionTopicId: result.inscriptionTopicId,
69
+ transactionId: result.transactionId,
70
+ },
71
+ };
72
+ } catch (error) {
73
+ return {
74
+ status: 'error',
75
+ message: error instanceof Error ? error.message : 'Unknown error',
76
+ };
77
+ }
78
+ }
79
+ }
@@ -0,0 +1,74 @@
1
+ import { z } from 'zod';
2
+ import { BaseHCS6TransactionTool } from './base-hcs6-tools';
3
+ import { HCS6TransactionToolParams } from './hcs6-tool-params';
4
+ import type { TransactionResponse } from 'hedera-agent-kit';
5
+
6
+ /**
7
+ * Schema for updating a dynamic hashinal
8
+ */
9
+ const UpdateDynamicHashinalSchema = z.object({
10
+ registryTopicId: z.string()
11
+ .describe('The registry topic ID that tracks this dynamic hashinal'),
12
+ metadata: z.record(z.unknown())
13
+ .describe('Updated metadata object for the hashinal'),
14
+ data: z.object({
15
+ base64: z.string().optional().describe('Base64 encoded data for the updated hashinal'),
16
+ url: z.string().optional().describe('URL to fetch updated data from'),
17
+ mimeType: z.string().optional().describe('MIME type of the data'),
18
+ }).optional()
19
+ .describe('Updated data to inscribe'),
20
+ memo: z.string()
21
+ .optional()
22
+ .describe('Optional memo for the update (e.g., "Level up", "Version 2.0")'),
23
+ submitKey: z.string()
24
+ .describe('Submit key for the registry (required to update)'),
25
+ });
26
+
27
+ export type UpdateDynamicHashinalInput = z.infer<typeof UpdateDynamicHashinalSchema>;
28
+
29
+ /**
30
+ * Tool for updating dynamic hashinals
31
+ */
32
+ export class UpdateDynamicHashinalTool extends BaseHCS6TransactionTool<typeof UpdateDynamicHashinalSchema> {
33
+ name = 'updateDynamicHashinal';
34
+ description = 'Update an existing dynamic hashinal with new content while maintaining the same registry';
35
+ schema = UpdateDynamicHashinalSchema;
36
+
37
+ constructor(params: HCS6TransactionToolParams) {
38
+ super(params);
39
+ }
40
+
41
+ protected async _call(
42
+ params: UpdateDynamicHashinalInput
43
+ ): Promise<TransactionResponse> {
44
+ try {
45
+ // Use the register method with the existing registry ID
46
+ const result = await this.hcs6Builder.register({
47
+ metadata: params.metadata,
48
+ data: params.data,
49
+ memo: params.memo,
50
+ registryTopicId: params.registryTopicId,
51
+ submitKey: params.submitKey,
52
+ });
53
+
54
+ if (!result.success) {
55
+ throw new Error(result.error || 'Failed to update dynamic hashinal');
56
+ }
57
+
58
+ return {
59
+ status: 'success',
60
+ data: {
61
+ registryTopicId: result.registryTopicId,
62
+ newInscriptionTopicId: result.inscriptionTopicId,
63
+ transactionId: result.transactionId,
64
+ updateMemo: params.memo,
65
+ },
66
+ };
67
+ } catch (error) {
68
+ return {
69
+ status: 'error',
70
+ message: error instanceof Error ? error.message : 'Unknown error',
71
+ };
72
+ }
73
+ }
74
+ }
@@ -0,0 +1,63 @@
1
+ import {
2
+ BaseHederaTransactionTool,
3
+ BaseHederaQueryTool,
4
+ BaseServiceBuilder,
5
+ } from 'hedera-agent-kit';
6
+ import { HCS6Builder } from '../../builders/hcs6/hcs6-builder';
7
+ import {
8
+ HCS6TransactionToolParams,
9
+ HCS6QueryToolParams,
10
+ } from './hcs6-tool-params';
11
+ import { z } from 'zod';
12
+
13
+ /**
14
+ * Base class for HCS6 transaction tools
15
+ */
16
+ export abstract class BaseHCS6TransactionTool<
17
+ T extends z.ZodObject<
18
+ z.ZodRawShape,
19
+ z.UnknownKeysParam,
20
+ z.ZodTypeAny
21
+ > = z.ZodObject<z.ZodRawShape>
22
+ > extends BaseHederaTransactionTool<T> {
23
+ protected hcs6Builder: HCS6Builder;
24
+ namespace = 'hcs6' as const;
25
+
26
+ constructor(params: HCS6TransactionToolParams) {
27
+ super(params);
28
+ this.hcs6Builder = params.hcs6Builder;
29
+ }
30
+
31
+ /**
32
+ * Override to return the HCS6Builder
33
+ */
34
+ protected getServiceBuilder(): BaseServiceBuilder {
35
+ return this.hcs6Builder;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Base class for HCS6 query tools
41
+ */
42
+ export abstract class BaseHCS6QueryTool<
43
+ T extends z.ZodObject<
44
+ z.ZodRawShape,
45
+ z.UnknownKeysParam,
46
+ z.ZodTypeAny
47
+ > = z.ZodObject<z.ZodRawShape>
48
+ > extends BaseHederaQueryTool<T> {
49
+ protected hcs6Builder: HCS6Builder;
50
+ namespace = 'hcs6' as const;
51
+
52
+ constructor(params: HCS6QueryToolParams) {
53
+ super(params);
54
+ this.hcs6Builder = params.hcs6Builder;
55
+ }
56
+
57
+ /**
58
+ * Override to return the HCS6Builder
59
+ */
60
+ protected getServiceBuilder(): BaseServiceBuilder {
61
+ return this.hcs6Builder;
62
+ }
63
+ }
@@ -0,0 +1,21 @@
1
+ import { HederaAgentKit } from 'hedera-agent-kit';
2
+ import type { BasePluginContext } from 'hedera-agent-kit';
3
+ import { HCS6Builder } from '../../builders/hcs6/hcs6-builder';
4
+
5
+ /**
6
+ * Parameters for HCS6 transaction tools
7
+ */
8
+ export interface HCS6TransactionToolParams {
9
+ hederaKit: HederaAgentKit;
10
+ hcs6Builder: HCS6Builder;
11
+ logger?: BasePluginContext['logger'];
12
+ }
13
+
14
+ /**
15
+ * Parameters for HCS6 query tools
16
+ */
17
+ export interface HCS6QueryToolParams {
18
+ hederaKit: HederaAgentKit;
19
+ hcs6Builder: HCS6Builder;
20
+ logger?: BasePluginContext['logger'];
21
+ }
@@ -0,0 +1,6 @@
1
+ export * from './base-hcs6-tools';
2
+ export * from './hcs6-tool-params';
3
+ export * from './CreateDynamicRegistryTool';
4
+ export * from './RegisterDynamicHashinalTool';
5
+ export * from './UpdateDynamicHashinalTool';
6
+ export * from './QueryDynamicRegistryTool';
@@ -1,3 +1,4 @@
1
1
  export * from './hcs10';
2
2
  export * from './hcs2';
3
+ export * from './hcs6';
3
4
  export * from './inscriber';
@@ -53,7 +53,7 @@ const inscribeFromBufferSchema = z.object({
53
53
  */
54
54
  export class InscribeFromBufferTool extends BaseInscriberQueryTool<typeof inscribeFromBufferSchema> {
55
55
  name = 'inscribeFromBuffer';
56
- description = 'Inscribe content from a buffer/base64 data to the Hedera network. IMPORTANT: Only use this tool when you have actual content to inscribe. The base64Data must contain valid, non-empty content (minimum 10 bytes). Useful for inscribing content that has been read into memory, including files accessed through MCP filesystem tools. Always verify the content exists and is meaningful before attempting inscription.';
56
+ description = 'Inscribe content that you already have retrieved or generated. ALWAYS use this tool for: web page articles (after using MCP tools), API responses, text data, or any content from MCP tools. Steps: 1) Retrieve content using appropriate tool, 2) Convert to base64, 3) Use this tool. NEVER use inscribeFromUrl for web pages - that tool is ONLY for direct file downloads like PDFs or images.';
57
57
 
58
58
  get specificInputSchema() {
59
59
  return inscribeFromBufferSchema;
@@ -42,7 +42,7 @@ const inscribeFromUrlSchema = z.object({
42
42
  */
43
43
  export class InscribeFromUrlTool extends BaseInscriberQueryTool<typeof inscribeFromUrlSchema> {
44
44
  name = 'inscribeFromUrl';
45
- description = 'Inscribe content from a URL to the Hedera network. IMPORTANT: Only use this tool when you have a valid URL pointing to actual content. The URL must be accessible and return meaningful data. The tool will validate that the content exists and is not empty before inscription.';
45
+ description = 'Inscribe content ONLY from URLs that point directly to downloadable files (PDF, image, JSON, ZIP, etc). This tool will FAIL for web pages, news sites, or social media. Examples of VALID URLs: https://example.com/document.pdf, https://cdn.example.com/image.jpg, https://api.example.com/data.json. For web page articles or any content you retrieve via MCP tools, you MUST use inscribeFromBuffer instead after retrieving the content.';
46
46
 
47
47
  get specificInputSchema() {
48
48
  return inscribeFromUrlSchema;
@@ -76,18 +76,32 @@ export class InscribeFromUrlTool extends BaseInscriberQueryTool<typeof inscribeF
76
76
  const timeoutId = setTimeout(() => controller.abort(), 10000);
77
77
 
78
78
  try {
79
- const response = await fetch(params.url, {
79
+ // First try HEAD request
80
+ const headResponse = await fetch(params.url, {
80
81
  method: 'HEAD',
81
82
  signal: controller.signal,
82
83
  });
83
84
 
84
85
  clearTimeout(timeoutId);
85
86
 
86
- if (!response.ok) {
87
- throw new Error(`URL returned error status ${response.status}: ${response.statusText}. Cannot inscribe content from inaccessible URLs.`);
87
+ if (!headResponse.ok) {
88
+ throw new Error(`URL returned error status ${headResponse.status}: ${headResponse.statusText}. Cannot inscribe content from inaccessible URLs.`);
88
89
  }
89
90
 
90
- const contentLength = response.headers.get('content-length');
91
+ const contentType = headResponse.headers.get('content-type') || '';
92
+ const contentLength = headResponse.headers.get('content-length');
93
+
94
+ // Check if content type indicates HTML/web page
95
+ const webPageContentTypes = [
96
+ 'text/html',
97
+ 'application/xhtml+xml',
98
+ 'text/xml'
99
+ ];
100
+
101
+ if (webPageContentTypes.some(type => contentType.toLowerCase().includes(type))) {
102
+ throw new Error(`URL returns HTML/web page content (Content-Type: ${contentType}). This tool only works with direct file URLs (PDFs, images, JSON, etc.). For web page content, first retrieve the content using the appropriate MCP tool or web scraper, then use inscribeFromBuffer to inscribe it.`);
103
+ }
104
+
91
105
  if (contentLength && parseInt(contentLength) === 0) {
92
106
  throw new Error('URL returns empty content (Content-Length: 0). Cannot inscribe empty content.');
93
107
  }
@@ -95,8 +109,47 @@ export class InscribeFromUrlTool extends BaseInscriberQueryTool<typeof inscribeF
95
109
  if (contentLength && parseInt(contentLength) < 10) {
96
110
  throw new Error(`URL content is too small (${contentLength} bytes). Content must be at least 10 bytes.`);
97
111
  }
112
+
113
+ // If HEAD doesn't provide content-type, do a partial GET to check
114
+ if (!contentType || contentType === 'application/octet-stream') {
115
+ console.log(`[InscribeFromUrlTool] Content-Type unclear, fetching first 1KB to verify...`);
116
+
117
+ const getController = new AbortController();
118
+ const getTimeoutId = setTimeout(() => getController.abort(), 5000);
119
+
120
+ try {
121
+ const getResponse = await fetch(params.url, {
122
+ signal: getController.signal,
123
+ headers: {
124
+ 'Range': 'bytes=0-1023' // Get first 1KB
125
+ }
126
+ });
127
+
128
+ clearTimeout(getTimeoutId);
129
+
130
+ if (getResponse.ok || getResponse.status === 206) { // 206 is partial content
131
+ const buffer = await getResponse.arrayBuffer();
132
+ const bytes = new Uint8Array(buffer);
133
+ const text = new TextDecoder('utf-8', { fatal: false }).decode(bytes.slice(0, 512));
134
+
135
+ // Check if it looks like HTML
136
+ if (text.toLowerCase().includes('<!doctype html') ||
137
+ text.toLowerCase().includes('<html') ||
138
+ text.match(/<meta\s+[^>]*>/i) ||
139
+ text.match(/<title>/i)) {
140
+ throw new Error(`URL returns HTML content. This tool only works with direct file URLs. For web page content, first retrieve it using the appropriate tool, then use inscribeFromBuffer.`);
141
+ }
142
+ }
143
+ } catch (getError) {
144
+ clearTimeout(getTimeoutId);
145
+ if (getError instanceof Error && getError.message.includes('HTML content')) {
146
+ throw getError;
147
+ }
148
+ // If partial GET fails, continue anyway
149
+ console.log(`[InscribeFromUrlTool] Could not perform partial GET validation: ${getError instanceof Error ? getError.message : 'Unknown error'}`);
150
+ }
151
+ }
98
152
 
99
- const contentType = response.headers.get('content-type');
100
153
  console.log(`[InscribeFromUrlTool] URL validation passed. Content-Type: ${contentType}, Content-Length: ${contentLength || 'unknown'}`);
101
154
  } catch (fetchError) {
102
155
  clearTimeout(timeoutId);
@@ -106,7 +159,7 @@ export class InscribeFromUrlTool extends BaseInscriberQueryTool<typeof inscribeF
106
159
  if (error instanceof Error) {
107
160
  if (error.name === 'AbortError') {
108
161
  console.log(`[InscribeFromUrlTool] Warning: URL validation timed out after 10 seconds. Proceeding with inscription attempt.`);
109
- } else if (error.message.includes('URL returned error') || error.message.includes('empty content') || error.message.includes('too small')) {
162
+ } else if (error.message.includes('URL returned error') || error.message.includes('empty content') || error.message.includes('too small') || error.message.includes('HTML')) {
110
163
  throw error;
111
164
  } else {
112
165
  console.log(`[InscribeFromUrlTool] Warning: Could not validate URL with HEAD request: ${error.message}. Proceeding with inscription attempt.`);