Ansvar Legal MCP Recording: complete MCP interaction recording for Ansvar legal and regulatory MCP servers. Tool calls, resource access, citation extraction, error handling, session lifecycle. Verified against 6 Ansvar MCP servers (Swedish data protection, cybersecurity, financial regulation, competition, energy regulation, security program).
All 11 events use the foundation.protocols.ai.ansvar namespace prefix — nested under ai to make clear that Ansvar is one specific legal/regulatory MCP integration within the broader foundation.protocols.ai.* governance framework.
session.start and session.end use state_key="" to track the current bridge session state. Other room members can read the latest session state at any time.m.relates_to with rel_type: "m.thread" referencing the session.start event, creating a threaded conversation per bridge session.tool.result records text_length but NOT the actual result text. The DCPAI principle “data stays home; questions travel” is enforced at the protocol level. Raw legal text never crosses the bridge.initialize, tools/list, tools/call, resources/list, resources/read). No semantic interpretation beyond citation extraction.2 state events tracking the MCP bridge session lifecycle — from proxy start to teardown.
Emitted when the bridge starts proxying MCP traffic. Lists all configured MCP servers. This event serves as the thread root for all subsequent events in the session.
| Field | Type | Description |
|---|---|---|
| session_id | string | Unique session identifier (e.g., ansvar_sess_20260411T120000Z) |
| servers | object[] | Configured MCP servers: name, command, cwd |
| timestamp | integer | Unix millisecond timestamp |
| actor | string | Matrix user ID |
{
"type": "foundation.protocols.ai.ansvar.session.start",
"content": {
"session_id": "ansvar_sess_20260411T120000Z",
"servers": [
{"name": "swedish-data-protection", "command": "npx", "cwd": "../ansvarsystems/swedish-data-protection-mcp"},
{"name": "swedish-cybersecurity", "command": "npx", "cwd": "../ansvarsystems/swedish-cybersecurity-mcp"}
],
"timestamp": 1744365600000,
"actor": "@raazesh:matrix.openearth.network"
}
}
Emitted when the bridge session terminates. Includes operation counts and total duration.
| Field | Type | Description |
|---|---|---|
| session_id | string | Session identifier |
| duration_ms | integer | Total session duration in milliseconds |
| operations | object | Operation counts: tool_calls, tool_results, resource_reads, citations, errors, server_connect |
| timestamp | integer | Unix millisecond timestamp |
| actor | string | Matrix user ID |
{
"type": "foundation.protocols.ai.ansvar.session.end",
"content": {
"session_id": "ansvar_sess_20260411T120000Z",
"duration_ms": 45230,
"operations": {
"tool_calls": 3,
"tool_results": 3,
"resource_reads": 1,
"citations": 5,
"errors": 0,
"server_connect": 2
},
"timestamp": 1744365645230,
"actor": "@raazesh:matrix.openearth.network"
}
}
1 event recording MCP server initialization — the initialize handshake.
Emitted when the MCP initialize handshake completes. Records server identity, protocol version, and capabilities.
| Field | Type | Description |
|---|---|---|
| session_id | string | Session identifier |
| server_name | string | MCP server name (e.g., swedish-data-protection) |
| protocol_version | string | MCP protocol version (e.g., 2024-11-05) |
| server_info | object | Server identity: name, version |
| capabilities | object | MCP capabilities (tools, resources, prompts) |
| timestamp | integer | Unix millisecond timestamp |
| actor | string | Matrix user ID |
{
"type": "foundation.protocols.ai.ansvar.server.connect",
"content": {
"session_id": "ansvar_sess_20260411T120000Z",
"server_name": "swedish-data-protection",
"protocol_version": "2024-11-05",
"server_info": {
"name": "swedish-data-protection-mcp",
"version": "1.0.0"
},
"capabilities": {"tools": {}, "resources": {}},
"timestamp": 1744365601000,
"actor": "@raazesh:matrix.openearth.network",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$session_start_event_id"
}
}
}
3 events for MCP tool lifecycle — discovery, invocation, and result capture.
Emitted when a tools/list response is received from the MCP server. Records available tools and their schemas.
| Field | Type | Description |
|---|---|---|
| session_id | string | Session identifier |
| server_name | string | MCP server name |
| tools | object[] | Available tools: name, description, input_schema |
| tool_count | integer | Number of tools available |
| timestamp | integer | Unix millisecond timestamp |
| actor | string | Matrix user ID |
{
"type": "foundation.protocols.ai.ansvar.tool.list",
"content": {
"session_id": "ansvar_sess_20260411T120000Z",
"server_name": "swedish-data-protection",
"tools": [
{
"name": "search_decisions",
"description": "Search IMY decisions on data protection",
"input_schema": {"type": "object", "properties": {"query": {"type": "string"}}}
},
{
"name": "get_decision",
"description": "Get a specific IMY decision by ID",
"input_schema": {"type": "object", "properties": {"id": {"type": "string"}}}
}
],
"tool_count": 2,
"timestamp": 1744365602000,
"actor": "@raazesh:matrix.openearth.network",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$session_start_event_id"
}
}
}
Emitted when a tools/call request is sent to the MCP server. Records the tool name and arguments.
| Field | Type | Description |
|---|---|---|
| session_id | string | Session identifier |
| server_name | string | MCP server name |
| request_id | integer|string | JSON-RPC request ID |
| tool_name | string | Name of the tool being called |
| arguments | object | Tool call arguments |
| timestamp | integer | Unix millisecond timestamp |
| actor | string | Matrix user ID |
{
"type": "foundation.protocols.ai.ansvar.tool.call",
"content": {
"session_id": "ansvar_sess_20260411T120000Z",
"server_name": "swedish-data-protection",
"request_id": 1,
"tool_name": "search_decisions",
"arguments": {"query": "GDPR consent requirements"},
"timestamp": 1744365603000,
"actor": "@raazesh:matrix.openearth.network",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$session_start_event_id"
}
}
}
Emitted when a tools/call response is received. Records content metadata (length, NOT raw text — data stays home),
latency, and the number of legal citations extracted.
| Field | Type | Description |
|---|---|---|
| session_id | string | Session identifier |
| server_name | string | MCP server name |
| request_id | integer|string | JSON-RPC request ID (matches tool.call) |
| tool_name | string | Tool that produced the result |
| content | object[] | Result metadata: type, text_length (raw text NOT included) |
| is_error | boolean | Whether the MCP server flagged this as an error result |
| latency_ms | integer | Time between tool.call and tool.result |
| citation_count | integer | Number of legal citations extracted from result text |
| timestamp | integer | Unix millisecond timestamp |
| actor | string | Matrix user ID |
{
"type": "foundation.protocols.ai.ansvar.tool.result",
"content": {
"session_id": "ansvar_sess_20260411T120000Z",
"server_name": "swedish-data-protection",
"request_id": 1,
"tool_name": "search_decisions",
"content": [{"type": "text", "text_length": 2847}],
"is_error": false,
"latency_ms": 234,
"citation_count": 3,
"timestamp": 1744365603234,
"actor": "@raazesh:matrix.openearth.network",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$session_start_event_id"
}
}
}
3 events for MCP resource access — discovery, read requests, and content delivery.
Emitted when a resources/list response is received. Records available legal resources and their URIs.
| Field | Type | Description |
|---|---|---|
| session_id | string | Session identifier |
| server_name | string | MCP server name |
| resources | object[] | Available resources: uri, name, description, mime_type |
| resource_count | integer | Number of resources available |
| timestamp | integer | Unix millisecond timestamp |
| actor | string | Matrix user ID |
{
"type": "foundation.protocols.ai.ansvar.resource.list",
"content": {
"session_id": "ansvar_sess_20260411T120000Z",
"server_name": "swedish-data-protection",
"resources": [
{
"uri": "imy://decisions/2024-001",
"name": "IMY Decision 2024-001",
"description": "GDPR enforcement decision — consent basis",
"mime_type": "text/plain"
}
],
"resource_count": 1,
"timestamp": 1744365604000,
"actor": "@raazesh:matrix.openearth.network",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$session_start_event_id"
}
}
}
Emitted when a resources/read request is sent. Records the resource URI being accessed.
| Field | Type | Description |
|---|---|---|
| session_id | string | Session identifier |
| server_name | string | MCP server name |
| request_id | integer|string | JSON-RPC request ID |
| uri | string | Resource URI being read |
| timestamp | integer | Unix millisecond timestamp |
| actor | string | Matrix user ID |
{
"type": "foundation.protocols.ai.ansvar.resource.read",
"content": {
"session_id": "ansvar_sess_20260411T120000Z",
"server_name": "swedish-data-protection",
"request_id": 2,
"uri": "imy://decisions/2024-001",
"timestamp": 1744365605000,
"actor": "@raazesh:matrix.openearth.network",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$session_start_event_id"
}
}
}
Emitted when a resources/read response is received. Records content metadata (length, MIME type) but NOT the raw content — data stays home.
| Field | Type | Description |
|---|---|---|
| session_id | string | Session identifier |
| server_name | string | MCP server name |
| request_id | integer|string | JSON-RPC request ID (matches resource.read) |
| uri | string | Resource URI |
| contents | object[] | Content metadata: uri, mime_type, text_length |
| latency_ms | integer | Time between resource.read and resource.content |
| timestamp | integer | Unix millisecond timestamp |
| actor | string | Matrix user ID |
{
"type": "foundation.protocols.ai.ansvar.resource.content",
"content": {
"session_id": "ansvar_sess_20260411T120000Z",
"server_name": "swedish-data-protection",
"request_id": 2,
"uri": "imy://decisions/2024-001",
"contents": [
{"uri": "imy://decisions/2024-001", "mime_type": "text/plain", "text_length": 14523}
],
"latency_ms": 89,
"timestamp": 1744365605089,
"actor": "@raazesh:matrix.openearth.network",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$session_start_event_id"
}
}
}
1 derived event — legal references extracted from tool results via regex-based citation parsing.
Derived event — extracted from tool.result text using regex-based citation parsing.
Jurisdiction is inferred from the MCP server name (e.g., swedish-* → SE).
One citation event per legal reference found.
| Field | Type | Description |
|---|---|---|
| session_id | string | Session identifier |
| server_name | string | MCP server that produced the source result |
| source_event_id | string | Event ID of the tool.result this citation was extracted from |
| jurisdiction | string | ISO country code (e.g., SE, EU) |
| reference | string | Full citation text |
| title | string | Law or regulation name |
| section | string | Section, Article, or Chapter number |
| url | string | URL to source document (if available) |
| timestamp | integer | Unix millisecond timestamp |
| actor | string | Matrix user ID |
{
"type": "foundation.protocols.ai.ansvar.citation",
"content": {
"session_id": "ansvar_sess_20260411T120000Z",
"server_name": "swedish-data-protection",
"source_event_id": "$tool_result_event_id",
"jurisdiction": "SE",
"reference": "Section 7 of the Swedish Data Protection Act",
"title": "the Swedish Data Protection Act",
"section": "7",
"timestamp": 1744365603300,
"actor": "@raazesh:matrix.openearth.network",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$session_start_event_id"
}
}
}
1 event for MCP JSON-RPC errors.
Emitted when a JSON-RPC error response is received from the MCP server. Records the standard JSON-RPC error code and message.
| Field | Type | Description |
|---|---|---|
| session_id | string | Session identifier |
| server_name | string | MCP server name |
| request_id | integer|string | JSON-RPC request ID |
| error_code | integer | JSON-RPC error code (e.g., -32601 for Method Not Found) |
| error_message | string | Error description |
| method | string | The MCP method that failed |
| timestamp | integer | Unix millisecond timestamp |
| actor | string | Matrix user ID |
{
"type": "foundation.protocols.ai.ansvar.error",
"content": {
"session_id": "ansvar_sess_20260411T120000Z",
"server_name": "swedish-data-protection",
"request_id": 99,
"error_code": -32601,
"error_message": "Method not found",
"method": "unknown/method",
"timestamp": 1744365610000,
"actor": "@raazesh:matrix.openearth.network",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$session_start_event_id"
}
}
}
| Component | Status | Details |
|---|---|---|
| Bridge daemon | Done | tools/ansvar_bridge.py — Python, MCP stdio proxy, matrix-nio |
| Test suite | Done | tools/test_ansvar_bridge.py — 27 unit tests, all passing |
| MCP servers | 6 configured | Ansvar-Systems repos (Apache-2.0): data protection, cybersecurity, financial, competition, energy, security |
| Citation extractor | Done | Regex-based: Section/Article/SFS/EU Regulation patterns, jurisdiction inference |
| Messenger views | Planned | Reuse Claude/Hopsworks view patterns (ToolCallCard, CitationBadge) |
| Live homeserver | Planned | Wire to a matrix.<your-homeserver> endpoint for demo |
License: bridge daemon is AGPL-3.0 (Layer 2 — strategic choice). MCP servers are Apache-2.0. The bridge communicates via MCP stdio protocol (JSON-RPC) and Matrix wire protocol (JSON/HTTPS) — both are license boundaries.