search_nonprofits
Search the ProPublica Nonprofit Explorer database for US nonprofits by name or keyword, with filters for state, NTEE category, and 501(c) subtype.
Instructions
Search US nonprofits in the ProPublica Nonprofit Explorer database by name or keyword, with optional filters for state, NTEE major category, and 501(c) subtype.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Name or keyword to search for. | |
| state | No | Optional 2-letter US state code, for example "CA". | |
| ntee_category | No | Optional NTEE major category from 1-10. 1=Arts, 2=Education, 3=Environment, 4=Health, 5=Human Services, 6=International, 7=Public Benefit, 8=Religion, 9=Membership Benefit, 10=Unknown. | |
| c_code | No | Optional 501(c) subtype code, for example 3 or 4. | |
| page | No | Optional zero-based page number. ProPublica returns 100 results per page. |
Implementation Reference
- src/tools/search-nonprofits.ts:53-68 (handler)The handler function for the search_nonprofits tool. Calls client.search(args) and maps results using curateOrganization, returning JSON or error results.
export async function handler( client: ProPublicaClient, args: z.infer<z.ZodObject<typeof inputSchema>>, ) { try { const result = await client.search(args); return jsonResult({ total_results: result.total_results, num_pages: result.num_pages, current_page: result.cur_page, organizations: result.organizations.map((org) => curateOrganization(org)), }); } catch (error) { return errorResult(error); } } - src/tools/search-nonprofits.ts:7-7 (registration)Exported constant defining the tool name as 'search_nonprofits'.
export const name = "search_nonprofits"; - src/tools/search-nonprofits.ts:8-9 (registration)Exported description for the search_nonprofits tool.
export const description = "Search US nonprofits in the ProPublica Nonprofit Explorer database by name or keyword, with optional filters for state, NTEE major category, and 501(c) subtype."; - src/tools/search-nonprofits.ts:11-39 (schema)Zod input schema for the tool: query (required string), and optional state, ntee_category, c_code, and page.
export const inputSchema = { query: z.string().min(1).describe("Name or keyword to search for."), state: z .string() .length(2) .optional() .describe('Optional 2-letter US state code, for example "CA".'), ntee_category: z .number() .int() .min(1) .max(10) .optional() .describe( "Optional NTEE major category from 1-10. 1=Arts, 2=Education, 3=Environment, 4=Health, 5=Human Services, 6=International, 7=Public Benefit, 8=Religion, 9=Membership Benefit, 10=Unknown.", ), c_code: z .number() .int() .positive() .optional() .describe("Optional 501(c) subtype code, for example 3 or 4."), page: z .number() .int() .min(0) .optional() .describe("Optional zero-based page number. ProPublica returns 100 results per page."), }; - src/tools/search-nonprofits.ts:41-51 (helper)Helper function curateOrganization that extracts a subset of fields from SearchOrganizationHit for the response.
function curateOrganization(org: SearchOrganizationHit) { return { ein: String(org.ein).replace(/\D/g, ""), name: org.name, city: org.city ?? null, state: org.state ?? null, ntee_code: org.ntee_code ?? null, subseccd: org.subseccd ?? null, score: org.score ?? null, }; } - src/index.ts:26-33 (registration)Registration of the search_nonprofits tool with the MCP server, linking name, description, inputSchema, and handler.
server.registerTool( searchNonprofits.name, { description: searchNonprofits.description, inputSchema: searchNonprofits.inputSchema, }, (args) => searchNonprofits.handler(client, args), );