list-organizations
Retrieve nonprofit organizations from the IRS database with updated tax-exempt status or filing information since a specified date to track recent changes or access bulk organization data.
Instructions
List nonprofit organizations from the IRS database that have been updated since a specified date. This tool retrieves organizations that have had changes to their tax-exempt status or filing information.
Parameters:
- since: ISO date string (required) - Get organizations updated since this date (e.g., "2024-01-01T00:00:00Z")
Returns detailed information about organizations including:
- Basic information (EIN, name, address)
- Tax status and classification details
- Financial information (revenue, assets)
- Filing requirements and ruling dates
Use this tool to get bulk organization data or track recent changes to nonprofit status.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| since | Yes | ISO date string to get organizations updated since this date (e.g., '2024-01-01T00:00:00Z') |
Implementation Reference
- src/tools/list-organizations.ts:37-128 (handler)Implements the tool execution: parses input with Zod schema, applies rate limiting, fetches organizations from CharityAPI updated since the given date, maps and formats the response data into markdown, handles errors.export async function handleListOrganizations(args: unknown): Promise<CallToolResult> { try { logger.debug("List organizations requested", { args }); // Validate input const input = ListOrganizationsInputSchema.parse(args); logger.debug("Input validated", { input }); // Check rate limit if (!(await rateLimiter.checkRateLimit('list_organizations'))) { const resetTime = rateLimiter.getResetTime('list_organizations'); const resetDate = new Date(resetTime).toISOString(); return { content: [ { type: "text", text: `Rate limit exceeded for list organizations. Please try again after ${resetDate}.`, } as TextContent, ], isError: true, }; } // Make API call logger.info("Listing organizations", { since: input.since.toISOString() }); const response = await charityAPIClient.listOrganizations(input.since); if (!response.data) { throw new CharityAPIError("No data returned from CharityAPI", 404); } // Handle the response data - it should be an array or single organization const organizations = Array.isArray(response.data) ? response.data : [response.data]; // Format response const output: ListOrganizationsOutput = { organizations: organizations.map(org => ({ ein: org.ein, name: org.name, city: org.city, state: org.state, zip: org.zip, street: org.street, status: org.status, classification: org.classification, subsection: org.subsection, foundation: org.foundation, activity: org.activity, organization: org.organization, deductibility: org.deductibility, ruling: org.ruling, taxPeriod: org.tax_period, revenueAmount: org.revenue_amt, incomeAmount: org.income_amt, assetAmount: org.asset_amt, })), since: input.since, }; // Create formatted text response const formattedText = formatListOrganizationsResponse(output, input); logger.info("List organizations completed successfully", { resultCount: output.organizations.length, since: input.since.toISOString() }); return { content: [ { type: "text", text: formattedText, } as TextContent, ], }; } catch (error) { logger.error("List organizations failed", { args, error }); const mcpError = handleMCPError(error); return { content: [ { type: "text", text: mcpError.message, } as TextContent, ], isError: true, }; } }
- src/schemas/charity-schemas.ts:48-55 (schema)Zod schema for validating and parsing the tool input parameter 'since' as a date.export const ListOrganizationsInputSchema = z.object({ since: z.string() .refine((dateStr) => { const date = new Date(dateStr); return !isNaN(date.getTime()); }, "Since must be a valid ISO date string") .transform((dateStr) => new Date(dateStr)), });
- src/tools/list-organizations.ts:7-35 (schema)MCP tool specification including name, description, and input schema for protocol compliance.export const LIST_ORGANIZATIONS_TOOL = { name: "list-organizations", description: ` List nonprofit organizations from the IRS database that have been updated since a specified date. This tool retrieves organizations that have had changes to their tax-exempt status or filing information. Parameters: - since: ISO date string (required) - Get organizations updated since this date (e.g., "2024-01-01T00:00:00Z") Returns detailed information about organizations including: - Basic information (EIN, name, address) - Tax status and classification details - Financial information (revenue, assets) - Filing requirements and ruling dates Use this tool to get bulk organization data or track recent changes to nonprofit status. `.trim(), inputSchema: { type: "object" as const, properties: { since: { type: "string", description: "ISO date string to get organizations updated since this date (e.g., '2024-01-01T00:00:00Z')", format: "date-time", }, }, required: ["since"], }, };
- src/tools/index.ts:9-55 (registration)Registers the tool with the MCP server: adds to listTools response and dispatches calls to the handler via switch statement.export function registerAllTools(server: Server) { try { // Register tools list handler server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ CHARITY_LOOKUP_TOOL, PUBLIC_CHARITY_CHECK_TOOL, CHARITY_SEARCH_TOOL, LIST_ORGANIZATIONS_TOOL, ], })); // Register tool call handler server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; switch (name) { case CHARITY_LOOKUP_TOOL.name: return await handleCharityLookup(args); case PUBLIC_CHARITY_CHECK_TOOL.name: return await handlePublicCharityCheck(args); case CHARITY_SEARCH_TOOL.name: return await handleCharitySearch(args); case LIST_ORGANIZATIONS_TOOL.name: return await handleListOrganizations(args); default: throw new Error(`Unknown tool: ${name}`); } }); logger.info("All charity tools registered successfully", { tools: [ CHARITY_LOOKUP_TOOL.name, PUBLIC_CHARITY_CHECK_TOOL.name, CHARITY_SEARCH_TOOL.name, LIST_ORGANIZATIONS_TOOL.name, ], }); } catch (error) { logger.error("Failed to register tools", { error }); throw error; } }
- Helper function to format the API response into a user-friendly markdown string listing organization details.function formatListOrganizationsResponse(output: ListOrganizationsOutput, input: ListOrganizationsInput): string { const { organizations, since } = output; let response = `# Organizations List\n\n`; // Query summary response += `**Updated Since:** ${since.toISOString()}\n`; response += `**Results:** ${organizations.length} organizations found\n\n`; if (organizations.length === 0) { response += `No organizations found that have been updated since ${since.toISOString()}.\n`; response += `Try using an earlier date to see more results.\n`; return response; } // Organizations listing organizations.forEach((org, index) => { response += `## ${index + 1}. ${org.name}\n`; response += `**EIN:** ${org.ein}\n`; // Address information const addressParts = [org.street, org.city, org.state, org.zip].filter(Boolean); if (addressParts.length > 0) { response += `**Address:** ${addressParts.join(', ')}\n`; } // Status and classification if (org.status) { response += `**Status:** ${getStatusDescription(org.status)}\n`; } if (org.subsection) { response += `**Subsection:** 501(c)(${org.subsection})\n`; } if (org.classification) { response += `**Classification:** ${org.classification}\n`; } if (org.foundation) { response += `**Foundation Code:** ${org.foundation}\n`; } // Financial information if (org.revenueAmount && org.revenueAmount !== '0') { response += `**Revenue:** $${formatCurrency(org.revenueAmount)}\n`; } if (org.assetAmount && org.assetAmount !== '0') { response += `**Assets:** $${formatCurrency(org.assetAmount)}\n`; } // Tax information if (org.taxPeriod) { response += `**Tax Period:** ${formatTaxPeriod(org.taxPeriod)}\n`; } if (org.ruling) { response += `**Ruling Date:** ${formatRulingDate(org.ruling)}\n`; } if (org.deductibility) { response += `**Deductible:** ${org.deductibility === '1' ? 'Yes' : 'No'}\n`; } response += `\n`; }); return response; }