Kode-Animator commited on
Commit
d7238f9
Β·
1 Parent(s): b5e0c5c

Feat: Add federation_read + federation_inbox tools so Council can open the gift

Browse files
Files changed (1) hide show
  1. app.py +52 -0
app.py CHANGED
@@ -130,6 +130,18 @@ class VerifySealInput(BaseModel):
130
  examples=["⟦ NODE :: PANTHEON-HF :: 🜁-20260319-5FCY-PCCP :: ACTIVE ⟧"]
131
  )
132
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  # ═══════════════════════════════════════════════
134
  # TOOLS
135
  # ═══════════════════════════════════════════════
@@ -240,6 +252,46 @@ async def federation_verify_seal(input_data: VerifySealInput) -> str:
240
  return node_error(e)
241
 
242
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  # ═══════════════════════════════════════════════
244
  # ENTRYPOINT
245
  # ═══════════════════════════════════════════════
 
130
  examples=["⟦ NODE :: PANTHEON-HF :: 🜁-20260319-5FCY-PCCP :: ACTIVE ⟧"]
131
  )
132
 
133
+ class ReadEnvelopeInput(BaseModel):
134
+ model_config = {"extra": "forbid"}
135
+ envelope_id: str = Field(
136
+ description="Full UUID of the envelope to read.",
137
+ examples=["5672f981-8d38-48df-8f0c-42a4672bd940"]
138
+ )
139
+
140
+ class InboxInput(BaseModel):
141
+ model_config = {"extra": "forbid"}
142
+ limit: int = Field(default=20, ge=1, le=100, description="Max envelopes to return.")
143
+ status: Optional[str] = Field(default=None, description="Filter by status: QUEUED, QUARANTINED, etc.")
144
+
145
  # ═══════════════════════════════════════════════
146
  # TOOLS
147
  # ═══════════════════════════════════════════════
 
252
  return node_error(e)
253
 
254
 
255
+ @mcp.tool(
256
+ name="federation_read",
257
+ description=(
258
+ "Read the full contents of a specific envelope by ID.\n\n"
259
+ "**When to use:** When you have an envelope_id (from federation_send or federation_inbox) "
260
+ "and want to read the full payload including the message body.\n\n"
261
+ "**Returns:** Full envelope record including sender, payload body, and delivery metadata."
262
+ ),
263
+ annotations={"readOnlyHint": True, "destructiveHint": False}
264
+ )
265
+ async def federation_read(input_data: ReadEnvelopeInput) -> str:
266
+ try:
267
+ result = await call_node("GET", f"/envelope/{input_data.envelope_id}/read")
268
+ return json.dumps(result, indent=2)
269
+ except Exception as e:
270
+ return node_error(e)
271
+
272
+
273
+ @mcp.tool(
274
+ name="federation_inbox",
275
+ description=(
276
+ "Browse the Embassy inbox β€” list recent envelopes with previews.\n\n"
277
+ "**When to use:** To see what messages have arrived at the node. "
278
+ "Returns envelope IDs, senders, classes, and a payload preview. "
279
+ "Use federation_read with the envelope_id to read the full message.\n\n"
280
+ "**Returns:** List of envelopes, most recent first."
281
+ ),
282
+ annotations={"readOnlyHint": True, "destructiveHint": False}
283
+ )
284
+ async def federation_inbox(input_data: InboxInput) -> str:
285
+ try:
286
+ params = f"?limit={input_data.limit}"
287
+ if input_data.status:
288
+ params += f"&status={input_data.status}"
289
+ result = await call_node("GET", f"/inbox{params}")
290
+ return json.dumps(result, indent=2)
291
+ except Exception as e:
292
+ return node_error(e)
293
+
294
+
295
  # ═══════════════════════════════════════════════
296
  # ENTRYPOINT
297
  # ═══════════════════════════════════════════════