Get Charity Profile
charity_profileRetrieve a complete Charity Commission profile for any UK charity by its registration number, including trustees, income, expenditure, insolvency flags, governing document, and operating countries.
Instructions
Fetch the full Charity Commission profile for a charity number.
Returns trustees, latest income/expenditure, insolvency flags, governing document type, classifications, and countries of operation. Use charity_search first to find the charity number.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| charity_number | Yes | Charity Commission registration number (e.g. '1234567'). Returned by charity_search. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| charity_number | Yes | Charity registration number. | |
| charity_name | No | Registered charity name. | |
| reg_status | No | Registration status code ('R', 'RM'). | |
| reg_status_label | No | Human-readable registration status. | |
| charity_type | No | Charity type. | |
| charity_co_reg_number | No | Companies House number for charities also registered as companies (Charitable Incorporated Organisations, etc.). | |
| date_of_registration | No | Date of first registration. | |
| address | No | Registered address of the charity (joined address lines). | |
| latest_income | No | Latest filed annual income in GBP. | |
| latest_expenditure | No | Latest filed annual expenditure in GBP. | |
| insolvent | No | True if the charity is flagged as insolvent. | |
| in_administration | No | True if the charity is in administration. | |
| trustee_names | No | Trustees on record. Truncated to 30 entries. | |
| trustee_names_truncated | No | True if the trustee list was truncated. | |
| trustee_names_total | No | Total trustees upstream before truncation. | |
| who_what_where | No | Who/What/Where classification entries. The list may be truncated truncated to 50 entries. | |
| who_what_where_truncated | No | True if the classification list was truncated. | |
| who_what_where_total | No | Total classification entries upstream before truncation. | |
| countries_of_operation | No | Countries the charity operates in (capped at 10 upstream). |
Implementation Reference
- charity.py:126-136 (handler)Tool handler function for 'charity_profile'. Takes a charity_number and delegates to _fetch_charity_profile to retrieve the full charity record.
) async def charity_profile( charity_number: Annotated[str, Field(description="Charity Commission registration number (e.g. '1234567'). Returned by charity_search.", min_length=1, max_length=20)], ) -> CharityProfile: """Fetch the full Charity Commission profile for a charity number. Returns trustees, latest income/expenditure, insolvency flags, governing document type, classifications, and countries of operation. Use charity_search first to find the charity number. """ return await _fetch_charity_profile(charity_number) - charity.py:145-204 (handler)Private helper that performs the actual API call to the Charity Commission /allcharitydetailsV2 endpoint and constructs a CharityProfile model with trustees, classifications, countries, financial data, and insolvency flags.
async def _fetch_charity_profile(charity_number: str) -> CharityProfile: async with charity_client() as client: suffix = "0" lookup_number = charity_number if "-" in charity_number: parts = charity_number.split("-", 1) lookup_number = parts[0] suffix = parts[1] resp = await _request_with_retry( client, "GET", f"/allcharitydetailsV2/{lookup_number}/{suffix}", ) data = resp.json() reg_num = str(data.get("reg_charity_number") or lookup_number) raw_status = data.get("reg_status") raw_trustees = data.get("trustee_names") or [] trustees_total = len(raw_trustees) trustees = [ CharityTrustee(trustee_name=t.get("trustee_name")) for t in raw_trustees[:30] if isinstance(t, dict) ] raw_www = data.get("who_what_where") or [] www_total = len(raw_www) classifications = [ CharityClassification( classification_type=w.get("classification_type"), classification_desc=w.get("classification_desc"), ) for w in raw_www[:50] if isinstance(w, dict) ] countries_raw = data.get("CharityAoOCountryContinent") or [] countries = [c.get("country") for c in countries_raw[:10] if isinstance(c, dict) and c.get("country")] return CharityProfile( charity_number=reg_num, charity_name=data.get("charity_name"), reg_status=raw_status, reg_status_label=_STATUS_LABELS.get(raw_status or "", raw_status), charity_type=data.get("charity_type"), charity_co_reg_number=data.get("charity_co_reg_number") or None, date_of_registration=(data.get("date_of_registration") or "")[:10] or None, address=_build_address(data), latest_income=_coerce_number(data.get("latest_income")), latest_expenditure=_coerce_number(data.get("latest_expenditure")), insolvent=bool(data.get("insolvent", False)), in_administration=bool(data.get("in_administration", False)), trustee_names=trustees, trustee_names_truncated=trustees_total > 30, trustee_names_total=trustees_total, who_what_where=classifications, who_what_where_truncated=www_total > 50, who_what_where_total=www_total, countries_of_operation=countries, ) - charity.py:117-136 (registration)Tool registration via @mcp.tool(name='charity_profile', ...) decorator within the register_tools function. Also registered as a resource at charity://{charity_number}/profile.
@mcp.tool( name="charity_profile", annotations={ "title": "Get Charity Profile", "readOnlyHint": True, "destructiveHint": False, "idempotentHint": True, "openWorldHint": True, }, ) async def charity_profile( charity_number: Annotated[str, Field(description="Charity Commission registration number (e.g. '1234567'). Returned by charity_search.", min_length=1, max_length=20)], ) -> CharityProfile: """Fetch the full Charity Commission profile for a charity number. Returns trustees, latest income/expenditure, insolvency flags, governing document type, classifications, and countries of operation. Use charity_search first to find the charity number. """ return await _fetch_charity_profile(charity_number) - server.py:159-165 (registration)Server-level registration: charity.register_tools(mcp) is called to register all charity tools including charity_profile.
charity.register_tools(mcp) disqualified.register_tools(mcp) land_registry.register_tools(mcp) gazette.register_tools(mcp) hmrc_vat.register_tools(mcp) search_fetch.register_tools(mcp) - models.py:540-610 (schema)The CharityProfile Pydantic model returned by the charity_profile tool, defining all fields including charity_number, name, status, income/expenditure, insolvency flags, trustees, classifications, and countries of operation.
class CharityProfile(BaseModel): """Full Charity Commission profile for a single charity.""" model_config = BASE_CFG charity_number: str = Field(..., description="Charity registration number.") charity_name: str | None = Field(None, description="Registered charity name.") reg_status: str | None = Field( None, description="Registration status code ('R', 'RM')." ) reg_status_label: str | None = Field( None, description="Human-readable registration status." ) charity_type: str | None = Field(None, description="Charity type.") charity_co_reg_number: str | None = Field( None, description=( "Companies House number for charities also registered as companies " "(Charitable Incorporated Organisations, etc.)." ), ) date_of_registration: str | None = Field( None, description="Date of first registration." ) address: str | None = Field( None, description="Registered address of the charity (joined address lines).", ) latest_income: float | None = Field( None, description="Latest filed annual income in GBP." ) latest_expenditure: float | None = Field( None, description="Latest filed annual expenditure in GBP." ) insolvent: bool = Field( False, description="True if the charity is flagged as insolvent." ) in_administration: bool = Field( False, description="True if the charity is in administration." ) trustee_names: list[CharityTrustee] = Field( default_factory=list, description=( "Trustees on record. Truncated to 30 entries." ), ) trustee_names_truncated: bool = Field( False, description="True if the trustee list was truncated." ) trustee_names_total: int = Field( 0, description="Total trustees upstream before truncation." ) who_what_where: list[CharityClassification] = Field( default_factory=list, description=( "Who/What/Where classification entries. The list may be truncated " "truncated to 50 entries." ), ) who_what_where_truncated: bool = Field( False, description="True if the classification list was truncated.", ) who_what_where_total: int = Field( 0, description="Total classification entries upstream before truncation.", ) countries_of_operation: list[str] = Field( default_factory=list, description="Countries the charity operates in (capped at 10 upstream).", )