Skip to main content
Glama
briancasteel

Charity MCP Server

by briancasteel

public-charity-check

Verify if a nonprofit qualifies as a public charity with IRS tax-deductible status using its EIN number to confirm donation eligibility.

Instructions

Verify if a nonprofit organization qualifies as a "public charity" according to the IRS. Public charities are eligible to receive tax-deductible donations under section 501(c)(3).

This tool returns:
- Whether the organization is classified as a public charity
- Tax deductibility status for donations
- EIN confirmation

Use this tool to quickly verify if donations to an organization are tax-deductible.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
einYesThe charity's EIN (Tax ID) in format XX-XXXXXXX or XXXXXXXXX (e.g., '13-1837418' or '131837418')

Implementation Reference

  • The primary handler function `handlePublicCharityCheck` that implements the core logic of the tool. It validates the input EIN using Zod schema, checks rate limits, queries the charityAPIClient, processes the response, formats it with `formatPublicCharityCheckResponse`, and returns MCP-formatted result or error.
    export async function handlePublicCharityCheck(args: unknown): Promise<CallToolResult> {
      try {
        logger.debug("Public charity check requested", { args });
    
        // Validate input
        const input = PublicCharityCheckInputSchema.parse(args);
        logger.debug("Input validated", { ein: input.ein });
    
        // Check rate limit
        if (!(await rateLimiter.checkRateLimit('public_charity_check'))) {
          const resetTime = rateLimiter.getResetTime('public_charity_check');
          const resetDate = new Date(resetTime).toISOString();
          
          return {
            content: [
              {
                type: "text",
                text: `Rate limit exceeded for public charity check. Please try again after ${resetDate}.`,
              } as TextContent,
            ],
            isError: true,
          };
        }
    
        // Make API call
        logger.info("Checking public charity status", { ein: input.ein });
        const response = await charityAPIClient.checkPublicCharity(input.ein);
        
        if (!response.data) {
          throw new CharityAPIError("No data returned from CharityAPI", 404);
        }
    
        // Format response
        const result = response.data;
        const output: PublicCharityCheckOutput = {
          ein: result.ein || input.ein,
          isPublicCharity: result.public_charity || false,
          deductible: result.public_charity || false,
        };
    
        // Create formatted text response
        const formattedText = formatPublicCharityCheckResponse(output);
    
        logger.info("Public charity check completed successfully", { 
          ein: input.ein, 
          isPublicCharity: output.isPublicCharity 
        });
    
        return {
          content: [
            {
              type: "text",
              text: formattedText,
            } as TextContent,
          ],
        };
    
      } catch (error) {
        logger.error("Public charity check failed", { args, error });
        
        const mcpError = handleMCPError(error);
        return {
          content: [
            {
              type: "text",
              text: mcpError.message,
            } as TextContent,
          ],
          isError: true,
        };
      }
    }
  • The tool definition `PUBLIC_CHARITY_CHECK_TOOL` exporting the name, description, and inputSchema required for MCP protocol compliance.
    export const PUBLIC_CHARITY_CHECK_TOOL = {
      name: "public-charity-check",
      description: `
        Verify if a nonprofit organization qualifies as a "public charity" according to the IRS.
        Public charities are eligible to receive tax-deductible donations under section 501(c)(3).
        
        This tool returns:
        - Whether the organization is classified as a public charity
        - Tax deductibility status for donations
        - EIN confirmation
        
        Use this tool to quickly verify if donations to an organization are tax-deductible.
      `.trim(),
      inputSchema: {
        type: "object" as const,
        properties: {
          ein: {
            type: "string",
            description: "The charity's EIN (Tax ID) in format XX-XXXXXXX or XXXXXXXXX (e.g., '13-1837418' or '131837418')",
            pattern: "^\\d{2}-?\\d{7}$",
          },
        },
        required: ["ein"],
      },
    };
  • The `registerAllTools` function that registers the public-charity-check tool (imported at line 4) into the MCP server for both `listTools` (line 15) and `callTool` handlers (lines 29-30).
    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 `formatPublicCharityCheckResponse` that formats the API response into a user-friendly Markdown string.
    function formatPublicCharityCheckResponse(result: PublicCharityCheckOutput): string {
      let response = `# Public Charity Status Check\n\n`;
      response += `**EIN:** ${result.ein}\n`;
      response += `**Public Charity Status:** ${result.isPublicCharity ? '✅ Yes' : '❌ No'}\n`;
      response += `**Tax-Deductible Donations:** ${result.deductible ? '✅ Yes' : '❌ No'}\n\n`;
    
      if (result.isPublicCharity) {
        response += `This organization is recognized as a public charity under IRS section 501(c)(3). `;
        response += `Donations to this organization are generally tax-deductible for donors who itemize deductions.`;
      } else {
        response += `This organization is not classified as a public charity. `;
        response += `Donations may not be tax-deductible, or the organization may not be found in the IRS database.`;
      }
    
      return response;
    }
  • Zod schemas for input validation (`PublicCharityCheckInputSchema` lines 24-26) and output typing (`PublicCharityCheckOutputSchema` lines 74-78), used in the handler for parsing and type safety.
    export const PublicCharityCheckInputSchema = z.object({
      ein: EINSchema,
    });
    
    // Charity search tool input schema
    export const CharitySearchInputSchema = z.object({
      query: z.string()
        .min(3, "Search query cannot be empty")
        .max(200, "Search query cannot exceed 200 characters")
        .optional(),
      city: z.string()
        .optional()
        .transform((val) => val === "" ? undefined : val)
        .refine((val) => val === undefined || (val.length <= 100), 
          "City name cannot exceed 100 characters"),
      state: z.string()
        .optional()
        .transform((val) => val === "" ? undefined : val)
        .transform((val) => val?.toUpperCase())
        .refine((val) => val === undefined || (val.length === 2 && /^[A-Za-z]{2}$/.test(val)), 
          "State must be a 2-letter abbreviation (e.g., CA, ca, NY, ny)"),
    });
    
    // List organizations tool input schema
    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)),
    });
    
    // Output schemas for type safety
    export const CharityLookupOutputSchema = z.object({
      ein: z.string(),
      name: z.string(),
      city: z.string().optional(),
      state: z.string().optional(),
      country: z.string().optional(),
      deductibilityCode: z.string().optional(),
      deductibilityDetail: z.string().optional(),
      status: z.string().optional(),
      classification: z.string().optional(),
      activity: z.string().optional(),
      organization: z.string().optional(),
      ruling: z.string().optional(),
      foundation: z.string().optional(),
    });
    
    export const PublicCharityCheckOutputSchema = z.object({
      ein: z.string(),
      isPublicCharity: z.boolean(),
      deductible: z.boolean().optional(),
    });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/briancasteel/charity-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server