relay_read
Fetch stored relay messages between terminals in AD4M. Filter results by session ID or specify a timestamp to retrieve only messages after a certain time.
Instructions
Read cross-terminal relay messages from AD4M. Optionally filter by session_id or since a timestamp.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| perspective_uuid | Yes | Perspective UUID (use ClaudeMemory UUID) | |
| session_id | No | Filter to a specific terminal/session | |
| since | No | ISO timestamp — only return messages after this time |
Implementation Reference
- src/index.ts:493-517 (handler)Handler function for relay_read tool: queries links with predicate 'franc://relay', optionally filters by session_id and since timestamp, returns sorted relay messages.
async ({ perspective_uuid, session_id, since }) => { const query: Record<string, string> = { predicate: "franc://relay" }; if (session_id) query.source = `franc://relay/${session_id}`; const data = await gql( `query Q($uuid: String!, $q: LinkQuery!) { perspectiveQueryLinks(uuid: $uuid, query: $q) { author timestamp data { source predicate target } } }`, { uuid: perspective_uuid, q: query } ); let links = data.perspectiveQueryLinks as LinkExpr[]; if (since) { const cutoff = new Date(since).getTime(); links = links.filter((l) => new Date(l.timestamp).getTime() > cutoff); } links.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()); return ok(links.map((l) => ({ session_id: l.data.source.replace("franc://relay/", ""), message: l.data.target.replace("literal://", ""), timestamp: l.timestamp, author: l.author, }))); } ); - src/index.ts:486-517 (schema)Tool registration with Zod schema for relay_read: perspective_uuid (required), session_id (optional), since (optional ISO timestamp).
server.tool("relay_read", "Read cross-terminal relay messages from AD4M. Optionally filter by session_id or since a timestamp.", { perspective_uuid: z.string().describe("Perspective UUID (use ClaudeMemory UUID)"), session_id: z.string().optional().describe("Filter to a specific terminal/session"), since: z.string().optional().describe("ISO timestamp — only return messages after this time"), }, async ({ perspective_uuid, session_id, since }) => { const query: Record<string, string> = { predicate: "franc://relay" }; if (session_id) query.source = `franc://relay/${session_id}`; const data = await gql( `query Q($uuid: String!, $q: LinkQuery!) { perspectiveQueryLinks(uuid: $uuid, query: $q) { author timestamp data { source predicate target } } }`, { uuid: perspective_uuid, q: query } ); let links = data.perspectiveQueryLinks as LinkExpr[]; if (since) { const cutoff = new Date(since).getTime(); links = links.filter((l) => new Date(l.timestamp).getTime() > cutoff); } links.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()); return ok(links.map((l) => ({ session_id: l.data.source.replace("franc://relay/", ""), message: l.data.target.replace("literal://", ""), timestamp: l.timestamp, author: l.author, }))); } ); - src/index.ts:485-517 (registration)Registration of relay_read as tool #13 on the MCP server using server.tool().
// 13. relay_read server.tool("relay_read", "Read cross-terminal relay messages from AD4M. Optionally filter by session_id or since a timestamp.", { perspective_uuid: z.string().describe("Perspective UUID (use ClaudeMemory UUID)"), session_id: z.string().optional().describe("Filter to a specific terminal/session"), since: z.string().optional().describe("ISO timestamp — only return messages after this time"), }, async ({ perspective_uuid, session_id, since }) => { const query: Record<string, string> = { predicate: "franc://relay" }; if (session_id) query.source = `franc://relay/${session_id}`; const data = await gql( `query Q($uuid: String!, $q: LinkQuery!) { perspectiveQueryLinks(uuid: $uuid, query: $q) { author timestamp data { source predicate target } } }`, { uuid: perspective_uuid, q: query } ); let links = data.perspectiveQueryLinks as LinkExpr[]; if (since) { const cutoff = new Date(since).getTime(); links = links.filter((l) => new Date(l.timestamp).getTime() > cutoff); } links.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()); return ok(links.map((l) => ({ session_id: l.data.source.replace("franc://relay/", ""), message: l.data.target.replace("literal://", ""), timestamp: l.timestamp, author: l.author, }))); } );