@lifesi/genesis-mcp 0.1.4 → 0.1.7

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.
@@ -8,7 +8,7 @@ export function hivesResourceInputSchema(id, fallback) {
8
8
  const upload = id.startsWith('hives_upload_object');
9
9
  return { type: 'object', properties: { ...keyProperties, ...(upload ? { body_base64: { type: 'string', maxLength: Math.ceil(OBJECT_BYTES / 3) * 4 }, content_type: { type: 'string', maxLength: 512 } } : {}) }, required: ['project_id', 'bucket_id', 'key', ...(upload ? ['body_base64'] : [])], additionalProperties: false };
10
10
  }
11
- export const isHivesResourceTool = (id) => /^(?:hives_marketplace_(?:categories|featured|installed|get_installation|uninstall|reconcile|list_packages|publish|get_package|install|update|list_versions)|hives_.*_native_queue|hives_(?:(?:list_volumes|create_volume|get_volume|delete_volume|mount_volume|unmount_volume)|list_buckets|create_bucket|get_bucket|delete_bucket|list_objects|upload_object(?:_by_key)?|delete_object(?:_by_key)?|download_object_by_key|get_cors_config|set_cors_config|generate_presigned_url|reconcile|list_runtimes|get_runtime|select_runtime|list_project_runtimes))$/.test(id);
11
+ export const isHivesResourceTool = (id) => /^(?:hives_marketplace_(?:categories|featured|installed|get_installation|uninstall|reconcile|list_packages|publish|get_package|install|update|list_versions)|hives_(?:get|configure|remove)_native_queue_consumer|hives_.*_native_queue|hives_.*_native_topic|hives_(?:(?:list_volumes|create_volume|get_volume|delete_volume|mount_volume|unmount_volume)|list_buckets|create_bucket|get_bucket|delete_bucket|list_objects|upload_object(?:_by_key)?|delete_object(?:_by_key)?|download_object_by_key|get_cors_config|set_cors_config|generate_presigned_url|reconcile|list_runtimes|get_runtime|select_runtime|list_project_runtimes))$/.test(id);
12
12
  function text(value) { if (typeof value !== 'string')
13
13
  throw new Error('Invalid Hives resource input.'); return value; }
14
14
  function decode(value) { const s = text(value); if (s.length > Math.ceil(OBJECT_BYTES / 3) * 4 || s.length % 4 || !/^[A-Za-z0-9+/]*={0,2}$/.test(s))
@@ -26,6 +26,14 @@ export async function callHivesResourceTool(g, id, a, signal) {
26
26
  const cells = g.hives.cells;
27
27
  const buzz = g.hives.queues;
28
28
  switch (id) {
29
+ case 'hives_list_native_topic': return g.hives.topics.list(project(), options);
30
+ case 'hives_inspect_native_topic': return g.hives.topics.get(project(), text(a.topic_id), options);
31
+ case 'hives_create_native_topic': return g.hives.topics.create(project(), body(), options);
32
+ case 'hives_delete_native_topic': return g.hives.topics.remove(project(), text(a.topic_id), options);
33
+ case 'hives_subscriptions_native_topic': return g.hives.topics.subscriptions.list(project(), text(a.topic_id), options);
34
+ case 'hives_subscribe_native_topic': return g.hives.topics.subscriptions.add(project(), text(a.topic_id), text(body()?.queueId), options);
35
+ case 'hives_unsubscribe_native_topic': return g.hives.topics.subscriptions.remove(project(), text(a.topic_id), text(a.subscription_id), options);
36
+ case 'hives_publish_native_topic': return g.hives.topics.publish(project(), text(a.topic_id), body(), options);
29
37
  case 'hives_list_volumes': return g.hives.volumes.list(project(), { page: a.page, per_page: a.per_page }, options);
30
38
  case 'hives_get_volume': return g.hives.volumes.get(project(), text(a.volume_id), options);
31
39
  case 'hives_create_volume': return g.hives.volumes.create(project(), body(), options);
@@ -57,6 +65,9 @@ export async function callHivesResourceTool(g, id, a, signal) {
57
65
  case 'hives_list_project_runtimes': return g.hives.runtimes.project(project(), options);
58
66
  case 'hives_get_runtime': return g.hives.runtimes.get(text(a.name), options);
59
67
  case 'hives_select_runtime': return g.hives.runtimes.select({ wasi: text(a.wasi), runner: text(a.runner), artifact: text(a.artifact) }, options);
68
+ case 'hives_get_native_queue_consumer': return buzz.consumer.get(project(), queue(), options);
69
+ case 'hives_configure_native_queue_consumer': return buzz.consumer.configure(project(), queue(), body(), options);
70
+ case 'hives_remove_native_queue_consumer': return buzz.consumer.remove(project(), queue(), options);
60
71
  case 'hives_list_native_queue': return buzz.list(project(), options);
61
72
  case 'hives_inspect_native_queue': return buzz.get(project(), queue(), options);
62
73
  case 'hives_create_native_queue': return buzz.create(project(), body(), options);
package/dist/server.js CHANGED
@@ -5,7 +5,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprot
5
5
  import http from 'node:http';
6
6
  import { callTool, tools } from './tools.js';
7
7
  export function createServer(opts = {}) {
8
- const server = new Server({ name: 'genesis', version: '0.1.4' }, {
8
+ const server = new Server({ name: 'genesis', version: '0.1.7' }, {
9
9
  capabilities: { tools: {} },
10
10
  instructions: 'Genesis: one API for Foundry (inference), Hives (compute), Relays (DNS) and LifeID keys. Use the named tools for common tasks; use genesis_search_tools + genesis_call for anything else.',
11
11
  });
package/dist/tools.js CHANGED
@@ -2,14 +2,14 @@ import { callHivesResourceTool, hivesResourceInputSchema, isHivesResourceTool }
2
2
  import { createHivesNodeTransport } from './hives-node-transport.js';
3
3
  import { BEACONS_PROVISION_OPERATION, beaconsInputSchema, callBeaconsProvision } from './beacons.js';
4
4
  import { fleetsInputSchema, isFleetsLifecycleTool, callFleetsLifecycleTool } from './fleets.js';
5
- import { Genesis, GenesisError, MAX_WASM_BYTES, hivesResponseBytes, operationTable } from '@lifesi/genesis';
5
+ import { isFoundryBillingOperation, Genesis, GenesisError, MAX_WASM_BYTES, hivesResponseBytes, operationTable } from '@lifesi/genesis';
6
6
  const uploadSchema = { type: 'object', properties: {
7
7
  project_id: { type: 'string', description: 'Project owned by the caller’s verified org' },
8
8
  wasm_base64: { type: 'string', maxLength: Math.ceil(MAX_WASM_BYTES / 3) * 4, description: 'Explicit standard-base64 content of a real WASM binary (decoded maximum 10 MiB)' },
9
9
  filename: { type: 'string', maxLength: 255 },
10
10
  git_sha: { type: 'string', minLength: 7, maxLength: 40 }, git_branch: { type: 'string', maxLength: 255 }, git_message: { type: 'string', maxLength: 1000 },
11
11
  }, required: ['project_id', 'wasm_base64'], additionalProperties: false };
12
- const inputSchema = (id, op) => id === 'hives_upload_deployment' ? uploadSchema : fleetsInputSchema(id, beaconsInputSchema(id, hivesResourceInputSchema(id, op.inputSchema)));
12
+ const inputSchema = (id, op) => isFoundryBillingOperation(id) ? { type: 'object', properties: ['foundry_ensureBillingProfile', 'foundry_createNativeCreditCheckout'].includes(id) ? { operation_key: { type: 'string', minLength: 1, maxLength: 255, description: 'Persisted original operation key; reconcile unknown outcomes before retrying.' } } : {}, required: ['foundry_ensureBillingProfile', 'foundry_createNativeCreditCheckout'].includes(id) ? ['operation_key'] : [], additionalProperties: false } : id === 'hives_upload_deployment' ? uploadSchema : fleetsInputSchema(id, beaconsInputSchema(id, hivesResourceInputSchema(id, op.inputSchema)));
13
13
  const all = Object.entries(operationTable);
14
14
  /** Operations callable by agents (everything except gateway-internal ones like credential verify). */
15
15
  export const callable = all.filter(([, op]) => !op.internal);
@@ -68,7 +68,13 @@ async function invoke(genesis, id, args, signal) {
68
68
  return text(`Unknown operation "${id}". Use genesis_search_tools to find one.`, true);
69
69
  try {
70
70
  let r;
71
- if (isFleetsLifecycleTool(id)) {
71
+ if (isFoundryBillingOperation(id)) {
72
+ const mutation = ['foundry_ensureBillingProfile', 'foundry_createNativeCreditCheckout'].includes(id);
73
+ if (Object.keys(args).some(k => k !== 'operation_key') || (mutation ? typeof args.operation_key !== 'string' : Object.keys(args).length !== 0))
74
+ throw new Error('Native billing accepts only a persisted operation key for mutations.');
75
+ r = id === 'foundry_readBillingProfile' ? await genesis.foundry.billing.profile({ signal }) : id === 'foundry_readNativeCreditBalance' ? await genesis.foundry.billing.creditBalance({ signal }) : id === 'foundry_ensureBillingProfile' ? await genesis.foundry.billing.ensureProfile(args.operation_key, { signal }) : await genesis.foundry.billing.checkoutCredits(args.operation_key, { signal });
76
+ }
77
+ else if (isFleetsLifecycleTool(id)) {
72
78
  r = await callFleetsLifecycleTool(genesis, id, args, signal);
73
79
  }
74
80
  else if (id === BEACONS_PROVISION_OPERATION) {
@@ -102,14 +108,14 @@ async function invoke(genesis, id, args, signal) {
102
108
  });
103
109
  }
104
110
  else
105
- r = op.service === 'hives'
111
+ r = (op.service === 'hives' || op.service === 'blinds' || id === 'relays_getEnrollment' || id === 'relays_enroll')
106
112
  ? await genesis.request(id, args, { signal })
107
113
  : await genesis.request(id, args);
108
114
  return text(r === undefined ? { ok: true } : r);
109
115
  }
110
116
  catch (e) {
111
117
  if (e instanceof GenesisError)
112
- return text({ error: { type: e.type, status: e.status, message: e.message, request_id: e.requestId } }, true);
118
+ return text({ error: { type: e.type, status: e.status, message: e.message, request_id: e.requestId, ...(isFoundryBillingOperation(id) && e.body && typeof e.body === 'object' && 'outcome' in e.body ? { outcome: e.body.outcome } : {}) } }, true);
113
119
  return text({ error: { type: 'network', message: e.message, hint: `The ${op.service} service may be unreachable (status: ${op.upstream.status}).` } }, true);
114
120
  }
115
121
  }
@@ -125,5 +131,5 @@ export async function callTool(opts, name, args = {}, signal) {
125
131
  return text(`Unknown operation "${id}". Use genesis_search_tools to find one.`, true);
126
132
  const hives = op.service === 'hives';
127
133
  const genesis = new Genesis(hives ? { ...opts, fetch: createHivesNodeTransport(opts, signal) } : opts);
128
- return invoke(genesis, id, input, hives || isFleetsLifecycleTool(id) ? signal : undefined);
134
+ return invoke(genesis, id, input, hives || isFoundryBillingOperation(id) || op.service === 'blinds' || id === 'relays_getEnrollment' || id === 'relays_enroll' || isFleetsLifecycleTool(id) ? signal : undefined);
129
135
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifesi/genesis-mcp",
3
- "version": "0.1.4",
3
+ "version": "0.1.7",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/l1felabs/genesis-api.git",
@@ -18,7 +18,7 @@
18
18
  "dependencies": {
19
19
  "@modelcontextprotocol/sdk": "^1.32.1",
20
20
  "undici": "6.29.0",
21
- "@lifesi/genesis": "0.1.4"
21
+ "@lifesi/genesis": "0.1.7"
22
22
  },
23
23
  "scripts": {
24
24
  "build": "tsc -p tsconfig.json"