Stonewake

Seventeen read only tools over cited company, portfolio and country data for bank credit desks.

Should I use this

Quality & Safety

A
Description quality
100%
Schema completeness
92%
Naming quality
84%
Poisoning risk
80%
Permission match
100%
Protocol compliance
100%

Findings (2)

  • HIGHTool poisoning patterns detected
  • LOWTool description contains role marker that could confuse chat modelsin search_stonewake_docs

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~5,079Tokens (tool definitions)
~1.3 KBTypical response size
Significant attention impact (3.97% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "stonewake": {
      "url": "https://mcp.stonewake.ai/mcp"
    }
  }
}

Remote endpoints

https://mcp.stonewake.ai/mcpstreamable-http

What it can do

Tool inventory

Tools (17)

🟒 Read-only🟑 WriteπŸ”΄ Deleteβšͺ Unknown
🟒portfolio_overview(transitions_since)

Current health of the monitored portfolio: how many exposures sit in each status band (green, amber, red, insufficient, not_assessed), the active exposure count, the number of transitions in the last 30 days and how many of them are status changes (an exposure's first assessment is an addition to the book, a transition but not a change), and how many exposures have an overdue credit review. Optionally pass transitions_since (an ISO 8601 date-time) to also list the individual status transitions since that moment, newest first, each with its cause: the signals whose change moved the status, their citation ids, and the register record behind the lead one. Start here for questions like how the book is doing or what changed since a date and why.

Input Schema

{
  "type": "object",
  "properties": {
    "transitions_since": {
      "type": "string",
      "format": "date-time",
      "description": "Also return status transitions at or after this ISO 8601 date-time, newest first."
    }
  },
  "additionalProperties": false
}
🟒portfolio_book(limit, offset, include_inactive)

The monitored book itself: one row per exposure with the team whose book holds it (team_id, team_name), its label, register identifier, entity class (corporate, sovereign_or_public_body, bank, spv or fund, derived from register-stated facts and null when none has been derived yet), desk, current status band, score, completeness, seen_share (the weight share of applicable signals actually observed), explained_share and reachable_share (the observed share of what a connected source can serve, the figure the insufficient floor reads), the top contributing signals with their citation ids, the most recent status change, and the standing credit review (disposition, note, next review date, and whether that date has passed). Ordered most severe first (red, amber, insufficient, not_assessed, green). Paged with limit and offset; the response carries the exact total. Set include_inactive true to include exposures no longer actively monitored.

Input Schema

{
  "type": "object",
  "properties": {
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "description": "Page size, default 50, maximum 100."
    },
    "offset": {
      "type": "integer",
      "minimum": 0,
      "description": "Rows to skip, default 0."
    },
    "include_inactive": {
      "type": "boolean",
      "description": "Include exposures no longer actively monitored."
    }
  },
  "additionalProperties": false
}
🟒portfolio_import_preview(csv, limit, offset)

Preview adding a book of companies to the caller team's monitored portfolio. Pass the book as CSV text whose header is identifier_type,identifier plus, optionally, name, currency, limit_amount and drawn_amount; at most 2,000 rows. Every row is matched by its registry identifier alone, where identifier_type is lei, uk_crn, de_register (register type, number and court, for example HRB 275806 MΓΌnchen), us_cik or another national register scheme. The name column is echoed back and never used to match. Each row answers its outcome (add, reactivate, in_book, duplicate, ambiguous, unresolved, invalid), a reason, and the matched node_id and register name. Rows are paged with limit and offset in file order; counts and total always cover the whole file, so page on until offset reaches total. Nothing is written, and applying an import happens in the Stonewake dashboard.

Input Schema

{
  "type": "object",
  "properties": {
    "csv": {
      "type": "string",
      "minLength": 1,
      "maxLength": 1000000,
      "description": "The book as CSV text, header row first."
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "description": "Page size, default 100, maximum 100."
    },
    "offset": {
      "type": "integer",
      "minimum": 0,
      "description": "Rows to skip, default 0."
    }
  },
  "required": [
    "csv"
  ],
  "additionalProperties": false
}
🟒entity_risk_profile(node_id)

The caller team's credit-risk view of one company, by its graph node_id (the id search_companies hits carry). Answers one of three honest shapes: not in the portfolio (in_portfolio false), held but not yet assessed (assessment null), or the full current assessment with its status band, score, seen_share, explained_share and reachable_share (the figure the insufficient floor reads), a coverage_line of one to three sentences counting covered signals and gaps with their reasons, and every signal with its state (evidenced, register_quiet, gap, awaiting_bank_input, not_applicable), gap_reason, evidence grade (A to D), evidence value, note, and citation ids. A signal no connected source reaches for the company's jurisdiction is a gap, never not_applicable. A held company also carries entity_class: the class its checks route on (a bank is never scored on corporate distress models) and its source, either your team's analyst override or the register rule that derived it. Company nodes only; person lookups answer not_found.

Input Schema

{
  "type": "object",
  "properties": {
    "node_id": {
      "type": "integer",
      "minimum": 1,
      "description": "The graph node id, as returned by search_companies. Not the entity_id of company_profile."
    }
  },
  "required": [
    "node_id"
  ],
  "additionalProperties": false
}
🟒search_companies(query, limit)

Find a company by name or identifier. The query can be a scheme-prefixed identifier such as lei:5493001KJTIIGC8Y1R12, a bare registration number (CRN, CIK, LEI and similar shapes), or a company name (matched exact, then prefix, then token, then fuzzy). Hits carry the graph node_id that entity_risk_profile takes, plus jurisdiction, status fields, and register identifiers. connected_sources names the registers an empty result was searched against. Companies only; persons are never returned.

Input Schema

{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "minLength": 2,
      "maxLength": 256,
      "description": "Company name, scheme:value identifier, or bare number."
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 25,
      "description": "Maximum hits, default 10, maximum 25."
    }
  },
  "required": [
    "query"
  ],
  "additionalProperties": false
}
🟒company_profile(entity_id)

One registry row's identity from the closed Stonewake registry of named market participants (export credit agencies, multilaterals and banks, plus the trade publications deals cite): slug, display name, full name, kind, country, aliases, and group memberships. Takes entity_id from the registry's own id space. This is NOT the node_id that search_companies returns and entity_risk_profile takes; the two id spaces are different, and an id from the wrong space answers not_found.

Input Schema

{
  "type": "object",
  "properties": {
    "entity_id": {
      "type": "integer",
      "minimum": 1,
      "description": "The registry entity id. Not a graph node_id from search_companies."
    }
  },
  "required": [
    "entity_id"
  ],
  "additionalProperties": false
}
🟒scoring_rubric

How scores are produced for the caller's team: the live scoring configuration (signal weights, status thresholds, evidence-coverage floor; version null means the built-in desk default is active) together with the team's stored rubric versions, newest first. Use this to interpret the status bands and scores that the portfolio and risk tools return.

Input Schema

{
  "type": "object",
  "properties": {},
  "additionalProperties": false
}
🟒search_stonewake_docs(query)

Search the Stonewake API documentation at docs.stonewake.ai: authentication and the swk_live_ key format, quickstart, key management, error bodies, status codes, and rate limits. Deterministic text search over the official pages; returns the best matching excerpts with each page's URL. This tool needs no Stonewake API key.

Input Schema

{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "minLength": 2,
      "description": "What to look up, for example: rate limits."
    }
  },
  "required": [
    "query"
  ],
  "additionalProperties": false
}
🟒screening_lookup(screening_id, subject_type, node_id, entity_id, iso3, ...)

Adverse media screenings run for the caller's team, covering organizations and countries; each row names its team (team_id, team_name; both null on a workspace wide screening every team reads). Without screening_id this lists screening runs newest first, filterable by subject_type (entity or country), by the subject's ids (node_id for a company from search_companies, entity_id for a registry institution from company_profile, iso3 for a country), or by subject name; paged with limit (default 20, maximum 100) and offset, and the response carries the exact total. With screening_id it returns that one run in full: per category verdicts with rationale and review state, the drafted summary, grounded findings with their press quotes, and the sources behind them. Findings quote reported coverage, not established fact.

Input Schema

{
  "type": "object",
  "properties": {
    "screening_id": {
      "type": "integer",
      "minimum": 1,
      "description": "A screening id from the list; when present the other arguments are not used."
    },
    "subject_type": {
      "type": "string",
      "enum": [
        "entity",
        "country"
      ],
      "description": "Filter the list by subject kind."
    },
    "node_id": {
      "type": "integer",
      "minimum": 1,
      "description": "Filter by the subject's graph node id."
    },
    "entity_id": {
      "type": "integer",
      "minimum": 1,
      "description": "Filter by the subject's registry entity id."
    },
    "iso3": {
      "type": "string",
      "minLength": 3,
      "maxLength": 3,
      "description": "Filter by the screened country's ISO alpha-3 code."
    },
    "subject": {
      "type": "string",
      "minLength": 1,
      "maxLength": 256,
      "description": "Filter by subject name, matched on its normalized form."
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "description": "Page size, default 20, maximum 100."
    },
    "offset": {
      "type": "integer",
      "minimum": 0,
      "description": "Rows to skip, default 0."
    }
  },
  "additionalProperties": false
}
🟒deal_book(deal_id, q, stage, window, eca_named, ...)

The deal book of the one team the caller's key reads; every row names that team (team_id, team_name). Without deal_id this lists deals ordered by their ranking window first (financing open, early stage, not confirmed, financing closed, cancelled) and the chosen sort inside it, filterable by stage, window, country_code (ISO country codes), sector, status, eca, eca_named (only deals naming an export credit agency), minimum contract value (min_value_usd), and free text (q); sort by score (default), last_activity, value, or first_seen; paged with limit (default 50, maximum 100) and offset, with the exact total. Dismissed deals are excluded unless status asks for them, and the portfolio rows a desk holds back by default (closed, cancelled, older than the stale window of 18 months by default, own bank, domestic; score_hidden true) are off the page unless include_hidden is true, and score_own_bank marks the rows where your own bank is a lender. A row carrying merged_into was found to be a duplicate and folded into the deal that field names: read that deal instead, and expect this one to be dismissed. Each row carries its window (score_window and its label), the band word and reason count behind its score (score_band, score_reason_count), the confirmed state over its linked findings (state, state_label), the newest quote backed event date (event_date, null when no source stated one), the lender names on the deal (lenders), and the two derived sentences a desk reads first: angle (why the row is on the list) and ask (what is still to be financed, read from the confirmed state, the window, the agencies and the lenders; a row whose state no source confirmed reads State not confirmed by a source yet). With deal_id (the deal_id field of list rows) it returns one deal in full: score_reasons, one plain sentence per scoring component saying which fact it matched, alongside parties carrying entity_id and node_id where bound, the cited timeline with press quotes (each entry also carrying the state its quote confirmed, the confirming passage and the event date), lifecycle events, sources each carrying source_tier (1 a primary source, 2 trade press, 3 an aggregator, which is also where an unclassified publisher lands) and its tier_label, the deal summary (summary_lines: three lines generated from the cited findings by fixed rules, not by a model, each with the finding and quote behind every field it states), the analyst's own next_action, and economics.

Input Schema

{
  "type": "object",
  "properties": {
    "deal_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "description": "A deal_id from the list; when present the other arguments are not used."
    },
    "q": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "description": "Free-text filter over deal names and summaries."
    },
    "stage": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Keep only these lifecycle stages."
    },
    "window": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Keep only these ranking windows: financing_open, early_stage, not_confirmed, financing_closed, cancelled."
    },
    "eca_named": {
      "type": "boolean",
      "description": "Keep only deals naming an export credit agency."
    },
    "include_hidden": {
      "type": "boolean",
      "description": "Also serve the rows a desk holds back by default (closed, cancelled, older than the stale window, own bank, domestic); off by default."
    },
    "country_code": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Keep only deals in these ISO country codes."
    },
    "sector": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Keep only these sectors."
    },
    "status": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Keep only these statuses; dismissed deals appear only when asked for here."
    },
    "eca": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "description": "Keep only deals naming this export credit agency."
    },
    "min_value_usd": {
      "type": "number",
      "minimum": 0,
      "description": "Keep only deals at or above this contract value in USD."
    },
    "sort": {
      "type": "string",
      "enum": [
        "score",
        "last_activity",
        "value",
        "first_seen"
      ],
      "description": "Ranking, default score."
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "description": "Page size, default 50, maximum 100."
    },
    "offset": {
      "type": "integer",
      "minimum": 0,
      "description": "Rows to skip, default 0."
    }
  },
  "additionalProperties": false
}
🟒country_profile(iso3)

Country intelligence for export finance. Without iso3 this returns the index of covered countries with each one's risk score and the caller team's live deal rollup. With iso3 (a three letter ISO 3166-1 alpha-3 code such as TUR) it returns one country in depth: the risk score with its cited component breakdown, indicator values, membership lists with legal citations, reference events, and the team's deals there. Indicator and dataset entries carry attribution fields such as attribution_text stating the data licence terms; preserve that attribution whenever values are quoted onward.

Input Schema

{
  "type": "object",
  "properties": {
    "iso3": {
      "type": "string",
      "minLength": 3,
      "maxLength": 3,
      "description": "ISO 3166-1 alpha-3 country code; omit to list every covered country."
    }
  },
  "additionalProperties": false
}
🟒company_financials(node_id)

Every financial figure for one company, newest reporting period first, each figure citing the source record it came from (a public register, a public filing repository, or the annual financial report the issuer published on its own website). Takes node_id, the graph node id carried by search_companies hits (not the entity_id of company_profile). Figures are served as filed at the source, except a figure with derived true, which the filing does not state and which was calculated from two figures the same filing states; its derivation says how in plain words. A missing period means nothing was filed, not zero.

Input Schema

{
  "type": "object",
  "properties": {
    "node_id": {
      "type": "integer",
      "minimum": 1,
      "description": "The graph node id, as returned by search_companies hits. Not the entity_id of company_profile."
    }
  },
  "required": [
    "node_id"
  ],
  "additionalProperties": false
}
🟒company_events(node_id, group)

The register event feed of one company: filings, status changes, and other register happenings, grouped into display rows and ordered by significance tier, each row citing its evidencing record where one exists. Takes node_id, the graph node id from search_companies hits. Related events arrive folded into one rollup row with a member_count and a group_key; pass that group_key as group to expand one rollup into its member events.

Input Schema

{
  "type": "object",
  "properties": {
    "node_id": {
      "type": "integer",
      "minimum": 1,
      "description": "The graph node id, as returned by search_companies hits. Not the entity_id of company_profile."
    },
    "group": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "description": "A group_key from a previous response; expands that one rollup into its member events."
    }
  },
  "required": [
    "node_id"
  ],
  "additionalProperties": false
}
🟒company_financing(node_id, include_matured, bucket)

The debt surface of one company: registered charges with status lines and bound lenders, listed debt instruments, filed debt position facts, derived aggregates, a maturity wall, and per section coverage states saying how complete each section is. Takes node_id, the graph node id from search_companies hits. Long instrument books fold into the maturity wall; pass bucket (within_12m, 1_to_2y, 2_to_5y, beyond_5y, or no_maturity) to expand one maturity slice, and include_matured true to also list matured instruments.

Input Schema

{
  "type": "object",
  "properties": {
    "node_id": {
      "type": "integer",
      "minimum": 1,
      "description": "The graph node id, as returned by search_companies hits. Not the entity_id of company_profile."
    },
    "include_matured": {
      "type": "boolean",
      "description": "Also list matured instruments, default false."
    },
    "bucket": {
      "type": "string",
      "enum": [
        "within_12m",
        "1_to_2y",
        "2_to_5y",
        "beyond_5y",
        "no_maturity"
      ],
      "description": "Expand one maturity-wall slice into its instruments."
    }
  },
  "required": [
    "node_id"
  ],
  "additionalProperties": false
}
🟒ownership_chain(node_id, threshold, max_depth)

The upward ownership chains of one company, composed across registers and cited hop by hop, with per register coverage notes. Takes node_id, the graph node id from search_companies hits. threshold is the minimum ownership percentage a chain must keep to be followed, default 25; max_depth caps the number of hops, default and maximum 8. Served owners are organizations; a chain reaching an individual terminates there with a stated terminal reason. Hop values are served verbatim from the registers, never synthesized.

Input Schema

{
  "type": "object",
  "properties": {
    "node_id": {
      "type": "integer",
      "minimum": 1,
      "description": "The graph node id, as returned by search_companies hits. Not the entity_id of company_profile."
    },
    "threshold": {
      "type": "number",
      "exclusiveMinimum": 0,
      "maximum": 100,
      "description": "Minimum ownership percentage a chain must keep, default 25."
    },
    "max_depth": {
      "type": "integer",
      "minimum": 1,
      "maximum": 8,
      "description": "Maximum hops to walk, default and maximum 8."
    }
  },
  "required": [
    "node_id"
  ],
  "additionalProperties": false
}
🟒company_records(node_id, connector_id, limit, offset)

The register records behind one company, a page at a time. Each row is a citation (register, record type, identifier, source URL, retrieval date), newest first. Takes node_id, the graph node id from search_companies hits. Every page states records_total, the company's whole count, and registers, each register's connector_id, name and count; pass one connector_id to page that register alone. A company listed in a securities register can hold over 100,000 records, so page with limit (default and maximum 25) and offset, and read registers first to decide what to page.

Input Schema

{
  "type": "object",
  "properties": {
    "node_id": {
      "type": "integer",
      "minimum": 1,
      "description": "The graph node id, as returned by search_companies hits. Not the entity_id of company_profile."
    },
    "connector_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 64,
      "description": "One register to page, as a registers row names it; omit it to page every register newest first."
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 25,
      "description": "Page size, default and maximum 25."
    },
    "offset": {
      "type": "integer",
      "minimum": 0,
      "maximum": 9223372036854776000,
      "description": "Rows to skip, default 0."
    }
  },
  "required": [
    "node_id"
  ],
  "additionalProperties": false
}
🟒developments(run_id, sort, limit, offset)

Dated, cited developments surfaced by your team's research runs, the runs of the one team the caller's key reads: grounded findings with a headline, category, verification state, and corroborating source count. Without run_id this is a feed paged with limit (default 25, maximum 100) and offset, with the exact total; sort is recent (default) or score. Each row names the run_id it came from and its team (team_id, team_name); pass run_id to load that whole research run with its grounded findings, press quotes, and cited sources. Another team's run_id answers not found, like an unknown one.

Input Schema

{
  "type": "object",
  "properties": {
    "run_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "description": "A run_id from a development row; when present the other arguments are not used."
    },
    "sort": {
      "type": "string",
      "enum": [
        "recent",
        "score"
      ],
      "description": "Feed order: recent (default) or score."
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "description": "Page size, default 25, maximum 100."
    },
    "offset": {
      "type": "integer",
      "minimum": 0,
      "description": "Rows to skip, default 0."
    }
  },
  "additionalProperties": false
}

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded17 tools