Koskamo

Family Office Knowledge Graph MCP

An MCP server providing read-only access to a knowledge graph of family offices, built from public records like GLEIF and national registers. It allows agents to resolve family offices, retrieve specific records with provenance, list events and aliases, and manage 'seats' for record ownership verification via on-chain receipts.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

Family Office Knowledge Graph MCP logo, by Agentic KG HoldingsVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-06Operated by Agentic KG Holdings
MCP endpoint (Streamable HTTP)
https://mcp.familyofficeknowledgegraph.ai/mcp
Vendor documentation

What its tools do

7 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

Can change data (1)

7 of 7 have a description · 7 of 7 declare behavior hints · 4 of 6 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Passed Official MCP Registry namespace is tied to familyofficeknowledgegraph.ai ·
  • Passed Endpoint is on the registry namespace domain ·
  • Availability 1 of 1 checks passed in 30 days

What you can do with it

  • Resolve a family office by identifier
  • Get detailed record with source provenance
  • List historical events for a record
  • Claim and verify ownership seat for a record

Source and maintenance

Vendor evidenceRegistry 0.21.0
Maintenance checked

Protocol and capabilities

Server
Family Office Knowledge Graph 0.21.0
MCP protocol negotiated in check
2025-11-25
Tools
7 advertised
Resources
Not advertised
Resource templates
Not advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": false
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Read-only door over the Family Office Knowledge Graph (public record, one record per family office, every field with source_url, read_by, state). This is the apex door; it holds the index and forwards to the node that serves the record. Tools: resolve_family_office, get_record, list_events_since, list_aliases, list_nodes (reads; each cleared read is evidenced by an RCO-10060 receipt on chain fo-kg); claim_seat and list_my_receipts (a family office's own agent, its own record only). Errors are typed. Nothing is answered from memory.

Tools

7 advertised

resolve_family_office
Advertised by the server during the last successful anonymous check.
Advertised read-only

Resolve an identifier (LEI, legal name, alias or register id) to the family-office records that carry it, with the node that serves each.

resolve_family_office input schema
{
  "type": "object",
  "required": [
    "identifier"
  ],
  "properties": {
    "identifier": {
      "type": "string",
      "maxLength": 200,
      "minLength": 2,
      "description": "Record id, LEI, legal name, alias, or a register identifier as it appears on the record (case-insensitive)"
    }
  }
}
resolve_family_office output schema
{
  "type": "object",
  "required": [
    "identifier",
    "matches"
  ],
  "properties": {
    "matches": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "lei": {
            "type": "string"
          },
          "node": {
            "type": "string"
          },
          "record": {
            "type": "string"
          },
          "legal_name": {
            "type": "string"
          },
          "matched_on": {
            "type": "string"
          }
        }
      }
    },
    "served_by": {
      "type": "object"
    },
    "identifier": {
      "type": "string"
    }
  }
}
resolve_family_office annotations
{
  "title": "Resolve a family office",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_record
Advertised by the server during the last successful anonymous check.
Advertised read-only

The Family Office Record for one identifier: every field with value, source_url, read_by and state; optionally a named version.

get_record input schema
{
  "type": "object",
  "required": [
    "identifier"
  ],
  "properties": {
    "version": {
      "type": "string",
      "description": "record version as listed by list_nodes (e.g. 2026-09-13.1); omit for current"
    },
    "identifier": {
      "type": "string",
      "maxLength": 200,
      "minLength": 2,
      "description": "Record id, LEI, legal name, alias, or a register identifier as it appears on the record (case-insensitive)"
    }
  }
}
get_record output schema
{
  "type": "object",
  "required": [
    "record"
  ],
  "properties": {
    "record": {
      "type": "object"
    },
    "served_by": {
      "type": "object"
    }
  }
}
get_record annotations
{
  "title": "Get a Family Office Record",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
list_events_since
Advertised by the server during the last successful anonymous check.
Advertised read-only

Dated, URL'd events on one record (registrations, renewals, orders, acquisitions), oldest first, optionally since a date, paged by cursor.

list_events_since input schema
{
  "type": "object",
  "required": [
    "identifier"
  ],
  "properties": {
    "limit": {
      "type": "integer",
      "default": 50,
      "maximum": 200,
      "minimum": 1
    },
    "since": {
      "type": "string",
      "description": "ISO date YYYY-MM-DD; events on or after it"
    },
    "cursor": {
      "type": "string",
      "description": "next_cursor from a previous page"
    },
    "identifier": {
      "type": "string",
      "maxLength": 200,
      "minLength": 2,
      "description": "Record id, LEI, legal name, alias, or a register identifier as it appears on the record (case-insensitive)"
    }
  }
}
list_events_since output schema
{
  "type": "object",
  "required": [
    "lei",
    "events"
  ],
  "properties": {
    "lei": {
      "type": "string"
    },
    "events": {
      "type": "array"
    },
    "served_by": {
      "type": "object"
    },
    "next_cursor": {
      "type": [
        "string",
        "null"
      ]
    }
  }
}
list_events_since annotations
{
  "title": "List events on a record",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
list_aliases
Advertised by the server during the last successful anonymous check.
Advertised read-only

Every name the record carries for one identifier — legal name, register names, other names — each with its source.

list_aliases input schema
{
  "type": "object",
  "required": [
    "identifier"
  ],
  "properties": {
    "identifier": {
      "type": "string",
      "maxLength": 200,
      "minLength": 2,
      "description": "Record id, LEI, legal name, alias, or a register identifier as it appears on the record (case-insensitive)"
    }
  }
}
list_aliases output schema
{
  "type": "object",
  "required": [
    "lei",
    "aliases"
  ],
  "properties": {
    "lei": {
      "type": "string"
    },
    "aliases": {
      "type": "array"
    },
    "served_by": {
      "type": "object"
    },
    "legal_name": {
      "type": "object"
    }
  }
}
list_aliases annotations
{
  "title": "List aliases",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
list_nodes
Advertised by the server during the last successful anonymous check.
Advertised read-only

The graph's nodes — one per jurisdiction — with record counts read from each node's index, the node door and its as-of.

list_nodes input schema
{
  "type": "object",
  "properties": {}
}
list_nodes output schema
{
  "type": "object",
  "required": [
    "nodes"
  ],
  "properties": {
    "apex": {
      "type": "object"
    },
    "nodes": {
      "type": "array"
    }
  }
}
list_nodes annotations
{
  "title": "List nodes",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
claim_seat
Advertised by the server during the last successful anonymous check.
Open-world

A family office's own agent claims the seat of its own record. Give card_url (the https URL of the office agent's card) and record_id (the record id as the graph serves it). The record must resolve to the name the card gives; the door then issues a domain challenge (DNS TXT _fo-kg-seat.<domain> or https://<domain>/.well-known/fo-kg-seat.txt). Call again with challenge_id: proven → the record moves listed → claimed and the seat key is answered once. With seat_key and rows, the seat sets its own fields on its own record only (website, aliases, sectors, structure, description, contact_url); the sourced fields are never touched and verified is set by a person, never by a tool. The seat settles on /seat (x402).

claim_seat input schema
{
  "type": "object",
  "required": [
    "card_url",
    "record_id"
  ],
  "properties": {
    "rows": {
      "type": "object",
      "properties": {
        "aliases": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "sectors": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "website": {
          "type": "string"
        },
        "structure": {
          "type": "string"
        },
        "contact_url": {
          "type": "string"
        },
        "description": {
          "type": "string"
        }
      },
      "description": "the seat's own fields"
    },
    "card_url": {
      "type": "string",
      "description": "https URL of the office agent's card (A2A agent card JSON)"
    },
    "seat_key": {
      "type": "string",
      "description": "the seat key answered when the claim was proven (for rows)"
    },
    "record_id": {
      "type": "string",
      "maxLength": 120,
      "minLength": 2,
      "description": "the office's record id as the graph serves it (resolve_family_office lists it)"
    },
    "challenge_id": {
      "type": "string",
      "description": "the challenge_id from the accepted claim, once the token is published"
    }
  }
}
claim_seat output schema
{
  "type": "object",
  "required": [
    "result"
  ],
  "properties": {
    "reason": {
      "type": "string"
    },
    "result": {
      "enum": [
        "accepted",
        "proof_failed",
        "claimed",
        "rows_set",
        "rows_refused",
        "refused",
        "error"
      ],
      "type": "string"
    },
    "seat_id": {
      "type": "string"
    },
    "seat_key": {
      "type": "string"
    },
    "challenge": {
      "type": "object"
    },
    "record_id": {
      "type": "string"
    },
    "claim_status": {
      "type": "string"
    }
  }
}
claim_seat annotations
{
  "title": "Claim a seat",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
list_my_receipts
Advertised by the server during the last successful anonymous check.
Advertised read-only

For a seat holder only: the RCO-10060 receipts whose subject is its own record — who read it (as the door saw the reader: user agent, network, country), when, and under which rule (the tool) — newest first, each with its verify URL. Needs record_id and the seat key of that record; nobody else can list them.

list_my_receipts input schema
{
  "type": "object",
  "required": [
    "record_id",
    "seat_key"
  ],
  "properties": {
    "limit": {
      "type": "integer",
      "default": 100,
      "maximum": 500,
      "minimum": 1
    },
    "cursor": {
      "type": "string"
    },
    "seat_key": {
      "type": "string"
    },
    "record_id": {
      "type": "string",
      "maxLength": 120,
      "minLength": 2
    }
  }
}
list_my_receipts output schema
{
  "type": "object",
  "required": [
    "result"
  ],
  "properties": {
    "result": {
      "type": "string"
    },
    "receipts": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "rule": {
            "type": "string"
          },
          "reader": {
            "type": "object"
          },
          "verify": {
            "type": "string"
          },
          "cleared_at": {
            "type": "string"
          }
        }
      }
    },
    "record_id": {
      "type": "string"
    }
  }
}
list_my_receipts annotations
{
  "title": "List the receipts of my record",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}

Prompts

Not advertised

No prompt definitions available.

Resources

Not advertised

No resource definitions available.

90-day uptime

A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.

Too few checks for a percentage yet (1 of 1 answered).

  1. 2026-11-07: 1 of 1 checks answered

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
1217 ms
95th percentile latency
1217 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 1217 ms · metadata changed · 7 tool(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http family-office-knowledge-graph-mcp https://mcp.familyofficeknowledgegraph.ai/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add family-office-knowledge-graph-mcp --url https://mcp.familyofficeknowledgegraph.ai/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable family-office-knowledge-graph-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "family-office-knowledge-graph-mcp": {
      "url": "https://mcp.familyofficeknowledgegraph.ai/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "family-office-knowledge-graph-mcp": {
      "type": "streamableHttp",
      "url": "https://mcp.familyofficeknowledgegraph.ai/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start family-office-knowledge-graph-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "family-office-knowledge-graph-mcp": {
      "type": "http",
      "url": "https://mcp.familyofficeknowledgegraph.ai/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http family-office-knowledge-graph-mcp https://mcp.familyofficeknowledgegraph.ai/mcp

Claude Desktop

Open Claude Settings > Connectors > Add custom connector, enter this server URL and enable it for the conversation. This is a manual remote-connector handoff, not a desktop JSON configuration.
Claude Desktop configuration
https://mcp.familyofficeknowledgegraph.ai/mcp

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "family-office-knowledge-graph-mcp": {
      "serverUrl": "https://mcp.familyofficeknowledgegraph.ai/mcp"
    }
  }
}

Let your agent find its tools

Find servers like Family Office Knowledge Graph MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run Family Office Knowledge Graph MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing