Spaces:
Sleeping
Sleeping
Commit Β·
d7238f9
1
Parent(s): b5e0c5c
Feat: Add federation_read + federation_inbox tools so Council can open the gift
Browse files
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 |
# βββββββββββββββββββββββββββββββββββββββββββββββ
|